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>
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;