[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen-unstable] x86_emulate: Do not request emulation of REP instructions beyond the



# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1219157791 -3600
# Node ID 6e3c97f43f9c79506c834fe0661b4ceb7ba21a99
# Parent  7c10be016e432163c8d95a9d5a79636ff6133e93
x86_emulate: Do not request emulation of REP instructions beyond the
point at which the index register (SI/DI) wraps. This can cause a
discontinuity in the address range accessed by the repeated
instruction.

Signed-off-by: Keir Fraser <keir.fraser@xxxxxxxxxx>
---
 xen/arch/x86/x86_emulate/x86_emulate.c |   17 +++++++++++++----
 1 files changed, 13 insertions(+), 4 deletions(-)

diff -r 7c10be016e43 -r 6e3c97f43f9c xen/arch/x86/x86_emulate/x86_emulate.c
--- a/xen/arch/x86/x86_emulate/x86_emulate.c    Tue Aug 19 10:51:41 2008 +0100
+++ b/xen/arch/x86/x86_emulate/x86_emulate.c    Tue Aug 19 15:56:31 2008 +0100
@@ -681,6 +681,15 @@ static void __put_rep_prefix(
         __put_rep_prefix(&_regs, ctxt->regs, ad_bytes, reps_completed); \
 })
 
+/* Clip maximum repetitions so that the index register only just wraps. */
+#define truncate_ea_and_reps(ea, reps, bytes_per_rep) ({                \
+    unsigned long __todo = (ctxt->regs->eflags & EF_DF) ? (ea) : ~(ea); \
+    __todo = truncate_word(__todo, ad_bytes);                           \
+    __todo = (__todo / (bytes_per_rep)) + 1;                            \
+    (reps) = (__todo < (reps)) ? __todo : (reps);                       \
+    truncate_word((ea), ad_bytes);                                      \
+})
+
 /* Compatibility function: read guest memory, zero-extend result to a ulong. */
 static int read_ulong(
         enum x86_segment seg,
@@ -2385,7 +2394,7 @@ x86_emulate(
         unsigned int port = (uint16_t)_regs.edx;
         dst.bytes = !(b & 1) ? 1 : (op_bytes == 8) ? 4 : op_bytes;
         dst.mem.seg = x86_seg_es;
-        dst.mem.off = truncate_ea(_regs.edi);
+        dst.mem.off = truncate_ea_and_reps(_regs.edi, nr_reps, dst.bytes);
         if ( (rc = ioport_access_check(port, dst.bytes, ctxt, ops)) != 0 )
             goto done;
         if ( (nr_reps > 1) && (ops->rep_ins != NULL) &&
@@ -2414,11 +2423,11 @@ x86_emulate(
         unsigned long nr_reps = get_rep_prefix();
         unsigned int port = (uint16_t)_regs.edx;
         dst.bytes = !(b & 1) ? 1 : (op_bytes == 8) ? 4 : op_bytes;
+        ea.mem.off = truncate_ea_and_reps(_regs.esi, nr_reps, dst.bytes);
         if ( (rc = ioport_access_check(port, dst.bytes, ctxt, ops)) != 0 )
             goto done;
         if ( (nr_reps > 1) && (ops->rep_outs != NULL) &&
-             ((rc = ops->rep_outs(ea.mem.seg, truncate_ea(_regs.esi),
-                                  port, dst.bytes,
+             ((rc = ops->rep_outs(ea.mem.seg, ea.mem.off, port, dst.bytes,
                                   &nr_reps, ctxt)) != X86EMUL_UNHANDLEABLE) )
         {
             if ( rc != 0 )
@@ -2569,7 +2578,7 @@ x86_emulate(
         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);
+        dst.mem.off = truncate_ea_and_reps(_regs.edi, nr_reps, dst.bytes);
         if ( (nr_reps > 1) && (ops->rep_movs != NULL) &&
              ((rc = ops->rep_movs(ea.mem.seg, truncate_ea(_regs.esi),
                                   dst.mem.seg, dst.mem.off, dst.bytes,

_______________________________________________
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®.