diff options
| author | Bruce Evans <bde@FreeBSD.org> | 1996-07-30 19:26:55 +0000 |
|---|---|---|
| committer | Bruce Evans <bde@FreeBSD.org> | 1996-07-30 19:26:55 +0000 |
| commit | 33ded19fc27ff5232f2cac8c093e70839dcb596c (patch) | |
| tree | 4d6daaea7044e1e95f0e1dfcbd5cdedb651b7567 /sys | |
| parent | bbd17bf8e1085896027c21b166e90eb4f3afbe1f (diff) | |
Notes
Diffstat (limited to 'sys')
| -rw-r--r-- | sys/amd64/amd64/tsc.c | 59 | ||||
| -rw-r--r-- | sys/amd64/include/clock.h | 8 | ||||
| -rw-r--r-- | sys/amd64/isa/clock.c | 59 | ||||
| -rw-r--r-- | sys/i386/i386/tsc.c | 59 | ||||
| -rw-r--r-- | sys/i386/include/clock.h | 8 | ||||
| -rw-r--r-- | sys/i386/isa/clock.c | 59 | ||||
| -rw-r--r-- | sys/isa/atrtc.c | 59 |
7 files changed, 217 insertions, 94 deletions
diff --git a/sys/amd64/amd64/tsc.c b/sys/amd64/amd64/tsc.c index 58678a6ea3778..7257b2fb8226a 100644 --- a/sys/amd64/amd64/tsc.c +++ b/sys/amd64/amd64/tsc.c @@ -34,7 +34,7 @@ * SUCH DAMAGE. * * from: @(#)clock.c 7.2 (Berkeley) 5/12/91 - * $Id: clock.c,v 1.64 1996/07/20 18:47:23 joerg Exp $ + * $Id: clock.c,v 1.65 1996/07/21 08:20:51 joerg Exp $ */ /* @@ -102,7 +102,9 @@ int wall_cmos_clock; /* wall CMOS clock assumed if != 0 */ u_int idelayed; #if defined(I586_CPU) || defined(I686_CPU) -unsigned i586_ctr_freq; +u_int i586_ctr_comultiplier; +u_int i586_ctr_freq; +u_int i586_ctr_multiplier; unsigned i586_ctr_rate; long long i586_ctr_bias; long long i586_last_tick; @@ -144,6 +146,10 @@ 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) +static void set_i586_ctr_freq(u_int i586_freq, u_int i8254_freq); +#endif + static void clkintr(struct clockframe frame) { @@ -553,11 +559,7 @@ calibrate_clocks(void) * similar to those for the i8254 clock. */ if (cpu_class == CPUCLASS_586 || cpu_class == CPUCLASS_686) { - unsigned long long i586_count; - - i586_count = rdtsc(); - i586_ctr_freq = i586_count; - i586_ctr_rate = (i586_count << I586_CTR_RATE_SHIFT) / 1000000; + set_i586_ctr_freq((u_int)rdtsc(), tot_count); printf("i586 clock: %u Hz, ", i586_ctr_freq); } #endif @@ -651,12 +653,9 @@ startrtclock() * clock failed. Do a less accurate calibration relative * to the i8254 clock. */ - unsigned long long i586_count; - wrmsr(0x10, 0LL); /* XXX */ DELAY(1000000); - i586_count = rdtsc(); - i586_ctr_rate = (i586_count << I586_CTR_RATE_SHIFT) / 1000000; + set_i586_ctr_freq((u_int)rdtsc(), timer_freq); #ifdef CLK_USE_I586_CALIBRATION printf("i586 clock: %u Hz\n", i586_ctr_freq); #endif @@ -861,10 +860,13 @@ sysctl_machdep_i8254_freq SYSCTL_HANDLER_ARGS */ freq = timer_freq; error = sysctl_handle_opaque(oidp, &freq, sizeof freq, req); - if (error == 0 && freq != timer_freq) { + if (error == 0 && req->newptr != NULL) { if (timer0_state != 0) return (EBUSY); /* too much trouble to handle */ set_timer_freq(freq, hz); +#if defined(I586_CPU) || defined(I686_CPU) + set_i586_ctr_freq(i586_ctr_freq, timer_freq); +#endif } return (error); } @@ -873,21 +875,42 @@ 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) +static void +set_i586_ctr_freq(u_int i586_freq, u_int i8254_freq) +{ + u_int comultiplier, multiplier, rate; + u_long ef; + + if (i586_freq == 0) { + i586_ctr_freq = i586_freq; + i586_ctr_rate = 0; + return; + } + comultiplier = ((unsigned long long)i586_freq + << I586_CTR_COMULTIPLIER_SHIFT) / i8254_freq; + multiplier = (1000000LL << I586_CTR_MULTIPLIER_SHIFT) / i586_freq; + rate = ((unsigned long long)i586_freq << I586_CTR_RATE_SHIFT) / 1000000; + ef = read_eflags(); + disable_intr(); + i586_ctr_freq = i586_freq; + i586_ctr_comultiplier = comultiplier; + i586_ctr_multiplier = multiplier; + i586_ctr_rate = rate; + write_eflags(ef); +} + static int sysctl_machdep_i586_freq SYSCTL_HANDLER_ARGS { int error; u_int freq; - if (i586_ctr_rate == 0) + if (cpu_class != CPUCLASS_586 && cpu_class != CPUCLASS_686) return (EOPNOTSUPP); freq = i586_ctr_freq; error = sysctl_handle_opaque(oidp, &freq, sizeof freq, req); - if (error == 0 && freq != i586_ctr_freq) { - i586_ctr_freq = freq; - i586_ctr_rate = ((unsigned long long)freq << - I586_CTR_RATE_SHIFT) / 1000000; - } + if (error == 0 && req->newptr != NULL) + set_i586_ctr_freq(freq, timer_freq); return (error); } diff --git a/sys/amd64/include/clock.h b/sys/amd64/include/clock.h index 830ae1367a08e..043936310dd5b 100644 --- a/sys/amd64/include/clock.h +++ b/sys/amd64/include/clock.h @@ -3,7 +3,7 @@ * Garrett Wollman, September 1994. * This file is in the public domain. * - * $Id: clock.h,v 1.13 1996/05/01 08:38:50 bde Exp $ + * $Id: clock.h,v 1.14 1996/06/14 11:00:56 asami Exp $ */ #ifndef _MACHINE_CLOCK_H_ @@ -38,6 +38,8 @@ #define CPU_THISTICKLEN(dflt) dflt #endif +#define I586_CTR_COMULTIPLIER_SHIFT 20 +#define I586_CTR_MULTIPLIER_SHIFT 32 #define I586_CTR_RATE_SHIFT 8 #if defined(KERNEL) && !defined(LOCORE) @@ -55,7 +57,9 @@ extern int statclock_disable; extern int wall_cmos_clock; #if defined(I586_CPU) || defined(I686_CPU) -extern unsigned i586_ctr_freq; +extern u_int i586_ctr_comultiplier; +extern u_int i586_ctr_freq; +extern u_int i586_ctr_multiplier; extern unsigned i586_ctr_rate; /* fixed point */ extern long long i586_last_tick; extern long long i586_ctr_bias; diff --git a/sys/amd64/isa/clock.c b/sys/amd64/isa/clock.c index 58678a6ea3778..7257b2fb8226a 100644 --- a/sys/amd64/isa/clock.c +++ b/sys/amd64/isa/clock.c @@ -34,7 +34,7 @@ * SUCH DAMAGE. * * from: @(#)clock.c 7.2 (Berkeley) 5/12/91 - * $Id: clock.c,v 1.64 1996/07/20 18:47:23 joerg Exp $ + * $Id: clock.c,v 1.65 1996/07/21 08:20:51 joerg Exp $ */ /* @@ -102,7 +102,9 @@ int wall_cmos_clock; /* wall CMOS clock assumed if != 0 */ u_int idelayed; #if defined(I586_CPU) || defined(I686_CPU) -unsigned i586_ctr_freq; +u_int i586_ctr_comultiplier; +u_int i586_ctr_freq; +u_int i586_ctr_multiplier; unsigned i586_ctr_rate; long long i586_ctr_bias; long long i586_last_tick; @@ -144,6 +146,10 @@ 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) +static void set_i586_ctr_freq(u_int i586_freq, u_int i8254_freq); +#endif + static void clkintr(struct clockframe frame) { @@ -553,11 +559,7 @@ calibrate_clocks(void) * similar to those for the i8254 clock. */ if (cpu_class == CPUCLASS_586 || cpu_class == CPUCLASS_686) { - unsigned long long i586_count; - - i586_count = rdtsc(); - i586_ctr_freq = i586_count; - i586_ctr_rate = (i586_count << I586_CTR_RATE_SHIFT) / 1000000; + set_i586_ctr_freq((u_int)rdtsc(), tot_count); printf("i586 clock: %u Hz, ", i586_ctr_freq); } #endif @@ -651,12 +653,9 @@ startrtclock() * clock failed. Do a less accurate calibration relative * to the i8254 clock. */ - unsigned long long i586_count; - wrmsr(0x10, 0LL); /* XXX */ DELAY(1000000); - i586_count = rdtsc(); - i586_ctr_rate = (i586_count << I586_CTR_RATE_SHIFT) / 1000000; + set_i586_ctr_freq((u_int)rdtsc(), timer_freq); #ifdef CLK_USE_I586_CALIBRATION printf("i586 clock: %u Hz\n", i586_ctr_freq); #endif @@ -861,10 +860,13 @@ sysctl_machdep_i8254_freq SYSCTL_HANDLER_ARGS */ freq = timer_freq; error = sysctl_handle_opaque(oidp, &freq, sizeof freq, req); - if (error == 0 && freq != timer_freq) { + if (error == 0 && req->newptr != NULL) { if (timer0_state != 0) return (EBUSY); /* too much trouble to handle */ set_timer_freq(freq, hz); +#if defined(I586_CPU) || defined(I686_CPU) + set_i586_ctr_freq(i586_ctr_freq, timer_freq); +#endif } return (error); } @@ -873,21 +875,42 @@ 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) +static void +set_i586_ctr_freq(u_int i586_freq, u_int i8254_freq) +{ + u_int comultiplier, multiplier, rate; + u_long ef; + + if (i586_freq == 0) { + i586_ctr_freq = i586_freq; + i586_ctr_rate = 0; + return; + } + comultiplier = ((unsigned long long)i586_freq + << I586_CTR_COMULTIPLIER_SHIFT) / i8254_freq; + multiplier = (1000000LL << I586_CTR_MULTIPLIER_SHIFT) / i586_freq; + rate = ((unsigned long long)i586_freq << I586_CTR_RATE_SHIFT) / 1000000; + ef = read_eflags(); + disable_intr(); + i586_ctr_freq = i586_freq; + i586_ctr_comultiplier = comultiplier; + i586_ctr_multiplier = multiplier; + i586_ctr_rate = rate; + write_eflags(ef); +} + static int sysctl_machdep_i586_freq SYSCTL_HANDLER_ARGS { int error; u_int freq; - if (i586_ctr_rate == 0) + if (cpu_class != CPUCLASS_586 && cpu_class != CPUCLASS_686) return (EOPNOTSUPP); freq = i586_ctr_freq; error = sysctl_handle_opaque(oidp, &freq, sizeof freq, req); - if (error == 0 && freq != i586_ctr_freq) { - i586_ctr_freq = freq; - i586_ctr_rate = ((unsigned long long)freq << - I586_CTR_RATE_SHIFT) / 1000000; - } + if (error == 0 && req->newptr != NULL) + set_i586_ctr_freq(freq, timer_freq); return (error); } diff --git a/sys/i386/i386/tsc.c b/sys/i386/i386/tsc.c index 58678a6ea3778..7257b2fb8226a 100644 --- a/sys/i386/i386/tsc.c +++ b/sys/i386/i386/tsc.c @@ -34,7 +34,7 @@ * SUCH DAMAGE. * * from: @(#)clock.c 7.2 (Berkeley) 5/12/91 - * $Id: clock.c,v 1.64 1996/07/20 18:47:23 joerg Exp $ + * $Id: clock.c,v 1.65 1996/07/21 08:20:51 joerg Exp $ */ /* @@ -102,7 +102,9 @@ int wall_cmos_clock; /* wall CMOS clock assumed if != 0 */ u_int idelayed; #if defined(I586_CPU) || defined(I686_CPU) -unsigned i586_ctr_freq; +u_int i586_ctr_comultiplier; +u_int i586_ctr_freq; +u_int i586_ctr_multiplier; unsigned i586_ctr_rate; long long i586_ctr_bias; long long i586_last_tick; @@ -144,6 +146,10 @@ 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) +static void set_i586_ctr_freq(u_int i586_freq, u_int i8254_freq); +#endif + static void clkintr(struct clockframe frame) { @@ -553,11 +559,7 @@ calibrate_clocks(void) * similar to those for the i8254 clock. */ if (cpu_class == CPUCLASS_586 || cpu_class == CPUCLASS_686) { - unsigned long long i586_count; - - i586_count = rdtsc(); - i586_ctr_freq = i586_count; - i586_ctr_rate = (i586_count << I586_CTR_RATE_SHIFT) / 1000000; + set_i586_ctr_freq((u_int)rdtsc(), tot_count); printf("i586 clock: %u Hz, ", i586_ctr_freq); } #endif @@ -651,12 +653,9 @@ startrtclock() * clock failed. Do a less accurate calibration relative * to the i8254 clock. */ - unsigned long long i586_count; - wrmsr(0x10, 0LL); /* XXX */ DELAY(1000000); - i586_count = rdtsc(); - i586_ctr_rate = (i586_count << I586_CTR_RATE_SHIFT) / 1000000; + set_i586_ctr_freq((u_int)rdtsc(), timer_freq); #ifdef CLK_USE_I586_CALIBRATION printf("i586 clock: %u Hz\n", i586_ctr_freq); #endif @@ -861,10 +860,13 @@ sysctl_machdep_i8254_freq SYSCTL_HANDLER_ARGS */ freq = timer_freq; error = sysctl_handle_opaque(oidp, &freq, sizeof freq, req); - if (error == 0 && freq != timer_freq) { + if (error == 0 && req->newptr != NULL) { if (timer0_state != 0) return (EBUSY); /* too much trouble to handle */ set_timer_freq(freq, hz); +#if defined(I586_CPU) || defined(I686_CPU) + set_i586_ctr_freq(i586_ctr_freq, timer_freq); +#endif } return (error); } @@ -873,21 +875,42 @@ 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) +static void +set_i586_ctr_freq(u_int i586_freq, u_int i8254_freq) +{ + u_int comultiplier, multiplier, rate; + u_long ef; + + if (i586_freq == 0) { + i586_ctr_freq = i586_freq; + i586_ctr_rate = 0; + return; + } + comultiplier = ((unsigned long long)i586_freq + << I586_CTR_COMULTIPLIER_SHIFT) / i8254_freq; + multiplier = (1000000LL << I586_CTR_MULTIPLIER_SHIFT) / i586_freq; + rate = ((unsigned long long)i586_freq << I586_CTR_RATE_SHIFT) / 1000000; + ef = read_eflags(); + disable_intr(); + i586_ctr_freq = i586_freq; + i586_ctr_comultiplier = comultiplier; + i586_ctr_multiplier = multiplier; + i586_ctr_rate = rate; + write_eflags(ef); +} + static int sysctl_machdep_i586_freq SYSCTL_HANDLER_ARGS { int error; u_int freq; - if (i586_ctr_rate == 0) + if (cpu_class != CPUCLASS_586 && cpu_class != CPUCLASS_686) return (EOPNOTSUPP); freq = i586_ctr_freq; error = sysctl_handle_opaque(oidp, &freq, sizeof freq, req); - if (error == 0 && freq != i586_ctr_freq) { - i586_ctr_freq = freq; - i586_ctr_rate = ((unsigned long long)freq << - I586_CTR_RATE_SHIFT) / 1000000; - } + if (error == 0 && req->newptr != NULL) + set_i586_ctr_freq(freq, timer_freq); return (error); } diff --git a/sys/i386/include/clock.h b/sys/i386/include/clock.h index 830ae1367a08e..043936310dd5b 100644 --- a/sys/i386/include/clock.h +++ b/sys/i386/include/clock.h @@ -3,7 +3,7 @@ * Garrett Wollman, September 1994. * This file is in the public domain. * - * $Id: clock.h,v 1.13 1996/05/01 08:38:50 bde Exp $ + * $Id: clock.h,v 1.14 1996/06/14 11:00:56 asami Exp $ */ #ifndef _MACHINE_CLOCK_H_ @@ -38,6 +38,8 @@ #define CPU_THISTICKLEN(dflt) dflt #endif +#define I586_CTR_COMULTIPLIER_SHIFT 20 +#define I586_CTR_MULTIPLIER_SHIFT 32 #define I586_CTR_RATE_SHIFT 8 #if defined(KERNEL) && !defined(LOCORE) @@ -55,7 +57,9 @@ extern int statclock_disable; extern int wall_cmos_clock; #if defined(I586_CPU) || defined(I686_CPU) -extern unsigned i586_ctr_freq; +extern u_int i586_ctr_comultiplier; +extern u_int i586_ctr_freq; +extern u_int i586_ctr_multiplier; extern unsigned i586_ctr_rate; /* fixed point */ extern long long i586_last_tick; extern long long i586_ctr_bias; diff --git a/sys/i386/isa/clock.c b/sys/i386/isa/clock.c index 58678a6ea3778..7257b2fb8226a 100644 --- a/sys/i386/isa/clock.c +++ b/sys/i386/isa/clock.c @@ -34,7 +34,7 @@ * SUCH DAMAGE. * * from: @(#)clock.c 7.2 (Berkeley) 5/12/91 - * $Id: clock.c,v 1.64 1996/07/20 18:47:23 joerg Exp $ + * $Id: clock.c,v 1.65 1996/07/21 08:20:51 joerg Exp $ */ /* @@ -102,7 +102,9 @@ int wall_cmos_clock; /* wall CMOS clock assumed if != 0 */ u_int idelayed; #if defined(I586_CPU) || defined(I686_CPU) -unsigned i586_ctr_freq; +u_int i586_ctr_comultiplier; +u_int i586_ctr_freq; +u_int i586_ctr_multiplier; unsigned i586_ctr_rate; long long i586_ctr_bias; long long i586_last_tick; @@ -144,6 +146,10 @@ 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) +static void set_i586_ctr_freq(u_int i586_freq, u_int i8254_freq); +#endif + static void clkintr(struct clockframe frame) { @@ -553,11 +559,7 @@ calibrate_clocks(void) * similar to those for the i8254 clock. */ if (cpu_class == CPUCLASS_586 || cpu_class == CPUCLASS_686) { - unsigned long long i586_count; - - i586_count = rdtsc(); - i586_ctr_freq = i586_count; - i586_ctr_rate = (i586_count << I586_CTR_RATE_SHIFT) / 1000000; + set_i586_ctr_freq((u_int)rdtsc(), tot_count); printf("i586 clock: %u Hz, ", i586_ctr_freq); } #endif @@ -651,12 +653,9 @@ startrtclock() * clock failed. Do a less accurate calibration relative * to the i8254 clock. */ - unsigned long long i586_count; - wrmsr(0x10, 0LL); /* XXX */ DELAY(1000000); - i586_count = rdtsc(); - i586_ctr_rate = (i586_count << I586_CTR_RATE_SHIFT) / 1000000; + set_i586_ctr_freq((u_int)rdtsc(), timer_freq); #ifdef CLK_USE_I586_CALIBRATION printf("i586 clock: %u Hz\n", i586_ctr_freq); #endif @@ -861,10 +860,13 @@ sysctl_machdep_i8254_freq SYSCTL_HANDLER_ARGS */ freq = timer_freq; error = sysctl_handle_opaque(oidp, &freq, sizeof freq, req); - if (error == 0 && freq != timer_freq) { + if (error == 0 && req->newptr != NULL) { if (timer0_state != 0) return (EBUSY); /* too much trouble to handle */ set_timer_freq(freq, hz); +#if defined(I586_CPU) || defined(I686_CPU) + set_i586_ctr_freq(i586_ctr_freq, timer_freq); +#endif } return (error); } @@ -873,21 +875,42 @@ 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) +static void +set_i586_ctr_freq(u_int i586_freq, u_int i8254_freq) +{ + u_int comultiplier, multiplier, rate; + u_long ef; + + if (i586_freq == 0) { + i586_ctr_freq = i586_freq; + i586_ctr_rate = 0; + return; + } + comultiplier = ((unsigned long long)i586_freq + << I586_CTR_COMULTIPLIER_SHIFT) / i8254_freq; + multiplier = (1000000LL << I586_CTR_MULTIPLIER_SHIFT) / i586_freq; + rate = ((unsigned long long)i586_freq << I586_CTR_RATE_SHIFT) / 1000000; + ef = read_eflags(); + disable_intr(); + i586_ctr_freq = i586_freq; + i586_ctr_comultiplier = comultiplier; + i586_ctr_multiplier = multiplier; + i586_ctr_rate = rate; + write_eflags(ef); +} + static int sysctl_machdep_i586_freq SYSCTL_HANDLER_ARGS { int error; u_int freq; - if (i586_ctr_rate == 0) + if (cpu_class != CPUCLASS_586 && cpu_class != CPUCLASS_686) return (EOPNOTSUPP); freq = i586_ctr_freq; error = sysctl_handle_opaque(oidp, &freq, sizeof freq, req); - if (error == 0 && freq != i586_ctr_freq) { - i586_ctr_freq = freq; - i586_ctr_rate = ((unsigned long long)freq << - I586_CTR_RATE_SHIFT) / 1000000; - } + if (error == 0 && req->newptr != NULL) + set_i586_ctr_freq(freq, timer_freq); return (error); } diff --git a/sys/isa/atrtc.c b/sys/isa/atrtc.c index 58678a6ea3778..7257b2fb8226a 100644 --- a/sys/isa/atrtc.c +++ b/sys/isa/atrtc.c @@ -34,7 +34,7 @@ * SUCH DAMAGE. * * from: @(#)clock.c 7.2 (Berkeley) 5/12/91 - * $Id: clock.c,v 1.64 1996/07/20 18:47:23 joerg Exp $ + * $Id: clock.c,v 1.65 1996/07/21 08:20:51 joerg Exp $ */ /* @@ -102,7 +102,9 @@ int wall_cmos_clock; /* wall CMOS clock assumed if != 0 */ u_int idelayed; #if defined(I586_CPU) || defined(I686_CPU) -unsigned i586_ctr_freq; +u_int i586_ctr_comultiplier; +u_int i586_ctr_freq; +u_int i586_ctr_multiplier; unsigned i586_ctr_rate; long long i586_ctr_bias; long long i586_last_tick; @@ -144,6 +146,10 @@ 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) +static void set_i586_ctr_freq(u_int i586_freq, u_int i8254_freq); +#endif + static void clkintr(struct clockframe frame) { @@ -553,11 +559,7 @@ calibrate_clocks(void) * similar to those for the i8254 clock. */ if (cpu_class == CPUCLASS_586 || cpu_class == CPUCLASS_686) { - unsigned long long i586_count; - - i586_count = rdtsc(); - i586_ctr_freq = i586_count; - i586_ctr_rate = (i586_count << I586_CTR_RATE_SHIFT) / 1000000; + set_i586_ctr_freq((u_int)rdtsc(), tot_count); printf("i586 clock: %u Hz, ", i586_ctr_freq); } #endif @@ -651,12 +653,9 @@ startrtclock() * clock failed. Do a less accurate calibration relative * to the i8254 clock. */ - unsigned long long i586_count; - wrmsr(0x10, 0LL); /* XXX */ DELAY(1000000); - i586_count = rdtsc(); - i586_ctr_rate = (i586_count << I586_CTR_RATE_SHIFT) / 1000000; + set_i586_ctr_freq((u_int)rdtsc(), timer_freq); #ifdef CLK_USE_I586_CALIBRATION printf("i586 clock: %u Hz\n", i586_ctr_freq); #endif @@ -861,10 +860,13 @@ sysctl_machdep_i8254_freq SYSCTL_HANDLER_ARGS */ freq = timer_freq; error = sysctl_handle_opaque(oidp, &freq, sizeof freq, req); - if (error == 0 && freq != timer_freq) { + if (error == 0 && req->newptr != NULL) { if (timer0_state != 0) return (EBUSY); /* too much trouble to handle */ set_timer_freq(freq, hz); +#if defined(I586_CPU) || defined(I686_CPU) + set_i586_ctr_freq(i586_ctr_freq, timer_freq); +#endif } return (error); } @@ -873,21 +875,42 @@ 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) +static void +set_i586_ctr_freq(u_int i586_freq, u_int i8254_freq) +{ + u_int comultiplier, multiplier, rate; + u_long ef; + + if (i586_freq == 0) { + i586_ctr_freq = i586_freq; + i586_ctr_rate = 0; + return; + } + comultiplier = ((unsigned long long)i586_freq + << I586_CTR_COMULTIPLIER_SHIFT) / i8254_freq; + multiplier = (1000000LL << I586_CTR_MULTIPLIER_SHIFT) / i586_freq; + rate = ((unsigned long long)i586_freq << I586_CTR_RATE_SHIFT) / 1000000; + ef = read_eflags(); + disable_intr(); + i586_ctr_freq = i586_freq; + i586_ctr_comultiplier = comultiplier; + i586_ctr_multiplier = multiplier; + i586_ctr_rate = rate; + write_eflags(ef); +} + static int sysctl_machdep_i586_freq SYSCTL_HANDLER_ARGS { int error; u_int freq; - if (i586_ctr_rate == 0) + if (cpu_class != CPUCLASS_586 && cpu_class != CPUCLASS_686) return (EOPNOTSUPP); freq = i586_ctr_freq; error = sysctl_handle_opaque(oidp, &freq, sizeof freq, req); - if (error == 0 && freq != i586_ctr_freq) { - i586_ctr_freq = freq; - i586_ctr_rate = ((unsigned long long)freq << - I586_CTR_RATE_SHIFT) / 1000000; - } + if (error == 0 && req->newptr != NULL) + set_i586_ctr_freq(freq, timer_freq); return (error); } |
