mirror of
https://github.com/Mathewnd/Astral.git
synced 2026-10-27 12:48:22 +00:00
timekeeper: ticks_per_us (mhz) -> hz
This commit is contained in:
@@ -89,7 +89,7 @@ static timekeeper_source_info_t *hpet_init(void) {
|
||||
struct acpi_hpet *table;
|
||||
|
||||
MUTEX_ACQUIRE(&init_mutex, false);
|
||||
if (timekeeper_source_info.ticks_per_us) {
|
||||
if (timekeeper_source_info.hz) {
|
||||
// already initialized by someone else
|
||||
goto leave;
|
||||
}
|
||||
@@ -107,9 +107,9 @@ static timekeeper_source_info_t *hpet_init(void) {
|
||||
hpet_private.hpet = (void *)((uintptr_t)hpet_private.hpet + page_offset);
|
||||
|
||||
uint64_t capabilities = read64(HPET_REG_CAPS);
|
||||
timekeeper_source_info.ticks_per_us = 1000000000 / HPET_CAP_FSPERTICK(capabilities);
|
||||
printf("hpet%lu: %lu ticks per us (%lu fs per tick)\n", table->number, timekeeper_source_info.ticks_per_us, HPET_CAP_FSPERTICK(capabilities));
|
||||
__assert(timekeeper_source_info.ticks_per_us);
|
||||
timekeeper_source_info.hz = 1000000000000000lu / HPET_CAP_FSPERTICK(capabilities);
|
||||
printf("hpet%lu: %lu ticks per us (%lu hz)\n", table->number, timekeeper_source_info.hz, HPET_CAP_FSPERTICK(capabilities));
|
||||
__assert(timekeeper_source_info.hz);
|
||||
|
||||
write64(HPET_REG_CONFIG, 0);
|
||||
write64(HPET_REG_COUNTER, 0);
|
||||
|
||||
@@ -47,7 +47,7 @@ static timekeeper_source_info_t *kvm_timer_init(void) {
|
||||
timekeeper_source_info_t *timekeeper_source_info = alloc(sizeof(timekeeper_source_info_t));
|
||||
__assert(timekeeper_source_info);
|
||||
|
||||
timekeeper_source_info->ticks_per_us = 1000; // each tick in the kvm timer system_time field is 1 ns
|
||||
timekeeper_source_info->hz = 1000000000; // each tick in the kvm timer system_time field is 1 ns
|
||||
void *virtual_address = alloc(sizeof(kvm_timer_info_t));
|
||||
__assert(virtual_address);
|
||||
__assert(((uintptr_t)virtual_address % KVM_TIMER_SYSTEM_TIME_ALIGNMENT) == 0);
|
||||
|
||||
@@ -21,7 +21,9 @@ static bool tsc_probe(void) {
|
||||
}
|
||||
|
||||
static MUTEX_DEFINE(init_mutex);
|
||||
static time_t ticks_per_us;
|
||||
// keeping this here in a multisocket machine could possibly result in completely wrong
|
||||
// tsc measurements for the other sokets. disable the tsc in these using the "notsc" commandline option.
|
||||
static time_t hz;
|
||||
|
||||
static timekeeper_source_info_t *tsc_init(void) {
|
||||
MUTEX_ACQUIRE(&init_mutex, false);
|
||||
@@ -32,7 +34,7 @@ static timekeeper_source_info_t *tsc_init(void) {
|
||||
|
||||
timekeeper_source_info->private = current_cpu();
|
||||
|
||||
if (ticks_per_us)
|
||||
if (hz)
|
||||
goto leave;
|
||||
|
||||
bool need_calibration = false;
|
||||
@@ -50,17 +52,17 @@ 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;
|
||||
ticks_per_us = tsc_frequency / 1000000;
|
||||
hz = tsc_frequency;
|
||||
}
|
||||
|
||||
calibrate:
|
||||
if (need_calibration) {
|
||||
ticks_per_us = arch_hpet_calibrate_tsc(200) / 1000;
|
||||
__assert(ticks_per_us);
|
||||
hz = arch_hpet_calibrate_tsc(200) * 1000;
|
||||
__assert(hz);
|
||||
}
|
||||
|
||||
leave:
|
||||
timekeeper_source_info->ticks_per_us = ticks_per_us;
|
||||
timekeeper_source_info->hz = hz;
|
||||
MUTEX_RELEASE(&init_mutex);
|
||||
return timekeeper_source_info;
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#define TIMEKEEPER_SOURCE_FLAGS_EARLY 1 // can be used as an early timer
|
||||
|
||||
typedef struct {
|
||||
time_t ticks_per_us;
|
||||
time_t hz;
|
||||
void *private;
|
||||
} timekeeper_source_info_t;
|
||||
|
||||
|
||||
+21
-18
@@ -17,17 +17,16 @@ timespec_t timekeeper_timefromboot(void) {
|
||||
|
||||
time_t ticks = current_cpu()->timekeeper_source->ticks(current_cpu()->timekeeper_source_info);
|
||||
time_t base_ticks = current_cpu()->timekeeper_source_base_ticks;
|
||||
time_t ticks_per_us = current_cpu()->timekeeper_source_info->ticks_per_us;
|
||||
time_t hz = current_cpu()->timekeeper_source_info->hz;
|
||||
time_t tick_offset = current_cpu()->timekeeper_source_tick_offset;
|
||||
|
||||
interrupt_loweripl(old_ipl);
|
||||
|
||||
timespec_t ts;
|
||||
ticks = ticks - base_ticks + tick_offset;
|
||||
time_t us_passed = ticks / ticks_per_us;
|
||||
|
||||
ts.s = us_passed / 1000000;
|
||||
ts.ns = (us_passed * 1000) % 1000000000;
|
||||
ts.s = ticks / hz;
|
||||
ts.ns = (ticks % hz) / (hz / 1000000) * 1000;
|
||||
|
||||
return ts;
|
||||
}
|
||||
@@ -46,8 +45,8 @@ static MUTEX_DEFINE(sync_mutex);
|
||||
static volatile bool sync_go_ahead;
|
||||
static volatile int cpus_waiting;
|
||||
static volatile int cpus_done;
|
||||
static volatile time_t sync_ticks;
|
||||
static volatile time_t sync_ticks_per_us;
|
||||
static volatile time_t sync_sec;
|
||||
static volatile time_t sync_usec;
|
||||
|
||||
static void timekeeper_sync_isr(isr_t *, context_t *) {
|
||||
// taking interrupts here could possibly add an undetermined amount of latency, which is bad
|
||||
@@ -55,13 +54,15 @@ static void timekeeper_sync_isr(isr_t *, context_t *) {
|
||||
|
||||
// try to get the tick code into the cache
|
||||
current_cpu()->timekeeper_source->ticks(current_cpu()->timekeeper_source_info);
|
||||
time_t hz = current_cpu()->timekeeper_source_info->hz;
|
||||
time_t mhz = hz / 1000000;
|
||||
|
||||
__atomic_fetch_add(&cpus_waiting, 1, __ATOMIC_SEQ_CST);
|
||||
|
||||
while (sync_go_ahead == false) asm("");
|
||||
|
||||
current_cpu()->timekeeper_source_base_ticks = current_cpu()->timekeeper_source->ticks(current_cpu()->timekeeper_source_info);
|
||||
current_cpu()->timekeeper_source_tick_offset = sync_ticks / sync_ticks_per_us * current_cpu()->timekeeper_source_info->ticks_per_us;
|
||||
current_cpu()->timekeeper_source_tick_offset = sync_sec * hz + sync_usec * mhz;
|
||||
|
||||
__atomic_fetch_add(&cpus_done, 1, __ATOMIC_SEQ_CST);
|
||||
}
|
||||
@@ -88,13 +89,15 @@ void timekeeper_sync(void) {
|
||||
// try to get things into the cache
|
||||
timekeeper_source_t *timekeeper_source = current_cpu()->timekeeper_source;
|
||||
timekeeper_source_info_t *timekeeper_source_info = current_cpu()->timekeeper_source_info;
|
||||
sync_ticks = timekeeper_source->ticks(timekeeper_source_info) - current_cpu()->timekeeper_source_base_ticks;
|
||||
sync_ticks_per_us = timekeeper_source_info->ticks_per_us;
|
||||
time_t hz = timekeeper_source_info->hz;
|
||||
time_t mhz = hz / 1000000;
|
||||
|
||||
while (cpus_waiting != arch_smp_cpusawake - 1) CPU_PAUSE();
|
||||
|
||||
// for real this time
|
||||
sync_ticks = timekeeper_source->ticks(timekeeper_source_info) - current_cpu()->timekeeper_source_base_ticks;
|
||||
time_t ticks = timekeeper_source->ticks(timekeeper_source_info) - current_cpu()->timekeeper_source_base_ticks;
|
||||
sync_sec = ticks / hz;
|
||||
sync_usec = (ticks % hz) / mhz;
|
||||
sync_go_ahead = true;
|
||||
|
||||
while (cpus_done != arch_smp_cpusawake - 1) CPU_PAUSE();
|
||||
@@ -103,7 +106,7 @@ void timekeeper_sync(void) {
|
||||
MUTEX_RELEASE(&sync_mutex);
|
||||
|
||||
for (int i = 0; i < arch_smp_cpusawake; ++i) {
|
||||
printf("cpu %d offset (us) @ %lu\n", smp_cpus[i]->id, smp_cpus[i]->timekeeper_source_tick_offset / smp_cpus[i]->timekeeper_source_info->ticks_per_us);
|
||||
printf("cpu %d offset (ticks) @ %lu\n", smp_cpus[i]->id, smp_cpus[i]->timekeeper_source_tick_offset);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -154,10 +157,10 @@ void timekeeper_early_init(time_t us_offset) {
|
||||
|
||||
// this tick offset is to account for any possible time before early_init.
|
||||
// for example, on SMP init the early init will have the time passed on the ap as an offset
|
||||
current_cpu()->timekeeper_source_tick_offset = us_offset * early_source_info->ticks_per_us;
|
||||
current_cpu()->timekeeper_source_tick_offset = us_offset * early_source_info->hz / 1000000;
|
||||
|
||||
printf("cpu%d: timekeeper: \"%s\" selected as early source. %lu ticks at early init (%lu ticks per us)\n",
|
||||
current_cpu_id(), early_source->name, current_cpu()->timekeeper_source_base_ticks, early_source_info->ticks_per_us);
|
||||
printf("cpu%d: timekeeper: \"%s\" selected as early source. %lu ticks at early init (%lu hz)\n",
|
||||
current_cpu_id(), early_source->name, current_cpu()->timekeeper_source_base_ticks, early_source_info->hz);
|
||||
}
|
||||
|
||||
// this will do a re-init per cpu
|
||||
@@ -190,11 +193,11 @@ void timekeeper_init(void) {
|
||||
// we will calculate how much time passed and have a tick offset
|
||||
time_t old_tick_offset = current_cpu()->timekeeper_source_tick_offset;
|
||||
time_t old_ticks = old_source->ticks(old_source_info);
|
||||
time_t old_us = (old_ticks - old_base + old_tick_offset) / old_source_info->ticks_per_us; // XXX would a division with rounding be better for precision here?
|
||||
current_cpu()->timekeeper_source_tick_offset = old_us * new_source_info->ticks_per_us;
|
||||
time_t old_us = (old_ticks - old_base + old_tick_offset) / (old_source_info->hz / 1000000); // XXX would a division with rounding be better for precision here?
|
||||
current_cpu()->timekeeper_source_tick_offset = old_us * (new_source_info->hz / 1000000);
|
||||
|
||||
interrupt_loweripl(old_ipl);
|
||||
|
||||
printf("cpu%d: timekeeper: \"%s\" selected as main source. %lu ticks at init (%lu ticks per us)\n",
|
||||
current_cpu_id(), new_source->name, current_cpu()->timekeeper_source_base_ticks, new_source_info->ticks_per_us);
|
||||
printf("cpu%d: timekeeper: \"%s\" selected as main source. %lu ticks at init (%lu hz)\n",
|
||||
current_cpu_id(), new_source->name, current_cpu()->timekeeper_source_base_ticks, new_source_info->hz);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user