Module Name: src Committed By: maxv Date: Tue Aug 11 15:31:52 UTC 2020
Modified Files: src/sys/dev/nvmm/x86: nvmm_x86_vmx.c Log Message: Improve the CPUID emulation on nvmm-intel: - Limit the highest extended leaf. - Limit 0x00000007 to ECX=0, for future-proofness. To generate a diff of this commit: cvs rdiff -u -r1.68 -r1.69 src/sys/dev/nvmm/x86/nvmm_x86_vmx.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/dev/nvmm/x86/nvmm_x86_vmx.c diff -u src/sys/dev/nvmm/x86/nvmm_x86_vmx.c:1.68 src/sys/dev/nvmm/x86/nvmm_x86_vmx.c:1.69 --- src/sys/dev/nvmm/x86/nvmm_x86_vmx.c:1.68 Tue Aug 11 15:27:46 2020 +++ src/sys/dev/nvmm/x86/nvmm_x86_vmx.c Tue Aug 11 15:31:51 2020 @@ -1,4 +1,4 @@ -/* $NetBSD: nvmm_x86_vmx.c,v 1.68 2020/08/11 15:27:46 maxv Exp $ */ +/* $NetBSD: nvmm_x86_vmx.c,v 1.69 2020/08/11 15:31:51 maxv Exp $ */ /* * Copyright (c) 2018-2020 The NetBSD Foundation, Inc. @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: nvmm_x86_vmx.c,v 1.68 2020/08/11 15:27:46 maxv Exp $"); +__KERNEL_RCSID(0, "$NetBSD: nvmm_x86_vmx.c,v 1.69 2020/08/11 15:31:51 maxv Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -1172,6 +1172,7 @@ error: #define VMX_CPUID_MAX_HYPERVISOR 0x40000000 #define VMX_CPUID_MAX_EXTENDED 0x80000008 static uint32_t vmx_cpuid_max_basic __read_mostly; +static uint32_t vmx_cpuid_max_extended __read_mostly; static void vmx_inkernel_exec_cpuid(struct vmx_cpudata *cpudata, uint64_t eax, uint64_t ecx) @@ -1203,6 +1204,11 @@ vmx_inkernel_handle_cpuid(struct nvmm_ma eax = vmx_cpuid_max_basic; vmx_inkernel_exec_cpuid(cpudata, eax, ecx); } + } else { + if (__predict_false(eax > vmx_cpuid_max_extended)) { + eax = vmx_cpuid_max_basic; + vmx_inkernel_exec_cpuid(cpudata, eax, ecx); + } } switch (eax) { @@ -1248,12 +1254,22 @@ vmx_inkernel_handle_cpuid(struct nvmm_ma cpudata->gprs[NVMM_X64_GPR_RDX] = 0; break; case 0x00000007: /* Structured Extended Feature Flags Enumeration */ - cpudata->gprs[NVMM_X64_GPR_RAX] &= nvmm_cpuid_00000007.eax; - cpudata->gprs[NVMM_X64_GPR_RBX] &= nvmm_cpuid_00000007.ebx; - cpudata->gprs[NVMM_X64_GPR_RCX] &= nvmm_cpuid_00000007.ecx; - cpudata->gprs[NVMM_X64_GPR_RDX] &= nvmm_cpuid_00000007.edx; - if (vmx_procbased_ctls2 & PROC_CTLS2_INVPCID_ENABLE) { - cpudata->gprs[NVMM_X64_GPR_RBX] |= CPUID_SEF_INVPCID; + switch (ecx) { + case 0: + cpudata->gprs[NVMM_X64_GPR_RAX] = 0; + cpudata->gprs[NVMM_X64_GPR_RBX] &= nvmm_cpuid_00000007.ebx; + cpudata->gprs[NVMM_X64_GPR_RCX] &= nvmm_cpuid_00000007.ecx; + cpudata->gprs[NVMM_X64_GPR_RDX] &= nvmm_cpuid_00000007.edx; + if (vmx_procbased_ctls2 & PROC_CTLS2_INVPCID_ENABLE) { + cpudata->gprs[NVMM_X64_GPR_RBX] |= CPUID_SEF_INVPCID; + } + break; + default: + cpudata->gprs[NVMM_X64_GPR_RAX] = 0; + cpudata->gprs[NVMM_X64_GPR_RBX] = 0; + cpudata->gprs[NVMM_X64_GPR_RCX] = 0; + cpudata->gprs[NVMM_X64_GPR_RDX] = 0; + break; } break; case 0x00000008: /* Empty */ @@ -1365,6 +1381,9 @@ vmx_inkernel_handle_cpuid(struct nvmm_ma memcpy(&cpudata->gprs[NVMM_X64_GPR_RDX], " ___", 4); break; + case 0x80000000: + cpudata->gprs[NVMM_X64_GPR_RAX] = vmx_cpuid_max_extended; + break; case 0x80000001: cpudata->gprs[NVMM_X64_GPR_RAX] &= nvmm_cpuid_80000001.eax; cpudata->gprs[NVMM_X64_GPR_RBX] &= nvmm_cpuid_80000001.ebx; @@ -3346,6 +3365,7 @@ vmx_init(void) uint64_t xc, msr; struct vmxon *vmxon; uint32_t revision; + u_int descs[4]; paddr_t pa; vaddr_t va; int error; @@ -3356,9 +3376,13 @@ vmx_init(void) /* Init the XCR0 mask. */ vmx_xcr0_mask = VMX_XCR0_MASK_DEFAULT & x86_xsave_features; - /* Init the max CPUID leaves. */ + /* Init the max basic CPUID leaf. */ vmx_cpuid_max_basic = uimin(cpuid_level, VMX_CPUID_MAX_BASIC); + /* Init the max extended CPUID leaf. */ + x86_cpuid(0x80000000, descs); + vmx_cpuid_max_extended = uimin(descs[0], VMX_CPUID_MAX_EXTENDED); + /* Init the TLB flush op, the EPT flush op and the EPTP type. */ msr = rdmsr(MSR_IA32_VMX_EPT_VPID_CAP); if ((msr & IA32_VMX_EPT_VPID_INVVPID_CONTEXT) != 0) {