mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 10:40:03 +01:00
x86/svm: Fix svm_nextrip_insn_length() when crossing the virtual boundary to 0
vmcb->nextrip can legitimately be less than vmcb->rip when execution wraps back around to 0. Instead, complain if the reported length is greater than 15 and use x86_decode_insn() as a fallback. While making changes here, fix two whitespace issues with the case labels. Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com> Reviewed-by: Jan Beulich <jbeulich@suse.com> Reviewed-by: Boris Ostrovsky <boris.ostrovsky@oracle.com> Release-acked-by: Wei Liu <wei.liu2@citrix.com>
This commit is contained in:
1 parent
58bd0c7985
commit
0745f665a5
1 file changed
+9
-6
@@ -30,18 +30,18 @@ static unsigned long svm_nextrip_insn_length(struct vcpu *v)
|
||||
{
|
||||
struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
|
||||
|
||||
if ( !cpu_has_svm_nrips || (vmcb->nextrip <= vmcb->rip) )
|
||||
if ( !cpu_has_svm_nrips )
|
||||
return 0;
|
||||
|
||||
#ifndef NDEBUG
|
||||
switch ( vmcb->exitcode )
|
||||
{
|
||||
case VMEXIT_CR0_READ... VMEXIT_DR15_WRITE:
|
||||
case VMEXIT_CR0_READ ... VMEXIT_DR15_WRITE:
|
||||
/* faults due to instruction intercepts */
|
||||
/* (exitcodes 84-95) are reserved */
|
||||
case VMEXIT_IDTR_READ ... VMEXIT_TR_WRITE:
|
||||
case VMEXIT_RDTSC ... VMEXIT_MSR:
|
||||
case VMEXIT_VMRUN ... VMEXIT_XSETBV:
|
||||
case VMEXIT_VMRUN ... VMEXIT_XSETBV:
|
||||
/* ...and the rest of the #VMEXITs */
|
||||
case VMEXIT_CR0_SEL_WRITE:
|
||||
case VMEXIT_EXCEPTION_BP:
|
||||
@@ -88,7 +88,8 @@ int __get_instruction_length_from_list(struct vcpu *v,
|
||||
struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
|
||||
struct hvm_emulate_ctxt ctxt;
|
||||
struct x86_emulate_state *state;
|
||||
unsigned int inst_len, j, modrm_rm, modrm_reg;
|
||||
unsigned long inst_len, j;
|
||||
unsigned int modrm_rm, modrm_reg;
|
||||
int modrm_mod;
|
||||
|
||||
/*
|
||||
@@ -96,7 +97,9 @@ int __get_instruction_length_from_list(struct vcpu *v,
|
||||
* hardware.
|
||||
*/
|
||||
#ifdef NDEBUG
|
||||
if ( (inst_len = svm_nextrip_insn_length(v)) != 0 )
|
||||
if ( (inst_len = svm_nextrip_insn_length(v)) > MAX_INST_LEN )
|
||||
gprintk(XENLOG_WARNING, "NRip reported insn_len %lu\n", insn_len);
|
||||
else if ( insn_len != 0 )
|
||||
return inst_len;
|
||||
|
||||
if ( vmcb->exitcode == VMEXIT_IOIO )
|
||||
@@ -120,7 +123,7 @@ int __get_instruction_length_from_list(struct vcpu *v,
|
||||
j = svm_nextrip_insn_length(v);
|
||||
if ( j && j != inst_len )
|
||||
{
|
||||
gprintk(XENLOG_WARNING, "insn-len[%02x]=%u (exp %u)\n",
|
||||
gprintk(XENLOG_WARNING, "insn-len[%02x]=%lu (exp %lu)\n",
|
||||
ctxt.ctxt.opcode, inst_len, j);
|
||||
return j;
|
||||
}
|
||||
|
||||