Author: luporl
Date: Thu Jul 25 15:27:05 2019
New Revision: 350323
URL: https://svnweb.freebsd.org/changeset/base/350323

Log:
  powerpc: Improve pvo allocation code
  
  Added allocation retry loop in alloc_pvo_entry(), to wait for
  memory to become available if the caller specifies the M_WAITOK flag.
  
  Also, the loop in moa64_enter() was removed, as moea64_pvo_enter()
  never returns ENOMEM. It is alloc_pvo_entry() memory allocation that
  can fail and must be retried.
  
  Reviewed by:  jhibbits
  Differential Revision:        https://reviews.freebsd.org/D21035

Modified:
  head/sys/powerpc/aim/mmu_oea64.c

Modified: head/sys/powerpc/aim/mmu_oea64.c
==============================================================================
--- head/sys/powerpc/aim/mmu_oea64.c    Thu Jul 25 07:57:01 2019        
(r350322)
+++ head/sys/powerpc/aim/mmu_oea64.c    Thu Jul 25 15:27:05 2019        
(r350323)
@@ -373,24 +373,28 @@ vm_page_to_pvoh(vm_page_t m)
 }
 
 static struct pvo_entry *
-alloc_pvo_entry(int bootstrap)
+alloc_pvo_entry(int bootstrap, int flags)
 {
        struct pvo_entry *pvo;
 
+       KASSERT(bootstrap || (flags & M_WAITOK) || (flags & M_NOWAIT),
+           ("Either M_WAITOK or M_NOWAIT flag must be specified "
+            "when bootstrap is 0"));
+       KASSERT(!bootstrap || !(flags & M_WAITOK),
+           ("M_WAITOK can't be used with bootstrap"));
+
        if (!moea64_initialized || bootstrap) {
                if (moea64_bpvo_pool_index >= moea64_bpvo_pool_size) {
                        panic("moea64_enter: bpvo pool exhausted, %d, %d, %zd",
-                             moea64_bpvo_pool_index, moea64_bpvo_pool_size, 
+                             moea64_bpvo_pool_index, moea64_bpvo_pool_size,
                              moea64_bpvo_pool_size * sizeof(struct pvo_entry));
                }
                pvo = &moea64_bpvo_pool[
                    atomic_fetchadd_int(&moea64_bpvo_pool_index, 1)];
                bzero(pvo, sizeof(*pvo));
                pvo->pvo_vaddr = PVO_BOOTSTRAP;
-       } else {
-               pvo = uma_zalloc(moea64_pvo_zone, M_NOWAIT);
-               bzero(pvo, sizeof(*pvo));
-       }
+       } else
+               pvo = uma_zalloc(moea64_pvo_zone, flags | M_ZERO);
 
        return (pvo);
 }
@@ -658,7 +662,7 @@ moea64_setup_direct_map(mmu_t mmup, vm_offset_t kernel
                     pregions[i].mr_size; pa += moea64_large_page_size) {
                        pte_lo = LPTE_M;
 
-                       pvo = alloc_pvo_entry(1 /* bootstrap */);
+                       pvo = alloc_pvo_entry(1 /* bootstrap */, 0);
                        pvo->pvo_vaddr |= PVO_WIRED | PVO_LARGE;
                        init_pvo_entry(pvo, kernel_pmap, PHYS_TO_DMAP(pa));
 
@@ -1399,7 +1403,9 @@ moea64_enter(mmu_t mmu, pmap_t pmap, vm_offset_t va, v
        if ((m->oflags & VPO_UNMANAGED) == 0 && !vm_page_xbusied(m))
                VM_OBJECT_ASSERT_LOCKED(m->object);
 
-       pvo = alloc_pvo_entry(0);
+       pvo = alloc_pvo_entry(0, M_NOWAIT);
+       if (pvo == NULL)
+               return (KERN_RESOURCE_SHORTAGE);
        pvo->pvo_pmap = NULL; /* to be filled in later */
        pvo->pvo_pte.prot = prot;
 
@@ -1415,61 +1421,53 @@ moea64_enter(mmu_t mmu, pmap_t pmap, vm_offset_t va, v
                pvo_head = &m->md.mdpg_pvoh;
                pvo->pvo_vaddr |= PVO_MANAGED;
        }
-       
-       for (;;) {
-               PV_PAGE_LOCK(m);
-               PMAP_LOCK(pmap);
-               if (pvo->pvo_pmap == NULL)
-                       init_pvo_entry(pvo, pmap, va);
-               if (prot & VM_PROT_WRITE)
-                       if (pmap_bootstrapped &&
-                           (m->oflags & VPO_UNMANAGED) == 0)
-                               vm_page_aflag_set(m, PGA_WRITEABLE);
 
-               error = moea64_pvo_enter(mmu, pvo, pvo_head, &oldpvo);
-               if (error == EEXIST) {
-                       if (oldpvo->pvo_vaddr == pvo->pvo_vaddr &&
-                           oldpvo->pvo_pte.pa == pvo->pvo_pte.pa &&
-                           oldpvo->pvo_pte.prot == prot) {
-                               /* Identical mapping already exists */
-                               error = 0;
+       PV_PAGE_LOCK(m);
+       PMAP_LOCK(pmap);
+       if (pvo->pvo_pmap == NULL)
+               init_pvo_entry(pvo, pmap, va);
+       if (prot & VM_PROT_WRITE)
+               if (pmap_bootstrapped &&
+                   (m->oflags & VPO_UNMANAGED) == 0)
+                       vm_page_aflag_set(m, PGA_WRITEABLE);
 
-                               /* If not in page table, reinsert it */
-                               if (MOEA64_PTE_SYNCH(mmu, oldpvo) < 0) {
-                                       STAT_MOEA64(moea64_pte_overflow--);
-                                       MOEA64_PTE_INSERT(mmu, oldpvo);
-                               }
+       error = moea64_pvo_enter(mmu, pvo, pvo_head, &oldpvo);
+       if (error == EEXIST) {
+               if (oldpvo->pvo_vaddr == pvo->pvo_vaddr &&
+                   oldpvo->pvo_pte.pa == pvo->pvo_pte.pa &&
+                   oldpvo->pvo_pte.prot == prot) {
+                       /* Identical mapping already exists */
+                       error = 0;
 
-                               /* Then just clean up and go home */
-                               PV_PAGE_UNLOCK(m);
-                               PMAP_UNLOCK(pmap);
-                               free_pvo_entry(pvo);
-                               break;
+                       /* If not in page table, reinsert it */
+                       if (MOEA64_PTE_SYNCH(mmu, oldpvo) < 0) {
+                               STAT_MOEA64(moea64_pte_overflow--);
+                               MOEA64_PTE_INSERT(mmu, oldpvo);
                        }
 
+                       /* Then just clean up and go home */
+                       PV_PAGE_UNLOCK(m);
+                       PMAP_UNLOCK(pmap);
+                       free_pvo_entry(pvo);
+                       goto out;
+               } else {
                        /* Otherwise, need to kill it first */
                        KASSERT(oldpvo->pvo_pmap == pmap, ("pmap of old "
                            "mapping does not match new mapping"));
                        moea64_pvo_remove_from_pmap(mmu, oldpvo);
                        moea64_pvo_enter(mmu, pvo, pvo_head, NULL);
                }
-               PV_PAGE_UNLOCK(m);
-               PMAP_UNLOCK(pmap);
+       }
+       PV_PAGE_UNLOCK(m);
+       PMAP_UNLOCK(pmap);
 
-               /* Free any dead pages */
-               if (error == EEXIST) {
-                       moea64_pvo_remove_from_page(mmu, oldpvo);
-                       free_pvo_entry(oldpvo);
-               }
-
-               if (error != ENOMEM)
-                       break;
-               if ((flags & PMAP_ENTER_NOSLEEP) != 0)
-                       return (KERN_RESOURCE_SHORTAGE);
-               VM_OBJECT_ASSERT_UNLOCKED(m->object);
-               vm_wait(NULL);
+       /* Free any dead pages */
+       if (error == EEXIST) {
+               moea64_pvo_remove_from_page(mmu, oldpvo);
+               free_pvo_entry(oldpvo);
        }
 
+out:
        /*
         * Flush the page from the instruction cache if this page is
         * mapped executable and cacheable.
@@ -1632,7 +1630,7 @@ moea64_uma_page_alloc(uma_zone_t zone, vm_size_t bytes
 
        va = VM_PAGE_TO_PHYS(m);
 
-       pvo = alloc_pvo_entry(1 /* bootstrap */);
+       pvo = alloc_pvo_entry(1 /* bootstrap */, 0);
 
        pvo->pvo_pte.prot = VM_PROT_READ | VM_PROT_WRITE;
        pvo->pvo_pte.pa = VM_PAGE_TO_PHYS(m) | LPTE_M;
@@ -1864,7 +1862,7 @@ moea64_kenter_attr(mmu_t mmu, vm_offset_t va, vm_paddr
        int             error;  
        struct pvo_entry *pvo, *oldpvo;
 
-       pvo = alloc_pvo_entry(0);
+       pvo = alloc_pvo_entry(0, M_WAITOK);
        pvo->pvo_pte.prot = VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE;
        pvo->pvo_pte.pa = (pa & ~ADDR_POFF) | moea64_calc_wimg(pa, ma);
        pvo->pvo_vaddr |= PVO_WIRED;
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to