summaryrefslogtreecommitdiffstats
path: root/sys/amd64/vmm
diff options
context:
space:
mode:
authorneel <neel@FreeBSD.org>2014-07-24 01:38:11 +0000
committerneel <neel@FreeBSD.org>2014-07-24 01:38:11 +0000
commit4535fa67c47e242c2d4c579630ebc12d8153d881 (patch)
treef10160daba1a9c8df5c059e74db7b03dcae6f007 /sys/amd64/vmm
parent57fd2f85267f7e1a29e8cef251c560081842963b (diff)
downloadFreeBSD-src-4535fa67c47e242c2d4c579630ebc12d8153d881.zip
FreeBSD-src-4535fa67c47e242c2d4c579630ebc12d8153d881.tar.gz
Fix fault injection in bhyve.
The faulting instruction needs to be restarted when the exception handler is done handling the fault. bhyve now does this correctly by setting 'vmexit[vcpu].inst_length' to zero so the %rip is not advanced. A minor complication is that the fault injection APIs are used by instruction emulation code that is shared by vmm.ko and bhyve. Thus the argument that refers to 'struct vm *' in kernel or 'struct vmctx *' in userspace needs to be loosely typed as a 'void *'.
Diffstat (limited to 'sys/amd64/vmm')
-rw-r--r--sys/amd64/vmm/vmm.c72
1 files changed, 15 insertions, 57 deletions
diff --git a/sys/amd64/vmm/vmm.c b/sys/amd64/vmm/vmm.c
index b667b48..78aefc4 100644
--- a/sys/amd64/vmm/vmm.c
+++ b/sys/amd64/vmm/vmm.c
@@ -1689,13 +1689,21 @@ vm_inject_exception(struct vm *vm, int vcpuid, struct vm_exception *exception)
return (0);
}
-static void
-vm_inject_fault(struct vm *vm, int vcpuid, struct vm_exception *exception)
+void
+vm_inject_fault(void *vmarg, int vcpuid, int vector, int errcode_valid,
+ int errcode)
{
+ struct vm_exception exception;
struct vm_exit *vmexit;
+ struct vm *vm;
int error;
- error = vm_inject_exception(vm, vcpuid, exception);
+ vm = vmarg;
+
+ exception.vector = vector;
+ exception.error_code = errcode;
+ exception.error_code_valid = errcode_valid;
+ error = vm_inject_exception(vm, vcpuid, &exception);
KASSERT(error == 0, ("vm_inject_exception error %d", error));
/*
@@ -1710,69 +1718,19 @@ vm_inject_fault(struct vm *vm, int vcpuid, struct vm_exception *exception)
}
void
-vm_inject_pf(struct vm *vm, int vcpuid, int error_code, uint64_t cr2)
+vm_inject_pf(void *vmarg, int vcpuid, int error_code, uint64_t cr2)
{
- struct vm_exception pf = {
- .vector = IDT_PF,
- .error_code_valid = 1,
- .error_code = error_code
- };
+ struct vm *vm;
int error;
+ vm = vmarg;
VCPU_CTR2(vm, vcpuid, "Injecting page fault: error_code %#x, cr2 %#lx",
error_code, cr2);
error = vm_set_register(vm, vcpuid, VM_REG_GUEST_CR2, cr2);
KASSERT(error == 0, ("vm_set_register(cr2) error %d", error));
- vm_inject_fault(vm, vcpuid, &pf);
-}
-
-void
-vm_inject_gp(struct vm *vm, int vcpuid)
-{
- struct vm_exception gpf = {
- .vector = IDT_GP,
- .error_code_valid = 1,
- .error_code = 0
- };
-
- vm_inject_fault(vm, vcpuid, &gpf);
-}
-
-void
-vm_inject_ud(struct vm *vm, int vcpuid)
-{
- struct vm_exception udf = {
- .vector = IDT_UD,
- .error_code_valid = 0
- };
-
- vm_inject_fault(vm, vcpuid, &udf);
-}
-
-void
-vm_inject_ac(struct vm *vm, int vcpuid, int error_code)
-{
- struct vm_exception acf = {
- .vector = IDT_AC,
- .error_code_valid = 1,
- .error_code = error_code
- };
-
- vm_inject_fault(vm, vcpuid, &acf);
-}
-
-void
-vm_inject_ss(struct vm *vm, int vcpuid, int error_code)
-{
- struct vm_exception ssf = {
- .vector = IDT_SS,
- .error_code_valid = 1,
- .error_code = error_code
- };
-
- vm_inject_fault(vm, vcpuid, &ssf);
+ vm_inject_fault(vm, vcpuid, IDT_PF, 1, error_code);
}
static VMM_STAT(VCPU_NMI_COUNT, "number of NMIs delivered to vcpu");
OpenPOWER on IntegriCloud