mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 10:11:27 +01:00
x86emul: fix rIP handling
Deal with rIP just like with any other register: Truncate to designated width upon entry, write back the zero-extended 32-bit value when emulating 32-bit code, and leave the upper 48 bits unchanged for 16-bit code. Signed-off-by: Jan Beulich <jbeulich@suse.com> Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
This commit is contained in:
1 parent
b3132fc91b
commit
0640ffb67f
1 file changed
+19
-1
@@ -570,7 +570,6 @@ do{ asm volatile ( \
|
||||
/* Fetch next part of the instruction being emulated. */
|
||||
#define insn_fetch_bytes(_size) \
|
||||
({ unsigned long _x = 0, _eip = _regs.eip; \
|
||||
if ( !mode_64bit() ) _eip = (uint32_t)_eip; /* ignore upper dword */ \
|
||||
_regs.eip += (_size); /* real hardware doesn't truncate */ \
|
||||
generate_exception_if((uint8_t)(_regs.eip - \
|
||||
ctxt->regs->eip) > MAX_INST_LEN, \
|
||||
@@ -1492,6 +1491,10 @@ x86_emulate(
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Truncate rIP to def_ad_bytes (2 or 4) if necessary. */
|
||||
if ( def_ad_bytes < sizeof(_regs.eip) )
|
||||
_regs.eip &= (1UL << (def_ad_bytes * 8)) - 1;
|
||||
|
||||
/* Prefix bytes. */
|
||||
for ( ; ; )
|
||||
{
|
||||
@@ -3783,6 +3786,21 @@ x86_emulate(
|
||||
|
||||
/* Commit shadow register state. */
|
||||
_regs.eflags &= ~EFLG_RF;
|
||||
switch ( __builtin_expect(def_ad_bytes, sizeof(_regs.eip)) )
|
||||
{
|
||||
uint16_t ip;
|
||||
|
||||
case 2:
|
||||
ip = _regs.eip;
|
||||
_regs.eip = ctxt->regs->eip;
|
||||
*(uint16_t *)&_regs.eip = ip;
|
||||
break;
|
||||
#ifdef __x86_64__
|
||||
case 4:
|
||||
_regs.rip = _regs._eip;
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
*ctxt->regs = _regs;
|
||||
|
||||
done:
|
||||
|
||||