Switch to using the TSC code in i386/i386/tsc.c.

This commit is contained in:
phk 2003-02-11 11:43:25 +00:00
parent 85caad2949
commit ea4f5a71da
4 changed files with 4 additions and 342 deletions

View File

@ -138,9 +138,6 @@ int statclock_disable;
#endif
u_int timer_freq = TIMER_FREQ;
int timer0_max_count;
uint64_t tsc_freq;
int tsc_is_broken;
u_int tsc_present;
int wall_cmos_clock; /* wall CMOS clock assumed if != 0 */
struct mtx clock_lock;
@ -173,17 +170,8 @@ static u_char timer2_state;
static void (*timer_func)(struct clockframe *frame) = hardclock;
static unsigned i8254_get_timecount(struct timecounter *tc);
static unsigned tsc_get_timecount(struct timecounter *tc);
static void set_timer_freq(u_int freq, int intr_freq);
static struct timecounter tsc_timecounter = {
tsc_get_timecount, /* get_timecount */
0, /* no poll_pps */
~0u, /* counter_mask */
0, /* frequency */
"TSC" /* name */
};
static struct timecounter i8254_timecounter = {
i8254_get_timecount, /* get_timecount */
0, /* no poll_pps */
@ -592,7 +580,6 @@ readrtc(int port)
static u_int
calibrate_clocks(void)
{
u_int64_t old_tsc;
u_int count, prev_count, tot_count;
int sec, start_sec, timeout;
@ -630,11 +617,6 @@ calibrate_clocks(void)
goto fail;
tot_count = 0;
if (tsc_present)
old_tsc = rdtsc();
else
old_tsc = 0; /* shut up gcc */
/*
* Wait for the mc146818A seconds counter to change. Read the i8254
* counter for each iteration since this is convenient and only
@ -663,16 +645,7 @@ calibrate_clocks(void)
goto fail;
}
/*
* Read the cpu cycle counter. The timing considerations are
* similar to those for the i8254 clock.
*/
if (tsc_present)
tsc_freq = rdtsc() - old_tsc;
if (bootverbose) {
if (tsc_present)
printf("TSC clock: %ju Hz, ", (intmax_t)tsc_freq);
printf("i8254 clock: %u Hz\n", tot_count);
}
return (tot_count);
@ -747,11 +720,6 @@ startrtclock()
{
u_int delta, freq;
if (cpu_feature & CPUID_TSC)
tsc_present = 1;
else
tsc_present = 0;
writertc(RTC_STATUSA, rtc_statusa);
writertc(RTC_STATUSB, RTCSB_24HR);
@ -785,68 +753,13 @@ startrtclock()
printf(
"%d Hz differs from default of %d Hz by more than 1%%\n",
freq, timer_freq);
tsc_freq = 0;
}
set_timer_freq(timer_freq, hz);
i8254_timecounter.tc_frequency = timer_freq;
tc_init(&i8254_timecounter);
#ifndef CLK_USE_TSC_CALIBRATION
if (tsc_freq != 0) {
if (bootverbose)
printf(
"CLK_USE_TSC_CALIBRATION not specified - using old calibration method\n");
tsc_freq = 0;
}
#endif
if (tsc_present && tsc_freq == 0) {
/*
* Calibration of the i586 clock relative to the mc146818A
* clock failed. Do a less accurate calibration relative
* to the i8254 clock.
*/
u_int64_t old_tsc = rdtsc();
DELAY(1000000);
tsc_freq = rdtsc() - old_tsc;
#ifdef CLK_USE_TSC_CALIBRATION
if (bootverbose)
printf("TSC clock: %ju Hz (Method B)\n",
(intmax_t)tsc_freq);
#endif
}
#if !defined(SMP)
/*
* We can not use the TSC in SMP mode, until we figure out a
* cheap (impossible), reliable and precise (yeah right!) way
* to synchronize the TSCs of all the CPUs.
* Curse Intel for leaving the counter out of the I/O APIC.
*/
/*
* We can not use the TSC if we support APM. Precise timekeeping
* on an APM'ed machine is at best a fools pursuit, since
* any and all of the time spent in various SMM code can't
* be reliably accounted for. Reading the RTC is your only
* source of reliable time info. The i8254 looses too of course
* but we need to have some kind of time...
* We don't know at this point whether APM is going to be used
* or not, nor when it might be activated. Play it safe.
*/
if (power_pm_get_type() == POWER_PM_TYPE_APM) {
if (bootverbose)
printf("TSC initialization skipped: APM enabled.\n");
return;
}
if (tsc_present && tsc_freq != 0 && !tsc_is_broken) {
tsc_timecounter.tc_frequency = tsc_freq;
tc_init(&tsc_timecounter);
}
#endif /* !defined(SMP) */
init_TSC();
}
/*
@ -1218,26 +1131,6 @@ 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, "IU", "");
static int
sysctl_machdep_tsc_freq(SYSCTL_HANDLER_ARGS)
{
int error;
uint64_t freq;
if (tsc_timecounter.tc_frequency == 0)
return (EOPNOTSUPP);
freq = tsc_freq;
error = sysctl_handle_int(oidp, &freq, sizeof(freq), req);
if (error == 0 && req->newptr != NULL) {
tsc_freq = freq;
tsc_timecounter.tc_frequency = tsc_freq;
}
return (error);
}
SYSCTL_PROC(_machdep, OID_AUTO, tsc_freq, CTLTYPE_QUAD | CTLFLAG_RW,
0, sizeof(u_int), sysctl_machdep_tsc_freq, "IU", "");
static unsigned
i8254_get_timecount(struct timecounter *tc)
{
@ -1274,12 +1167,6 @@ i8254_get_timecount(struct timecounter *tc)
return (count);
}
static unsigned
tsc_get_timecount(struct timecounter *tc)
{
return (rdtsc());
}
#ifdef DEV_ISA
/*
* Attach to the ISA PnP descriptors for the timer and realtime clock.

View File

@ -231,6 +231,7 @@ i386/i386/pmap.c standard
i386/i386/support.s standard
i386/i386/swtch.s standard
i386/i386/sys_machdep.c standard
i386/i386/tsc.c standard
i386/i386/trap.c standard
i386/i386/vm86.c standard
i386/i386/vm_machdep.c standard

View File

@ -138,9 +138,6 @@ int statclock_disable;
#endif
u_int timer_freq = TIMER_FREQ;
int timer0_max_count;
uint64_t tsc_freq;
int tsc_is_broken;
u_int tsc_present;
int wall_cmos_clock; /* wall CMOS clock assumed if != 0 */
struct mtx clock_lock;
@ -173,17 +170,8 @@ static u_char timer2_state;
static void (*timer_func)(struct clockframe *frame) = hardclock;
static unsigned i8254_get_timecount(struct timecounter *tc);
static unsigned tsc_get_timecount(struct timecounter *tc);
static void set_timer_freq(u_int freq, int intr_freq);
static struct timecounter tsc_timecounter = {
tsc_get_timecount, /* get_timecount */
0, /* no poll_pps */
~0u, /* counter_mask */
0, /* frequency */
"TSC" /* name */
};
static struct timecounter i8254_timecounter = {
i8254_get_timecount, /* get_timecount */
0, /* no poll_pps */
@ -592,7 +580,6 @@ readrtc(int port)
static u_int
calibrate_clocks(void)
{
u_int64_t old_tsc;
u_int count, prev_count, tot_count;
int sec, start_sec, timeout;
@ -630,11 +617,6 @@ calibrate_clocks(void)
goto fail;
tot_count = 0;
if (tsc_present)
old_tsc = rdtsc();
else
old_tsc = 0; /* shut up gcc */
/*
* Wait for the mc146818A seconds counter to change. Read the i8254
* counter for each iteration since this is convenient and only
@ -663,16 +645,7 @@ calibrate_clocks(void)
goto fail;
}
/*
* Read the cpu cycle counter. The timing considerations are
* similar to those for the i8254 clock.
*/
if (tsc_present)
tsc_freq = rdtsc() - old_tsc;
if (bootverbose) {
if (tsc_present)
printf("TSC clock: %ju Hz, ", (intmax_t)tsc_freq);
printf("i8254 clock: %u Hz\n", tot_count);
}
return (tot_count);
@ -747,11 +720,6 @@ startrtclock()
{
u_int delta, freq;
if (cpu_feature & CPUID_TSC)
tsc_present = 1;
else
tsc_present = 0;
writertc(RTC_STATUSA, rtc_statusa);
writertc(RTC_STATUSB, RTCSB_24HR);
@ -785,68 +753,13 @@ startrtclock()
printf(
"%d Hz differs from default of %d Hz by more than 1%%\n",
freq, timer_freq);
tsc_freq = 0;
}
set_timer_freq(timer_freq, hz);
i8254_timecounter.tc_frequency = timer_freq;
tc_init(&i8254_timecounter);
#ifndef CLK_USE_TSC_CALIBRATION
if (tsc_freq != 0) {
if (bootverbose)
printf(
"CLK_USE_TSC_CALIBRATION not specified - using old calibration method\n");
tsc_freq = 0;
}
#endif
if (tsc_present && tsc_freq == 0) {
/*
* Calibration of the i586 clock relative to the mc146818A
* clock failed. Do a less accurate calibration relative
* to the i8254 clock.
*/
u_int64_t old_tsc = rdtsc();
DELAY(1000000);
tsc_freq = rdtsc() - old_tsc;
#ifdef CLK_USE_TSC_CALIBRATION
if (bootverbose)
printf("TSC clock: %ju Hz (Method B)\n",
(intmax_t)tsc_freq);
#endif
}
#if !defined(SMP)
/*
* We can not use the TSC in SMP mode, until we figure out a
* cheap (impossible), reliable and precise (yeah right!) way
* to synchronize the TSCs of all the CPUs.
* Curse Intel for leaving the counter out of the I/O APIC.
*/
/*
* We can not use the TSC if we support APM. Precise timekeeping
* on an APM'ed machine is at best a fools pursuit, since
* any and all of the time spent in various SMM code can't
* be reliably accounted for. Reading the RTC is your only
* source of reliable time info. The i8254 looses too of course
* but we need to have some kind of time...
* We don't know at this point whether APM is going to be used
* or not, nor when it might be activated. Play it safe.
*/
if (power_pm_get_type() == POWER_PM_TYPE_APM) {
if (bootverbose)
printf("TSC initialization skipped: APM enabled.\n");
return;
}
if (tsc_present && tsc_freq != 0 && !tsc_is_broken) {
tsc_timecounter.tc_frequency = tsc_freq;
tc_init(&tsc_timecounter);
}
#endif /* !defined(SMP) */
init_TSC();
}
/*
@ -1218,26 +1131,6 @@ 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, "IU", "");
static int
sysctl_machdep_tsc_freq(SYSCTL_HANDLER_ARGS)
{
int error;
uint64_t freq;
if (tsc_timecounter.tc_frequency == 0)
return (EOPNOTSUPP);
freq = tsc_freq;
error = sysctl_handle_int(oidp, &freq, sizeof(freq), req);
if (error == 0 && req->newptr != NULL) {
tsc_freq = freq;
tsc_timecounter.tc_frequency = tsc_freq;
}
return (error);
}
SYSCTL_PROC(_machdep, OID_AUTO, tsc_freq, CTLTYPE_QUAD | CTLFLAG_RW,
0, sizeof(u_int), sysctl_machdep_tsc_freq, "IU", "");
static unsigned
i8254_get_timecount(struct timecounter *tc)
{
@ -1274,12 +1167,6 @@ i8254_get_timecount(struct timecounter *tc)
return (count);
}
static unsigned
tsc_get_timecount(struct timecounter *tc)
{
return (rdtsc());
}
#ifdef DEV_ISA
/*
* Attach to the ISA PnP descriptors for the timer and realtime clock.

View File

@ -138,9 +138,6 @@ int statclock_disable;
#endif
u_int timer_freq = TIMER_FREQ;
int timer0_max_count;
uint64_t tsc_freq;
int tsc_is_broken;
u_int tsc_present;
int wall_cmos_clock; /* wall CMOS clock assumed if != 0 */
struct mtx clock_lock;
@ -173,17 +170,8 @@ static u_char timer2_state;
static void (*timer_func)(struct clockframe *frame) = hardclock;
static unsigned i8254_get_timecount(struct timecounter *tc);
static unsigned tsc_get_timecount(struct timecounter *tc);
static void set_timer_freq(u_int freq, int intr_freq);
static struct timecounter tsc_timecounter = {
tsc_get_timecount, /* get_timecount */
0, /* no poll_pps */
~0u, /* counter_mask */
0, /* frequency */
"TSC" /* name */
};
static struct timecounter i8254_timecounter = {
i8254_get_timecount, /* get_timecount */
0, /* no poll_pps */
@ -592,7 +580,6 @@ readrtc(int port)
static u_int
calibrate_clocks(void)
{
u_int64_t old_tsc;
u_int count, prev_count, tot_count;
int sec, start_sec, timeout;
@ -630,11 +617,6 @@ calibrate_clocks(void)
goto fail;
tot_count = 0;
if (tsc_present)
old_tsc = rdtsc();
else
old_tsc = 0; /* shut up gcc */
/*
* Wait for the mc146818A seconds counter to change. Read the i8254
* counter for each iteration since this is convenient and only
@ -663,16 +645,7 @@ calibrate_clocks(void)
goto fail;
}
/*
* Read the cpu cycle counter. The timing considerations are
* similar to those for the i8254 clock.
*/
if (tsc_present)
tsc_freq = rdtsc() - old_tsc;
if (bootverbose) {
if (tsc_present)
printf("TSC clock: %ju Hz, ", (intmax_t)tsc_freq);
printf("i8254 clock: %u Hz\n", tot_count);
}
return (tot_count);
@ -747,11 +720,6 @@ startrtclock()
{
u_int delta, freq;
if (cpu_feature & CPUID_TSC)
tsc_present = 1;
else
tsc_present = 0;
writertc(RTC_STATUSA, rtc_statusa);
writertc(RTC_STATUSB, RTCSB_24HR);
@ -785,68 +753,13 @@ startrtclock()
printf(
"%d Hz differs from default of %d Hz by more than 1%%\n",
freq, timer_freq);
tsc_freq = 0;
}
set_timer_freq(timer_freq, hz);
i8254_timecounter.tc_frequency = timer_freq;
tc_init(&i8254_timecounter);
#ifndef CLK_USE_TSC_CALIBRATION
if (tsc_freq != 0) {
if (bootverbose)
printf(
"CLK_USE_TSC_CALIBRATION not specified - using old calibration method\n");
tsc_freq = 0;
}
#endif
if (tsc_present && tsc_freq == 0) {
/*
* Calibration of the i586 clock relative to the mc146818A
* clock failed. Do a less accurate calibration relative
* to the i8254 clock.
*/
u_int64_t old_tsc = rdtsc();
DELAY(1000000);
tsc_freq = rdtsc() - old_tsc;
#ifdef CLK_USE_TSC_CALIBRATION
if (bootverbose)
printf("TSC clock: %ju Hz (Method B)\n",
(intmax_t)tsc_freq);
#endif
}
#if !defined(SMP)
/*
* We can not use the TSC in SMP mode, until we figure out a
* cheap (impossible), reliable and precise (yeah right!) way
* to synchronize the TSCs of all the CPUs.
* Curse Intel for leaving the counter out of the I/O APIC.
*/
/*
* We can not use the TSC if we support APM. Precise timekeeping
* on an APM'ed machine is at best a fools pursuit, since
* any and all of the time spent in various SMM code can't
* be reliably accounted for. Reading the RTC is your only
* source of reliable time info. The i8254 looses too of course
* but we need to have some kind of time...
* We don't know at this point whether APM is going to be used
* or not, nor when it might be activated. Play it safe.
*/
if (power_pm_get_type() == POWER_PM_TYPE_APM) {
if (bootverbose)
printf("TSC initialization skipped: APM enabled.\n");
return;
}
if (tsc_present && tsc_freq != 0 && !tsc_is_broken) {
tsc_timecounter.tc_frequency = tsc_freq;
tc_init(&tsc_timecounter);
}
#endif /* !defined(SMP) */
init_TSC();
}
/*
@ -1218,26 +1131,6 @@ 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, "IU", "");
static int
sysctl_machdep_tsc_freq(SYSCTL_HANDLER_ARGS)
{
int error;
uint64_t freq;
if (tsc_timecounter.tc_frequency == 0)
return (EOPNOTSUPP);
freq = tsc_freq;
error = sysctl_handle_int(oidp, &freq, sizeof(freq), req);
if (error == 0 && req->newptr != NULL) {
tsc_freq = freq;
tsc_timecounter.tc_frequency = tsc_freq;
}
return (error);
}
SYSCTL_PROC(_machdep, OID_AUTO, tsc_freq, CTLTYPE_QUAD | CTLFLAG_RW,
0, sizeof(u_int), sysctl_machdep_tsc_freq, "IU", "");
static unsigned
i8254_get_timecount(struct timecounter *tc)
{
@ -1274,12 +1167,6 @@ i8254_get_timecount(struct timecounter *tc)
return (count);
}
static unsigned
tsc_get_timecount(struct timecounter *tc)
{
return (rdtsc());
}
#ifdef DEV_ISA
/*
* Attach to the ISA PnP descriptors for the timer and realtime clock.