Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/uvm/pmap move pmap segtab history into a new history of ...
details: https://anonhg.NetBSD.org/src/rev/80c717265be1
branches: trunk
changeset: 974998:80c717265be1
user: mrg <mrg%NetBSD.org@localhost>
date: Thu Aug 20 05:54:32 2020 +0000
description:
move pmap segtab history into a new history of only 1000 entries,
but will overflow much slower than the main pmap history.
move various debug info into kernhist. make pte array checker
into an array and use it in pmap_segtab_release() and
pmap_pte_reserve(). move check before MD callback(), incase it
wants to change ptes for some reason (they're passed in, but
this callback is currently always NULL.)
clean up some history logs to reduce the number of lines required.
diffstat:
sys/uvm/pmap/pmap.c | 7 ++-
sys/uvm/pmap/pmap.h | 3 +-
sys/uvm/pmap/pmap_segtab.c | 109 ++++++++++++++++++++++++++++++++------------
3 files changed, 85 insertions(+), 34 deletions(-)
diffs (281 lines):
diff -r d4a77ac6bb99 -r 80c717265be1 sys/uvm/pmap/pmap.c
--- a/sys/uvm/pmap/pmap.c Thu Aug 20 05:46:31 2020 +0000
+++ b/sys/uvm/pmap/pmap.c Thu Aug 20 05:54:32 2020 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: pmap.c,v 1.54 2020/08/19 07:29:01 simonb Exp $ */
+/* $NetBSD: pmap.c,v 1.55 2020/08/20 05:54:32 mrg 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.54 2020/08/19 07:29:01 simonb Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.55 2020/08/20 05:54:32 mrg Exp $");
/*
* Manages physical address maps.
@@ -217,8 +217,10 @@
#ifdef UVMHIST
static struct kern_history_ent pmapexechistbuf[10000];
static struct kern_history_ent pmaphistbuf[10000];
+static struct kern_history_ent pmapsegtabhistbuf[1000];
UVMHIST_DEFINE(pmapexechist);
UVMHIST_DEFINE(pmaphist);
+UVMHIST_DEFINE(pmapsegtabhist);
#endif
/*
@@ -587,6 +589,7 @@
{
UVMHIST_INIT_STATIC(pmapexechist, pmapexechistbuf);
UVMHIST_INIT_STATIC(pmaphist, pmaphistbuf);
+ UVMHIST_INIT_STATIC(pmapsegtabhist, pmapsegtabhistbuf);
UVMHIST_FUNC(__func__);
UVMHIST_CALLED(pmaphist);
diff -r d4a77ac6bb99 -r 80c717265be1 sys/uvm/pmap/pmap.h
--- a/sys/uvm/pmap/pmap.h Thu Aug 20 05:46:31 2020 +0000
+++ b/sys/uvm/pmap/pmap.h Thu Aug 20 05:54:32 2020 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: pmap.h,v 1.16 2020/08/07 07:19:45 skrll Exp $ */
+/* $NetBSD: pmap.h,v 1.17 2020/08/20 05:54:32 mrg Exp $ */
/*
* Copyright (c) 1992, 1993
@@ -78,6 +78,7 @@
#ifdef UVMHIST
UVMHIST_DECL(pmapexechist);
UVMHIST_DECL(pmaphist);
+UVMHIST_DECL(pmapsegtabhist);
#endif
/*
diff -r d4a77ac6bb99 -r 80c717265be1 sys/uvm/pmap/pmap_segtab.c
--- a/sys/uvm/pmap/pmap_segtab.c Thu Aug 20 05:46:31 2020 +0000
+++ b/sys/uvm/pmap/pmap_segtab.c Thu Aug 20 05:54:32 2020 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: pmap_segtab.c,v 1.18 2020/08/18 11:48:21 simonb Exp $ */
+/* $NetBSD: pmap_segtab.c,v 1.19 2020/08/20 05:54:32 mrg 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.18 2020/08/18 11:48:21 simonb Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pmap_segtab.c,v 1.19 2020/08/20 05:54:32 mrg Exp $");
/*
* Manages physical address maps.
@@ -131,16 +131,32 @@
kmutex_t pmap_segtab_lock __cacheline_aligned;
+/*
+ * Check that a seg_tab[] array is empty.
+ *
+ * This is used when allocating or freeing a pmap_segtab_t. The stp
+ * should be unused -- meaning, none of the seg_tab[] pointers are
+ * not NULL, as it transitions from either freshly allocated segtab from
+ * pmap pool, an unused allocated page segtab alloc from the SMP case,
+ * where two CPUs attempt to allocate the same underlying segtab, the
+ * release of a segtab entry to the freelist, or for SMP, where reserve
+ * also frees a freshly allocated but unused entry.
+ */
static void
pmap_check_stp(pmap_segtab_t *stp, const char *caller, const char *why)
{
#ifdef DEBUG
for (size_t i = 0; i < PMAP_SEGTABSIZE; i++) {
- if (stp->seg_tab[i] != 0) {
+ if (stp->seg_tab[i] != NULL) {
+#define DEBUG_NOISY
#ifdef DEBUG_NOISY
+ UVMHIST_FUNC(__func__);
+ UVMHIST_CALLARGS(pmapsegtabhist, "stp=%#jx",
+ (uintptr_t)stp, 0, 0, 0);
for (size_t j = i; j < PMAP_SEGTABSIZE; j++)
- printf("%s: pm_segtab.seg_tab[%zu] = %p\n",
- caller, j, stp->seg_tab[j]);
+ if (stp->seg_tab[j] != NULL)
+ printf("%s: stp->seg_tab[%zu] = %p\n",
+ caller, j, stp->seg_tab[j]);
#endif
panic("%s: pm_segtab.seg_tab[%zu] != 0 (%p): %s",
caller, i, stp->seg_tab[i], why);
@@ -149,6 +165,31 @@
#endif
}
+/*
+ * Check that an array of ptes is actually zero.
+ */
+static void
+pmap_check_ptes(pt_entry_t *pte, const char *caller)
+{
+#ifdef DEBUG
+ for (size_t i = 0; i < NPTEPG; i++)
+ if (!pte_zero_p(pte[i])) {
+#ifdef DEBUG_NOISY
+ UVMHIST_FUNC(__func__);
+ UVMHIST_CALLARGS(pmapsegtabhist, "pte=%#jx",
+ (uintptr_t)pte, 0, 0, 0);
+ for (size_t j = i + 1; j < NPTEPG; j++)
+ if (!pte_zero_p(pte[j]))
+ UVMHIST_LOG(pmapsegtabhist,
+ "pte[%zu] = %#"PRIxPTE,
+ j, pte_value(pte[j]), 0, 0);
+#endif
+ panic("%s: pte[%ju] entry at %pu not 0 (%#"PRIxPTE")",
+ caller, i, &pte[i], pte_value(pte[i]));
+ }
+#endif
+}
+
static inline struct vm_page *
pmap_pte_pagealloc(void)
{
@@ -190,12 +231,16 @@
return pte + ((va >> PGSHIFT) & (NPTEPG - 1));
}
+/*
+ * Insert the segtab into the segtab freelist.
+ */
static void
pmap_segtab_free(pmap_segtab_t *stp)
{
- /*
- * Insert the segtab into the segtab freelist.
- */
+ UVMHIST_FUNC(__func__);
+
+ UVMHIST_CALLARGS(pmapsegtabhist, "stp=%#jx", stp, 0, 0, 0);
+
mutex_spin_enter(&pmap_segtab_lock);
stp->seg_seg[0] = pmap_segtab_info.free_segtab;
pmap_segtab_info.free_segtab = stp;
@@ -211,9 +256,9 @@
pmap_segtab_t *stp = *stp_p;
UVMHIST_FUNC(__func__);
- UVMHIST_CALLARGS(pmaphist, "pm=%#jx stpp=%#jx free=%jd",
+ UVMHIST_CALLARGS(pmapsegtabhist, "pm=%#jx stpp=%#jx free=%jd",
(uintptr_t)pmap, (uintptr_t)stp_p, free_stp, 0);
- UVMHIST_LOG(pmaphist, " callback=%jx flags=%jx va=%jx vinc=%jx",
+ UVMHIST_LOG(pmapsegtabhist, " callback=%jx flags=%jx va=%jx vinc=%jx",
(uintptr_t)callback, flags, (uintptr_t)va, (uintptr_t)vinc);
for (size_t i = (va / vinc) & (PMAP_SEGTABSIZE - 1);
i < PMAP_SEGTABSIZE;
@@ -221,7 +266,8 @@
#ifdef _LP64
if (vinc > NBSEG) {
if (stp->seg_seg[i] != NULL) {
- UVMHIST_LOG(pmaphist, " recursing", 0, 0, 0, 0);
+ UVMHIST_LOG(pmapsegtabhist,
+ " recursing %jd", i, 0, 0, 0);
pmap_segtab_release(pmap, &stp->seg_seg[i],
true, callback, flags, va, vinc / NSEGPG);
KASSERT(stp->seg_seg[i] == NULL);
@@ -235,6 +281,18 @@
pt_entry_t *pte = stp->seg_tab[i];
if (pte == NULL)
continue;
+ pmap_check_ptes(pte, __func__);
+
+#if defined(__mips_n64) && PAGE_SIZE == 8192
+ /*
+ * XXX This is evil. If vinc is 1000000 we are in
+ * the last level, and this pte should be page aligned.
+ */
+ if (vinc == 0x1000000 && ((uintptr_t)pte & PAGE_MASK) != 0) {
+ panic("%s: pte entry at %p not page aligned",
+ __func__, pte);
+ }
+#endif
/*
* If our caller wants a callback, do so.
@@ -242,13 +300,7 @@
if (callback != NULL) {
(*callback)(pmap, va, va + vinc, pte, flags);
}
-#ifdef DEBUG
- for (size_t j = 0; j < NPTEPG; j++) {
- if (!pte_zero_p(pte[j]))
- panic("%s: pte entry at %p not 0 (%#"PRIxPTE")",
- __func__, &pte[j], pte_value(pte[j]));
- }
-#endif
+
// PMAP_UNMAP_POOLPAGE should handle any VCA issues itself
paddr_t pa = PMAP_UNMAP_POOLPAGE((vaddr_t)pte);
struct vm_page *pg = PHYS_TO_VM_PAGE(pa);
@@ -261,7 +313,7 @@
#endif
stp->seg_tab[i] = NULL;
- UVMHIST_LOG(pmaphist, " zeroing tab[%jd]", i, 0, 0, 0);
+ UVMHIST_LOG(pmapsegtabhist, " zeroing tab[%jd]", i, 0, 0, 0);
}
if (free_stp) {
@@ -290,6 +342,7 @@
pmap_segtab_t *stp;
bool found_on_freelist = false;
+ UVMHIST_FUNC(__func__);
again:
mutex_spin_enter(&pmap_segtab_lock);
if (__predict_true((stp = pmap_segtab_info.free_segtab) != NULL)) {
@@ -297,6 +350,7 @@
stp->seg_seg[0] = NULL;
SEGTAB_ADD(nget, 1);
found_on_freelist = true;
+ UVMHIST_CALLARGS(pmapsegtabhist, "freelist stp=%#jx", stp, 0, 0, 0);
}
mutex_spin_exit(&pmap_segtab_lock);
@@ -314,6 +368,7 @@
const paddr_t stp_pa = VM_PAGE_TO_PHYS(stp_pg);
stp = (pmap_segtab_t *)PMAP_MAP_POOLPAGE(stp_pa);
+ UVMHIST_CALLARGS(pmapsegtabhist, "new stp=%#jx", stp, 0, 0, 0);
const size_t n = NBPG / sizeof(*stp);
if (n > 1) {
/*
@@ -454,10 +509,7 @@
{
pmap_segtab_t *stp = pmap->pm_segtab;
pt_entry_t *pte;
-
UVMHIST_FUNC(__func__);
- UVMHIST_CALLARGS(pmaphist, "pm=%#jx va=%#jx flags=%jx",
- (uintptr_t)pmap, (uintptr_t)va, flags, 0);
pte = pmap_pte_lookup(pmap, va);
if (__predict_false(pte == NULL)) {
@@ -524,16 +576,11 @@
*pte_p = pte;
#endif
KASSERT(pte == stp->seg_tab[(va >> SEGSHIFT) & (PMAP_SEGTABSIZE - 1)]);
- UVMHIST_LOG(pmaphist, " set tab[%jd]=%jx",
- (va >> SEGSHIFT) & (PMAP_SEGTABSIZE - 1), pte, 0, 0);
+ UVMHIST_CALLARGS(pmapsegtabhist, "pm=%#jx va=%#jx -> tab[%jd]=%jx",
+ (uintptr_t)pmap, (uintptr_t)va,
+ (va >> SEGSHIFT) & (PMAP_SEGTABSIZE - 1), pte);
-#ifdef DEBUG
- for (size_t i = 0; i < NPTEPG; i++) {
- if (!pte_zero_p(pte[i]))
- panic("%s: new segmap %p not empty @ %zu",
- __func__, pte, i);
- }
-#endif
+ pmap_check_ptes(pte, __func__);
pte += (va >> PGSHIFT) & (NPTEPG - 1);
}
Home |
Main Index |
Thread Index |
Old Index