HV: Add the emulation of CPUID with 0x16 leaf

The CPUID with 0x16 leaf can report the CPU hz and it is faster. And this
mechanism is widely used in Linux kernel.(native_calibrate_cpu).
As this is not supported on APL, currently sos adds the cpu_khz callback
in pv_cpu_ops to read the cpu frequency. This is quite hack.
(In fact HV leverages the cpuid with 0x40000010 leaf).
If it is emulated, the sos and guest os can use the cpuid to obtain the
corresponding cpu_khz. Then the cpu_khz in pv_cpu_ops can be removed.

V2: Simple the logic of adding unsupported cpuid level entry after the
CPUID 0x16 is emulated. Initialize the vcpuid_entry explicitly with zero
for the unsupported cpuid.

Signed-off-by: Zhao Yakui <yakui.zhao@intel.com>
Acked-by: Eddie Dong <eddie.dong@intel.com>
This commit is contained in:
Zhao Yakui 2018-08-14 10:41:21 +08:00 committed by lijinxia
parent e0eeb8a558
commit 7d83abb4a5

View File

@ -119,6 +119,21 @@ static void init_vcpuid_entry(__unused struct vm *vm,
entry->ecx = 0U;
entry->edx = 0U;
break;
case 0x16U:
if (boot_cpu_data.cpuid_level >= 0x16U) {
/* call the cpuid when 0x16 is supported */
cpuid_subleaf(leaf, subleaf,
&entry->eax, &entry->ebx,
&entry->ecx, &entry->edx);
} else {
/* Use the tsc to derive the emulated 0x16U cpuid. */
entry->eax = (uint32_t) (tsc_khz / 1000U);
entry->ebx = entry->eax;
/* Bus frequency: hard coded to 100M */
entry->ecx = 100U;
entry->edx = 0U;
}
break;
/*
* Leaf 0x40000000
@ -173,6 +188,11 @@ int set_vcpuid_entries(struct vm *vm)
uint32_t i, j;
init_vcpuid_entry(vm, 0U, 0U, 0U, &entry);
if (boot_cpu_data.cpuid_level < 0x16U) {
/* The cpuid with zero leaf returns the max level.
* Emulate that the 0x16U is supported */
entry.eax = 0x16U;
}
result = set_vcpuid_entry(vm, &entry);
if (result != 0) {
return result;