diff options
author | Patrick Mooney <pmooney@pfmooney.com> | 2020-11-06 07:38:53 +0000 |
---|---|---|
committer | Patrick Mooney <pmooney@oxide.computer> | 2020-11-13 02:45:02 +0000 |
commit | 04573c73a7ab1505c46b2c4db26bfde5176dd6a5 (patch) | |
tree | 6e563e61e8a93e9b189e72033e099a865c16bfb9 /usr/src/uts | |
parent | 3dfdac06b0c70e672dbe56a2f38ec05fc0254d07 (diff) | |
download | illumos-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.c | 27 |
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); |