ia64/xen-unstable

changeset 16695:4c1a0d2a318d

Fix x86_emulate() handling of imul with immediate operands.

This fixes a repeatable crash in RHEL 4.2 ext2 filesystem during boot.

Signed-off-by: Gary Grebus <ggrebus@virtualiron.com>
Signed-off-by: Ben Guthro <bguthro@virtualiron.com>
author Keir Fraser <keir.fraser@citrix.com>
date Wed Jan 09 10:09:04 2008 +0000 (2008-01-09)
parents 15cfd1f8fa38
children b5b3e27f1af3
files xen/arch/x86/x86_emulate.c
line diff
     1.1 --- a/xen/arch/x86/x86_emulate.c	Tue Jan 08 16:45:08 2008 +0000
     1.2 +++ b/xen/arch/x86/x86_emulate.c	Wed Jan 09 10:09:04 2008 +0000
     1.3 @@ -103,8 +103,8 @@ static uint8_t opcode_table[256] = {
     1.4      ImplicitOps, ImplicitOps, DstReg|SrcMem|ModRM, DstReg|SrcMem16|ModRM|Mov,
     1.5      0, 0, 0, 0,
     1.6      /* 0x68 - 0x6F */
     1.7 -    ImplicitOps|Mov, DstMem|SrcImm|ModRM|Mov,
     1.8 -    ImplicitOps|Mov, DstMem|SrcImmByte|ModRM|Mov,
     1.9 +    ImplicitOps|Mov, DstReg|SrcImm|ModRM|Mov,
    1.10 +    ImplicitOps|Mov, DstReg|SrcImmByte|ModRM|Mov,
    1.11      ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
    1.12      /* 0x70 - 0x77 */
    1.13      ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
    1.14 @@ -1331,34 +1331,37 @@ x86_emulate(
    1.15  
    1.16      case 0x69: /* imul imm16/32 */
    1.17      case 0x6b: /* imul imm8 */ {
    1.18 -        unsigned long reg = *(long *)decode_register(modrm_reg, &_regs, 0);
    1.19 +        unsigned long src1; /* ModR/M source operand */
    1.20 +        if ( ea.type == OP_REG )
    1.21 +            src1 = *ea.reg;
    1.22 +        else if ( (rc = ops->read(ea.mem.seg, ea.mem.off,
    1.23 +                                  &src1, op_bytes, ctxt)) )
    1.24 +            goto done;
    1.25          _regs.eflags &= ~(EFLG_OF|EFLG_CF);
    1.26          switch ( dst.bytes )
    1.27          {
    1.28          case 2:
    1.29              dst.val = ((uint32_t)(int16_t)src.val *
    1.30 -                       (uint32_t)(int16_t)reg);
    1.31 +                       (uint32_t)(int16_t)src1);
    1.32              if ( (int16_t)dst.val != (uint32_t)dst.val )
    1.33                  _regs.eflags |= EFLG_OF|EFLG_CF;
    1.34              break;
    1.35  #ifdef __x86_64__
    1.36          case 4:
    1.37              dst.val = ((uint64_t)(int32_t)src.val *
    1.38 -                       (uint64_t)(int32_t)reg);
    1.39 +                       (uint64_t)(int32_t)src1);
    1.40              if ( (int32_t)dst.val != dst.val )
    1.41                  _regs.eflags |= EFLG_OF|EFLG_CF;
    1.42              break;
    1.43  #endif
    1.44          default: {
    1.45 -            unsigned long m[2] = { src.val, reg };
    1.46 +            unsigned long m[2] = { src.val, src1 };
    1.47              if ( imul_dbl(m) )
    1.48                  _regs.eflags |= EFLG_OF|EFLG_CF;
    1.49              dst.val = m[0];
    1.50              break;
    1.51          }
    1.52          }
    1.53 -        dst.type = OP_REG;
    1.54 -        dst.reg  = decode_register(modrm_reg, &_regs, 0);
    1.55          break;
    1.56      }
    1.57