Source-Changes-HG archive

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

[src/trunk]: src/sys/dev/nvmm Optimize: change the behavior of the HLT vmexit...



details:   https://anonhg.NetBSD.org/src/rev/3f62d83cf5fe
branches:  trunk
changeset: 447806:3f62d83cf5fe
user:      maxv <maxv%NetBSD.org@localhost>
date:      Thu Jan 24 13:05:59 2019 +0000

description:
Optimize: change the behavior of the HLT vmexit, make it a "change in vcpu
state" which occurs after the instruction executed, rather than an
instruction intercept which occurs before. Disable the shadow and the intr
window in kernel mode, and advance the RIP, so that the virtualizer doesn't
have to do it itself. This saves two syscalls and one VMCB cache flush.

Provide npc for other instruction intercepts, in case someone is
interested.

diffstat:

 sys/dev/nvmm/nvmm.h             |  16 +++++-----
 sys/dev/nvmm/x86/nvmm_x86_svm.c |  63 ++++++++++++++++++++++------------------
 2 files changed, 42 insertions(+), 37 deletions(-)

diffs (184 lines):

diff -r 3c06c121c1ff -r 3f62d83cf5fe sys/dev/nvmm/nvmm.h
--- a/sys/dev/nvmm/nvmm.h       Thu Jan 24 09:33:03 2019 +0000
+++ b/sys/dev/nvmm/nvmm.h       Thu Jan 24 13:05:59 2019 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: nvmm.h,v 1.2 2019/01/06 16:10:51 maxv Exp $    */
+/*     $NetBSD: nvmm.h,v 1.3 2019/01/24 13:05:59 maxv Exp $    */
 
 /*
  * Copyright (c) 2018 The NetBSD Foundation, Inc.
@@ -53,13 +53,13 @@
        NVMM_EXIT_MSR           = 0x0000000000000003,
        NVMM_EXIT_INT_READY     = 0x0000000000000004,
        NVMM_EXIT_NMI_READY     = 0x0000000000000005,
-       NVMM_EXIT_SHUTDOWN      = 0x0000000000000006,
+       NVMM_EXIT_HALTED        = 0x0000000000000006,
+       NVMM_EXIT_SHUTDOWN      = 0x0000000000000007,
 
        /* Instructions (x86). */
-       NVMM_EXIT_HLT           = 0x0000000000001000,
-       NVMM_EXIT_MONITOR       = 0x0000000000001001,
-       NVMM_EXIT_MWAIT         = 0x0000000000001002,
-       NVMM_EXIT_MWAIT_COND    = 0x0000000000001003,
+       NVMM_EXIT_MONITOR       = 0x0000000000001000,
+       NVMM_EXIT_MWAIT         = 0x0000000000001001,
+       NVMM_EXIT_MWAIT_COND    = 0x0000000000001002,
 
        NVMM_EXIT_INVALID       = 0xFFFFFFFFFFFFFFFF
 };
@@ -106,7 +106,7 @@
        uint64_t npc;
 };
 
-struct nvmm_exit_hlt {
+struct nvmm_exit_insn {
        uint64_t npc;
 };
 
@@ -116,7 +116,7 @@
                struct nvmm_exit_memory mem;
                struct nvmm_exit_io io;
                struct nvmm_exit_msr msr;
-               struct nvmm_exit_hlt hlt;
+               struct nvmm_exit_insn insn;
        } u;
        uint64_t exitstate[8];
 };
diff -r 3c06c121c1ff -r 3f62d83cf5fe sys/dev/nvmm/x86/nvmm_x86_svm.c
--- a/sys/dev/nvmm/x86/nvmm_x86_svm.c   Thu Jan 24 09:33:03 2019 +0000
+++ b/sys/dev/nvmm/x86/nvmm_x86_svm.c   Thu Jan 24 13:05:59 2019 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: nvmm_x86_svm.c,v 1.16 2019/01/20 16:55:21 maxv Exp $   */
+/*     $NetBSD: nvmm_x86_svm.c,v 1.17 2019/01/24 13:05:59 maxv Exp $   */
 
 /*
  * Copyright (c) 2018 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: nvmm_x86_svm.c,v 1.16 2019/01/20 16:55:21 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: nvmm_x86_svm.c,v 1.17 2019/01/24 13:05:59 maxv Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -726,20 +726,6 @@
 }
 
 static void
-svm_inject_db(struct nvmm_machine *mach, struct nvmm_cpu *vcpu)
-{
-       struct nvmm_event event;
-       int ret __diagused;
-
-       event.type = NVMM_EVENT_EXCEPTION;
-       event.vector = 1;
-       event.u.error = 0;
-
-       ret = svm_vcpu_inject(mach, vcpu, &event);
-       KASSERT(ret == 0);
-}
-
-static void
 svm_inject_gp(struct nvmm_machine *mach, struct nvmm_cpu *vcpu)
 {
        struct nvmm_event event;
@@ -753,6 +739,18 @@
        KASSERT(ret == 0);
 }
 
+static inline void
+svm_inkernel_advance(struct vmcb *vmcb)
+{
+       /*
+        * Maybe we should also apply single-stepping and debug exceptions.
+        * Matters for guest-ring3, because it can execute 'cpuid' under a
+        * debugger.
+        */
+       vmcb->state.rip = vmcb->ctrl.nrip;
+       vmcb->ctrl.intr &= ~VMCB_CTRL_INTR_SHADOW;
+}
+
 static void
 svm_inkernel_handle_cpuid(struct nvmm_cpu *vcpu, uint64_t eax, uint64_t ecx)
 {
@@ -842,12 +840,7 @@
        /* Overwrite non-tunable leaves. */
        svm_inkernel_handle_cpuid(vcpu, eax, ecx);
 
-       /* For now we omit DBREGS. */
-       if (__predict_false(cpudata->vmcb->state.rflags & PSL_T)) {
-               svm_inject_db(mach, vcpu);
-       }
-
-       cpudata->vmcb->state.rip = cpudata->vmcb->ctrl.nrip;
+       svm_inkernel_advance(cpudata->vmcb);
        exit->reason = NVMM_EXIT_NONE;
 }
 
@@ -856,9 +849,14 @@
     struct nvmm_exit *exit)
 {
        struct svm_cpudata *cpudata = vcpu->cpudata;
+       struct vmcb *vmcb = cpudata->vmcb;
 
-       exit->reason = NVMM_EXIT_HLT;
-       exit->u.hlt.npc = cpudata->vmcb->ctrl.nrip;
+       if (cpudata->int_window_exit && (vmcb->state.rflags & PSL_I)) {
+               svm_event_waitexit_disable(vcpu, false);
+       }
+
+       svm_inkernel_advance(cpudata->vmcb);
+       exit->reason = NVMM_EXIT_HALTED;
 }
 
 #define SVM_EXIT_IO_PORT       __BITS(31,16)
@@ -994,7 +992,7 @@
        return false;
 
 handled:
-       cpudata->vmcb->state.rip = cpudata->vmcb->ctrl.nrip;
+       svm_inkernel_advance(cpudata->vmcb);
        return true;
 }
 
@@ -1060,6 +1058,13 @@
 }
 
 static void
+svm_exit_insn(struct vmcb *vmcb, struct nvmm_exit *exit, uint64_t reason)
+{
+       exit->u.insn.npc = vmcb->ctrl.nrip;
+       exit->reason = reason;
+}
+
+static void
 svm_exit_xsetbv(struct nvmm_machine *mach, struct nvmm_cpu *vcpu,
     struct nvmm_exit *exit)
 {
@@ -1084,7 +1089,7 @@
 
        cpudata->gxcr0 = val;
 
-       cpudata->vmcb->state.rip = cpudata->vmcb->ctrl.nrip;
+       svm_inkernel_advance(cpudata->vmcb);
        return;
 
 error:
@@ -1269,13 +1274,13 @@
                        exit->reason = NVMM_EXIT_NONE;
                        break;
                case VMCB_EXITCODE_MONITOR:
-                       exit->reason = NVMM_EXIT_MONITOR;
+                       svm_exit_insn(vmcb, exit, NVMM_EXIT_MONITOR);
                        break;
                case VMCB_EXITCODE_MWAIT:
-                       exit->reason = NVMM_EXIT_MWAIT;
+                       svm_exit_insn(vmcb, exit, NVMM_EXIT_MWAIT);
                        break;
                case VMCB_EXITCODE_MWAIT_CONDITIONAL:
-                       exit->reason = NVMM_EXIT_MWAIT_COND;
+                       svm_exit_insn(vmcb, exit, NVMM_EXIT_MWAIT_COND);
                        break;
                case VMCB_EXITCODE_XSETBV:
                        svm_exit_xsetbv(mach, vcpu, exit);



Home | Main Index | Thread Index | Old Index