Index: sys/amd64/vmm/intel/vmx.c =================================================================== --- sys/amd64/vmm/intel/vmx.c (revision 265407) +++ sys/amd64/vmm/intel/vmx.c (working copy) @@ -1894,11 +1894,6 @@ vmexit->u.inout.rep = (qual & 0x20) ? 1 : 0; vmexit->u.inout.port = (uint16_t)(qual >> 16); vmexit->u.inout.eax = (uint32_t)(vmxctx->guest_rax); - error = emulate_ioport(vmx->vm, vcpu, vmexit); - if (error == 0) { - handled = 1; - vmxctx->guest_rax = vmexit->u.inout.eax; - } break; case EXIT_REASON_CPUID: vmm_stat_incr(vmx->vm, vcpu, VMEXIT_CPUID, 1); Index: sys/amd64/vmm/vmm.c =================================================================== --- sys/amd64/vmm/vmm.c (revision 265407) +++ sys/amd64/vmm/vmm.c (working copy) @@ -63,6 +63,7 @@ #include #include +#include "vmm_ioport.h" #include "vmm_ktr.h" #include "vmm_host.h" #include "vmm_mem.h" @@ -1348,6 +1349,9 @@ case VM_EXITCODE_INST_EMUL: error = vm_handle_inst_emul(vm, vcpuid, &retu); break; + case VM_EXITCODE_INOUT: + error = emulate_ioport(vm, vcpuid, vme, &retu); + break; default: retu = true; /* handled in userland */ break; Index: sys/amd64/vmm/vmm_ioport.c =================================================================== --- sys/amd64/vmm/vmm_ioport.c (revision 265407) +++ sys/amd64/vmm/vmm_ioport.c (working copy) @@ -38,6 +38,7 @@ #include "vatpic.h" #include "vatpit.h" #include "vmm_ioport.h" +#include "vmm_ktr.h" #define MAX_IOPORTS 1280 @@ -55,19 +56,63 @@ [IO_ELCR2] = vatpic_elc_handler, }; +#ifdef KTR +static const char * +inout_instruction(struct vm_exit *vmexit) +{ + int index; + + static const char *iodesc[] = { + "outb", "outw", "outl", + "inb", "inw", "inl", + "outsb", "outsw", "outsd" + "insb", "insw", "insd", + }; + + KASSERT(vmexit->exitcode == VM_EXITCODE_INOUT, + ("%s: invalid exitcode %d", __func__, vmexit->exitcode)); + + switch (vmexit->u.inout.bytes) { + case 1: + index = 0; + break; + case 2: + index = 1; + break; + default: + index = 2; + break; + } + + if (vmexit->u.inout.in) + index += 3; + + if (vmexit->u.inout.string) + index += 6; + + KASSERT(index < nitems(iodesc), ("%s: invalid index %d", + __func__, index)); + + return (iodesc[index]); +} +#endif + int -emulate_ioport(struct vm *vm, int vcpuid, struct vm_exit *vmexit) +emulate_ioport(struct vm *vm, int vcpuid, struct vm_exit *vmexit, bool *retu) { ioport_handler_func_t handler; uint32_t mask, val; int error; + error = 0; + *retu = true; + if (vmexit->u.inout.port >= MAX_IOPORTS) - return (-1); + goto done; handler = ioport_handler[vmexit->u.inout.port]; if (handler == NULL) - return (-1); + goto done; switch (vmexit->u.inout.bytes) { case 1: @@ -88,10 +133,24 @@ error = (*handler)(vm, vcpuid, vmexit->u.inout.in, vmexit->u.inout.port, vmexit->u.inout.bytes, &val); - if (!error && vmexit->u.inout.in) { - vmexit->u.inout.eax &= ~mask; - vmexit->u.inout.eax |= val & mask; + if (!error) { + *retu = false; + if (vmexit->u.inout.in) { + vmexit->u.inout.eax &= ~mask; + vmexit->u.inout.eax |= val & mask; + error = vm_set_register(vm, vcpuid, + VM_REG_GUEST_RAX, vmexit->u.inout.eax); + KASSERT(error == 0, ("emulate_ioport: error %d " + "setting guest rax register", error)); + } } +done: + VCPU_CTR4(vm, vcpuid, "%s%s 0x%04x: %s", + vmexit->u.inout.rep ? "rep " : "", + inout_instruction(vmexit), + vmexit->u.inout.port, + error ? "error" : (*retu ? "userspace" : "handled")); + return (error); } Index: sys/amd64/vmm/vmm_ioport.h =================================================================== --- sys/amd64/vmm/vmm_ioport.h (revision 265407) +++ sys/amd64/vmm/vmm_ioport.h (working copy) @@ -32,6 +32,6 @@ typedef int (*ioport_handler_func_t)(void *vm, int vcpuid, bool in, int port, int bytes, uint32_t *val); -int emulate_ioport(struct vm *vm, int vcpuid, struct vm_exit *vmexit); +int emulate_ioport(struct vm *vm, int vcpuid, struct vm_exit *vme, bool *retu); #endif /* _VMM_IOPORT_H_ */ Index: sys/amd64/vmm/vmm_ktr.h =================================================================== --- sys/amd64/vmm/vmm_ktr.h (revision 265407) +++ sys/amd64/vmm/vmm_ktr.h (working copy) @@ -48,6 +48,10 @@ #define VCPU_CTR3(vm, vcpuid, format, p1, p2, p3) \ CTR5(KTR_VMM, "vm %s[%d]: " format, vm_name((vm)), (vcpuid), (p1), (p2), (p3)) +#define VCPU_CTR4(vm, vcpuid, format, p1, p2, p3, p4) \ +CTR6(KTR_VMM, "vm %s[%d]: " format, vm_name((vm)), (vcpuid), \ + (p1), (p2), (p3), (p4)) + #define VM_CTR0(vm, format) \ CTR1(KTR_VMM, "vm %s: " format, vm_name((vm)))