diff options
| author | maxv <maxv@NetBSD.org> | 2020-08-20 11:09:56 +0000 |
|---|---|---|
| committer | maxv <maxv@NetBSD.org> | 2020-08-20 11:09:56 +0000 |
| commit | 968df1ee379f5faf75cb699f77ffec71e239c5fa (patch) | |
| tree | 04d0431e342e87f250e2622f4cb596a7838feb6d /sys/dev/nvmm | |
| parent | 9839abd63f1cb517acf6e1eb9720d2f4703b6028 (diff) | |
nvmm-x86: improve the CPUID emulation
- x86-svm: explicitly handle 0x80000007 and 0x80000008. The latter
contains extended features we must filter out. Apply the same in
x86-vmx for symmetry.
- x86-svm: explicitly handle extended leaves until 0x8000001F, and
truncate to it.
Diffstat (limited to 'sys/dev/nvmm')
| -rw-r--r-- | sys/dev/nvmm/x86/nvmm_x86.c | 24 | ||||
| -rw-r--r-- | sys/dev/nvmm/x86/nvmm_x86.h | 6 | ||||
| -rw-r--r-- | sys/dev/nvmm/x86/nvmm_x86_svm.c | 77 | ||||
| -rw-r--r-- | sys/dev/nvmm/x86/nvmm_x86_vmx.c | 14 |
4 files changed, 113 insertions, 8 deletions
diff --git a/sys/dev/nvmm/x86/nvmm_x86.c b/sys/dev/nvmm/x86/nvmm_x86.c index 6d46601fed5..8cf740b06fd 100644 --- a/sys/dev/nvmm/x86/nvmm_x86.c +++ b/sys/dev/nvmm/x86/nvmm_x86.c @@ -1,4 +1,4 @@ -/* $NetBSD: nvmm_x86.c,v 1.13 2020/08/20 11:07:43 maxv Exp $ */ +/* $NetBSD: nvmm_x86.c,v 1.14 2020/08/20 11:09:56 maxv Exp $ */ /* * Copyright (c) 2018-2020 The NetBSD Foundation, Inc. @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: nvmm_x86.c,v 1.13 2020/08/20 11:07:43 maxv Exp $"); +__KERNEL_RCSID(0, "$NetBSD: nvmm_x86.c,v 1.14 2020/08/20 11:09:56 maxv Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -421,6 +421,26 @@ const struct nvmm_x86_cpuid_mask nvmm_cpuid_80000001 = { CPUID_3DNOW }; +const struct nvmm_x86_cpuid_mask nvmm_cpuid_80000007 = { + .eax = 0, + .ebx = 0, + .ecx = 0, + .edx = CPUID_APM_ITSC +}; + +const struct nvmm_x86_cpuid_mask nvmm_cpuid_80000008 = { + .eax = ~0, + .ebx = + CPUID_CAPEX_CLZERO | + /* CPUID_CAPEX_IRPERF excluded */ + CPUID_CAPEX_XSAVEERPTR | + /* CPUID_CAPEX_RDPRU excluded */ + /* CPUID_CAPEX_MCOMMIT excluded */ + CPUID_CAPEX_WBNOINVD, + .ecx = ~0, /* TODO? */ + .edx = 0 +}; + bool nvmm_x86_pat_validate(uint64_t val) { diff --git a/sys/dev/nvmm/x86/nvmm_x86.h b/sys/dev/nvmm/x86/nvmm_x86.h index 6b37e984d78..be6846b9d29 100644 --- a/sys/dev/nvmm/x86/nvmm_x86.h +++ b/sys/dev/nvmm/x86/nvmm_x86.h @@ -1,7 +1,7 @@ -/* $NetBSD: nvmm_x86.h,v 1.18 2019/10/28 08:30:49 maxv Exp $ */ +/* $NetBSD: nvmm_x86.h,v 1.19 2020/08/20 11:09:56 maxv Exp $ */ /* - * Copyright (c) 2018-2019 The NetBSD Foundation, Inc. + * Copyright (c) 2018-2020 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation @@ -320,6 +320,8 @@ extern const struct nvmm_x64_state nvmm_x86_reset_state; extern const struct nvmm_x86_cpuid_mask nvmm_cpuid_00000001; extern const struct nvmm_x86_cpuid_mask nvmm_cpuid_00000007; extern const struct nvmm_x86_cpuid_mask nvmm_cpuid_80000001; +extern const struct nvmm_x86_cpuid_mask nvmm_cpuid_80000007; +extern const struct nvmm_x86_cpuid_mask nvmm_cpuid_80000008; bool nvmm_x86_pat_validate(uint64_t); #endif diff --git a/sys/dev/nvmm/x86/nvmm_x86_svm.c b/sys/dev/nvmm/x86/nvmm_x86_svm.c index 518ad625508..82968d376e9 100644 --- a/sys/dev/nvmm/x86/nvmm_x86_svm.c +++ b/sys/dev/nvmm/x86/nvmm_x86_svm.c @@ -1,4 +1,4 @@ -/* $NetBSD: nvmm_x86_svm.c,v 1.69 2020/08/18 17:08:05 maxv Exp $ */ +/* $NetBSD: nvmm_x86_svm.c,v 1.70 2020/08/20 11:09:56 maxv Exp $ */ /* * Copyright (c) 2018-2020 The NetBSD Foundation, Inc. @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: nvmm_x86_svm.c,v 1.69 2020/08/18 17:08:05 maxv Exp $"); +__KERNEL_RCSID(0, "$NetBSD: nvmm_x86_svm.c,v 1.70 2020/08/20 11:09:56 maxv Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -795,7 +795,9 @@ svm_inkernel_advance(struct vmcb *vmcb) #define SVM_CPUID_MAX_BASIC 0xD #define SVM_CPUID_MAX_HYPERVISOR 0x40000000 +#define SVM_CPUID_MAX_EXTENDED 0x8000001F static uint32_t svm_cpuid_max_basic __read_mostly; +static uint32_t svm_cpuid_max_extended __read_mostly; static void svm_inkernel_exec_cpuid(struct svm_cpudata *cpudata, uint64_t eax, uint64_t ecx) @@ -825,6 +827,11 @@ svm_inkernel_handle_cpuid(struct nvmm_cpu *vcpu, uint64_t eax, uint64_t ecx) eax = svm_cpuid_max_basic; svm_inkernel_exec_cpuid(cpudata, eax, ecx); } + } else { + if (__predict_false(eax > svm_cpuid_max_extended)) { + eax = svm_cpuid_max_basic; + svm_inkernel_exec_cpuid(cpudata, eax, ecx); + } } switch (eax) { @@ -928,12 +935,74 @@ svm_inkernel_handle_cpuid(struct nvmm_cpu *vcpu, uint64_t eax, uint64_t ecx) memcpy(&cpudata->gprs[NVMM_X64_GPR_RDX], " ___", 4); break; + case 0x80000000: + cpudata->vmcb->state.rax = svm_cpuid_max_extended; + break; case 0x80000001: cpudata->vmcb->state.rax &= nvmm_cpuid_80000001.eax; cpudata->gprs[NVMM_X64_GPR_RBX] &= nvmm_cpuid_80000001.ebx; cpudata->gprs[NVMM_X64_GPR_RCX] &= nvmm_cpuid_80000001.ecx; cpudata->gprs[NVMM_X64_GPR_RDX] &= nvmm_cpuid_80000001.edx; break; + case 0x80000002: /* Extended Processor Name String */ + case 0x80000003: /* Extended Processor Name String */ + case 0x80000004: /* Extended Processor Name String */ + case 0x80000005: /* L1 Cache and TLB Information */ + case 0x80000006: /* L2 Cache and TLB and L3 Cache Information */ + break; + case 0x80000007: /* Processor Power Management and RAS Capabilities */ + cpudata->vmcb->state.rax &= nvmm_cpuid_80000007.eax; + cpudata->gprs[NVMM_X64_GPR_RBX] &= nvmm_cpuid_80000007.ebx; + cpudata->gprs[NVMM_X64_GPR_RCX] &= nvmm_cpuid_80000007.ecx; + cpudata->gprs[NVMM_X64_GPR_RDX] &= nvmm_cpuid_80000007.edx; + break; + case 0x80000008: /* Processor Capacity Parameters and Ext Feat Ident */ + cpudata->vmcb->state.rax &= nvmm_cpuid_80000008.eax; + cpudata->gprs[NVMM_X64_GPR_RBX] &= nvmm_cpuid_80000008.ebx; + cpudata->gprs[NVMM_X64_GPR_RCX] &= nvmm_cpuid_80000008.ecx; + cpudata->gprs[NVMM_X64_GPR_RDX] &= nvmm_cpuid_80000008.edx; + break; + case 0x80000009: /* Empty */ + case 0x8000000A: /* SVM Features */ + case 0x8000000B: /* Empty */ + case 0x8000000C: /* Empty */ + case 0x8000000D: /* Empty */ + case 0x8000000E: /* Empty */ + case 0x8000000F: /* Empty */ + case 0x80000010: /* Empty */ + case 0x80000011: /* Empty */ + case 0x80000012: /* Empty */ + case 0x80000013: /* Empty */ + case 0x80000014: /* Empty */ + case 0x80000015: /* Empty */ + case 0x80000016: /* Empty */ + case 0x80000017: /* Empty */ + case 0x80000018: /* Empty */ + cpudata->vmcb->state.rax = 0; + cpudata->gprs[NVMM_X64_GPR_RBX] = 0; + cpudata->gprs[NVMM_X64_GPR_RCX] = 0; + cpudata->gprs[NVMM_X64_GPR_RDX] = 0; + break; + case 0x80000019: /* TLB Characteristics for 1GB pages */ + case 0x8000001A: /* Instruction Optimizations */ + break; + case 0x8000001B: /* Instruction-Based Sampling Capabilities */ + case 0x8000001C: /* Lightweight Profiling Capabilities */ + cpudata->vmcb->state.rax = 0; + cpudata->gprs[NVMM_X64_GPR_RBX] = 0; + cpudata->gprs[NVMM_X64_GPR_RCX] = 0; + cpudata->gprs[NVMM_X64_GPR_RDX] = 0; + break; + case 0x8000001D: /* Cache Topology Information */ + case 0x8000001E: /* Processor Topology Information */ + break; /* TODO? */ + case 0x8000001F: /* Encrypted Memory Capabilities */ + cpudata->vmcb->state.rax = 0; + cpudata->gprs[NVMM_X64_GPR_RBX] = 0; + cpudata->gprs[NVMM_X64_GPR_RCX] = 0; + cpudata->gprs[NVMM_X64_GPR_RDX] = 0; + break; + default: break; } @@ -2460,6 +2529,10 @@ svm_init(void) /* Init the max basic CPUID leaf. */ svm_cpuid_max_basic = uimin(cpuid_level, SVM_CPUID_MAX_BASIC); + /* Init the max extended CPUID leaf. */ + x86_cpuid(0x80000000, descs); + svm_cpuid_max_extended = uimin(descs[0], SVM_CPUID_MAX_EXTENDED); + memset(hsave, 0, sizeof(hsave)); for (CPU_INFO_FOREACH(cii, ci)) { pg = uvm_pagealloc(NULL, 0, NULL, UVM_PGA_ZERO); diff --git a/sys/dev/nvmm/x86/nvmm_x86_vmx.c b/sys/dev/nvmm/x86/nvmm_x86_vmx.c index dd17479fd29..8b2323127d9 100644 --- a/sys/dev/nvmm/x86/nvmm_x86_vmx.c +++ b/sys/dev/nvmm/x86/nvmm_x86_vmx.c @@ -1,4 +1,4 @@ -/* $NetBSD: nvmm_x86_vmx.c,v 1.70 2020/08/18 17:03:10 maxv Exp $ */ +/* $NetBSD: nvmm_x86_vmx.c,v 1.71 2020/08/20 11:09:56 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.70 2020/08/18 17:03:10 maxv Exp $"); +__KERNEL_RCSID(0, "$NetBSD: nvmm_x86_vmx.c,v 1.71 2020/08/20 11:09:56 maxv Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -1395,8 +1395,18 @@ vmx_inkernel_handle_cpuid(struct nvmm_machine *mach, struct nvmm_cpu *vcpu, case 0x80000004: /* Processor Brand String */ case 0x80000005: /* Reserved Zero */ case 0x80000006: /* Cache Information */ + break; case 0x80000007: /* TSC Information */ + cpudata->gprs[NVMM_X64_GPR_RAX] &= nvmm_cpuid_80000007.eax; + cpudata->gprs[NVMM_X64_GPR_RBX] &= nvmm_cpuid_80000007.ebx; + cpudata->gprs[NVMM_X64_GPR_RCX] &= nvmm_cpuid_80000007.ecx; + cpudata->gprs[NVMM_X64_GPR_RDX] &= nvmm_cpuid_80000007.edx; + break; case 0x80000008: /* Address Sizes */ + cpudata->gprs[NVMM_X64_GPR_RAX] &= nvmm_cpuid_80000008.eax; + cpudata->gprs[NVMM_X64_GPR_RBX] &= nvmm_cpuid_80000008.ebx; + cpudata->gprs[NVMM_X64_GPR_RCX] &= nvmm_cpuid_80000008.ecx; + cpudata->gprs[NVMM_X64_GPR_RDX] &= nvmm_cpuid_80000008.edx; break; default: |
