summaryrefslogtreecommitdiff
path: root/usr/src/uts
diff options
context:
space:
mode:
authorPatrick Mooney <pmooney@pfmooney.com>2020-11-06 07:38:53 +0000
committerPatrick Mooney <pmooney@oxide.computer>2020-11-13 02:45:02 +0000
commit04573c73a7ab1505c46b2c4db26bfde5176dd6a5 (patch)
tree6e563e61e8a93e9b189e72033e099a865c16bfb9 /usr/src/uts
parent3dfdac06b0c70e672dbe56a2f38ec05fc0254d07 (diff)
downloadillumos-joyent-04573c73a7ab1505c46b2c4db26bfde5176dd6a5.tar.gz
13286 bhyve ins/outs emulation misuses %rax
Reviewed by: Robert Mustacchi <rm@fingolfin.org> Reviewed by: Toomas Soome <tsoome@me.com> Approved by: Gordon Ross <gordon.w.ross@gmail.com>
Diffstat (limited to 'usr/src/uts')
-rw-r--r--usr/src/uts/i86pc/io/vmm/vmm_instruction_emul.c27
1 files changed, 17 insertions, 10 deletions
diff --git a/usr/src/uts/i86pc/io/vmm/vmm_instruction_emul.c b/usr/src/uts/i86pc/io/vmm/vmm_instruction_emul.c
index 0ac5e21fd0..18d756e363 100644
--- a/usr/src/uts/i86pc/io/vmm/vmm_instruction_emul.c
+++ b/usr/src/uts/i86pc/io/vmm/vmm_instruction_emul.c
@@ -2022,7 +2022,8 @@ vie_emulate_mmio(struct vie *vie, struct vm *vm, int vcpuid)
}
static int
-vie_emulate_inout_port(struct vie *vie, struct vm *vm, int vcpuid)
+vie_emulate_inout_port(struct vie *vie, struct vm *vm, int vcpuid,
+ uint32_t *eax)
{
uint32_t mask, val;
bool in;
@@ -2032,18 +2033,19 @@ vie_emulate_inout_port(struct vie *vie, struct vm *vm, int vcpuid)
in = (vie->inout.flags & INOUT_IN) != 0;
if (!in) {
- val = vie->inout.eax & mask;
+ val = *eax & mask;
}
if (vie->inout_req_state != VR_DONE) {
err = vm_ioport_access(vm, vcpuid, in, vie->inout.port,
vie->inout.bytes, &val);
+ val &= mask;
} else {
/*
* This port access was handled in userspace and the result was
* injected in to be handled now.
*/
- val = vie->inout_req_val;
+ val = vie->inout_req_val & mask;
vie->inout_req_state = VR_NONE;
err = 0;
}
@@ -2057,11 +2059,7 @@ vie_emulate_inout_port(struct vie *vie, struct vm *vm, int vcpuid)
}
if (in) {
- val &= mask;
- val |= (vie->inout.eax & ~mask);
- err = vm_set_register(vm, vcpuid, VM_REG_GUEST_RAX, val);
- KASSERT(err == 0, ("emulate_ioport: error %d setting guest "
- "rax register", err));
+ *eax = (*eax & ~mask) | val;
}
return (0);
}
@@ -2156,7 +2154,7 @@ vie_emulate_inout_str(struct vie *vie, struct vm *vm, int vcpuid)
vm_copyin(vm, vcpuid, copyinfo, &vie->inout.eax, bytes);
}
- err = vie_emulate_inout_port(vie, vm, vcpuid);
+ err = vie_emulate_inout_port(vie, vm, vcpuid, &vie->inout.eax);
if (err == 0 && in) {
vm_copyout(vm, vcpuid, &vie->inout.eax, copyinfo, bytes);
@@ -2217,7 +2215,16 @@ vie_emulate_inout(struct vie *vie, struct vm *vm, int vcpuid)
return (EINVAL);
}
- err = vie_emulate_inout_port(vie, vm, vcpuid);
+ err = vie_emulate_inout_port(vie, vm, vcpuid, &vie->inout.eax);
+ if (err == 0 && (vie->inout.flags & INOUT_IN) != 0) {
+ /*
+ * With the inX access now a success, the result needs
+ * to be stored in the guest %rax.
+ */
+ err = vm_set_register(vm, vcpuid, VM_REG_GUEST_RAX,
+ vie->inout.eax);
+ VERIFY0(err);
+ }
} else {
vie->status &= ~VIES_REPEAT;
err = vie_emulate_inout_str(vie, vm, vcpuid);