Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/nvmm/x86 Improve the CPUID emulation on nvmm-intel: ...



details:   https://anonhg.NetBSD.org/src/rev/e4c02dd498a0
branches:  trunk
changeset: 933183:e4c02dd498a0
user:      maxv <maxv%NetBSD.org@localhost>
date:      Thu May 21 07:36:16 2020 +0000

description:
Improve the CPUID emulation on nvmm-intel: limit the highest basic and
hypervisor leaves.

diffstat:

 sys/dev/nvmm/x86/nvmm_x86_vmx.c |  55 +++++++++++++++++++++++++++++++++-------
 1 files changed, 45 insertions(+), 10 deletions(-)

diffs (110 lines):

diff -r 7a7d3a8036e5 -r e4c02dd498a0 sys/dev/nvmm/x86/nvmm_x86_vmx.c
--- a/sys/dev/nvmm/x86/nvmm_x86_vmx.c   Thu May 21 05:58:00 2020 +0000
+++ b/sys/dev/nvmm/x86/nvmm_x86_vmx.c   Thu May 21 07:36:16 2020 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: nvmm_x86_vmx.c,v 1.57 2020/05/10 06:24:16 maxv Exp $   */
+/*     $NetBSD: nvmm_x86_vmx.c,v 1.58 2020/05/21 07:36:16 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.57 2020/05/10 06:24:16 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: nvmm_x86_vmx.c,v 1.58 2020/05/21 07:36:16 maxv Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -1137,7 +1137,22 @@
        vmx_exit_invalid(exit, VMCS_EXITCODE_EXC_NMI);
 }
 
+#define VMX_CPUID_MAX_BASIC            0x16
 #define VMX_CPUID_MAX_HYPERVISOR       0x40000000
+#define VMX_CPUID_MAX_EXTENDED         0x80000008
+static uint32_t vmx_cpuid_max_basic __read_mostly;
+
+static void
+vmx_inkernel_exec_cpuid(struct vmx_cpudata *cpudata, uint64_t eax, uint64_t ecx)
+{
+       u_int descs[4];
+
+       x86_cpuid2(eax, ecx, descs);
+       cpudata->gprs[NVMM_X64_GPR_RAX] = descs[0];
+       cpudata->gprs[NVMM_X64_GPR_RBX] = descs[1];
+       cpudata->gprs[NVMM_X64_GPR_RCX] = descs[2];
+       cpudata->gprs[NVMM_X64_GPR_RDX] = descs[3];
+}
 
 static void
 vmx_inkernel_handle_cpuid(struct nvmm_machine *mach, struct nvmm_cpu *vcpu,
@@ -1147,7 +1162,22 @@
        unsigned int ncpus;
        uint64_t cr4;
 
+       if (eax < 0x40000000) {
+               if (__predict_false(eax > vmx_cpuid_max_basic)) {
+                       eax = vmx_cpuid_max_basic;
+                       vmx_inkernel_exec_cpuid(cpudata, eax, ecx);
+               }
+       } else if (eax < 0x80000000) {
+               if (__predict_false(eax > VMX_CPUID_MAX_HYPERVISOR)) {
+                       eax = vmx_cpuid_max_basic;
+                       vmx_inkernel_exec_cpuid(cpudata, eax, ecx);
+               }
+       }
+
        switch (eax) {
+       case 0x00000000:
+               cpudata->gprs[NVMM_X64_GPR_RAX] = vmx_cpuid_max_basic;
+               break;
        case 0x00000001:
                cpudata->gprs[NVMM_X64_GPR_RAX] &= nvmm_cpuid_00000001.eax;
 
@@ -1310,6 +1340,15 @@
                cpudata->gprs[NVMM_X64_GPR_RCX] &= nvmm_cpuid_80000001.ecx;
                cpudata->gprs[NVMM_X64_GPR_RDX] &= nvmm_cpuid_80000001.edx;
                break;
+       case 0x80000002: /* Processor Brand String */
+       case 0x80000003: /* Processor Brand String */
+       case 0x80000004: /* Processor Brand String */
+       case 0x80000005: /* Reserved Zero */
+       case 0x80000006: /* Cache Information */
+       case 0x80000007: /* TSC Information */
+       case 0x80000008: /* Address Sizes */
+               break;
+
        default:
                break;
        }
@@ -1333,18 +1372,11 @@
        struct vmx_cpudata *cpudata = vcpu->cpudata;
        struct nvmm_vcpu_conf_cpuid *cpuid;
        uint64_t eax, ecx;
-       u_int descs[4];
        size_t i;
 
        eax = cpudata->gprs[NVMM_X64_GPR_RAX];
        ecx = cpudata->gprs[NVMM_X64_GPR_RCX];
-       x86_cpuid2(eax, ecx, descs);
-
-       cpudata->gprs[NVMM_X64_GPR_RAX] = descs[0];
-       cpudata->gprs[NVMM_X64_GPR_RBX] = descs[1];
-       cpudata->gprs[NVMM_X64_GPR_RCX] = descs[2];
-       cpudata->gprs[NVMM_X64_GPR_RDX] = descs[3];
-
+       vmx_inkernel_exec_cpuid(cpudata, eax, ecx);
        vmx_inkernel_handle_cpuid(mach, vcpu, eax, ecx);
 
        for (i = 0; i < VMX_NCPUIDS; i++) {
@@ -3279,6 +3311,9 @@
        /* Init the XCR0 mask. */
        vmx_xcr0_mask = VMX_XCR0_MASK_DEFAULT & x86_xsave_features;
 
+       /* Init the max CPUID leaves. */
+       vmx_cpuid_max_basic = uimin(cpuid_level, VMX_CPUID_MAX_BASIC);
+
        /* 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) {



Home | Main Index | Thread Index | Old Index