Module Name: src
Committed By: maxv
Date: Thu Aug 20 11:09:56 UTC 2020
Modified Files:
src/sys/dev/nvmm/x86: nvmm_x86.c nvmm_x86.h nvmm_x86_svm.c
nvmm_x86_vmx.c
Log Message:
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.
To generate a diff of this commit:
cvs rdiff -u -r1.13 -r1.14 src/sys/dev/nvmm/x86/nvmm_x86.c
cvs rdiff -u -r1.18 -r1.19 src/sys/dev/nvmm/x86/nvmm_x86.h
cvs rdiff -u -r1.69 -r1.70 src/sys/dev/nvmm/x86/nvmm_x86_svm.c
cvs rdiff -u -r1.70 -r1.71 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.c
diff -u src/sys/dev/nvmm/x86/nvmm_x86.c:1.13 src/sys/dev/nvmm/x86/nvmm_x86.c:1.14
--- src/sys/dev/nvmm/x86/nvmm_x86.c:1.13 Thu Aug 20 11:07:43 2020
+++ src/sys/dev/nvmm/x86/nvmm_x86.c Thu Aug 20 11:09:56 2020
@@ -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_cp
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)
{
Index: src/sys/dev/nvmm/x86/nvmm_x86.h
diff -u src/sys/dev/nvmm/x86/nvmm_x86.h:1.18 src/sys/dev/nvmm/x86/nvmm_x86.h:1.19
--- src/sys/dev/nvmm/x86/nvmm_x86.h:1.18 Mon Oct 28 08:30:49 2019
+++ src/sys/dev/nvmm/x86/nvmm_x86.h Thu Aug 20 11:09:56 2020
@@ -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_
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
Index: src/sys/dev/nvmm/x86/nvmm_x86_svm.c
diff -u src/sys/dev/nvmm/x86/nvmm_x86_svm.c:1.69 src/sys/dev/nvmm/x86/nvmm_x86_svm.c:1.70
--- src/sys/dev/nvmm/x86/nvmm_x86_svm.c:1.69 Tue Aug 18 17:08:05 2020
+++ src/sys/dev/nvmm/x86/nvmm_x86_svm.c Thu Aug 20 11:09:56 2020
@@ -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_cp
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_cp
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);
Index: src/sys/dev/nvmm/x86/nvmm_x86_vmx.c
diff -u src/sys/dev/nvmm/x86/nvmm_x86_vmx.c:1.70 src/sys/dev/nvmm/x86/nvmm_x86_vmx.c:1.71
--- src/sys/dev/nvmm/x86/nvmm_x86_vmx.c:1.70 Tue Aug 18 17:03:10 2020
+++ src/sys/dev/nvmm/x86/nvmm_x86_vmx.c Thu Aug 20 11:09:56 2020
@@ -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_ma
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: