svn commit: r264648 - in head: sys/amd64/vmm sys/amd64/vmm/io usr.sbin/bhyve
Tycho Nightingale
tychon at FreeBSD.org
Fri Apr 18 15:22:58 UTC 2014
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
More information about the svn-src-all
mailing list