diff options
author | neel <neel@FreeBSD.org> | 2014-07-24 01:38:11 +0000 |
---|---|---|
committer | neel <neel@FreeBSD.org> | 2014-07-24 01:38:11 +0000 |
commit | 4535fa67c47e242c2d4c579630ebc12d8153d881 (patch) | |
tree | f10160daba1a9c8df5c059e74db7b03dcae6f007 /sys/amd64/vmm | |
parent | 57fd2f85267f7e1a29e8cef251c560081842963b (diff) | |
download | FreeBSD-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.c | 72 |
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"); |