diff options
author | neel <neel@FreeBSD.org> | 2014-05-23 19:59:14 +0000 |
---|---|---|
committer | neel <neel@FreeBSD.org> | 2014-05-23 19:59:14 +0000 |
commit | 2ccda87acabbb02f574bc3d56994076404bc689b (patch) | |
tree | 83967173eb01a2c4de511c4eb71440661a9ed8f1 /usr.sbin/bhyve/inout.c | |
parent | 549a5817c0ebaf4934c376d9bab4bf1bfefb0471 (diff) | |
download | FreeBSD-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.c | 25 |
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); |