KVM: nVMX: Apply addr size mask to effective address for VMX instructions
The address size of an instruction affects the effective address, not
the virtual/linear address. The final address may still be truncated,
e.g. to 32-bits outside of long mode, but that happens irrespective of
the address size, e.g. a 32-bit address size can yield a 64-bit virtual
address when using FS/GS with a non-zero base.
Fixes: 064aea7747
("KVM: nVMX: Decoding memory operands of VMX instructions")
Cc: stable@vger.kernel.org
Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
946c522b60
commit
8570f9e881
|
@ -4029,20 +4029,41 @@ int get_vmx_mem_address(struct kvm_vcpu *vcpu, unsigned long exit_qualification,
|
|||
if (index_is_valid)
|
||||
off += kvm_register_read(vcpu, index_reg)<<scaling;
|
||||
vmx_get_segment(vcpu, &s, seg_reg);
|
||||
*ret = s.base + off;
|
||||
|
||||
/*
|
||||
* The effective address, i.e. @off, of a memory operand is truncated
|
||||
* based on the address size of the instruction. Note that this is
|
||||
* the *effective address*, i.e. the address prior to accounting for
|
||||
* the segment's base.
|
||||
*/
|
||||
if (addr_size == 1) /* 32 bit */
|
||||
*ret &= 0xffffffff;
|
||||
off &= 0xffffffff;
|
||||
else if (addr_size == 0) /* 16 bit */
|
||||
off &= 0xffff;
|
||||
|
||||
/* Checks for #GP/#SS exceptions. */
|
||||
exn = false;
|
||||
if (is_long_mode(vcpu)) {
|
||||
/*
|
||||
* The virtual/linear address is never truncated in 64-bit
|
||||
* mode, e.g. a 32-bit address size can yield a 64-bit virtual
|
||||
* address when using FS/GS with a non-zero base.
|
||||
*/
|
||||
*ret = s.base + off;
|
||||
|
||||
/* Long mode: #GP(0)/#SS(0) if the memory address is in a
|
||||
* non-canonical form. This is the only check on the memory
|
||||
* destination for long mode!
|
||||
*/
|
||||
exn = is_noncanonical_address(*ret, vcpu);
|
||||
} else if (is_protmode(vcpu)) {
|
||||
/*
|
||||
* When not in long mode, the virtual/linear address is
|
||||
* unconditionally truncated to 32 bits regardless of the
|
||||
* address size.
|
||||
*/
|
||||
*ret = (s.base + off) & 0xffffffff;
|
||||
|
||||
/* Protected mode: apply checks for segment validity in the
|
||||
* following order:
|
||||
* - segment type check (#GP(0) may be thrown)
|
||||
|
|
Loading…
Reference in New Issue