[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH v2] x86/HVM: correct hvmemul_map_linear_addr() for multi-page case
> -----Original Message----- > From: Jan Beulich [mailto:JBeulich@xxxxxxxx] > Sent: 13 September 2018 11:13 > To: xen-devel <xen-devel@xxxxxxxxxxxxxxxxxxxx> > Cc: Andrew Cooper <Andrew.Cooper3@xxxxxxxxxx>; Paul Durrant > <Paul.Durrant@xxxxxxxxxx> > Subject: [PATCH v2] x86/HVM: correct hvmemul_map_linear_addr() for multi- > page case > > The function does two translations in one go for a single guest access. > Any failure of the first translation step (guest linear -> guest > physical), resulting in #PF, ought to take precedence over any failure > of the second step (guest physical -> host physical). Bail out of the > loop early solely when translation produces HVMTRANS_bad_linear_to_gfn, > and record the most relevant of perhaps multiple different errors > otherwise. (The choice of ZERO_BLOCK_PTR as sentinel is arbitrary.) > > Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx> > --- > v2: Add comment (mapping table) and adjust update_map_err() > accordingly. > > --- a/xen/arch/x86/hvm/emulate.c > +++ b/xen/arch/x86/hvm/emulate.c > @@ -532,6 +532,36 @@ static int hvmemul_do_mmio_addr(paddr_t > } > > /* > + * Intended mapping, implemented without table lookup: > + * > + * ----------------------------------------- > + * | \ new | | | | | > + * | \ | OKAY | NULL | RETRY | UNHND | > + * | err \ | | | | | > + * ----------------------------------------- > + * | OKAY | OKAY | NULL | RETRY | UNHND | > + * ----------------------------------------- > + * | NULL | NULL | NULL | RETRY | UNHND | > + * ----------------------------------------- > + * | RETRY | RETRY | RETRY | RETRY | UNHND | > + * ----------------------------------------- > + * | UNHND | UNHND | UNHND | UNHND | UNHND | > + * ----------------------------------------- > + */ > +static void *update_map_err(void *err, void *new) > +{ > + if ( err == ZERO_BLOCK_PTR || err == ERR_PTR(~X86EMUL_OKAY) || > + new == ERR_PTR(~X86EMUL_UNHANDLEABLE) ) > + return new; > + > + if ( new == ERR_PTR(~X86EMUL_OKAY) || > + err == ERR_PTR(~X86EMUL_UNHANDLEABLE) ) > + return err; > + > + return err ?: new; Took a while to check but that logic does match the table :-) > +} > + > +/* > * Map the frame(s) covering an individual linear access, for writeable > * access. May return NULL for MMIO, or ERR_PTR(~X86EMUL_*) for other > errors > * including ERR_PTR(~X86EMUL_OKAY) for write-discard mappings. > @@ -544,7 +574,7 @@ static void *hvmemul_map_linear_addr( > struct hvm_emulate_ctxt *hvmemul_ctxt) > { > struct vcpu *curr = current; > - void *err, *mapping; > + void *err = ZERO_BLOCK_PTR, *mapping; Given the revised logic, can't you just start *err with the value ERR_PTR(~X86EMUL_OKAY) now? You can then lose the extra test in the first if of update_map_err(). Paul > unsigned int nr_frames = ((linear + bytes - !!bytes) >> PAGE_SHIFT) - > (linear >> PAGE_SHIFT) + 1; > unsigned int i; > @@ -600,27 +630,28 @@ static void *hvmemul_map_linear_addr( > goto out; > > case HVMTRANS_bad_gfn_to_mfn: > - err = NULL; > - goto out; > + err = update_map_err(err, NULL); > + continue; > > case HVMTRANS_gfn_paged_out: > case HVMTRANS_gfn_shared: > - err = ERR_PTR(~X86EMUL_RETRY); > - goto out; > + err = update_map_err(err, ERR_PTR(~X86EMUL_RETRY)); > + continue; > > default: > - goto unhandleable; > + err = update_map_err(err, ERR_PTR(~X86EMUL_UNHANDLEABLE)); > + continue; > } > > *mfn++ = page_to_mfn(page); > > if ( p2m_is_discard_write(p2mt) ) > - { > - err = ERR_PTR(~X86EMUL_OKAY); > - goto out; > - } > + err = update_map_err(err, ERR_PTR(~X86EMUL_OKAY)); > } > > + if ( err != ZERO_BLOCK_PTR ) > + goto out; > + > /* Entire access within a single frame? */ > if ( nr_frames == 1 ) > mapping = map_domain_page(hvmemul_ctxt->mfn[0]); > @@ -639,6 +670,7 @@ static void *hvmemul_map_linear_addr( > return mapping + (linear & ~PAGE_MASK); > > unhandleable: > + ASSERT(err == ZERO_BLOCK_PTR); > err = ERR_PTR(~X86EMUL_UNHANDLEABLE); > > out: > > > _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxxx https://lists.xenproject.org/mailman/listinfo/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |