From 65ef516fd89e6f55872f927a3b8de8118a8ab7a7 Mon Sep 17 00:00:00 2001 From: Matheus Date: Wed, 2 Oct 2024 19:42:33 -0300 Subject: [PATCH] tsc: redo calibration, directly use hpet --- kernel-src/arch/x86-64/hpet.c | 23 +++++++++++++++++++++++ kernel-src/arch/x86-64/tsc.c | 25 +++++++++++++------------ kernel-src/include/x86-64/arch/hpet.h | 6 +----- 3 files changed, 37 insertions(+), 17 deletions(-) diff --git a/kernel-src/arch/x86-64/hpet.c b/kernel-src/arch/x86-64/hpet.c index 7ceb7929..876950f2 100644 --- a/kernel-src/arch/x86-64/hpet.c +++ b/kernel-src/arch/x86-64/hpet.c @@ -4,6 +4,7 @@ #include #include #include +#include #include #include @@ -165,6 +166,28 @@ time_t hpet_ticks(timekeeper_source_info_t *) { } } +time_t arch_hpet_calibrate_tsc(time_t ms_wait) { + if (hpet_private.hpet == NULL) + return 0; + + long old_ipl = interrupt_raiseipl(IPL_TIMER - 1); + + uint64_t capabilities = read64(HPET_REG_CAPS); + + time_t ticks_to_wait = ms_wait * 1000000000000lu / HPET_CAP_FSPERTICK(capabilities); + time_t tsc_tick_start = rdtsc_serialized(); + time_t tsc_tick_end; + + time_t ticks_target = hpet_ticks(&timekeeper_source_info) + ticks_to_wait; + + do { + tsc_tick_end = rdtsc_serialized(); + } while (hpet_ticks(&timekeeper_source_info) < ticks_target); + + interrupt_loweripl(old_ipl); + return (tsc_tick_end - tsc_tick_start) / ms_wait; +} + TIMEKEEPER_SOURCE( hpet_source, .name = "HPET", diff --git a/kernel-src/arch/x86-64/tsc.c b/kernel-src/arch/x86-64/tsc.c index 92955429..18c0c165 100644 --- a/kernel-src/arch/x86-64/tsc.c +++ b/kernel-src/arch/x86-64/tsc.c @@ -15,7 +15,11 @@ static bool tsc_probe(void) { return cpuid_results.edx & (1 << 8); } +static MUTEX_DEFINE(init_mutex); +static time_t ticks_per_us; + static timekeeper_source_info_t *tsc_init(void) { + MUTEX_ACQUIRE(&init_mutex, false); __assert(tsc_probe()); timekeeper_source_info_t *timekeeper_source_info = alloc(sizeof(timekeeper_source_info_t)); @@ -23,6 +27,9 @@ static timekeeper_source_info_t *tsc_init(void) { timekeeper_source_info->private = current_cpu(); + if (ticks_per_us) + goto leave; + bool need_calibration = false; if (cpuid_base_max_leaf() >= 0x15) { cpuid_results_t cpuid_results; @@ -38,24 +45,18 @@ static timekeeper_source_info_t *tsc_init(void) { uint64_t core_denominator = cpuid_results.eax; uint64_t tsc_frequency = core_frequency * core_numerator / core_denominator; - timekeeper_source_info->ticks_per_us = tsc_frequency / 1000000; + ticks_per_us = tsc_frequency / 1000000; } calibrate: if (need_calibration) { - for (int i = 0; i < 10; ++i) { - long old_ipl = interrupt_raiseipl(IPL_TIMER - 1); - time_t ticks_start = rdtsc_serialized(); - - timekeeper_wait_us(50000); - time_t ticks_end = rdtsc_serialized(); - - interrupt_loweripl(old_ipl); - - timekeeper_source_info->ticks_per_us = (ticks_end - ticks_start) / 50000; - } + ticks_per_us = arch_hpet_calibrate_tsc(200) / 1000; + __assert(ticks_per_us); } + leave: + timekeeper_source_info->ticks_per_us = ticks_per_us; + MUTEX_RELEASE(&init_mutex); return timekeeper_source_info; } diff --git a/kernel-src/include/x86-64/arch/hpet.h b/kernel-src/include/x86-64/arch/hpet.h index 33784bbd..0d277c9d 100644 --- a/kernel-src/include/x86-64/arch/hpet.h +++ b/kernel-src/include/x86-64/arch/hpet.h @@ -4,10 +4,6 @@ #include #include -time_t arch_hpet_ticks(); -void arch_hpet_waitticks(time_t ticks); -void arch_hpet_waitus(time_t us); -bool arch_hpet_exists(); -time_t arch_hpet_init(); +time_t arch_hpet_calibrate_tsc(time_t ms_wait); #endif