Date: Fri, 18 Apr 2014 15:22:57 +0000 (UTC) From: Tycho Nightingale <tychon@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r264648 - in head: sys/amd64/vmm sys/amd64/vmm/io usr.sbin/bhyve Message-ID: <201404181522.s3IFMvJ7009065@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: tychon Date: Fri Apr 18 15:22:56 2014 New Revision: 264648 URL: http://svnweb.freebsd.org/changeset/base/264648 Log: Respect the destination operand size of the 'Input from Port' instruction. Approved by: grehan (co-mentor) Modified: head/sys/amd64/vmm/io/vatpic.c head/sys/amd64/vmm/io/vatpic.h head/sys/amd64/vmm/io/vatpit.c head/sys/amd64/vmm/io/vatpit.h head/sys/amd64/vmm/vmm_ioport.c head/sys/amd64/vmm/vmm_ioport.h head/usr.sbin/bhyve/inout.c Modified: head/sys/amd64/vmm/io/vatpic.c ============================================================================== --- head/sys/amd64/vmm/io/vatpic.c Fri Apr 18 14:59:39 2014 (r264647) +++ head/sys/amd64/vmm/io/vatpic.c Fri Apr 18 15:22:56 2014 (r264648) @@ -517,7 +517,8 @@ vatpic_intr_accepted(struct vm *vm, int } static int -vatpic_read(struct vatpic *vatpic, struct atpic *atpic, struct vm_exit *vmexit) +vatpic_read(struct vatpic *vatpic, struct atpic *atpic, bool in, int port, + int bytes, uint32_t *eax) { VATPIC_LOCK(vatpic); @@ -526,16 +527,16 @@ vatpic_read(struct vatpic *vatpic, struc VATPIC_UNLOCK(vatpic); return (-1); } else { - if (vmexit->u.inout.port & ICU_IMR_OFFSET) { + if (port & ICU_IMR_OFFSET) { /* read interrrupt mask register */ - vmexit->u.inout.eax = atpic->mask; + *eax = atpic->mask; } else { if (atpic->rd_cmd_reg == OCW3_RIS) { /* read interrupt service register */ - vmexit->u.inout.eax = atpic->service; + *eax = atpic->service; } else { /* read interrupt request register */ - vmexit->u.inout.eax = atpic->request; + *eax = atpic->request; } } } @@ -547,17 +548,17 @@ vatpic_read(struct vatpic *vatpic, struc } static int -vatpic_write(struct vatpic *vatpic, struct atpic *atpic, - struct vm_exit *vmexit) +vatpic_write(struct vatpic *vatpic, struct atpic *atpic, bool in, int port, + int bytes, uint32_t *eax) { int error; uint8_t val; - val = vmexit->u.inout.eax; + val = *eax; VATPIC_LOCK(vatpic); - if (vmexit->u.inout.port & ICU_IMR_OFFSET) { + if (port & ICU_IMR_OFFSET) { if (atpic->ready) { error = vatpic_ocw1(vatpic, atpic, val); } else { @@ -594,7 +595,8 @@ vatpic_write(struct vatpic *vatpic, stru } int -vatpic_master_handler(void *vm, int vcpuid, struct vm_exit *vmexit) +vatpic_master_handler(void *vm, int vcpuid, bool in, int port, int bytes, + uint32_t *eax) { struct vatpic *vatpic; struct atpic *atpic; @@ -602,18 +604,19 @@ vatpic_master_handler(void *vm, int vcpu vatpic = vm_atpic(vm); atpic = &vatpic->atpic[0]; - if (vmexit->u.inout.bytes != 1) + if (bytes != 1) return (-1); - if (vmexit->u.inout.in) { - return (vatpic_read(vatpic, atpic, vmexit)); + if (in) { + return (vatpic_read(vatpic, atpic, in, port, bytes, eax)); } - return (vatpic_write(vatpic, atpic, vmexit)); + return (vatpic_write(vatpic, atpic, in, port, bytes, eax)); } int -vatpic_slave_handler(void *vm, int vcpuid, struct vm_exit *vmexit) +vatpic_slave_handler(void *vm, int vcpuid, bool in, int port, int bytes, + uint32_t *eax) { struct vatpic *vatpic; struct atpic *atpic; @@ -621,35 +624,36 @@ vatpic_slave_handler(void *vm, int vcpui vatpic = vm_atpic(vm); atpic = &vatpic->atpic[1]; - if (vmexit->u.inout.bytes != 1) + if (bytes != 1) return (-1); - if (vmexit->u.inout.in) { - return (vatpic_read(vatpic, atpic, vmexit)); + if (in) { + return (vatpic_read(vatpic, atpic, in, port, bytes, eax)); } - return (vatpic_write(vatpic, atpic, vmexit)); + return (vatpic_write(vatpic, atpic, in, port, bytes, eax)); } int -vatpic_elc_handler(void *vm, int vcpuid, struct vm_exit *vmexit) +vatpic_elc_handler(void *vm, int vcpuid, bool in, int port, int bytes, + uint32_t *eax) { struct vatpic *vatpic; bool is_master; vatpic = vm_atpic(vm); - is_master = (vmexit->u.inout.port == IO_ELCR1); + is_master = (port == IO_ELCR1); - if (vmexit->u.inout.bytes != 1) + if (bytes != 1) return (-1); VATPIC_LOCK(vatpic); - if (vmexit->u.inout.in) { + if (in) { if (is_master) - vmexit->u.inout.eax = vatpic->elc[0]; + *eax = vatpic->elc[0]; else - vmexit->u.inout.eax = vatpic->elc[1]; + *eax = vatpic->elc[1]; } else { /* * For the master PIC the cascade channel (IRQ2), the @@ -662,9 +666,9 @@ vatpic_elc_handler(void *vm, int vcpuid, * be programmed for level mode. */ if (is_master) - vatpic->elc[0] = (vmexit->u.inout.eax & 0xf8); + vatpic->elc[0] = (*eax & 0xf8); else - vatpic->elc[1] = (vmexit->u.inout.eax & 0xde); + vatpic->elc[1] = (*eax & 0xde); } VATPIC_UNLOCK(vatpic); Modified: head/sys/amd64/vmm/io/vatpic.h ============================================================================== --- head/sys/amd64/vmm/io/vatpic.h Fri Apr 18 14:59:39 2014 (r264647) +++ head/sys/amd64/vmm/io/vatpic.h Fri Apr 18 15:22:56 2014 (r264648) @@ -39,9 +39,12 @@ struct vatpic *vatpic_init(struct vm *vm); void vatpic_cleanup(struct vatpic *vatpic); -int vatpic_master_handler(void *vm, int vcpuid, struct vm_exit *vmexit); -int vatpic_slave_handler(void *vm, int vcpuid, struct vm_exit *vmexit); -int vatpic_elc_handler(void *vm, int vcpuid, struct vm_exit *vmexit); +int vatpic_master_handler(void *vm, int vcpuid, bool in, int port, int bytes, + uint32_t *eax); +int vatpic_slave_handler(void *vm, int vcpuid, bool in, int port, int bytes, + uint32_t *eax); +int vatpic_elc_handler(void *vm, int vcpuid, bool in, int port, int bytes, + uint32_t *eax); int vatpic_assert_irq(struct vm *vm, int irq); int vatpic_deassert_irq(struct vm *vm, int irq); Modified: head/sys/amd64/vmm/io/vatpit.c ============================================================================== --- head/sys/amd64/vmm/io/vatpit.c Fri Apr 18 14:59:39 2014 (r264647) +++ head/sys/amd64/vmm/io/vatpit.c Fri Apr 18 15:22:56 2014 (r264648) @@ -253,24 +253,23 @@ vatpit_update_mode(struct vatpit *vatpit } int -vatpit_handler(void *vm, int vcpuid, struct vm_exit *vmexit) +vatpit_handler(void *vm, int vcpuid, bool in, int port, int bytes, + uint32_t *eax) { struct vatpit *vatpit; struct channel *c; - int port; uint8_t val; int error; vatpit = vm_atpit(vm); - if (vmexit->u.inout.bytes != 1) + if (bytes != 1) return (-1); - val = vmexit->u.inout.eax; - port = vmexit->u.inout.port; + val = *eax; if (port == TIMER_MODE) { - if (vmexit->u.inout.in) { + if (in) { VM_CTR0(vatpit->vm, "vatpit attempt to read mode"); return (-1); } @@ -283,12 +282,12 @@ vatpit_handler(void *vm, int vcpuid, str } /* counter ports */ - KASSERT(port >= TIMER_CNTR0 && vmexit->u.inout.port <= TIMER_CNTR2, + KASSERT(port >= TIMER_CNTR0 && port <= TIMER_CNTR2, ("invalid port 0x%x", port)); c = &vatpit->channel[port - TIMER_CNTR0]; VATPIT_LOCK(vatpit); - if (vmexit->u.inout.in) { + if (in) { /* * The spec says that once the output latch is completely * read it should revert to "following" the counter. Use @@ -303,12 +302,12 @@ vatpit_handler(void *vm, int vcpuid, str if (c->frbyte) tmp >>= 8; tmp &= 0xff; - vmexit->u.inout.eax = tmp; + *eax = tmp; c->frbyte ^= 1; } else - vmexit->u.inout.eax = c->ol[--c->olbyte]; + *eax = c->ol[--c->olbyte]; } else { - c->cr[c->crbyte++] = vmexit->u.inout.eax; + c->cr[c->crbyte++] = *eax; if (c->crbyte == 2) { c->frbyte = 0; c->crbyte = 0; @@ -329,18 +328,19 @@ vatpit_handler(void *vm, int vcpuid, str } int -vatpit_nmisc_handler(void *vm, int vcpuid, struct vm_exit *vmexit) +vatpit_nmisc_handler(void *vm, int vcpuid, bool in, int port, int bytes, + uint32_t *eax) { struct vatpit *vatpit; vatpit = vm_atpit(vm); - if (vmexit->u.inout.in) { + if (in) { VATPIT_LOCK(vatpit); if (vatpit_get_out(vatpit, 2)) - vmexit->u.inout.eax = TMR2_OUT_STS; + *eax = TMR2_OUT_STS; else - vmexit->u.inout.eax = 0; + *eax = 0; VATPIT_UNLOCK(vatpit); } Modified: head/sys/amd64/vmm/io/vatpit.h ============================================================================== --- head/sys/amd64/vmm/io/vatpit.h Fri Apr 18 14:59:39 2014 (r264647) +++ head/sys/amd64/vmm/io/vatpit.h Fri Apr 18 15:22:56 2014 (r264648) @@ -37,7 +37,9 @@ struct vatpit *vatpit_init(struct vm *vm); void vatpit_cleanup(struct vatpit *vatpit); -int vatpit_handler(void *vm, int vcpuid, struct vm_exit *vmexit); -int vatpit_nmisc_handler(void *vm, int vcpuid, struct vm_exit *vmexit); +int vatpit_handler(void *vm, int vcpuid, bool in, int port, int bytes, + uint32_t *eax); +int vatpit_nmisc_handler(void *vm, int vcpuid, bool in, int port, int bytes, + uint32_t *eax); #endif /* _VATPIT_H_ */ Modified: head/sys/amd64/vmm/vmm_ioport.c ============================================================================== --- head/sys/amd64/vmm/vmm_ioport.c Fri Apr 18 14:59:39 2014 (r264647) +++ head/sys/amd64/vmm/vmm_ioport.c Fri Apr 18 15:22:56 2014 (r264648) @@ -59,6 +59,8 @@ int emulate_ioport(struct vm *vm, int vcpuid, struct vm_exit *vmexit) { ioport_handler_func_t handler; + uint32_t mask, val; + int error; if (vmexit->u.inout.port >= MAX_IOPORTS) return (-1); @@ -67,5 +69,39 @@ emulate_ioport(struct vm *vm, int vcpuid if (handler == NULL) return (-1); - return ((*handler)(vm, vcpuid, vmexit)); + if (!vmexit->u.inout.in) { + switch (vmexit->u.inout.bytes) { + case 1: + mask = 0xff; + break; + case 2: + mask = 0xffff; + break; + default: + mask = 0xffffffff; + break; + } + val = vmexit->u.inout.eax & mask; + } + + error = (*handler)(vm, vcpuid, vmexit->u.inout.in, + vmexit->u.inout.port, vmexit->u.inout.bytes, &val); + + if (!error && vmexit->u.inout.in) { + switch (vmexit->u.inout.bytes) { + case 1: + mask = 0xff; + break; + case 2: + mask = 0xffff; + break; + default: + mask = 0xffffffff; + break; + } + vmexit->u.inout.eax &= ~mask; + vmexit->u.inout.eax |= val & mask; + } + + return (error); } Modified: head/sys/amd64/vmm/vmm_ioport.h ============================================================================== --- head/sys/amd64/vmm/vmm_ioport.h Fri Apr 18 14:59:39 2014 (r264647) +++ head/sys/amd64/vmm/vmm_ioport.h Fri Apr 18 15:22:56 2014 (r264648) @@ -30,7 +30,7 @@ #define _VMM_IOPORT_H_ typedef int (*ioport_handler_func_t)(void *vm, int vcpuid, - struct vm_exit *vmexit); + bool in, int port, int bytes, uint32_t *val); int emulate_ioport(struct vm *vm, int vcpuid, struct vm_exit *vmexit); Modified: head/usr.sbin/bhyve/inout.c ============================================================================== --- head/usr.sbin/bhyve/inout.c Fri Apr 18 14:59:39 2014 (r264647) +++ head/usr.sbin/bhyve/inout.c Fri Apr 18 15:22:56 2014 (r264648) @@ -95,9 +95,10 @@ emulate_inout(struct vmctx *ctx, int vcp uint32_t *eax, int strict) { int flags; - uint32_t mask; + uint32_t mask, val; inout_func_t handler; void *arg; + int error; assert(port < MAX_IOPORTS); @@ -118,16 +119,34 @@ emulate_inout(struct vmctx *ctx, int vcp mask = 0xffffffff; break; } - *eax = *eax & mask; + val = *eax & mask; } flags = inout_handlers[port].flags; arg = inout_handlers[port].arg; if ((in && (flags & IOPORT_F_IN)) || (!in && (flags & IOPORT_F_OUT))) - return ((*handler)(ctx, vcpu, in, port, bytes, eax, arg)); + error = (*handler)(ctx, vcpu, in, port, bytes, &val, arg); else - return (-1); + error = -1; + + if (!error && in) { + switch (bytes) { + case 1: + mask = 0xff; + break; + case 2: + mask = 0xffff; + break; + default: + mask = 0xffffffff; + break; + } + *eax &= ~mask; + *eax |= val & mask; + } + + return (error); } void
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201404181522.s3IFMvJ7009065>