[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] [XEN] Allow stack-address-size to be specified differently from
# HG changeset patch # User kfraser@xxxxxxxxxxxxxxxxxxxxx # Date 1168875800 0 # Node ID 0ba81aa56455be37c2d5c19920f3633ad267604c # Parent ba5e80864f9c9cc91879e2fc175370634d3bdd9a [XEN] Allow stack-address-size to be specified differently from regular address-size in the emulator. Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx> --- tools/tests/test_x86_emulator.c | 3 +- xen/arch/x86/mm.c | 3 +- xen/arch/x86/mm/shadow/common.c | 25 +++++++++++++---- xen/arch/x86/x86_emulate.c | 53 ++++++++++++++++++++------------------ xen/include/asm-x86/x86_emulate.h | 7 +++-- 5 files changed, 56 insertions(+), 35 deletions(-) diff -r ba5e80864f9c -r 0ba81aa56455 tools/tests/test_x86_emulator.c --- a/tools/tests/test_x86_emulator.c Mon Jan 15 14:32:25 2007 +0000 +++ b/tools/tests/test_x86_emulator.c Mon Jan 15 15:43:20 2007 +0000 @@ -118,7 +118,8 @@ int main(int argc, char **argv) #endif ctxt.regs = ®s; - ctxt.address_bytes = 4; + ctxt.addr_size = 32; + ctxt.sp_size = 32; res = mmap((void *)0x100000, MMAP_SZ, PROT_READ|PROT_WRITE, MAP_FIXED|MAP_PRIVATE|MAP_ANONYMOUS, 0, 0); diff -r ba5e80864f9c -r 0ba81aa56455 xen/arch/x86/mm.c --- a/xen/arch/x86/mm.c Mon Jan 15 14:32:25 2007 +0000 +++ b/xen/arch/x86/mm.c Mon Jan 15 15:43:20 2007 +0000 @@ -3376,7 +3376,8 @@ int ptwr_do_page_fault(struct vcpu *v, u goto bail; ptwr_ctxt.ctxt.regs = guest_cpu_user_regs(); - ptwr_ctxt.ctxt.address_bytes = IS_COMPAT(d) ? 4 : sizeof(long); + ptwr_ctxt.ctxt.addr_size = ptwr_ctxt.ctxt.sp_size = + IS_COMPAT(d) ? 32 : BITS_PER_LONG; ptwr_ctxt.cr2 = addr; ptwr_ctxt.pte = pte; if ( x86_emulate(&ptwr_ctxt.ctxt, &ptwr_emulate_ops) ) diff -r ba5e80864f9c -r 0ba81aa56455 xen/arch/x86/mm/shadow/common.c --- a/xen/arch/x86/mm/shadow/common.c Mon Jan 15 14:32:25 2007 +0000 +++ b/xen/arch/x86/mm/shadow/common.c Mon Jan 15 15:43:20 2007 +0000 @@ -110,7 +110,7 @@ static int hvm_translate_linear_addr( unsigned long limit, addr = offset; uint32_t last_byte; - if ( sh_ctxt->ctxt.address_bytes != 8 ) + if ( sh_ctxt->ctxt.addr_size != 64 ) { /* * COMPATIBILITY MODE: Apply segment checks and add base. @@ -399,7 +399,7 @@ struct x86_emulate_ops *shadow_init_emul struct x86_emulate_ops *shadow_init_emulation( struct sh_emulate_ctxt *sh_ctxt, struct cpu_user_regs *regs) { - struct segment_register *creg; + struct segment_register *creg, *sreg; struct vcpu *v = current; unsigned long addr; @@ -407,7 +407,7 @@ struct x86_emulate_ops *shadow_init_emul if ( !is_hvm_vcpu(v) ) { - sh_ctxt->ctxt.address_bytes = sizeof(long); + sh_ctxt->ctxt.addr_size = sh_ctxt->ctxt.sp_size = BITS_PER_LONG; return &pv_shadow_emulator_ops; } @@ -417,11 +417,24 @@ struct x86_emulate_ops *shadow_init_emul /* Work out the emulation mode. */ if ( hvm_long_mode_enabled(v) ) - sh_ctxt->ctxt.address_bytes = creg->attr.fields.l ? 8 : 4; + { + sh_ctxt->ctxt.addr_size = creg->attr.fields.l ? 64 : 32; + if ( (sh_ctxt->ctxt.sp_size = sh_ctxt->ctxt.addr_size) != 64 ) + { + sreg = hvm_get_seg_reg(x86_seg_ss, sh_ctxt); + sh_ctxt->ctxt.sp_size = sreg->attr.fields.db ? 32 : 16; + } + } else if ( regs->eflags & X86_EFLAGS_VM ) - sh_ctxt->ctxt.address_bytes = 2; + { + sh_ctxt->ctxt.addr_size = sh_ctxt->ctxt.sp_size = 16; + } else - sh_ctxt->ctxt.address_bytes = creg->attr.fields.db ? 4 : 2; + { + sreg = hvm_get_seg_reg(x86_seg_ss, sh_ctxt); + sh_ctxt->ctxt.addr_size = creg->attr.fields.db ? 32 : 16; + sh_ctxt->ctxt.sp_size = sreg->attr.fields.db ? 32 : 16; + } /* Attempt to prefetch whole instruction. */ sh_ctxt->insn_buf_bytes = diff -r ba5e80864f9c -r 0ba81aa56455 xen/arch/x86/x86_emulate.c --- a/xen/arch/x86/x86_emulate.c Mon Jan 15 14:32:25 2007 +0000 +++ b/xen/arch/x86/x86_emulate.c Mon Jan 15 15:43:20 2007 +0000 @@ -443,10 +443,11 @@ do{ __asm__ __volatile__ ( }) #define insn_fetch_type(_type) ((_type)insn_fetch_bytes(sizeof(_type))) -#define _truncate_ea(ea, byte_width) \ -({ unsigned long __ea = (ea); \ - (((byte_width) == sizeof(unsigned long)) ? __ea : \ - (__ea & ((1UL << ((byte_width) << 3)) - 1))); \ +#define _truncate_ea(ea, byte_width) \ +({ unsigned long __ea = (ea); \ + unsigned int _width = (byte_width); \ + ((_width == sizeof(unsigned long)) ? __ea : \ + (__ea & ((1UL << (_width << 3)) - 1))); \ }) #define truncate_ea(ea) _truncate_ea((ea), ad_bytes) @@ -473,16 +474,27 @@ static int even_parity(uint8_t v) #define _register_address_increment(reg, inc, byte_width) \ do { \ int _inc = (inc); /* signed type ensures sign extension to long */ \ - if ( (byte_width) == sizeof(unsigned long) ) \ + unsigned int _width = (byte_width); \ + if ( _width == sizeof(unsigned long) ) \ (reg) += _inc; \ else if ( mode_64bit() ) \ - (reg) = ((reg) + _inc) & ((1UL << ((byte_width) << 3)) - 1); \ + (reg) = ((reg) + _inc) & ((1UL << (_width << 3)) - 1); \ else \ - (reg) = ((reg) & ~((1UL << ((byte_width) << 3)) - 1)) | \ - (((reg) + _inc) & ((1UL << ((byte_width) << 3)) - 1)); \ + (reg) = ((reg) & ~((1UL << (_width << 3)) - 1)) | \ + (((reg) + _inc) & ((1UL << (_width << 3)) - 1)); \ } while (0) #define register_address_increment(reg, inc) \ _register_address_increment((reg), (inc), ad_bytes) + +#define sp_pre_dec(dec) ({ \ + _register_address_increment(_regs.esp, -(dec), ctxt->sp_size/8); \ + _truncate_ea(_regs.esp, ctxt->sp_size/8); \ +}) +#define sp_post_inc(inc) ({ \ + unsigned long __esp = _truncate_ea(_regs.esp, ctxt->sp_size/8); \ + _register_address_increment(_regs.esp, (inc), ctxt->sp_size/8); \ + __esp; \ +}) #define jmp_rel(rel) \ do { \ @@ -679,7 +691,7 @@ x86_emulate( ea.mem.seg = x86_seg_ds; ea.mem.off = 0; - op_bytes = def_op_bytes = ad_bytes = def_ad_bytes = ctxt->address_bytes; + op_bytes = def_op_bytes = ad_bytes = def_ad_bytes = ctxt->addr_size/8; if ( op_bytes == 8 ) { op_bytes = def_op_bytes = 4; @@ -1194,10 +1206,9 @@ x86_emulate( /* 64-bit mode: POP defaults to a 64-bit operand. */ if ( mode_64bit() && (dst.bytes == 4) ) dst.bytes = 8; - if ( (rc = ops->read(x86_seg_ss, truncate_ea(_regs.esp), + if ( (rc = ops->read(x86_seg_ss, sp_post_inc(dst.bytes), &dst.val, dst.bytes, ctxt)) != 0 ) goto done; - register_address_increment(_regs.esp, dst.bytes); break; case 0xb0 ... 0xb7: /* mov imm8,r8 */ @@ -1488,8 +1499,7 @@ x86_emulate( &dst.val, 8, ctxt)) != 0 ) goto done; } - register_address_increment(_regs.esp, -dst.bytes); - if ( (rc = ops->write(x86_seg_ss, truncate_ea(_regs.esp), + if ( (rc = ops->write(x86_seg_ss, sp_pre_dec(dst.bytes), dst.val, dst.bytes, ctxt)) != 0 ) goto done; dst.type = OP_NONE; @@ -1644,10 +1654,9 @@ x86_emulate( dst.bytes = op_bytes; if ( mode_64bit() && (dst.bytes == 4) ) dst.bytes = 8; - if ( (rc = ops->read(x86_seg_ss, truncate_ea(_regs.esp), + if ( (rc = ops->read(x86_seg_ss, sp_post_inc(dst.bytes), &dst.val, dst.bytes, ctxt)) != 0 ) goto done; - register_address_increment(_regs.esp, dst.bytes); break; case 0x60: /* pusha */ { @@ -1657,11 +1666,9 @@ x86_emulate( _regs.esp, _regs.ebp, _regs.esi, _regs.edi }; generate_exception_if(mode_64bit(), EXC_UD); for ( i = 0; i < 8; i++ ) - if ( (rc = ops->write(x86_seg_ss, - truncate_ea(_regs.esp-(i+1)*op_bytes), + if ( (rc = ops->write(x86_seg_ss, sp_pre_dec(op_bytes), regs[i], op_bytes, ctxt)) != 0 ) goto done; - register_address_increment(_regs.esp, -8*op_bytes); break; } @@ -1674,11 +1681,9 @@ x86_emulate( (unsigned long *)&_regs.ecx, (unsigned long *)&_regs.eax }; generate_exception_if(mode_64bit(), EXC_UD); for ( i = 0; i < 8; i++ ) - if ( (rc = ops->read(x86_seg_ss, - truncate_ea(_regs.esp+i*op_bytes), + if ( (rc = ops->read(x86_seg_ss, sp_post_inc(op_bytes), regs[i], op_bytes, ctxt)) != 0 ) goto done; - register_address_increment(_regs.esp, 8*op_bytes); break; } @@ -1697,9 +1702,8 @@ x86_emulate( if ( mode_64bit() && (dst.bytes == 4) ) dst.bytes = 8; dst.val = src.val; - register_address_increment(_regs.esp, -dst.bytes); dst.mem.seg = x86_seg_ss; - dst.mem.off = truncate_ea(_regs.esp); + dst.mem.off = sp_pre_dec(dst.bytes); break; case 0x70 ... 0x7f: /* jcc (short) */ { @@ -1813,11 +1817,10 @@ x86_emulate( case 0xc3: /* ret (near) */ { int offset = (b == 0xc2) ? insn_fetch_type(uint16_t) : 0; op_bytes = mode_64bit() ? 8 : op_bytes; - if ( (rc = ops->read(x86_seg_ss, truncate_ea(_regs.esp), + if ( (rc = ops->read(x86_seg_ss, sp_post_inc(op_bytes + offset), &dst.val, op_bytes, ctxt)) != 0 ) goto done; _regs.eip = dst.val; - register_address_increment(_regs.esp, op_bytes + offset); break; } diff -r ba5e80864f9c -r 0ba81aa56455 xen/include/asm-x86/x86_emulate.h --- a/xen/include/asm-x86/x86_emulate.h Mon Jan 15 14:32:25 2007 +0000 +++ b/xen/include/asm-x86/x86_emulate.h Mon Jan 15 15:43:20 2007 +0000 @@ -150,8 +150,11 @@ struct x86_emulate_ctxt /* Register state before/after emulation. */ struct cpu_user_regs *regs; - /* Default address size in current execution mode (2, 4, or 8). */ - int address_bytes; + /* Default address size in current execution mode (16, 32, or 64). */ + unsigned int addr_size; + + /* Stack pointer width in bits (16, 32 or 64). */ + unsigned int sp_size; }; /* _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |