Module Name: src Committed By: maxv Date: Mon Feb 18 12:17:45 UTC 2019
Modified Files: src/sys/dev/nvmm: nvmm.c src/sys/dev/nvmm/x86: nvmm_x86_svm.c nvmm_x86_vmx.c Log Message: 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. To generate a diff of this commit: cvs rdiff -u -r1.7 -r1.8 src/sys/dev/nvmm/nvmm.c cvs rdiff -u -r1.26 -r1.27 src/sys/dev/nvmm/x86/nvmm_x86_svm.c cvs rdiff -u -r1.6 -r1.7 src/sys/dev/nvmm/x86/nvmm_x86_vmx.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/dev/nvmm/nvmm.c diff -u src/sys/dev/nvmm/nvmm.c:1.7 src/sys/dev/nvmm/nvmm.c:1.8 --- src/sys/dev/nvmm/nvmm.c:1.7 Wed Feb 13 16:03:16 2019 +++ src/sys/dev/nvmm/nvmm.c Mon Feb 18 12:17:45 2019 @@ -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 @@ out: 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 @@ nvmm_vcpu_run(struct nvmm_ioc_vcpu_run * 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: Index: src/sys/dev/nvmm/x86/nvmm_x86_svm.c diff -u src/sys/dev/nvmm/x86/nvmm_x86_svm.c:1.26 src/sys/dev/nvmm/x86/nvmm_x86_svm.c:1.27 --- src/sys/dev/nvmm/x86/nvmm_x86_svm.c:1.26 Sat Feb 16 12:58:13 2019 +++ src/sys/dev/nvmm/x86/nvmm_x86_svm.c Mon Feb 18 12:17:45 2019 @@ -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 @@ svm_exit_npf(struct nvmm_machine *mach, { 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 Index: src/sys/dev/nvmm/x86/nvmm_x86_vmx.c diff -u src/sys/dev/nvmm/x86/nvmm_x86_vmx.c:1.6 src/sys/dev/nvmm/x86/nvmm_x86_vmx.c:1.7 --- src/sys/dev/nvmm/x86/nvmm_x86_vmx.c:1.6 Sat Feb 16 12:40:31 2019 +++ src/sys/dev/nvmm/x86/nvmm_x86_vmx.c Mon Feb 18 12:17:45 2019 @@ -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 @@ vmx_exit_epf(struct nvmm_machine *mach, { 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