Source-Changes-HG archive

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

[src/trunk]: src Add a new VCPU conf option, that allows userland to request ...



details:   https://anonhg.NetBSD.org/src/rev/050feb794f59
branches:  trunk
changeset: 460526:050feb794f59
user:      maxv <maxv%NetBSD.org@localhost>
date:      Sun Oct 27 10:28:55 2019 +0000

description:
Add a new VCPU conf option, that allows userland to request VMEXITs after a
TPR change. This is supported on all Intel CPUs, and not-too-old AMD CPUs.

The reason for wanting this option is that certain OSes (like Win10 64bit)
manage interrupt priority in hardware via CR8 directly, and for these OSes,
the emulator may want to sync its internal TPR state on each change.

Add two new fields in cap.arch, to report the conf capabilities. Report TPR
only on Intel for now, not AMD, because I don't have a recent AMD CPU on
which to test.

diffstat:

 lib/libnvmm/libnvmm.3           |   5 ++-
 sys/dev/nvmm/x86/nvmm_x86.h     |  19 ++++++++++--
 sys/dev/nvmm/x86/nvmm_x86_svm.c |  36 +++++++++++++++++-------
 sys/dev/nvmm/x86/nvmm_x86_vmx.c |  60 ++++++++++++++++++++++++++++++----------
 4 files changed, 89 insertions(+), 31 deletions(-)

diffs (truncated from 319 to 300 lines):

diff -r 50712e75202d -r 050feb794f59 lib/libnvmm/libnvmm.3
--- a/lib/libnvmm/libnvmm.3     Sun Oct 27 09:38:09 2019 +0000
+++ b/lib/libnvmm/libnvmm.3     Sun Oct 27 10:28:55 2019 +0000
@@ -1,4 +1,4 @@
-.\"    $NetBSD: libnvmm.3,v 1.21 2019/10/27 07:08:15 maxv Exp $
+.\"    $NetBSD: libnvmm.3,v 1.22 2019/10/27 10:28:55 maxv Exp $
 .\"
 .\" Copyright (c) 2018, 2019 The NetBSD Foundation, Inc.
 .\" All rights reserved.
@@ -27,7 +27,7 @@
 .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 .\" POSSIBILITY OF SUCH DAMAGE.
 .\"
-.Dd October 25, 2019
+.Dd October 27, 2019
 .Dt LIBNVMM 3
 .Os
 .Sh NAME
@@ -489,6 +489,7 @@
 #define NVMM_VCPU_EXIT_INT_READY       0x0000000000001001ULL
 #define NVMM_VCPU_EXIT_NMI_READY       0x0000000000001002ULL
 #define NVMM_VCPU_EXIT_HALTED          0x0000000000001003ULL
+#define NVMM_VCPU_EXIT_TPR_CHANGED     0x0000000000001004ULL
 /* x86: instructions. */
 #define NVMM_VCPU_EXIT_RDMSR           0x0000000000002000ULL
 #define NVMM_VCPU_EXIT_WRMSR           0x0000000000002001ULL
diff -r 50712e75202d -r 050feb794f59 sys/dev/nvmm/x86/nvmm_x86.h
--- a/sys/dev/nvmm/x86/nvmm_x86.h       Sun Oct 27 09:38:09 2019 +0000
+++ b/sys/dev/nvmm/x86/nvmm_x86.h       Sun Oct 27 10:28:55 2019 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: nvmm_x86.h,v 1.16 2019/10/23 07:01:11 maxv Exp $       */
+/*     $NetBSD: nvmm_x86.h,v 1.17 2019/10/27 10:28:55 maxv Exp $       */
 
 /*
  * Copyright (c) 2018-2019 The NetBSD Foundation, Inc.
@@ -84,6 +84,7 @@
 #define NVMM_VCPU_EXIT_INT_READY       0x0000000000001001ULL
 #define NVMM_VCPU_EXIT_NMI_READY       0x0000000000001002ULL
 #define NVMM_VCPU_EXIT_HALTED          0x0000000000001003ULL
+#define NVMM_VCPU_EXIT_TPR_CHANGED     0x0000000000001004ULL
 /* x86: instructions. */
 #define NVMM_VCPU_EXIT_RDMSR           0x0000000000002000ULL
 #define NVMM_VCPU_EXIT_WRMSR           0x0000000000002001ULL
@@ -118,10 +119,16 @@
 };
 
 struct nvmm_cap_md {
+       uint64_t mach_conf_support;
+
+       uint64_t vcpu_conf_support;
+#define NVMM_CAP_ARCH_VCPU_CONF_CPUID  __BIT(0)
+#define NVMM_CAP_ARCH_VCPU_CONF_TPR    __BIT(1)
+
        uint64_t xcr0_mask;
        uint32_t mxcsr_mask;
        uint32_t conf_cpuid_maxops;
-       uint64_t rsvd[6];
+       uint64_t rsvd[4];
 };
 
 #endif
@@ -261,6 +268,7 @@
 };
 
 #define NVMM_VCPU_CONF_CPUID   NVMM_VCPU_CONF_MD_BEGIN
+#define NVMM_VCPU_CONF_TPR     (NVMM_VCPU_CONF_MD_BEGIN + 1)
 
 struct nvmm_vcpu_conf_cpuid {
        /* The options. */
@@ -290,13 +298,18 @@
        } u;
 };
 
+struct nvmm_vcpu_conf_tpr {
+       uint32_t exit_changed:1;
+       uint32_t rsvd:31;
+};
+
 #define nvmm_vcpu_exit         nvmm_x86_exit
 #define nvmm_vcpu_event                nvmm_x86_event
 #define nvmm_vcpu_state                nvmm_x64_state
 
 #ifdef _KERNEL
 #define NVMM_X86_MACH_NCONF    0
-#define NVMM_X86_VCPU_NCONF    1
+#define NVMM_X86_VCPU_NCONF    2
 struct nvmm_x86_cpuid_mask {
        uint32_t eax;
        uint32_t ebx;
diff -r 50712e75202d -r 050feb794f59 sys/dev/nvmm/x86/nvmm_x86_svm.c
--- a/sys/dev/nvmm/x86/nvmm_x86_svm.c   Sun Oct 27 09:38:09 2019 +0000
+++ b/sys/dev/nvmm/x86/nvmm_x86_svm.c   Sun Oct 27 10:28:55 2019 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: nvmm_x86_svm.c,v 1.51 2019/10/23 07:01:11 maxv Exp $   */
+/*     $NetBSD: nvmm_x86_svm.c,v 1.52 2019/10/27 10:28:55 maxv Exp $   */
 
 /*
  * Copyright (c) 2018-2019 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: nvmm_x86_svm.c,v 1.51 2019/10/23 07:01:11 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: nvmm_x86_svm.c,v 1.52 2019/10/27 10:28:55 maxv Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -509,7 +509,9 @@
 
 static const size_t svm_vcpu_conf_sizes[NVMM_X86_VCPU_NCONF] = {
        [NVMM_VCPU_CONF_MD(NVMM_VCPU_CONF_CPUID)] =
-           sizeof(struct nvmm_vcpu_conf_cpuid)
+           sizeof(struct nvmm_vcpu_conf_cpuid),
+       [NVMM_VCPU_CONF_MD(NVMM_VCPU_CONF_TPR)] =
+           sizeof(struct nvmm_vcpu_conf_tpr)
 };
 
 struct svm_cpudata {
@@ -2128,18 +2130,14 @@
            roundup(sizeof(*cpudata), PAGE_SIZE), UVM_KMF_WIRED);
 }
 
+/* -------------------------------------------------------------------------- */
+
 static int
-svm_vcpu_configure(struct nvmm_cpu *vcpu, uint64_t op, void *data)
+svm_vcpu_configure_cpuid(struct svm_cpudata *cpudata, void *data)
 {
-       struct svm_cpudata *cpudata = vcpu->cpudata;
-       struct nvmm_vcpu_conf_cpuid *cpuid;
+       struct nvmm_vcpu_conf_cpuid *cpuid = data;
        size_t i;
 
-       if (__predict_false(op != NVMM_VCPU_CONF_MD(NVMM_VCPU_CONF_CPUID))) {
-               return EINVAL;
-       }
-       cpuid = data;
-
        if (__predict_false(cpuid->mask && cpuid->exit)) {
                return EINVAL;
        }
@@ -2189,6 +2187,19 @@
        return ENOBUFS;
 }
 
+static int
+svm_vcpu_configure(struct nvmm_cpu *vcpu, uint64_t op, void *data)
+{
+       struct svm_cpudata *cpudata = vcpu->cpudata;
+
+       switch (op) {
+       case NVMM_VCPU_CONF_MD(NVMM_VCPU_CONF_CPUID):
+               return svm_vcpu_configure_cpuid(cpudata, data);
+       default:
+               return EINVAL;
+       }
+}
+
 /* -------------------------------------------------------------------------- */
 
 static void
@@ -2387,6 +2398,9 @@
 static void
 svm_capability(struct nvmm_capability *cap)
 {
+       cap->arch.mach_conf_support = 0;
+       cap->arch.vcpu_conf_support =
+           NVMM_CAP_ARCH_VCPU_CONF_CPUID;
        cap->arch.xcr0_mask = svm_xcr0_mask;
        cap->arch.mxcsr_mask = x86_fpu_mxcsr_mask;
        cap->arch.conf_cpuid_maxops = SVM_NCPUIDS;
diff -r 50712e75202d -r 050feb794f59 sys/dev/nvmm/x86/nvmm_x86_vmx.c
--- a/sys/dev/nvmm/x86/nvmm_x86_vmx.c   Sun Oct 27 09:38:09 2019 +0000
+++ b/sys/dev/nvmm/x86/nvmm_x86_vmx.c   Sun Oct 27 10:28:55 2019 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: nvmm_x86_vmx.c,v 1.40 2019/10/23 07:01:11 maxv Exp $   */
+/*     $NetBSD: nvmm_x86_vmx.c,v 1.41 2019/10/27 10:28:55 maxv Exp $   */
 
 /*
  * Copyright (c) 2018-2019 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: nvmm_x86_vmx.c,v 1.40 2019/10/23 07:01:11 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: nvmm_x86_vmx.c,v 1.41 2019/10/27 10:28:55 maxv Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -702,7 +702,9 @@
 
 static const size_t vmx_vcpu_conf_sizes[NVMM_X86_VCPU_NCONF] = {
        [NVMM_VCPU_CONF_MD(NVMM_VCPU_CONF_CPUID)] =
-           sizeof(struct nvmm_vcpu_conf_cpuid)
+           sizeof(struct nvmm_vcpu_conf_cpuid),
+       [NVMM_VCPU_CONF_MD(NVMM_VCPU_CONF_TPR)] =
+           sizeof(struct nvmm_vcpu_conf_tpr)
 };
 
 struct vmx_cpudata {
@@ -752,6 +754,7 @@
        /* VCPU configuration. */
        bool cpuidpresent[VMX_NCPUIDS];
        struct nvmm_vcpu_conf_cpuid cpuid[VMX_NCPUIDS];
+       struct nvmm_vcpu_conf_tpr tpr;
 };
 
 static const struct {
@@ -1404,7 +1407,7 @@
 
 static int
 vmx_inkernel_handle_cr8(struct nvmm_machine *mach, struct nvmm_cpu *vcpu,
-    uint64_t qual)
+    uint64_t qual, struct nvmm_vcpu_exit *exit)
 {
        struct vmx_cpudata *cpudata = vcpu->cpudata;
        uint64_t type, gpr;
@@ -1428,6 +1431,9 @@
                } else {
                        cpudata->gcr8 = cpudata->gprs[gpr];
                }
+               if (cpudata->tpr.exit_changed) {
+                       exit->reason = NVMM_VCPU_EXIT_TPR_CHANGED;
+               }
        } else {
                if (gpr == NVMM_X64_GPR_RSP) {
                        vmx_vmwrite(VMCS_GUEST_RSP, cpudata->gcr8);
@@ -1447,6 +1453,8 @@
        uint64_t qual;
        int ret;
 
+       exit->reason = NVMM_VCPU_EXIT_NONE;
+
        qual = vmx_vmread(VMCS_EXIT_QUALIFICATION);
 
        switch (__SHIFTOUT(qual, VMX_QUAL_CR_NUM)) {
@@ -1457,7 +1465,7 @@
                ret = vmx_inkernel_handle_cr4(mach, vcpu, qual);
                break;
        case 8:
-               ret = vmx_inkernel_handle_cr8(mach, vcpu, qual);
+               ret = vmx_inkernel_handle_cr8(mach, vcpu, qual, exit);
                break;
        default:
                ret = -1;
@@ -1467,8 +1475,6 @@
        if (ret == -1) {
                vmx_inject_gp(vcpu);
        }
-
-       exit->reason = NVMM_VCPU_EXIT_NONE;
 }
 
 #define VMX_QUAL_IO_SIZE       __BITS(2,0)
@@ -2750,18 +2756,14 @@
            roundup(sizeof(*cpudata), PAGE_SIZE), UVM_KMF_WIRED);
 }
 
+/* -------------------------------------------------------------------------- */
+
 static int
-vmx_vcpu_configure(struct nvmm_cpu *vcpu, uint64_t op, void *data)
+vmx_vcpu_configure_cpuid(struct vmx_cpudata *cpudata, void *data)
 {
-       struct vmx_cpudata *cpudata = vcpu->cpudata;
-       struct nvmm_vcpu_conf_cpuid *cpuid;
+       struct nvmm_vcpu_conf_cpuid *cpuid = data;
        size_t i;
 
-       if (__predict_false(op != NVMM_VCPU_CONF_MD(NVMM_VCPU_CONF_CPUID))) {
-               return EINVAL;
-       }
-       cpuid = data;
-
        if (__predict_false(cpuid->mask && cpuid->exit)) {
                return EINVAL;
        }
@@ -2811,6 +2813,30 @@
        return ENOBUFS;
 }
 
+static int
+vmx_vcpu_configure_tpr(struct vmx_cpudata *cpudata, void *data)
+{
+       struct nvmm_vcpu_conf_tpr *tpr = data;
+
+       memcpy(&cpudata->tpr, tpr, sizeof(*tpr));
+       return 0;
+}
+
+static int
+vmx_vcpu_configure(struct nvmm_cpu *vcpu, uint64_t op, void *data)
+{
+       struct vmx_cpudata *cpudata = vcpu->cpudata;
+
+       switch (op) {
+       case NVMM_VCPU_CONF_MD(NVMM_VCPU_CONF_CPUID):
+               return vmx_vcpu_configure_cpuid(cpudata, data);
+       case NVMM_VCPU_CONF_MD(NVMM_VCPU_CONF_TPR):
+               return vmx_vcpu_configure_tpr(cpudata, data);



Home | Main Index | Thread Index | Old Index