Subject: Re: Any clues?
To: John Klos <john@ziaspace.com>
From: Chuck Silvers <chuq@chuq.com>
List: port-macppc
Date: 08/15/2004 08:45:56
--liOOAslEiF7prFVr
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
hi,
this happens because the machine runs out of memory and the ppc pmap
doesn't know how to reclaim another active pvo entry.
try the attached patch.
-Chuck
On Tue, Aug 10, 2004 at 10:53:18PM -0400, John Klos wrote:
> Hi,
>
> Just saw this today when I had 8179 processes running at the same time.
> NetBSD 2.0 from a few days ago.
>
> Aug 11 02:44:25 lain /netbsd: proc: table is full - increase kern.maxproc
> or NP
> OC
> panic: pmap_pvo_enter: failed
> Begin traceback...
> 0xda0178b0: at pmap_pvo_enter+0x334
> 0xda017900: at pmap_enter+0x198
> 0xda017930: at ubc_fault+0x37c
> 0xda0179e0: at uvm_fault+0x1068
> 0xda017b10: at trap+0x2c0
> 0xda017b90: kernel DSI read trap @ 0xd57f4000 by memcpy+0x88: srr1=0x9032
> 0
> r1=0xda017c50 cr=0x40000024 xer=0x20000000 ctr=0xb6
> dsisr=0x4000000
> 0xda017c50: at ddbstk+0x1fa4
> 0xda017c60: at pmap_pvo_remove+0x230
> 0xda017cf0: at uiomove+0x1b0
> 0xda017d20: at ffs_read+0x4ac
> 0xda017dc0: at vn_read+0x114
> 0xda017e40: at dofileread+0xb8
> 0xda017eb0: at sys_read+0x8c
> 0xda017ed0: at syscall_plain+0xe0
> 0xda017f40: user SC trap #3 by 0x41873498: srr1=0xd032
> r1=0xffffd6b0 cr=0x20000044 xer=0 ctr=0x41901684
> End traceback...
--liOOAslEiF7prFVr
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="diff.pmap-ppc-pvoreclaim"
Index: src/sys/arch/powerpc/oea/pmap.c
===================================================================
RCS file: /cvsroot/src/sys/arch/powerpc/oea/pmap.c,v
retrieving revision 1.24
diff -u -p -r1.24 pmap.c
--- src/sys/arch/powerpc/oea/pmap.c 9 Jun 2004 19:30:57 -0000 1.24
+++ src/sys/arch/powerpc/oea/pmap.c 15 Aug 2004 15:44:14 -0000
@@ -243,10 +243,10 @@ STATIC void pmap_pvo_check(const struct
STATIC int pmap_pte_insert(int, struct pte *);
STATIC int pmap_pvo_enter(pmap_t, struct pool *, struct pvo_head *,
vaddr_t, paddr_t, register_t, int);
-STATIC void pmap_pvo_remove(struct pvo_entry *, int);
+STATIC void pmap_pvo_remove(struct pvo_entry *, int, boolean_t);
STATIC struct pvo_entry *pmap_pvo_find_va(pmap_t, vaddr_t, int *);
STATIC volatile struct pte *pmap_pvo_to_pte(const struct pvo_entry *, int);
-#define pmap_pvo_reclaim(pm) NULL
+STATIC struct pvo_entry *pmap_pvo_reclaim(struct pmap *);
STATIC void pvo_set_exec(struct pvo_entry *);
STATIC void pvo_clear_exec(struct pvo_entry *);
@@ -255,6 +255,8 @@ STATIC void tlbia(void);
STATIC void pmap_release(pmap_t);
STATIC void *pmap_boot_find_memory(psize_t, psize_t, int);
+static uint32_t pmap_reclaim_nextidx;
+
#define VSID_NBPW (sizeof(uint32_t) * 8)
static uint32_t pmap_vsid_bitmap[NPMAPS / VSID_NBPW];
@@ -1489,6 +1491,33 @@ pmap_pvo_check(const struct pvo_entry *p
#endif /* DEBUG || PMAPCHECK */
/*
+ * Search the PVO table looking for a non-wired entry for the given pmap.
+ * If we find one, remove it and return it.
+ */
+
+struct pvo_entry *
+pmap_pvo_reclaim(struct pmap *pm)
+{
+ struct pvo_tqhead *pvoh;
+ struct pvo_entry *pvo;
+ uint32_t idx, endidx;
+
+ endidx = pmap_reclaim_nextidx++;
+ for (idx = (endidx + 1) & pmap_pteg_mask; idx != endidx;
+ idx = (idx + 1) & pmap_pteg_mask) {
+ pvoh = &pmap_pvo_table[idx];
+ TAILQ_FOREACH(pvo, pvoh, pvo_olink) {
+ if (pvo->pvo_pmap == pm &&
+ (pvo->pvo_vaddr & PVO_WIRED) == 0) {
+ pmap_pvo_remove(pvo, -1, FALSE);
+ return pvo;
+ }
+ }
+ }
+ return NULL;
+}
+
+/*
* This returns whether this is the first mapping of a page.
*/
int
@@ -1539,7 +1568,7 @@ pmap_pvo_enter(pmap_t pm, struct pool *p
}
#endif
PMAPCOUNT(mappings_replaced);
- pmap_pvo_remove(pvo, -1);
+ pmap_pvo_remove(pvo, -1, TRUE);
break;
}
}
@@ -1562,6 +1591,7 @@ pmap_pvo_enter(pmap_t pm, struct pool *p
return ENOMEM;
}
}
+
pvo->pvo_vaddr = va;
pvo->pvo_pmap = pm;
pvo->pvo_vaddr &= ~ADDR_POFF;
@@ -1626,7 +1656,7 @@ pmap_pvo_enter(pmap_t pm, struct pool *p
}
void
-pmap_pvo_remove(struct pvo_entry *pvo, int pteidx)
+pmap_pvo_remove(struct pvo_entry *pvo, int pteidx, boolean_t free)
{
volatile struct pte *pt;
int ptegidx;
@@ -1697,8 +1727,10 @@ pmap_pvo_remove(struct pvo_entry *pvo, i
*/
LIST_REMOVE(pvo, pvo_vlink);
TAILQ_REMOVE(&pmap_pvo_table[ptegidx], pvo, pvo_olink);
- pool_put(pvo->pvo_vaddr & PVO_MANAGED
- ? &pmap_mpvo_pool : &pmap_upvo_pool, pvo);
+ if (free) {
+ pool_put(pvo->pvo_vaddr & PVO_MANAGED ? &pmap_mpvo_pool :
+ &pmap_upvo_pool, pvo);
+ }
#if defined(DIAGNOSTIC) || defined(DEBUG) || defined(PMAPCHECK)
pmap_pvo_remove_depth--;
#endif
@@ -1933,7 +1965,7 @@ pmap_remove(pmap_t pm, vaddr_t va, vaddr
for (; va < endva; va += PAGE_SIZE) {
pvo = pmap_pvo_find_va(pm, va, &pteidx);
if (pvo != NULL) {
- pmap_pvo_remove(pvo, pteidx);
+ pmap_pvo_remove(pvo, pteidx, TRUE);
}
}
pmap_interrupts_restore(msr);
@@ -2125,7 +2157,7 @@ pmap_page_protect(struct vm_page *pg, vm
* Downgrading to no mapping at all, we just remove the entry.
*/
if ((prot & VM_PROT_READ) == 0) {
- pmap_pvo_remove(pvo, -1);
+ pmap_pvo_remove(pvo, -1, TRUE);
continue;
}
--liOOAslEiF7prFVr--