49 lines
2.1 KiB
Diff
49 lines
2.1 KiB
Diff
|
# Commit ee1cc4bfdca84d526805c4c72302c026f5e9cd94
|
||
|
# Date 2016-09-01 15:23:46 +0200
|
||
|
# Author Jan Beulich <jbeulich@suse.com>
|
||
|
# Committer Jan Beulich <jbeulich@suse.com>
|
||
|
x86/32on64: misc adjustments to call gate emulation
|
||
|
|
||
|
- There's no 32-bit displacement in 16-bit addressing mode.
|
||
|
- It is wrong to ASSERT() anything on parts of an instruction fetched
|
||
|
from guest memory.
|
||
|
- The two scaling bits of a SIB byte don't affect whether there is a
|
||
|
scaled index register or not.
|
||
|
|
||
|
Signed-off-by: Jan Beulich <jbeulich@suse.com>
|
||
|
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
|
||
|
|
||
|
--- a/xen/arch/x86/traps.c
|
||
|
+++ b/xen/arch/x86/traps.c
|
||
|
@@ -3176,7 +3176,7 @@ static void emulate_gate_op(struct cpu_u
|
||
|
sib = insn_fetch(u8, base, eip, limit);
|
||
|
|
||
|
modrm = (modrm & ~7) | (sib & 7);
|
||
|
- if ( (sib >>= 3) != 4 )
|
||
|
+ if ( ((sib >>= 3) & 7) != 4 )
|
||
|
opnd_off = *(unsigned long *)
|
||
|
decode_register(sib & 7, regs, 0);
|
||
|
opnd_off <<= sib >> 3;
|
||
|
@@ -3236,7 +3236,10 @@ static void emulate_gate_op(struct cpu_u
|
||
|
opnd_off += insn_fetch(s8, base, eip, limit);
|
||
|
break;
|
||
|
case 0x80:
|
||
|
- opnd_off += insn_fetch(s32, base, eip, limit);
|
||
|
+ if ( ad_bytes > 2 )
|
||
|
+ opnd_off += insn_fetch(s32, base, eip, limit);
|
||
|
+ else
|
||
|
+ opnd_off += insn_fetch(s16, base, eip, limit);
|
||
|
break;
|
||
|
}
|
||
|
if ( ad_bytes == 4 )
|
||
|
@@ -3273,8 +3276,7 @@ static void emulate_gate_op(struct cpu_u
|
||
|
#define ad_default ad_bytes
|
||
|
opnd_sel = insn_fetch(u16, base, opnd_off, limit);
|
||
|
#undef ad_default
|
||
|
- ASSERT((opnd_sel & ~3) == regs->error_code);
|
||
|
- if ( dpl < (opnd_sel & 3) )
|
||
|
+ if ( (opnd_sel & ~3) != regs->error_code || dpl < (opnd_sel & 3) )
|
||
|
{
|
||
|
do_guest_trap(TRAP_gp_fault, regs, 1);
|
||
|
return;
|