Module Name: src Committed By: maxv Date: Thu Mar 7 15:06:37 UTC 2019
Modified Files: src/sys/dev/nvmm/x86: nvmm_x86_vmx.c Log Message: Parse EXC_NMI on nvmm-intel, and don't return NVMM_EXIT_INVALID if we received a host NMI, otherwise the guest could get killed if an NMI comes in, typically when the host runs tprof at the same time. Already handled on nvmm-amd. To generate a diff of this commit: cvs rdiff -u -r1.16 -r1.17 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/x86/nvmm_x86_vmx.c diff -u src/sys/dev/nvmm/x86/nvmm_x86_vmx.c:1.16 src/sys/dev/nvmm/x86/nvmm_x86_vmx.c:1.17 --- src/sys/dev/nvmm/x86/nvmm_x86_vmx.c:1.16 Sun Mar 3 07:01:09 2019 +++ src/sys/dev/nvmm/x86/nvmm_x86_vmx.c Thu Mar 7 15:06:37 2019 @@ -1,4 +1,4 @@ -/* $NetBSD: nvmm_x86_vmx.c,v 1.16 2019/03/03 07:01:09 maxv Exp $ */ +/* $NetBSD: nvmm_x86_vmx.c,v 1.17 2019/03/07 15:06:37 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.16 2019/03/03 07:01:09 maxv Exp $"); +__KERNEL_RCSID(0, "$NetBSD: nvmm_x86_vmx.c,v 1.17 2019/03/07 15:06:37 maxv Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -282,13 +282,14 @@ int vmx_vmresume(uint64_t *gprs); #define VMCS_ENTRY_MSR_LOAD_COUNT 0x00004014 #define VMCS_ENTRY_INTR_INFO 0x00004016 #define INTR_INFO_VECTOR __BITS(7,0) -#define INTR_INFO_TYPE_EXT_INT (0 << 8) -#define INTR_INFO_TYPE_NMI (2 << 8) -#define INTR_INFO_TYPE_HW_EXC (3 << 8) -#define INTR_INFO_TYPE_SW_INT (4 << 8) -#define INTR_INFO_TYPE_PRIV_SW_EXC (5 << 8) -#define INTR_INFO_TYPE_SW_EXC (6 << 8) -#define INTR_INFO_TYPE_OTHER (7 << 8) +#define INTR_INFO_TYPE __BITS(10,8) +#define INTR_TYPE_EXT_INT 0 +#define INTR_TYPE_NMI 2 +#define INTR_TYPE_HW_EXC 3 +#define INTR_TYPE_SW_INT 4 +#define INTR_TYPE_PRIV_SW_EXC 5 +#define INTR_TYPE_SW_EXC 6 +#define INTR_TYPE_OTHER 7 #define INTR_INFO_ERROR __BIT(11) #define INTR_INFO_VALID __BIT(31) #define VMCS_ENTRY_EXCEPTION_ERROR 0x00004018 @@ -883,12 +884,12 @@ vmx_vcpu_inject(struct nvmm_machine *mac switch (event->type) { case NVMM_EVENT_INTERRUPT_HW: - type = INTR_INFO_TYPE_EXT_INT; + type = INTR_TYPE_EXT_INT; if (event->vector == 2) { - type = INTR_INFO_TYPE_NMI; + type = INTR_TYPE_NMI; } vmx_vmread(VMCS_GUEST_INTERRUPTIBILITY, &intstate); - if (type == INTR_INFO_TYPE_NMI) { + if (type == INTR_TYPE_NMI) { if (cpudata->nmi_window_exit) { ret = EAGAIN; goto out; @@ -917,7 +918,7 @@ vmx_vcpu_inject(struct nvmm_machine *mac ret = EINVAL; goto out; } - type = INTR_INFO_TYPE_HW_EXC; + type = INTR_TYPE_HW_EXC; err = vmx_event_has_error(event->vector); break; default: @@ -927,7 +928,7 @@ vmx_vcpu_inject(struct nvmm_machine *mac info = __SHIFTIN(event->vector, INTR_INFO_VECTOR) | - type | + __SHIFTIN(type, INTR_INFO_TYPE) | __SHIFTIN(err, INTR_INFO_ERROR) | __SHIFTIN(1, INTR_INFO_VALID); vmx_vmwrite(VMCS_ENTRY_INTR_INFO, info); @@ -985,6 +986,28 @@ vmx_inkernel_advance(void) } static void +vmx_exit_exc_nmi(struct nvmm_machine *mach, struct nvmm_cpu *vcpu, + struct nvmm_exit *exit) +{ + uint64_t qual; + + vmx_vmread(VMCS_EXIT_INTR_INFO, &qual); + + if ((qual & INTR_INFO_VALID) == 0) { + goto error; + } + if (__SHIFTOUT(qual, INTR_INFO_TYPE) != INTR_TYPE_NMI) { + goto error; + } + + exit->reason = NVMM_EXIT_NONE; + return; + +error: + exit->reason = NVMM_EXIT_INVALID; +} + +static void vmx_inkernel_handle_cpuid(struct nvmm_cpu *vcpu, uint64_t eax, uint64_t ecx) { struct vmx_cpudata *cpudata = vcpu->cpudata; @@ -1753,6 +1776,9 @@ vmx_vcpu_run(struct nvmm_machine *mach, exitcode &= __BITS(15,0); switch (exitcode) { + case VMCS_EXITCODE_EXC_NMI: + vmx_exit_exc_nmi(mach, vcpu, exit); + break; case VMCS_EXITCODE_EXT_INT: exit->reason = NVMM_EXIT_NONE; break;