[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
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
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |