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

Re: [Xen-devel] [PATCH] x86_emulate: fix wrap around handling for repeated string instructions


  • To: Jan Beulich <JBeulich@xxxxxxxx>, xen-devel <xen-devel@xxxxxxxxxxxxxxxxxxxx>
  • From: Keir Fraser <keir.xen@xxxxxxxxx>
  • Date: Fri, 20 Sep 2013 11:19:42 +0100
  • Delivery-date: Fri, 20 Sep 2013 10:20:13 +0000
  • List-id: Xen developer discussion <xen-devel.lists.xen.org>
  • Thread-index: Ac616uuZpOGbjtis0ESJNrGVlUbfxQ==
  • Thread-topic: [PATCH] x86_emulate: fix wrap around handling for repeated string instructions

On 20/09/2013 10:19, "Jan Beulich" <JBeulich@xxxxxxxx> wrote:

> For one, repeat count clipping for MOVS must be done taking into
> consideration both source and destination addresses.
> 
> And then we should allow a wrap on the final iteration only if either
> the wrap is a precise one (i.e. the access itself doesn't wrap, just
> the resulting index register value would) or if there is just one
> iteration. In all other cases we should do a bulk operation first
> without hitting the wrap, and then issue an individual iteration. If
> we don't do it that way,
> - the last iteration not completing successfully will cause the whole
>   operation to fail (i.e. registers not get updated to the failure
>   point)
> - hvmemul_virtual_to_linear() may needlessly enforce non-repeated
>   operation
> 
> Additionally with the prior implementation there was a case
> (df=1, ea=~0, reps=~0, bytes_per_rep=1) where we'd end up passing zero
> reps back to the caller, yet various places assume that there's at
> least on iteration.
> 
> Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx>

Acked-by: Keir Fraser <keir@xxxxxxx>

> --- a/xen/arch/x86/x86_emulate/x86_emulate.c
> +++ b/xen/arch/x86/x86_emulate/x86_emulate.c
> @@ -773,13 +773,20 @@ 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. */
> +/* Clip maximum repetitions so that the index register at most just wraps. */
>  #define truncate_ea_and_reps(ea, reps, bytes_per_rep) ({                  \
> -    unsigned long __todo = (ctxt->regs->eflags & EFLG_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);                                        \
> +    unsigned long todo__, ea__ = truncate_word(ea, ad_bytes);             \
> +    if ( !(ctxt->regs->eflags & EFLG_DF) )                                \
> +        todo__ = truncate_word(-(ea), ad_bytes) / (bytes_per_rep);        \
> +    else if ( truncate_word((ea) + (bytes_per_rep) - 1, ad_bytes) < ea__ )\
> +        todo__ = 1;                                                       \
> +    else                                                                  \
> +        todo__ = ea__ / (bytes_per_rep) + 1;                              \
> +    if ( !todo__ )                                                        \
> +        (reps) = 1;                                                       \
> +    else if ( todo__ < (reps) )                                           \
> +        (reps) = todo__;                                                  \
> +    ea__;                                                                 \
>  })
>  
>  /* Compatibility function: read guest memory, zero-extend result to a ulong.
> */
> @@ -2385,8 +2392,9 @@ x86_emulate(
>          dst.bytes = (d & ByteOp) ? 1 : op_bytes;
>          dst.mem.seg = x86_seg_es;
>          dst.mem.off = truncate_ea_and_reps(_regs.edi, nr_reps, dst.bytes);
> +        src.mem.off = truncate_ea_and_reps(_regs.esi, nr_reps, dst.bytes);
>          if ( (nr_reps > 1) && (ops->rep_movs != NULL) &&
> -             ((rc = ops->rep_movs(ea.mem.seg, truncate_ea(_regs.esi),
> +             ((rc = ops->rep_movs(ea.mem.seg, src.mem.off,
>                                    dst.mem.seg, dst.mem.off, dst.bytes,
>                                    &nr_reps, ctxt)) != X86EMUL_UNHANDLEABLE) )
>          {
> @@ -2395,7 +2403,7 @@ x86_emulate(
>          }
>          else
>          {
> -            if ( (rc = read_ulong(ea.mem.seg, truncate_ea(_regs.esi),
> +            if ( (rc = read_ulong(ea.mem.seg, src.mem.off,
>                                    &dst.val, dst.bytes, ctxt, ops)) != 0 )
>                  goto done;
>              dst.type = OP_MEM;
> 
> 
> 



_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

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