ia64/xen-unstable

changeset 14849:5f6b31335cda

hvm: Fix some bugs in mmio decoder

Some instructions, like "add $imm8, r/m16"/"MOV $imm32, r/m64" require
the src immediate operand be sign-extented befere the op is executed,
but this is omitted in the current Xcode. The patch fixes this.
The patch also fixes an issue in handling address-size override
prefix, and fixes an issue in get_immediate().

Signed-off-by: Dexuan Cui <dexuan.cui@intel.com>
author kfraser@localhost.localdomain
date Fri Apr 13 12:30:04 2007 +0100 (2007-04-13)
parents ba8d4bc2435a
children d51b3bc40ca5
files xen/arch/x86/hvm/platform.c
line diff
     1.1 --- a/xen/arch/x86/hvm/platform.c	Fri Apr 13 12:29:06 2007 +0100
     1.2 +++ b/xen/arch/x86/hvm/platform.c	Fri Apr 13 12:30:04 2007 +0100
     1.3 @@ -221,7 +221,6 @@ static inline unsigned long get_immediat
     1.4  
     1.5      inst++; //skip ModR/M byte
     1.6      if ( ad_size != WORD && mod != 3 && rm == 4 ) {
     1.7 -        rm = *inst & 7;
     1.8          inst++; //skip SIB byte
     1.9      }
    1.10  
    1.11 @@ -257,6 +256,33 @@ static inline unsigned long get_immediat
    1.12      return val;
    1.13  }
    1.14  
    1.15 +/* Some instructions, like "add $imm8, r/m16"/"MOV $imm32, r/m64" require
    1.16 + * the src immediate operand be sign-extented befere the op is executed. Here
    1.17 + * we always sign-extend the operand to a "unsigned long" variable.
    1.18 + *
    1.19 + * Note: to simplify the logic here, the sign-extension here may be performed
    1.20 + * redundantly against some instructions, like "MOV $imm16, r/m16" -- however
    1.21 + * this is harmless, since we always remember the operand's size.
    1.22 + */
    1.23 +static inline unsigned long get_immediate_sign_ext(int ad_size,
    1.24 +                                                   const unsigned char *inst,
    1.25 +                                                   int op_size)
    1.26 +{
    1.27 +    unsigned long result = get_immediate(ad_size, inst, op_size);
    1.28 +
    1.29 +    if ( op_size == QUAD )
    1.30 +        op_size = LONG;
    1.31 +
    1.32 +    ASSERT( op_size == BYTE || op_size == WORD || op_size == LONG );
    1.33 +
    1.34 +    if ( result & (1UL << ((8*op_size) - 1)) )
    1.35 +    {
    1.36 +        unsigned long mask = ~0UL >> (8 * (sizeof(mask) - op_size));
    1.37 +        result = ~mask | (result & mask);
    1.38 +    }
    1.39 +    return result;
    1.40 +}
    1.41 +
    1.42  static inline int get_index(const unsigned char *inst, unsigned char rex)
    1.43  {
    1.44      int mod, reg, rm;
    1.45 @@ -394,7 +420,9 @@ static int mmio_decode(int address_bytes
    1.46      case 8:
    1.47          if ( *op_size == 0 )
    1.48              *op_size = rex & 0x8 ? QUAD : LONG;
    1.49 -        if ( *ad_size == 0 )
    1.50 +        if ( *ad_size == WORD )
    1.51 +            *ad_size = LONG;
    1.52 +        else if ( *ad_size == 0 )
    1.53              *ad_size = QUAD;
    1.54          break;
    1.55  #endif
    1.56 @@ -520,10 +548,10 @@ static int mmio_decode(int address_bytes
    1.57          /* opcode 0x83 always has a single byte operand */
    1.58          if ( opcode[0] == 0x83 )
    1.59              mmio_op->immediate =
    1.60 -                (signed char)get_immediate(*ad_size, opcode + 1, BYTE);
    1.61 +                get_immediate_sign_ext(*ad_size, opcode + 1, BYTE);
    1.62          else
    1.63              mmio_op->immediate =
    1.64 -                get_immediate(*ad_size, opcode + 1, *op_size);
    1.65 +                get_immediate_sign_ext(*ad_size, opcode + 1, *op_size);
    1.66  
    1.67          mmio_op->operand[0] = mk_operand(size_reg, 0, 0, IMMEDIATE);
    1.68          mmio_op->operand[1] = mk_operand(size_reg, 0, 0, MEMORY);
    1.69 @@ -677,7 +705,7 @@ static int mmio_decode(int address_bytes
    1.70  
    1.71              mmio_op->operand[0] = mk_operand(*op_size, 0, 0, IMMEDIATE);
    1.72              mmio_op->immediate =
    1.73 -                    get_immediate(*ad_size, opcode + 1, *op_size);
    1.74 +                    get_immediate_sign_ext(*ad_size, opcode + 1, *op_size);
    1.75              mmio_op->operand[1] = mk_operand(*op_size, 0, 0, MEMORY);
    1.76  
    1.77              return DECODE_success;
    1.78 @@ -699,7 +727,7 @@ static int mmio_decode(int address_bytes
    1.79  
    1.80              mmio_op->operand[0] = mk_operand(size_reg, 0, 0, IMMEDIATE);
    1.81              mmio_op->immediate =
    1.82 -                    get_immediate(*ad_size, opcode + 1, *op_size);
    1.83 +                    get_immediate_sign_ext(*ad_size, opcode + 1, *op_size);
    1.84              mmio_op->operand[1] = mk_operand(size_reg, 0, 0, MEMORY);
    1.85  
    1.86              return DECODE_success;