summaryrefslogtreecommitdiffstats
path: root/usr.sbin
diff options
context:
space:
mode:
authortychon <tychon@FreeBSD.org>2014-04-18 15:22:56 +0000
committertychon <tychon@FreeBSD.org>2014-04-18 15:22:56 +0000
commit2c52df9a16291875deff8314a294582040ff68c3 (patch)
tree4fa8a427cba6f245ab149568c8864a1576f2460d /usr.sbin
parent0cd6870500947ef766e04e48ebae89e91cf375c6 (diff)
downloadFreeBSD-src-2c52df9a16291875deff8314a294582040ff68c3.zip
FreeBSD-src-2c52df9a16291875deff8314a294582040ff68c3.tar.gz
Respect the destination operand size of the 'Input from Port' instruction.
Approved by: grehan (co-mentor)
Diffstat (limited to 'usr.sbin')
-rw-r--r--usr.sbin/bhyve/inout.c27
1 files changed, 23 insertions, 4 deletions
diff --git a/usr.sbin/bhyve/inout.c b/usr.sbin/bhyve/inout.c
index a200265..9fec70a 100644
--- a/usr.sbin/bhyve/inout.c
+++ b/usr.sbin/bhyve/inout.c
@@ -95,9 +95,10 @@ emulate_inout(struct vmctx *ctx, int vcpu, int in, int port, int bytes,
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 vcpu, int in, int port, int bytes,
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
OpenPOWER on IntegriCloud