diff options
author | Stefan Kempf <stefan@cvs.openbsd.org> | 2016-01-10 18:18:26 +0000 |
---|---|---|
committer | Stefan Kempf <stefan@cvs.openbsd.org> | 2016-01-10 18:18:26 +0000 |
commit | 6f64250a49f0393166ad6a13554b045c6fd22bae (patch) | |
tree | 9004fc8e665db02ec82be5aa3323a06c8c8cc02d /sys | |
parent | 3d51bbdb718f5c8892b138e58aba74e19480a7f9 (diff) |
Page fault handling tweaks for vmm:
- compute fault reason for uvm_fault() (e.g. page not present,
protection violation) instead of passing a protection code
- a page does not need to be zero'd after faulting it in. uvm_fault() does
that for fresh anon pages already, and we also do not want a page that
is swapped back in have its contents wiped.
ok mlarkin@
Diffstat (limited to 'sys')
-rw-r--r-- | sys/arch/amd64/amd64/vmm.c | 51 | ||||
-rw-r--r-- | sys/arch/amd64/include/specialreg.h | 6 |
2 files changed, 20 insertions, 37 deletions
diff --git a/sys/arch/amd64/amd64/vmm.c b/sys/arch/amd64/amd64/vmm.c index c26945212e0..67056fe7b67 100644 --- a/sys/arch/amd64/amd64/vmm.c +++ b/sys/arch/amd64/amd64/vmm.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vmm.c,v 1.30 2016/01/08 11:20:58 reyk Exp $ */ +/* $OpenBSD: vmm.c,v 1.31 2016/01/10 18:18:25 stefan Exp $ */ /* * Copyright (c) 2014 Mike Larkin <mlarkin@openbsd.org> * @@ -601,7 +601,7 @@ vm_writepage(struct vm_writepage_params *vwp) if (!pmap_extract(vm->vm_map->pmap, vw_page, &host_pa)) { /* page not present */ ret = uvm_fault(vm->vm_map, vw_page, - PROT_WRITE, PROT_READ | PROT_WRITE | PROT_EXEC); + VM_FAULT_INVALID, PROT_READ | PROT_WRITE | PROT_EXEC); if (ret) { free(pagedata, M_DEVBUF, PAGE_SIZE); rw_exit_read(&vmm_softc->vm_lock); @@ -3032,18 +3032,19 @@ int vmx_get_guest_faulttype(void) { uint64_t exit_qualification; + uint64_t presentmask = IA32_VMX_EPT_FAULT_WAS_READABLE | + IA32_VMX_EPT_FAULT_WAS_WRITABLE | IA32_VMX_EPT_FAULT_WAS_EXECABLE; + uint64_t protmask = IA32_VMX_EPT_FAULT_READ | + IA32_VMX_EPT_FAULT_WRITE | IA32_VMX_EPT_FAULT_EXEC; if (vmx_get_exit_qualification(&exit_qualification)) - return (EINVAL); + return (-1); - if (exit_qualification & IA32_VMX_EPT_FAULT_WRITE) - return (PROT_WRITE); - else if (exit_qualification & IA32_VMX_EPT_FAULT_READ) - return (PROT_READ); - else if (exit_qualification & IA32_VMX_EPT_FAULT_EXEC) - return (PROT_EXEC); - else - return (EINVAL); + if ((exit_qualification & presentmask) == 0) + return VM_FAULT_INVALID; + if (exit_qualification & protmask) + return VM_FAULT_PROTECT; + return (-1); } /* @@ -3056,7 +3057,7 @@ int svm_get_guest_faulttype(void) { /* XXX removed due to rot */ - return (EINVAL); + return (-1); } /* @@ -3069,12 +3070,10 @@ int vmx_fault_page(struct vcpu *vcpu, paddr_t gpa) { int fault_type, ret; - vaddr_t kva; - paddr_t host_pa; struct pmap *pmap; fault_type = vmx_get_guest_faulttype(); - if (fault_type == EINVAL) { + if (fault_type == -1) { printf("vmx_fault_page: invalid fault type\n"); return (EINVAL); } @@ -3083,27 +3082,7 @@ vmx_fault_page(struct vcpu *vcpu, paddr_t gpa) PROT_READ | PROT_WRITE | PROT_EXEC); if (!ret) { pmap = vcpu->vc_parent->vm_map->pmap; - if (!vmx_fix_ept_pte(pmap, gpa)) { - if (pmap_extract(pmap, (vaddr_t)gpa, &host_pa)) { - kva = (vaddr_t)km_alloc(PAGE_SIZE, &kv_any, - &kp_none, &kd_nowait); - if (kva) { - pmap_kenter_pa(kva, host_pa, - PROT_READ | PROT_WRITE); - bzero((void *)kva, PAGE_SIZE); - pmap_kremove(kva, PAGE_SIZE); - km_free((void *)kva, PAGE_SIZE, &kv_any, - &kp_none); - vcpu->vc_parent->vm_used_size += PAGE_SIZE; - } else { - printf("vmx_fault_page: kva failure\n"); - ret = ENOMEM; - } - } else { - printf("vmx_fault_page: extract failure\n"); - ret = EFAULT; - } - } else { + if (vmx_fix_ept_pte(pmap, gpa)) { printf("vmx_fault_page: ept fixup failure\n"); ret = EINVAL; } diff --git a/sys/arch/amd64/include/specialreg.h b/sys/arch/amd64/include/specialreg.h index 7e09109eebf..f5295ccc9ed 100644 --- a/sys/arch/amd64/include/specialreg.h +++ b/sys/arch/amd64/include/specialreg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: specialreg.h,v 1.39 2015/12/07 06:34:14 jsg Exp $ */ +/* $OpenBSD: specialreg.h,v 1.40 2016/01/10 18:18:25 stefan Exp $ */ /* $NetBSD: specialreg.h,v 1.1 2003/04/26 18:39:48 fvdl Exp $ */ /* $NetBSD: x86/specialreg.h,v 1.2 2003/04/25 21:54:30 fvdl Exp $ */ @@ -1020,6 +1020,10 @@ #define IA32_VMX_EPT_FAULT_WRITE (1ULL << 1) #define IA32_VMX_EPT_FAULT_EXEC (1ULL << 2) +#define IA32_VMX_EPT_FAULT_WAS_READABLE (1ULL << 3) +#define IA32_VMX_EPT_FAULT_WAS_WRITABLE (1ULL << 4) +#define IA32_VMX_EPT_FAULT_WAS_EXECABLE (1ULL << 5) + #define IA32_VMX_MSR_LIST_SIZE_MASK (3ULL << 25) /* |