576fd8e4dfd9256afa153a79ccbacb8b78371ccd Implement CPUID leaf 0x40000010 in nvmm: VMware compatible TSC and LAPIC frequency detection diff --git a/sys/arch/x86/include/cpuvar.h b/sys/arch/x86/include/cpuvar.h index bdc617ee73f..78b75b7d421 100644 --- a/sys/arch/x86/include/cpuvar.h +++ b/sys/arch/x86/include/cpuvar.h @@ -124,6 +124,8 @@ void x86_cpu_idle_xen(void); void cpu_get_tsc_freq(struct cpu_info *); void pat_init(struct cpu_info *); +bool has_lapic(void); + extern int cpu_vendor; extern bool x86_mp_online; diff --git a/sys/arch/x86/x86/cpu.c b/sys/arch/x86/x86/cpu.c index c2072448206..4d8ae05a1d4 100644 --- a/sys/arch/x86/x86/cpu.c +++ b/sys/arch/x86/x86/cpu.c @@ -1490,6 +1490,16 @@ cpu_get_tsc_freq(struct cpu_info *ci) ci->ci_data.cpu_cc_freq = freq; } +bool +has_lapic(void) +{ +#if NLAPIC > 0 + return true; +#else + return false; +#endif +} + void x86_cpu_idle_mwait(void) { diff --git a/sys/dev/nvmm/x86/nvmm_x86_svm.c b/sys/dev/nvmm/x86/nvmm_x86_svm.c index 4b823d1c7ba..57e319cfba6 100644 --- a/sys/dev/nvmm/x86/nvmm_x86_svm.c +++ b/sys/dev/nvmm/x86/nvmm_x86_svm.c @@ -42,6 +42,7 @@ __KERNEL_RCSID(0, "$NetBSD: nvmm_x86_svm.c,v 1.86 2025/03/09 19:16:47 riastradh #include <uvm/uvm_extern.h> #include <uvm/uvm_page.h> +#include <x86/apicvar.h> #include <x86/cputypes.h> #include <x86/specialreg.h> #include <x86/dbregs.h> @@ -839,7 +840,7 @@ svm_inkernel_advance(struct vmcb *vmcb) } #define SVM_CPUID_MAX_BASIC 0xD -#define SVM_CPUID_MAX_HYPERVISOR 0x40000000 +#define SVM_CPUID_MAX_HYPERVISOR 0x40000010 #define SVM_CPUID_MAX_EXTENDED 0x8000001F static uint32_t svm_cpuid_max_basic __read_mostly; static uint32_t svm_cpuid_max_extended __read_mostly; @@ -1001,6 +1002,15 @@ svm_inkernel_handle_cpuid(struct nvmm_cpu *vcpu, uint64_t eax, uint64_t ecx) memcpy(&cpudata->gprs[NVMM_X64_GPR_RCX], "NVMM", 4); memcpy(&cpudata->gprs[NVMM_X64_GPR_RDX], " ___", 4); break; + case 0x40000010: /* VMware-style TSC and LAPIC freq */ + cpudata->gprs[NVMM_X64_GPR_RAX] = curcpu()->ci_data.cpu_cc_freq / 1000; + if (has_lapic()) + cpudata->gprs[NVMM_X64_GPR_RBX] = lapic_per_second / 1000; + else + cpudata->gprs[NVMM_X64_GPR_RBX] = 0; + cpudata->gprs[NVMM_X64_GPR_RCX] = 0; + cpudata->gprs[NVMM_X64_GPR_RDX] = 0; + break; /* * extended CPUID range diff --git a/sys/dev/nvmm/x86/nvmm_x86_vmx.c b/sys/dev/nvmm/x86/nvmm_x86_vmx.c index 74c879f0890..289e71094e2 100644 --- a/sys/dev/nvmm/x86/nvmm_x86_vmx.c +++ b/sys/dev/nvmm/x86/nvmm_x86_vmx.c @@ -43,6 +43,7 @@ __KERNEL_RCSID(0, "$NetBSD: nvmm_x86_vmx.c,v 1.87 2025/03/09 19:16:47 riastradh #include <uvm/uvm_extern.h> #include <uvm/uvm_page.h> +#include <x86/apicvar.h> #include <x86/cputypes.h> #include <x86/specialreg.h> #include <x86/dbregs.h> @@ -1220,7 +1221,7 @@ error: } #define VMX_CPUID_MAX_BASIC 0x16 -#define VMX_CPUID_MAX_HYPERVISOR 0x40000000 +#define VMX_CPUID_MAX_HYPERVISOR 0x40000010 #define VMX_CPUID_MAX_EXTENDED 0x80000008 static uint32_t vmx_cpuid_max_basic __read_mostly; static uint32_t vmx_cpuid_max_extended __read_mostly; @@ -1452,6 +1453,15 @@ vmx_inkernel_handle_cpuid(struct nvmm_machine *mach, struct nvmm_cpu *vcpu, memcpy(&cpudata->gprs[NVMM_X64_GPR_RCX], "NVMM", 4); memcpy(&cpudata->gprs[NVMM_X64_GPR_RDX], " ___", 4); break; + case 0x40000010: /* VMware-style TSC and LAPIC freq */ + cpudata->gprs[NVMM_X64_GPR_RAX] = curcpu()->ci_data.cpu_cc_freq / 1000; + if (has_lapic()) + cpudata->gprs[NVMM_X64_GPR_RBX] = lapic_per_second / 1000; + else + cpudata->gprs[NVMM_X64_GPR_RBX] = 0; + cpudata->gprs[NVMM_X64_GPR_RCX] = 0; + cpudata->gprs[NVMM_X64_GPR_RDX] = 0; + break; /* * extended CPUID range