Author: jhibbits
Date: Tue Aug  6 03:16:06 2019
New Revision: 350622
URL: https://svnweb.freebsd.org/changeset/base/350622

Log:
  powerpc/pmap: Simplify Book-E 64-bit page table management
  
  There is no need for the 64-bit pmap to have a fixed number of page table
  buffers.  Since the 64-bit pmap has a DMAP, we can effectively have user
  page tables limited only by total RAM size.

Modified:
  head/sys/powerpc/booke/pmap.c

Modified: head/sys/powerpc/booke/pmap.c
==============================================================================
--- head/sys/powerpc/booke/pmap.c       Tue Aug  6 00:50:25 2019        
(r350621)
+++ head/sys/powerpc/booke/pmap.c       Tue Aug  6 03:16:06 2019        
(r350622)
@@ -59,8 +59,7 @@
   * 0xc000_0000_0000_0000 - 0xcfff_ffff_ffff_ffff      : kernel reserved
   *   0xc000_0000_0000_0000 - endkernel-1              : kernel code & data
   *               endkernel - msgbufp-1                : flat device tree
-  *                 msgbufp - ptbl_bufs-1              : message buffer
-  *               ptbl_bufs - kernel_pdir-1            : kernel page tables
+  *                 msgbufp - kernel_pdir-1            : message buffer
   *             kernel_pdir - kernel_pp2d-1            : kernel page directory
   *             kernel_pp2d - .                        : kernel pointers to 
page directory
   *      pmap_zero_copy_min - crashdumpmap-1           : reserved for page 
zero/copy
@@ -262,11 +261,6 @@ static int pv_entry_count = 0, pv_entry_max = 0, pv_en
 #define PMAP_SHPGPERPROC       200
 #endif
 
-static void ptbl_init(void);
-static struct ptbl_buf *ptbl_buf_alloc(void);
-static void ptbl_buf_free(struct ptbl_buf *);
-static void ptbl_free_pmap_ptbl(pmap_t, pte_t *);
-
 #ifdef __powerpc64__
 static pte_t *ptbl_alloc(mmu_t, pmap_t, pte_t **,
                         unsigned int, boolean_t);
@@ -274,6 +268,11 @@ static void ptbl_free(mmu_t, pmap_t, pte_t **, unsigne
 static void ptbl_hold(mmu_t, pmap_t, pte_t **, unsigned int);
 static int ptbl_unhold(mmu_t, pmap_t, vm_offset_t);
 #else
+static void ptbl_init(void);
+static struct ptbl_buf *ptbl_buf_alloc(void);
+static void ptbl_buf_free(struct ptbl_buf *);
+static void ptbl_free_pmap_ptbl(pmap_t, pte_t *);
+
 static pte_t *ptbl_alloc(mmu_t, pmap_t, unsigned int, boolean_t);
 static void ptbl_free(mmu_t, pmap_t, unsigned int);
 static void ptbl_hold(mmu_t, pmap_t, unsigned int);
@@ -293,18 +292,15 @@ static void pv_remove(pmap_t, vm_offset_t, vm_page_t);
 
 static void booke_pmap_init_qpages(void);
 
-/* Number of kva ptbl buffers, each covering one ptbl (PTBL_PAGES). */
-#ifdef __powerpc64__
-#define PTBL_BUFS               (16UL * 16 * 16)
-#else
-#define PTBL_BUFS              (128 * 16)
-#endif
-
 struct ptbl_buf {
        TAILQ_ENTRY(ptbl_buf) link;     /* list link */
        vm_offset_t kva;                /* va of mapping */
 };
 
+#ifndef __powerpc64__
+/* Number of kva ptbl buffers, each covering one ptbl (PTBL_PAGES). */
+#define PTBL_BUFS              (128 * 16)
+
 /* ptbl free list and a lock used for access synchronization. */
 static TAILQ_HEAD(, ptbl_buf) ptbl_buf_freelist;
 static struct mtx ptbl_buf_freelist_lock;
@@ -314,6 +310,7 @@ static vm_offset_t ptbl_buf_pool_vabase;
 
 /* Pointer to ptbl_buf structures. */
 static struct ptbl_buf *ptbl_bufs;
+#endif
 
 #ifdef SMP
 extern tlb_entry_t __boot_tlb1[];
@@ -574,63 +571,8 @@ tlb1_get_tlbconf(void)
 static void
 ptbl_init(void)
 {
-       int             i;
-
-       mtx_init(&ptbl_buf_freelist_lock, "ptbl bufs lock", NULL, MTX_DEF);
-       TAILQ_INIT(&ptbl_buf_freelist);
-
-       for (i = 0; i < PTBL_BUFS; i++) {
-               ptbl_bufs[i].kva = ptbl_buf_pool_vabase +
-                   i * MAX(PTBL_PAGES,PDIR_PAGES) * PAGE_SIZE;
-               TAILQ_INSERT_TAIL(&ptbl_buf_freelist, &ptbl_bufs[i], link);
-       }
 }
 
-/* Get an sf_buf from the freelist. */
-static struct ptbl_buf *
-ptbl_buf_alloc(void)
-{
-       struct ptbl_buf *buf;
-
-       mtx_lock(&ptbl_buf_freelist_lock);
-       buf = TAILQ_FIRST(&ptbl_buf_freelist);
-       if (buf != NULL)
-               TAILQ_REMOVE(&ptbl_buf_freelist, buf, link);
-       mtx_unlock(&ptbl_buf_freelist_lock);
-
-       return (buf);
-}
-
-/* Return ptbl buff to free pool. */
-static void
-ptbl_buf_free(struct ptbl_buf *buf)
-{
-       mtx_lock(&ptbl_buf_freelist_lock);
-       TAILQ_INSERT_TAIL(&ptbl_buf_freelist, buf, link);
-       mtx_unlock(&ptbl_buf_freelist_lock);
-}
-
-/*
- * Search the list of allocated ptbl bufs and find on list of allocated ptbls
- */
-static void
-ptbl_free_pmap_ptbl(pmap_t pmap, pte_t * ptbl)
-{
-       struct ptbl_buf *pbuf;
-
-       TAILQ_FOREACH(pbuf, &pmap->pm_ptbl_list, link) {
-               if (pbuf->kva == (vm_offset_t) ptbl) {
-                       /* Remove from pmap ptbl buf list. */
-                       TAILQ_REMOVE(&pmap->pm_ptbl_list, pbuf, link);
-
-                       /* Free corresponding ptbl buf. */
-                       ptbl_buf_free(pbuf);
-
-                       break;
-               }
-       }
-}
-
 /* Get a pointer to a PTE in a page table. */
 static __inline pte_t *
 pte_find(mmu_t mmu, pmap_t pmap, vm_offset_t va)
@@ -648,25 +590,36 @@ pte_find(mmu_t mmu, pmap_t pmap, vm_offset_t va)
 }
 
 /*
- * Search the list of allocated pdir bufs and find on list of allocated pdirs
+ * allocate a page of pointers to page directories, do not preallocate the
+ * page tables
  */
-static void
-ptbl_free_pmap_pdir(mmu_t mmu, pmap_t pmap, pte_t ** pdir)
+static pte_t  **
+pdir_alloc(mmu_t mmu, pmap_t pmap, unsigned int pp2d_idx, bool nosleep)
 {
-       struct ptbl_buf *pbuf;
+       vm_page_t       m;
+       pte_t          **pdir;
+       int             req;
 
-       TAILQ_FOREACH(pbuf, &pmap->pm_pdir_list, link) {
-               if (pbuf->kva == (vm_offset_t) pdir) {
-                       /* Remove from pmap ptbl buf list. */
-                       TAILQ_REMOVE(&pmap->pm_pdir_list, pbuf, link);
+       KASSERT((pdir[pdir_idx] == NULL),
+               ("%s: valid pdir entry exists!", __func__));
 
-                       /* Free corresponding pdir buf. */
-                       ptbl_buf_free(pbuf);
-
-                       break;
+       req = VM_ALLOC_NOOBJ | VM_ALLOC_WIRED;
+       while ((m = vm_page_alloc(NULL, pp2d_idx, req)) == NULL) {
+               PMAP_UNLOCK(pmap);
+               if (nosleep) {
+                       return (NULL);
                }
+               vm_wait(NULL);
+               PMAP_LOCK(pmap);
        }
+
+       /* Zero whole ptbl. */
+       pdir = (pte_t **)PHYS_TO_DMAP(VM_PAGE_TO_PHYS(m));
+       bzero(pdir, PAGE_SIZE);
+
+       return (pdir);
 }
+
 /* Free pdir pages and invalidate pdir entry. */
 static void
 pdir_free(mmu_t mmu, pmap_t pmap, unsigned int pp2d_idx)
@@ -675,7 +628,6 @@ pdir_free(mmu_t mmu, pmap_t pmap, unsigned int pp2d_id
        vm_paddr_t      pa;
        vm_offset_t     va;
        vm_page_t       m;
-       int             i;
 
        pdir = pmap->pm_pp2d[pp2d_idx];
 
@@ -683,16 +635,10 @@ pdir_free(mmu_t mmu, pmap_t pmap, unsigned int pp2d_id
 
        pmap->pm_pp2d[pp2d_idx] = NULL;
 
-       for (i = 0; i < PDIR_PAGES; i++) {
-               va = ((vm_offset_t) pdir + (i * PAGE_SIZE));
-               pa = pte_vatopa(mmu, kernel_pmap, va);
-               m = PHYS_TO_VM_PAGE(pa);
-               vm_page_free_zero(m);
-               vm_wire_sub(1);
-               pmap_kremove(va);
-       }
-
-       ptbl_free_pmap_pdir(mmu, pmap, pdir);
+       va = (vm_offset_t) pdir;
+       pa = DMAP_TO_PHYS(va);
+       m = PHYS_TO_VM_PAGE(pa);
+       vm_page_free_zero(m);
 }
 
 /*
@@ -707,30 +653,20 @@ pdir_unhold(mmu_t mmu, pmap_t pmap, u_int pp2d_idx)
        pte_t         **pdir;
        vm_paddr_t      pa;
        vm_page_t       m;
-       int             i;
 
        KASSERT((pmap != kernel_pmap),
                ("pdir_unhold: unholding kernel pdir!"));
 
        pdir = pmap->pm_pp2d[pp2d_idx];
 
-       KASSERT(((vm_offset_t) pdir >= VM_MIN_KERNEL_ADDRESS),
-           ("pdir_unhold: non kva pdir"));
-
        /* decrement hold count */
-       for (i = 0; i < PDIR_PAGES; i++) {
-               pa = pte_vatopa(mmu, kernel_pmap,
-                   (vm_offset_t) pdir + (i * PAGE_SIZE));
-               m = PHYS_TO_VM_PAGE(pa);
-               m->wire_count--;
-       }
+       pa = DMAP_TO_PHYS((vm_offset_t) pdir);
+       m = PHYS_TO_VM_PAGE(pa);
 
        /*
-        * Free pdir pages if there are no dir entries in this pdir.
-        * wire_count has the same value for all ptbl pages, so check the
-        * last page.
+        * Free pdir page if there are no dir entries in this pdir.
         */
-       if (m->wire_count == 0) {
+       if (vm_page_unwire_noq(m)) {
                pdir_free(mmu, pmap, pp2d_idx);
                return (1);
        }
@@ -744,21 +680,15 @@ pdir_unhold(mmu_t mmu, pmap_t pmap, u_int pp2d_idx)
 static void
 pdir_hold(mmu_t mmu, pmap_t pmap, pte_t ** pdir)
 {
-       vm_paddr_t      pa;
        vm_page_t       m;
-       int             i;
 
        KASSERT((pmap != kernel_pmap),
                ("pdir_hold: holding kernel pdir!"));
 
        KASSERT((pdir != NULL), ("pdir_hold: null pdir"));
 
-       for (i = 0; i < PDIR_PAGES; i++) {
-               pa = pte_vatopa(mmu, kernel_pmap,
-                               (vm_offset_t) pdir + (i * PAGE_SIZE));
-               m = PHYS_TO_VM_PAGE(pa);
-               m->wire_count++;
-       }
+       m = PHYS_TO_VM_PAGE(DMAP_TO_PHYS((vm_offset_t)pdir));
+       vm_page_wire(m);
 }
 
 /* Allocate page table. */
@@ -766,51 +696,29 @@ static pte_t   *
 ptbl_alloc(mmu_t mmu, pmap_t pmap, pte_t ** pdir, unsigned int pdir_idx,
     boolean_t nosleep)
 {
-       vm_page_t       mtbl  [PTBL_PAGES];
        vm_page_t       m;
-       struct ptbl_buf *pbuf;
-       unsigned int    pidx;
        pte_t          *ptbl;
-       int             i, j;
        int             req;
 
        KASSERT((pdir[pdir_idx] == NULL),
                ("%s: valid ptbl entry exists!", __func__));
 
-       pbuf = ptbl_buf_alloc();
-       if (pbuf == NULL)
-               panic("%s: couldn't alloc kernel virtual memory", __func__);
-
-       ptbl = (pte_t *) pbuf->kva;
-
-       for (i = 0; i < PTBL_PAGES; i++) {
-               pidx = (PTBL_PAGES * pdir_idx) + i;
-               req = VM_ALLOC_NOOBJ | VM_ALLOC_WIRED;
-               while ((m = vm_page_alloc(NULL, pidx, req)) == NULL) {
-                       PMAP_UNLOCK(pmap);
-                       rw_wunlock(&pvh_global_lock);
-                       if (nosleep) {
-                               ptbl_free_pmap_ptbl(pmap, ptbl);
-                               for (j = 0; j < i; j++)
-                                       vm_page_free(mtbl[j]);
-                               vm_wire_sub(i);
-                               return (NULL);
-                       }
-                       vm_wait(NULL);
-                       rw_wlock(&pvh_global_lock);
-                       PMAP_LOCK(pmap);
+       req = VM_ALLOC_NOOBJ | VM_ALLOC_WIRED;
+       while ((m = vm_page_alloc(NULL, pdir_idx, req)) == NULL) {
+               PMAP_UNLOCK(pmap);
+               rw_wunlock(&pvh_global_lock);
+               if (nosleep) {
+                       return (NULL);
                }
-               mtbl[i] = m;
+               vm_wait(NULL);
+               rw_wlock(&pvh_global_lock);
+               PMAP_LOCK(pmap);
        }
 
-       /* Mapin allocated pages into kernel_pmap. */
-       mmu_booke_qenter(mmu, (vm_offset_t) ptbl, mtbl, PTBL_PAGES);
        /* Zero whole ptbl. */
-       bzero((caddr_t) ptbl, PTBL_PAGES * PAGE_SIZE);
+       ptbl = (pte_t *)PHYS_TO_DMAP(VM_PAGE_TO_PHYS(m));
+       bzero(ptbl, PAGE_SIZE);
 
-       /* Add pbuf to the pmap ptbl bufs list. */
-       TAILQ_INSERT_TAIL(&pmap->pm_ptbl_list, pbuf, link);
-
        return (ptbl);
 }
 
@@ -822,7 +730,6 @@ ptbl_free(mmu_t mmu, pmap_t pmap, pte_t ** pdir, unsig
        vm_paddr_t      pa;
        vm_offset_t     va;
        vm_page_t       m;
-       int             i;
 
        ptbl = pdir[pdir_idx];
 
@@ -830,16 +737,10 @@ ptbl_free(mmu_t mmu, pmap_t pmap, pte_t ** pdir, unsig
 
        pdir[pdir_idx] = NULL;
 
-       for (i = 0; i < PTBL_PAGES; i++) {
-               va = ((vm_offset_t) ptbl + (i * PAGE_SIZE));
-               pa = pte_vatopa(mmu, kernel_pmap, va);
-               m = PHYS_TO_VM_PAGE(pa);
-               vm_page_free_zero(m);
-               vm_wire_sub(1);
-               pmap_kremove(va);
-       }
-
-       ptbl_free_pmap_ptbl(pmap, ptbl);
+       va = (vm_offset_t) ptbl;
+       pa = DMAP_TO_PHYS(va);
+       m = PHYS_TO_VM_PAGE(pa);
+       vm_page_free_zero(m);
 }
 
 /*
@@ -852,12 +753,10 @@ static int
 ptbl_unhold(mmu_t mmu, pmap_t pmap, vm_offset_t va)
 {
        pte_t          *ptbl;
-       vm_paddr_t      pa;
        vm_page_t       m;
        u_int           pp2d_idx;
        pte_t         **pdir;
        u_int           pdir_idx;
-       int             i;
 
        pp2d_idx = PP2D_IDX(va);
        pdir_idx = PDIR_IDX(va);
@@ -868,30 +767,15 @@ ptbl_unhold(mmu_t mmu, pmap_t pmap, vm_offset_t va)
        pdir = pmap->pm_pp2d[pp2d_idx];
        ptbl = pdir[pdir_idx];
 
-       KASSERT(((vm_offset_t) ptbl >= VM_MIN_KERNEL_ADDRESS),
-           ("ptbl_unhold: non kva ptbl"));
-
        /* decrement hold count */
-       for (i = 0; i < PTBL_PAGES; i++) {
-               pa = pte_vatopa(mmu, kernel_pmap,
-                   (vm_offset_t) ptbl + (i * PAGE_SIZE));
-               m = PHYS_TO_VM_PAGE(pa);
-               m->wire_count--;
-       }
+       m = PHYS_TO_VM_PAGE(DMAP_TO_PHYS((vm_offset_t) ptbl));
 
        /*
         * Free ptbl pages if there are no pte entries in this ptbl.
         * wire_count has the same value for all ptbl pages, so check the
         * last page.
         */
-       if (m->wire_count == 0) {
-               /* A pair of indirect entries might point to this ptbl page */
-#if 0
-               tlb_flush_entry(pmap, va & ~((2UL * PAGE_SIZE_1M) - 1),
-                               TLB_SIZE_1M, MAS6_SIND);
-               tlb_flush_entry(pmap, (va & ~((2UL * PAGE_SIZE_1M) - 1)) | 
PAGE_SIZE_1M,
-                               TLB_SIZE_1M, MAS6_SIND);
-#endif
+       if (vm_page_unwire_noq(m)) {
                ptbl_free(mmu, pmap, pdir, pdir_idx);
                pdir_unhold(mmu, pmap, pp2d_idx);
                return (1);
@@ -906,10 +790,8 @@ ptbl_unhold(mmu_t mmu, pmap_t pmap, vm_offset_t va)
 static void
 ptbl_hold(mmu_t mmu, pmap_t pmap, pte_t ** pdir, unsigned int pdir_idx)
 {
-       vm_paddr_t      pa;
        pte_t          *ptbl;
        vm_page_t       m;
-       int             i;
 
        KASSERT((pmap != kernel_pmap),
                ("ptbl_hold: holding kernel ptbl!"));
@@ -918,12 +800,8 @@ ptbl_hold(mmu_t mmu, pmap_t pmap, pte_t ** pdir, unsig
 
        KASSERT((ptbl != NULL), ("ptbl_hold: null ptbl"));
 
-       for (i = 0; i < PTBL_PAGES; i++) {
-               pa = pte_vatopa(mmu, kernel_pmap,
-                               (vm_offset_t) ptbl + (i * PAGE_SIZE));
-               m = PHYS_TO_VM_PAGE(pa);
-               m->wire_count++;
-       }
+       m = PHYS_TO_VM_PAGE(DMAP_TO_PHYS((vm_offset_t) ptbl));
+       vm_page_wire(m);
 }
 #else
 
@@ -1328,51 +1206,6 @@ pte_remove(mmu_t mmu, pmap_t pmap, vm_offset_t va, u_i
 }
 
 /*
- * allocate a page of pointers to page directories, do not preallocate the
- * page tables
- */
-static pte_t  **
-pdir_alloc(mmu_t mmu, pmap_t pmap, unsigned int pp2d_idx, bool nosleep)
-{
-       vm_page_t       mtbl  [PDIR_PAGES];
-       vm_page_t       m;
-       struct ptbl_buf *pbuf;
-       pte_t         **pdir;
-       unsigned int    pidx;
-       int             i;
-       int             req;
-
-       pbuf = ptbl_buf_alloc();
-
-       if (pbuf == NULL)
-               panic("%s: couldn't alloc kernel virtual memory", __func__);
-
-       /* Allocate pdir pages, this will sleep! */
-       for (i = 0; i < PDIR_PAGES; i++) {
-               pidx = (PDIR_PAGES * pp2d_idx) + i;
-               req = VM_ALLOC_NOOBJ | VM_ALLOC_WIRED;
-               while ((m = vm_page_alloc(NULL, pidx, req)) == NULL) {
-                       PMAP_UNLOCK(pmap);
-                       vm_wait(NULL);
-                       PMAP_LOCK(pmap);
-               }
-               mtbl[i] = m;
-       }
-
-       /* Mapin allocated pages into kernel_pmap. */
-       pdir = (pte_t **) pbuf->kva;
-       pmap_qenter((vm_offset_t) pdir, mtbl, PDIR_PAGES);
-
-       /* Zero whole pdir. */
-       bzero((caddr_t) pdir, PDIR_PAGES * PAGE_SIZE);
-
-       /* Add pdir to the pmap pdir bufs list. */
-       TAILQ_INSERT_TAIL(&pmap->pm_pdir_list, pbuf, link);
-
-       return pdir;
-}
-
-/*
  * Insert PTE for a given page and virtual address.
  */
 static int
@@ -1485,8 +1318,8 @@ kernel_pte_alloc(vm_offset_t data_end, vm_offset_t add
                for (j = PDIR_IDX(va + (i * PAGE_SIZE * PDIR_NENTRIES * 
PTBL_NENTRIES));
                    j < PDIR_NENTRIES; j++) {
                        kernel_pmap->pm_pp2d[i + PP2D_IDX(va)][j] =
-                           (pte_t *)(pdir + (kernel_pdirs * PAGE_SIZE * 
PDIR_PAGES) +
-                            (((i * PDIR_NENTRIES) + j) * PAGE_SIZE * 
PTBL_PAGES));
+                           (pte_t *)(pdir + (kernel_pdirs * PAGE_SIZE) +
+                            (((i * PDIR_NENTRIES) + j) * PAGE_SIZE));
                }
        }
 
@@ -1764,6 +1597,7 @@ mmu_booke_bootstrap(mmu_t mmu, vm_offset_t start, vm_o
 
        data_end = round_page(data_end);
 
+#ifndef __powerpc64__
        /* Allocate space for ptbl_bufs. */
        ptbl_bufs = (struct ptbl_buf *)data_end;
        data_end += sizeof(struct ptbl_buf) * PTBL_BUFS;
@@ -1771,6 +1605,7 @@ mmu_booke_bootstrap(mmu_t mmu, vm_offset_t start, vm_o
            (uintptr_t)ptbl_bufs, data_end);
 
        data_end = round_page(data_end);
+#endif
 
        /* Allocate PTE tables for kernel KVA. */
        kernel_pdir = data_end;
@@ -1799,12 +1634,12 @@ mmu_booke_bootstrap(mmu_t mmu, vm_offset_t start, vm_o
         * all range up to the currently calculated 'data_end' is covered.
         */
        dpcpu_init(dpcpu, 0);
-       memset((void *)ptbl_bufs, 0, sizeof(struct ptbl_buf) * PTBL_SIZE);
 #ifdef __powerpc64__
        memset((void *)kernel_pdir, 0,
            kernel_pdirs * PDIR_PAGES * PAGE_SIZE +
            kernel_ptbls * PTBL_PAGES * PAGE_SIZE);
 #else
+       memset((void *)ptbl_bufs, 0, sizeof(struct ptbl_buf) * PTBL_SIZE);
        memset((void *)kernel_pdir, 0, kernel_ptbls * PTBL_PAGES * PAGE_SIZE);
 #endif
 
@@ -1829,11 +1664,13 @@ mmu_booke_bootstrap(mmu_t mmu, vm_offset_t start, vm_o
        mtx_init(&zero_page_mutex, "mmu_booke_zero_page", NULL, MTX_DEF);
        mtx_init(&copy_page_mutex, "mmu_booke_copy_page", NULL, MTX_DEF);
 
+#ifndef __powerpc64__
        /* Allocate KVA space for ptbl bufs. */
        ptbl_buf_pool_vabase = virtual_avail;
        virtual_avail += PTBL_BUFS * PTBL_PAGES * PAGE_SIZE;
        debugf("ptbl_buf_pool_vabase = 0x%"PRI0ptrX" end = 0x%"PRI0ptrX"\n",
            ptbl_buf_pool_vabase, virtual_avail);
+#endif
 
        /* Calculate corresponding physical addresses for the kernel region. */
        phys_kernelend = kernload + kernsize;
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to