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