[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH 1/2] x86/mm: factor out the code for shattering an l3 PTE
Hi Andrew, On Fri, 2019-12-06 at 17:50 +0000, Andrew Cooper wrote: > On 06/12/2019 15:53, Hongyan Xia wrote: > > map_pages_to_xen and modify_xen_mappings are performing almost > > exactly > > the same operations when shattering an l3 PTE, the only difference > > being whether we want to flush. > > > > Signed-off-by: Hongyan Xia <hongyxia@xxxxxxxxxx> > > Just for reviewing purposes, how does this relate to your other > posted > series. Is it independent, a prerequisite, or does it depend on that > series? This is independent. Other series I posted will touch a lot of PTE functions, and as Jan suggested, it would be nice to refactor some of the long and complicated ones before changing them, which could also prepare us for 5-level paging in the future. Although if these refactoring patches get in, I need to rebase the series I posted before. > > > --- > > xen/arch/x86/mm.c | 85 ++++++++++++++++++++++--------------------- > > ---- > > 1 file changed, 40 insertions(+), 45 deletions(-) > > > > diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c > > index 7d4dd80a85..42aaaa1083 100644 > > --- a/xen/arch/x86/mm.c > > +++ b/xen/arch/x86/mm.c > > @@ -5151,6 +5151,43 @@ l1_pgentry_t *virt_to_xen_l1e(unsigned long > > v) > > flush_area_local((const void *)v, f) : \ > > flush_area_all((const void *)v, f)) > > > > +/* Shatter an l3 entry and populate l2. If virt is passed in, also > > do flush. */ > > +static void shatter_l3e(l3_pgentry_t *pl3e, l2_pgentry_t *l2t, > > + unsigned long virt, bool locking) > > +{ > > + unsigned int i; > > + l3_pgentry_t ol3e = *pl3e; > > + > > + for ( i = 0; i < L2_PAGETABLE_ENTRIES; i++ ) > > + l2e_write(l2t + i, > > + l2e_from_pfn(l3e_get_pfn(ol3e) + > > + (i << PAGETABLE_ORDER), > > + l3e_get_flags(ol3e))); > > The PTE macros are especially poor for generated asm, and in cases > like > this, I'd like to improve things. > > In particular, I believe the following code has identical behaviour: > > l2_pgentry_t nl2e = l2e_from_intpte(l3e_get_intpte(ol3e)); > > for ( i = 0; i < L2_PAGETABLE_ENTRIES; i++, nl2e.l2 += > PAGETABLE_ORDER ) > l2e_write(l2t + i, nl2e); > > (although someone please double check my logic) and rather better asm > generation. (I also expect there to be some discussion on whether > using > n2le.l2 directly is something we'd want to start doing.) > I believe it should be nl2e.l2 += 1<<(PAGETABLE_ORDER+PAGE_SHIFT) ? Although the code rarely touches the field (.l2) directly, so maybe use the macros (get_intpte -> add -> from_intpte) for consistency? They should produce the same code if the compiler is not too stupid. > > + > > + if ( locking ) > > + spin_lock(&map_pgdir_lock); > > + if ( (l3e_get_flags(ol3e) & _PAGE_PRESENT) && > > + (l3e_get_flags(ol3e) & _PAGE_PSE) ) > > There is a subtle difference between the original code, and the > refactored code, and it depends on the memory barrier from > spin_lock(). > > Previously, it was re-read from memory after the lock, whereas now it > is > likely the stale version from before map_pgdir was locked. > > Either you can go back to the old version and use *pl3e, or > alternatively use: > > if ( locking ) > spin_lock(&map_pgdir_lock); > ol3e = ACCESS_ONCE(*pl3e); > if ( ... > > to make it clear that a reread from memory is required. > Good point. Thanks. > > + { > > + l3e_write_atomic(pl3e, l3e_from_mfn(virt_to_mfn(l2t), > > This would probably generate better asm by using the maddr variants > so > we don't have a double shift. > Right. I can change that. > > + __PAGE_HYPERVISOR)); > > + l2t = NULL; > > + } > > + if ( locking ) > > + spin_unlock(&map_pgdir_lock); > > + if ( virt ) > > + { > > + unsigned int flush_flags = > > + FLUSH_TLB | FLUSH_ORDER(2 * PAGETABLE_ORDER); > > + > > + if ( (l3e_get_flags(ol3e) & _PAGE_GLOBAL) ) > > + flush_flags |= FLUSH_TLB_GLOBAL; > > + flush_area(virt, flush_flags); > > + } > > + if ( l2t ) > > + free_xen_pagetable(l2t); > > This surely needs to NULL out l2t, just so the caller doesn't get any > clever ideas and ends up with a use-after-free? > > ~Andrew hmm... if we want to make the nullification visible to the caller we might need to pass &. I wonder if it makes sense to simply move the memory allocation of pl2e into shatter_l3e as well, so that the caller cannot have any ideas. Thanks, Hongyan _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxxx https://lists.xenproject.org/mailman/listinfo/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |