Source-Changes-HG archive

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

[src/trunk]: src/sys/dev/nvmm Ah, finally found you. Fix scheduling bug in NVMM.



details:   https://anonhg.NetBSD.org/src/rev/ff6ea6f66e0f
branches:  trunk
changeset: 449006:ff6ea6f66e0f
user:      maxv <maxv%NetBSD.org@localhost>
date:      Mon Feb 18 12:17:45 2019 +0000

description:
Ah, finally found you. Fix scheduling bug in NVMM.

When processing guest page faults, we were calling uvm_fault with
preemption disabled. The thing is, uvm_fault may block, and if it does,
we land in sleepq_block which calls mi_switch; so we get switched away
while we explicitly asked not to be. From then on things could go really
wrong.

Fix that by processing such faults in MI, where we have preemption enabled
and are allowed to block.

A KASSERT in sleepq_block (or before) would have helped.

diffstat:

 sys/dev/nvmm/nvmm.c             |  24 +++++++++++++++++++++---
 sys/dev/nvmm/x86/nvmm_x86_svm.c |  33 +++++++++++++--------------------
 sys/dev/nvmm/x86/nvmm_x86_vmx.c |  31 ++++++++++++-------------------
 3 files changed, 46 insertions(+), 42 deletions(-)

diffs (162 lines):

diff -r 125980399125 -r ff6ea6f66e0f sys/dev/nvmm/nvmm.c
--- a/sys/dev/nvmm/nvmm.c       Mon Feb 18 11:22:56 2019 +0000
+++ b/sys/dev/nvmm/nvmm.c       Mon Feb 18 12:17:45 2019 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: nvmm.c,v 1.7 2019/02/13 16:03:16 maxv Exp $    */
+/*     $NetBSD: nvmm.c,v 1.8 2019/02/18 12:17:45 maxv Exp $    */
 
 /*
  * Copyright (c) 2018 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: nvmm.c,v 1.7 2019/02/13 16:03:16 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: nvmm.c,v 1.8 2019/02/18 12:17:45 maxv Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -478,6 +478,24 @@
        return error;
 }
 
+static void
+nvmm_do_vcpu_run(struct nvmm_machine *mach, struct nvmm_cpu *vcpu,
+    struct nvmm_exit *exit)
+{
+       struct vmspace *vm = mach->vm;
+
+       while (1) {
+               (*nvmm_impl->vcpu_run)(mach, vcpu, exit);
+
+               if (__predict_true(exit->reason != NVMM_EXIT_MEMORY)) {
+                       break;
+               }
+               if (uvm_fault(&vm->vm_map, exit->u.mem.gpa, VM_PROT_ALL)) {
+                       break;
+               }
+       }
+}
+
 static int
 nvmm_vcpu_run(struct nvmm_ioc_vcpu_run *args)
 {
@@ -493,7 +511,7 @@
        if (error)
                goto out;
 
-       (*nvmm_impl->vcpu_run)(mach, vcpu, &args->exit);
+       nvmm_do_vcpu_run(mach, vcpu, &args->exit);
        nvmm_vcpu_put(vcpu);
 
 out:
diff -r 125980399125 -r ff6ea6f66e0f sys/dev/nvmm/x86/nvmm_x86_svm.c
--- a/sys/dev/nvmm/x86/nvmm_x86_svm.c   Mon Feb 18 11:22:56 2019 +0000
+++ b/sys/dev/nvmm/x86/nvmm_x86_svm.c   Mon Feb 18 12:17:45 2019 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: nvmm_x86_svm.c,v 1.26 2019/02/16 12:58:13 maxv Exp $   */
+/*     $NetBSD: nvmm_x86_svm.c,v 1.27 2019/02/18 12:17:45 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.26 2019/02/16 12:58:13 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: nvmm_x86_svm.c,v 1.27 2019/02/18 12:17:45 maxv Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -1048,25 +1048,18 @@
 {
        struct svm_cpudata *cpudata = vcpu->cpudata;
        gpaddr_t gpa = cpudata->vmcb->ctrl.exitinfo2;
-       int error;
 
-       error = uvm_fault(&mach->vm->vm_map, gpa, VM_PROT_ALL);
-
-       if (error) {
-               exit->reason = NVMM_EXIT_MEMORY;
-               if (cpudata->vmcb->ctrl.exitinfo1 & PGEX_W)
-                       exit->u.mem.perm = NVMM_EXIT_MEMORY_WRITE;
-               else if (cpudata->vmcb->ctrl.exitinfo1 & PGEX_X)
-                       exit->u.mem.perm = NVMM_EXIT_MEMORY_EXEC;
-               else
-                       exit->u.mem.perm = NVMM_EXIT_MEMORY_READ;
-               exit->u.mem.gpa = gpa;
-               exit->u.mem.inst_len = cpudata->vmcb->ctrl.inst_len;
-               memcpy(exit->u.mem.inst_bytes, cpudata->vmcb->ctrl.inst_bytes,
-                   sizeof(exit->u.mem.inst_bytes));
-       } else {
-               exit->reason = NVMM_EXIT_NONE;
-       }
+       exit->reason = NVMM_EXIT_MEMORY;
+       if (cpudata->vmcb->ctrl.exitinfo1 & PGEX_W)
+               exit->u.mem.perm = NVMM_EXIT_MEMORY_WRITE;
+       else if (cpudata->vmcb->ctrl.exitinfo1 & PGEX_X)
+               exit->u.mem.perm = NVMM_EXIT_MEMORY_EXEC;
+       else
+               exit->u.mem.perm = NVMM_EXIT_MEMORY_READ;
+       exit->u.mem.gpa = gpa;
+       exit->u.mem.inst_len = cpudata->vmcb->ctrl.inst_len;
+       memcpy(exit->u.mem.inst_bytes, cpudata->vmcb->ctrl.inst_bytes,
+           sizeof(exit->u.mem.inst_bytes));
 }
 
 static void
diff -r 125980399125 -r ff6ea6f66e0f sys/dev/nvmm/x86/nvmm_x86_vmx.c
--- a/sys/dev/nvmm/x86/nvmm_x86_vmx.c   Mon Feb 18 11:22:56 2019 +0000
+++ b/sys/dev/nvmm/x86/nvmm_x86_vmx.c   Mon Feb 18 12:17:45 2019 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: nvmm_x86_vmx.c,v 1.6 2019/02/16 12:40:31 maxv Exp $    */
+/*     $NetBSD: nvmm_x86_vmx.c,v 1.7 2019/02/18 12:17:45 maxv Exp $    */
 
 /*
  * Copyright (c) 2018 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: nvmm_x86_vmx.c,v 1.6 2019/02/16 12:40:31 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: nvmm_x86_vmx.c,v 1.7 2019/02/18 12:17:45 maxv Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -1495,26 +1495,19 @@
 {
        uint64_t perm;
        gpaddr_t gpa;
-       int error;
 
        vmx_vmread(VMCS_GUEST_PHYSICAL_ADDRESS, &gpa);
 
-       error = uvm_fault(&mach->vm->vm_map, gpa, VM_PROT_ALL);
-
-       if (error) {
-               exit->reason = NVMM_EXIT_MEMORY;
-               vmx_vmread(VMCS_EXIT_QUALIFICATION, &perm);
-               if (perm & VMX_EPT_VIOLATION_WRITE)
-                       exit->u.mem.perm = NVMM_EXIT_MEMORY_WRITE;
-               else if (perm & VMX_EPT_VIOLATION_EXECUTE)
-                       exit->u.mem.perm = NVMM_EXIT_MEMORY_EXEC;
-               else
-                       exit->u.mem.perm = NVMM_EXIT_MEMORY_READ;
-               exit->u.mem.gpa = gpa;
-               exit->u.mem.inst_len = 0;
-       } else {
-               exit->reason = NVMM_EXIT_NONE;
-       }
+       exit->reason = NVMM_EXIT_MEMORY;
+       vmx_vmread(VMCS_EXIT_QUALIFICATION, &perm);
+       if (perm & VMX_EPT_VIOLATION_WRITE)
+               exit->u.mem.perm = NVMM_EXIT_MEMORY_WRITE;
+       else if (perm & VMX_EPT_VIOLATION_EXECUTE)
+               exit->u.mem.perm = NVMM_EXIT_MEMORY_EXEC;
+       else
+               exit->u.mem.perm = NVMM_EXIT_MEMORY_READ;
+       exit->u.mem.gpa = gpa;
+       exit->u.mem.inst_len = 0;
 }
 
 static void



Home | Main Index | Thread Index | Old Index