Changeset View
Changeset View
Standalone View
Standalone View
sys/x86/x86/tsc.c
Show First 20 Lines • Show All 42 Lines • ▼ Show 20 Lines | |||||
#include <sys/sysctl.h> | #include <sys/sysctl.h> | ||||
#include <sys/time.h> | #include <sys/time.h> | ||||
#include <sys/timetc.h> | #include <sys/timetc.h> | ||||
#include <sys/kernel.h> | #include <sys/kernel.h> | ||||
#include <sys/smp.h> | #include <sys/smp.h> | ||||
#include <sys/vdso.h> | #include <sys/vdso.h> | ||||
#include <machine/clock.h> | #include <machine/clock.h> | ||||
#include <machine/cputypes.h> | #include <machine/cputypes.h> | ||||
#include <machine/fpu.h> | |||||
#include <machine/md_var.h> | #include <machine/md_var.h> | ||||
#include <machine/specialreg.h> | #include <machine/specialreg.h> | ||||
#include <x86/vmware.h> | #include <x86/vmware.h> | ||||
#include <dev/acpica/acpi_hpet.h> | #include <dev/acpica/acpi_hpet.h> | ||||
#include <contrib/dev/acpica/include/acpi.h> | #include <contrib/dev/acpica/include/acpi.h> | ||||
#include "cpufreq_if.h" | #include "cpufreq_if.h" | ||||
▲ Show 20 Lines • Show All 639 Lines • ▼ Show 20 Lines | |||||
/* | /* | ||||
* Perform late calibration of the TSC frequency once ACPI-based timecounters | * Perform late calibration of the TSC frequency once ACPI-based timecounters | ||||
* are available. At this point timehands are not set up, so we read the | * are available. At this point timehands are not set up, so we read the | ||||
* highest-quality timecounter directly rather than using (s)binuptime(). | * highest-quality timecounter directly rather than using (s)binuptime(). | ||||
*/ | */ | ||||
void | void | ||||
tsc_calibrate(void) | tsc_calibrate(void) | ||||
{ | { | ||||
struct timecounter *tc; | uint64_t freq; | ||||
uint64_t freq, tsc_start, tsc_end; | |||||
u_int t_start, t_end; | |||||
register_t flags; | |||||
int cpu; | |||||
if (tsc_disabled) | if (tsc_disabled) | ||||
return; | return; | ||||
if (tsc_early_calib_exact) | if (tsc_early_calib_exact) | ||||
goto calibrated; | goto calibrated; | ||||
/* | fpu_kern_enter(curthread, NULL, FPU_KERN_NOCTX); | ||||
* Avoid using a low-quality timecounter to re-calibrate. In | freq = clockcalib(rdtsc_ordered, "TSC"); | ||||
* particular, old 32-bit platforms might only have the 8254 timer to | fpu_kern_leave(curthread, NULL); | ||||
markj: Can't we enter the FPU-enabled section in clockcalib(), rather than forcing all callers to do… | |||||
Not Done Inline ActionsThis was discussed to the death in some previous review. There is no compiler barrier that prevents it from reordering FPU instructions out of the region. The separate compilation unit is used as a kind of barrier, and could break with LTO turned on, I suspect. kib: This was discussed to the death in some previous review. There is no compiler barrier that… | |||||
* calibrate against. | |||||
*/ | |||||
tc = atomic_load_ptr(&timecounter); | |||||
if (tc->tc_quality <= 0) | |||||
goto calibrated; | |||||
flags = intr_disable(); | |||||
cpu = curcpu; | |||||
tsc_start = rdtsc_ordered(); | |||||
t_start = tc->tc_get_timecount(tc) & tc->tc_counter_mask; | |||||
intr_restore(flags); | |||||
DELAY(1000000); | |||||
thread_lock(curthread); | |||||
sched_bind(curthread, cpu); | |||||
flags = intr_disable(); | |||||
tsc_end = rdtsc_ordered(); | |||||
t_end = tc->tc_get_timecount(tc) & tc->tc_counter_mask; | |||||
intr_restore(flags); | |||||
sched_unbind(curthread); | |||||
thread_unlock(curthread); | |||||
if (t_end <= t_start) { | |||||
/* Assume that the counter has wrapped around at most once. */ | |||||
t_end += (uint64_t)tc->tc_counter_mask + 1; | |||||
} | |||||
freq = tc->tc_frequency * (tsc_end - tsc_start) / (t_end - t_start); | |||||
tsc_update_freq(freq); | tsc_update_freq(freq); | ||||
calibrated: | calibrated: | ||||
tc_init(&tsc_timecounter); | tc_init(&tsc_timecounter); | ||||
set_cputicker(rdtsc, tsc_freq, !tsc_is_invariant); | set_cputicker(rdtsc, tsc_freq, !tsc_is_invariant); | ||||
} | } | ||||
void | void | ||||
resume_TSC(void) | resume_TSC(void) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 204 Lines • Show Last 20 Lines |
Can't we enter the FPU-enabled section in clockcalib(), rather than forcing all callers to do it?