Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/arch/powerpc/powerpc Implement pmap_kenter_pa() and pmap...
details: https://anonhg.NetBSD.org/src/rev/68191842372d
branches: trunk
changeset: 518552:68191842372d
user: tsutsui <tsutsui%NetBSD.org@localhost>
date: Sat Dec 01 23:34:52 2001 +0000
description:
Implement pmap_kenter_pa() and pmap_kremove() properly.
This should fix `kernel diagnostic assertion "rv" failed' panic
and the problem was tracked down by tsubai.
Also add small optimization in pmap_enter() and pmap_remove(), from tsubai.
diffstat:
sys/arch/powerpc/powerpc/pmap.c | 119 ++++++++++++++++++++++++++++++++++++---
1 files changed, 108 insertions(+), 11 deletions(-)
diffs (165 lines):
diff -r e2e914db4765 -r 68191842372d sys/arch/powerpc/powerpc/pmap.c
--- a/sys/arch/powerpc/powerpc/pmap.c Sat Dec 01 23:06:45 2001 +0000
+++ b/sys/arch/powerpc/powerpc/pmap.c Sat Dec 01 23:34:52 2001 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: pmap.c,v 1.47 2001/10/13 18:28:10 chs Exp $ */
+/* $NetBSD: pmap.c,v 1.48 2001/12/01 23:34:52 tsutsui Exp $ */
/*
* Copyright (C) 1995, 1996 Wolfgang Solfrank.
@@ -1019,7 +1019,8 @@
/*
* Flush the real memory from the cache.
*/
- __syncicache((void *)pa, NBPG);
+ if (prot & VM_PROT_EXECUTE)
+ __syncicache((void *)pa, NBPG);
}
s = splvm();
@@ -1051,17 +1052,61 @@
paddr_t pa;
vm_prot_t prot;
{
- pmap_enter(pmap_kernel(), va, pa, prot, PMAP_WIRED);
-}
+ struct pmap *pm = pmap_kernel();
+ sr_t sr;
+ int idx, s;
+ pte_t pte;
+ struct pte_ovfl *po;
+ struct mem_region *mp;
+
+ /*
+ * Have to remove any existing mapping first.
+ */
+ pmap_kremove(va, NBPG);
+
+ /*
+ * Compute the HTAB index.
+ */
+ idx = pteidx(sr = ptesr(pm->pm_sr, va), va);
+ /*
+ * Construct the PTE.
+ *
+ * Note: Don't set the valid bit for correct operation of tlb update.
+ */
+ pte.pte_hi = ((sr & SR_VSID) << PTE_VSID_SHFT)
+ | ((va & ADDR_PIDX) >> ADDR_API_SHFT);
+ pte.pte_lo = (pa & PTE_RPGN) | PTE_M | PTE_I | PTE_G;
-void
-pmap_kremove(va, len)
- vaddr_t va;
- vsize_t len;
-{
- for (len >>= PAGE_SHIFT; len > 0; len--, va += PAGE_SIZE) {
- pmap_remove(pmap_kernel(), va, va + PAGE_SIZE);
+ for (mp = mem; mp->size; mp++) {
+ if (pa >= mp->start && pa < mp->start + mp->size) {
+ pte.pte_lo &= ~(PTE_I | PTE_G);
+ break;
+ }
}
+ if (prot & VM_PROT_WRITE)
+ pte.pte_lo |= PTE_RW;
+ else
+ pte.pte_lo |= PTE_RO;
+
+ s = splvm();
+ pm->pm_stats.resident_count++;
+ /*
+ * Try to insert directly into HTAB.
+ */
+ if (pte_insert(idx, &pte)) {
+ splx(s);
+ return;
+ }
+
+ /*
+ * Have to allocate overflow entry.
+ *
+ * Note, that we must use real addresses for these.
+ */
+ po = poalloc();
+ po->po_pte = pte;
+ LIST_INSERT_HEAD(potable + idx, po, po_list);
+ splx(s);
}
/*
@@ -1088,6 +1133,7 @@
tlbie(va);
tlbsync();
pm->pm_stats.resident_count--;
+ goto next;
}
for (ptp = ptable + (idx ^ ptab_mask) * 8, i = 8; --i >= 0; ptp++)
if (ptematch(ptp, sr, va, PTE_VALID | PTE_HID)) {
@@ -1097,6 +1143,7 @@
tlbie(va);
tlbsync();
pm->pm_stats.resident_count--;
+ goto next;
}
for (po = potable[idx].lh_first; po; po = npo) {
npo = po->po_list.le_next;
@@ -1106,8 +1153,58 @@
LIST_REMOVE(po, po_list);
pofree(po, 1);
pm->pm_stats.resident_count--;
+ goto next;
}
}
+ next:
+ va += NBPG;
+ }
+ splx(s);
+}
+
+void
+pmap_kremove(va, len)
+ vaddr_t va;
+ vsize_t len;
+{
+ struct pmap *pm = pmap_kernel();
+ vaddr_t endva = va + len;
+ int idx, i, s;
+ sr_t sr;
+ pte_t *ptp;
+ struct pte_ovfl *po, *npo;
+
+ s = splvm();
+ while (va < endva) {
+ idx = pteidx(sr = ptesr(pm->pm_sr, va), va);
+ for (ptp = ptable + idx * 8, i = 8; --i >= 0; ptp++)
+ if (ptematch(ptp, sr, va, PTE_VALID)) {
+ ptp->pte_hi &= ~PTE_VALID;
+ asm volatile ("sync");
+ tlbie(va);
+ tlbsync();
+ pm->pm_stats.resident_count--;
+ goto next;
+ }
+ for (ptp = ptable + (idx ^ ptab_mask) * 8, i = 8; --i >= 0; ptp++)
+ if (ptematch(ptp, sr, va, PTE_VALID | PTE_HID)) {
+ ptp->pte_hi &= ~PTE_VALID;
+ asm volatile ("sync");
+ tlbie(va);
+ tlbsync();
+ pm->pm_stats.resident_count--;
+ goto next;
+ }
+ for (po = potable[idx].lh_first; po; po = npo) {
+ npo = po->po_list.le_next;
+ if (ptematch(&po->po_pte, sr, va, 0)) {
+ LIST_REMOVE(po, po_list);
+ pofree(po, 1);
+ pm->pm_stats.resident_count--;
+ goto next;
+ }
+ }
+ next:
va += NBPG;
}
splx(s);
Home |
Main Index |
Thread Index |
Old Index