Source-Changes-HG archive

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

[src/trunk]: src/sys/dev/nvmm/x86 nvmm-x86: improve the handling of RFLAGS.RF



details:   https://anonhg.NetBSD.org/src/rev/65779a2d12e0
branches:  trunk
changeset: 937779:65779a2d12e0
user:      maxv <maxv%NetBSD.org@localhost>
date:      Wed Aug 26 16:32:02 2020 +0000

description:
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 |  40 ++++++++++++++++++++++++++++++++--------
 2 files changed, 57 insertions(+), 14 deletions(-)

diffs (183 lines):

diff -r b387f91ca180 -r 65779a2d12e0 sys/dev/nvmm/x86/nvmm_x86_svm.c
--- a/sys/dev/nvmm/x86/nvmm_x86_svm.c   Wed Aug 26 16:30:50 2020 +0000
+++ b/sys/dev/nvmm/x86/nvmm_x86_svm.c   Wed Aug 26 16:32:02 2020 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: nvmm_x86_svm.c,v 1.72 2020/08/26 16:29:19 maxv Exp $   */
+/*     $NetBSD: nvmm_x86_svm.c,v 1.73 2020/08/26 16:32:02 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.72 2020/08/26 16:29:19 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: nvmm_x86_svm.c,v 1.73 2020/08/26 16:32:02 maxv Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -676,8 +676,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 */
@@ -717,7 +731,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;
@@ -790,6 +807,7 @@
         * debugger.
         */
        vmcb->state.rip = vmcb->ctrl.nrip;
+       vmcb->state.rflags &= ~PSL_RF;
        vmcb->ctrl.intr &= ~VMCB_CTRL_INTR_SHADOW;
 }
 
@@ -1473,11 +1491,12 @@
        uint64_t machgen;
        int hcpu;
 
+       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 b387f91ca180 -r 65779a2d12e0 sys/dev/nvmm/x86/nvmm_x86_vmx.c
--- a/sys/dev/nvmm/x86/nvmm_x86_vmx.c   Wed Aug 26 16:30:50 2020 +0000
+++ b/sys/dev/nvmm/x86/nvmm_x86_vmx.c   Wed Aug 26 16:32:02 2020 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: nvmm_x86_vmx.c,v 1.73 2020/08/26 16:30:50 maxv Exp $   */
+/*     $NetBSD: nvmm_x86_vmx.c,v 1.74 2020/08/26 16:32:02 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.73 2020/08/26 16:30:50 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: nvmm_x86_vmx.c,v 1.74 2020/08/26 16:32:02 maxv Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -1038,8 +1038,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 */
@@ -1062,9 +1076,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;
@@ -1079,8 +1093,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;
@@ -1151,16 +1169,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));
@@ -2160,12 +2183,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();



Home | Main Index | Thread Index | Old Index