Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/arch/sparc/sparc * Allow pv_link4_4c() to fail with ENOM...
details: https://anonhg.NetBSD.org/src/rev/7834e29f1b8b
branches: trunk
changeset: 565341:7834e29f1b8b
user: pk <pk%NetBSD.org@localhost>
date: Sun Apr 04 18:34:35 2004 +0000
description:
* Allow pv_link4_4c() to fail with ENOMEM on pool allocation failures
(catching up with pv_link4m()).
* Fix return code checking for pv_link4m() calls.
* Add low water setting to pv pool.
diffstat:
sys/arch/sparc/sparc/pmap.c | 157 +++++++++++++++++++++++++++----------------
1 files changed, 98 insertions(+), 59 deletions(-)
diffs (truncated from 314 to 300 lines):
diff -r 88bb6c986e49 -r 7834e29f1b8b sys/arch/sparc/sparc/pmap.c
--- a/sys/arch/sparc/sparc/pmap.c Sun Apr 04 18:24:22 2004 +0000
+++ b/sys/arch/sparc/sparc/pmap.c Sun Apr 04 18:34:35 2004 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: pmap.c,v 1.277 2004/04/03 23:11:14 pk Exp $ */
+/* $NetBSD: pmap.c,v 1.278 2004/04/04 18:34:35 pk Exp $ */
/*
* Copyright (c) 1996
@@ -56,7 +56,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.277 2004/04/03 23:11:14 pk Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.278 2004/04/04 18:34:35 pk Exp $");
#include "opt_ddb.h"
#include "opt_kgdb.h"
@@ -556,7 +556,7 @@
int, struct vm_page *, int);
/*static*/ void pv_changepte4_4c(struct vm_page *, int, int);
/*static*/ int pv_syncflags4_4c(struct vm_page *);
-/*static*/ int pv_link4_4c(struct vm_page *, struct pmap *, vaddr_t, int);
+/*static*/ int pv_link4_4c(struct vm_page *, struct pmap *, vaddr_t, u_int *);
/*static*/ void pv_unlink4_4c(struct vm_page *, struct pmap *, vaddr_t);
#endif
@@ -2578,8 +2578,12 @@
} else {
struct pvlist *prev;
+ pmap_stats.ps_unlink_pvsearch++;
for (prev = pv0;; prev = npv, npv = npv->pv_next) {
- pmap_stats.ps_unlink_pvsearch++;
+ if (npv == NULL) {
+ panic("pv_unlink: pm %p is missing on pg %p",
+ pm, pg);
+ }
if (npv->pv_pmap == pm && npv->pv_va == va)
break;
}
@@ -2606,17 +2610,16 @@
* be cached.
*/
/*static*/ int
-pv_link4_4c(pg, pm, va, nc)
+pv_link4_4c(pg, pm, va, pteprotop)
struct vm_page *pg;
struct pmap *pm;
vaddr_t va;
- int nc;
-{
- struct pvlist *pv0, *npv;
- int ret;
+ unsigned int *pteprotop;
+{
+ struct pvlist *pv0, *pv, *npv;
+ int nc = (*pteprotop & PG_NC) != 0 ? PV_NC : 0;
pv0 = VM_MDPAGE_PVHEAD(pg);
- ret = nc ? PG_NC : 0;
if (pv0->pv_pmap == NULL) {
/* no pvlist entries yet */
@@ -2624,55 +2627,66 @@
pv0->pv_next = NULL;
pv0->pv_pmap = pm;
pv0->pv_va = va;
- pv0->pv_flags |= nc ? PV_NC : 0;
- return (ret);
- }
+ pv0->pv_flags |= nc;
+ return (0);
+ }
+
+ /*
+ * Allocate the new PV entry now, and, if that fails, bail out
+ * before changing the cacheable state of the existing mappings.
+ */
+ npv = pool_get(&pv_pool, PR_NOWAIT);
+ if (npv == NULL)
+ return (ENOMEM);
+
+ pmap_stats.ps_enter_secondpv++;
+
/*
* Before entering the new mapping, see if
* it will cause old mappings to become aliased
* and thus need to be `discached'.
*/
- pmap_stats.ps_enter_secondpv++;
if (pv0->pv_flags & PV_ANC) {
/* already uncached, just stay that way */
- ret = PG_NC;
- } else {
- for (npv = pv0; npv != NULL; npv = npv->pv_next) {
- if (npv->pv_flags & PV_NC) {
- ret = PG_NC;
-#ifdef DEBUG
- /* Check currently illegal condition */
- if (nc == 0)
- printf("pv_link: proc %s, va=0x%lx: "
- "unexpected uncached mapping at 0x%lx\n",
- curproc ? curproc->p_comm : "--",
- va, npv->pv_va);
-#endif
- }
- if (BADALIAS(va, npv->pv_va)) {
+ *pteprotop |= PG_NC;
+ goto link_npv;
+ }
+
+ for (pv = pv0; pv != NULL; pv = pv->pv_next) {
+ if ((pv->pv_flags & PV_NC) != 0) {
+ *pteprotop |= PG_NC;
#ifdef DEBUG
- if (pmapdebug & PDB_CACHESTUFF)
- printf(
- "pv_link: badalias: proc %s, 0x%lx<=>0x%lx, pv %p\n",
- curproc ? curproc->p_comm : "--",
- va, npv->pv_va, pg);
-#endif
- /* Mark list head `uncached due to aliases' */
- pv0->pv_flags |= PV_ANC;
- pv_changepte4_4c(pg, ret = PG_NC, 0);
- break;
- }
+ /* Check currently illegal condition */
+ if (nc == 0)
+ printf("pv_link: proc %s, va=0x%lx: "
+ "unexpected uncached mapping at 0x%lx\n",
+ curproc ? curproc->p_comm : "--",
+ va, pv->pv_va);
+#endif
}
- }
- npv = pool_get(&pv_pool, PR_NOWAIT);
- if (npv == NULL)
- panic("pv_link: pv_pool exhausted");
+ if (BADALIAS(va, pv->pv_va)) {
+#ifdef DEBUG
+ if (pmapdebug & PDB_CACHESTUFF)
+ printf(
+ "pv_link: badalias: proc %s, 0x%lx<=>0x%lx, pg %p\n",
+ curproc ? curproc->p_comm : "--",
+ va, pv->pv_va, pg);
+#endif
+ /* Mark list head `uncached due to aliases' */
+ pv0->pv_flags |= PV_ANC;
+ pv_changepte4_4c(pg, PG_NC, 0);
+ *pteprotop |= PG_NC;
+ break;
+ }
+ }
+
+link_npv:
npv->pv_next = pv0->pv_next;
npv->pv_pmap = pm;
npv->pv_va = va;
- npv->pv_flags = nc ? PV_NC : 0;
+ npv->pv_flags = nc;
pv0->pv_next = npv;
- return (ret);
+ return (0);
}
#endif /* SUN4 || SUN4C */
@@ -2867,13 +2881,13 @@
} else {
struct pvlist *prev;
+ pmap_stats.ps_unlink_pvsearch++;
for (prev = pv0;; prev = npv, npv = npv->pv_next) {
if (npv == NULL) {
- panic("pm %p is missing ", pm);
- printf("pm %p is missing ", pm);
+ panic("pv_unlink: pm %p is missing on pg %p",
+ pm, pg);
goto out;
}
- pmap_stats.ps_unlink_pvsearch++;
if (npv->pv_pmap == pm && npv->pv_va == va)
break;
}
@@ -2935,8 +2949,6 @@
goto out;
}
- pmap_stats.ps_enter_secondpv++;
-
/*
* Allocate the new PV entry now, and, if that fails, bail out
* before changing the cacheable state of the existing mappings.
@@ -2947,6 +2959,8 @@
goto out;
}
+ pmap_stats.ps_enter_secondpv++;
+
/*
* See if the new mapping will cause old mappings to
* become aliased and thus need to be `discached'.
@@ -2995,7 +3009,7 @@
out:
simple_unlock(&pg->mdpage.pv_slock);
- return (0);
+ return (error);
}
#endif
@@ -4371,6 +4385,11 @@
}
#endif /* SUN4M || SUN4D */
+ /* XXX - a peculiar place to do this, but we can't do it in pmap_init
+ * and here at least it's off the beaten code track.
+ */
+{static int x; if (x == 0) pool_setlowat(&pv_pool, 512), x = 1; }
+
return (0);
}
@@ -5698,6 +5717,7 @@
int *ptep;
struct regmap *rp;
struct segmap *sp;
+ int error = 0;
vr = VA_VREG(va);
vs = VA_VSEG(va);
@@ -5738,6 +5758,9 @@
cache_flush_page(va, 0);
}
}
+ *ptep = 0;
+ if (inmmu)
+ setpte4(va, 0);
if (pte & PG_WIRED)
sp->sg_nwired--;
pm->pm_stats.resident_count--;
@@ -5759,8 +5782,13 @@
/*
* If the new mapping is for a managed PA, enter into pvlist.
*/
- if (pg != NULL)
- pteproto |= pv_link4_4c(pg, pm, va, pteproto & PG_NC);
+ if (pg != NULL && (error = pv_link4_4c(pg, pm, va, &pteproto)) != 0) {
+ if (--sp->sg_npte == 0)
+ pgt_lvl23_remove4_4c(pm, rp, sp, vr, vs);
+ if ((flags & PMAP_CANFAIL) != 0)
+ goto out;
+ panic("pmap_enter: cannot allocate PV entry");
+ }
/* Update S/W page table */
*ptep = pteproto;
@@ -5781,8 +5809,9 @@
/* Update H/W page table */
setpte4(va, pteproto & ~PG_MBZ);
+out:
splx(s);
- return (0);
+ return (error);
}
/* enter new (or change existing) user mapping */
@@ -5928,6 +5957,9 @@
if (pte & PG_WIRED)
sp->sg_nwired--;
pm->pm_stats.resident_count--;
+ ptep[VA_VPG(va)] = 0;
+ if (sp->sg_pmeg != seginval)
+ setpte4(va, 0);
} else {
/* adding new entry */
sp->sg_npte++;
@@ -5940,8 +5972,15 @@
}
}
- if (pg != NULL)
- pteproto |= pv_link4_4c(pg, pm, va, pteproto & PG_NC);
+ if (pg != NULL && (error = pv_link4_4c(pg, pm, va, &pteproto)) != 0) {
+ if (--sp->sg_npte == 0)
+ /* Sigh, undo pgt allocations */
+ pgt_lvl23_remove4_4c(pm, rp, sp, vr, vs);
+
+ if ((flags & PMAP_CANFAIL) != 0)
+ goto out;
+ panic("pmap_enter: cannot allocate PV entry");
+ }
/* Update S/W page table */
ptep += VA_VPG(va);
@@ -6368,7 +6407,7 @@
/*
* If the new mapping is for a managed PA, enter into pvlist.
*/
Home |
Main Index |
Thread Index |
Old Index