Changeset View
Changeset View
Standalone View
Standalone View
sys/x86/x86/tsc.c
Show First 20 Lines • Show All 141 Lines • ▼ Show 20 Lines | tsc_freq_vmware(void) | ||||
u_int regs[4]; | u_int regs[4]; | ||||
vmware_hvcall(VMW_HVCMD_GETHZ, regs); | vmware_hvcall(VMW_HVCMD_GETHZ, regs); | ||||
if (regs[1] != UINT_MAX) | if (regs[1] != UINT_MAX) | ||||
tsc_freq = regs[0] | ((uint64_t)regs[1] << 32); | tsc_freq = regs[0] | ((uint64_t)regs[1] << 32); | ||||
tsc_early_calib_exact = 1; | tsc_early_calib_exact = 1; | ||||
} | } | ||||
static void | |||||
tsc_freq_xen(void) | |||||
{ | |||||
u_int regs[4]; | |||||
/* | /* | ||||
* Must run *after* generic tsc_freq_cpuid_vm, so that when Xen is | |||||
* emulating Viridian support the Viridian leaf is used instead. | |||||
markj: Since this routine is using virtualized cpuid leaf to obtain a fequency value, why not simply… | |||||
Done Inline ActionsI was mostly following what's done for tsc_freq_vmware(), but I could see about unifying all those into a single helper if that's preferred. royger: I was mostly following what's done for tsc_freq_vmware(), but I could see about unifying all… | |||||
Not Done Inline ActionsOk, on second thought your approach seems good. The probe_tsc_freq() helpers are a bit inconsistent (e.g., whether or not they assign to tsc_freq directly or not, whether they emit the bootverbose message or not) and could maybe benefit from some refactoring, but that's a separate change. markj: Ok, on second thought your approach seems good. The probe_tsc_freq() helpers are a bit… | |||||
*/ | |||||
KASSERT(hv_high >= 0x40000003, ("Invalid max hypervisor leaf on Xen")); | |||||
Not Done Inline ActionsShould we verify hv_high >= 0x40000003 first? markj: Should we verify `hv_high >= 0x40000003` first? | |||||
Done Inline ActionsIt's a non-optional leaf so not having it would mean something has gone very wrong. I had a KASSERT originally, but ended up removing it. I can add it. royger: It's a non-optional leaf so not having it would mean something has gone very wrong. I had a… | |||||
cpuid_count(0x40000003, 0, regs); | |||||
tsc_freq = (uint64_t)(regs[2]) * 1000; | |||||
tsc_early_calib_exact = 1; | |||||
} | |||||
/* | |||||
* Calculate TSC frequency using information from the CPUID leaf 0x15 'Time | * Calculate TSC frequency using information from the CPUID leaf 0x15 'Time | ||||
* Stamp Counter and Nominal Core Crystal Clock'. If leaf 0x15 is not | * Stamp Counter and Nominal Core Crystal Clock'. If leaf 0x15 is not | ||||
* functional, as it is on Skylake/Kabylake, try 0x16 'Processor Frequency | * functional, as it is on Skylake/Kabylake, try 0x16 'Processor Frequency | ||||
* Information'. Leaf 0x16 is described in the SDM as informational only, but | * Information'. Leaf 0x16 is described in the SDM as informational only, but | ||||
* we can use this value until late calibration is complete. | * we can use this value until late calibration is complete. | ||||
*/ | */ | ||||
static bool | static bool | ||||
tsc_freq_cpuid(uint64_t *res) | tsc_freq_cpuid(uint64_t *res) | ||||
▲ Show 20 Lines • Show All 193 Lines • ▼ Show 20 Lines | if (bootverbose) | ||||
printf( | printf( | ||||
"Early TSC frequency %juHz derived from hypervisor CPUID\n", | "Early TSC frequency %juHz derived from hypervisor CPUID\n", | ||||
(uintmax_t)tsc_freq); | (uintmax_t)tsc_freq); | ||||
} else if (vm_guest == VM_GUEST_VMWARE) { | } else if (vm_guest == VM_GUEST_VMWARE) { | ||||
tsc_freq_vmware(); | tsc_freq_vmware(); | ||||
if (bootverbose) | if (bootverbose) | ||||
printf( | printf( | ||||
"Early TSC frequency %juHz derived from VMWare hypercall\n", | "Early TSC frequency %juHz derived from VMWare hypercall\n", | ||||
(uintmax_t)tsc_freq); | |||||
} else if (vm_guest == VM_GUEST_XEN) { | |||||
tsc_freq_xen(); | |||||
if (bootverbose) | |||||
printf( | |||||
"Early TSC frequency %juHz derived from Xen CPUID\n", | |||||
(uintmax_t)tsc_freq); | (uintmax_t)tsc_freq); | ||||
} else if (tsc_freq_cpuid(&tsc_freq)) { | } else if (tsc_freq_cpuid(&tsc_freq)) { | ||||
/* | /* | ||||
* If possible, use the value obtained from CPUID as the initial | * If possible, use the value obtained from CPUID as the initial | ||||
* frequency. This will be refined later during boot but is | * frequency. This will be refined later during boot but is | ||||
* good enough for now. The 8254 PIT is not functional on some | * good enough for now. The 8254 PIT is not functional on some | ||||
* newer platforms anyway, so don't delay our boot for what | * newer platforms anyway, so don't delay our boot for what | ||||
* might be a garbage result. Late calibration is required if | * might be a garbage result. Late calibration is required if | ||||
▲ Show 20 Lines • Show All 610 Lines • Show Last 20 Lines |
Since this routine is using virtualized cpuid leaf to obtain a fequency value, why not simply inline it into tsc_freq_cpuid_vm() or call this routine from there?