Commit fede8076 authored by Paolo Bonzini's avatar Paolo Bonzini

KVM: x86: handle wrap around 32-bit address space

KVM is not handling the case where EIP wraps around the 32-bit address
space (that is, outside long mode).  This is needed both in vmx.c
and in emulate.c.  SVM with NRIPS is okay, but it can still print
an error to dmesg due to integer overflow.
Reported-by: default avatarNick Peterson <everdox@gmail.com>
Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
parent c4e115f0
...@@ -5798,6 +5798,8 @@ int x86_emulate_insn(struct x86_emulate_ctxt *ctxt) ...@@ -5798,6 +5798,8 @@ int x86_emulate_insn(struct x86_emulate_ctxt *ctxt)
} }
ctxt->eip = ctxt->_eip; ctxt->eip = ctxt->_eip;
if (ctxt->mode != X86EMUL_MODE_PROT64)
ctxt->eip = (u32)ctxt->_eip;
done: done:
if (rc == X86EMUL_PROPAGATE_FAULT) { if (rc == X86EMUL_PROPAGATE_FAULT) {
......
...@@ -319,9 +319,6 @@ static int skip_emulated_instruction(struct kvm_vcpu *vcpu) ...@@ -319,9 +319,6 @@ static int skip_emulated_instruction(struct kvm_vcpu *vcpu)
if (!kvm_emulate_instruction(vcpu, EMULTYPE_SKIP)) if (!kvm_emulate_instruction(vcpu, EMULTYPE_SKIP))
return 0; return 0;
} else { } else {
if (svm->next_rip - kvm_rip_read(vcpu) > MAX_INST_SIZE)
pr_err("%s: ip 0x%lx next 0x%llx\n",
__func__, kvm_rip_read(vcpu), svm->next_rip);
kvm_rip_write(vcpu, svm->next_rip); kvm_rip_write(vcpu, svm->next_rip);
} }
svm_set_interrupt_shadow(vcpu, 0); svm_set_interrupt_shadow(vcpu, 0);
......
...@@ -1555,7 +1555,7 @@ static int vmx_rtit_ctl_check(struct kvm_vcpu *vcpu, u64 data) ...@@ -1555,7 +1555,7 @@ static int vmx_rtit_ctl_check(struct kvm_vcpu *vcpu, u64 data)
static int skip_emulated_instruction(struct kvm_vcpu *vcpu) static int skip_emulated_instruction(struct kvm_vcpu *vcpu)
{ {
unsigned long rip; unsigned long rip, orig_rip;
/* /*
* Using VMCS.VM_EXIT_INSTRUCTION_LEN on EPT misconfig depends on * Using VMCS.VM_EXIT_INSTRUCTION_LEN on EPT misconfig depends on
...@@ -1567,8 +1567,17 @@ static int skip_emulated_instruction(struct kvm_vcpu *vcpu) ...@@ -1567,8 +1567,17 @@ static int skip_emulated_instruction(struct kvm_vcpu *vcpu)
*/ */
if (!static_cpu_has(X86_FEATURE_HYPERVISOR) || if (!static_cpu_has(X86_FEATURE_HYPERVISOR) ||
to_vmx(vcpu)->exit_reason != EXIT_REASON_EPT_MISCONFIG) { to_vmx(vcpu)->exit_reason != EXIT_REASON_EPT_MISCONFIG) {
rip = kvm_rip_read(vcpu); orig_rip = kvm_rip_read(vcpu);
rip += vmcs_read32(VM_EXIT_INSTRUCTION_LEN); rip = orig_rip + vmcs_read32(VM_EXIT_INSTRUCTION_LEN);
#ifdef CONFIG_X86_64
/*
* We need to mask out the high 32 bits of RIP if not in 64-bit
* mode, but just finding out that we are in 64-bit mode is
* quite expensive. Only do it if there was a carry.
*/
if (unlikely(((rip ^ orig_rip) >> 31) == 3) && !is_64_bit_mode(vcpu))
rip = (u32)rip;
#endif
kvm_rip_write(vcpu, rip); kvm_rip_write(vcpu, rip);
} else { } else {
if (!kvm_emulate_instruction(vcpu, EMULTYPE_SKIP)) if (!kvm_emulate_instruction(vcpu, EMULTYPE_SKIP))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment