Module Name: src
Committed By: riz
Date: Wed May 9 22:42:32 UTC 2012
Modified Files:
src/sys/arch/evbppc/mpc85xx [netbsd-6]: machdep.c
src/sys/arch/powerpc/booke [netbsd-6]: booke_pmap.c e500_tlb.c
src/sys/arch/powerpc/conf [netbsd-6]: files.powerpc
src/sys/arch/powerpc/include/booke [netbsd-6]: e500var.h pmap.h
Added Files:
src/sys/arch/powerpc/conf [netbsd-6]: kern-mb.ldscript
Log Message:
Pull up following revision(s) (requested by matt in ticket #241):
sys/arch/powerpc/conf/kern-mb.ldscript: revision 1.1
sys/arch/powerpc/include/booke/pmap.h: revision 1.9
sys/arch/powerpc/booke/e500_tlb.c: revision 1.8
sys/arch/powerpc/conf/files.powerpc: revision 1.83
sys/arch/powerpc/booke/booke_pmap.c: revision 1.13
sys/arch/powerpc/include/booke/e500var.h: revision 1.5
sys/arch/evbppc/mpc85xx/machdep.c: revision 1.23
Add ldscript which aligns .data to a 1MB boundary. (used for testing)
Add PMAP_MINIMALTLB defflag
Add vsize_t to pmap_md_{un,}map_poolpage.
Add pmap_kvptefill prototype.
Slightly change pmap_bootstrap prototype.
Add e500_tlb_minimize prototype.
Add support PMAP_MINIMALTLB option. This changes the default use of TLB1
entries to map all of physical memory to using two TLB1 entries, one for
mapping text and one for data. The rest of memory is mapped using the
page table which is updated as needed. This is used to trap memory
corruption issues.
Add support for PMAP_MINIMALTLB.
To generate a diff of this commit:
cvs rdiff -u -r1.22 -r1.22.2.1 src/sys/arch/evbppc/mpc85xx/machdep.c
cvs rdiff -u -r1.12 -r1.12.2.1 src/sys/arch/powerpc/booke/booke_pmap.c
cvs rdiff -u -r1.7 -r1.7.8.1 src/sys/arch/powerpc/booke/e500_tlb.c
cvs rdiff -u -r1.82 -r1.82.8.1 src/sys/arch/powerpc/conf/files.powerpc
cvs rdiff -u -r0 -r1.1.6.2 src/sys/arch/powerpc/conf/kern-mb.ldscript
cvs rdiff -u -r1.4 -r1.4.8.1 src/sys/arch/powerpc/include/booke/e500var.h
cvs rdiff -u -r1.8 -r1.8.8.1 src/sys/arch/powerpc/include/booke/pmap.h
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/arch/evbppc/mpc85xx/machdep.c
diff -u src/sys/arch/evbppc/mpc85xx/machdep.c:1.22 src/sys/arch/evbppc/mpc85xx/machdep.c:1.22.2.1
--- src/sys/arch/evbppc/mpc85xx/machdep.c:1.22 Fri Jan 27 18:52:54 2012
+++ src/sys/arch/evbppc/mpc85xx/machdep.c Wed May 9 22:42:32 2012
@@ -1,4 +1,4 @@
-/* $NetBSD: machdep.c,v 1.22 2012/01/27 18:52:54 para Exp $ */
+/* $NetBSD: machdep.c,v 1.22.2.1 2012/05/09 22:42:32 riz Exp $ */
/*-
* Copyright (c) 2010, 2011 The NetBSD Foundation, Inc.
* All rights reserved.
@@ -1126,44 +1126,20 @@ initppc(vaddr_t startkernel, vaddr_t end
/*
* Initialize the pmap.
*/
- pmap_bootstrap(startkernel, endkernel, availmemr, nmemr);
+ endkernel = pmap_bootstrap(startkernel, endkernel, availmemr, nmemr);
/*
* Let's take all the indirect calls via our stubs and patch
* them to be direct calls.
*/
cpu_fixup_stubs();
-#if 0
+
/*
* As a debug measure we can change the TLB entry that maps all of
* memory to one that encompasses the 64KB with the kernel vectors.
* All other pages will be soft faulted into the TLB as needed.
*/
- const uint32_t saved_mas0 = mfspr(SPR_MAS0);
- mtspr(SPR_MAS6, 0);
- __asm volatile("tlbsx\t0, %0" :: "b"(startkernel));
- uint32_t mas0 = mfspr(SPR_MAS0);
- uint32_t mas1 = mfspr(SPR_MAS1);
- uint32_t mas2 = mfspr(SPR_MAS2);
- uint32_t mas3 = mfspr(SPR_MAS3);
- KASSERT(mas3 & MAS3_SW);
- KASSERT(mas3 & MAS3_SR);
- KASSERT(mas3 & MAS3_SX);
- mas1 = (mas1 & ~MAS1_TSIZE) | MASX_TSIZE_64KB;
- pt_entry_t xpn_mask = ~0 << (10 + 2 * MASX_TSIZE_GET(mas1));
- mas2 = (mas2 & ~(MAS2_EPN )) | (startkernel & xpn_mask);
- mas3 = (mas3 & ~(MAS3_RPN|MAS3_SW)) | (startkernel & xpn_mask);
- printf(" %#lx=<%#x,%#x,%#x,%#x>", startkernel, mas0, mas1, mas2, mas3);
-#if 1
- mtspr(SPR_MAS1, mas1);
- mtspr(SPR_MAS2, mas2);
- mtspr(SPR_MAS3, mas3);
- extern void tlbwe(void);
- tlbwe();
- mtspr(SPR_MAS0, saved_mas0);
- printf("(ok)");
-#endif
-#endif
+ e500_tlb_minimize(endkernel);
/*
* Set some more MD helpers
Index: src/sys/arch/powerpc/booke/booke_pmap.c
diff -u src/sys/arch/powerpc/booke/booke_pmap.c:1.12 src/sys/arch/powerpc/booke/booke_pmap.c:1.12.2.1
--- src/sys/arch/powerpc/booke/booke_pmap.c:1.12 Thu Feb 2 18:59:44 2012
+++ src/sys/arch/powerpc/booke/booke_pmap.c Wed May 9 22:42:32 2012
@@ -1,4 +1,4 @@
-/* $NetBSD: booke_pmap.c,v 1.12 2012/02/02 18:59:44 para Exp $ */
+/* $NetBSD: booke_pmap.c,v 1.12.2.1 2012/05/09 22:42:32 riz Exp $ */
/*-
* Copyright (c) 2010, 2011 The NetBSD Foundation, Inc.
* All rights reserved.
@@ -38,7 +38,7 @@
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: booke_pmap.c,v 1.12 2012/02/02 18:59:44 para Exp $");
+__KERNEL_RCSID(0, "$NetBSD: booke_pmap.c,v 1.12.2.1 2012/05/09 22:42:32 riz Exp $");
#include <sys/param.h>
#include <sys/kcore.h>
@@ -59,6 +59,8 @@ __KERNEL_RCSID(0, "$NetBSD: booke_pmap.c
CTASSERT(sizeof(struct pmap_segtab) == NBPG);
+struct pmap_segtab pmap_kernel_segtab;
+
void
pmap_procwr(struct proc *p, vaddr_t va, size_t len)
{
@@ -120,30 +122,46 @@ pmap_md_direct_mapped_vaddr_to_paddr(vad
return (paddr_t) va;
}
+#ifdef PMAP_MINIMALTLB
+static pt_entry_t *
+kvtopte(const struct pmap_segtab *stp, vaddr_t va)
+{
+ pt_entry_t * const ptep = stp->seg_tab[va >> SEGSHIFT];
+ if (ptep == NULL)
+ return NULL;
+ return &ptep[(va & SEGOFSET) >> PAGE_SHIFT];
+}
+
+vaddr_t
+pmap_kvptefill(vaddr_t sva, vaddr_t eva, pt_entry_t pt_entry)
+{
+ const struct pmap_segtab * const stp = pmap_kernel()->pm_segtab;
+ KASSERT(sva == trunc_page(sva));
+ pt_entry_t *ptep = kvtopte(stp, sva);
+ for (; sva < eva; sva += NBPG) {
+ *ptep++ = pt_entry ? (sva | pt_entry) : 0;
+ }
+ return sva;
+}
+#endif
+
/*
* Bootstrap the system enough to run with virtual memory.
* firstaddr is the first unused kseg0 address (not page aligned).
*/
-void
+vaddr_t
pmap_bootstrap(vaddr_t startkernel, vaddr_t endkernel,
- const phys_ram_seg_t *avail, size_t cnt)
+ phys_ram_seg_t *avail, size_t cnt)
{
- for (size_t i = 0; i < cnt; i++) {
- printf(" uvm_page_physload(%#lx,%#lx,%#lx,%#lx,%d)",
- atop(avail[i].start),
- atop(avail[i].start + avail[i].size) - 1,
- atop(avail[i].start),
- atop(avail[i].start + avail[i].size) - 1,
- VM_FREELIST_DEFAULT);
- uvm_page_physload(
- atop(avail[i].start),
- atop(avail[i].start + avail[i].size) - 1,
- atop(avail[i].start),
- atop(avail[i].start + avail[i].size) - 1,
- VM_FREELIST_DEFAULT);
- }
+ struct pmap_segtab * const stp = &pmap_kernel_segtab;
+
+ /*
+ * Initialize the kernel segment table.
+ */
+ pmap_kernel()->pm_segtab = stp;
+ curcpu()->ci_pmap_kern_segtab = stp;
- pmap_tlb_info_init(&pmap_tlb0_info); /* init the lock */
+ KASSERT(endkernel == trunc_page(endkernel));
/*
* Compute the number of pages kmem_arena will have.
@@ -160,7 +178,7 @@ pmap_bootstrap(vaddr_t startkernel, vadd
vsize_t bufsz = buf_memcalc();
buf_setvalimit(bufsz);
- vsize_t nsegtabs = pmap_round_seg(VM_PHYS_SIZE
+ vsize_t kv_nsegtabs = pmap_round_seg(VM_PHYS_SIZE
+ (ubc_nwins << ubc_winshift)
+ bufsz
+ 16 * NCARGS
@@ -169,7 +187,7 @@ pmap_bootstrap(vaddr_t startkernel, vadd
#ifdef SYSVSHM
+ NBPG * shminfo.shmall
#endif
- + NBPG * nkmempages);
+ + NBPG * nkmempages) >> SEGSHIFT;
/*
* Initialize `FYI' variables. Note we're relying on
@@ -179,68 +197,100 @@ pmap_bootstrap(vaddr_t startkernel, vadd
*/
pmap_limits.avail_start = vm_physmem[0].start << PGSHIFT;
pmap_limits.avail_end = vm_physmem[vm_nphysseg - 1].end << PGSHIFT;
- const vsize_t max_nsegtabs =
+ const size_t max_nsegtabs =
(pmap_round_seg(VM_MAX_KERNEL_ADDRESS)
- pmap_trunc_seg(VM_MIN_KERNEL_ADDRESS)) / NBSEG;
- if (nsegtabs >= max_nsegtabs) {
+ if (kv_nsegtabs >= max_nsegtabs) {
pmap_limits.virtual_end = VM_MAX_KERNEL_ADDRESS;
- nsegtabs = max_nsegtabs;
+ kv_nsegtabs = max_nsegtabs;
} else {
pmap_limits.virtual_end = VM_MIN_KERNEL_ADDRESS
- + nsegtabs * NBSEG;
+ + kv_nsegtabs * NBSEG;
}
- pmap_pvlist_lock_init(curcpu()->ci_ci.dcache_line_size);
-
/*
* Now actually allocate the kernel PTE array (must be done
* after virtual_end is initialized).
*/
- vaddr_t segtabs =
- uvm_pageboot_alloc(NBPG * nsegtabs + sizeof(struct pmap_segtab));
+ const vaddr_t kv_segtabs = avail[0].start;
+ KASSERT(kv_segtabs == endkernel);
+ KASSERT(avail[0].size >= NBPG * kv_nsegtabs);
+ printf(" kv_nsegtabs=%#"PRIxVSIZE, kv_nsegtabs);
+ printf(" kv_segtabs=%#"PRIxVADDR, kv_segtabs);
+ avail[0].start += NBPG * kv_nsegtabs;
+ avail[0].size -= NBPG * kv_nsegtabs;
+ endkernel += NBPG * kv_nsegtabs;
/*
* Initialize the kernel's two-level page level. This only wastes
* an extra page for the segment table and allows the user/kernel
* access to be common.
*/
- struct pmap_segtab * const stp = (void *)segtabs;
- segtabs += round_page(sizeof(struct pmap_segtab));
pt_entry_t **ptp = &stp->seg_tab[VM_MIN_KERNEL_ADDRESS >> SEGSHIFT];
- for (u_int i = 0; i < nsegtabs; i++, segtabs += NBPG) {
- *ptp++ = (void *)segtabs;
+ pt_entry_t *ptep = (void *)kv_segtabs;
+ memset(ptep, 0, NBPG * kv_nsegtabs);
+ for (size_t i = 0; i < kv_nsegtabs; i++, ptep += NPTEPG) {
+ *ptp++ = ptep;
}
- pmap_kernel()->pm_segtab = stp;
- curcpu()->ci_pmap_kern_segtab = stp;
- printf(" kern_segtab=%p", stp);
-#if 0
- nsegtabs = (physmem + NPTEPG - 1) / NPTEPG;
- segtabs = uvm_pageboot_alloc(NBPG * nsegtabs);
+#if PMAP_MINIMALTLB
+ const vsize_t dm_nsegtabs = (physmem + NPTEPG - 1) / NPTEPG;
+ const vaddr_t dm_segtabs = avail[0].start;
+ printf(" dm_nsegtabs=%#"PRIxVSIZE, dm_nsegtabs);
+ printf(" dm_segtabs=%#"PRIxVADDR, dm_segtabs);
+ KASSERT(dm_segtabs == endkernel);
+ KASSERT(avail[0].size >= NBPG * dm_nsegtabs);
+ avail[0].start += NBPG * dm_nsegtabs;
+ avail[0].size -= NBPG * dm_nsegtabs;
+ endkernel += NBPG * dm_nsegtabs;
+
ptp = stp->seg_tab;
- pt_entry_t pt_entry = PTE_M|PTE_xX|PTE_xR;
- pt_entry_t *ptep = (void *)segtabs;
- printf("%s: allocated %lu page table pages for mapping %u pages\n",
- __func__, nsegtabs, physmem);
- for (u_int i = 0; i < nsegtabs; i++, segtabs += NBPG, ptp++) {
+ ptep = (void *)dm_segtabs;
+ memset(ptep, 0, NBPG * dm_nsegtabs);
+ for (size_t i = 0; i < dm_nsegtabs; i++, ptp++, ptep += NPTEPG) {
*ptp = ptep;
- for (u_int j = 0; j < NPTEPG; j++, ptep++) {
- *ptep = pt_entry;
- pt_entry += NBPG;
- }
- printf(" [%u]=%p (%#x)", i, *ptp, **ptp);
- pt_entry |= PTE_xW;
- pt_entry &= ~PTE_xX;
}
/*
- * Now make everything before the kernel inaccessible.
*/
- for (u_int i = 0; i < startkernel / NBPG; i += NBPG) {
- stp->seg_tab[i >> SEGSHIFT][(i & SEGOFSET) >> PAGE_SHIFT] = 0;
- }
+ extern uint32_t _fdata[], _etext[];
+ vaddr_t va;
+
+ /* Now make everything before the kernel inaccessible. */
+ va = pmap_kvptefill(NBPG, startkernel, 0);
+
+ /* Kernel text is readonly & executable */
+ va = pmap_kvptefill(va, round_page((vaddr_t)_etext),
+ PTE_M | PTE_xR | PTE_xX);
+
+ /* Kernel .rdata is readonly */
+ va = pmap_kvptefill(va, trunc_page((vaddr_t)_fdata), PTE_M | PTE_xR);
+
+ /* Kernel .data/.bss + page tables are read-write */
+ va = pmap_kvptefill(va, round_page(endkernel), PTE_M | PTE_xR | PTE_xW);
+
+ /* message buffer page table pages are read-write */
+ (void) pmap_kvptefill(msgbuf_paddr, msgbuf_paddr+round_page(MSGBUFSIZE),
+ PTE_M | PTE_xR | PTE_xW);
#endif
+ for (size_t i = 0; i < cnt; i++) {
+ printf(" uvm_page_physload(%#lx,%#lx,%#lx,%#lx,%d)",
+ atop(avail[i].start),
+ atop(avail[i].start + avail[i].size) - 1,
+ atop(avail[i].start),
+ atop(avail[i].start + avail[i].size) - 1,
+ VM_FREELIST_DEFAULT);
+ uvm_page_physload(
+ atop(avail[i].start),
+ atop(avail[i].start + avail[i].size) - 1,
+ atop(avail[i].start),
+ atop(avail[i].start + avail[i].size) - 1,
+ VM_FREELIST_DEFAULT);
+ }
+
+ pmap_pvlist_lock_init(curcpu()->ci_ci.dcache_line_size);
+
/*
* Initialize the pools.
*/
@@ -250,6 +300,8 @@ pmap_bootstrap(vaddr_t startkernel, vadd
&pmap_pv_page_allocator, IPL_NONE);
tlb_set_asid(0);
+
+ return endkernel;
}
struct vm_page *
@@ -261,38 +313,69 @@ pmap_md_alloc_poolpage(int flags)
return uvm_pagealloc(NULL, 0, NULL, flags);
}
+vaddr_t
+pmap_md_map_poolpage(paddr_t pa, vsize_t size)
+{
+ const vaddr_t sva = (vaddr_t) pa;
+#ifdef PMAP_MINIMALTLB
+ const vaddr_t eva = sva + size;
+ pmap_kvptefill(sva, eva, PTE_M | PTE_xR | PTE_xW);
+#endif
+ return sva;
+}
+
+void
+pmap_md_unmap_poolpage(vaddr_t va, vsize_t size)
+{
+#ifdef PMAP_MINIMALTLB
+ struct pmap * const pm = pmap_kernel();
+ const vaddr_t eva = va + size;
+ pmap_kvptefill(va, eva, 0);
+ for (;va < eva; va += NBPG) {
+ pmap_tlb_invalidate_addr(pm, va);
+ }
+ pmap_update(pm);
+#endif
+}
+
void
pmap_zero_page(paddr_t pa)
{
- dcache_zero_page(pa);
+ vaddr_t va = pmap_md_map_poolpage(pa, NBPG);
+ dcache_zero_page(va);
- KASSERT(!VM_PAGEMD_EXECPAGE_P(VM_PAGE_TO_MD(PHYS_TO_VM_PAGE(pa))));
+ KASSERT(!VM_PAGEMD_EXECPAGE_P(VM_PAGE_TO_MD(PHYS_TO_VM_PAGE(va))));
+ pmap_md_unmap_poolpage(va, NBPG);
}
void
pmap_copy_page(paddr_t src, paddr_t dst)
{
const size_t line_size = curcpu()->ci_ci.dcache_line_size;
- const paddr_t end = src + PAGE_SIZE;
+ vaddr_t src_va = pmap_md_map_poolpage(src, NBPG);
+ vaddr_t dst_va = pmap_md_map_poolpage(dst, NBPG);
+ const vaddr_t end = src_va + PAGE_SIZE;
- while (src < end) {
+ while (src_va < end) {
__asm(
"dcbt %2,%1" "\n\t" /* touch next src cachline */
"dcba 0,%1" "\n\t" /* don't fetch dst cacheline */
- :: "b"(src), "b"(dst), "b"(line_size));
+ :: "b"(src_va), "b"(dst_va), "b"(line_size));
for (u_int i = 0;
i < line_size;
- src += 32, dst += 32, i += 32) {
+ src_va += 32, dst_va += 32, i += 32) {
__asm(
"lmw 24,0(%0)" "\n\t"
"stmw 24,0(%1)"
- :: "b"(src), "b"(dst)
+ :: "b"(src_va), "b"(dst_va)
: "r24", "r25", "r26", "r27",
"r28", "r29", "r30", "r31");
}
}
+ pmap_md_unmap_poolpage(src_va, NBPG);
+ pmap_md_unmap_poolpage(dst_va, NBPG);
- KASSERT(!VM_PAGEMD_EXECPAGE_P(VM_PAGE_TO_MD(PHYS_TO_VM_PAGE(dst - PAGE_SIZE))));
+ KASSERT(!VM_PAGEMD_EXECPAGE_P(VM_PAGE_TO_MD(PHYS_TO_VM_PAGE(dst))));
}
void
Index: src/sys/arch/powerpc/booke/e500_tlb.c
diff -u src/sys/arch/powerpc/booke/e500_tlb.c:1.7 src/sys/arch/powerpc/booke/e500_tlb.c:1.7.8.1
--- src/sys/arch/powerpc/booke/e500_tlb.c:1.7 Thu Jun 30 00:52:58 2011
+++ src/sys/arch/powerpc/booke/e500_tlb.c Wed May 9 22:42:32 2012
@@ -1,4 +1,4 @@
-/* $NetBSD: e500_tlb.c,v 1.7 2011/06/30 00:52:58 matt Exp $ */
+/* $NetBSD: e500_tlb.c,v 1.7.8.1 2012/05/09 22:42:32 riz Exp $ */
/*-
* Copyright (c) 2010, 2011 The NetBSD Foundation, Inc.
* All rights reserved.
@@ -34,9 +34,11 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
+#define __PMAP_PRIVATE
+
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: e500_tlb.c,v 1.7 2011/06/30 00:52:58 matt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: e500_tlb.c,v 1.7.8.1 2012/05/09 22:42:32 riz Exp $");
#include <sys/param.h>
@@ -45,6 +47,7 @@ __KERNEL_RCSID(0, "$NetBSD: e500_tlb.c,v
#include <powerpc/spr.h>
#include <powerpc/booke/spr.h>
#include <powerpc/booke/cpuvar.h>
+#include <powerpc/booke/e500reg.h>
#include <powerpc/booke/e500var.h>
#include <powerpc/booke/pmap.h>
@@ -257,7 +260,7 @@ tlb_to_hwtlb(const struct e500_tlb tlb)
KASSERT(cntlz <= 19);
hwtlb.hwtlb_mas0 = MAS0_TLBSEL_TLB1;
/*
- * TSIZE is defined (4^TSIZE) Kbytes except a TSIZE of is not
+ * TSIZE is defined (4^TSIZE) Kbytes except a TSIZE of 0 is not
* allowed. So 1K would be 0x00000400 giving 21 leading zero
* bits. Subtracting the leading number of zero bits from 21
* and dividing by 2 gives us the number that the MMU wants.
@@ -316,7 +319,7 @@ e500_alloc_tlb1_entry(void)
KASSERT((tlb1->tlb1_entries[slot].e_hwtlb.hwtlb_mas1 & MAS1_V) == 0);
tlb1->tlb1_entries[slot].e_hwtlb.hwtlb_mas0 =
MAS0_TLBSEL_TLB1 | __SHIFTOUT(slot, MAS0_ESEL);
- return slot;
+ return (int)slot;
}
static void
@@ -1018,3 +1021,87 @@ e500_tlb_init(vaddr_t endkernel, psize_t
*/
e500_tlb_invalidate_all();
}
+
+void
+e500_tlb_minimize(vaddr_t endkernel)
+{
+#ifdef PMAP_MINIMALTLB
+ struct e500_tlb1 * const tlb1 = &e500_tlb1;
+ extern uint32_t _fdata[];
+
+ u_int slot;
+
+ paddr_t boot_page = cpu_read_4(GUR_BPTR);
+ if (boot_page & BPTR_EN) {
+ /*
+ * shift it to an address
+ */
+ boot_page = (boot_page & BPTR_BOOT_PAGE) << PAGE_SHIFT;
+ pmap_kvptefill(boot_page, boot_page + NBPG,
+ PTE_M | PTE_xR | PTE_xW | PTE_xX);
+ }
+
+
+ KASSERT(endkernel - (uintptr_t)_fdata < 0x400000);
+ KASSERT((uintptr_t)_fdata == 0x400000);
+
+ struct e500_xtlb *xtlb = e500_tlb_lookup_xtlb(endkernel, &slot);
+
+ KASSERT(xtlb == e500_tlb_lookup_xtlb2(0, endkernel));
+ const u_int tmp_slot = e500_alloc_tlb1_entry();
+ KASSERT(tmp_slot != (u_int) -1);
+
+ struct e500_xtlb * const tmp_xtlb = &tlb1->tlb1_entries[tmp_slot];
+ tmp_xtlb->e_tlb = xtlb->e_tlb;
+ tmp_xtlb->e_hwtlb = tlb_to_hwtlb(tmp_xtlb->e_tlb);
+ tmp_xtlb->e_hwtlb.hwtlb_mas1 |= MAS1_TS;
+ KASSERT((tmp_xtlb->e_hwtlb.hwtlb_mas0 & MAS0_TLBSEL) == MAS0_TLBSEL_TLB1);
+ tmp_xtlb->e_hwtlb.hwtlb_mas0 |= __SHIFTIN(tmp_slot, MAS0_ESEL);
+ hwtlb_write(tmp_xtlb->e_hwtlb, true);
+
+ const u_int text_slot = e500_alloc_tlb1_entry();
+ KASSERT(text_slot != (u_int)-1);
+ struct e500_xtlb * const text_xtlb = &tlb1->tlb1_entries[text_slot];
+ text_xtlb->e_tlb.tlb_va = 0;
+ text_xtlb->e_tlb.tlb_size = 0x400000;
+ text_xtlb->e_tlb.tlb_pte = PTE_M | PTE_xR | PTE_xX | text_xtlb->e_tlb.tlb_va;
+ text_xtlb->e_tlb.tlb_asid = 0;
+ text_xtlb->e_hwtlb = tlb_to_hwtlb(text_xtlb->e_tlb);
+ KASSERT((text_xtlb->e_hwtlb.hwtlb_mas0 & MAS0_TLBSEL) == MAS0_TLBSEL_TLB1);
+ text_xtlb->e_hwtlb.hwtlb_mas0 |= __SHIFTIN(text_slot, MAS0_ESEL);
+
+ const u_int data_slot = e500_alloc_tlb1_entry();
+ KASSERT(data_slot != (u_int)-1);
+ struct e500_xtlb * const data_xtlb = &tlb1->tlb1_entries[data_slot];
+ data_xtlb->e_tlb.tlb_va = 0x400000;
+ data_xtlb->e_tlb.tlb_size = 0x400000;
+ data_xtlb->e_tlb.tlb_pte = PTE_M | PTE_xR | PTE_xW | data_xtlb->e_tlb.tlb_va;
+ data_xtlb->e_tlb.tlb_asid = 0;
+ data_xtlb->e_hwtlb = tlb_to_hwtlb(data_xtlb->e_tlb);
+ KASSERT((data_xtlb->e_hwtlb.hwtlb_mas0 & MAS0_TLBSEL) == MAS0_TLBSEL_TLB1);
+ data_xtlb->e_hwtlb.hwtlb_mas0 |= __SHIFTIN(data_slot, MAS0_ESEL);
+
+ const register_t msr = mfmsr();
+ const register_t ts_msr = (msr | PSL_DS | PSL_IS) & ~PSL_EE;
+
+ __asm __volatile(
+ "mtmsr %[ts_msr]" "\n\t"
+ "sync" "\n\t"
+ "isync"
+ :: [ts_msr] "r" (ts_msr));
+
+#if 0
+ hwtlb_write(text_xtlb->e_hwtlb, false);
+ hwtlb_write(data_xtlb->e_hwtlb, false);
+ e500_free_tlb1_entry(xtlb, slot, true);
+#endif
+
+ __asm __volatile(
+ "mtmsr %[msr]" "\n\t"
+ "sync" "\n\t"
+ "isync"
+ :: [msr] "r" (msr));
+
+ e500_free_tlb1_entry(tmp_xtlb, tmp_slot, true);
+#endif /* PMAP_MINIMALTLB */
+}
Index: src/sys/arch/powerpc/conf/files.powerpc
diff -u src/sys/arch/powerpc/conf/files.powerpc:1.82 src/sys/arch/powerpc/conf/files.powerpc:1.82.8.1
--- src/sys/arch/powerpc/conf/files.powerpc:1.82 Wed Jun 29 06:02:43 2011
+++ src/sys/arch/powerpc/conf/files.powerpc Wed May 9 22:42:31 2012
@@ -1,10 +1,10 @@
-# $NetBSD: files.powerpc,v 1.82 2011/06/29 06:02:43 matt Exp $
+# $NetBSD: files.powerpc,v 1.82.8.1 2012/05/09 22:42:31 riz Exp $
defflag opt_altivec.h ALTIVEC K_ALTIVEC PPC_HAVE_SPE
defflag opt_openpic.h OPENPIC OPENPIC_SERIAL_MODE OPENPIC_DISTRIBUTE
defparam opt_ppcparam.h L2CR_CONFIG L3CR_CONFIG INTSTK CLOCKBASE VERBOSE_INITPPC
defflag opt_ppcarch.h PPC_OEA PPC_OEA601 PPC_OEA64 PPC_OEA64_BRIDGE PPC_MPC8XX PPC_IBM4XX PPC_IBM403 PPC_BOOKE
-defflag opt_pmap.h PMAPDEBUG PMAPCHECK PMAPCOUNTERS
+defflag opt_pmap.h PMAPDEBUG PMAPCHECK PMAPCOUNTERS PMAP_MINIMALTLB
defparam opt_pmap.h PTEGCOUNT PMAP_MEMLIMIT
file arch/powerpc/powerpc/copystr.c
Index: src/sys/arch/powerpc/include/booke/e500var.h
diff -u src/sys/arch/powerpc/include/booke/e500var.h:1.4 src/sys/arch/powerpc/include/booke/e500var.h:1.4.8.1
--- src/sys/arch/powerpc/include/booke/e500var.h:1.4 Wed Jun 29 06:01:33 2011
+++ src/sys/arch/powerpc/include/booke/e500var.h Wed May 9 22:42:31 2012
@@ -1,4 +1,4 @@
-/* $NetBSD: e500var.h,v 1.4 2011/06/29 06:01:33 matt Exp $ */
+/* $NetBSD: e500var.h,v 1.4.8.1 2012/05/09 22:42:31 riz Exp $ */
/*-
* Copyright (c) 2010, 2011 The NetBSD Foundation, Inc.
* All rights reserved.
@@ -55,6 +55,7 @@ void e500_device_register(device_t, void
int e500_clock_intr(void *);
void e500_cpu_start(void);
void e500_tlb_init(vaddr_t, psize_t);
+void e500_tlb_minimize(vaddr_t);
bool e500_device_disabled_p(uint32_t);
struct e500_truthtab {
Index: src/sys/arch/powerpc/include/booke/pmap.h
diff -u src/sys/arch/powerpc/include/booke/pmap.h:1.8 src/sys/arch/powerpc/include/booke/pmap.h:1.8.8.1
--- src/sys/arch/powerpc/include/booke/pmap.h:1.8 Thu Jun 30 00:52:59 2011
+++ src/sys/arch/powerpc/include/booke/pmap.h Wed May 9 22:42:31 2012
@@ -1,4 +1,4 @@
-/* $NetBSD: pmap.h,v 1.8 2011/06/30 00:52:59 matt Exp $ */
+/* $NetBSD: pmap.h,v 1.8.8.1 2012/05/09 22:42:31 riz Exp $ */
/*-
* Copyright (c) 2010, 2011 The NetBSD Foundation, Inc.
* All rights reserved.
@@ -44,6 +44,10 @@
#error this file should not be included by loadable kernel modules
#endif
+#ifdef _KERNEL_OPT
+#include "opt_pmap.h"
+#endif
+
#include <sys/cpu.h>
#include <sys/kcore.h>
#include <uvm/uvm_page.h>
@@ -77,7 +81,8 @@ void pmap_procwr(struct proc *, vaddr_t,
#ifdef __PMAP_PRIVATE
struct vm_page *
pmap_md_alloc_poolpage(int flags);
-vaddr_t pmap_md_map_poolpage(paddr_t);
+vaddr_t pmap_md_map_poolpage(paddr_t, vsize_t);
+void pmap_md_unmap_poolpage(vaddr_t, vsize_t);
bool pmap_md_direct_mapped_vaddr_p(vaddr_t);
bool pmap_md_io_vaddr_p(vaddr_t);
paddr_t pmap_md_direct_mapped_vaddr_to_paddr(vaddr_t);
@@ -85,10 +90,14 @@ vaddr_t pmap_md_direct_map_paddr(paddr_t
void pmap_md_init(void);
bool pmap_md_tlb_check_entry(void *, vaddr_t, tlb_asid_t, pt_entry_t);
+
+#ifdef PMAP_MINIMALTLB
+vaddr_t pmap_kvptefill(vaddr_t, vaddr_t, pt_entry_t);
+#endif
#endif
void pmap_md_page_syncicache(struct vm_page *, __cpuset_t);
-void pmap_bootstrap(vaddr_t, vaddr_t, const phys_ram_seg_t *, size_t);
+vaddr_t pmap_bootstrap(vaddr_t, vaddr_t, phys_ram_seg_t *, size_t);
bool pmap_extract(struct pmap *, vaddr_t, paddr_t *);
static inline paddr_t vtophys(vaddr_t);
Added files:
Index: src/sys/arch/powerpc/conf/kern-mb.ldscript
diff -u /dev/null src/sys/arch/powerpc/conf/kern-mb.ldscript:1.1.6.2
--- /dev/null Wed May 9 22:42:32 2012
+++ src/sys/arch/powerpc/conf/kern-mb.ldscript Wed May 9 22:42:31 2012
@@ -0,0 +1,76 @@
+/* $NetBSD: kern-mb.ldscript,v 1.1.6.2 2012/05/09 22:42:31 riz Exp $ */
+
+/* ldscript for NetBSD/powerpc kernels and LKMs */
+OUTPUT_ARCH(powerpc)
+ENTRY(_start)
+SEARCH_DIR(/lib);
+/* Do we need any of these?
+ __DYNAMIC = 0; */
+_DYNAMIC_LINK = 0;
+SECTIONS
+{
+ /* Read-only sections, merged into text segment. Assumes the
+ kernel Makefile sets the start address via -Ttext. */
+ .text :
+ {
+ _ftext = . ;
+ *(.text)
+ __stub_start = .;
+ *(.stub)
+ __stub_end = .;
+ __stub_pmap_start = .;
+ *(.stub.pmap)
+ __stub_pmap_end = .;
+ *(.gnu.warning)
+ } =0
+ _etext = .;
+ PROVIDE (etext = .);
+ .rodata : { *(.rodata) *(.rodata.*) }
+ .reginfo : { *(.reginfo) }
+ . = ALIGN(0x100000);
+ .data :
+ {
+ _fdata = . ;
+ *(.data)
+ CONSTRUCTORS
+ }
+ .data1 : { *(.data1) }
+ . = ALIGN(32); /* COHERENCY UNIT */
+ .data.cacheline_aligned : { *(.data.cacheline_aligned) }
+ . = ALIGN(32); /* COHERENCY UNIT */
+ .data.read_mostly : { *(.data.read_mostly) }
+ . = ALIGN(32); /* COHERENCY UNIT */
+ _gp = ALIGN(16) + 0x7ff0;
+ .lit8 : { *(.lit8) }
+ .lit4 : { *(.lit4) }
+ .sdata : { *(.sdata) }
+ _edata = .;
+ PROVIDE (edata = .);
+ __bss_start = .;
+ _fbss = .;
+ .sbss : { *(.sbss) *(.scommon) }
+ .bss :
+ {
+ *(.bss)
+ *(COMMON)
+ }
+ _end = . ;
+ PROVIDE (end = .);
+ /* These are needed for ELF backends which have not yet been
+ converted to the new style linker. */
+ .stab 0 : { *(.stab) }
+ .stabstr 0 : { *(.stabstr) }
+ /* DWARF debug sections.
+ Symbols in the .debug DWARF section are relative to the beginning of the
+ section so we begin .debug at 0. It's not clear yet what needs to happen
+ for the others. */
+ .debug 0 : { *(.debug) }
+ .debug_srcinfo 0 : { *(.debug_srcinfo) }
+ .debug_aranges 0 : { *(.debug_aranges) }
+ .debug_pubnames 0 : { *(.debug_pubnames) }
+ .debug_sfnames 0 : { *(.debug_sfnames) }
+ .line 0 : { *(.line) }
+ /* These must appear regardless of . */
+ .gptab.sdata : { *(.gptab.data) *(.gptab.sdata) }
+ .gptab.sbss : { *(.gptab.bss) *(.gptab.sbss) }
+}