svn commit: r253044 - in projects/bhyve_npt_pmap: sys/amd64/include sys/amd64/vmm sys/amd64/vmm/intel usr.sbin/bhyve
Neel Natu
neel at FreeBSD.org
Mon Jul 8 19:40:52 UTC 2013
Author: neel
Date: Mon Jul 8 19:40:50 2013
New Revision: 253044
URL: http://svnweb.freebsd.org/changeset/base/253044
Log:
Fault in guest memory in response to EPT faults.
The EPT faults are distinguished as follows:
- Faults that point to an address that is assigned to a "memory" region
will be resolved using vm_fault()
- All other EPT faults are resolved via instruction emulation under the
assumption that they happened because of an instruction accessing MMIO.
Modified:
projects/bhyve_npt_pmap/sys/amd64/include/vmm.h
projects/bhyve_npt_pmap/sys/amd64/vmm/intel/vmx.c
projects/bhyve_npt_pmap/sys/amd64/vmm/vmm.c
projects/bhyve_npt_pmap/usr.sbin/bhyve/bhyverun.c
Modified: projects/bhyve_npt_pmap/sys/amd64/include/vmm.h
==============================================================================
--- projects/bhyve_npt_pmap/sys/amd64/include/vmm.h Mon Jul 8 19:19:29 2013 (r253043)
+++ projects/bhyve_npt_pmap/sys/amd64/include/vmm.h Mon Jul 8 19:40:50 2013 (r253044)
@@ -98,6 +98,7 @@ int vm_gpabase2memseg(struct vm *vm, vm_
struct vm_memory_segment *seg);
int vm_get_memobj(struct vm *vm, vm_paddr_t gpa, size_t len,
vm_offset_t *offset, struct vm_object **object);
+boolean_t vm_mem_allocated(struct vm *vm, vm_paddr_t gpa);
int vm_get_register(struct vm *vm, int vcpu, int reg, uint64_t *retval);
int vm_set_register(struct vm *vm, int vcpu, int reg, uint64_t val);
int vm_get_seg_desc(struct vm *vm, int vcpu, int reg,
@@ -269,6 +270,8 @@ struct vm_exit {
struct {
uint64_t gpa;
struct vie vie;
+ int inst_emulation;
+ int fault_type;
} paging;
/*
* VMX specific payload. Used when there is no "better"
Modified: projects/bhyve_npt_pmap/sys/amd64/vmm/intel/vmx.c
==============================================================================
--- projects/bhyve_npt_pmap/sys/amd64/vmm/intel/vmx.c Mon Jul 8 19:19:29 2013 (r253043)
+++ projects/bhyve_npt_pmap/sys/amd64/vmm/intel/vmx.c Mon Jul 8 19:40:50 2013 (r253044)
@@ -1175,7 +1175,22 @@ vmx_emulate_cr_access(struct vmx *vmx, i
}
static int
-vmx_ept_fault(struct vm *vm, int cpu,
+ept_fault_type(uint64_t ept_qual)
+{
+ int fault_type = 0;
+
+ if (ept_qual & EPT_VIOLATION_INST_FETCH)
+ fault_type |= VM_PROT_EXECUTE;
+ if (ept_qual & EPT_VIOLATION_DATA_READ)
+ fault_type |= VM_PROT_READ;
+ if (ept_qual & EPT_VIOLATION_DATA_WRITE)
+ fault_type |= VM_PROT_WRITE;
+
+ return (fault_type);
+}
+
+static int
+vmx_inst_emul(struct vm *vm, int cpu,
uint64_t gla, uint64_t gpa, uint64_t rip, int inst_length,
uint64_t cr3, uint64_t ept_qual, struct vie *vie)
{
@@ -1223,7 +1238,7 @@ vmx_ept_fault(struct vm *vm, int cpu,
static int
vmx_exit_process(struct vmx *vmx, int vcpu, struct vm_exit *vmexit)
{
- int error, handled;
+ int error, handled, emulation;
struct vmcs *vmcs;
struct vmxctx *vmxctx;
uint32_t eax, ecx, edx;
@@ -1334,15 +1349,30 @@ vmx_exit_process(struct vmx *vmx, int vc
break;
case EXIT_REASON_EPT_FAULT:
vmm_stat_incr(vmx->vm, vcpu, VMEXIT_EPT_FAULT, 1);
- gla = vmcs_gla();
+ /*
+ * If 'gpa' lies within the address space allocated to
+ * memory then this must be a nested page fault otherwise
+ * this must be an instruction that accesses MMIO space.
+ */
gpa = vmcs_gpa();
- cr3 = vmcs_guest_cr3();
- handled = vmx_ept_fault(vmx->vm, vcpu, gla, gpa,
- vmexit->rip, vmexit->inst_length,
- cr3, qual, &vmexit->u.paging.vie);
+ if (vm_mem_allocated(vmx->vm, gpa)) {
+ handled = 0;
+ emulation = 0;
+ } else {
+ emulation = 1;
+ gla = vmcs_gla();
+ cr3 = vmcs_guest_cr3();
+ vie_init(&vmexit->u.paging.vie);
+ handled = vmx_inst_emul(vmx->vm, vcpu, gla, gpa,
+ vmexit->rip, vmexit->inst_length,
+ cr3, qual, &vmexit->u.paging.vie);
+ }
+
if (!handled) {
vmexit->exitcode = VM_EXITCODE_PAGING;
vmexit->u.paging.gpa = gpa;
+ vmexit->u.paging.inst_emulation = emulation;
+ vmexit->u.paging.fault_type = ept_fault_type(qual);
}
break;
default:
Modified: projects/bhyve_npt_pmap/sys/amd64/vmm/vmm.c
==============================================================================
--- projects/bhyve_npt_pmap/sys/amd64/vmm/vmm.c Mon Jul 8 19:19:29 2013 (r253043)
+++ projects/bhyve_npt_pmap/sys/amd64/vmm/vmm.c Mon Jul 8 19:40:50 2013 (r253044)
@@ -49,6 +49,8 @@ __FBSDID("$FreeBSD$");
#include <vm/vm_page.h>
#include <vm/pmap.h>
#include <vm/vm_map.h>
+#include <vm/vm_extern.h>
+#include <vm/vm_param.h>
#include <machine/vm.h>
#include <machine/pcb.h>
@@ -364,26 +366,20 @@ vm_unmap_mmio(struct vm *vm, vm_paddr_t
return (ENXIO); /* XXX fixme */
}
-/*
- * Returns TRUE if 'gpa' is available for allocation and FALSE otherwise
- */
-static boolean_t
-vm_gpa_available(struct vm *vm, vm_paddr_t gpa)
+boolean_t
+vm_mem_allocated(struct vm *vm, vm_paddr_t gpa)
{
int i;
vm_paddr_t gpabase, gpalimit;
- if (gpa & PAGE_MASK)
- panic("vm_gpa_available: gpa (0x%016lx) not page aligned", gpa);
-
for (i = 0; i < vm->num_mem_segs; i++) {
gpabase = vm->mem_segs[i].gpa;
gpalimit = gpabase + vm->mem_segs[i].len;
if (gpa >= gpabase && gpa < gpalimit)
- return (FALSE);
+ return (TRUE);
}
- return (TRUE);
+ return (FALSE);
}
/*
@@ -403,10 +399,10 @@ vm_malloc(struct vm *vm, vm_paddr_t gpa,
available = allocated = 0;
g = gpa;
while (g < gpa + len) {
- if (vm_gpa_available(vm, g))
- available++;
- else
+ if (vm_mem_allocated(vm, g))
allocated++;
+ else
+ available++;
g += PAGE_SIZE;
}
@@ -657,11 +653,14 @@ restart:
critical_exit();
+ if (error)
+ goto done;
+
/*
* Oblige the guest's desire to 'hlt' by sleeping until the vcpu
* is ready to run.
*/
- if (error == 0 && vme->exitcode == VM_EXITCODE_HLT) {
+ if (vme->exitcode == VM_EXITCODE_HLT) {
vcpu_lock(vcpu);
/*
@@ -699,6 +698,39 @@ restart:
goto restart;
}
+ if (vme->exitcode == VM_EXITCODE_PAGING &&
+ vme->u.paging.inst_emulation == 0) {
+ int rv;
+ struct thread *td;
+ struct proc *p;
+ struct vm_map *map;
+ vm_prot_t ftype;
+
+ td = curthread;
+ p = td->td_proc;
+ map = &vm->vmspace->vm_map;
+ ftype = vme->u.paging.fault_type;
+
+ PROC_LOCK(p);
+ p->p_lock++;
+ PROC_UNLOCK(p);
+
+ rv = vm_fault(map, vme->u.paging.gpa, ftype, VM_FAULT_NORMAL);
+
+ PROC_LOCK(p);
+ p->p_lock--;
+ PROC_UNLOCK(p);
+
+ if (rv == KERN_SUCCESS) {
+ rip = vme->rip;
+ goto restart;
+ } else {
+ /* XXX */
+ vme->inst_length = 0;
+ }
+ }
+
+done:
return (error);
}
Modified: projects/bhyve_npt_pmap/usr.sbin/bhyve/bhyverun.c
==============================================================================
--- projects/bhyve_npt_pmap/usr.sbin/bhyve/bhyverun.c Mon Jul 8 19:19:29 2013 (r253043)
+++ projects/bhyve_npt_pmap/usr.sbin/bhyve/bhyverun.c Mon Jul 8 19:40:50 2013 (r253044)
@@ -440,8 +440,11 @@ vmexit_paging(struct vmctx *ctx, struct
int err;
stats.vmexit_paging++;
- err = emulate_mem(ctx, *pvcpu, vmexit->u.paging.gpa,
- &vmexit->u.paging.vie);
+ if (vmexit->u.paging.inst_emulation) {
+ err = emulate_mem(ctx, *pvcpu, vmexit->u.paging.gpa,
+ &vmexit->u.paging.vie);
+ } else
+ err = ESRCH;
if (err) {
if (err == EINVAL) {
More information about the svn-src-projects
mailing list