diff options
| author | maxv <maxv@NetBSD.org> | 2020-08-26 16:30:50 +0000 |
|---|---|---|
| committer | maxv <maxv@NetBSD.org> | 2020-08-26 16:30:50 +0000 |
| commit | 38248ace32720c32c8ba007fbce80baffa3a749d (patch) | |
| tree | ce128f968274277f8937a48fbef70ff087fcdd92 /sys/dev | |
| parent | d1bb16b664dc0dd36b7f3a6d835046994ca86f59 (diff) | |
nvmm-x86-vmx: improve the handling of CR4
- Filter out certain features we don't want the guest to enable. This is
for general correctness, and future-proofness.
- Flush the guest TLB when certain flags change.
Diffstat (limited to 'sys/dev')
| -rw-r--r-- | sys/dev/nvmm/x86/nvmm_x86_vmx.c | 46 |
1 files changed, 40 insertions, 6 deletions
diff --git a/sys/dev/nvmm/x86/nvmm_x86_vmx.c b/sys/dev/nvmm/x86/nvmm_x86_vmx.c index 5f45bd8b1b3..13bbb104214 100644 --- a/sys/dev/nvmm/x86/nvmm_x86_vmx.c +++ b/sys/dev/nvmm/x86/nvmm_x86_vmx.c @@ -1,4 +1,4 @@ -/* $NetBSD: nvmm_x86_vmx.c,v 1.72 2020/08/22 11:01:10 maxv Exp $ */ +/* $NetBSD: nvmm_x86_vmx.c,v 1.73 2020/08/26 16:30:50 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.72 2020/08/22 11:01:10 maxv Exp $"); +__KERNEL_RCSID(0, "$NetBSD: nvmm_x86_vmx.c,v 1.73 2020/08/26 16:30:50 maxv Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -729,6 +729,33 @@ static uint64_t vmx_xcr0_mask __read_mostly; #define MSRBM_NPAGES 1 #define MSRBM_SIZE (MSRBM_NPAGES * PAGE_SIZE) +#define CR4_VALID \ + (CR4_VME | \ + CR4_PVI | \ + CR4_TSD | \ + CR4_DE | \ + CR4_PSE | \ + CR4_PAE | \ + CR4_MCE | \ + CR4_PGE | \ + CR4_PCE | \ + CR4_OSFXSR | \ + CR4_OSXMMEXCPT | \ + CR4_UMIP | \ + /* CR4_LA57 excluded */ \ + /* CR4_VMXE excluded */ \ + /* CR4_SMXE excluded */ \ + CR4_FSGSBASE | \ + CR4_PCIDE | \ + CR4_OSXSAVE | \ + CR4_SMEP | \ + CR4_SMAP \ + /* CR4_PKE excluded */ \ + /* CR4_CET excluded */ \ + /* CR4_PKS excluded */) +#define CR4_INVALID \ + (0xFFFFFFFFFFFFFFFFULL & ~CR4_VALID) + #define EFER_TLB_FLUSH \ (EFER_NXE|EFER_LMA|EFER_LME) #define CR0_TLB_FLUSH \ @@ -1589,12 +1616,18 @@ vmx_inkernel_handle_cr4(struct nvmm_machine *mach, struct nvmm_cpu *vcpu, gpr = cpudata->gprs[gpr]; } + if (gpr & CR4_INVALID) { + return -1; + } cr4 = gpr | CR4_VMXE; - if (vmx_check_cr(cr4, vmx_cr4_fixed0, vmx_cr4_fixed1) == -1) { return -1; } + if ((vmx_vmread(VMCS_GUEST_CR4) ^ cr4) & CR4_TLB_FLUSH) { + cpudata->gtlb_want_flush = true; + } + vmx_vmwrite(VMCS_GUEST_CR4, cr4); vmx_inkernel_advance(); return 0; @@ -2514,7 +2547,7 @@ vmx_vcpu_setstate(struct nvmm_cpu *vcpu) cpudata->gcr2 = state->crs[NVMM_X64_CR_CR2]; vmx_vmwrite(VMCS_GUEST_CR3, state->crs[NVMM_X64_CR_CR3]); // XXX PDPTE? vmx_vmwrite(VMCS_GUEST_CR4, - state->crs[NVMM_X64_CR_CR4] | CR4_VMXE); + (state->crs[NVMM_X64_CR_CR4] & CR4_VALID) | CR4_VMXE); cpudata->gcr8 = state->crs[NVMM_X64_CR_CR8]; if (vmx_xcr0_mask != 0) { @@ -2839,8 +2872,9 @@ vmx_vcpu_init(struct nvmm_machine *mach, struct nvmm_cpu *vcpu) vmx_vmwrite(VMCS_CR0_MASK, CR0_NW|CR0_CD|CR0_ET); vmx_vmwrite(VMCS_CR0_SHADOW, CR0_ET); - /* Force CR4_VMXE to zero. */ - vmx_vmwrite(VMCS_CR4_MASK, CR4_VMXE); + /* Force unsupported CR4 fields to zero. */ + vmx_vmwrite(VMCS_CR4_MASK, CR4_INVALID); + vmx_vmwrite(VMCS_CR4_SHADOW, 0); /* Set the Host state for resuming. */ vmx_vmwrite(VMCS_HOST_RIP, (uint64_t)&vmx_resume_rip); |
