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:

Reply via email to