summaryrefslogtreecommitdiffstats
path: root/sys/i386
diff options
context:
space:
mode:
authorbde <bde@FreeBSD.org>1996-07-30 19:26:55 +0000
committerbde <bde@FreeBSD.org>1996-07-30 19:26:55 +0000
commit008531d59980ae7a5f7f3090057a8fdea1e63d5e (patch)
tree4d6daaea7044e1e95f0e1dfcbd5cdedb651b7567 /sys/i386
parent50a3e4ed9e414f69f86253ea0bf631d402af6571 (diff)
downloadFreeBSD-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.c59
-rw-r--r--sys/i386/include/clock.h8
-rw-r--r--sys/i386/isa/clock.c59
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);
}
OpenPOWER on IntegriCloud