tsc: redo calibration, directly use hpet

This commit is contained in:
Matheus
2024-10-02 19:42:33 -03:00
parent e9b9242653
commit 65ef516fd8
3 changed files with 37 additions and 17 deletions
+23
View File
@@ -4,6 +4,7 @@
#include <arch/hpet.h>
#include <kernel/vmm.h>
#include <kernel/interrupt.h>
#include <arch/tsc.h>
#include <uacpi/acpi.h>
#include <uacpi/tables.h>
@@ -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",
+13 -12
View File
@@ -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;
}
+1 -5
View File
@@ -4,10 +4,6 @@
#include <stdbool.h>
#include <time.h>
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