svn commit: r257178 - in head/sys/powerpc: aim booke include mpc85xx powerpc

Nathan Whitehorn nwhitehorn at FreeBSD.org
Sat Oct 26 18:18:16 UTC 2013


Author: nwhitehorn
Date: Sat Oct 26 18:18:14 2013
New Revision: 257178
URL: http://svnweb.freebsd.org/changeset/base/257178

Log:
  Interrelated improvements to early boot mappings:
  - Remove explicit requirement that the SOC registers be found except as an
    optimization (although the MPC85XX LAW drivers still require they be found
    externally, which should change).
  - Remove magic CCSRBAR_VA value.
  - Allow bus_machdep.c's early-boot code to handle non 1:1 mappings and
    systems not in real-mode or global 1:1 maps in early boot.
  - Allow pmap_mapdev() on Book-E to reissue previous addresses if the
    area is already mapped. Additionally have it check all mappings, not
    just the CCSR area.
  
  This allows the console on e500 systems to actually work on systems where
  the boot loader was not kind enough to set up a 1:1 mapping before starting
  the kernel.

Modified:
  head/sys/powerpc/aim/machdep.c
  head/sys/powerpc/booke/machdep.c
  head/sys/powerpc/booke/machdep_e500.c
  head/sys/powerpc/booke/pmap.c
  head/sys/powerpc/include/pmap.h
  head/sys/powerpc/include/tlb.h
  head/sys/powerpc/include/vmparam.h
  head/sys/powerpc/mpc85xx/mpc85xx.c
  head/sys/powerpc/mpc85xx/mpc85xx.h
  head/sys/powerpc/powerpc/bus_machdep.c

Modified: head/sys/powerpc/aim/machdep.c
==============================================================================
--- head/sys/powerpc/aim/machdep.c	Sat Oct 26 18:03:36 2013	(r257177)
+++ head/sys/powerpc/aim/machdep.c	Sat Oct 26 18:18:14 2013	(r257178)
@@ -775,3 +775,11 @@ va_to_vsid(pmap_t pm, vm_offset_t va)
 }
 
 #endif
+
+vm_offset_t
+pmap_early_io_map(vm_paddr_t pa, vm_size_t size)
+{
+
+	return (pa);
+}
+

Modified: head/sys/powerpc/booke/machdep.c
==============================================================================
--- head/sys/powerpc/booke/machdep.c	Sat Oct 26 18:03:36 2013	(r257177)
+++ head/sys/powerpc/booke/machdep.c	Sat Oct 26 18:18:14 2013	(r257178)
@@ -350,13 +350,18 @@ booke_init(uint32_t arg1, uint32_t arg2)
 	if (OF_init((void *)dtbp) != 0)
 		while (1);
 
-	if (fdt_immr_addr(CCSRBAR_VA) != 0)
-		while (1);
-
 	OF_interpret("perform-fixup", 0);
 	
 	/* Set up TLB initially */
-	booke_init_tlb(fdt_immr_pa);
+	tlb1_init();
+
+	/* Set up IMMR */
+	if (fdt_immr_addr(0) == 0) {
+		fdt_immr_va = pmap_early_io_map(fdt_immr_pa, fdt_immr_size);
+	} else {
+		printf("Warning: SOC base registers could not be found!\n");
+		fdt_immr_va = 0;
+	}
 
 	/* Reset Time Base */
 	mttb(0);

Modified: head/sys/powerpc/booke/machdep_e500.c
==============================================================================
--- head/sys/powerpc/booke/machdep_e500.c	Sat Oct 26 18:03:36 2013	(r257177)
+++ head/sys/powerpc/booke/machdep_e500.c	Sat Oct 26 18:18:14 2013	(r257178)
@@ -47,8 +47,6 @@ void
 booke_init_tlb(vm_paddr_t fdt_immr_pa)
 {
 
-	/* Initialize TLB1 handling */
-	tlb1_init(fdt_immr_pa);
 }
 
 void

Modified: head/sys/powerpc/booke/pmap.c
==============================================================================
--- head/sys/powerpc/booke/pmap.c	Sat Oct 26 18:03:36 2013	(r257177)
+++ head/sys/powerpc/booke/pmap.c	Sat Oct 26 18:18:14 2013	(r257178)
@@ -113,7 +113,6 @@ extern uint32_t *bootinfo;
 extern uint32_t bp_ntlb1s;
 #endif
 
-vm_paddr_t ccsrbar_pa;
 vm_paddr_t kernload;
 vm_offset_t kernstart;
 vm_size_t kernsize;
@@ -2662,22 +2661,25 @@ mmu_booke_mapdev_attr(mmu_t mmu, vm_padd
 	void *res;
 	uintptr_t va;
 	vm_size_t sz;
+	int i;
 
 	/*
-	 * CCSR is premapped. Note that (pa + size - 1) is there to make sure
-	 * we don't wrap around. Devices on the local bus typically extend all
-	 * the way up to and including 0xffffffff. In that case (pa + size)
-	 * would be 0. This creates a false positive (i.e. we think it's
-	 * within the CCSR) and not create a mapping.
-	 */
-	if (ma == VM_MEMATTR_DEFAULT && pa >= ccsrbar_pa &&
-	    (pa + size - 1) < (ccsrbar_pa + CCSRBAR_SIZE)) {
-		va = CCSRBAR_VA + (pa - ccsrbar_pa);
-		return ((void *)va);
+	 * Check if this is premapped in TLB1. Note: this should probably also
+	 * check whether a sequence of TLB1 entries exist that match the
+	 * requirement, but now only checks the easy case.
+	 */
+	if (ma == VM_MEMATTR_DEFAULT) {
+		for (i = 0; i < tlb1_idx; i++) {
+			if (!(tlb1[i].mas1 & MAS1_VALID))
+				continue;
+			if (pa >= tlb1[i].phys &&
+			    (pa + size) <= (tlb1[i].phys + tlb1[i].size))
+				return (void *)(tlb1[i].virt +
+				    (pa - tlb1[i].phys));
+		}
 	}
 
-	if (size < PAGE_SIZE)
-	    size = PAGE_SIZE;
+	size = roundup(size, PAGE_SIZE);
 
 	if (pa >= (VM_MAXUSER_ADDRESS + PAGE_SIZE) &&
 	    (pa + size - 1) < VM_MIN_KERNEL_ADDRESS) 
@@ -2899,9 +2901,8 @@ tlb0_print_tlbentries(void)
 /*
  * TLB1 mapping notes:
  *
- * TLB1[0]	CCSRBAR
- * TLB1[1]	Kernel text and data.
- * TLB1[2-15]	Additional kernel text and data mappings (if required), PCI
+ * TLB1[0]	Kernel text and data.
+ * TLB1[1-15]	Additional kernel text and data mappings (if required), PCI
  *		windows, other devices mappings.
  */
 
@@ -3094,14 +3095,12 @@ tlb1_mapin_region(vm_offset_t va, vm_pad
  * assembler level setup done in locore.S.
  */
 void
-tlb1_init(vm_offset_t ccsrbar)
+tlb1_init()
 {
-	uint32_t mas0, mas1, mas3;
+	uint32_t mas0, mas1, mas2, mas3;
 	uint32_t tsz;
 	u_int i;
 
-	ccsrbar_pa = ccsrbar;
-
 	if (bootinfo != NULL && bootinfo[0] != 1) {
 		tlb1_idx = *((uint16_t *)(bootinfo + 8));
 	} else
@@ -3117,22 +3116,23 @@ tlb1_init(vm_offset_t ccsrbar)
 		if ((mas1 & MAS1_VALID) == 0)
 			continue;
 
+		mas2 = mfspr(SPR_MAS2);
 		mas3 = mfspr(SPR_MAS3);
 
 		tlb1[i].mas1 = mas1;
 		tlb1[i].mas2 = mfspr(SPR_MAS2);
 		tlb1[i].mas3 = mas3;
+		tlb1[i].virt = mas2 & MAS2_EPN_MASK;
+		tlb1[i].phys = mas3 & MAS3_RPN;
 
 		if (i == 0)
 			kernload = mas3 & MAS3_RPN;
 
 		tsz = (mas1 & MAS1_TSIZE_MASK) >> MAS1_TSIZE_SHIFT;
-		kernsize += (tsz > 0) ? tsize2size(tsz) : 0;
+		tlb1[i].size = (tsz > 0) ? tsize2size(tsz) : 0;
+		kernsize += tlb1[i].size;
 	}
 
-	/* Map in CCSRBAR. */
-	tlb1_set_entry(CCSRBAR_VA, ccsrbar, CCSRBAR_SIZE, _TLB_ENTRY_IO);
-
 #ifdef SMP
 	bp_ntlb1s = tlb1_idx;
 #endif
@@ -3145,6 +3145,43 @@ tlb1_init(vm_offset_t ccsrbar)
 	set_mas4_defaults();
 }
 
+vm_offset_t 
+pmap_early_io_map(vm_paddr_t pa, vm_size_t size)
+{
+	static vm_offset_t early_io_map_base = VM_MAX_KERNEL_ADDRESS;
+	vm_paddr_t pa_base;
+	vm_offset_t va, sz;
+	int i;
+
+	KASSERT(!pmap_bootstrapped, ("Do not use after PMAP is up!"));
+	
+	for (i = 0; i < tlb1_idx; i++) {
+		if (!(tlb1[i].mas1 & MAS1_VALID))
+			continue;
+		if (pa >= tlb1[i].phys && (pa + size) <=
+		    (tlb1[i].phys + tlb1[i].size))
+			return (tlb1[i].virt + (pa - tlb1[i].phys));
+	}
+
+	pa_base = trunc_page(pa);
+	size = roundup(size + (pa - pa_base), PAGE_SIZE);
+	va = early_io_map_base + (pa - pa_base);
+
+	do {
+		sz = 1 << (ilog2(size) & ~1);
+		tlb1_set_entry(early_io_map_base, pa_base, sz, _TLB_ENTRY_IO);
+		size -= sz;
+		pa_base += sz;
+		early_io_map_base += sz;
+	} while (size > 0);
+
+#ifdef SMP
+	bp_ntlb1s = tlb1_idx;
+#endif
+
+	return (va);
+}
+
 /*
  * Setup MAS4 defaults.
  * These values are loaded to MAS0-2 on a TLB miss.

Modified: head/sys/powerpc/include/pmap.h
==============================================================================
--- head/sys/powerpc/include/pmap.h	Sat Oct 26 18:03:36 2013	(r257177)
+++ head/sys/powerpc/include/pmap.h	Sat Oct 26 18:18:14 2013	(r257178)
@@ -254,6 +254,8 @@ extern void pmap_dumpsys_unmap(struct pm
 
 extern struct pmap_md *pmap_scan_md(struct pmap_md *);
 
+vm_offset_t pmap_early_io_map(vm_paddr_t pa, vm_size_t size);
+
 #endif
 
 #endif /* !_MACHINE_PMAP_H_ */

Modified: head/sys/powerpc/include/tlb.h
==============================================================================
--- head/sys/powerpc/include/tlb.h	Sat Oct 26 18:03:36 2013	(r257177)
+++ head/sys/powerpc/include/tlb.h	Sat Oct 26 18:18:14 2013	(r257178)
@@ -126,6 +126,9 @@
 
 #if !defined(LOCORE)
 typedef struct tlb_entry {
+	vm_paddr_t phys;
+	vm_offset_t virt;
+	vm_size_t size;
 	uint32_t mas1;
 	uint32_t mas2;
 	uint32_t mas3;
@@ -134,7 +137,7 @@ typedef struct tlb_entry {
 void tlb0_print_tlbentries(void);
 
 void tlb1_inval_entry(unsigned int);
-void tlb1_init(vm_offset_t);
+void tlb1_init(void);
 void tlb1_print_entries(void);
 void tlb1_print_tlbentries(void);
 #endif /* !LOCORE */

Modified: head/sys/powerpc/include/vmparam.h
==============================================================================
--- head/sys/powerpc/include/vmparam.h	Sat Oct 26 18:03:36 2013	(r257177)
+++ head/sys/powerpc/include/vmparam.h	Sat Oct 26 18:18:14 2013	(r257178)
@@ -108,12 +108,6 @@
 
 #else /* Book-E */
 
-/*
- * Kernel CCSRBAR location. We make this the reset location.
- */
-#define	CCSRBAR_VA		0xfef00000
-#define	CCSRBAR_SIZE		0x00100000
-
 #define	KERNBASE		0xc0000000	/* start of kernel virtual */
 
 #define	VM_MIN_KERNEL_ADDRESS	KERNBASE

Modified: head/sys/powerpc/mpc85xx/mpc85xx.c
==============================================================================
--- head/sys/powerpc/mpc85xx/mpc85xx.c	Sat Oct 26 18:03:36 2013	(r257177)
+++ head/sys/powerpc/mpc85xx/mpc85xx.c	Sat Oct 26 18:18:14 2013	(r257178)
@@ -41,6 +41,8 @@ __FBSDID("$FreeBSD$");
 #include <machine/pio.h>
 #include <machine/spr.h>
 
+#include <dev/fdt/fdt_common.h>
+
 #include <powerpc/mpc85xx/mpc85xx.h>
 
 /*

Modified: head/sys/powerpc/mpc85xx/mpc85xx.h
==============================================================================
--- head/sys/powerpc/mpc85xx/mpc85xx.h	Sat Oct 26 18:03:36 2013	(r257177)
+++ head/sys/powerpc/mpc85xx/mpc85xx.h	Sat Oct 26 18:18:14 2013	(r257178)
@@ -33,6 +33,7 @@
 /*
  * Configuration control and status registers
  */
+#define CCSRBAR_VA		fdt_immr_va
 #define	OCP85XX_CCSRBAR		(CCSRBAR_VA + 0x0)
 #define	OCP85XX_BPTR		(CCSRBAR_VA + 0x20)
 

Modified: head/sys/powerpc/powerpc/bus_machdep.c
==============================================================================
--- head/sys/powerpc/powerpc/bus_machdep.c	Sat Oct 26 18:03:36 2013	(r257177)
+++ head/sys/powerpc/powerpc/bus_machdep.c	Sat Oct 26 18:18:14 2013	(r257178)
@@ -58,6 +58,7 @@ __FBSDID("$FreeBSD$");
 #define	MAX_EARLYBOOT_MAPPINGS	6
 
 static struct {
+	vm_offset_t virt;
 	bus_addr_t addr;
 	bus_size_t size;
 	int flags;
@@ -86,10 +87,12 @@ bs_gen_map(bus_addr_t addr, bus_size_t s
 		KASSERT(earlyboot_map_idx < MAX_EARLYBOOT_MAPPINGS,
 		    ("%s: too many early boot mapping requests", __func__));
 		earlyboot_mappings[earlyboot_map_idx].addr = addr;
+		earlyboot_mappings[earlyboot_map_idx].virt =
+		    pmap_early_io_map(addr, size);
 		earlyboot_mappings[earlyboot_map_idx].size = size;
 		earlyboot_mappings[earlyboot_map_idx].flags = flags;
+		*bshp = earlyboot_mappings[earlyboot_map_idx].virt;
 		earlyboot_map_idx++;
-		*bshp = addr;
 	} else {
 		ma = VM_MEMATTR_DEFAULT;
 		switch (flags) {
@@ -110,13 +113,13 @@ void
 bs_remap_earlyboot(void)
 {
 	int i;
-	vm_offset_t pa, spa;
+	vm_offset_t pa, spa, va;
 	vm_memattr_t ma;
 
 	for (i = 0; i < earlyboot_map_idx; i++) {
 		spa = earlyboot_mappings[i].addr;
-		if (pmap_dev_direct_mapped(spa, earlyboot_mappings[i].size)
-		    == 0)
+		if (spa == earlyboot_mappings[i].virt &&
+		   pmap_dev_direct_mapped(spa, earlyboot_mappings[i].size) == 0)
 			continue;
 
 		ma = VM_MEMATTR_DEFAULT;
@@ -130,8 +133,10 @@ bs_remap_earlyboot(void)
 		}
 
 		pa = trunc_page(spa);
+		va = trunc_page(earlyboot_mappings[i].virt);
 		while (pa < spa + earlyboot_mappings[i].size) {
-			pmap_kenter_attr(pa, pa, ma);
+			pmap_kenter_attr(va, pa, ma);
+			va += PAGE_SIZE;
 			pa += PAGE_SIZE;
 		}
 	}


More information about the svn-src-head mailing list