summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorStefan Kempf <stefan@cvs.openbsd.org>2016-01-10 18:18:26 +0000
committerStefan Kempf <stefan@cvs.openbsd.org>2016-01-10 18:18:26 +0000
commit6f64250a49f0393166ad6a13554b045c6fd22bae (patch)
tree9004fc8e665db02ec82be5aa3323a06c8c8cc02d /sys
parent3d51bbdb718f5c8892b138e58aba74e19480a7f9 (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.c51
-rw-r--r--sys/arch/amd64/include/specialreg.h6
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)
/*