diff options
author | Neel Natu <neel@FreeBSD.org> | 2014-05-23 19:59:14 +0000 |
---|---|---|
committer | Neel Natu <neel@FreeBSD.org> | 2014-05-23 19:59:14 +0000 |
commit | a7424861fb6b4ee710fde4c6e0505dc3eb33ed1c (patch) | |
tree | 83967173eb01a2c4de511c4eb71440661a9ed8f1 /usr.sbin | |
parent | fa2f411c4e8d8223ebab42f1ecf8f7ad8f155f75 (diff) | |
download | src-a7424861fb6b4ee710fde4c6e0505dc3eb33ed1c.tar.gz src-a7424861fb6b4ee710fde4c6e0505dc3eb33ed1c.zip |
Check for alignment check violation when processing in/out string instructions.
Notes
Notes:
svn path=/head/; revision=266595
Diffstat (limited to 'usr.sbin')
-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 c2bb50a7dd07..0bbcde1bb786 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); |