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-unstable] Merge with ia64 tree

# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1201030012 0
# Node ID 087c2b76d360021657dea9fb3b5573c86572d589
# Parent  b79802517a75a23abb88eda900ff802810a6add6
# Parent  7eafc6e841882426d1c1830f31f8a48b5e842e4b
Merge with ia64 tree
---
 xen/arch/x86/Rules.mk             |    2 
 xen/arch/x86/hvm/vmx/realmode.c   |   60 +++++++++++++
 xen/arch/x86/x86_emulate.c        |  173 ++++++++++++++++++++++++++------------
 xen/include/asm-x86/x86_emulate.h |   43 +++++++++
 4 files changed, 226 insertions(+), 52 deletions(-)

diff -r b79802517a75 -r 087c2b76d360 xen/arch/x86/Rules.mk
--- a/xen/arch/x86/Rules.mk     Tue Jan 22 09:04:41 2008 -0700
+++ b/xen/arch/x86/Rules.mk     Tue Jan 22 19:26:52 2008 +0000
@@ -11,7 +11,7 @@ xenoprof := y
 #
 pae ?= n
 supervisor_mode_kernel ?= n
-vmxassist ?= y
+vmxassist ?= n
 
 ifeq ($(vmxassist),y)
 CFLAGS += -DVMXASSIST
diff -r b79802517a75 -r 087c2b76d360 xen/arch/x86/hvm/vmx/realmode.c
--- a/xen/arch/x86/hvm/vmx/realmode.c   Tue Jan 22 09:04:41 2008 -0700
+++ b/xen/arch/x86/hvm/vmx/realmode.c   Tue Jan 22 19:26:52 2008 +0000
@@ -221,6 +221,64 @@ realmode_emulate_cmpxchg(
 {
     /* Fix this in case the guest is really relying on r-m-w atomicity. */
     return realmode_emulate_write(seg, offset, new, bytes, ctxt);
+}
+
+static int 
+realmode_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)
+{
+    struct realmode_emulate_ctxt *rm_ctxt =
+        container_of(ctxt, struct realmode_emulate_ctxt, ctxt);
+    struct vcpu *curr = current;
+    uint32_t paddr = rm_ctxt->seg_reg[dst_seg].base + dst_offset;
+
+    if ( curr->arch.hvm_vmx.real_mode_io_in_progress )
+        return X86EMUL_UNHANDLEABLE;
+
+    if ( !curr->arch.hvm_vmx.real_mode_io_completed )
+    {
+        curr->arch.hvm_vmx.real_mode_io_in_progress = 1;
+        send_pio_req(src_port, *reps, bytes_per_rep,
+                     paddr, IOREQ_READ,
+                     !!(ctxt->regs->eflags & X86_EFLAGS_DF), 1);
+    }
+
+    if ( !curr->arch.hvm_vmx.real_mode_io_completed )
+        return X86EMUL_RETRY;
+
+    curr->arch.hvm_vmx.real_mode_io_completed = 0;
+
+    return X86EMUL_OKAY;
+}
+
+static int 
+realmode_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)
+{
+    struct realmode_emulate_ctxt *rm_ctxt =
+        container_of(ctxt, struct realmode_emulate_ctxt, ctxt);
+    struct vcpu *curr = current;
+    uint32_t paddr = rm_ctxt->seg_reg[src_seg].base + src_offset;
+
+    if ( curr->arch.hvm_vmx.real_mode_io_in_progress )
+        return X86EMUL_UNHANDLEABLE;
+
+    curr->arch.hvm_vmx.real_mode_io_in_progress = 1;
+    send_pio_req(dst_port, *reps, bytes_per_rep,
+                 paddr, IOREQ_WRITE,
+                 !!(ctxt->regs->eflags & X86_EFLAGS_DF), 1);
+
+    return X86EMUL_OKAY;
 }
 
 static int
@@ -420,6 +478,8 @@ static struct x86_emulate_ops realmode_e
     .insn_fetch    = realmode_emulate_insn_fetch,
     .write         = realmode_emulate_write,
     .cmpxchg       = realmode_emulate_cmpxchg,
+    .rep_ins       = realmode_rep_ins,
+    .rep_outs      = realmode_rep_outs,
     .read_segment  = realmode_read_segment,
     .write_segment = realmode_write_segment,
     .read_io       = realmode_read_io,
diff -r b79802517a75 -r 087c2b76d360 xen/arch/x86/x86_emulate.c
--- a/xen/arch/x86/x86_emulate.c        Tue Jan 22 09:04:41 2008 -0700
+++ b/xen/arch/x86/x86_emulate.c        Tue Jan 22 19:26:52 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 b79802517a75 -r 087c2b76d360 xen/include/asm-x86/x86_emulate.h
--- a/xen/include/asm-x86/x86_emulate.h Tue Jan 22 09:04:41 2008 -0700
+++ b/xen/include/asm-x86/x86_emulate.h Tue Jan 22 19:26:52 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>