direct-io.hg

changeset 13327:558960865583

[XEN] More emulator fixes:
1. Emulate LAHF/SAHF instructions
2. #GP if instruction is longer than 15 bytes
3. Accept any number of prefix bytes (up to
15-byte total instruction length)
4. Repeated addr/data-size overrides are sticky
rather than toggling.

2,3,4 are based on a patch from Jan Beulich.

Signed-off-by: Keir Fraser <keir@xensource.com>
author kfraser@localhost.localdomain
date Thu Jan 11 10:10:16 2007 +0000 (2007-01-11)
parents dc0638bb4628
children 204a4a040a42
files xen/arch/x86/x86_emulate.c
line diff
     1.1 --- a/xen/arch/x86/x86_emulate.c	Thu Jan 11 10:08:14 2007 +0000
     1.2 +++ b/xen/arch/x86/x86_emulate.c	Thu Jan 11 10:10:16 2007 +0000
     1.3 @@ -107,7 +107,7 @@ static uint8_t opcode_table[256] = {
     1.4      ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
     1.5      ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
     1.6      /* 0x98 - 0x9F */
     1.7 -    0, 0, 0, 0, 0, 0, 0, 0,
     1.8 +    0, 0, 0, 0, 0, 0, ImplicitOps, ImplicitOps,
     1.9      /* 0xA0 - 0xA7 */
    1.10      ByteOp|ImplicitOps|Mov, ImplicitOps|Mov,
    1.11      ByteOp|ImplicitOps|Mov, ImplicitOps|Mov,
    1.12 @@ -230,7 +230,8 @@ struct operand {
    1.13  #define EFLG_CF (1<<0)
    1.14  
    1.15  /* Exception definitions. */
    1.16 -#define EXC_DE 0
    1.17 +#define EXC_DE  0
    1.18 +#define EXC_GP 13
    1.19  
    1.20  /*
    1.21   * Instruction emulation:
    1.22 @@ -394,11 +395,13 @@ do{ __asm__ __volatile__ (              
    1.23  
    1.24  /* Fetch next part of the instruction being emulated. */
    1.25  #define insn_fetch_bytes(_size)                                         \
    1.26 -({ unsigned long _x, _eip = _truncate_ea(_regs.eip, def_ad_bytes);      \
    1.27 +({ unsigned long _x, _eip = _regs.eip;                                  \
    1.28     if ( !mode_64bit() ) _eip = (uint32_t)_eip; /* ignore upper dword */ \
    1.29 +   _regs.eip += (_size); /* real hardware doesn't truncate */           \
    1.30 +   generate_exception_if((uint8_t)(_regs.eip - ctxt->regs->eip) > 15,   \
    1.31 +                         EXC_GP);                                       \
    1.32     rc = ops->insn_fetch(x86_seg_cs, _eip, &_x, (_size), ctxt);          \
    1.33     if ( rc ) goto done;                                                 \
    1.34 -   _regs.eip += (_size); /* real hardware doesn't truncate */           \
    1.35     _x;                                                                  \
    1.36  })
    1.37  #define insn_fetch_type(_type) ((_type)insn_fetch_bytes(sizeof(_type)))
    1.38 @@ -540,8 +543,8 @@ x86_emulate(
    1.39  
    1.40      uint8_t b, d, sib, sib_index, sib_base, twobyte = 0, rex_prefix = 0;
    1.41      uint8_t modrm, modrm_mod = 0, modrm_reg = 0, modrm_rm = 0;
    1.42 -    unsigned int op_bytes, ad_bytes, def_ad_bytes;
    1.43 -    unsigned int lock_prefix = 0, rep_prefix = 0, i;
    1.44 +    unsigned int op_bytes, def_op_bytes, ad_bytes, def_ad_bytes;
    1.45 +    unsigned int lock_prefix = 0, rep_prefix = 0;
    1.46      int rc = 0;
    1.47      struct operand src, dst;
    1.48  
    1.49 @@ -553,28 +556,25 @@ x86_emulate(
    1.50      ea.mem.seg = x86_seg_ds;
    1.51      ea.mem.off = 0;
    1.52  
    1.53 -    op_bytes = ad_bytes = def_ad_bytes = ctxt->address_bytes;
    1.54 +    op_bytes = def_op_bytes = ad_bytes = def_ad_bytes = ctxt->address_bytes;
    1.55      if ( op_bytes == 8 )
    1.56      {
    1.57 -        op_bytes = 4;
    1.58 +        op_bytes = def_op_bytes = 4;
    1.59  #ifndef __x86_64__
    1.60          return -1;
    1.61  #endif
    1.62      }
    1.63  
    1.64      /* Prefix bytes. */
    1.65 -    for ( i = 0; i < 8; i++ )
    1.66 +    for ( ; ; )
    1.67      {
    1.68          switch ( b = insn_fetch_type(uint8_t) )
    1.69          {
    1.70          case 0x66: /* operand-size override */
    1.71 -            op_bytes ^= 6;      /* switch between 2/4 bytes */
    1.72 +            op_bytes = def_op_bytes ^ 6;
    1.73              break;
    1.74          case 0x67: /* address-size override */
    1.75 -            if ( mode_64bit() )
    1.76 -                ad_bytes ^= 12; /* switch between 4/8 bytes */
    1.77 -            else
    1.78 -                ad_bytes ^= 6;  /* switch between 2/4 bytes */
    1.79 +            ad_bytes = def_ad_bytes ^ (mode_64bit() ? 12 : 6);
    1.80              break;
    1.81          case 0x2e: /* CS override */
    1.82              ea.mem.seg = x86_seg_cs;
    1.83 @@ -1288,6 +1288,14 @@ x86_emulate(
    1.84          dst.val  = dst.orig_val = *dst.reg;
    1.85          goto xchg;
    1.86  
    1.87 +    case 0x9e: /* sahf */
    1.88 +        *(uint8_t *)_regs.eflags = (((uint8_t *)&_regs.eax)[1] & 0xd7) | 0x02;
    1.89 +        break;
    1.90 +
    1.91 +    case 0x9f: /* lahf */
    1.92 +        ((uint8_t *)&_regs.eax)[1] = (_regs.eflags & 0xd7) | 0x02;
    1.93 +        break;
    1.94 +
    1.95      case 0xa0 ... 0xa1: /* mov mem.offs,{%al,%ax,%eax,%rax} */
    1.96          /* Source EA is not encoded via ModRM. */
    1.97          dst.type  = OP_REG;