Subject: evbppc reserved-tlb cleanup
To: None <port-powerpc@NetBSD.org>
From: Jachym Holecek <freza@dspfpga.com>
List: port-powerpc
Date: 09/24/2006 02:57:51
Hello,

the patch below converts ibm4xx-based evbppc from static reserved-TLB
entry allocation to recently introduced ppc4xx_tlb_reserve() API (and
fixes a stupid bug therein, too ;-). Some side effects:

  o ibm405gp UART0 used to be linear mapped. The VA happens to be
    inside kernel segment, giving us the possibility of multiple
    VA matches in the TLB. This is considered "programming error"
    by 405 core and results in "undefined behaviour". We now avoid
    mapping peripherals in kernel segment.

  o Some boards used to map hardwired RAM size. We now use the real
    size as passed in by boot firmware.

  o TLB_NRESERVED is (finally) gone.

I don't have any of the affected boards to play with, so it would be
great to know how it works on Walnut, Explora451 and OpenBlocks.

Assuming all boards work, would this be OK to commit?

Thanks,
	-- Jachym

Index: powerpc/ibm4xx/pmap.c
===================================================================
RCS file: /cvsroot/src/sys/arch/powerpc/ibm4xx/pmap.c,v
retrieving revision 1.42
diff -d -p -u -r1.42 pmap.c
--- powerpc/ibm4xx/pmap.c	31 Aug 2006 22:13:51 -0000	1.42
+++ powerpc/ibm4xx/pmap.c	24 Sep 2006 00:32:22 -0000
@@ -267,10 +267,6 @@ pmap_bootstrap(u_int kernelstart, u_int 
 	int cnt, i;
 	u_int s, e, sz;
 
-	/* XXXfreza: compat, we used to statically reserve 4 entries. */
-	if (tlb_nreserved == 0)
-		tlb_nreserved = TLB_NRESERVED;
-
 	tlbnext = tlb_nreserved;
 
 	/*
@@ -1454,7 +1450,7 @@ ppc4xx_tlb_reserve(paddr_t pa, vaddr_t v
 	va &= ~(rsize - 1); 	/* EPN */
 
 	lo = pa | TLB_WR | flags;
-	hi = va | TLB_VALID | szmask | KERNEL_PID;
+	hi = va | TLB_VALID | szmask;
 
 #ifdef PPC_4XX_NOCACHE
 	lo |= TLB_I;
Index: powerpc/include/ibm4xx/tlb.h
===================================================================
RCS file: /cvsroot/src/sys/arch/powerpc/include/ibm4xx/tlb.h,v
retrieving revision 1.3
diff -d -p -u -r1.3 tlb.h
--- powerpc/include/ibm4xx/tlb.h	31 Aug 2006 22:13:51 -0000	1.3
+++ powerpc/include/ibm4xx/tlb.h	24 Sep 2006 00:32:23 -0000
@@ -109,6 +109,4 @@ void 	*ppc4xx_tlb_mapiodev(paddr_t, psiz
 
 #define TLB_PID_INVALID 0xFFFF
 
-#define TLB_NRESERVED	4	/* XXXfreza: kill. */
-
 #endif	/* _IBM4XX_TLB_H_ */
Index: evbppc/explora/machdep.c
===================================================================
RCS file: /cvsroot/src/sys/arch/evbppc/explora/machdep.c,v
retrieving revision 1.13
diff -d -p -u -r1.13 machdep.c
--- evbppc/explora/machdep.c	18 Sep 2006 22:05:47 -0000	1.13
+++ evbppc/explora/machdep.c	24 Sep 2006 00:32:24 -0000
@@ -134,26 +134,6 @@ static struct {
 #endif /* DDB */
 };
 
-static void
-set_tlb(int idx, u_int addr, u_int flags)
-{
-	u_int lo, hi;
-
-	addr &= ~(TLB_PG_SIZE-1);
-
-	lo = addr | TLB_EX | TLB_WR | flags;
-#ifdef PPC_4XX_NOCACHE
-	lo |= TLB_I;
-#endif
-	hi = addr | TLB_VALID | TLB_PG_16M;
-
-	__asm volatile(
-	    "	tlbwe %1,%0,1	\n"
-	    "	tlbwe %2,%0,0	\n"
-	    "	sync		\n"
-	    : : "r" (idx), "r" (lo), "r" (hi) );
-}
-
 /*
  * Install a trap vector. We cannot use memcpy because the
  * destination may be zero.
@@ -174,7 +154,7 @@ void
 bootstrap(u_int startkernel, u_int endkernel)
 {
 	u_int i, j, t, br[4];
-	u_int ntlb, maddr, msize, size;
+	u_int maddr, msize, size;
 	struct cpu_info * const ci = &cpu_info[0];
 
 	consinit();
@@ -198,14 +178,6 @@ bootstrap(u_int startkernel, u_int endke
 			size = maddr+msize;
 	}
 
-#ifdef COM_IS_CONSOLE
-	ntlb = TLB_NRESERVED-1;
-#else
-	ntlb = TLB_NRESERVED-2;
-#endif
-	if (size > ntlb*TLB_PG_SIZE)
-		size = ntlb*TLB_PG_SIZE;
-
 	phys_mem[0].start = 0;
 	phys_mem[0].size = size & ~PGOFSET;
 	avail_mem[0].start = startkernel;
@@ -214,7 +186,7 @@ bootstrap(u_int startkernel, u_int endke
 	__asm volatile(
 	    "	mtpid %0	\n"
 	    "	sync		\n"
-	    : : "r" (1) );
+	    : : "r" (KERNEL_PID) );
 
 	/*
 	 * Setup initial tlbs.
@@ -224,13 +196,13 @@ bootstrap(u_int startkernel, u_int endke
 
 	t = 0;
 	for (maddr = 0; maddr < phys_mem[0].size; maddr += TLB_PG_SIZE)
-		set_tlb(t++, maddr, 0);
+		ppc4xx_tlb_reserve(maddr, maddr, TLB_PG_SIZE, TLB_EX);
 
 #ifdef COM_IS_CONSOLE
-	set_tlb(t++, BASE_COM, TLB_I | TLB_G);
+	ppc4xx_tlb_reserve(BASE_COM, BASE_COM, TLB_PG_SIZE, TLB_I | TLB_G);
 #else
-	set_tlb(t++, BASE_FB, TLB_I | TLB_G);
-	set_tlb(t++, BASE_FB2, TLB_I | TLB_G);
+	ppc4xx_tlb_reserve(BASE_FB,  BASE_FB,  TLB_PG_SIZE, TLB_I | TLB_G);
+	ppc4xx_tlb_reserve(BASE_FB2, BASE_FB2, TLB_PG_SIZE, TLB_I | TLB_G);
 #endif
 
 	/* Disable all external interrupts */
Index: evbppc/obs405/obs200_locore.S
===================================================================
RCS file: /cvsroot/src/sys/arch/evbppc/obs405/obs200_locore.S,v
retrieving revision 1.3
diff -d -p -u -r1.3 obs200_locore.S
--- evbppc/obs405/obs200_locore.S	30 Jun 2006 17:54:50 -0000	1.3
+++ evbppc/obs405/obs200_locore.S	24 Sep 2006 00:32:24 -0000
@@ -190,59 +190,11 @@ __start_cpu0:
 	stw	%r8,0(%r7)
 #endif
 
-	/*
-	 * Set up TLB entry to cover kernel addresses.
-	 *
-	 * XXX: Skip TLB 0 for now, due to unresolved TLB 0 replacement
-	 *	and hard hangs
-	 */
-	li	%r0,1
+	/* Set kernel MMU context. */
+	li	%r0,KERNEL_PID
 	mtpid	%r0
 	sync
 
-	li	%r0,0
-#ifdef PPC_4XX_NOCACHE
-	li	%r4,TLB_EX|TLB_WR|TLB_I /* |TLB_W */
-#else
-	li	%r4,TLB_EX|TLB_WR /* |TLB_W */
-#endif
-        li	%r3,TLB_VALID|TLB_PG_16M
-        tlbwe	%r4,%r0,1		/* Load the data(Low) portion of the entry */
-        tlbwe	%r3,%r0,0		/* Load the tag(High) portion of the entry */
-
-#if 1
-	/* Damn. Have to be able to access all real memory.... Hardcode for 32M for now. */
-	li	%r0,1
-	lis	%r4,0x01000000@h
-	ori	%r3,%r4,0
-#ifdef PPC_4XX_NOCACHE
-	addi	%r4,%r4,TLB_EX|TLB_WR|TLB_I /* |TLB_W */
-#else
-	addi	%r4,%r4,TLB_EX|TLB_WR /* |TLB_W */
-#endif
-	addi	%r3,%r3,TLB_VALID|TLB_PG_16M
-	tlbwe	%r4,%r0,1		/* Load the data(Low) portion of the entry */
-	tlbwe	%r3,%r0,0		/* Load the tag(High) portion of the entry */
-#endif
-
-	/* set up a TLB mapping to cover uart0 */
-	lis	%r3,0xef000000@h	/* Load the virtual address */
-	ori	%r4,%r3,0		/* Load the physical address */
-
-	clrrwi	%r4,%r4,10		/* Mask off the real page number */
-	/* write, execute, cache inhibit, guarded */
-	ori	%r4,%r4,(TLB_WR|TLB_EX|TLB_I|TLB_G)
-
-	clrrwi	%r3,%r3,10		/* Mask off the effective page number */
-	ori	%r3,%r3,(TLB_VALID|TLB_PG_16M)
-
-	li	%r0,2
-
-	tlbwe	%r4,%r0,1		/* Load the data portion of the entry */
-	tlbwe	%r3,%r0,0		/* Load the tag portion of the entry */
-
-	/* END of TLB setup */
-
 	INIT_CPUINFO(8,1,9,0)
 	mr	%r4,%r8
 
Index: evbppc/obs405/obs200_machdep.c
===================================================================
RCS file: /cvsroot/src/sys/arch/evbppc/obs405/obs200_machdep.c,v
retrieving revision 1.3
diff -d -p -u -r1.3 obs200_machdep.c
--- evbppc/obs405/obs200_machdep.c	29 Mar 2006 17:50:33 -0000	1.3
+++ evbppc/obs405/obs200_machdep.c	24 Sep 2006 00:32:24 -0000
@@ -97,6 +97,9 @@ __KERNEL_RCSID(0, "$NetBSD: obs200_machd
 
 #include "ksyms.h"
 
+
+#define	TLB_PG_SIZE 	(16*1024*1024)
+
 /*
  * Global variables used here and there
  */
@@ -117,6 +120,7 @@ initppc(u_int startkernel, u_int endkern
 {
 	u_int32_t pllmode;
 	u_int32_t psr;
+	vaddr_t va;
 	u_int memsize;
 
 	/* Disable all external interrupts */
@@ -128,6 +132,13 @@ initppc(u_int startkernel, u_int endkern
 	bios_board_init(info_block, startkernel);
 	memsize = bios_board_memsize_get();
 
+	/* Linear map whole physmem. */
+	for (va = 0; va < memsize; va += TLB_PG_SIZE)
+		ppc4xx_tlb_reserve(va, va, TLB_PG_SIZE, TLB_EX);
+
+	/* Map console right after RAM. */
+	ppc4xx_tlb_reserve(0xef000000, va, TLB_PG_SIZE, TLB_I | TLB_G);
+
 	/* Initialize IBM405GPr CPU */
 	ibm40x_memsize_init(memsize, startkernel);
 	ibm4xx_init((void (*)(void))ext_intr);
Index: evbppc/obs405/obs266_machdep.c
===================================================================
RCS file: /cvsroot/src/sys/arch/evbppc/obs405/obs266_machdep.c,v
retrieving revision 1.4
diff -d -p -u -r1.4 obs266_machdep.c
--- evbppc/obs405/obs266_machdep.c	29 Mar 2006 17:50:33 -0000	1.4
+++ evbppc/obs405/obs266_machdep.c	24 Sep 2006 00:32:24 -0000
@@ -97,6 +97,9 @@ __KERNEL_RCSID(0, "$NetBSD: obs266_machd
 
 #include "ksyms.h"
 
+
+#define	TLB_PG_SIZE 	(16*1024*1024)
+
 /*
  * Global variables used here and there
  */
@@ -115,6 +118,7 @@ int lcsplx(int);
 void
 initppc(u_int startkernel, u_int endkernel, char *args, void *info_block)
 {
+	vaddr_t va;
 	u_int memsize;
 
 	/* Disable all external interrupts */
@@ -124,6 +128,13 @@ initppc(u_int startkernel, u_int endkern
 	openbios_board_init(info_block, startkernel);
 	memsize = openbios_board_memsize_get();
 
+	/* Linear map whole physmem */
+	for (va = 0; va < memsize; va += TLB_PG_SIZE)
+		ppc4xx_tlb_reserve(va, va, TLB_PG_SIZE, TLB_EX);
+
+	/* Map console just after RAM */
+	ppc4xx_tlb_reserve(0xef000000, va, TLB_PG_SIZE, TLB_I | TLB_G);
+
 	/* Initialize IBM405GPr CPU */
 	ibm40x_memsize_init(memsize, startkernel);
 	ibm4xx_init((void (*)(void))ext_intr);
Index: evbppc/walnut/machdep.c
===================================================================
RCS file: /cvsroot/src/sys/arch/evbppc/walnut/machdep.c,v
retrieving revision 1.29
diff -d -p -u -r1.29 machdep.c
--- evbppc/walnut/machdep.c	13 Jul 2006 07:36:04 -0000	1.29
+++ evbppc/walnut/machdep.c	24 Sep 2006 00:32:25 -0000
@@ -115,6 +115,9 @@ __KERNEL_RCSID(0, "$NetBSD: machdep.c,v 
 #include <ddb/db_extern.h>
 #endif
 
+
+#define TLB_PG_SIZE 	(16*1024*1024)
+
 /*
  * Global variables used here and there
  */
@@ -171,6 +174,7 @@ initppc(u_int startkernel, u_int endkern
 #ifdef IPKDB
 	extern int ipkdblow, ipkdbsize;
 #endif
+	vaddr_t va;
 	int exc, dbcr0;
 	struct cpu_info * const ci = curcpu();
 
@@ -191,6 +195,13 @@ initppc(u_int startkernel, u_int endkern
 	availmemr[0].start = startkernel; 
 	availmemr[0].size = board_data.mem_size - availmemr[0].start;
 
+	/* Linear map whole physmem */
+	for (va = 0; va < board_data.mem_size; va += TLB_PG_SIZE)
+		ppc4xx_tlb_reserve(va, va, TLB_PG_SIZE, TLB_EX);
+
+	/* Map console just after RAM */
+	ppc4xx_tlb_reserve(0xef000000, va, TLB_PG_SIZE, TLB_I | TLB_G);
+
 	/*
 	 * Initialize lwp0 and current pcb and pmap pointers.
 	 */
Index: evbppc/walnut/walnut_start.S
===================================================================
RCS file: /cvsroot/src/sys/arch/evbppc/walnut/walnut_start.S,v
retrieving revision 1.13
diff -d -p -u -r1.13 walnut_start.S
--- evbppc/walnut/walnut_start.S	30 Jun 2006 17:54:51 -0000	1.13
+++ evbppc/walnut/walnut_start.S	24 Sep 2006 00:32:25 -0000
@@ -192,59 +192,11 @@ __start_cpu0:
 	stw	%r8,0(%r7)
 #endif
 
-	/*
-	 * Set up TLB entry to cover kernel addresses.
-	 *
-	 * XXX: Skip TLB 0 for now, due to unresolved TLB 0 replacement
-	 *	and hard hangs
-	 */
-	li	%r0,1
+	/* Set kernel MMU context. */
+	li	%r0,KERNEL_PID
 	mtpid	%r0
 	sync
 
-	li	%r0,0
-#ifdef PPC_4XX_NOCACHE
-	li	%r4,TLB_EX|TLB_WR|TLB_I /* |TLB_W */
-#else
-	li	%r4,TLB_EX|TLB_WR /* |TLB_W */
-#endif
-        li	%r3,TLB_VALID|TLB_PG_16M
-        tlbwe	%r4,%r0,1		/* Load the data(Low) portion of the entry */
-        tlbwe	%r3,%r0,0		/* Load the tag(High) portion of the entry */
-
-#if 1
-	/* Damn. Have to be able to access all real memory.... Hardcode for 32M for now. */
-	li	%r0,1
-	lis	%r4,0x01000000@h
-	ori	%r3,%r4,0
-#ifdef PPC_4XX_NOCACHE
-	addi	%r4,%r4,TLB_EX|TLB_WR|TLB_I /* |TLB_W */
-#else
-	addi	%r4,%r4,TLB_EX|TLB_WR /* |TLB_W */
-#endif
-	addi	%r3,%r3,TLB_VALID|TLB_PG_16M
-	tlbwe	%r4,%r0,1		/* Load the data(Low) portion of the entry */
-	tlbwe	%r3,%r0,0		/* Load the tag(High) portion of the entry */
-#endif
-
-	/* set up a TLB mapping to cover uart0 */
-	lis	%r3,0xef000000@h	/* Load the virtual address */
-	ori	%r4,%r3,0		/* Load the physical address */
-
-	clrrwi	%r4,%r4,10		/* Mask off the real page number */
-	/* write, execute, cache inhibit, guarded */
-	ori	%r4,%r4,(TLB_WR|TLB_EX|TLB_I|TLB_G)
-
-	clrrwi	%r3,%r3,10		/* Mask off the effective page number */
-	ori	%r3,%r3,(TLB_VALID|TLB_PG_16M)
-
-	li	%r0,2
-
-	tlbwe	%r4,%r0,1		/* Load the data portion of the entry */
-	tlbwe	%r3,%r0,0		/* Load the tag portion of the entry */
-
-	/* END of TLB setup */
-
 	INIT_CPUINFO(8,1,9,0)
 	mr	%r4,%r8