WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] [xen-3.2-testing] x86_emulate: Provide callbacks for fas

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-3.2-testing] x86_emulate: Provide callbacks for faster emulation of:
From: "Xen patchbot-3.2-testing" <patchbot-3.2-testing@xxxxxxxxxxxxxxxxxxx>
Date: Thu, 07 Feb 2008 01:20:25 -0800
Delivery-date: Thu, 07 Feb 2008 01:20:27 -0800
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1202291321 0
# Node ID f69df2cee4a6222706bc4e8e24533090325e5c9e
# Parent  a76ece384befe5f6199b088f5e0ae3fce90968dd
x86_emulate: Provide callbacks for faster emulation of:
 REP MOVS, REP INS, REP OUTS.
Signed-off-by: Keir Fraser <keir.fraser@xxxxxxxxxx>
xen-unstable changeset:   16792:a878752a83f9c610d678b894063b133a5cf0719a
xen-unstable date:        Tue Jan 22 17:18:02 2008 +0000
---
 xen/arch/x86/x86_emulate.c        |  173 ++++++++++++++++++++++++++------------
 xen/include/asm-x86/x86_emulate.h |   43 +++++++++
 2 files changed, 165 insertions(+), 51 deletions(-)

diff -r a76ece384bef -r f69df2cee4a6 xen/arch/x86/x86_emulate.c
--- a/xen/arch/x86/x86_emulate.c        Mon Feb 04 14:16:28 2008 +0000
+++ b/xen/arch/x86/x86_emulate.c        Wed Feb 06 09:48:41 2008 +0000
@@ -552,7 +552,7 @@ do {                                    
                      ? (uint16_t)_regs.eip : (uint32_t)_regs.eip);      \
 } while (0)
 
-static int __handle_rep_prefix(
+static unsigned long __get_rep_prefix(
     struct cpu_user_regs *int_regs,
     struct cpu_user_regs *ext_regs,
     int ad_bytes)
@@ -561,11 +561,36 @@ static int __handle_rep_prefix(
                          (ad_bytes == 4) ? (uint32_t)int_regs->ecx :
                          int_regs->ecx);
 
-    if ( ecx-- == 0 )
-    {
+    /* Skip the instruction if no repetitions are required. */
+    if ( ecx == 0 )
         ext_regs->eip = int_regs->eip;
-        return 1;
-    }
+
+    return ecx;
+}
+
+#define get_rep_prefix() ({                                             \
+    unsigned long max_reps = 1;                                         \
+    if ( rep_prefix )                                                   \
+        max_reps = __get_rep_prefix(&_regs, ctxt->regs, ad_bytes);      \
+    if ( max_reps == 0 )                                                \
+        goto done;                                                      \
+   max_reps;                                                            \
+})
+
+static void __put_rep_prefix(
+    struct cpu_user_regs *int_regs,
+    struct cpu_user_regs *ext_regs,
+    int ad_bytes,
+    unsigned long reps_completed)
+{
+    unsigned long ecx = ((ad_bytes == 2) ? (uint16_t)int_regs->ecx :
+                         (ad_bytes == 4) ? (uint32_t)int_regs->ecx :
+                         int_regs->ecx);
+
+    /* Reduce counter appropriately, and repeat instruction if non-zero. */
+    ecx -= reps_completed;
+    if ( ecx != 0 )
+        int_regs->eip = ext_regs->eip;
 
     if ( ad_bytes == 2 )
         *(uint16_t *)&int_regs->ecx = ecx;
@@ -573,15 +598,12 @@ static int __handle_rep_prefix(
         int_regs->ecx = (uint32_t)ecx;
     else
         int_regs->ecx = ecx;
-    int_regs->eip = ext_regs->eip;
-    return 0;
 }
 
-#define handle_rep_prefix()                                                \
-do {                                                                       \
-    if ( rep_prefix && __handle_rep_prefix(&_regs, ctxt->regs, ad_bytes) ) \
-        goto done;                                                         \
-} while (0)
+#define put_rep_prefix(reps_completed) ({                               \
+    if ( rep_prefix )                                                   \
+        __put_rep_prefix(&_regs, ctxt->regs, ad_bytes, reps_completed); \
+})
 
 /*
  * Unsigned multiplication with double-word result.
@@ -2051,35 +2073,63 @@ x86_emulate(
         dst.mem.off = sp_pre_dec(dst.bytes);
         break;
 
-    case 0x6c ... 0x6d: /* ins %dx,%es:%edi */
-        handle_rep_prefix();
+    case 0x6c ... 0x6d: /* ins %dx,%es:%edi */ {
+        unsigned long nr_reps = get_rep_prefix();
         generate_exception_if(!mode_iopl(), EXC_GP);
-        dst.type  = OP_MEM;
         dst.bytes = !(b & 1) ? 1 : (op_bytes == 8) ? 4 : op_bytes;
         dst.mem.seg = x86_seg_es;
         dst.mem.off = truncate_ea(_regs.edi);
-        fail_if(ops->read_io == NULL);
-        if ( (rc = ops->read_io((uint16_t)_regs.edx, dst.bytes,
-                                &dst.val, ctxt)) != 0 )
-            goto done;
+        if ( (nr_reps > 1) && (ops->rep_ins != NULL) )
+        {
+            if ( (rc = ops->rep_ins((uint16_t)_regs.edx, dst.mem.seg,
+                                    dst.mem.off, dst.bytes,
+                                    &nr_reps, ctxt)) != 0 )
+                goto done;
+        }
+        else
+        {
+            fail_if(ops->read_io == NULL);
+            if ( (rc = ops->read_io((uint16_t)_regs.edx, dst.bytes,
+                                    &dst.val, ctxt)) != 0 )
+                goto done;
+            dst.type = OP_MEM;
+            nr_reps = 1;
+        }
         register_address_increment(
-            _regs.edi, (_regs.eflags & EFLG_DF) ? -dst.bytes : dst.bytes);
-        break;
-
-    case 0x6e ... 0x6f: /* outs %esi,%dx */
-        handle_rep_prefix();
+            _regs.edi,
+            nr_reps * ((_regs.eflags & EFLG_DF) ? -dst.bytes : dst.bytes));
+        put_rep_prefix(nr_reps);
+        break;
+    }
+
+    case 0x6e ... 0x6f: /* outs %esi,%dx */ {
+        unsigned long nr_reps = get_rep_prefix();
         generate_exception_if(!mode_iopl(), EXC_GP);
         dst.bytes = !(b & 1) ? 1 : (op_bytes == 8) ? 4 : op_bytes;
-        if ( (rc = ops->read(ea.mem.seg, truncate_ea(_regs.esi),
-                             &dst.val, dst.bytes, ctxt)) != 0 )
-            goto done;
-        fail_if(ops->write_io == NULL);
-        if ( (rc = ops->write_io((uint16_t)_regs.edx, dst.bytes,
-                                 dst.val, ctxt)) != 0 )
-            goto done;
+        if ( (nr_reps > 1) && (ops->rep_outs != NULL) )
+        {
+            if ( (rc = ops->rep_outs(ea.mem.seg, truncate_ea(_regs.esi),
+                                     (uint16_t)_regs.edx, dst.bytes,
+                                     &nr_reps, ctxt)) != 0 )
+                goto done;
+        }
+        else
+        {
+            if ( (rc = ops->read(ea.mem.seg, truncate_ea(_regs.esi),
+                                 &dst.val, dst.bytes, ctxt)) != 0 )
+                goto done;
+            fail_if(ops->write_io == NULL);
+            if ( (rc = ops->write_io((uint16_t)_regs.edx, dst.bytes,
+                                     dst.val, ctxt)) != 0 )
+                goto done;
+            nr_reps = 1;
+        }
         register_address_increment(
-            _regs.esi, (_regs.eflags & EFLG_DF) ? -dst.bytes : dst.bytes);
-        break;
+            _regs.esi,
+            nr_reps * ((_regs.eflags & EFLG_DF) ? -dst.bytes : dst.bytes));
+        put_rep_prefix(nr_reps);
+        break;
+    }
 
     case 0x70 ... 0x7f: /* jcc (short) */ {
         int rel = insn_fetch_type(int8_t);
@@ -2202,24 +2252,39 @@ x86_emulate(
         dst.val   = (unsigned long)_regs.eax;
         break;
 
-    case 0xa4 ... 0xa5: /* movs */
-        handle_rep_prefix();
-        dst.type  = OP_MEM;
+    case 0xa4 ... 0xa5: /* movs */ {
+        unsigned long nr_reps = get_rep_prefix();
         dst.bytes = (d & ByteOp) ? 1 : op_bytes;
         dst.mem.seg = x86_seg_es;
         dst.mem.off = truncate_ea(_regs.edi);
-        if ( (rc = ops->read(ea.mem.seg, truncate_ea(_regs.esi),
-                             &dst.val, dst.bytes, ctxt)) != 0 )
-            goto done;
+        if ( (nr_reps > 1) && (ops->rep_movs != NULL) )
+        {
+            if ( (rc = ops->rep_movs(ea.mem.seg, truncate_ea(_regs.esi),
+                                     dst.mem.seg, dst.mem.off, dst.bytes,
+                                     &nr_reps, ctxt)) != 0 )
+                goto done;
+        }
+        else
+        {
+            if ( (rc = ops->read(ea.mem.seg, truncate_ea(_regs.esi),
+                                 &dst.val, dst.bytes, ctxt)) != 0 )
+                goto done;
+            dst.type = OP_MEM;
+            nr_reps = 1;
+        }
         register_address_increment(
-            _regs.esi, (_regs.eflags & EFLG_DF) ? -dst.bytes : dst.bytes);
+            _regs.esi,
+            nr_reps * ((_regs.eflags & EFLG_DF) ? -dst.bytes : dst.bytes));
         register_address_increment(
-            _regs.edi, (_regs.eflags & EFLG_DF) ? -dst.bytes : dst.bytes);
-        break;
+            _regs.edi,
+            nr_reps * ((_regs.eflags & EFLG_DF) ? -dst.bytes : dst.bytes));
+        put_rep_prefix(nr_reps);
+        break;
+    }
 
     case 0xa6 ... 0xa7: /* cmps */ {
         unsigned long next_eip = _regs.eip;
-        handle_rep_prefix();
+        get_rep_prefix();
         src.bytes = dst.bytes = (d & ByteOp) ? 1 : op_bytes;
         if ( (rc = ops->read(ea.mem.seg, truncate_ea(_regs.esi),
                              &dst.val, dst.bytes, ctxt)) ||
@@ -2230,6 +2295,7 @@ x86_emulate(
             _regs.esi, (_regs.eflags & EFLG_DF) ? -dst.bytes : dst.bytes);
         register_address_increment(
             _regs.edi, (_regs.eflags & EFLG_DF) ? -src.bytes : src.bytes);
+        put_rep_prefix(1);
         /* cmp: dst - src ==> src=*%%edi,dst=*%%esi ==> *%%esi - *%%edi */
         emulate_2op_SrcV("cmp", src, dst, _regs.eflags);
         if ( ((rep_prefix == REPE_PREFIX) && !(_regs.eflags & EFLG_ZF)) ||
@@ -2238,8 +2304,8 @@ x86_emulate(
         break;
     }
 
-    case 0xaa ... 0xab: /* stos */
-        handle_rep_prefix();
+    case 0xaa ... 0xab: /* stos */ {
+        /* unsigned long max_reps = */get_rep_prefix();
         dst.type  = OP_MEM;
         dst.bytes = (d & ByteOp) ? 1 : op_bytes;
         dst.mem.seg = x86_seg_es;
@@ -2247,10 +2313,12 @@ x86_emulate(
         dst.val   = _regs.eax;
         register_address_increment(
             _regs.edi, (_regs.eflags & EFLG_DF) ? -dst.bytes : dst.bytes);
-        break;
-
-    case 0xac ... 0xad: /* lods */
-        handle_rep_prefix();
+        put_rep_prefix(1);
+        break;
+    }
+
+    case 0xac ... 0xad: /* lods */ {
+        /* unsigned long max_reps = */get_rep_prefix();
         dst.type  = OP_REG;
         dst.bytes = (d & ByteOp) ? 1 : op_bytes;
         dst.reg   = (unsigned long *)&_regs.eax;
@@ -2259,11 +2327,13 @@ x86_emulate(
             goto done;
         register_address_increment(
             _regs.esi, (_regs.eflags & EFLG_DF) ? -dst.bytes : dst.bytes);
-        break;
+        put_rep_prefix(1);
+        break;
+    }
 
     case 0xae ... 0xaf: /* scas */ {
         unsigned long next_eip = _regs.eip;
-        handle_rep_prefix();
+        get_rep_prefix();
         src.bytes = dst.bytes = (d & ByteOp) ? 1 : op_bytes;
         dst.val = _regs.eax;
         if ( (rc = ops->read(x86_seg_es, truncate_ea(_regs.edi),
@@ -2271,6 +2341,7 @@ x86_emulate(
             goto done;
         register_address_increment(
             _regs.edi, (_regs.eflags & EFLG_DF) ? -src.bytes : src.bytes);
+        put_rep_prefix(1);
         /* cmp: dst - src ==> src=*%%edi,dst=%%eax ==> %%eax - *%%edi */
         emulate_2op_SrcV("cmp", src, dst, _regs.eflags);
         if ( ((rep_prefix == REPE_PREFIX) && !(_regs.eflags & EFLG_ZF)) ||
diff -r a76ece384bef -r f69df2cee4a6 xen/include/asm-x86/x86_emulate.h
--- a/xen/include/asm-x86/x86_emulate.h Mon Feb 04 14:16:28 2008 +0000
+++ b/xen/include/asm-x86/x86_emulate.h Wed Feb 06 09:48:41 2008 +0000
@@ -175,6 +175,49 @@ struct x86_emulate_ops
         struct x86_emulate_ctxt *ctxt);
 
     /*
+     * rep_ins: Emulate INS: <src_port> -> <dst_seg:dst_offset>.
+     *  @bytes_per_rep: [IN ] Bytes transferred per repetition.
+     *  @reps:  [IN ] Maximum repetitions to be emulated.
+     *          [OUT] Number of repetitions actually emulated.
+     */
+    int (*rep_ins)(
+        uint16_t src_port,
+        enum x86_segment dst_seg,
+        unsigned long dst_offset,
+        unsigned int bytes_per_rep,
+        unsigned long *reps,
+        struct x86_emulate_ctxt *ctxt);
+
+    /*
+     * rep_outs: Emulate OUTS: <src_seg:src_offset> -> <dst_port>.
+     *  @bytes_per_rep: [IN ] Bytes transferred per repetition.
+     *  @reps:  [IN ] Maximum repetitions to be emulated.
+     *          [OUT] Number of repetitions actually emulated.
+     */
+    int (*rep_outs)(
+        enum x86_segment src_seg,
+        unsigned long src_offset,
+        uint16_t dst_port,
+        unsigned int bytes_per_rep,
+        unsigned long *reps,
+        struct x86_emulate_ctxt *ctxt);
+
+    /*
+     * rep_movs: Emulate MOVS: <src_seg:src_offset> -> <dst_seg:dst_offset>.
+     *  @bytes_per_rep: [IN ] Bytes transferred per repetition.
+     *  @reps:  [IN ] Maximum repetitions to be emulated.
+     *          [OUT] Number of repetitions actually emulated.
+     */
+    int (*rep_movs)(
+        enum x86_segment src_seg,
+        unsigned long src_offset,
+        enum x86_segment dst_seg,
+        unsigned long dst_offset,
+        unsigned int bytes_per_rep,
+        unsigned long *reps,
+        struct x86_emulate_ctxt *ctxt);
+
+    /*
      * read_segment: Emulate a read of full context of a segment register.
      *  @reg:   [OUT] Contents of segment register (visible and hidden state).
      */

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [xen-3.2-testing] x86_emulate: Provide callbacks for faster emulation of:, Xen patchbot-3.2-testing <=