Commit de1292c6 authored by Colin Percival's avatar Colin Percival
Browse files

Use CPUID leaf 0x40000010 for local APIC freq

Some VM systems announce the frequency of the local APIC via the
CPUID leaf 0x40000010.  Using this allows us to boot slightly
faster by avoiding the need for timer calibration.

Reviewed by:	markj
Sponsored by:	https://www.patreon.com/cperciva
parent 4a432614
...@@ -1002,6 +1002,35 @@ native_lapic_disable_pmc(void) ...@@ -1002,6 +1002,35 @@ native_lapic_disable_pmc(void)
#endif #endif
} }
static int
lapic_calibrate_initcount_cpuid_vm(void)
{
u_int regs[4];
uint64_t freq;
/* Get value from CPUID leaf if possible. */
if (vm_guest == VM_GUEST_NO)
return (false);
if (hv_high < 0x40000010)
return (false);
do_cpuid(0x40000010, regs);
freq = (uint64_t)(regs[1]) * 1000;
/* Pick timer divisor. */
lapic_timer_divisor = 2;
do {
if (freq / lapic_timer_divisor < APIC_TIMER_MAX_COUNT)
break;
lapic_timer_divisor <<= 1;
} while (lapic_timer_divisor <= 128);
if (lapic_timer_divisor > 128)
return (false);
/* Record divided frequency. */
count_freq = freq / lapic_timer_divisor;
return (true);
}
static uint64_t static uint64_t
cb_lapic_getcount(void) cb_lapic_getcount(void)
{ {
...@@ -1014,6 +1043,9 @@ lapic_calibrate_initcount(struct lapic *la) ...@@ -1014,6 +1043,9 @@ lapic_calibrate_initcount(struct lapic *la)
{ {
uint64_t freq; uint64_t freq;
if (lapic_calibrate_initcount_cpuid_vm())
goto done;
/* Calibrate the APIC timer frequency. */ /* Calibrate the APIC timer frequency. */
lapic_timer_set_divisor(2); lapic_timer_set_divisor(2);
lapic_timer_oneshot_nointr(la, APIC_TIMER_MAX_COUNT); lapic_timer_oneshot_nointr(la, APIC_TIMER_MAX_COUNT);
...@@ -1031,6 +1063,7 @@ lapic_calibrate_initcount(struct lapic *la) ...@@ -1031,6 +1063,7 @@ lapic_calibrate_initcount(struct lapic *la)
if (lapic_timer_divisor > 128) if (lapic_timer_divisor > 128)
panic("lapic: Divisor too big"); panic("lapic: Divisor too big");
count_freq = freq * 2 / lapic_timer_divisor; count_freq = freq * 2 / lapic_timer_divisor;
done:
if (bootverbose) { if (bootverbose) {
printf("lapic: Divisor %lu, Frequency %lu Hz\n", printf("lapic: Divisor %lu, Frequency %lu Hz\n",
lapic_timer_divisor, count_freq); lapic_timer_divisor, count_freq);
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment