Module Name:    src
Committed By:   matt
Date:           Wed Feb  1 05:25:58 UTC 2012

Modified Files:
        src/sys/arch/powerpc/include/oea: bat.h spr.h
        src/sys/arch/powerpc/oea: cpu_subr.c genassym.cf oea_machdep.c
            ofw_rascons.c pmap.c
        src/sys/arch/powerpc/powerpc: bus_space.c db_interface.c trap_subr.S

Log Message:
Enable XBSEN and HIGHBAT for OEA 7455 and related CPUs.
The BAT entries now have a resolution of 8MB.  (Adjacent entries are merged
up to a total of 2GB per entry).


To generate a diff of this commit:
cvs rdiff -u -r1.14 -r1.15 src/sys/arch/powerpc/include/oea/bat.h
cvs rdiff -u -r1.1 -r1.2 src/sys/arch/powerpc/include/oea/spr.h
cvs rdiff -u -r1.71 -r1.72 src/sys/arch/powerpc/oea/cpu_subr.c
cvs rdiff -u -r1.25 -r1.26 src/sys/arch/powerpc/oea/genassym.cf
cvs rdiff -u -r1.60 -r1.61 src/sys/arch/powerpc/oea/oea_machdep.c
cvs rdiff -u -r1.6 -r1.7 src/sys/arch/powerpc/oea/ofw_rascons.c
cvs rdiff -u -r1.82 -r1.83 src/sys/arch/powerpc/oea/pmap.c
cvs rdiff -u -r1.30 -r1.31 src/sys/arch/powerpc/powerpc/bus_space.c
cvs rdiff -u -r1.48 -r1.49 src/sys/arch/powerpc/powerpc/db_interface.c
cvs rdiff -u -r1.72 -r1.73 src/sys/arch/powerpc/powerpc/trap_subr.S

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/powerpc/include/oea/bat.h
diff -u src/sys/arch/powerpc/include/oea/bat.h:1.14 src/sys/arch/powerpc/include/oea/bat.h:1.15
--- src/sys/arch/powerpc/include/oea/bat.h:1.14	Mon Jun 20 06:04:33 2011
+++ src/sys/arch/powerpc/include/oea/bat.h	Wed Feb  1 05:25:57 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: bat.h,v 1.14 2011/06/20 06:04:33 matt Exp $	*/
+/*	$NetBSD: bat.h,v 1.15 2012/02/01 05:25:57 matt Exp $	*/
 
 /*-
  * Copyright (c) 1999 The NetBSD Foundation, Inc.
@@ -126,6 +126,8 @@ struct bat {
 #define	BAT_BL_2G	0x0000fffc
 #define	BAT_BL_4G	0x0001fffc
 
+#define	BAT_BL_TO_SIZE(bl)	(((bl)+4) << 15)
+
 #define	BATU(va, len, v)						\
 	(((va) & BAT_EPI) | ((len) & BAT_BL) | ((v) & BAT_V))
 
@@ -196,7 +198,8 @@ struct bat {
 #define	BAT601_VALID_P(batl) \
 	((batl) & BAT601_V)
 
-#define	BAT_VA2IDX(va)	((va) >> ADDR_SR_SHFT)
+#define	BAT_VA2IDX(va)	((va) / (8*1024*1024))
+#define	BAT_IDX2VA(i)	((i) * (8*1024*1024))
 
 #if defined(_KERNEL) && !defined(_LOCORE)
 void oea_batinit(paddr_t, ...);

Index: src/sys/arch/powerpc/include/oea/spr.h
diff -u src/sys/arch/powerpc/include/oea/spr.h:1.1 src/sys/arch/powerpc/include/oea/spr.h:1.2
--- src/sys/arch/powerpc/include/oea/spr.h:1.1	Thu Feb 25 23:30:05 2010
+++ src/sys/arch/powerpc/include/oea/spr.h	Wed Feb  1 05:25:57 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: spr.h,v 1.1 2010/02/25 23:30:05 matt Exp $	*/
+/*	$NetBSD: spr.h,v 1.2 2012/02/01 05:25:57 matt Exp $	*/
 
 #ifndef _POWERPC_OEA_SPR_H_
 #define	_POWERPC_OEA_SPR_H_
@@ -108,6 +108,7 @@
 #define	SPR_DBAT6U		0x23c	/* ..6. Data BAT Reg 6 Upper */
 #define	SPR_DBAT6L		0x23d	/* ..6. Data BAT Reg 6 Lower */
 #define	SPR_DBAT7U		0x23e	/* ..6. Data BAT Reg 7 Upper */
+#define	SPR_DBAT7L		0x23f	/* ..6. Data BAT Reg 7 Upper */
 #define	SPR_UMMCR2		0x3a0	/* ..6. User Monitor Mode Control Register 2 */
 #define	SPR_UMMCR0		0x3a8	/* ..6. User Monitor Mode Control Register 0 */
 #define	SPR_USIA		0x3ab	/* ..6. User Sampled Instruction Address */

Index: src/sys/arch/powerpc/oea/cpu_subr.c
diff -u src/sys/arch/powerpc/oea/cpu_subr.c:1.71 src/sys/arch/powerpc/oea/cpu_subr.c:1.72
--- src/sys/arch/powerpc/oea/cpu_subr.c:1.71	Mon Jan 23 16:22:57 2012
+++ src/sys/arch/powerpc/oea/cpu_subr.c	Wed Feb  1 05:25:57 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: cpu_subr.c,v 1.71 2012/01/23 16:22:57 phx Exp $	*/
+/*	$NetBSD: cpu_subr.c,v 1.72 2012/02/01 05:25:57 matt Exp $	*/
 
 /*-
  * Copyright (c) 2001 Matt Thomas.
@@ -34,7 +34,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: cpu_subr.c,v 1.71 2012/01/23 16:22:57 phx Exp $");
+__KERNEL_RCSID(0, "$NetBSD: cpu_subr.c,v 1.72 2012/02/01 05:25:57 matt Exp $");
 
 #include "opt_ppcparam.h"
 #include "opt_multiprocessor.h"
@@ -269,17 +269,27 @@ cpu_model_init(void)
 	oeacpufeat = 0;
 	
 	if ((vers >= IBMRS64II && vers <= IBM970GX) || vers == MPC620 ||
-		vers == IBMCELL || vers == IBMPOWER6P5)
-		oeacpufeat |= OEACPU_64 | OEACPU_64_BRIDGE | OEACPU_NOBAT;
+		vers == IBMCELL || vers == IBMPOWER6P5) {
+		oeacpufeat |= OEACPU_64;
+		oeacpufeat |= OEACPU_64_BRIDGE;
+		oeacpufeat |= OEACPU_NOBAT;
 	
-	else if (vers == MPC601)
+	} else if (vers == MPC601) {
 		oeacpufeat |= OEACPU_601;
 
-	else if (MPC745X_P(vers) && vers != MPC7450)
-		oeacpufeat |= OEACPU_XBSEN | OEACPU_HIGHBAT | OEACPU_HIGHSPRG;
+	} else if (MPC745X_P(vers) && vers != MPC7450) {
+		oeacpufeat |= OEACPU_HIGHSPRG;
+		oeacpufeat |= OEACPU_XBSEN;
+		oeacpufeat |= OEACPU_HIGHBAT;
+		/* Enable more and larger BAT registers */
+		register_t hid0 = mfspr(SPR_HID0);
+		hid0 |= HID0_XBSEN;
+		hid0 |= HID0_HIGH_BAT_EN;
+		mtspr(SPR_HID0, hid0);
 
-	else if (vers == IBM750FX || vers == IBM750GX)
+	} else if (vers == IBM750FX || vers == IBM750GX) {
 		oeacpufeat |= OEACPU_HIGHBAT;
+	}
 }
 
 void
@@ -525,11 +535,6 @@ cpu_setup(device_t self, struct cpu_info
 		/* Enable the 7450 branch caches */
 		hid0 |= HID0_SGE | HID0_BTIC;
 		hid0 |= HID0_LRSTK | HID0_FOLD | HID0_BHT;
-		/* Enable more and larger BAT registers */
-		if (oeacpufeat & OEACPU_XBSEN)
-			hid0 |= HID0_XBSEN;
-		if (oeacpufeat & OEACPU_HIGHBAT)
-			hid0 |= HID0_HIGH_BAT_EN;
 		/* Disable BTIC on 7450 Rev 2.0 or earlier */
 		if (vers == MPC7450 && (pvr & 0xFFFF) <= 0x0200)
 			hid0 &= ~HID0_BTIC;

Index: src/sys/arch/powerpc/oea/genassym.cf
diff -u src/sys/arch/powerpc/oea/genassym.cf:1.25 src/sys/arch/powerpc/oea/genassym.cf:1.26
--- src/sys/arch/powerpc/oea/genassym.cf:1.25	Mon Jun 20 19:56:12 2011
+++ src/sys/arch/powerpc/oea/genassym.cf	Wed Feb  1 05:25:57 2012
@@ -1,4 +1,4 @@
-#	$NetBSD: genassym.cf,v 1.25 2011/06/20 19:56:12 matt Exp $
+#	$NetBSD: genassym.cf,v 1.26 2012/02/01 05:25:57 matt Exp $
 
 #
 # Copyright (C) 1995, 1996 Wolfgang Solfrank.
@@ -46,6 +46,7 @@ include <machine/pcb.h>
 include <machine/pmap.h>
 
 include <powerpc/cpu.h>
+include <powerpc/oea/bat.h>
 include <powerpc/oea/cpufeat.h>
 
 define	FRAME_DAR	offsetof(struct ktrapframe, ktf_tf.tf_dar)
@@ -85,6 +86,8 @@ define	OEACPU_601	OEACPU_601
 define	OEACPU_HIGHSPRG	OEACPU_HIGHSPRG
 define	OEACPU_ALTIVEC	OEACPU_ALTIVEC
 
+define	BAT_ADDR_SHIFT	ilog2(BAT_IDX2VA(1))
+
 define	PTE_REF		PTE_REF
 define	PTE_CHG		PTE_CHG
 define	PTE_HID		PTE_HID

Index: src/sys/arch/powerpc/oea/oea_machdep.c
diff -u src/sys/arch/powerpc/oea/oea_machdep.c:1.60 src/sys/arch/powerpc/oea/oea_machdep.c:1.61
--- src/sys/arch/powerpc/oea/oea_machdep.c:1.60	Sun Jul 17 20:54:46 2011
+++ src/sys/arch/powerpc/oea/oea_machdep.c	Wed Feb  1 05:25:57 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: oea_machdep.c,v 1.60 2011/07/17 20:54:46 joerg Exp $	*/
+/*	$NetBSD: oea_machdep.c,v 1.61 2012/02/01 05:25:57 matt Exp $	*/
 
 /*
  * Copyright (C) 2002 Matt Thomas
@@ -33,7 +33,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: oea_machdep.c,v 1.60 2011/07/17 20:54:46 joerg Exp $");
+__KERNEL_RCSID(0, "$NetBSD: oea_machdep.c,v 1.61 2012/02/01 05:25:57 matt Exp $");
 
 #include "opt_ppcarch.h"
 #include "opt_compat_netbsd.h"
@@ -81,10 +81,10 @@ __KERNEL_RCSID(0, "$NetBSD: oea_machdep.
 #include <powerpc/altivec.h>
 #include <powerpc/pcb.h>
 
-#include <powerpc/oea/spr.h>
 #include <powerpc/oea/bat.h>
-#include <powerpc/oea/sr_601.h>
 #include <powerpc/oea/cpufeat.h>
+#include <powerpc/oea/spr.h>
+#include <powerpc/oea/sr_601.h>
 
 char machine[] = MACHINE;		/* from <machine/param.h> */
 char machine_arch[] = MACHINE_ARCH;	/* from <machine/param.h> */
@@ -97,13 +97,18 @@ struct vm_map *phys_map = NULL;
 static void trap0(void *);
 
 /* XXXSL: The battable is not initialized to non-zero for PPC_OEA64 and PPC_OEA64_BRIDGE */
-struct bat battable[512];
+struct bat battable[BAT_VA2IDX(0xffffffff)+1];
 
 register_t iosrtable[16];	/* I/O segments, for kernel_pmap setup */
 #ifndef MSGBUFADDR
 paddr_t msgbuf_paddr;
 #endif
 
+extern int dsitrap_fix_dbat4[];
+extern int dsitrap_fix_dbat5[];
+extern int dsitrap_fix_dbat6[];
+extern int dsitrap_fix_dbat7[];
+
 void
 oea_init(void (*handler)(void))
 {
@@ -362,6 +367,8 @@ oea_init(void (*handler)(void))
 	 */
 	__syncicache((void *) trapstart,
 	    (uintptr_t) trapend - (uintptr_t) trapstart);
+	__syncicache(dsitrap_fix_dbat4, 16);
+	__syncicache(dsitrap_fix_dbat7, 8);
 #ifdef PPC_OEA601
 
 	/*
@@ -449,35 +456,69 @@ mpc601_ioseg_add(paddr_t pa, register_t 
 #endif /* PPC_OEA601 */
 
 #if defined (PPC_OEA) || defined (PPC_OEA64_BRIDGE)
+#define	DBAT_SET(n, batl, batu)				\
+	do {						\
+		mtspr(SPR_DBAT##n##L, (batl));		\
+		mtspr(SPR_DBAT##n##U, (batu));		\
+	} while (/*CONSTCOND*/ 0)
+#define	DBAT_RESET(n)	DBAT_SET(n, 0, 0)
+#define	DBATU_GET(n)	mfspr(SPR_DBAT##n##U)
+#define	IBAT_SET(n, batl, batu)				\
+	do {						\
+		mtspr(SPR_IBAT##n##L, (batl));		\
+		mtspr(SPR_IBAT##n##U, (batu));		\
+	} while (/*CONSTCOND*/ 0)
+#define	IBAT_RESET(n)	IBAT_SET(n, 0, 0)
+	
 void
 oea_iobat_add(paddr_t pa, register_t len)
 {
-	static int n = 1;
-	const u_int i = pa >> 28;
-	battable[i].batl = BATL(pa, BAT_I|BAT_G, BAT_PP_RW);
-	battable[i].batu = BATU(pa, len, BAT_Vs);
+	static int z = 1;
+	const u_int n = __SHIFTOUT(len, (BAT_XBL|BAT_BL) & ~BAT_BL_8M);
+	const u_int i = BAT_VA2IDX(pa) & -n; /* in case pa was in the middle */
+	const int after_bat3 = (oeacpufeat & OEACPU_HIGHBAT) ? 4 : 8;
+
+	KASSERT(len >= BAT_BL_8M);
+
+	const register_t batl = BATL(pa, BAT_I|BAT_G, BAT_PP_RW);
+	const register_t batu = BATU(pa, len, BAT_Vs);
+
+	for (u_int j = 0; j < n; j++) {
+		battable[i + j].batl = batl;
+		battable[i + j].batu = batu;
+	}
 
 	/*
 	 * Let's start loading the BAT registers.
 	 */
-	switch (n) {
+	switch (z) {
 	case 1:
-		__asm volatile ("mtdbatl 1,%0; mtdbatu 1,%1;"
-		    ::	"r"(battable[i].batl),
-			"r"(battable[i].batu));
-		n = 2;
+		DBAT_SET(1, batl, batu);
+		z = 2;
 		break;
 	case 2:
-		__asm volatile ("mtdbatl 2,%0; mtdbatu 2,%1;"
-		    ::	"r"(battable[i].batl),
-			"r"(battable[i].batu));
-		n = 3;
+		DBAT_SET(2, batl, batu);
+		z = 3;
 		break;
 	case 3:
-		__asm volatile ("mtdbatl 3,%0; mtdbatu 3,%1;"
-		    ::	"r"(battable[i].batl),
-			"r"(battable[i].batu));
-		n = 4;
+		DBAT_SET(3, batl, batu);
+		z = after_bat3;			/* no highbat, skip to end */
+		break;
+	case 4:
+		DBAT_SET(4, batl, batu);
+		z = 5;
+		break;
+	case 5:
+		DBAT_SET(5, batl, batu);
+		z = 6;
+		break;
+	case 6:
+		DBAT_SET(6, batl, batu);
+		z = 7;
+		break;
+	case 7:
+		DBAT_SET(7, batl, batu);
+		z = 8;
 		break;
 	default:
 		break;
@@ -487,38 +528,63 @@ oea_iobat_add(paddr_t pa, register_t len
 void
 oea_iobat_remove(paddr_t pa)
 {
-	register_t batu;
-	int i, n;
+	const u_int i = BAT_VA2IDX(pa);
 
-	n = pa >> ADDR_SR_SHFT;
-	if (!BAT_VA_MATCH_P(battable[n].batu, pa) ||
-	    !BAT_VALID_P(battable[n].batu, PSL_PR))
+	if (!BAT_VA_MATCH_P(battable[i].batu, pa) ||
+	    !BAT_VALID_P(battable[i].batu, PSL_PR))
 		return;
-	battable[n].batl = 0;
-	battable[n].batu = 0;
-#define	BAT_RESET(n) \
-	__asm volatile("mtdbatu %0,%1; mtdbatl %0,%1" :: "n"(n), "r"(0))
-#define	BATU_GET(n, r)	__asm volatile("mfdbatu %0,%1" : "=r"(r) : "n"(n))
-
-	for (i=1 ; i<4 ; i++) {
-		switch (i) {
+	const int n =
+	    __SHIFTOUT(battable[i].batu, (BAT_XBL|BAT_BL) & ~BAT_BL_8M) + 1;
+	KASSERT((n & (n-1)) == 0);	/* power of 2 */
+	KASSERT((i & (n-1)) == 0);	/* multiple of n */
+
+	memset(&battable[i], 0, n*sizeof(battable[0]));
+
+	const int maxbat = oeacpufeat & OEACPU_HIGHBAT ? 8 : 4;
+	for (u_int k = 1 ; k < maxbat; k++) {
+		register_t batu;
+		switch (k) {
 		case 1:
-			BATU_GET(1, batu);
+			batu = DBATU_GET(1);
 			if (BAT_VA_MATCH_P(batu, pa) &&
 			    BAT_VALID_P(batu, PSL_PR))
-				BAT_RESET(1);
+				DBAT_RESET(1);
 			break;
 		case 2:
-			BATU_GET(2, batu);
+			batu = DBATU_GET(2);
 			if (BAT_VA_MATCH_P(batu, pa) &&
 			    BAT_VALID_P(batu, PSL_PR))
-				BAT_RESET(2);
+				DBAT_RESET(2);
 			break;
 		case 3:
-			BATU_GET(3, batu);
+			batu = DBATU_GET(3);
 			if (BAT_VA_MATCH_P(batu, pa) &&
 			    BAT_VALID_P(batu, PSL_PR))
-				BAT_RESET(3);
+				DBAT_RESET(3);
+			break;
+		case 4:
+			batu = DBATU_GET(4);
+			if (BAT_VA_MATCH_P(batu, pa) &&
+			    BAT_VALID_P(batu, PSL_PR))
+				DBAT_RESET(4);
+			break;
+		case 5:
+			batu = DBATU_GET(5);
+			if (BAT_VA_MATCH_P(batu, pa) &&
+			    BAT_VALID_P(batu, PSL_PR))
+				DBAT_RESET(5);
+			break;
+		case 6:
+			batu = DBATU_GET(6);
+			if (BAT_VA_MATCH_P(batu, pa) &&
+			    BAT_VALID_P(batu, PSL_PR))
+				DBAT_RESET(6);
+			break;
+		case 7:
+			batu = DBATU_GET(7);
+			if (BAT_VA_MATCH_P(batu, pa) &&
+			    BAT_VALID_P(batu, PSL_PR))
+				DBAT_RESET(7);
 			break;
 		default:
 			break;
@@ -558,14 +624,46 @@ oea_batinit(paddr_t pa, ...)
 		} else
 #endif /* PPC_OEA601 */
 		{
-			__asm volatile ("mtibatu 0,%0" :: "r"(0));
-			__asm volatile ("mtibatu 1,%0" :: "r"(0));
-			__asm volatile ("mtibatu 2,%0" :: "r"(0));
-			__asm volatile ("mtibatu 3,%0" :: "r"(0));
-			__asm volatile ("mtdbatu 0,%0" :: "r"(0));
-			__asm volatile ("mtdbatu 1,%0" :: "r"(0));
-			__asm volatile ("mtdbatu 2,%0" :: "r"(0));
-			__asm volatile ("mtdbatu 3,%0" :: "r"(0));
+			DBAT_RESET(0); IBAT_RESET(0);
+			DBAT_RESET(1); IBAT_RESET(1);
+			DBAT_RESET(2); IBAT_RESET(2);
+			DBAT_RESET(3); IBAT_RESET(3);
+			if (oeacpufeat & OEACPU_HIGHBAT) {
+				DBAT_RESET(4); IBAT_RESET(4);
+				DBAT_RESET(5); IBAT_RESET(5);
+				DBAT_RESET(6); IBAT_RESET(6);
+				DBAT_RESET(7); IBAT_RESET(7);
+
+				/*
+				 * Change the first instruction to branch to
+				 * dsitrap_fix_dbat6
+				 */
+				dsitrap_fix_dbat4[0] &= ~0xfffc;
+				dsitrap_fix_dbat4[0]
+				    += (uintptr_t)dsitrap_fix_dbat6
+				     - (uintptr_t)&dsitrap_fix_dbat4[0];
+
+				/*
+				 * Change the second instruction to branch to
+				 * dsitrap_fix_dbat5 if bit 30 (aka bit 1) is
+				 * true.
+				 */
+				dsitrap_fix_dbat4[1] = 0x419e0000
+				    + (uintptr_t)dsitrap_fix_dbat5
+				    - (uintptr_t)&dsitrap_fix_dbat4[1];
+
+				/*
+				 * Change it to load dbat4 instead of dbat2
+				 */
+				dsitrap_fix_dbat4[2] = 0x7fd88ba6;
+				dsitrap_fix_dbat4[3] = 0x7ff98ba6;
+
+				/*
+				 * Change it to load dbat7 instead of dbat3
+				 */
+				dsitrap_fix_dbat7[0] = 0x7fde8ba6;
+				dsitrap_fix_dbat7[1] = 0x7fff8ba6;
+			}
 		}
 	}
 
@@ -599,19 +697,8 @@ oea_batinit(paddr_t pa, ...)
 		__asm volatile ("mtibatu 3,%1; mtibatl 3,%0"
 		    :: "r"(battable[0x01800000 >> 23].batl),
 		       "r"(battable[0x01800000 >> 23].batu));
-	} else
-#endif /* PPC_OEA601 */
-	{
-		/*
-		 * Set up BAT0 to only map the lowest 256 MB area
-		 */
-		battable[0].batl = BATL(0x00000000, BAT_M, BAT_PP_RW);
-		battable[0].batu = BATU(0x00000000, BAT_BL_256M, BAT_Vs);
-
-		__asm volatile ("mtibatl 0,%0; mtibatu 0,%1;"
-				  "mtdbatl 0,%0; mtdbatu 0,%1;"
-		    ::	"r"(battable[0].batl), "r"(battable[0].batu));
 	}
+#endif /* PPC_OEA601 */
 
 	/*
 	 * Now setup other fixed bat registers
@@ -669,20 +756,55 @@ oea_batinit(paddr_t pa, ...)
 	} else
 #endif
 	{
+		const register_t bat_inc = BAT_IDX2VA(1);
 		for (mp = allmem; mp->size; mp++) {
-			paddr_t paddr = mp->start & 0xf0000000;
-			paddr_t end = mp->start + mp->size;
+			paddr_t paddr = mp->start & -bat_inc;
+			paddr_t end = roundup2(mp->start + mp->size, bat_inc);
 
-			do {
-				u_int ix = paddr >> 28;
+			/*
+			 * If the next entries are adjacent, merge them
+			 * into this one
+			 */
+			while (mp[1].size && end == (mp[1].start & -bat_inc)) {
+				mp++;
+				end = roundup2(mp->start + mp->size, bat_inc);
+			}
 
-				battable[ix].batl =
-				    BATL(paddr, BAT_M, BAT_PP_RW);
-				battable[ix].batu =
-				    BATU(paddr, BAT_BL_256M, BAT_Vs);
-				paddr += SEGMENT_LENGTH;
-			} while (paddr < end);
+			while (paddr < end) {
+				register_t bl = (oeacpufeat & OEACPU_XBSEN
+				    ? BAT_BL_2G
+				    : BAT_BL_256M);
+				psize_t size = BAT_BL_TO_SIZE(bl);
+				u_int n = BAT_VA2IDX(size);
+				u_int i = BAT_VA2IDX(paddr);
+
+				while ((paddr & (size - 1))
+				    || paddr + size > end) {
+					size >>= 1;
+					bl = (bl >> 1) & (BAT_XBL|BAT_BL);
+					n >>= 1;
+				}
+
+				KASSERT(size >= bat_inc);
+				KASSERT(n >= 1);
+				KASSERT(bl >= BAT_BL_8M);
+
+				register_t batl = BATL(paddr, BAT_M, BAT_PP_RW);
+				register_t batu = BATU(paddr, bl, BAT_Vs);
+
+				for (; n-- > 0; i++) {
+					battable[i].batl = batl;
+					battable[i].batu = batu;
+				}
+				paddr += size;
+			}
 		}
+		/*
+		 * Set up BAT0 to only map the lowest area.
+		 */
+		__asm volatile ("mtibatl 0,%0; mtibatu 0,%1;"
+				  "mtdbatl 0,%0; mtdbatu 0,%1;"
+		    ::	"r"(battable[0].batl), "r"(battable[0].batu));
 	}
 }
 #endif /* PPC_OEA || PPC_OEA64_BRIDGE */

Index: src/sys/arch/powerpc/oea/ofw_rascons.c
diff -u src/sys/arch/powerpc/oea/ofw_rascons.c:1.6 src/sys/arch/powerpc/oea/ofw_rascons.c:1.7
--- src/sys/arch/powerpc/oea/ofw_rascons.c:1.6	Fri Jul  1 18:59:19 2011
+++ src/sys/arch/powerpc/oea/ofw_rascons.c	Wed Feb  1 05:25:57 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: ofw_rascons.c,v 1.6 2011/07/01 18:59:19 dyoung Exp $	*/
+/*	$NetBSD: ofw_rascons.c,v 1.7 2012/02/01 05:25:57 matt Exp $	*/
 
 /*
  * Copyright (c) 1995, 1996 Carnegie-Mellon University.
@@ -28,7 +28,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ofw_rascons.c,v 1.6 2011/07/01 18:59:19 dyoung Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ofw_rascons.c,v 1.7 2012/02/01 05:25:57 matt Exp $");
 
 #include <sys/param.h>
 #include <sys/buf.h>
@@ -199,17 +199,27 @@ rascons_init_rasops(int node, struct ras
 	if (rascons_enable_cache) {
 		vaddr_t va;
 		/*
-		 * Let's try to find an empty BAT to use
+		 * Let's try to find an empty 256M BAT to use
 		 */
 		for (va = SEGMENT_LENGTH; va < (USER_SR << ADDR_SR_SHFT);
 		     va += SEGMENT_LENGTH) {
-			if (battable[va >> ADDR_SR_SHFT].batu == 0) {
-				battable[va >> ADDR_SR_SHFT].batl =
-				    BATL(fbaddr & 0xf0000000,
-					 BAT_G | BAT_W | BAT_M, BAT_PP_RW);
-				battable[va >> ADDR_SR_SHFT].batu =
-				    BATL(va, BAT_BL_256M, BAT_Vs);
-				fbaddr &= 0x0fffffff;
+			const u_int i = BAT_VA2IDX(va);
+			const u_int n = BAT_VA2IDX(SEGMENT_LENGTH);
+			u_int j;
+			for (j = 0; j < n; j++) {
+				if (battable[i+j].batu != 0) {
+					break;
+				}
+			}
+			if (j == n) {
+				register_t batl = BATL(fbaddr & 0xf0000000,
+				    BAT_G | BAT_W | BAT_M, BAT_PP_RW);
+				register_t batu = BATL(va, BAT_BL_256M, BAT_Vs);
+				for (j = 0; j < n; j++) {
+					battable[i+j].batl = batl;
+					battable[i+j].batu = batu;
+				}
+				fbaddr &= SEGMENT_MASK;
 				fbaddr |= va;
 				break;
 			}

Index: src/sys/arch/powerpc/oea/pmap.c
diff -u src/sys/arch/powerpc/oea/pmap.c:1.82 src/sys/arch/powerpc/oea/pmap.c:1.83
--- src/sys/arch/powerpc/oea/pmap.c:1.82	Sun Jul 17 20:54:46 2011
+++ src/sys/arch/powerpc/oea/pmap.c	Wed Feb  1 05:25:57 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: pmap.c,v 1.82 2011/07/17 20:54:46 joerg Exp $	*/
+/*	$NetBSD: pmap.c,v 1.83 2012/02/01 05:25:57 matt Exp $	*/
 /*-
  * Copyright (c) 2001 The NetBSD Foundation, Inc.
  * All rights reserved.
@@ -63,7 +63,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.82 2011/07/17 20:54:46 joerg Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.83 2012/02/01 05:25:57 matt Exp $");
 
 #define	PMAP_NOOPNAMES
 
@@ -2131,12 +2131,11 @@ pmap_extract(pmap_t pm, vaddr_t va, padd
 		} else
 #endif /* PPC_OEA601 */
 		{
-			register_t batu = battable[va >> ADDR_SR_SHFT].batu;
+			register_t batu = battable[BAT_VA2IDX(va)].batu;
 			if (BAT_VALID_P(batu,0) && BAT_VA_MATCH_P(batu,va)) {
-				register_t batl =
-				    battable[va >> ADDR_SR_SHFT].batl;
+				register_t batl = battable[BAT_VA2IDX(va)].batl;
 				register_t mask =
-				    (~(batu & BAT_BL) << 15) & ~0x1ffffL;
+				    (~(batu & (BAT_XBL|BAT_BL)) << 15) & ~0x1ffffL;
 				if (pap)
 					*pap = (batl & mask) | (va & ~mask);
 				PMAP_UNLOCK();

Index: src/sys/arch/powerpc/powerpc/bus_space.c
diff -u src/sys/arch/powerpc/powerpc/bus_space.c:1.30 src/sys/arch/powerpc/powerpc/bus_space.c:1.31
--- src/sys/arch/powerpc/powerpc/bus_space.c:1.30	Fri Jan 27 18:53:00 2012
+++ src/sys/arch/powerpc/powerpc/bus_space.c	Wed Feb  1 05:25:58 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: bus_space.c,v 1.30 2012/01/27 18:53:00 para Exp $	*/
+/*	$NetBSD: bus_space.c,v 1.31 2012/02/01 05:25:58 matt Exp $	*/
 
 /*-
  * Copyright (c) 1996, 1997, 1998 The NetBSD Foundation, Inc.
@@ -31,7 +31,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: bus_space.c,v 1.30 2012/01/27 18:53:00 para Exp $");
+__KERNEL_RCSID(0, "$NetBSD: bus_space.c,v 1.31 2012/02/01 05:25:58 matt Exp $");
 
 #define _POWERPC_BUS_SPACE_PRIVATE
 
@@ -550,20 +550,21 @@ memio_map(bus_space_tag_t t, bus_addr_t 
 		 */
 		if (extent_flags) {
 #endif
-		/*
-		 * Before we go any further, let's make sure that this
-		 * region is available.
-		 */
-		error = extent_alloc_region(t->pbs_extent, bpa, size,
-		    EX_NOWAIT | extent_flags);
-		if (error) {
+			/*
+			 * Before we go any further, let's make sure that this
+			 * region is available.
+			 */
+			error = extent_alloc_region(t->pbs_extent, bpa, size,
+			    EX_NOWAIT | extent_flags);
+			if (error) {
 #ifdef DEBUG
-			printf("bus_space_map(%p[%x:%x], %#x, %#x) failed"
-			    ": %d\n",
-			    t, t->pbs_base, t->pbs_limit, bpa, size, error);
+				printf("bus_space_map(%p[%x:%x], %#x, %#x)"
+				    " failed: %d\n",
+				    t, t->pbs_base, t->pbs_limit,
+				    bpa, size, error);
 #endif
-			return (error);
-		}
+				return (error);
+			}
 #ifdef PPC_IBM4XX
 		}
 #endif
@@ -600,14 +601,15 @@ memio_map(bus_space_tag_t t, bus_addr_t 
 
 	if (t->pbs_extent != NULL) {
 #if !defined(PPC_IBM4XX)
-	if (extent_flags == 0) {
-		extent_free(t->pbs_extent, bpa, size, EX_NOWAIT);
+		if (extent_flags == 0) {
+			extent_free(t->pbs_extent, bpa, size, EX_NOWAIT);
 #ifdef DEBUG
-		printf("bus_space_map(%p[%x:%x], %#x, %#x) failed: ENOMEM\n",
-		    t, t->pbs_base, t->pbs_limit, bpa, size);
+			printf("bus_space_map(%p[%x:%x], %#x, %#x)"
+			    " failed: ENOMEM\n",
+			    t, t->pbs_base, t->pbs_limit, bpa, size);
 #endif
-		return (ENOMEM);
-	}
+			return (ENOMEM);
+		}
 #endif
 	}
 
@@ -617,7 +619,10 @@ memio_map(bus_space_tag_t t, bus_addr_t 
 	*bshp = (bus_space_handle_t) mapiodev(pa, size,
 	    (flags & BUS_SPACE_MAP_PREFETCHABLE) != 0);
 	if (*bshp == 0) {
-		extent_free(t->pbs_extent, bpa, size, EX_NOWAIT | extent_flags);
+		if (t->pbs_extent != NULL) {
+			extent_free(t->pbs_extent, bpa, size,
+			    EX_NOWAIT | extent_flags);
+		}
 #ifdef DEBUG
 		printf("bus_space_map(%p[%x:%x], %#x, %#x) failed: ENOMEM\n",
 		    t, t->pbs_base, t->pbs_limit, bpa, size);

Index: src/sys/arch/powerpc/powerpc/db_interface.c
diff -u src/sys/arch/powerpc/powerpc/db_interface.c:1.48 src/sys/arch/powerpc/powerpc/db_interface.c:1.49
--- src/sys/arch/powerpc/powerpc/db_interface.c:1.48	Tue Dec 13 11:03:52 2011
+++ src/sys/arch/powerpc/powerpc/db_interface.c	Wed Feb  1 05:25:58 2012
@@ -1,8 +1,8 @@
-/*	$NetBSD: db_interface.c,v 1.48 2011/12/13 11:03:52 kiyohara Exp $ */
+/*	$NetBSD: db_interface.c,v 1.49 2012/02/01 05:25:58 matt Exp $ */
 /*	$OpenBSD: db_interface.c,v 1.2 1996/12/28 06:21:50 rahnds Exp $	*/
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: db_interface.c,v 1.48 2011/12/13 11:03:52 kiyohara Exp $");
+__KERNEL_RCSID(0, "$NetBSD: db_interface.c,v 1.49 2012/02/01 05:25:58 matt Exp $");
 
 #define USERACC
 
@@ -26,6 +26,7 @@ __KERNEL_RCSID(0, "$NetBSD: db_interface
 #if defined (PPC_OEA) || defined(PPC_OEA64) || defined (PPC_OEA64_BRIDGE)
 #include <powerpc/oea/spr.h>
 #include <powerpc/oea/bat.h>
+#include <powerpc/oea/cpufeat.h>
 #endif
 
 #ifdef PPC_IBM4XX
@@ -249,10 +250,10 @@ kdb_trap(int type, void *v)
 static void
 print_battranslation(struct bat *bat, unsigned int blidx)
 {
-	static const char *const batsizes[] = {
-		"128kB",
-		"256kB",
-		"512kB",
+	static const char const batsizes[][6] = {
+		"128KB",
+		"256KB",
+		"512KB",
 		"1MB",
 		"2MB",
 		"4MB",
@@ -261,7 +262,11 @@ print_battranslation(struct bat *bat, un
 		"32MB",
 		"64MB",
 		"128MB",
-		"256MB"
+		"256MB",
+		"512MB",
+		"1GB",
+		"2GB",
+		"4GB",
 	};
 	vsize_t len;
 
@@ -305,7 +310,8 @@ print_bat(struct bat *bat)
 		db_printf("\tdisabled\n\n");
 		return;
 	}
-	print_battranslation(bat, 30 - __builtin_clz((bat->batu & BAT_BL)|2));
+	print_battranslation(bat,
+	    30 - __builtin_clz((bat->batu & (BAT_XBL|BAT_BL))|2));
 	print_batmodes(bat->batu & BAT_Vs, bat->batu & BAT_Vu,
 	    bat->batl & BAT_PP);
 	print_wimg(bat->batl & BAT_WIMG);
@@ -331,49 +337,66 @@ print_bat601(struct bat *bat)
 static void
 db_show_bat(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif)
 {
-	struct bat ibat[4];
-	struct bat dbat[4];
+	struct bat ibat[8];
+	struct bat dbat[8];
 	unsigned int cpuvers;
-	int i;
+	u_int i;
+	u_int maxbat = (oeacpufeat & OEACPU_HIGHBAT) ? 8 : 4;
 
 	cpuvers = mfpvr() >> 16;
 
-	__asm volatile ("mfibatu %0,0" : "=r"(ibat[0].batu));
-	__asm volatile ("mfibatl %0,0" : "=r"(ibat[0].batl));
-	__asm volatile ("mfibatu %0,1" : "=r"(ibat[1].batu));
-	__asm volatile ("mfibatl %0,1" : "=r"(ibat[1].batl));
-	__asm volatile ("mfibatu %0,2" : "=r"(ibat[2].batu));
-	__asm volatile ("mfibatl %0,2" : "=r"(ibat[2].batl));
-	__asm volatile ("mfibatu %0,3" : "=r"(ibat[3].batu));
-	__asm volatile ("mfibatl %0,3" : "=r"(ibat[3].batl));
+	ibat[0].batu = mfspr(SPR_IBAT0U);
+	ibat[0].batl = mfspr(SPR_IBAT0L);
+	ibat[1].batu = mfspr(SPR_IBAT1U);
+	ibat[1].batl = mfspr(SPR_IBAT1L);
+	ibat[2].batu = mfspr(SPR_IBAT2U);
+	ibat[2].batl = mfspr(SPR_IBAT2L);
+	ibat[3].batu = mfspr(SPR_IBAT3U);
+	ibat[3].batl = mfspr(SPR_IBAT3L);
+	if (maxbat == 8) {
+		ibat[4].batu = mfspr(SPR_IBAT4U);
+		ibat[4].batl = mfspr(SPR_IBAT4L);
+		ibat[5].batu = mfspr(SPR_IBAT5U);
+		ibat[5].batl = mfspr(SPR_IBAT5L);
+		ibat[6].batu = mfspr(SPR_IBAT6U);
+		ibat[6].batl = mfspr(SPR_IBAT6L);
+		ibat[7].batu = mfspr(SPR_IBAT7U);
+		ibat[7].batl = mfspr(SPR_IBAT7L);
+	}
 
 	if (cpuvers != MPC601) {
 		/* The 601 has only four unified BATs */
-		__asm volatile ("mfdbatu %0,0" : "=r"(dbat[0].batu));
-		__asm volatile ("mfdbatl %0,0" : "=r"(dbat[0].batl));
-		__asm volatile ("mfdbatu %0,1" : "=r"(dbat[1].batu));
-		__asm volatile ("mfdbatl %0,1" : "=r"(dbat[1].batl));
-		__asm volatile ("mfdbatu %0,2" : "=r"(dbat[2].batu));
-		__asm volatile ("mfdbatl %0,2" : "=r"(dbat[2].batl));
-		__asm volatile ("mfdbatu %0,3" : "=r"(dbat[3].batu));
-		__asm volatile ("mfdbatl %0,3" : "=r"(dbat[3].batl));
+		dbat[0].batu = mfspr(SPR_DBAT0U);
+		dbat[0].batl = mfspr(SPR_DBAT0L);
+		dbat[1].batu = mfspr(SPR_DBAT1U);
+		dbat[1].batl = mfspr(SPR_DBAT1L);
+		dbat[2].batu = mfspr(SPR_DBAT2U);
+		dbat[2].batl = mfspr(SPR_DBAT2L);
+		dbat[3].batu = mfspr(SPR_DBAT3U);
+		dbat[3].batl = mfspr(SPR_DBAT3L);
+		if (maxbat == 8) {
+			dbat[4].batu = mfspr(SPR_DBAT4U);
+			dbat[4].batl = mfspr(SPR_DBAT4L);
+			dbat[5].batu = mfspr(SPR_DBAT5U);
+			dbat[5].batl = mfspr(SPR_DBAT5L);
+			dbat[6].batu = mfspr(SPR_DBAT6U);
+			dbat[6].batl = mfspr(SPR_DBAT6L);
+			dbat[7].batu = mfspr(SPR_DBAT7U);
+			dbat[7].batl = mfspr(SPR_DBAT7L);
+		}
 	}
 
-	for (i = 0; i < 4; i++) {
+	for (i = 0; i < maxbat; i++) {
 #ifdef PPC_OEA601
 		if (cpuvers == MPC601) {
-			db_printf("bat%d:", i);
+			db_printf("bat[%u]:\n", i);
 			print_bat601(&ibat[i]);
 		} else
 #endif
 		{
-			db_printf("ibat%d:", i);
+			db_printf("ibat[%u]:\n", i);
 			print_bat(&ibat[i]);
-		}
-	}
-	if (cpuvers != MPC601) {
-		for (i = 0; i < 4; i++) {
-			db_printf("dbat%d:", i);
+			db_printf("dbat[%u]:\n", i);
 			print_bat(&dbat[i]);
 		}
 	}

Index: src/sys/arch/powerpc/powerpc/trap_subr.S
diff -u src/sys/arch/powerpc/powerpc/trap_subr.S:1.72 src/sys/arch/powerpc/powerpc/trap_subr.S:1.73
--- src/sys/arch/powerpc/powerpc/trap_subr.S:1.72	Tue Dec 13 11:03:51 2011
+++ src/sys/arch/powerpc/powerpc/trap_subr.S	Wed Feb  1 05:25:58 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: trap_subr.S,v 1.72 2011/12/13 11:03:51 kiyohara Exp $	*/
+/*	$NetBSD: trap_subr.S,v 1.73 2012/02/01 05:25:58 matt Exp $	*/
 
 /*
  * Copyright (C) 1995, 1996 Wolfgang Solfrank.
@@ -238,7 +238,8 @@ _C_LABEL(dsitrap):
 	mtcr	%r31
 	bt	MSR_PR,1f		/* branch if PSL_PR is set */
 	mfdar	%r31			/* get fault address */
-	rlwinm	%r31,%r31,7,25,28	/* get segment * 8 */
+	rlwinm	%r31,%r31,3+(32-BAT_ADDR_SHIFT),BAT_ADDR_SHIFT-3,28
+					/* get segment * 8 */
 
 	/* get batu */
 	addis	%r31,%r31,_C_LABEL(battable)@ha
@@ -250,15 +251,39 @@ _C_LABEL(dsitrap):
 	ldreg	%r31,_C_LABEL(battable)+SZREG@l(%r31)
 /* We randomly use the highest two bat registers here */
 	mftb	%r28
-	andi.	%r28,%r28,1
-	bne	2f
-	mtdbatu	2,%r30
-	mtdbatl	2,%r31
-	b	3f
-2:
-	mtdbatu	3,%r30
-	mtdbatl	3,%r31
+	mtcr	%r28
+	.globl	dsitrap_fix_dbat4, dsitrap_fix_dbat5
+	.globl	dsitrap_fix_dbat6, dsitrap_fix_dbat7
+dsitrap_fix_dbat4:
+	bt	31,3f
+	/*
+	 * If we are running on a CPU that has HIGHBAT, these will be replaced
+	 * by instructions to test bit 30 (aka bit 1 for normal people) and if
+	 * set skip ahead to 5f (4 instructions),  follored by instructions to
+	 * update BAT4.
+	 */
+	mtspr	SPR_DBAT2U,%r30		/*	bt	30,dsitrap_fix_dbat5 */
+	mtspr	SPR_DBAT2L,%r31		/*	mtspr	SPR_DBAT4U,%r30 */
+	b	8f			/*	mtspr	SPR_DBAT4L,%r31 */	
+	b	8f			/*	do not remove */
+dsitrap_fix_dbat5:
+	mtspr	SPR_DBAT5U,%r30
+	mtspr	SPR_DBAT5L,%r31
+	b	8f
+dsitrap_fix_dbat6:
+	bt	30,3f
+	mtspr	SPR_DBAT6U,%r30
+	mtspr	SPR_DBAT6L,%r31
+	b	8f
 3:
+dsitrap_fix_dbat7:
+	/*
+	 * If we are running on a CPU that has HIGHBAT, these will be replaced
+	 * by instructions to update BAT7.
+	 */
+	mtspr	SPR_DBAT3U,%r30		/*	mtspr	SPR_DBAT7U,%r30 */
+	mtspr	SPR_DBAT3L,%r31		/*	mtspr	SPR_DBAT7L,%r31 */
+8:
 	mfsprg2	%r30			/* restore XER */
 	mtxer	%r30
 	mtcr	%r29			/* restore CR */

Reply via email to