More cleanup relating to our use of the TSC.
Look in the cpu_feature (CPUID output) to see if we have it.
This commit is contained in:
parent
d46e059f94
commit
0f12aa9ffd
@ -34,7 +34,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* from: @(#)clock.c 7.2 (Berkeley) 5/12/91
|
||||
* $Id: clock.c,v 1.105 1997/12/26 20:42:05 phk Exp $
|
||||
* $Id: clock.c,v 1.106 1997/12/28 13:36:07 phk Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -67,12 +67,14 @@
|
||||
#include <machine/frame.h>
|
||||
#include <machine/ipl.h>
|
||||
#include <machine/limits.h>
|
||||
#include <machine/md_var.h>
|
||||
#ifdef APIC_IO
|
||||
#include <machine/segments.h>
|
||||
#endif
|
||||
#if defined(SMP) || defined(APIC_IO)
|
||||
#include <machine/smp.h>
|
||||
#endif /* SMP || APIC_IO */
|
||||
#include <machine/specialreg.h>
|
||||
|
||||
#include <i386/isa/icu.h>
|
||||
#include <i386/isa/isa.h>
|
||||
@ -126,16 +128,11 @@ u_int timer_freq = 1193182;
|
||||
int timer0_max_count;
|
||||
u_int timer0_overflow_threshold;
|
||||
u_int timer0_prescaler_count;
|
||||
#if defined(I586_CPU) || defined(I686_CPU)
|
||||
#ifndef SMP
|
||||
u_int tsc_bias;
|
||||
u_int tsc_comultiplier;
|
||||
#endif
|
||||
u_int tsc_freq;
|
||||
#ifndef SMP
|
||||
u_int tsc_multiplier;
|
||||
#endif
|
||||
#endif
|
||||
u_int tsc_present;
|
||||
int wall_cmos_clock; /* wall CMOS clock assumed if != 0 */
|
||||
|
||||
static int beeping = 0;
|
||||
@ -163,9 +160,7 @@ static u_char timer0_state;
|
||||
static u_char timer2_state;
|
||||
static void (*timer_func) __P((struct clockframe *frame)) = hardclock;
|
||||
|
||||
#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP)
|
||||
static void set_tsc_freq(u_int i586_freq, u_int i8254_freq);
|
||||
#endif
|
||||
static void set_tsc_freq(u_int tsc_count, u_int i8254_freq);
|
||||
static void set_timer_freq(u_int freq, int intr_freq);
|
||||
|
||||
static void
|
||||
@ -574,10 +569,8 @@ calibrate_clocks(void)
|
||||
goto fail;
|
||||
tot_count = 0;
|
||||
|
||||
#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP)
|
||||
if (cpu_class == CPUCLASS_586 || cpu_class == CPUCLASS_686)
|
||||
if (tsc_present)
|
||||
wrmsr(0x10, 0LL); /* XXX 0x10 is the MSR for the TSC */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Wait for the mc146818A seconds counter to change. Read the i8254
|
||||
@ -607,17 +600,15 @@ calibrate_clocks(void)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP)
|
||||
/*
|
||||
* Read the cpu cycle counter. The timing considerations are
|
||||
* similar to those for the i8254 clock.
|
||||
*/
|
||||
if (cpu_class == CPUCLASS_586 || cpu_class == CPUCLASS_686) {
|
||||
if (tsc_present) {
|
||||
set_tsc_freq((u_int)rdtsc(), tot_count);
|
||||
if (bootverbose)
|
||||
printf("TSC clock: %u Hz, ", tsc_freq);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (bootverbose)
|
||||
printf("i8254 clock: %u Hz\n", tot_count);
|
||||
@ -656,6 +647,15 @@ startrtclock()
|
||||
{
|
||||
u_int delta, freq;
|
||||
|
||||
if (cpu_feature & CPUID_TSC)
|
||||
tsc_present = 1;
|
||||
else
|
||||
tsc_present = 0;
|
||||
|
||||
#ifdef SMP
|
||||
tsc_present = 0;
|
||||
#endif
|
||||
|
||||
writertc(RTC_STATUSA, rtc_statusa);
|
||||
writertc(RTC_STATUSB, RTCSB_24HR);
|
||||
|
||||
@ -689,14 +689,11 @@ startrtclock()
|
||||
printf(
|
||||
"%d Hz differs from default of %d Hz by more than 1%%\n",
|
||||
freq, timer_freq);
|
||||
#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP)
|
||||
tsc_freq = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
set_timer_freq(timer_freq, hz);
|
||||
|
||||
#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP)
|
||||
#ifndef CLK_USE_TSC_CALIBRATION
|
||||
if (tsc_freq != 0) {
|
||||
if (bootverbose)
|
||||
@ -705,8 +702,7 @@ startrtclock()
|
||||
tsc_freq = 0;
|
||||
}
|
||||
#endif
|
||||
if (tsc_freq == 0 &&
|
||||
(cpu_class == CPUCLASS_586 || cpu_class == CPUCLASS_686)) {
|
||||
if (tsc_present && tsc_freq == 0) {
|
||||
/*
|
||||
* Calibration of the i586 clock relative to the mc146818A
|
||||
* clock failed. Do a less accurate calibration relative
|
||||
@ -715,12 +711,11 @@ startrtclock()
|
||||
wrmsr(0x10, 0LL); /* XXX */
|
||||
DELAY(1000000);
|
||||
set_tsc_freq((u_int)rdtsc(), timer_freq);
|
||||
#ifdef CLK_USE_I586_CALIBRATION
|
||||
#ifdef CLK_USE_TSC_CALIBRATION
|
||||
if (bootverbose)
|
||||
printf("TSC clock: %u Hz\n", tsc_freq);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
@ -925,13 +920,11 @@ cpu_initclocks()
|
||||
|
||||
#endif /* APIC_IO */
|
||||
|
||||
#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP)
|
||||
/*
|
||||
* Finish setting up anti-jitter measures.
|
||||
*/
|
||||
if (tsc_freq != 0)
|
||||
tsc_bias = rdtsc();
|
||||
#endif
|
||||
|
||||
/* Initialize RTC. */
|
||||
writertc(RTC_STATUSA, rtc_statusa);
|
||||
@ -988,9 +981,8 @@ sysctl_machdep_i8254_freq SYSCTL_HANDLER_ARGS
|
||||
if (timer0_state != 0)
|
||||
return (EBUSY); /* too much trouble to handle */
|
||||
set_timer_freq(freq, hz);
|
||||
#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP)
|
||||
set_tsc_freq(tsc_freq, timer_freq);
|
||||
#endif
|
||||
if (tsc_present)
|
||||
set_tsc_freq(tsc_freq, timer_freq);
|
||||
}
|
||||
return (error);
|
||||
}
|
||||
@ -998,23 +990,22 @@ sysctl_machdep_i8254_freq SYSCTL_HANDLER_ARGS
|
||||
SYSCTL_PROC(_machdep, OID_AUTO, i8254_freq, CTLTYPE_INT | CTLFLAG_RW,
|
||||
0, sizeof(u_int), sysctl_machdep_i8254_freq, "I", "");
|
||||
|
||||
#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP)
|
||||
static void
|
||||
set_tsc_freq(u_int i586_freq, u_int i8254_freq)
|
||||
set_tsc_freq(u_int tsc_count, u_int i8254_freq)
|
||||
{
|
||||
u_int comultiplier, multiplier;
|
||||
u_long ef;
|
||||
|
||||
if (i586_freq == 0) {
|
||||
tsc_freq = i586_freq;
|
||||
if (tsc_count == 0) {
|
||||
tsc_freq = tsc_count;
|
||||
return;
|
||||
}
|
||||
comultiplier = ((unsigned long long)i586_freq
|
||||
comultiplier = ((unsigned long long)tsc_count
|
||||
<< TSC_COMULTIPLIER_SHIFT) / i8254_freq;
|
||||
multiplier = (1000000LL << TSC_MULTIPLIER_SHIFT) / i586_freq;
|
||||
multiplier = (1000000LL << TSC_MULTIPLIER_SHIFT) / tsc_count;
|
||||
ef = read_eflags();
|
||||
disable_intr();
|
||||
tsc_freq = i586_freq;
|
||||
tsc_freq = tsc_count;
|
||||
tsc_comultiplier = comultiplier;
|
||||
tsc_multiplier = multiplier;
|
||||
CLOCK_UNLOCK();
|
||||
@ -1022,12 +1013,12 @@ set_tsc_freq(u_int i586_freq, u_int i8254_freq)
|
||||
}
|
||||
|
||||
static int
|
||||
sysctl_machdep_i586_freq SYSCTL_HANDLER_ARGS
|
||||
sysctl_machdep_tsc_freq SYSCTL_HANDLER_ARGS
|
||||
{
|
||||
int error;
|
||||
u_int freq;
|
||||
|
||||
if (cpu_class != CPUCLASS_586 && cpu_class != CPUCLASS_686)
|
||||
if (!tsc_present)
|
||||
return (EOPNOTSUPP);
|
||||
freq = tsc_freq;
|
||||
error = sysctl_handle_opaque(oidp, &freq, sizeof freq, req);
|
||||
@ -1036,6 +1027,5 @@ sysctl_machdep_i586_freq SYSCTL_HANDLER_ARGS
|
||||
return (error);
|
||||
}
|
||||
|
||||
SYSCTL_PROC(_machdep, OID_AUTO, i586_freq, CTLTYPE_INT | CTLFLAG_RW,
|
||||
0, sizeof(u_int), sysctl_machdep_i586_freq, "I", "");
|
||||
#endif /* (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP) */
|
||||
SYSCTL_PROC(_machdep, OID_AUTO, tsc_freq, CTLTYPE_INT | CTLFLAG_RW,
|
||||
0, sizeof(u_int), sysctl_machdep_tsc_freq, "I", "");
|
||||
|
@ -3,17 +3,13 @@
|
||||
* Garrett Wollman, September 1994.
|
||||
* This file is in the public domain.
|
||||
*
|
||||
* $Id: clock.h,v 1.28 1997/12/26 20:42:01 phk Exp $
|
||||
* $Id: clock.h,v 1.29 1997/12/28 13:36:06 phk Exp $
|
||||
*/
|
||||
|
||||
#ifndef _MACHINE_CLOCK_H_
|
||||
#define _MACHINE_CLOCK_H_
|
||||
|
||||
#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP)
|
||||
#define CPU_CLOCKUPDATE(otime, ntime) cpu_clockupdate((otime), (ntime))
|
||||
#else
|
||||
#define CPU_CLOCKUPDATE(otime, ntime) (*(otime) = *(ntime))
|
||||
#endif
|
||||
|
||||
#define CPU_THISTICKLEN(dflt) dflt
|
||||
|
||||
@ -33,16 +29,10 @@ extern u_int timer_freq;
|
||||
extern int timer0_max_count;
|
||||
extern u_int timer0_overflow_threshold;
|
||||
extern u_int timer0_prescaler_count;
|
||||
#if defined(I586_CPU) || defined(I686_CPU)
|
||||
#ifndef SMP
|
||||
extern u_int tsc_bias;
|
||||
extern u_int tsc_comultiplier;
|
||||
#endif
|
||||
extern u_int tsc_freq;
|
||||
#ifndef SMP
|
||||
extern u_int tsc_multiplier;
|
||||
#endif
|
||||
#endif
|
||||
extern int wall_cmos_clock;
|
||||
|
||||
/*
|
||||
@ -85,7 +75,6 @@ clock_latency(void)
|
||||
- ((high << 8) | low));
|
||||
}
|
||||
|
||||
#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP)
|
||||
/*
|
||||
* When we update `time', on we also update `tsc_bias'
|
||||
* atomically. `tsc_bias' is the best available approximation to
|
||||
@ -117,7 +106,6 @@ cpu_clockupdate(volatile struct timeval *otime, struct timeval *ntime)
|
||||
} else
|
||||
*otime = *ntime;
|
||||
}
|
||||
#endif /* I586_CPU || I686_CPU */
|
||||
|
||||
#endif /* CLOCK_HAIR */
|
||||
|
||||
|
@ -34,7 +34,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* from: @(#)clock.c 7.2 (Berkeley) 5/12/91
|
||||
* $Id: clock.c,v 1.105 1997/12/26 20:42:05 phk Exp $
|
||||
* $Id: clock.c,v 1.106 1997/12/28 13:36:07 phk Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -67,12 +67,14 @@
|
||||
#include <machine/frame.h>
|
||||
#include <machine/ipl.h>
|
||||
#include <machine/limits.h>
|
||||
#include <machine/md_var.h>
|
||||
#ifdef APIC_IO
|
||||
#include <machine/segments.h>
|
||||
#endif
|
||||
#if defined(SMP) || defined(APIC_IO)
|
||||
#include <machine/smp.h>
|
||||
#endif /* SMP || APIC_IO */
|
||||
#include <machine/specialreg.h>
|
||||
|
||||
#include <i386/isa/icu.h>
|
||||
#include <i386/isa/isa.h>
|
||||
@ -126,16 +128,11 @@ u_int timer_freq = 1193182;
|
||||
int timer0_max_count;
|
||||
u_int timer0_overflow_threshold;
|
||||
u_int timer0_prescaler_count;
|
||||
#if defined(I586_CPU) || defined(I686_CPU)
|
||||
#ifndef SMP
|
||||
u_int tsc_bias;
|
||||
u_int tsc_comultiplier;
|
||||
#endif
|
||||
u_int tsc_freq;
|
||||
#ifndef SMP
|
||||
u_int tsc_multiplier;
|
||||
#endif
|
||||
#endif
|
||||
u_int tsc_present;
|
||||
int wall_cmos_clock; /* wall CMOS clock assumed if != 0 */
|
||||
|
||||
static int beeping = 0;
|
||||
@ -163,9 +160,7 @@ static u_char timer0_state;
|
||||
static u_char timer2_state;
|
||||
static void (*timer_func) __P((struct clockframe *frame)) = hardclock;
|
||||
|
||||
#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP)
|
||||
static void set_tsc_freq(u_int i586_freq, u_int i8254_freq);
|
||||
#endif
|
||||
static void set_tsc_freq(u_int tsc_count, u_int i8254_freq);
|
||||
static void set_timer_freq(u_int freq, int intr_freq);
|
||||
|
||||
static void
|
||||
@ -574,10 +569,8 @@ calibrate_clocks(void)
|
||||
goto fail;
|
||||
tot_count = 0;
|
||||
|
||||
#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP)
|
||||
if (cpu_class == CPUCLASS_586 || cpu_class == CPUCLASS_686)
|
||||
if (tsc_present)
|
||||
wrmsr(0x10, 0LL); /* XXX 0x10 is the MSR for the TSC */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Wait for the mc146818A seconds counter to change. Read the i8254
|
||||
@ -607,17 +600,15 @@ calibrate_clocks(void)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP)
|
||||
/*
|
||||
* Read the cpu cycle counter. The timing considerations are
|
||||
* similar to those for the i8254 clock.
|
||||
*/
|
||||
if (cpu_class == CPUCLASS_586 || cpu_class == CPUCLASS_686) {
|
||||
if (tsc_present) {
|
||||
set_tsc_freq((u_int)rdtsc(), tot_count);
|
||||
if (bootverbose)
|
||||
printf("TSC clock: %u Hz, ", tsc_freq);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (bootverbose)
|
||||
printf("i8254 clock: %u Hz\n", tot_count);
|
||||
@ -656,6 +647,15 @@ startrtclock()
|
||||
{
|
||||
u_int delta, freq;
|
||||
|
||||
if (cpu_feature & CPUID_TSC)
|
||||
tsc_present = 1;
|
||||
else
|
||||
tsc_present = 0;
|
||||
|
||||
#ifdef SMP
|
||||
tsc_present = 0;
|
||||
#endif
|
||||
|
||||
writertc(RTC_STATUSA, rtc_statusa);
|
||||
writertc(RTC_STATUSB, RTCSB_24HR);
|
||||
|
||||
@ -689,14 +689,11 @@ startrtclock()
|
||||
printf(
|
||||
"%d Hz differs from default of %d Hz by more than 1%%\n",
|
||||
freq, timer_freq);
|
||||
#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP)
|
||||
tsc_freq = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
set_timer_freq(timer_freq, hz);
|
||||
|
||||
#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP)
|
||||
#ifndef CLK_USE_TSC_CALIBRATION
|
||||
if (tsc_freq != 0) {
|
||||
if (bootverbose)
|
||||
@ -705,8 +702,7 @@ startrtclock()
|
||||
tsc_freq = 0;
|
||||
}
|
||||
#endif
|
||||
if (tsc_freq == 0 &&
|
||||
(cpu_class == CPUCLASS_586 || cpu_class == CPUCLASS_686)) {
|
||||
if (tsc_present && tsc_freq == 0) {
|
||||
/*
|
||||
* Calibration of the i586 clock relative to the mc146818A
|
||||
* clock failed. Do a less accurate calibration relative
|
||||
@ -715,12 +711,11 @@ startrtclock()
|
||||
wrmsr(0x10, 0LL); /* XXX */
|
||||
DELAY(1000000);
|
||||
set_tsc_freq((u_int)rdtsc(), timer_freq);
|
||||
#ifdef CLK_USE_I586_CALIBRATION
|
||||
#ifdef CLK_USE_TSC_CALIBRATION
|
||||
if (bootverbose)
|
||||
printf("TSC clock: %u Hz\n", tsc_freq);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
@ -925,13 +920,11 @@ cpu_initclocks()
|
||||
|
||||
#endif /* APIC_IO */
|
||||
|
||||
#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP)
|
||||
/*
|
||||
* Finish setting up anti-jitter measures.
|
||||
*/
|
||||
if (tsc_freq != 0)
|
||||
tsc_bias = rdtsc();
|
||||
#endif
|
||||
|
||||
/* Initialize RTC. */
|
||||
writertc(RTC_STATUSA, rtc_statusa);
|
||||
@ -988,9 +981,8 @@ sysctl_machdep_i8254_freq SYSCTL_HANDLER_ARGS
|
||||
if (timer0_state != 0)
|
||||
return (EBUSY); /* too much trouble to handle */
|
||||
set_timer_freq(freq, hz);
|
||||
#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP)
|
||||
set_tsc_freq(tsc_freq, timer_freq);
|
||||
#endif
|
||||
if (tsc_present)
|
||||
set_tsc_freq(tsc_freq, timer_freq);
|
||||
}
|
||||
return (error);
|
||||
}
|
||||
@ -998,23 +990,22 @@ sysctl_machdep_i8254_freq SYSCTL_HANDLER_ARGS
|
||||
SYSCTL_PROC(_machdep, OID_AUTO, i8254_freq, CTLTYPE_INT | CTLFLAG_RW,
|
||||
0, sizeof(u_int), sysctl_machdep_i8254_freq, "I", "");
|
||||
|
||||
#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP)
|
||||
static void
|
||||
set_tsc_freq(u_int i586_freq, u_int i8254_freq)
|
||||
set_tsc_freq(u_int tsc_count, u_int i8254_freq)
|
||||
{
|
||||
u_int comultiplier, multiplier;
|
||||
u_long ef;
|
||||
|
||||
if (i586_freq == 0) {
|
||||
tsc_freq = i586_freq;
|
||||
if (tsc_count == 0) {
|
||||
tsc_freq = tsc_count;
|
||||
return;
|
||||
}
|
||||
comultiplier = ((unsigned long long)i586_freq
|
||||
comultiplier = ((unsigned long long)tsc_count
|
||||
<< TSC_COMULTIPLIER_SHIFT) / i8254_freq;
|
||||
multiplier = (1000000LL << TSC_MULTIPLIER_SHIFT) / i586_freq;
|
||||
multiplier = (1000000LL << TSC_MULTIPLIER_SHIFT) / tsc_count;
|
||||
ef = read_eflags();
|
||||
disable_intr();
|
||||
tsc_freq = i586_freq;
|
||||
tsc_freq = tsc_count;
|
||||
tsc_comultiplier = comultiplier;
|
||||
tsc_multiplier = multiplier;
|
||||
CLOCK_UNLOCK();
|
||||
@ -1022,12 +1013,12 @@ set_tsc_freq(u_int i586_freq, u_int i8254_freq)
|
||||
}
|
||||
|
||||
static int
|
||||
sysctl_machdep_i586_freq SYSCTL_HANDLER_ARGS
|
||||
sysctl_machdep_tsc_freq SYSCTL_HANDLER_ARGS
|
||||
{
|
||||
int error;
|
||||
u_int freq;
|
||||
|
||||
if (cpu_class != CPUCLASS_586 && cpu_class != CPUCLASS_686)
|
||||
if (!tsc_present)
|
||||
return (EOPNOTSUPP);
|
||||
freq = tsc_freq;
|
||||
error = sysctl_handle_opaque(oidp, &freq, sizeof freq, req);
|
||||
@ -1036,6 +1027,5 @@ sysctl_machdep_i586_freq SYSCTL_HANDLER_ARGS
|
||||
return (error);
|
||||
}
|
||||
|
||||
SYSCTL_PROC(_machdep, OID_AUTO, i586_freq, CTLTYPE_INT | CTLFLAG_RW,
|
||||
0, sizeof(u_int), sysctl_machdep_i586_freq, "I", "");
|
||||
#endif /* (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP) */
|
||||
SYSCTL_PROC(_machdep, OID_AUTO, tsc_freq, CTLTYPE_INT | CTLFLAG_RW,
|
||||
0, sizeof(u_int), sysctl_machdep_tsc_freq, "I", "");
|
||||
|
@ -32,7 +32,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* from: Steve McCanne's microtime code
|
||||
* $Id: microtime.s,v 1.37 1997/12/26 20:41:35 phk Exp $
|
||||
* $Id: microtime.s,v 1.38 1997/12/28 13:36:05 phk Exp $
|
||||
*/
|
||||
|
||||
#include <machine/asmacros.h>
|
||||
@ -47,7 +47,6 @@
|
||||
|
||||
ENTRY(microtime)
|
||||
|
||||
#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP)
|
||||
movl _tsc_freq, %ecx
|
||||
testl %ecx, %ecx
|
||||
je i8254_microtime
|
||||
@ -57,11 +56,8 @@ ENTRY(microtime)
|
||||
subl _tsc_bias, %eax
|
||||
mull _tsc_multiplier
|
||||
movl %edx, %eax
|
||||
popfl /* restore interrupt mask */
|
||||
jmp common_microtime
|
||||
ALIGN_TEXT
|
||||
#else
|
||||
xorl %ecx, %ecx /* clear ecx */
|
||||
#endif
|
||||
|
||||
i8254_microtime:
|
||||
movb $TIMER_SEL0|TIMER_LATCH, %al /* prepare to latch */
|
||||
@ -205,10 +201,6 @@ overflow:
|
||||
#endif /* 0 */
|
||||
shr $15, %eax
|
||||
|
||||
common_microtime:
|
||||
addl _time+4, %eax /* usec += time.tv_sec */
|
||||
movl _time, %edx /* sec = time.tv_sec */
|
||||
|
||||
#ifdef USE_CLOCKLOCK
|
||||
pushl %eax /* s_lock destroys %eax, %ecx */
|
||||
pushl %edx /* during profiling, %edx is also destroyed */
|
||||
@ -220,6 +212,11 @@ common_microtime:
|
||||
#endif /* USE_CLOCKLOCK */
|
||||
popfl /* restore interrupt mask */
|
||||
|
||||
common_microtime:
|
||||
|
||||
addl _time+4, %eax /* usec += time.tv_sec */
|
||||
movl _time, %edx /* sec = time.tv_sec */
|
||||
|
||||
cmpl $1000000, %eax /* usec valid? */
|
||||
jb 1f
|
||||
subl $1000000, %eax /* adjust usec */
|
||||
|
@ -26,7 +26,7 @@
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: perfmon.c,v 1.12 1997/10/28 15:58:10 bde Exp $
|
||||
* $Id: perfmon.c,v 1.13 1997/12/26 20:41:37 phk Exp $
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
@ -339,16 +339,17 @@ perfmon_ioctl(dev_t dev, int cmd, caddr_t param, int flags, struct proc *p)
|
||||
rv = perfmon_read(pmcd->pmcd_num, &pmcd->pmcd_value);
|
||||
break;
|
||||
|
||||
#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP)
|
||||
case PMIOTSTAMP:
|
||||
if (!tsc_freq) {
|
||||
rv = ENOTTY;
|
||||
break;
|
||||
}
|
||||
pmct = (struct pmc_tstamp *)param;
|
||||
/* XXX interface loses precision. */
|
||||
pmct->pmct_rate = tsc_freq / 1000000;
|
||||
pmct->pmct_value = rdtsc();
|
||||
rv = 0;
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
rv = ENOTTY;
|
||||
}
|
||||
|
@ -34,7 +34,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* from: @(#)clock.c 7.2 (Berkeley) 5/12/91
|
||||
* $Id: clock.c,v 1.105 1997/12/26 20:42:05 phk Exp $
|
||||
* $Id: clock.c,v 1.106 1997/12/28 13:36:07 phk Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -67,12 +67,14 @@
|
||||
#include <machine/frame.h>
|
||||
#include <machine/ipl.h>
|
||||
#include <machine/limits.h>
|
||||
#include <machine/md_var.h>
|
||||
#ifdef APIC_IO
|
||||
#include <machine/segments.h>
|
||||
#endif
|
||||
#if defined(SMP) || defined(APIC_IO)
|
||||
#include <machine/smp.h>
|
||||
#endif /* SMP || APIC_IO */
|
||||
#include <machine/specialreg.h>
|
||||
|
||||
#include <i386/isa/icu.h>
|
||||
#include <i386/isa/isa.h>
|
||||
@ -126,16 +128,11 @@ u_int timer_freq = 1193182;
|
||||
int timer0_max_count;
|
||||
u_int timer0_overflow_threshold;
|
||||
u_int timer0_prescaler_count;
|
||||
#if defined(I586_CPU) || defined(I686_CPU)
|
||||
#ifndef SMP
|
||||
u_int tsc_bias;
|
||||
u_int tsc_comultiplier;
|
||||
#endif
|
||||
u_int tsc_freq;
|
||||
#ifndef SMP
|
||||
u_int tsc_multiplier;
|
||||
#endif
|
||||
#endif
|
||||
u_int tsc_present;
|
||||
int wall_cmos_clock; /* wall CMOS clock assumed if != 0 */
|
||||
|
||||
static int beeping = 0;
|
||||
@ -163,9 +160,7 @@ static u_char timer0_state;
|
||||
static u_char timer2_state;
|
||||
static void (*timer_func) __P((struct clockframe *frame)) = hardclock;
|
||||
|
||||
#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP)
|
||||
static void set_tsc_freq(u_int i586_freq, u_int i8254_freq);
|
||||
#endif
|
||||
static void set_tsc_freq(u_int tsc_count, u_int i8254_freq);
|
||||
static void set_timer_freq(u_int freq, int intr_freq);
|
||||
|
||||
static void
|
||||
@ -574,10 +569,8 @@ calibrate_clocks(void)
|
||||
goto fail;
|
||||
tot_count = 0;
|
||||
|
||||
#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP)
|
||||
if (cpu_class == CPUCLASS_586 || cpu_class == CPUCLASS_686)
|
||||
if (tsc_present)
|
||||
wrmsr(0x10, 0LL); /* XXX 0x10 is the MSR for the TSC */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Wait for the mc146818A seconds counter to change. Read the i8254
|
||||
@ -607,17 +600,15 @@ calibrate_clocks(void)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP)
|
||||
/*
|
||||
* Read the cpu cycle counter. The timing considerations are
|
||||
* similar to those for the i8254 clock.
|
||||
*/
|
||||
if (cpu_class == CPUCLASS_586 || cpu_class == CPUCLASS_686) {
|
||||
if (tsc_present) {
|
||||
set_tsc_freq((u_int)rdtsc(), tot_count);
|
||||
if (bootverbose)
|
||||
printf("TSC clock: %u Hz, ", tsc_freq);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (bootverbose)
|
||||
printf("i8254 clock: %u Hz\n", tot_count);
|
||||
@ -656,6 +647,15 @@ startrtclock()
|
||||
{
|
||||
u_int delta, freq;
|
||||
|
||||
if (cpu_feature & CPUID_TSC)
|
||||
tsc_present = 1;
|
||||
else
|
||||
tsc_present = 0;
|
||||
|
||||
#ifdef SMP
|
||||
tsc_present = 0;
|
||||
#endif
|
||||
|
||||
writertc(RTC_STATUSA, rtc_statusa);
|
||||
writertc(RTC_STATUSB, RTCSB_24HR);
|
||||
|
||||
@ -689,14 +689,11 @@ startrtclock()
|
||||
printf(
|
||||
"%d Hz differs from default of %d Hz by more than 1%%\n",
|
||||
freq, timer_freq);
|
||||
#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP)
|
||||
tsc_freq = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
set_timer_freq(timer_freq, hz);
|
||||
|
||||
#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP)
|
||||
#ifndef CLK_USE_TSC_CALIBRATION
|
||||
if (tsc_freq != 0) {
|
||||
if (bootverbose)
|
||||
@ -705,8 +702,7 @@ startrtclock()
|
||||
tsc_freq = 0;
|
||||
}
|
||||
#endif
|
||||
if (tsc_freq == 0 &&
|
||||
(cpu_class == CPUCLASS_586 || cpu_class == CPUCLASS_686)) {
|
||||
if (tsc_present && tsc_freq == 0) {
|
||||
/*
|
||||
* Calibration of the i586 clock relative to the mc146818A
|
||||
* clock failed. Do a less accurate calibration relative
|
||||
@ -715,12 +711,11 @@ startrtclock()
|
||||
wrmsr(0x10, 0LL); /* XXX */
|
||||
DELAY(1000000);
|
||||
set_tsc_freq((u_int)rdtsc(), timer_freq);
|
||||
#ifdef CLK_USE_I586_CALIBRATION
|
||||
#ifdef CLK_USE_TSC_CALIBRATION
|
||||
if (bootverbose)
|
||||
printf("TSC clock: %u Hz\n", tsc_freq);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
@ -925,13 +920,11 @@ cpu_initclocks()
|
||||
|
||||
#endif /* APIC_IO */
|
||||
|
||||
#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP)
|
||||
/*
|
||||
* Finish setting up anti-jitter measures.
|
||||
*/
|
||||
if (tsc_freq != 0)
|
||||
tsc_bias = rdtsc();
|
||||
#endif
|
||||
|
||||
/* Initialize RTC. */
|
||||
writertc(RTC_STATUSA, rtc_statusa);
|
||||
@ -988,9 +981,8 @@ sysctl_machdep_i8254_freq SYSCTL_HANDLER_ARGS
|
||||
if (timer0_state != 0)
|
||||
return (EBUSY); /* too much trouble to handle */
|
||||
set_timer_freq(freq, hz);
|
||||
#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP)
|
||||
set_tsc_freq(tsc_freq, timer_freq);
|
||||
#endif
|
||||
if (tsc_present)
|
||||
set_tsc_freq(tsc_freq, timer_freq);
|
||||
}
|
||||
return (error);
|
||||
}
|
||||
@ -998,23 +990,22 @@ sysctl_machdep_i8254_freq SYSCTL_HANDLER_ARGS
|
||||
SYSCTL_PROC(_machdep, OID_AUTO, i8254_freq, CTLTYPE_INT | CTLFLAG_RW,
|
||||
0, sizeof(u_int), sysctl_machdep_i8254_freq, "I", "");
|
||||
|
||||
#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP)
|
||||
static void
|
||||
set_tsc_freq(u_int i586_freq, u_int i8254_freq)
|
||||
set_tsc_freq(u_int tsc_count, u_int i8254_freq)
|
||||
{
|
||||
u_int comultiplier, multiplier;
|
||||
u_long ef;
|
||||
|
||||
if (i586_freq == 0) {
|
||||
tsc_freq = i586_freq;
|
||||
if (tsc_count == 0) {
|
||||
tsc_freq = tsc_count;
|
||||
return;
|
||||
}
|
||||
comultiplier = ((unsigned long long)i586_freq
|
||||
comultiplier = ((unsigned long long)tsc_count
|
||||
<< TSC_COMULTIPLIER_SHIFT) / i8254_freq;
|
||||
multiplier = (1000000LL << TSC_MULTIPLIER_SHIFT) / i586_freq;
|
||||
multiplier = (1000000LL << TSC_MULTIPLIER_SHIFT) / tsc_count;
|
||||
ef = read_eflags();
|
||||
disable_intr();
|
||||
tsc_freq = i586_freq;
|
||||
tsc_freq = tsc_count;
|
||||
tsc_comultiplier = comultiplier;
|
||||
tsc_multiplier = multiplier;
|
||||
CLOCK_UNLOCK();
|
||||
@ -1022,12 +1013,12 @@ set_tsc_freq(u_int i586_freq, u_int i8254_freq)
|
||||
}
|
||||
|
||||
static int
|
||||
sysctl_machdep_i586_freq SYSCTL_HANDLER_ARGS
|
||||
sysctl_machdep_tsc_freq SYSCTL_HANDLER_ARGS
|
||||
{
|
||||
int error;
|
||||
u_int freq;
|
||||
|
||||
if (cpu_class != CPUCLASS_586 && cpu_class != CPUCLASS_686)
|
||||
if (!tsc_present)
|
||||
return (EOPNOTSUPP);
|
||||
freq = tsc_freq;
|
||||
error = sysctl_handle_opaque(oidp, &freq, sizeof freq, req);
|
||||
@ -1036,6 +1027,5 @@ sysctl_machdep_i586_freq SYSCTL_HANDLER_ARGS
|
||||
return (error);
|
||||
}
|
||||
|
||||
SYSCTL_PROC(_machdep, OID_AUTO, i586_freq, CTLTYPE_INT | CTLFLAG_RW,
|
||||
0, sizeof(u_int), sysctl_machdep_i586_freq, "I", "");
|
||||
#endif /* (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP) */
|
||||
SYSCTL_PROC(_machdep, OID_AUTO, tsc_freq, CTLTYPE_INT | CTLFLAG_RW,
|
||||
0, sizeof(u_int), sysctl_machdep_tsc_freq, "I", "");
|
||||
|
@ -3,17 +3,13 @@
|
||||
* Garrett Wollman, September 1994.
|
||||
* This file is in the public domain.
|
||||
*
|
||||
* $Id: clock.h,v 1.28 1997/12/26 20:42:01 phk Exp $
|
||||
* $Id: clock.h,v 1.29 1997/12/28 13:36:06 phk Exp $
|
||||
*/
|
||||
|
||||
#ifndef _MACHINE_CLOCK_H_
|
||||
#define _MACHINE_CLOCK_H_
|
||||
|
||||
#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP)
|
||||
#define CPU_CLOCKUPDATE(otime, ntime) cpu_clockupdate((otime), (ntime))
|
||||
#else
|
||||
#define CPU_CLOCKUPDATE(otime, ntime) (*(otime) = *(ntime))
|
||||
#endif
|
||||
|
||||
#define CPU_THISTICKLEN(dflt) dflt
|
||||
|
||||
@ -33,16 +29,10 @@ extern u_int timer_freq;
|
||||
extern int timer0_max_count;
|
||||
extern u_int timer0_overflow_threshold;
|
||||
extern u_int timer0_prescaler_count;
|
||||
#if defined(I586_CPU) || defined(I686_CPU)
|
||||
#ifndef SMP
|
||||
extern u_int tsc_bias;
|
||||
extern u_int tsc_comultiplier;
|
||||
#endif
|
||||
extern u_int tsc_freq;
|
||||
#ifndef SMP
|
||||
extern u_int tsc_multiplier;
|
||||
#endif
|
||||
#endif
|
||||
extern int wall_cmos_clock;
|
||||
|
||||
/*
|
||||
@ -85,7 +75,6 @@ clock_latency(void)
|
||||
- ((high << 8) | low));
|
||||
}
|
||||
|
||||
#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP)
|
||||
/*
|
||||
* When we update `time', on we also update `tsc_bias'
|
||||
* atomically. `tsc_bias' is the best available approximation to
|
||||
@ -117,7 +106,6 @@ cpu_clockupdate(volatile struct timeval *otime, struct timeval *ntime)
|
||||
} else
|
||||
*otime = *ntime;
|
||||
}
|
||||
#endif /* I586_CPU || I686_CPU */
|
||||
|
||||
#endif /* CLOCK_HAIR */
|
||||
|
||||
|
@ -34,7 +34,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* from: @(#)clock.c 7.2 (Berkeley) 5/12/91
|
||||
* $Id: clock.c,v 1.105 1997/12/26 20:42:05 phk Exp $
|
||||
* $Id: clock.c,v 1.106 1997/12/28 13:36:07 phk Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -67,12 +67,14 @@
|
||||
#include <machine/frame.h>
|
||||
#include <machine/ipl.h>
|
||||
#include <machine/limits.h>
|
||||
#include <machine/md_var.h>
|
||||
#ifdef APIC_IO
|
||||
#include <machine/segments.h>
|
||||
#endif
|
||||
#if defined(SMP) || defined(APIC_IO)
|
||||
#include <machine/smp.h>
|
||||
#endif /* SMP || APIC_IO */
|
||||
#include <machine/specialreg.h>
|
||||
|
||||
#include <i386/isa/icu.h>
|
||||
#include <i386/isa/isa.h>
|
||||
@ -126,16 +128,11 @@ u_int timer_freq = 1193182;
|
||||
int timer0_max_count;
|
||||
u_int timer0_overflow_threshold;
|
||||
u_int timer0_prescaler_count;
|
||||
#if defined(I586_CPU) || defined(I686_CPU)
|
||||
#ifndef SMP
|
||||
u_int tsc_bias;
|
||||
u_int tsc_comultiplier;
|
||||
#endif
|
||||
u_int tsc_freq;
|
||||
#ifndef SMP
|
||||
u_int tsc_multiplier;
|
||||
#endif
|
||||
#endif
|
||||
u_int tsc_present;
|
||||
int wall_cmos_clock; /* wall CMOS clock assumed if != 0 */
|
||||
|
||||
static int beeping = 0;
|
||||
@ -163,9 +160,7 @@ static u_char timer0_state;
|
||||
static u_char timer2_state;
|
||||
static void (*timer_func) __P((struct clockframe *frame)) = hardclock;
|
||||
|
||||
#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP)
|
||||
static void set_tsc_freq(u_int i586_freq, u_int i8254_freq);
|
||||
#endif
|
||||
static void set_tsc_freq(u_int tsc_count, u_int i8254_freq);
|
||||
static void set_timer_freq(u_int freq, int intr_freq);
|
||||
|
||||
static void
|
||||
@ -574,10 +569,8 @@ calibrate_clocks(void)
|
||||
goto fail;
|
||||
tot_count = 0;
|
||||
|
||||
#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP)
|
||||
if (cpu_class == CPUCLASS_586 || cpu_class == CPUCLASS_686)
|
||||
if (tsc_present)
|
||||
wrmsr(0x10, 0LL); /* XXX 0x10 is the MSR for the TSC */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Wait for the mc146818A seconds counter to change. Read the i8254
|
||||
@ -607,17 +600,15 @@ calibrate_clocks(void)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP)
|
||||
/*
|
||||
* Read the cpu cycle counter. The timing considerations are
|
||||
* similar to those for the i8254 clock.
|
||||
*/
|
||||
if (cpu_class == CPUCLASS_586 || cpu_class == CPUCLASS_686) {
|
||||
if (tsc_present) {
|
||||
set_tsc_freq((u_int)rdtsc(), tot_count);
|
||||
if (bootverbose)
|
||||
printf("TSC clock: %u Hz, ", tsc_freq);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (bootverbose)
|
||||
printf("i8254 clock: %u Hz\n", tot_count);
|
||||
@ -656,6 +647,15 @@ startrtclock()
|
||||
{
|
||||
u_int delta, freq;
|
||||
|
||||
if (cpu_feature & CPUID_TSC)
|
||||
tsc_present = 1;
|
||||
else
|
||||
tsc_present = 0;
|
||||
|
||||
#ifdef SMP
|
||||
tsc_present = 0;
|
||||
#endif
|
||||
|
||||
writertc(RTC_STATUSA, rtc_statusa);
|
||||
writertc(RTC_STATUSB, RTCSB_24HR);
|
||||
|
||||
@ -689,14 +689,11 @@ startrtclock()
|
||||
printf(
|
||||
"%d Hz differs from default of %d Hz by more than 1%%\n",
|
||||
freq, timer_freq);
|
||||
#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP)
|
||||
tsc_freq = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
set_timer_freq(timer_freq, hz);
|
||||
|
||||
#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP)
|
||||
#ifndef CLK_USE_TSC_CALIBRATION
|
||||
if (tsc_freq != 0) {
|
||||
if (bootverbose)
|
||||
@ -705,8 +702,7 @@ startrtclock()
|
||||
tsc_freq = 0;
|
||||
}
|
||||
#endif
|
||||
if (tsc_freq == 0 &&
|
||||
(cpu_class == CPUCLASS_586 || cpu_class == CPUCLASS_686)) {
|
||||
if (tsc_present && tsc_freq == 0) {
|
||||
/*
|
||||
* Calibration of the i586 clock relative to the mc146818A
|
||||
* clock failed. Do a less accurate calibration relative
|
||||
@ -715,12 +711,11 @@ startrtclock()
|
||||
wrmsr(0x10, 0LL); /* XXX */
|
||||
DELAY(1000000);
|
||||
set_tsc_freq((u_int)rdtsc(), timer_freq);
|
||||
#ifdef CLK_USE_I586_CALIBRATION
|
||||
#ifdef CLK_USE_TSC_CALIBRATION
|
||||
if (bootverbose)
|
||||
printf("TSC clock: %u Hz\n", tsc_freq);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
@ -925,13 +920,11 @@ cpu_initclocks()
|
||||
|
||||
#endif /* APIC_IO */
|
||||
|
||||
#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP)
|
||||
/*
|
||||
* Finish setting up anti-jitter measures.
|
||||
*/
|
||||
if (tsc_freq != 0)
|
||||
tsc_bias = rdtsc();
|
||||
#endif
|
||||
|
||||
/* Initialize RTC. */
|
||||
writertc(RTC_STATUSA, rtc_statusa);
|
||||
@ -988,9 +981,8 @@ sysctl_machdep_i8254_freq SYSCTL_HANDLER_ARGS
|
||||
if (timer0_state != 0)
|
||||
return (EBUSY); /* too much trouble to handle */
|
||||
set_timer_freq(freq, hz);
|
||||
#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP)
|
||||
set_tsc_freq(tsc_freq, timer_freq);
|
||||
#endif
|
||||
if (tsc_present)
|
||||
set_tsc_freq(tsc_freq, timer_freq);
|
||||
}
|
||||
return (error);
|
||||
}
|
||||
@ -998,23 +990,22 @@ sysctl_machdep_i8254_freq SYSCTL_HANDLER_ARGS
|
||||
SYSCTL_PROC(_machdep, OID_AUTO, i8254_freq, CTLTYPE_INT | CTLFLAG_RW,
|
||||
0, sizeof(u_int), sysctl_machdep_i8254_freq, "I", "");
|
||||
|
||||
#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP)
|
||||
static void
|
||||
set_tsc_freq(u_int i586_freq, u_int i8254_freq)
|
||||
set_tsc_freq(u_int tsc_count, u_int i8254_freq)
|
||||
{
|
||||
u_int comultiplier, multiplier;
|
||||
u_long ef;
|
||||
|
||||
if (i586_freq == 0) {
|
||||
tsc_freq = i586_freq;
|
||||
if (tsc_count == 0) {
|
||||
tsc_freq = tsc_count;
|
||||
return;
|
||||
}
|
||||
comultiplier = ((unsigned long long)i586_freq
|
||||
comultiplier = ((unsigned long long)tsc_count
|
||||
<< TSC_COMULTIPLIER_SHIFT) / i8254_freq;
|
||||
multiplier = (1000000LL << TSC_MULTIPLIER_SHIFT) / i586_freq;
|
||||
multiplier = (1000000LL << TSC_MULTIPLIER_SHIFT) / tsc_count;
|
||||
ef = read_eflags();
|
||||
disable_intr();
|
||||
tsc_freq = i586_freq;
|
||||
tsc_freq = tsc_count;
|
||||
tsc_comultiplier = comultiplier;
|
||||
tsc_multiplier = multiplier;
|
||||
CLOCK_UNLOCK();
|
||||
@ -1022,12 +1013,12 @@ set_tsc_freq(u_int i586_freq, u_int i8254_freq)
|
||||
}
|
||||
|
||||
static int
|
||||
sysctl_machdep_i586_freq SYSCTL_HANDLER_ARGS
|
||||
sysctl_machdep_tsc_freq SYSCTL_HANDLER_ARGS
|
||||
{
|
||||
int error;
|
||||
u_int freq;
|
||||
|
||||
if (cpu_class != CPUCLASS_586 && cpu_class != CPUCLASS_686)
|
||||
if (!tsc_present)
|
||||
return (EOPNOTSUPP);
|
||||
freq = tsc_freq;
|
||||
error = sysctl_handle_opaque(oidp, &freq, sizeof freq, req);
|
||||
@ -1036,6 +1027,5 @@ sysctl_machdep_i586_freq SYSCTL_HANDLER_ARGS
|
||||
return (error);
|
||||
}
|
||||
|
||||
SYSCTL_PROC(_machdep, OID_AUTO, i586_freq, CTLTYPE_INT | CTLFLAG_RW,
|
||||
0, sizeof(u_int), sysctl_machdep_i586_freq, "I", "");
|
||||
#endif /* (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP) */
|
||||
SYSCTL_PROC(_machdep, OID_AUTO, tsc_freq, CTLTYPE_INT | CTLFLAG_RW,
|
||||
0, sizeof(u_int), sysctl_machdep_tsc_freq, "I", "");
|
||||
|
@ -34,7 +34,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* from: @(#)clock.c 7.2 (Berkeley) 5/12/91
|
||||
* $Id: clock.c,v 1.105 1997/12/26 20:42:05 phk Exp $
|
||||
* $Id: clock.c,v 1.106 1997/12/28 13:36:07 phk Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -67,12 +67,14 @@
|
||||
#include <machine/frame.h>
|
||||
#include <machine/ipl.h>
|
||||
#include <machine/limits.h>
|
||||
#include <machine/md_var.h>
|
||||
#ifdef APIC_IO
|
||||
#include <machine/segments.h>
|
||||
#endif
|
||||
#if defined(SMP) || defined(APIC_IO)
|
||||
#include <machine/smp.h>
|
||||
#endif /* SMP || APIC_IO */
|
||||
#include <machine/specialreg.h>
|
||||
|
||||
#include <i386/isa/icu.h>
|
||||
#include <i386/isa/isa.h>
|
||||
@ -126,16 +128,11 @@ u_int timer_freq = 1193182;
|
||||
int timer0_max_count;
|
||||
u_int timer0_overflow_threshold;
|
||||
u_int timer0_prescaler_count;
|
||||
#if defined(I586_CPU) || defined(I686_CPU)
|
||||
#ifndef SMP
|
||||
u_int tsc_bias;
|
||||
u_int tsc_comultiplier;
|
||||
#endif
|
||||
u_int tsc_freq;
|
||||
#ifndef SMP
|
||||
u_int tsc_multiplier;
|
||||
#endif
|
||||
#endif
|
||||
u_int tsc_present;
|
||||
int wall_cmos_clock; /* wall CMOS clock assumed if != 0 */
|
||||
|
||||
static int beeping = 0;
|
||||
@ -163,9 +160,7 @@ static u_char timer0_state;
|
||||
static u_char timer2_state;
|
||||
static void (*timer_func) __P((struct clockframe *frame)) = hardclock;
|
||||
|
||||
#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP)
|
||||
static void set_tsc_freq(u_int i586_freq, u_int i8254_freq);
|
||||
#endif
|
||||
static void set_tsc_freq(u_int tsc_count, u_int i8254_freq);
|
||||
static void set_timer_freq(u_int freq, int intr_freq);
|
||||
|
||||
static void
|
||||
@ -574,10 +569,8 @@ calibrate_clocks(void)
|
||||
goto fail;
|
||||
tot_count = 0;
|
||||
|
||||
#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP)
|
||||
if (cpu_class == CPUCLASS_586 || cpu_class == CPUCLASS_686)
|
||||
if (tsc_present)
|
||||
wrmsr(0x10, 0LL); /* XXX 0x10 is the MSR for the TSC */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Wait for the mc146818A seconds counter to change. Read the i8254
|
||||
@ -607,17 +600,15 @@ calibrate_clocks(void)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP)
|
||||
/*
|
||||
* Read the cpu cycle counter. The timing considerations are
|
||||
* similar to those for the i8254 clock.
|
||||
*/
|
||||
if (cpu_class == CPUCLASS_586 || cpu_class == CPUCLASS_686) {
|
||||
if (tsc_present) {
|
||||
set_tsc_freq((u_int)rdtsc(), tot_count);
|
||||
if (bootverbose)
|
||||
printf("TSC clock: %u Hz, ", tsc_freq);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (bootverbose)
|
||||
printf("i8254 clock: %u Hz\n", tot_count);
|
||||
@ -656,6 +647,15 @@ startrtclock()
|
||||
{
|
||||
u_int delta, freq;
|
||||
|
||||
if (cpu_feature & CPUID_TSC)
|
||||
tsc_present = 1;
|
||||
else
|
||||
tsc_present = 0;
|
||||
|
||||
#ifdef SMP
|
||||
tsc_present = 0;
|
||||
#endif
|
||||
|
||||
writertc(RTC_STATUSA, rtc_statusa);
|
||||
writertc(RTC_STATUSB, RTCSB_24HR);
|
||||
|
||||
@ -689,14 +689,11 @@ startrtclock()
|
||||
printf(
|
||||
"%d Hz differs from default of %d Hz by more than 1%%\n",
|
||||
freq, timer_freq);
|
||||
#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP)
|
||||
tsc_freq = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
set_timer_freq(timer_freq, hz);
|
||||
|
||||
#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP)
|
||||
#ifndef CLK_USE_TSC_CALIBRATION
|
||||
if (tsc_freq != 0) {
|
||||
if (bootverbose)
|
||||
@ -705,8 +702,7 @@ startrtclock()
|
||||
tsc_freq = 0;
|
||||
}
|
||||
#endif
|
||||
if (tsc_freq == 0 &&
|
||||
(cpu_class == CPUCLASS_586 || cpu_class == CPUCLASS_686)) {
|
||||
if (tsc_present && tsc_freq == 0) {
|
||||
/*
|
||||
* Calibration of the i586 clock relative to the mc146818A
|
||||
* clock failed. Do a less accurate calibration relative
|
||||
@ -715,12 +711,11 @@ startrtclock()
|
||||
wrmsr(0x10, 0LL); /* XXX */
|
||||
DELAY(1000000);
|
||||
set_tsc_freq((u_int)rdtsc(), timer_freq);
|
||||
#ifdef CLK_USE_I586_CALIBRATION
|
||||
#ifdef CLK_USE_TSC_CALIBRATION
|
||||
if (bootverbose)
|
||||
printf("TSC clock: %u Hz\n", tsc_freq);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
@ -925,13 +920,11 @@ cpu_initclocks()
|
||||
|
||||
#endif /* APIC_IO */
|
||||
|
||||
#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP)
|
||||
/*
|
||||
* Finish setting up anti-jitter measures.
|
||||
*/
|
||||
if (tsc_freq != 0)
|
||||
tsc_bias = rdtsc();
|
||||
#endif
|
||||
|
||||
/* Initialize RTC. */
|
||||
writertc(RTC_STATUSA, rtc_statusa);
|
||||
@ -988,9 +981,8 @@ sysctl_machdep_i8254_freq SYSCTL_HANDLER_ARGS
|
||||
if (timer0_state != 0)
|
||||
return (EBUSY); /* too much trouble to handle */
|
||||
set_timer_freq(freq, hz);
|
||||
#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP)
|
||||
set_tsc_freq(tsc_freq, timer_freq);
|
||||
#endif
|
||||
if (tsc_present)
|
||||
set_tsc_freq(tsc_freq, timer_freq);
|
||||
}
|
||||
return (error);
|
||||
}
|
||||
@ -998,23 +990,22 @@ sysctl_machdep_i8254_freq SYSCTL_HANDLER_ARGS
|
||||
SYSCTL_PROC(_machdep, OID_AUTO, i8254_freq, CTLTYPE_INT | CTLFLAG_RW,
|
||||
0, sizeof(u_int), sysctl_machdep_i8254_freq, "I", "");
|
||||
|
||||
#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP)
|
||||
static void
|
||||
set_tsc_freq(u_int i586_freq, u_int i8254_freq)
|
||||
set_tsc_freq(u_int tsc_count, u_int i8254_freq)
|
||||
{
|
||||
u_int comultiplier, multiplier;
|
||||
u_long ef;
|
||||
|
||||
if (i586_freq == 0) {
|
||||
tsc_freq = i586_freq;
|
||||
if (tsc_count == 0) {
|
||||
tsc_freq = tsc_count;
|
||||
return;
|
||||
}
|
||||
comultiplier = ((unsigned long long)i586_freq
|
||||
comultiplier = ((unsigned long long)tsc_count
|
||||
<< TSC_COMULTIPLIER_SHIFT) / i8254_freq;
|
||||
multiplier = (1000000LL << TSC_MULTIPLIER_SHIFT) / i586_freq;
|
||||
multiplier = (1000000LL << TSC_MULTIPLIER_SHIFT) / tsc_count;
|
||||
ef = read_eflags();
|
||||
disable_intr();
|
||||
tsc_freq = i586_freq;
|
||||
tsc_freq = tsc_count;
|
||||
tsc_comultiplier = comultiplier;
|
||||
tsc_multiplier = multiplier;
|
||||
CLOCK_UNLOCK();
|
||||
@ -1022,12 +1013,12 @@ set_tsc_freq(u_int i586_freq, u_int i8254_freq)
|
||||
}
|
||||
|
||||
static int
|
||||
sysctl_machdep_i586_freq SYSCTL_HANDLER_ARGS
|
||||
sysctl_machdep_tsc_freq SYSCTL_HANDLER_ARGS
|
||||
{
|
||||
int error;
|
||||
u_int freq;
|
||||
|
||||
if (cpu_class != CPUCLASS_586 && cpu_class != CPUCLASS_686)
|
||||
if (!tsc_present)
|
||||
return (EOPNOTSUPP);
|
||||
freq = tsc_freq;
|
||||
error = sysctl_handle_opaque(oidp, &freq, sizeof freq, req);
|
||||
@ -1036,6 +1027,5 @@ sysctl_machdep_i586_freq SYSCTL_HANDLER_ARGS
|
||||
return (error);
|
||||
}
|
||||
|
||||
SYSCTL_PROC(_machdep, OID_AUTO, i586_freq, CTLTYPE_INT | CTLFLAG_RW,
|
||||
0, sizeof(u_int), sysctl_machdep_i586_freq, "I", "");
|
||||
#endif /* (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP) */
|
||||
SYSCTL_PROC(_machdep, OID_AUTO, tsc_freq, CTLTYPE_INT | CTLFLAG_RW,
|
||||
0, sizeof(u_int), sysctl_machdep_tsc_freq, "I", "");
|
||||
|
Loading…
Reference in New Issue
Block a user