mirror of
https://github.com/Mathewnd/Astral.git
synced 2026-10-27 12:48:22 +00:00
tsc: redo calibration, directly use hpet
This commit is contained in:
@@ -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",
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user