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>
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 = ®s; 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 /*