summaryrefslogtreecommitdiffstats
path: root/usr.sbin/bhyve/inout.c
diff options
context:
space:
mode:
authorneel <neel@FreeBSD.org>2014-05-23 19:59:14 +0000
committerneel <neel@FreeBSD.org>2014-05-23 19:59:14 +0000
commit2ccda87acabbb02f574bc3d56994076404bc689b (patch)
tree83967173eb01a2c4de511c4eb71440661a9ed8f1 /usr.sbin/bhyve/inout.c
parent549a5817c0ebaf4934c376d9bab4bf1bfefb0471 (diff)
downloadFreeBSD-src-2ccda87acabbb02f574bc3d56994076404bc689b.zip
FreeBSD-src-2ccda87acabbb02f574bc3d56994076404bc689b.tar.gz
Check for alignment check violation when processing in/out string instructions.
Diffstat (limited to 'usr.sbin/bhyve/inout.c')
-rw-r--r--usr.sbin/bhyve/inout.c25
1 files changed, 13 insertions, 12 deletions
diff --git a/usr.sbin/bhyve/inout.c b/usr.sbin/bhyve/inout.c
index c2bb50a..0bbcde1 100644
--- a/usr.sbin/bhyve/inout.c
+++ b/usr.sbin/bhyve/inout.c
@@ -33,6 +33,7 @@ __FBSDID("$FreeBSD$");
#include <sys/linker_set.h>
#include <x86/psl.h>
+#include <x86/segments.h>
#include <machine/vmm.h>
#include <vmmapi.h>
@@ -110,13 +111,6 @@ emulate_inout(struct vmctx *ctx, int vcpu, struct vm_exit *vmexit, int strict)
uint64_t index, count;
struct vm_inout_str *vis;
- static uint64_t size2mask[] = {
- [1] = 0xff,
- [2] = 0xffff,
- [4] = 0xffffffff,
- [8] = 0xffffffffffffffff,
- };
-
bytes = vmexit->u.inout.bytes;
in = vmexit->u.inout.in;
port = vmexit->u.inout.port;
@@ -149,15 +143,22 @@ emulate_inout(struct vmctx *ctx, int vcpu, struct vm_exit *vmexit, int strict)
/* Index register */
idxreg = in ? VM_REG_GUEST_RDI : VM_REG_GUEST_RSI;
- index = vis->index & size2mask[addrsize];
+ index = vis->index & vie_size2mask(addrsize);
/* Count register */
- count = vis->count & size2mask[addrsize];
+ count = vis->count & vie_size2mask(addrsize);
gpa = vis->gpa;
gpaend = rounddown(gpa + PAGE_SIZE, PAGE_SIZE);
gva = paddr_guest2host(ctx, gpa, gpaend - gpa);
+ if (vie_alignment_check(vis->cpl, bytes, vis->cr0,
+ vis->rflags, vis->gla)) {
+ error = vm_inject_exception2(ctx, vcpu, IDT_AC, 0);
+ assert(error == 0);
+ return (INOUT_RESTART);
+ }
+
while (count != 0 && gpa < gpaend) {
/*
* XXX this may not work for unaligned accesses because
@@ -209,12 +210,12 @@ emulate_inout(struct vmctx *ctx, int vcpu, struct vm_exit *vmexit, int strict)
retval = INOUT_RESTART;
} else {
if (!in) {
- val = vmexit->u.inout.eax & size2mask[bytes];
+ val = vmexit->u.inout.eax & vie_size2mask(bytes);
}
retval = handler(ctx, vcpu, in, port, bytes, &val, arg);
if (retval == 0 && in) {
- vmexit->u.inout.eax &= ~size2mask[bytes];
- vmexit->u.inout.eax |= val & size2mask[bytes];
+ vmexit->u.inout.eax &= ~vie_size2mask(bytes);
+ vmexit->u.inout.eax |= val & vie_size2mask(bytes);
}
}
return (retval);
OpenPOWER on IntegriCloud