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:
Poul-Henning Kamp 1997-12-28 17:33:10 +00:00
parent d46e059f94
commit 0f12aa9ffd
9 changed files with 164 additions and 240 deletions

View File

@ -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", "");

View File

@ -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 */

View File

@ -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", "");

View File

@ -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 */

View File

@ -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;
}

View File

@ -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", "");

View File

@ -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 */

View File

@ -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", "");

View File

@ -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", "");