kernel/x86: Determine the APIC frequency in the kernel instead of the bootloader.
We use the TSC to measure the APIC frequency, but the TSC frequency is only fully initialized in the kernel (where it's read from CPUID on recent hardware). Furthermore, on some more recent systems, it seems there may only be X2APIC and no MMIO APIC timer at all, and the bootloader does not handle that case. The method in the kernel uses spin() instead of a fixed instruction count as well as system_time_nsecs() and a double for (hopefully) more accurate calibration. At least on VMware, this method seems more accurate: the APIC frequency read from the hypervisor CPUID leaf is 66,000,000; the old method in in the bootloader yielded values like "65,801,075" and "65,106,382", while the new one yields values like "65,963,920" and "65,962,580" (those pairs of values are from two consecutive boots.) The difference was sometimes similar (but smaller as a percentage) in QEMU with software emulation: e.g. "993,218,085" vs. "992,965,761". But sometimes it wasn't: e.g "991,619,585" vs. "993,689,669". (QEMU in software mode doesn't report a frequency via hypervisor CPUID leaf.) Change-Id: I4fb8535d1d984f13867e2f84e7dfad1ceed42c13 Reviewed-on: https://review.haiku-os.org/c/haiku/+/8999 Tested-by: Commit checker robot <[email protected]> Reviewed-by: waddlesplash <[email protected]>
This commit is contained in:
committed by
waddlesplash
parent
b801f14f55
commit
3d840c4289
@@ -131,6 +131,7 @@ uint32 apic_lvt_error();
|
||||
void apic_set_lvt_error(uint32 config);
|
||||
uint32 apic_lvt_initial_timer_count();
|
||||
void apic_set_lvt_initial_timer_count(uint32 config);
|
||||
uint32 apic_lvt_current_timer_count();
|
||||
uint32 apic_lvt_timer_divide_config();
|
||||
void apic_set_lvt_timer_divide_config(uint32 config);
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ typedef struct {
|
||||
uint64 virtual_end;
|
||||
uint64 page_hole;
|
||||
// smp stuff
|
||||
uint32 apic_time_cv_factor; // apic ticks per second
|
||||
uint32 _unused; // previously: apic ticks per second
|
||||
uint32 apic_phys;
|
||||
FixedWidthPointer<void> apic;
|
||||
uint32 ioapic_phys;
|
||||
|
||||
Reference in New Issue
Block a user