direct-io.hg

changeset 11534:38765166ad7a

[XEN] Fix the emulation of instructions in vm86 mode. It fetches
them using cs and eip instead of only eip. This makes it at least
possible to use the i945GM vesa bios from the running system.

Signed-off-by: Bastian Blank <waldi@debian.org>
author kfraser@localhost.localdomain
date Tue Sep 19 11:13:10 2006 +0100 (2006-09-19)
parents e5d29225a8d1
children c5d4d47bbeb8
files xen/arch/x86/traps.c
line diff
     1.1 --- a/xen/arch/x86/traps.c	Tue Sep 19 11:08:11 2006 +0100
     1.2 +++ b/xen/arch/x86/traps.c	Tue Sep 19 11:13:10 2006 +0100
     1.3 @@ -1028,9 +1028,11 @@ static inline unsigned char inb_user(
     1.4      (admin_io_okay(_p, 4, _d, _r) ? outl(_v, _p) : ((void)0))
     1.5  
     1.6  /* Instruction fetch with error handling. */
     1.7 -#define insn_fetch(_type, _size, _ptr)                                      \
     1.8 -({  unsigned long _rc, _x;                                                  \
     1.9 -    if ( (_rc = copy_from_user(&_x, (_type *)eip, sizeof(_type))) != 0 )    \
    1.10 +#define insn_fetch(_type, _size, cs, eip)                                   \
    1.11 +({  unsigned long _rc, _x, _ptr = eip;                                      \
    1.12 +    if ( vm86_mode(regs) )                                                  \
    1.13 +        _ptr += cs << 4;                                                    \
    1.14 +    if ( (_rc = copy_from_user(&_x, (_type *)_ptr, sizeof(_type))) != 0 )   \
    1.15      {                                                                       \
    1.16          propagate_page_fault(eip + sizeof(_type) - _rc, 0);                 \
    1.17          return EXCRET_fault_fixed;                                          \
    1.18 @@ -1040,7 +1042,7 @@ static inline unsigned char inb_user(
    1.19  static int emulate_privileged_op(struct cpu_user_regs *regs)
    1.20  {
    1.21      struct vcpu *v = current;
    1.22 -    unsigned long *reg, eip = regs->eip, res;
    1.23 +    unsigned long *reg, eip = regs->eip, cs = regs->cs, res;
    1.24      u8 opcode, modrm_reg = 0, modrm_rm = 0, rep_prefix = 0;
    1.25      unsigned int port, i, op_bytes = 4, data, rc;
    1.26      u32 l, h;
    1.27 @@ -1048,7 +1050,7 @@ static int emulate_privileged_op(struct 
    1.28      /* Legacy prefixes. */
    1.29      for ( i = 0; i < 8; i++ )
    1.30      {
    1.31 -        switch ( opcode = insn_fetch(u8, 1, eip) )
    1.32 +        switch ( opcode = insn_fetch(u8, 1, cs, eip) )
    1.33          {
    1.34          case 0x66: /* operand-size override */
    1.35              op_bytes ^= 6; /* switch between 2/4 bytes */
    1.36 @@ -1080,7 +1082,7 @@ static int emulate_privileged_op(struct 
    1.37          modrm_rm  = (opcode & 1) << 3;  /* REX.B */
    1.38  
    1.39          /* REX.W and REX.X do not need to be decoded. */
    1.40 -        opcode = insn_fetch(u8, 1, eip);
    1.41 +        opcode = insn_fetch(u8, 1, cs, eip);
    1.42      }
    1.43  #endif
    1.44      
    1.45 @@ -1162,7 +1164,7 @@ static int emulate_privileged_op(struct 
    1.46      case 0xe4: /* IN imm8,%al */
    1.47          op_bytes = 1;
    1.48      case 0xe5: /* IN imm8,%eax */
    1.49 -        port = insn_fetch(u8, 1, eip);
    1.50 +        port = insn_fetch(u8, 1, cs, eip);
    1.51      exec_in:
    1.52          if ( !guest_io_okay(port, op_bytes, v, regs) )
    1.53              goto fail;
    1.54 @@ -1191,7 +1193,7 @@ static int emulate_privileged_op(struct 
    1.55      case 0xe6: /* OUT %al,imm8 */
    1.56          op_bytes = 1;
    1.57      case 0xe7: /* OUT %eax,imm8 */
    1.58 -        port = insn_fetch(u8, 1, eip);
    1.59 +        port = insn_fetch(u8, 1, cs, eip);
    1.60      exec_out:
    1.61          if ( !guest_io_okay(port, op_bytes, v, regs) )
    1.62              goto fail;
    1.63 @@ -1240,7 +1242,7 @@ static int emulate_privileged_op(struct 
    1.64          goto fail;
    1.65  
    1.66      /* Privileged (ring 0) instructions. */
    1.67 -    opcode = insn_fetch(u8, 1, eip);
    1.68 +    opcode = insn_fetch(u8, 1, cs, eip);
    1.69      switch ( opcode )
    1.70      {
    1.71      case 0x06: /* CLTS */
    1.72 @@ -1258,7 +1260,7 @@ static int emulate_privileged_op(struct 
    1.73          break;
    1.74  
    1.75      case 0x20: /* MOV CR?,<reg> */
    1.76 -        opcode = insn_fetch(u8, 1, eip);
    1.77 +        opcode = insn_fetch(u8, 1, cs, eip);
    1.78          modrm_reg |= (opcode >> 3) & 7;
    1.79          modrm_rm  |= (opcode >> 0) & 7;
    1.80          reg = decode_register(modrm_rm, regs, 0);
    1.81 @@ -1292,7 +1294,7 @@ static int emulate_privileged_op(struct 
    1.82          break;
    1.83  
    1.84      case 0x21: /* MOV DR?,<reg> */
    1.85 -        opcode = insn_fetch(u8, 1, eip);
    1.86 +        opcode = insn_fetch(u8, 1, cs, eip);
    1.87          modrm_reg |= (opcode >> 3) & 7;
    1.88          modrm_rm  |= (opcode >> 0) & 7;
    1.89          reg = decode_register(modrm_rm, regs, 0);
    1.90 @@ -1302,7 +1304,7 @@ static int emulate_privileged_op(struct 
    1.91          break;
    1.92  
    1.93      case 0x22: /* MOV <reg>,CR? */
    1.94 -        opcode = insn_fetch(u8, 1, eip);
    1.95 +        opcode = insn_fetch(u8, 1, cs, eip);
    1.96          modrm_reg |= (opcode >> 3) & 7;
    1.97          modrm_rm  |= (opcode >> 0) & 7;
    1.98          reg = decode_register(modrm_rm, regs, 0);
    1.99 @@ -1342,7 +1344,7 @@ static int emulate_privileged_op(struct 
   1.100          break;
   1.101  
   1.102      case 0x23: /* MOV <reg>,DR? */
   1.103 -        opcode = insn_fetch(u8, 1, eip);
   1.104 +        opcode = insn_fetch(u8, 1, cs, eip);
   1.105          modrm_reg |= (opcode >> 3) & 7;
   1.106          modrm_rm  |= (opcode >> 0) & 7;
   1.107          reg = decode_register(modrm_rm, regs, 0);