diff options
Diffstat (limited to 'sys/amd64/vmm/vmm.c')
-rw-r--r-- | sys/amd64/vmm/vmm.c | 67 |
1 files changed, 54 insertions, 13 deletions
diff --git a/sys/amd64/vmm/vmm.c b/sys/amd64/vmm/vmm.c index 9aed5f5..8ebdfd7 100644 --- a/sys/amd64/vmm/vmm.c +++ b/sys/amd64/vmm/vmm.c @@ -62,7 +62,9 @@ __FBSDID("$FreeBSD$"); #include <machine/vmm.h> #include <machine/vmm_dev.h> +#include <machine/vmm_instruction_emul.h> +#include "vmm_ioport.h" #include "vmm_ktr.h" #include "vmm_host.h" #include "vmm_mem.h" @@ -1131,34 +1133,33 @@ vm_handle_inst_emul(struct vm *vm, int vcpuid, bool *retu) struct vie *vie; struct vcpu *vcpu; struct vm_exit *vme; - int error, inst_length; - uint64_t rip, gla, gpa, cr3; - enum vie_cpu_mode cpu_mode; - enum vie_paging_mode paging_mode; + uint64_t gla, gpa; + struct vm_guest_paging *paging; mem_region_read_t mread; mem_region_write_t mwrite; + int error; vcpu = &vm->vcpu[vcpuid]; vme = &vcpu->exitinfo; - rip = vme->rip; - inst_length = vme->inst_length; - gla = vme->u.inst_emul.gla; gpa = vme->u.inst_emul.gpa; - cr3 = vme->u.inst_emul.cr3; - cpu_mode = vme->u.inst_emul.cpu_mode; - paging_mode = vme->u.inst_emul.paging_mode; vie = &vme->u.inst_emul.vie; + paging = &vme->u.inst_emul.paging; vie_init(vie); /* Fetch, decode and emulate the faulting instruction */ - if (vmm_fetch_instruction(vm, vcpuid, rip, inst_length, cr3, - paging_mode, vie) != 0) + error = vmm_fetch_instruction(vm, vcpuid, paging, vme->rip, + vme->inst_length, vie); + if (error == 1) + return (0); /* Resume guest to handle page fault */ + else if (error == -1) return (EFAULT); + else if (error != 0) + panic("%s: vmm_fetch_instruction error %d", __func__, error); - if (vmm_decode_instruction(vm, vcpuid, gla, cpu_mode, vie) != 0) + if (vmm_decode_instruction(vm, vcpuid, gla, paging->cpu_mode, vie) != 0) return (EFAULT); /* return to userland unless this is an in-kernel emulated device */ @@ -1348,6 +1349,10 @@ restart: case VM_EXITCODE_INST_EMUL: error = vm_handle_inst_emul(vm, vcpuid, &retu); break; + case VM_EXITCODE_INOUT: + case VM_EXITCODE_INOUT_STR: + error = vm_handle_inout(vm, vcpuid, vme, &retu); + break; default: retu = true; /* handled in userland */ break; @@ -1430,6 +1435,25 @@ 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) +{ + struct vm_exception pf = { + .vector = IDT_PF, + .error_code_valid = 1, + .error_code = error_code + }; + int error; + + 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 = { @@ -1856,3 +1880,20 @@ vm_atpit(struct vm *vm) { return (vm->vatpit); } + +enum vm_reg_name +vm_segment_name(int seg) +{ + static enum vm_reg_name seg_names[] = { + VM_REG_GUEST_ES, + VM_REG_GUEST_CS, + VM_REG_GUEST_SS, + VM_REG_GUEST_DS, + VM_REG_GUEST_FS, + VM_REG_GUEST_GS + }; + + KASSERT(seg >= 0 && seg < nitems(seg_names), + ("%s: invalid segment encoding %d", __func__, seg)); + return (seg_names[seg]); +} |