direct-io.hg

changeset 11625:8905ffc1a3c8

[XEN] Fix x86_emulate and hvm-mmio-insn-len decoders
to properly add cs<<4 to eip only when guest is in real
mode (or vm86 mode).
Remove bogus test-and-fail from hvm-mmio-insn-len decoder.
Signed-off-by: Keir Fraser <keir@xensource.com>
author kfraser@localhost.localdomain
date Wed Sep 27 09:29:46 2006 +0100 (2006-09-27)
parents bd811e94d293
children 5ab400346b13
files xen/arch/x86/hvm/instrlen.c xen/arch/x86/x86_emulate.c
line diff
     1.1 --- a/xen/arch/x86/hvm/instrlen.c	Tue Sep 26 19:50:07 2006 +0100
     1.2 +++ b/xen/arch/x86/hvm/instrlen.c	Wed Sep 27 09:29:46 2006 +0100
     1.3 @@ -196,26 +196,17 @@ static uint8_t twobyte_table[256] = {
     1.4  
     1.5  /* 
     1.6   * insn_fetch - fetch the next 1 to 4 bytes from instruction stream 
     1.7 - * 
     1.8   * @_type:   u8, u16, u32, s8, s16, or s32
     1.9   * @_size:   1, 2, or 4 bytes
    1.10 - * @_eip:    address to fetch from guest memory
    1.11 - * @_length: increments the current instruction length counter by _size
    1.12 - *
    1.13 - * This is used internally by hvm_instruction_length to fetch the next byte,
    1.14 - * word, or dword from guest memory at location _eip.  we currently use a local
    1.15 - * unsigned long as the storage buffer since the most bytes we're gonna get
    1.16 - * is limited to 4.
    1.17   */
    1.18 -#define insn_fetch(_type, _size, _eip, _length)                         \
    1.19 -({  unsigned long _x;                                                   \
    1.20 -        if ((rc = inst_copy_from_guest((unsigned char *)(&(_x)),        \
    1.21 -                (unsigned long)(_eip), _size))                          \
    1.22 -                    != _size)                                           \
    1.23 -        goto done;                                                      \
    1.24 -    (_eip) += (_size);                                                  \
    1.25 -    (_length) += (_size);                                               \
    1.26 -    (_type)_x;                                                          \
    1.27 +#define insn_fetch(_type, _size)                                        \
    1.28 +({ unsigned long _x, _ptr = _regs.eip;                                  \
    1.29 +   if ( mode == X86EMUL_MODE_REAL ) _ptr += _regs.cs << 4;              \
    1.30 +   rc = inst_copy_from_guest((unsigned char *)(&(_x)), _ptr, _size);    \
    1.31 +   if ( rc != _size ) goto done;                                        \
    1.32 +   _regs.eip += (_size);                                                \
    1.33 +   length += (_size);                                                   \
    1.34 +   (_type)_x;                                                           \
    1.35  })
    1.36  
    1.37  /**
    1.38 @@ -231,7 +222,7 @@ int hvm_instruction_length(struct cpu_us
    1.39  {
    1.40      uint8_t b, d, 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, lock_prefix = 0, rep_prefix = 0, i;
    1.43 +    unsigned int op_bytes, ad_bytes, i;
    1.44      int rc = 0;
    1.45      int length = 0;
    1.46      unsigned int tmp;
    1.47 @@ -239,10 +230,6 @@ int hvm_instruction_length(struct cpu_us
    1.48      /* Shadow copy of register state. Committed on successful emulation. */
    1.49      struct cpu_user_regs _regs = *regs;
    1.50  
    1.51 -    /* include CS for 16-bit modes */
    1.52 -    if (mode == X86EMUL_MODE_REAL || mode == X86EMUL_MODE_PROT16)
    1.53 -        _regs.eip += (_regs.cs << 4);
    1.54 -
    1.55      switch ( mode )
    1.56      {
    1.57      case X86EMUL_MODE_REAL:
    1.58 @@ -265,7 +252,7 @@ int hvm_instruction_length(struct cpu_us
    1.59      /* Legacy prefixes. */
    1.60      for ( i = 0; i < 8; i++ )
    1.61      {
    1.62 -        switch ( b = insn_fetch(uint8_t, 1, _regs.eip, length) )
    1.63 +        switch ( b = insn_fetch(uint8_t, 1) )
    1.64          {
    1.65          case 0x66: /* operand-size override */
    1.66              op_bytes ^= 6;      /* switch between 2/4 bytes */
    1.67 @@ -282,13 +269,8 @@ int hvm_instruction_length(struct cpu_us
    1.68          case 0x64: /* FS override */
    1.69          case 0x65: /* GS override */
    1.70          case 0x36: /* SS override */
    1.71 -            break;
    1.72          case 0xf0: /* LOCK */
    1.73 -            lock_prefix = 1;
    1.74 -            break;
    1.75          case 0xf3: /* REP/REPE/REPZ */
    1.76 -            rep_prefix = 1;
    1.77 -            break;
    1.78          case 0xf2: /* REPNE/REPNZ */
    1.79              break;
    1.80          default:
    1.81 @@ -297,12 +279,6 @@ int hvm_instruction_length(struct cpu_us
    1.82      }
    1.83  done_prefixes:
    1.84  
    1.85 -    /* Note quite the same as 80386 real mode, but hopefully good enough. */
    1.86 -    if ( (mode == X86EMUL_MODE_REAL) && (ad_bytes != 2) ) {
    1.87 -        printf("sonofabitch!! we don't support 32-bit addresses in realmode\n");
    1.88 -        goto cannot_emulate;
    1.89 -    }
    1.90 -
    1.91      /* REX prefix. */
    1.92      if ( (mode == X86EMUL_MODE_PROT64) && ((b & 0xf0) == 0x40) )
    1.93      {
    1.94 @@ -311,7 +287,7 @@ done_prefixes:
    1.95              op_bytes = 8;          /* REX.W */
    1.96          modrm_reg = (b & 4) << 1;  /* REX.R */
    1.97          /* REX.B and REX.X do not need to be decoded. */
    1.98 -        b = insn_fetch(uint8_t, 1, _regs.eip, length);
    1.99 +        b = insn_fetch(uint8_t, 1);
   1.100      }
   1.101  
   1.102      /* Opcode byte(s). */
   1.103 @@ -322,7 +298,7 @@ done_prefixes:
   1.104          if ( b == 0x0f )
   1.105          {
   1.106              twobyte = 1;
   1.107 -            b = insn_fetch(uint8_t, 1, _regs.eip, length);
   1.108 +            b = insn_fetch(uint8_t, 1);
   1.109              d = twobyte_table[b];
   1.110          }
   1.111  
   1.112 @@ -334,7 +310,7 @@ done_prefixes:
   1.113      /* ModRM and SIB bytes. */
   1.114      if ( d & ModRM )
   1.115      {
   1.116 -        modrm = insn_fetch(uint8_t, 1, _regs.eip, length);
   1.117 +        modrm = insn_fetch(uint8_t, 1);
   1.118          modrm_mod |= (modrm & 0xc0) >> 6;
   1.119          modrm_reg |= (modrm & 0x38) >> 3;
   1.120          modrm_rm  |= (modrm & 0x07);
   1.121 @@ -374,7 +350,7 @@ done_prefixes:
   1.122              {
   1.123              case 0:
   1.124                  if ( (modrm_rm == 4) && 
   1.125 -                     (((insn_fetch(uint8_t, 1, _regs.eip, length)) & 7) 
   1.126 +                     (((insn_fetch(uint8_t, 1)) & 7) 
   1.127                          == 5) )
   1.128                  {
   1.129                      length += 4;
   1.130 @@ -389,7 +365,7 @@ done_prefixes:
   1.131              case 1:
   1.132                  if ( modrm_rm == 4 )
   1.133                  {
   1.134 -                    insn_fetch(uint8_t, 1, _regs.eip, length);
   1.135 +                    insn_fetch(uint8_t, 1);
   1.136                  }
   1.137                  length += 1;
   1.138                  _regs.eip += 1; /* skip disp8 */
   1.139 @@ -397,7 +373,7 @@ done_prefixes:
   1.140              case 2:
   1.141                  if ( modrm_rm == 4 )
   1.142                  {
   1.143 -                    insn_fetch(uint8_t, 1, _regs.eip, length);
   1.144 +                    insn_fetch(uint8_t, 1);
   1.145                  }
   1.146                  length += 4;
   1.147                  _regs.eip += 4; /* skip disp32 */
   1.148 @@ -423,13 +399,13 @@ done_prefixes:
   1.149          /* NB. Immediates are sign-extended as necessary. */
   1.150          switch ( tmp )
   1.151          {
   1.152 -        case 1: insn_fetch(int8_t,  1, _regs.eip, length); break;
   1.153 -        case 2: insn_fetch(int16_t, 2, _regs.eip, length); break;
   1.154 -        case 4: insn_fetch(int32_t, 4, _regs.eip, length); break;
   1.155 +        case 1: insn_fetch(int8_t,  1); break;
   1.156 +        case 2: insn_fetch(int16_t, 2); break;
   1.157 +        case 4: insn_fetch(int32_t, 4); break;
   1.158          }
   1.159          break;
   1.160      case SrcImmByte:
   1.161 -        insn_fetch(int8_t,  1, _regs.eip, length);
   1.162 +        insn_fetch(int8_t,  1);
   1.163          break;
   1.164      }
   1.165  
   1.166 @@ -455,9 +431,9 @@ done_prefixes:
   1.167              if ( tmp == 8 ) tmp = 4;
   1.168              switch ( tmp )
   1.169              {
   1.170 -            case 1: insn_fetch(int8_t,  1, _regs.eip, length); break;
   1.171 -            case 2: insn_fetch(int16_t, 2, _regs.eip, length); break;
   1.172 -            case 4: insn_fetch(int32_t, 4, _regs.eip, length); break;
   1.173 +            case 1: insn_fetch(int8_t,  1); break;
   1.174 +            case 2: insn_fetch(int16_t, 2); break;
   1.175 +            case 4: insn_fetch(int32_t, 4); break;
   1.176              }
   1.177              goto done;
   1.178          }
     2.1 --- a/xen/arch/x86/x86_emulate.c	Tue Sep 26 19:50:07 2006 +0100
     2.2 +++ b/xen/arch/x86/x86_emulate.c	Wed Sep 27 09:29:46 2006 +0100
     2.3 @@ -368,12 +368,13 @@ do{ __asm__ __volatile__ (              
     2.4  #endif /* __i386__ */
     2.5  
     2.6  /* Fetch next part of the instruction being emulated. */
     2.7 -#define insn_fetch(_type, _size, _eip)                                  \
     2.8 -({ unsigned long _x;                                                    \
     2.9 -   rc = ops->read_std((unsigned long)(_eip), &_x, (_size), ctxt);       \
    2.10 +#define insn_fetch(_type, _size)                                        \
    2.11 +({ unsigned long _x, _ptr = _regs.eip;                                  \
    2.12 +   if ( mode == X86EMUL_MODE_REAL ) _ptr += _regs.cs << 4;              \
    2.13 +   rc = ops->read_std(_ptr, &_x, (_size), ctxt);                        \
    2.14     if ( rc != 0 )                                                       \
    2.15         goto done;                                                       \
    2.16 -   (_eip) += (_size);                                                   \
    2.17 +   _regs.eip += (_size);                                                \
    2.18     (_type)_x;                                                           \
    2.19  })
    2.20  
    2.21 @@ -478,7 +479,7 @@ x86_emulate_memop(
    2.22      /* Legacy prefixes. */
    2.23      for ( i = 0; i < 8; i++ )
    2.24      {
    2.25 -        switch ( b = insn_fetch(uint8_t, 1, _regs.eip) )
    2.26 +        switch ( b = insn_fetch(uint8_t, 1) )
    2.27          {
    2.28          case 0x66: /* operand-size override */
    2.29              op_bytes ^= 6;      /* switch between 2/4 bytes */
    2.30 @@ -529,7 +530,7 @@ x86_emulate_memop(
    2.31              op_bytes = 8;          /* REX.W */
    2.32          modrm_reg = (b & 4) << 1;  /* REX.R */
    2.33          /* REX.B and REX.X do not need to be decoded. */
    2.34 -        b = insn_fetch(uint8_t, 1, _regs.eip);
    2.35 +        b = insn_fetch(uint8_t, 1);
    2.36      }
    2.37  
    2.38      /* Opcode byte(s). */
    2.39 @@ -540,7 +541,7 @@ x86_emulate_memop(
    2.40          if ( b == 0x0f )
    2.41          {
    2.42              twobyte = 1;
    2.43 -            b = insn_fetch(uint8_t, 1, _regs.eip);
    2.44 +            b = insn_fetch(uint8_t, 1);
    2.45              d = twobyte_table[b];
    2.46          }
    2.47  
    2.48 @@ -552,7 +553,7 @@ x86_emulate_memop(
    2.49      /* ModRM and SIB bytes. */
    2.50      if ( d & ModRM )
    2.51      {
    2.52 -        modrm = insn_fetch(uint8_t, 1, _regs.eip);
    2.53 +        modrm = insn_fetch(uint8_t, 1);
    2.54          modrm_mod |= (modrm & 0xc0) >> 6;
    2.55          modrm_reg |= (modrm & 0x38) >> 3;
    2.56          modrm_rm  |= (modrm & 0x07);
    2.57 @@ -587,19 +588,19 @@ x86_emulate_memop(
    2.58              {
    2.59              case 0:
    2.60                  if ( (modrm_rm == 4) && 
    2.61 -                     (((sib = insn_fetch(uint8_t, 1, _regs.eip)) & 7) == 5) )
    2.62 +                     (((sib = insn_fetch(uint8_t, 1)) & 7) == 5) )
    2.63                      _regs.eip += 4; /* skip disp32 specified by SIB.base */
    2.64                  else if ( modrm_rm == 5 )
    2.65                      _regs.eip += 4; /* skip disp32 */
    2.66                  break;
    2.67              case 1:
    2.68                  if ( modrm_rm == 4 )
    2.69 -                    sib = insn_fetch(uint8_t, 1, _regs.eip);
    2.70 +                    sib = insn_fetch(uint8_t, 1);
    2.71                  _regs.eip += 1; /* skip disp8 */
    2.72                  break;
    2.73              case 2:
    2.74                  if ( modrm_rm == 4 )
    2.75 -                    sib = insn_fetch(uint8_t, 1, _regs.eip);
    2.76 +                    sib = insn_fetch(uint8_t, 1);
    2.77                  _regs.eip += 4; /* skip disp32 */
    2.78                  break;
    2.79              }
    2.80 @@ -691,16 +692,16 @@ x86_emulate_memop(
    2.81          /* NB. Immediates are sign-extended as necessary. */
    2.82          switch ( src.bytes )
    2.83          {
    2.84 -        case 1: src.val = insn_fetch(int8_t,  1, _regs.eip); break;
    2.85 -        case 2: src.val = insn_fetch(int16_t, 2, _regs.eip); break;
    2.86 -        case 4: src.val = insn_fetch(int32_t, 4, _regs.eip); break;
    2.87 +        case 1: src.val = insn_fetch(int8_t,  1); break;
    2.88 +        case 2: src.val = insn_fetch(int16_t, 2); break;
    2.89 +        case 4: src.val = insn_fetch(int32_t, 4); break;
    2.90          }
    2.91          break;
    2.92      case SrcImmByte:
    2.93          src.type  = OP_IMM;
    2.94          src.ptr   = (unsigned long *)_regs.eip;
    2.95          src.bytes = 1;
    2.96 -        src.val   = insn_fetch(int8_t,  1, _regs.eip);
    2.97 +        src.val   = insn_fetch(int8_t,  1);
    2.98          break;
    2.99      }
   2.100  
   2.101 @@ -840,9 +841,9 @@ x86_emulate_memop(
   2.102              if ( src.bytes == 8 ) src.bytes = 4;
   2.103              switch ( src.bytes )
   2.104              {
   2.105 -            case 1: src.val = insn_fetch(int8_t,  1, _regs.eip); break;
   2.106 -            case 2: src.val = insn_fetch(int16_t, 2, _regs.eip); break;
   2.107 -            case 4: src.val = insn_fetch(int32_t, 4, _regs.eip); break;
   2.108 +            case 1: src.val = insn_fetch(int8_t,  1); break;
   2.109 +            case 2: src.val = insn_fetch(int16_t, 2); break;
   2.110 +            case 4: src.val = insn_fetch(int32_t, 4); break;
   2.111              }
   2.112              goto test;
   2.113          case 2: /* not */