[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 = &regs;
-    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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.