direct-io.hg

changeset 13381:0ba81aa56455

[XEN] Allow stack-address-size to be specified differently from
regular address-size in the emulator.
Signed-off-by: Keir Fraser <keir@xensource.com>
author kfraser@localhost.localdomain
date Mon Jan 15 15:43:20 2007 +0000 (2007-01-15)
parents ba5e80864f9c
children ef23a0150abb
files tools/tests/test_x86_emulator.c xen/arch/x86/mm.c xen/arch/x86/mm/shadow/common.c xen/arch/x86/x86_emulate.c xen/include/asm-x86/x86_emulate.h
line diff
     1.1 --- a/tools/tests/test_x86_emulator.c	Mon Jan 15 14:32:25 2007 +0000
     1.2 +++ b/tools/tests/test_x86_emulator.c	Mon Jan 15 15:43:20 2007 +0000
     1.3 @@ -118,7 +118,8 @@ int main(int argc, char **argv)
     1.4  #endif
     1.5  
     1.6      ctxt.regs = &regs;
     1.7 -    ctxt.address_bytes = 4;
     1.8 +    ctxt.addr_size = 32;
     1.9 +    ctxt.sp_size   = 32;
    1.10  
    1.11      res = mmap((void *)0x100000, MMAP_SZ, PROT_READ|PROT_WRITE,
    1.12                 MAP_FIXED|MAP_PRIVATE|MAP_ANONYMOUS, 0, 0);
     2.1 --- a/xen/arch/x86/mm.c	Mon Jan 15 14:32:25 2007 +0000
     2.2 +++ b/xen/arch/x86/mm.c	Mon Jan 15 15:43:20 2007 +0000
     2.3 @@ -3376,7 +3376,8 @@ int ptwr_do_page_fault(struct vcpu *v, u
     2.4          goto bail;
     2.5  
     2.6      ptwr_ctxt.ctxt.regs = guest_cpu_user_regs();
     2.7 -    ptwr_ctxt.ctxt.address_bytes = IS_COMPAT(d) ? 4 : sizeof(long);
     2.8 +    ptwr_ctxt.ctxt.addr_size = ptwr_ctxt.ctxt.sp_size =
     2.9 +        IS_COMPAT(d) ? 32 : BITS_PER_LONG;
    2.10      ptwr_ctxt.cr2 = addr;
    2.11      ptwr_ctxt.pte = pte;
    2.12      if ( x86_emulate(&ptwr_ctxt.ctxt, &ptwr_emulate_ops) )
     3.1 --- a/xen/arch/x86/mm/shadow/common.c	Mon Jan 15 14:32:25 2007 +0000
     3.2 +++ b/xen/arch/x86/mm/shadow/common.c	Mon Jan 15 15:43:20 2007 +0000
     3.3 @@ -110,7 +110,7 @@ static int hvm_translate_linear_addr(
     3.4      unsigned long limit, addr = offset;
     3.5      uint32_t last_byte;
     3.6  
     3.7 -    if ( sh_ctxt->ctxt.address_bytes != 8 )
     3.8 +    if ( sh_ctxt->ctxt.addr_size != 64 )
     3.9      {
    3.10          /*
    3.11           * COMPATIBILITY MODE: Apply segment checks and add base.
    3.12 @@ -399,7 +399,7 @@ static struct x86_emulate_ops pv_shadow_
    3.13  struct x86_emulate_ops *shadow_init_emulation(
    3.14      struct sh_emulate_ctxt *sh_ctxt, struct cpu_user_regs *regs)
    3.15  {
    3.16 -    struct segment_register *creg;
    3.17 +    struct segment_register *creg, *sreg;
    3.18      struct vcpu *v = current;
    3.19      unsigned long addr;
    3.20  
    3.21 @@ -407,7 +407,7 @@ struct x86_emulate_ops *shadow_init_emul
    3.22  
    3.23      if ( !is_hvm_vcpu(v) )
    3.24      {
    3.25 -        sh_ctxt->ctxt.address_bytes = sizeof(long);
    3.26 +        sh_ctxt->ctxt.addr_size = sh_ctxt->ctxt.sp_size = BITS_PER_LONG;
    3.27          return &pv_shadow_emulator_ops;
    3.28      }
    3.29  
    3.30 @@ -417,11 +417,24 @@ struct x86_emulate_ops *shadow_init_emul
    3.31  
    3.32      /* Work out the emulation mode. */
    3.33      if ( hvm_long_mode_enabled(v) )
    3.34 -        sh_ctxt->ctxt.address_bytes = creg->attr.fields.l ? 8 : 4;
    3.35 +    {
    3.36 +        sh_ctxt->ctxt.addr_size = creg->attr.fields.l ? 64 : 32;
    3.37 +        if ( (sh_ctxt->ctxt.sp_size = sh_ctxt->ctxt.addr_size) != 64 )
    3.38 +        {
    3.39 +            sreg = hvm_get_seg_reg(x86_seg_ss, sh_ctxt);
    3.40 +            sh_ctxt->ctxt.sp_size = sreg->attr.fields.db ? 32 : 16;
    3.41 +        }
    3.42 +    }
    3.43      else if ( regs->eflags & X86_EFLAGS_VM )
    3.44 -        sh_ctxt->ctxt.address_bytes = 2;
    3.45 +    {
    3.46 +        sh_ctxt->ctxt.addr_size = sh_ctxt->ctxt.sp_size = 16;
    3.47 +    }
    3.48      else
    3.49 -        sh_ctxt->ctxt.address_bytes = creg->attr.fields.db ? 4 : 2;
    3.50 +    {
    3.51 +        sreg = hvm_get_seg_reg(x86_seg_ss, sh_ctxt);
    3.52 +        sh_ctxt->ctxt.addr_size = creg->attr.fields.db ? 32 : 16;
    3.53 +        sh_ctxt->ctxt.sp_size   = sreg->attr.fields.db ? 32 : 16;
    3.54 +    }
    3.55  
    3.56      /* Attempt to prefetch whole instruction. */
    3.57      sh_ctxt->insn_buf_bytes =
     4.1 --- a/xen/arch/x86/x86_emulate.c	Mon Jan 15 14:32:25 2007 +0000
     4.2 +++ b/xen/arch/x86/x86_emulate.c	Mon Jan 15 15:43:20 2007 +0000
     4.3 @@ -443,10 +443,11 @@ do{ __asm__ __volatile__ (              
     4.4  })
     4.5  #define insn_fetch_type(_type) ((_type)insn_fetch_bytes(sizeof(_type)))
     4.6  
     4.7 -#define _truncate_ea(ea, byte_width)                    \
     4.8 -({  unsigned long __ea = (ea);                          \
     4.9 -    (((byte_width) == sizeof(unsigned long)) ? __ea :   \
    4.10 -     (__ea & ((1UL << ((byte_width) << 3)) - 1)));      \
    4.11 +#define _truncate_ea(ea, byte_width)            \
    4.12 +({  unsigned long __ea = (ea);                  \
    4.13 +    unsigned int _width = (byte_width);         \
    4.14 +    ((_width == sizeof(unsigned long)) ? __ea : \
    4.15 +     (__ea & ((1UL << (_width << 3)) - 1)));    \
    4.16  })
    4.17  #define truncate_ea(ea) _truncate_ea((ea), ad_bytes)
    4.18  
    4.19 @@ -473,17 +474,28 @@ static int even_parity(uint8_t v)
    4.20  #define _register_address_increment(reg, inc, byte_width)               \
    4.21  do {                                                                    \
    4.22      int _inc = (inc); /* signed type ensures sign extension to long */  \
    4.23 -    if ( (byte_width) == sizeof(unsigned long) )                        \
    4.24 +    unsigned int _width = (byte_width);                                 \
    4.25 +    if ( _width == sizeof(unsigned long) )                              \
    4.26          (reg) += _inc;                                                  \
    4.27      else if ( mode_64bit() )                                            \
    4.28 -        (reg) = ((reg) + _inc) & ((1UL << ((byte_width) << 3)) - 1);    \
    4.29 +        (reg) = ((reg) + _inc) & ((1UL << (_width << 3)) - 1);          \
    4.30      else                                                                \
    4.31 -        (reg) = ((reg) & ~((1UL << ((byte_width) << 3)) - 1)) |         \
    4.32 -                (((reg) + _inc) & ((1UL << ((byte_width) << 3)) - 1));  \
    4.33 +        (reg) = ((reg) & ~((1UL << (_width << 3)) - 1)) |               \
    4.34 +                (((reg) + _inc) & ((1UL << (_width << 3)) - 1));        \
    4.35  } while (0)
    4.36  #define register_address_increment(reg, inc) \
    4.37      _register_address_increment((reg), (inc), ad_bytes)
    4.38  
    4.39 +#define sp_pre_dec(dec) ({                                              \
    4.40 +    _register_address_increment(_regs.esp, -(dec), ctxt->sp_size/8);    \
    4.41 +    _truncate_ea(_regs.esp, ctxt->sp_size/8);                           \
    4.42 +})
    4.43 +#define sp_post_inc(inc) ({                                             \
    4.44 +    unsigned long __esp = _truncate_ea(_regs.esp, ctxt->sp_size/8);     \
    4.45 +    _register_address_increment(_regs.esp, (inc), ctxt->sp_size/8);     \
    4.46 +    __esp;                                                              \
    4.47 +})
    4.48 +
    4.49  #define jmp_rel(rel)                                                    \
    4.50  do {                                                                    \
    4.51      _regs.eip += (int)(rel);                                            \
    4.52 @@ -679,7 +691,7 @@ x86_emulate(
    4.53      ea.mem.seg = x86_seg_ds;
    4.54      ea.mem.off = 0;
    4.55  
    4.56 -    op_bytes = def_op_bytes = ad_bytes = def_ad_bytes = ctxt->address_bytes;
    4.57 +    op_bytes = def_op_bytes = ad_bytes = def_ad_bytes = ctxt->addr_size/8;
    4.58      if ( op_bytes == 8 )
    4.59      {
    4.60          op_bytes = def_op_bytes = 4;
    4.61 @@ -1194,10 +1206,9 @@ x86_emulate(
    4.62          /* 64-bit mode: POP defaults to a 64-bit operand. */
    4.63          if ( mode_64bit() && (dst.bytes == 4) )
    4.64              dst.bytes = 8;
    4.65 -        if ( (rc = ops->read(x86_seg_ss, truncate_ea(_regs.esp),
    4.66 +        if ( (rc = ops->read(x86_seg_ss, sp_post_inc(dst.bytes),
    4.67                               &dst.val, dst.bytes, ctxt)) != 0 )
    4.68              goto done;
    4.69 -        register_address_increment(_regs.esp, dst.bytes);
    4.70          break;
    4.71  
    4.72      case 0xb0 ... 0xb7: /* mov imm8,r8 */
    4.73 @@ -1488,8 +1499,7 @@ x86_emulate(
    4.74                                       &dst.val, 8, ctxt)) != 0 )
    4.75                      goto done;
    4.76              }
    4.77 -            register_address_increment(_regs.esp, -dst.bytes);
    4.78 -            if ( (rc = ops->write(x86_seg_ss, truncate_ea(_regs.esp),
    4.79 +            if ( (rc = ops->write(x86_seg_ss, sp_pre_dec(dst.bytes),
    4.80                                    dst.val, dst.bytes, ctxt)) != 0 )
    4.81                  goto done;
    4.82              dst.type = OP_NONE;
    4.83 @@ -1644,10 +1654,9 @@ x86_emulate(
    4.84          dst.bytes = op_bytes;
    4.85          if ( mode_64bit() && (dst.bytes == 4) )
    4.86              dst.bytes = 8;
    4.87 -        if ( (rc = ops->read(x86_seg_ss, truncate_ea(_regs.esp),
    4.88 +        if ( (rc = ops->read(x86_seg_ss, sp_post_inc(dst.bytes),
    4.89                               &dst.val, dst.bytes, ctxt)) != 0 )
    4.90              goto done;
    4.91 -        register_address_increment(_regs.esp, dst.bytes);
    4.92          break;
    4.93  
    4.94      case 0x60: /* pusha */ {
    4.95 @@ -1657,11 +1666,9 @@ x86_emulate(
    4.96              _regs.esp, _regs.ebp, _regs.esi, _regs.edi };
    4.97          generate_exception_if(mode_64bit(), EXC_UD);
    4.98          for ( i = 0; i < 8; i++ )
    4.99 -            if ( (rc = ops->write(x86_seg_ss,
   4.100 -                                  truncate_ea(_regs.esp-(i+1)*op_bytes),
   4.101 +            if ( (rc = ops->write(x86_seg_ss, sp_pre_dec(op_bytes),
   4.102                                    regs[i], op_bytes, ctxt)) != 0 )
   4.103              goto done;
   4.104 -        register_address_increment(_regs.esp, -8*op_bytes);
   4.105          break;
   4.106      }
   4.107  
   4.108 @@ -1674,11 +1681,9 @@ x86_emulate(
   4.109              (unsigned long *)&_regs.ecx, (unsigned long *)&_regs.eax };
   4.110          generate_exception_if(mode_64bit(), EXC_UD);
   4.111          for ( i = 0; i < 8; i++ )
   4.112 -            if ( (rc = ops->read(x86_seg_ss,
   4.113 -                                 truncate_ea(_regs.esp+i*op_bytes),
   4.114 +            if ( (rc = ops->read(x86_seg_ss, sp_post_inc(op_bytes),
   4.115                                   regs[i], op_bytes, ctxt)) != 0 )
   4.116              goto done;
   4.117 -        register_address_increment(_regs.esp, 8*op_bytes);
   4.118          break;
   4.119      }
   4.120  
   4.121 @@ -1697,9 +1702,8 @@ x86_emulate(
   4.122          if ( mode_64bit() && (dst.bytes == 4) )
   4.123              dst.bytes = 8;
   4.124          dst.val = src.val;
   4.125 -        register_address_increment(_regs.esp, -dst.bytes);
   4.126          dst.mem.seg = x86_seg_ss;
   4.127 -        dst.mem.off = truncate_ea(_regs.esp);
   4.128 +        dst.mem.off = sp_pre_dec(dst.bytes);
   4.129          break;
   4.130  
   4.131      case 0x70 ... 0x7f: /* jcc (short) */ {
   4.132 @@ -1813,11 +1817,10 @@ x86_emulate(
   4.133      case 0xc3: /* ret (near) */ {
   4.134          int offset = (b == 0xc2) ? insn_fetch_type(uint16_t) : 0;
   4.135          op_bytes = mode_64bit() ? 8 : op_bytes;
   4.136 -        if ( (rc = ops->read(x86_seg_ss, truncate_ea(_regs.esp),
   4.137 +        if ( (rc = ops->read(x86_seg_ss, sp_post_inc(op_bytes + offset),
   4.138                               &dst.val, op_bytes, ctxt)) != 0 )
   4.139              goto done;
   4.140          _regs.eip = dst.val;
   4.141 -        register_address_increment(_regs.esp, op_bytes + offset);
   4.142          break;
   4.143      }
   4.144  
     5.1 --- a/xen/include/asm-x86/x86_emulate.h	Mon Jan 15 14:32:25 2007 +0000
     5.2 +++ b/xen/include/asm-x86/x86_emulate.h	Mon Jan 15 15:43:20 2007 +0000
     5.3 @@ -150,8 +150,11 @@ struct x86_emulate_ctxt
     5.4      /* Register state before/after emulation. */
     5.5      struct cpu_user_regs *regs;
     5.6  
     5.7 -    /* Default address size in current execution mode (2, 4, or 8). */
     5.8 -    int                   address_bytes;
     5.9 +    /* Default address size in current execution mode (16, 32, or 64). */
    5.10 +    unsigned int addr_size;
    5.11 +
    5.12 +    /* Stack pointer width in bits (16, 32 or 64). */
    5.13 +    unsigned int sp_size;
    5.14  };
    5.15  
    5.16  /*