diff options
author | bde <bde@FreeBSD.org> | 1996-07-30 19:26:55 +0000 |
---|---|---|
committer | bde <bde@FreeBSD.org> | 1996-07-30 19:26:55 +0000 |
commit | 008531d59980ae7a5f7f3090057a8fdea1e63d5e (patch) | |
tree | 4d6daaea7044e1e95f0e1dfcbd5cdedb651b7567 /sys/i386 | |
parent | 50a3e4ed9e414f69f86253ea0bf631d402af6571 (diff) | |
download | FreeBSD-src-008531d59980ae7a5f7f3090057a8fdea1e63d5e.zip FreeBSD-src-008531d59980ae7a5f7f3090057a8fdea1e63d5e.tar.gz |
Fixed the machdep.i8254_freq and machdep.i586_freq sysctls. Writes were
handled bogusly.
Centralized the setting of all the frequency variables. Set these
variables atomically. Some new ones aren't used yet.
Diffstat (limited to 'sys/i386')
-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 |
3 files changed, 88 insertions, 38 deletions
diff --git a/sys/i386/i386/tsc.c b/sys/i386/i386/tsc.c index 58678a6..7257b2f 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 830ae13..0439363 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 58678a6..7257b2f 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); } |