ia64/xen-unstable

changeset 18339:6e3c97f43f9c

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@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Tue Aug 19 15:56:31 2008 +0100 (2008-08-19)
parents 7c10be016e43
children a3fe573a0e1e
files xen/arch/x86/x86_emulate/x86_emulate.c
line diff
     1.1 --- a/xen/arch/x86/x86_emulate/x86_emulate.c	Tue Aug 19 10:51:41 2008 +0100
     1.2 +++ b/xen/arch/x86/x86_emulate/x86_emulate.c	Tue Aug 19 15:56:31 2008 +0100
     1.3 @@ -681,6 +681,15 @@ static void __put_rep_prefix(
     1.4          __put_rep_prefix(&_regs, ctxt->regs, ad_bytes, reps_completed); \
     1.5  })
     1.6  
     1.7 +/* Clip maximum repetitions so that the index register only just wraps. */
     1.8 +#define truncate_ea_and_reps(ea, reps, bytes_per_rep) ({                \
     1.9 +    unsigned long __todo = (ctxt->regs->eflags & EF_DF) ? (ea) : ~(ea); \
    1.10 +    __todo = truncate_word(__todo, ad_bytes);                           \
    1.11 +    __todo = (__todo / (bytes_per_rep)) + 1;                            \
    1.12 +    (reps) = (__todo < (reps)) ? __todo : (reps);                       \
    1.13 +    truncate_word((ea), ad_bytes);                                      \
    1.14 +})
    1.15 +
    1.16  /* Compatibility function: read guest memory, zero-extend result to a ulong. */
    1.17  static int read_ulong(
    1.18          enum x86_segment seg,
    1.19 @@ -2385,7 +2394,7 @@ x86_emulate(
    1.20          unsigned int port = (uint16_t)_regs.edx;
    1.21          dst.bytes = !(b & 1) ? 1 : (op_bytes == 8) ? 4 : op_bytes;
    1.22          dst.mem.seg = x86_seg_es;
    1.23 -        dst.mem.off = truncate_ea(_regs.edi);
    1.24 +        dst.mem.off = truncate_ea_and_reps(_regs.edi, nr_reps, dst.bytes);
    1.25          if ( (rc = ioport_access_check(port, dst.bytes, ctxt, ops)) != 0 )
    1.26              goto done;
    1.27          if ( (nr_reps > 1) && (ops->rep_ins != NULL) &&
    1.28 @@ -2414,11 +2423,11 @@ x86_emulate(
    1.29          unsigned long nr_reps = get_rep_prefix();
    1.30          unsigned int port = (uint16_t)_regs.edx;
    1.31          dst.bytes = !(b & 1) ? 1 : (op_bytes == 8) ? 4 : op_bytes;
    1.32 +        ea.mem.off = truncate_ea_and_reps(_regs.esi, nr_reps, dst.bytes);
    1.33          if ( (rc = ioport_access_check(port, dst.bytes, ctxt, ops)) != 0 )
    1.34              goto done;
    1.35          if ( (nr_reps > 1) && (ops->rep_outs != NULL) &&
    1.36 -             ((rc = ops->rep_outs(ea.mem.seg, truncate_ea(_regs.esi),
    1.37 -                                  port, dst.bytes,
    1.38 +             ((rc = ops->rep_outs(ea.mem.seg, ea.mem.off, port, dst.bytes,
    1.39                                    &nr_reps, ctxt)) != X86EMUL_UNHANDLEABLE) )
    1.40          {
    1.41              if ( rc != 0 )
    1.42 @@ -2569,7 +2578,7 @@ x86_emulate(
    1.43          unsigned long nr_reps = get_rep_prefix();
    1.44          dst.bytes = (d & ByteOp) ? 1 : op_bytes;
    1.45          dst.mem.seg = x86_seg_es;
    1.46 -        dst.mem.off = truncate_ea(_regs.edi);
    1.47 +        dst.mem.off = truncate_ea_and_reps(_regs.edi, nr_reps, dst.bytes);
    1.48          if ( (nr_reps > 1) && (ops->rep_movs != NULL) &&
    1.49               ((rc = ops->rep_movs(ea.mem.seg, truncate_ea(_regs.esi),
    1.50                                    dst.mem.seg, dst.mem.off, dst.bytes,