Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/common/pmap/tlb Add 3-level page table support (from MIP...



details:   https://anonhg.NetBSD.org/src/rev/84ae09d67af5
branches:  trunk
changeset: 780001:84ae09d67af5
user:      matt <matt%NetBSD.org@localhost>
date:      Thu Jul 05 16:55:11 2012 +0000

description:
Add 3-level page table support (from MIPS).  Rename a few routines.

diffstat:

 sys/common/pmap/tlb/pmap.c        |   14 +-
 sys/common/pmap/tlb/pmap.h        |    6 +-
 sys/common/pmap/tlb/pmap_segtab.c |  136 +++++++++++++++++++++++++++----------
 3 files changed, 110 insertions(+), 46 deletions(-)

diffs (truncated from 303 to 300 lines):

diff -r 33e0f26fc9e0 -r 84ae09d67af5 sys/common/pmap/tlb/pmap.c
--- a/sys/common/pmap/tlb/pmap.c        Thu Jul 05 13:55:58 2012 +0000
+++ b/sys/common/pmap/tlb/pmap.c        Thu Jul 05 16:55:11 2012 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: pmap.c,v 1.14 2012/07/04 11:39:42 matt Exp $   */
+/*     $NetBSD: pmap.c,v 1.15 2012/07/05 16:55:11 matt Exp $   */
 
 /*-
  * Copyright (c) 1998, 2001 The NetBSD Foundation, Inc.
@@ -67,7 +67,7 @@
 
 #include <sys/cdefs.h>
 
-__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.14 2012/07/04 11:39:42 matt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.15 2012/07/05 16:55:11 matt Exp $");
 
 /*
  *     Manages physical address maps.
@@ -450,8 +450,8 @@
 void
 pmap_init(void)
 {
-        UVMHIST_INIT_STATIC(pmapexechist, pmapexechistbuf);
-        UVMHIST_INIT_STATIC(pmaphist, pmaphistbuf);
+       UVMHIST_INIT_STATIC(pmapexechist, pmapexechistbuf);
+       UVMHIST_INIT_STATIC(pmaphist, pmaphistbuf);
 
        UVMHIST_FUNC(__func__); UVMHIST_CALLED(pmaphist);
 
@@ -504,7 +504,7 @@
        pmap->pm_minaddr = VM_MIN_ADDRESS;
        pmap->pm_maxaddr = VM_MAXUSER_ADDRESS;
 
-       pmap_segtab_alloc(pmap);
+       pmap_segtab_init(pmap);
 
        UVMHIST_LOG(pmaphist, "<- pmap %p", pmap,0,0,0);
        return pmap;
@@ -530,7 +530,7 @@
        PMAP_COUNT(destroy);
        kpreempt_disable();
        pmap_tlb_asid_release_all(pmap);
-       pmap_segtab_free(pmap);
+       pmap_segtab_destroy(pmap);
 
        pool_put(&pmap_pmap_pool, pmap);
        kpreempt_enable();
@@ -1482,7 +1482,7 @@
            pmap, va, pg, VM_PAGE_TO_PHYS(pg));
        UVMHIST_LOG(pmaphist, "nptep=%p (%#x))", npte, *npte, 0, 0);
 
-        KASSERT(kpreempt_disabled());
+       KASSERT(kpreempt_disabled());
        KASSERT(pmap != pmap_kernel() || !pmap_md_direct_mapped_vaddr_p(va));
 
        apv = NULL;
diff -r 33e0f26fc9e0 -r 84ae09d67af5 sys/common/pmap/tlb/pmap.h
--- a/sys/common/pmap/tlb/pmap.h        Thu Jul 05 13:55:58 2012 +0000
+++ b/sys/common/pmap/tlb/pmap.h        Thu Jul 05 16:55:11 2012 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: pmap.h,v 1.13 2012/07/04 11:39:42 matt Exp $   */
+/*     $NetBSD: pmap.h,v 1.14 2012/07/05 16:55:11 matt Exp $   */
 
 /*
  * Copyright (c) 1992, 1993
@@ -107,8 +107,8 @@
 void pmap_pte_process(struct pmap *, vaddr_t, vaddr_t, pte_callback_t,
        uintptr_t);
 void pmap_segtab_activate(struct pmap *, struct lwp *);
-void pmap_segtab_alloc(struct pmap *);
-void pmap_segtab_free(struct pmap *);
+void pmap_segtab_init(struct pmap *);
+void pmap_segtab_destroy(struct pmap *);
 extern kmutex_t pmap_segtab_lock;
 #endif /* _KERNEL */
 
diff -r 33e0f26fc9e0 -r 84ae09d67af5 sys/common/pmap/tlb/pmap_segtab.c
--- a/sys/common/pmap/tlb/pmap_segtab.c Thu Jul 05 13:55:58 2012 +0000
+++ b/sys/common/pmap/tlb/pmap_segtab.c Thu Jul 05 16:55:11 2012 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: pmap_segtab.c,v 1.5 2012/07/04 11:39:42 matt Exp $     */
+/*     $NetBSD: pmap_segtab.c,v 1.6 2012/07/05 16:55:11 matt Exp $     */
 
 /*-
  * Copyright (c) 1998, 2001 The NetBSD Foundation, Inc.
@@ -67,7 +67,7 @@
 
 #include <sys/cdefs.h>
 
-__KERNEL_RCSID(0, "$NetBSD: pmap_segtab.c,v 1.5 2012/07/04 11:39:42 matt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pmap_segtab.c,v 1.6 2012/07/05 16:55:11 matt Exp $");
 
 /*
  *     Manages physical address maps.
@@ -134,7 +134,12 @@
 {
        struct pmap_segtab *stp = pmap->pm_segtab;
        KASSERT(pmap != pmap_kernel() || !pmap_md_direct_mapped_vaddr_p(va));
-       return stp->seg_tab[va >> SEGSHIFT];
+#ifdef _LP64
+       stp = stp->seg_seg[(va >> XSEGSHIFT) & (NSEGPG - 1)];
+       if (stp == NULL)
+               return NULL;
+#endif
+       return stp->seg_tab[(va >> SEGSHIFT) & (PMAP_SEGTABSIZE - 1)];
 }
 
 pt_entry_t *
@@ -147,6 +152,55 @@
        return pte + ((va >> PGSHIFT) & (NPTEPG - 1));
 }
 
+static void
+pmap_segtab_free(struct pmap_segtab *stp)
+{
+       /*
+        * Insert the the segtab into the segtab freelist.
+        */
+       mutex_spin_enter(&pmap_segtab_lock);
+       stp->seg_tab[0] = (void *) pmap_segtab_info.free_segtab;
+       pmap_segtab_info.free_segtab = stp;
+       SEGTAB_ADD(nput, 1);
+       mutex_spin_exit(&pmap_segtab_lock);
+}
+
+static void
+pmap_segtab_release(struct pmap_segtab *stp, u_int level)
+{
+
+       for (size_t i = 0; i < PMAP_SEGTABSIZE; i++) {
+               paddr_t pa;
+#ifdef _LP64
+               if (level > 0) {
+                       if (stp->seg_seg[i] != NULL) {
+                               pmap_segtab_release(stp->seg_seg[i], level - 1);
+                               stp->seg_seg[i] = NULL;
+                       }
+                       continue;
+               }
+#endif
+
+               /* get pointer to segment map */
+               pt_entry_t *pte = stp->seg_tab[i];
+               if (pte == NULL)
+                       continue;
+#ifdef PARANOIADIAG
+               for (size_t j = 0; j < NPTEPG; j++) {
+                       if ((pte + j)->pt_entry)
+                               panic("pmap_destroy: segmap not empty");
+               }
+#endif
+
+               pa = POOL_VTOPHYS(pte);
+               uvm_pagefree(PHYS_TO_VM_PAGE(pa));
+
+               stp->seg_tab[i] = NULL;
+       }
+
+       pmap_segtab_free(stp);
+}
+
 /*
  *     Create and return a physical map.
  *
@@ -159,10 +213,11 @@
  *     the map will be used in software only, and
  *     is bounded by that size.
  */
-void
-pmap_segtab_alloc(pmap_t pmap)
+static struct pmap_segtab *
+pmap_segtab_alloc(void)
 {
        struct pmap_segtab *stp;
+
  again:
        mutex_spin_enter(&pmap_segtab_lock);
        if (__predict_true((stp = pmap_segtab_info.free_segtab) != NULL)) {
@@ -172,7 +227,7 @@
                SEGTAB_ADD(nget, 1);
        }
        mutex_spin_exit(&pmap_segtab_lock);
-       
+
        if (__predict_false(stp == NULL)) {
                struct vm_page * const stp_pg = pmap_pte_pagealloc();
 
@@ -187,7 +242,7 @@
                const paddr_t stp_pa = VM_PAGE_TO_PHYS(stp_pg);
 
                stp = (struct pmap_segtab *)POOL_PHYSTOV(stp_pa);
-               const size_t n = NBPG / sizeof(struct pmap_segtab);
+               const size_t n = NBPG / sizeof(*stp);
                if (n > 1) {
                        /*
                         * link all the segtabs in this page together
@@ -212,8 +267,14 @@
                        panic("pmap_create: pm_segtab.seg_tab[%zu] != 0");
        }
 #endif
+       return stp;
+}
 
-       pmap->pm_segtab = stp;
+void
+pmap_segtab_init(pmap_t pmap)
+{
+
+       pmap->pm_segtab = pmap_segtab_alloc();
 }
 
 /*
@@ -222,40 +283,18 @@
  *     no valid mappings.
  */
 void
-pmap_segtab_free(pmap_t pmap)
+pmap_segtab_destroy(pmap_t pmap)
 {
        struct pmap_segtab *stp = pmap->pm_segtab;
 
        if (stp == NULL)
                return;
 
-       for (size_t i = 0; i < PMAP_SEGTABSIZE; i++) {
-               paddr_t pa;
-               /* get pointer to segment map */
-               pt_entry_t *pte = stp->seg_tab[i];
-               if (pte == NULL)
-                       continue;
-#ifdef PARANOIADIAG
-               for (size_t j = 0; j < NPTEPG; j++) {
-                       if ((pte + j)->pt_entry)
-                               panic("pmap_destroy: segmap not empty");
-               }
+#ifdef _LP64
+       pmap_segtab_release(stp, 1);
+#else
+       pmap_segtab_release(stp, 0);
 #endif
-
-               pa = POOL_VTOPHYS(pte);
-               uvm_pagefree(PHYS_TO_VM_PAGE(pa));
-
-               stp->seg_tab[i] = NULL;
-       }
-
-       /*
-        * Insert the the segtab into the segtab freelist.
-        */
-       mutex_spin_enter(&pmap_segtab_lock);
-       stp->seg_tab[0] = (void *) pmap_segtab_info.free_segtab;
-       pmap_segtab_info.free_segtab = stp;
-       SEGTAB_ADD(nput, 1);
-       mutex_spin_exit(&pmap_segtab_lock);
 }
 
 /*
@@ -265,11 +304,17 @@
 pmap_segtab_activate(struct pmap *pm, struct lwp *l)
 {
        if (l == curlwp) {
+               KASSERT(pm == l->l_proc->p_vmspace->vm_map.pmap);
                if (pm == pmap_kernel()) {
                        l->l_cpu->ci_pmap_user_segtab = (void*)0xdeadbabe;
+#ifdef _LP64
+                       l->l_cpu->ci_pmap_user_seg0tab = (void*)0xdeadbabe;
+#endif
                } else {
-                       KASSERT(pm == l->l_proc->p_vmspace->vm_map.pmap);
                        l->l_cpu->ci_pmap_user_segtab = pm->pm_segtab;
+#ifdef _LP64
+                       l->l_cpu->ci_pmap_user_seg0tab = pm->pm_segtab->seg_seg[0];
+#endif
                }
        }
 }
@@ -324,6 +369,25 @@
 
        pte = pmap_pte_lookup(pmap, va);
        if (__predict_false(pte == NULL)) {
+#ifdef _LP64
+               struct pmap_segtab ** const stp_p =
+                   &stp->seg_seg[(va >> XSEGSHIFT) & (NSEGPG - 1)];  
+               if (__predict_false((stp = *stp_p) == NULL)) {  
+                       struct pmap_segtab *nstp = pmap_segtab_alloc();
+#ifdef MULTIPROCESSOR 
+                       struct pmap_segtab *ostp = atomic_cas_ptr(stp_p, NULL, nstp);
+                       if (__predict_false(ostp != NULL)) {
+                               pmap_segtab_free(nstp);
+                               nstp = ostp;
+                       }
+#else   
+                       *stp_p = nstp;
+#endif /* MULTIPROCESSOR */
+                       stp = nstp;
+               }
+               KASSERT(stp == pmap->pm_segtab->seg_seg[(va >> XSEGSHIFT) & (NSE
+GPG - 1)]);
+#endif /* _LP64 */



Home | Main Index | Thread Index | Old Index