Source-Changes-HG archive

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

[src/netbsd-9]: src/sys/dev/nvmm/x86 Pull up following revision(s) (requested...



details:   https://anonhg.NetBSD.org/src/rev/c9b6e5f83fab
branches:  netbsd-9
changeset: 938691:c9b6e5f83fab
user:      martin <martin%NetBSD.org@localhost>
date:      Sun Sep 13 11:56:44 2020 +0000

description:
Pull up following revision(s) (requested by maxv in ticket #1078):

        sys/dev/nvmm/x86/nvmm_x86_svm.c: revision 1.73
        sys/dev/nvmm/x86/nvmm_x86_vmx.c: revision 1.73
        sys/dev/nvmm/x86/nvmm_x86_vmx.c: revision 1.74

nvmm-x86-vmx: improve the handling of CR4
 - Filter out certain features we don't want the guest to enable. This is
   for general correctness, and future-proofness.
 - Flush the guest TLB when certain flags change.

nvmm-x86: improve the handling of RFLAGS.RF
 - When injecting certain exceptions, set RF. For us to have an up-to-date
   view of RFLAGS, we commit the state before the event.
 - When advancing RIP, clear RF.

diffstat:

 sys/dev/nvmm/x86/nvmm_x86_svm.c |  31 ++++++++++++---
 sys/dev/nvmm/x86/nvmm_x86_vmx.c |  82 +++++++++++++++++++++++++++++++++++------
 2 files changed, 95 insertions(+), 18 deletions(-)

diffs (258 lines):

diff -r 7f0cfd9834fb -r c9b6e5f83fab sys/dev/nvmm/x86/nvmm_x86_svm.c
--- a/sys/dev/nvmm/x86/nvmm_x86_svm.c   Sun Sep 13 11:54:10 2020 +0000
+++ b/sys/dev/nvmm/x86/nvmm_x86_svm.c   Sun Sep 13 11:56:44 2020 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: nvmm_x86_svm.c,v 1.46.4.12 2020/09/13 11:54:10 martin Exp $    */
+/*     $NetBSD: nvmm_x86_svm.c,v 1.46.4.13 2020/09/13 11:56:44 martin 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.46.4.12 2020/09/13 11:54:10 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: nvmm_x86_svm.c,v 1.46.4.13 2020/09/13 11:56:44 martin Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -666,8 +666,22 @@
        svm_vmcb_cache_flush(vmcb, VMCB_CTRL_VMCB_CLEAN_I);
 }
 
+static inline bool
+svm_excp_has_rf(uint8_t vector)
+{
+       switch (vector) {
+       case 1:         /* #DB */
+       case 4:         /* #OF */
+       case 8:         /* #DF */
+       case 18:        /* #MC */
+               return false;
+       default:
+               return true;
+       }
+}
+
 static inline int
-svm_event_has_error(uint8_t vector)
+svm_excp_has_error(uint8_t vector)
 {
        switch (vector) {
        case 8:         /* #DF */
@@ -707,7 +721,10 @@
                        return EINVAL;
                if (vector == 3 || vector == 0)
                        return EINVAL;
-               err = svm_event_has_error(vector);
+               if (svm_excp_has_rf(vector)) {
+                       vmcb->state.rflags |= PSL_RF;
+               }
+               err = svm_excp_has_error(vector);
                break;
        case NVMM_VCPU_EVENT_INTR:
                type = SVM_EVENT_TYPE_HW_INT;
@@ -780,6 +797,7 @@
         * debugger.
         */
        vmcb->state.rip = vmcb->ctrl.nrip;
+       vmcb->state.rflags &= ~PSL_RF;
        vmcb->ctrl.intr &= ~VMCB_CTRL_INTR_SHADOW;
 }
 
@@ -1472,11 +1490,12 @@
        uint64_t machgen;
        int hcpu, s;
 
+       svm_vcpu_state_commit(vcpu);
+       comm->state_cached = 0;
+
        if (__predict_false(svm_vcpu_event_commit(vcpu) != 0)) {
                return EINVAL;
        }
-       svm_vcpu_state_commit(vcpu);
-       comm->state_cached = 0;
 
        kpreempt_disable();
        hcpu = cpu_number();
diff -r 7f0cfd9834fb -r c9b6e5f83fab sys/dev/nvmm/x86/nvmm_x86_vmx.c
--- a/sys/dev/nvmm/x86/nvmm_x86_vmx.c   Sun Sep 13 11:54:10 2020 +0000
+++ b/sys/dev/nvmm/x86/nvmm_x86_vmx.c   Sun Sep 13 11:56:44 2020 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: nvmm_x86_vmx.c,v 1.36.2.14 2020/09/13 11:54:10 martin Exp $    */
+/*     $NetBSD: nvmm_x86_vmx.c,v 1.36.2.15 2020/09/13 11:56:44 martin 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.36.2.14 2020/09/13 11:54:10 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: nvmm_x86_vmx.c,v 1.36.2.15 2020/09/13 11:56:44 martin Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -717,6 +717,33 @@
 #define MSRBM_NPAGES   1
 #define MSRBM_SIZE     (MSRBM_NPAGES * PAGE_SIZE)
 
+#define CR4_VALID \
+       (CR4_VME |                      \
+        CR4_PVI |                      \
+        CR4_TSD |                      \
+        CR4_DE |                       \
+        CR4_PSE |                      \
+        CR4_PAE |                      \
+        CR4_MCE |                      \
+        CR4_PGE |                      \
+        CR4_PCE |                      \
+        CR4_OSFXSR |                   \
+        CR4_OSXMMEXCPT |               \
+        CR4_UMIP |                     \
+        /* CR4_LA57 excluded */        \
+        /* CR4_VMXE excluded */        \
+        /* CR4_SMXE excluded */        \
+        CR4_FSGSBASE |                 \
+        CR4_PCIDE |                    \
+        CR4_OSXSAVE |                  \
+        CR4_SMEP |                     \
+        CR4_SMAP                       \
+        /* CR4_PKE excluded */         \
+        /* CR4_CET excluded */         \
+        /* CR4_PKS excluded */)
+#define CR4_INVALID \
+       (0xFFFFFFFFFFFFFFFFULL & ~CR4_VALID)
+
 #define EFER_TLB_FLUSH \
        (EFER_NXE|EFER_LMA|EFER_LME)
 #define CR0_TLB_FLUSH \
@@ -1001,8 +1028,22 @@
        vmx_vmwrite(VMCS_PROCBASED_CTLS, ctls1);
 }
 
+static inline bool
+vmx_excp_has_rf(uint8_t vector)
+{
+       switch (vector) {
+       case 1:         /* #DB */
+       case 4:         /* #OF */
+       case 8:         /* #DF */
+       case 18:        /* #MC */
+               return false;
+       default:
+               return true;
+       }
+}
+
 static inline int
-vmx_event_has_error(uint8_t vector)
+vmx_excp_has_error(uint8_t vector)
 {
        switch (vector) {
        case 8:         /* #DF */
@@ -1025,9 +1066,9 @@
        struct nvmm_comm_page *comm = vcpu->comm;
        struct vmx_cpudata *cpudata = vcpu->cpudata;
        int type = 0, err = 0, ret = EINVAL;
+       uint64_t rflags, info, error;
        u_int evtype;
        uint8_t vector;
-       uint64_t info, error;
 
        evtype = comm->event.type;
        vector = comm->event.vector;
@@ -1042,8 +1083,12 @@
                        goto out;
                if (vector == 3 || vector == 0)
                        goto out;
+               if (vmx_excp_has_rf(vector)) {
+                       rflags = vmx_vmread(VMCS_GUEST_RFLAGS);
+                       vmx_vmwrite(VMCS_GUEST_RFLAGS, rflags | PSL_RF);
+               }
                type = INTR_TYPE_HW_EXC;
-               err = vmx_event_has_error(vector);
+               err = vmx_excp_has_error(vector);
                break;
        case NVMM_VCPU_EVENT_INTR:
                type = INTR_TYPE_EXT_INT;
@@ -1114,16 +1159,21 @@
 static inline void
 vmx_inkernel_advance(void)
 {
-       uint64_t rip, inslen, intstate;
+       uint64_t rip, inslen, intstate, rflags;
 
        /*
         * Maybe we should also apply single-stepping and debug exceptions.
         * Matters for guest-ring3, because it can execute 'cpuid' under a
         * debugger.
         */
+
        inslen = vmx_vmread(VMCS_EXIT_INSTRUCTION_LENGTH);
        rip = vmx_vmread(VMCS_GUEST_RIP);
        vmx_vmwrite(VMCS_GUEST_RIP, rip + inslen);
+
+       rflags = vmx_vmread(VMCS_GUEST_RFLAGS);
+       vmx_vmwrite(VMCS_GUEST_RFLAGS, rflags & ~PSL_RF);
+
        intstate = vmx_vmread(VMCS_GUEST_INTERRUPTIBILITY);
        vmx_vmwrite(VMCS_GUEST_INTERRUPTIBILITY,
            intstate & ~(INT_STATE_STI|INT_STATE_MOVSS));
@@ -1579,12 +1629,18 @@
                gpr = cpudata->gprs[gpr];
        }
 
+       if (gpr & CR4_INVALID) {
+               return -1;
+       }
        cr4 = gpr | CR4_VMXE;
-
        if (vmx_check_cr(cr4, vmx_cr4_fixed0, vmx_cr4_fixed1) == -1) {
                return -1;
        }
 
+       if ((vmx_vmread(VMCS_GUEST_CR4) ^ cr4) & CR4_TLB_FLUSH) {
+               cpudata->gtlb_want_flush = true;
+       }
+
        vmx_vmwrite(VMCS_GUEST_CR4, cr4);
        vmx_inkernel_advance();
        return 0;
@@ -2119,12 +2175,13 @@
 
        vmx_vmcs_enter(vcpu);
 
+       vmx_vcpu_state_commit(vcpu);
+       comm->state_cached = 0;
+
        if (__predict_false(vmx_vcpu_event_commit(vcpu) != 0)) {
                vmx_vmcs_leave(vcpu);
                return EINVAL;
        }
-       vmx_vcpu_state_commit(vcpu);
-       comm->state_cached = 0;
 
        ci = curcpu();
        hcpu = cpu_number();
@@ -2506,7 +2563,7 @@
                cpudata->gcr2 = state->crs[NVMM_X64_CR_CR2];
                vmx_vmwrite(VMCS_GUEST_CR3, state->crs[NVMM_X64_CR_CR3]); // XXX PDPTE?
                vmx_vmwrite(VMCS_GUEST_CR4,
-                   state->crs[NVMM_X64_CR_CR4] | CR4_VMXE);
+                   (state->crs[NVMM_X64_CR_CR4] & CR4_VALID) | CR4_VMXE);
                cpudata->gcr8 = state->crs[NVMM_X64_CR_CR8];
 
                if (vmx_xcr0_mask != 0) {
@@ -2831,8 +2888,9 @@
        vmx_vmwrite(VMCS_CR0_MASK, CR0_NW|CR0_CD|CR0_ET);
        vmx_vmwrite(VMCS_CR0_SHADOW, CR0_ET);
 
-       /* Force CR4_VMXE to zero. */
-       vmx_vmwrite(VMCS_CR4_MASK, CR4_VMXE);
+       /* Force unsupported CR4 fields to zero. */
+       vmx_vmwrite(VMCS_CR4_MASK, CR4_INVALID);
+       vmx_vmwrite(VMCS_CR4_SHADOW, 0);
 
        /* Set the Host state for resuming. */
        vmx_vmwrite(VMCS_HOST_RIP, (uint64_t)&vmx_resume_rip);



Home | Main Index | Thread Index | Old Index