Download raw body.
uvm_fault_upper_lookup: delay pmap_extract()
> Date: Thu, 28 Nov 2024 10:01:15 +0100
> From: Martin Pieuchot <mpi@grenadille.net>
>
> uvm_fault_upper_lookup() enters existing neighbor pages found in the
> amap.
>
> Diff below reorder the checks in the loop to avoid calling the expensive
> pmap_extract(9) when there is no corresponding anon or if the page is
> PG_RELEASED|PG_BUSY and won't be entered anyway.
Out of curiosity, do you know what part of pmap_extract() is
expensive? Is it the locking? Or is it the PTE (descriptor) lookup?
> While here call pmap_update() only if, at least, a page has been entered.
>
> ok?
>
> Index: uvm/uvm_fault.c
> ===================================================================
> RCS file: /cvs/src/sys/uvm/uvm_fault.c,v
> diff -u -p -r1.146 uvm_fault.c
> --- uvm/uvm_fault.c 27 Nov 2024 10:58:07 -0000 1.146
> +++ uvm/uvm_fault.c 28 Nov 2024 08:35:10 -0000
> @@ -841,10 +841,11 @@ uvm_fault_upper_lookup(struct uvm_faulti
> {
> struct vm_amap *amap = ufi->entry->aref.ar_amap;
> struct vm_anon *anon;
> + struct vm_page *pg;
> boolean_t shadowed;
> vaddr_t currva;
> paddr_t pa;
> - int lcv;
> + int lcv, entered = 0;
>
> /* locked: maps(read), amap(if there) */
> KASSERT(amap == NULL ||
> @@ -859,16 +860,6 @@ uvm_fault_upper_lookup(struct uvm_faulti
> shadowed = FALSE;
> for (lcv = 0; lcv < flt->npages; lcv++, currva += PAGE_SIZE) {
> /*
> - * dont play with VAs that are already mapped
> - * except for center)
> - */
> - if (lcv != flt->centeridx &&
> - pmap_extract(ufi->orig_map->pmap, currva, &pa)) {
> - pages[lcv] = PGO_DONTCARE;
> - continue;
> - }
> -
> - /*
> * unmapped or center page. check if any anon at this level.
> */
> if (amap == NULL || anons[lcv] == NULL) {
> @@ -884,12 +875,20 @@ uvm_fault_upper_lookup(struct uvm_faulti
> shadowed = TRUE;
> continue;
> }
> +
> anon = anons[lcv];
> + pg = anon->an_page;
> +
> KASSERT(anon->an_lock == amap->am_lock);
> - if (anon->an_page &&
> - (anon->an_page->pg_flags & (PG_RELEASED|PG_BUSY)) == 0) {
> +
> + /*
> + * ignore busy pages.
> + * don't play with VAs that are already mapped.
> + */
> + if (pg && (pg->pg_flags & (PG_RELEASED|PG_BUSY)) == 0 &&
> + !pmap_extract(ufi->orig_map->pmap, currva, &pa)) {
> uvm_lock_pageq();
> - uvm_pageactivate(anon->an_page); /* reactivate */
> + uvm_pageactivate(pg); /* reactivate */
> uvm_unlock_pageq();
> counters_inc(uvmexp_counters, flt_namap);
>
> @@ -902,13 +901,14 @@ uvm_fault_upper_lookup(struct uvm_faulti
> * that we enter these right now.
> */
> (void) pmap_enter(ufi->orig_map->pmap, currva,
> - VM_PAGE_TO_PHYS(anon->an_page) | flt->pa_flags,
> + VM_PAGE_TO_PHYS(pg) | flt->pa_flags,
> (anon->an_ref > 1) ?
> (flt->enter_prot & ~PROT_WRITE) : flt->enter_prot,
> PMAP_CANFAIL);
> + entered++;
> }
> }
> - if (flt->npages > 1)
> + if (entered > 0)
> pmap_update(ufi->orig_map->pmap);
>
> return shadowed;
>
>
>
uvm_fault_upper_lookup: delay pmap_extract()