svn commit: r195952 - in projects/ppc64/sys/powerpc: aim aim64

Nathan Whitehorn nwhitehorn at FreeBSD.org
Wed Jul 29 21:36:40 UTC 2009


Author: nwhitehorn
Date: Wed Jul 29 21:36:40 2009
New Revision: 195952
URL: http://svn.freebsd.org/changeset/base/195952

Log:
  Fix physical memory map detection on IBM-style machines like the
  Cell simulator.

Modified:
  projects/ppc64/sys/powerpc/aim/ofw_machdep.c
  projects/ppc64/sys/powerpc/aim64/mmu_oea64.c

Modified: projects/ppc64/sys/powerpc/aim/ofw_machdep.c
==============================================================================
--- projects/ppc64/sys/powerpc/aim/ofw_machdep.c	Wed Jul 29 21:09:03 2009	(r195951)
+++ projects/ppc64/sys/powerpc/aim/ofw_machdep.c	Wed Jul 29 21:36:40 2009	(r195952)
@@ -62,12 +62,6 @@ __FBSDID("$FreeBSD$");
 static struct mem_region OFmem[OFMEM_REGIONS + 1], OFavail[OFMEM_REGIONS + 3];
 static struct mem_region OFfree[OFMEM_REGIONS + 3];
 
-struct mem_region64 {
-        vm_offset_t     mr_start_hi;
-        vm_offset_t     mr_start_lo;
-        vm_size_t       mr_size;
-};	
-
 extern register_t ofmsr[5];
 extern struct	pmap ofw_pmap;
 static int	(*ofwcall)(void *);
@@ -146,24 +140,13 @@ memr_merge(struct mem_region *from, stru
 	to->mr_size = end - to->mr_start;
 }
 
-/*
- * This is called during powerpc_init, before the system is really initialized.
- * It shall provide the total and the available regions of RAM.
- * Both lists must have a zero-size entry as terminator.
- * The available regions need not take the kernel into account, but needs
- * to provide space for two additional entry beyond the terminating one.
- */
-void
-ofw_mem_regions(struct mem_region **memp, int *memsz,
-		struct mem_region **availp, int *availsz)
+static int
+parse_ofw_memory(phandle_t node, const char *prop, struct mem_region *output)
 {
+	cell_t address_cells, size_cells;
+	int sz, i, j;
 	phandle_t phandle;
-	int asz, msz, fsz;
-	int i, j;
-	int still_merging;
-	cell_t address_cells;
-
-	asz = msz = 0;
+	sz = 0;
 
 	/*
 	 * Get #address-cells from root node, defaulting to 1 if it cannot
@@ -173,71 +156,97 @@ ofw_mem_regions(struct mem_region **memp
 	if (OF_getprop(phandle, "#address-cells", &address_cells, 
 	    sizeof(address_cells)) < sizeof(address_cells))
 		address_cells = 1;
+	if (OF_getprop(phandle, "#size-cells", &size_cells, 
+	    sizeof(size_cells)) < sizeof(size_cells))
+		size_cells = 1;
 	
 	/*
 	 * Get memory.
 	 */
-	if ((phandle = OF_finddevice("/memory")) == -1
-	    || (asz = OF_getprop(phandle, "available",
-		  OFavail, sizeof OFavail[0] * OFMEM_REGIONS)) <= 0)
-	{
-		if (ofw_real_mode) {
-			/* XXX MAMBO */
-			printf("Physical memory unknown -- guessing 128 MB\n");
-
-			/* Leave the first 0xA000000 bytes for the kernel */
-			OFavail[0].mr_start = 0xA00000;
-			OFavail[0].mr_size = 0x75FFFFF;
-			asz = sizeof(OFavail[0]);
-		} else {
-			panic("no memory?");
-		}
-	}
-
-	if (address_cells == 2) {
-	    struct mem_region64 OFmem64[OFMEM_REGIONS + 1];
-	    if ((phandle == -1) || (msz = OF_getprop(phandle, "reg",
-			  OFmem64, sizeof OFmem64[0] * OFMEM_REGIONS)) <= 0) {
-		if (ofw_real_mode) {
-			/* XXX MAMBO */
-			OFmem64[0].mr_start_hi = 0;
-			OFmem64[0].mr_start_lo = 0x0;
-			OFmem64[0].mr_size = 0x7FFFFFF;
-			msz = sizeof(OFmem64[0]);
-		} else {
+	if (address_cells > 1 || size_cells > 1) {
+	    cell_t OFmem[4*(OFMEM_REGIONS + 1)];
+	    if ((node == -1) || (sz = OF_getprop(node, prop,
+		OFmem, sizeof(OFmem[0]) * 4 * OFMEM_REGIONS)) <= 0)
 			panic("Physical memory map not found");
+
+	    i = 0;
+	    j = 0;
+	    while (i < sz/sizeof(cell_t)) {
+	      #ifndef __powerpc64__
+		/* On 32-bit PPC, ignore regions starting above 4 GB */
+		if (OFmem[i] > 0) {
+			i += address_cells + size_cells;
+			continue;
+		}
+	      #endif
+
+		output[j].mr_start = OFmem[i++];
+		if (address_cells == 2) {
+			output[j].mr_start <<= 32;
+			output[j].mr_start += OFmem[i++];
+		}
+			
+		output[j].mr_size = OFmem[i++];
+		if (size_cells == 2) {
+			output[j].mr_size <<= 32;
+			output[j].mr_size += OFmem[i++];
 		}
-	    }
 
-	    for (i = 0, j = 0; i < msz/sizeof(OFmem64[0]); i++) {
-		if (OFmem64[i].mr_start_hi == 0) {
-			OFmem[i].mr_start = OFmem64[i].mr_start_lo;
-			OFmem[i].mr_size = OFmem64[i].mr_size;
-
-			/*
-			 * Check for memory regions extending above 32-bit
-			 * memory space, and restrict them to stay there.
-			 */
-			if (((uint64_t)OFmem[i].mr_start +
-			    (uint64_t)OFmem[i].mr_size) >
-			    BUS_SPACE_MAXADDR_32BIT) {
-				OFmem[i].mr_size = BUS_SPACE_MAXADDR_32BIT -
-				    OFmem[i].mr_start;
-			}
-			j++;
+	      #ifndef __powerpc64__
+		/*
+		 * Check for memory regions extending above 32-bit
+		 * memory space, and restrict them to stay there.
+		 */
+		if (((uint64_t)output[j].mr_start +
+		    (uint64_t)output[j].mr_size) >
+		    BUS_SPACE_MAXADDR_32BIT) {
+			ouptut[j].mr_size = BUS_SPACE_MAXADDR_32BIT -
+			    output[j].mr_start;
 		}
+	      #endif
+		j++;
 	    }
-	    msz = j*sizeof(OFmem[0]);
+	    sz = j*sizeof(output[0]);
 	} else {
-	    if ((msz = OF_getprop(phandle, "reg",
-			  OFmem, sizeof OFmem[0] * OFMEM_REGIONS)) <= 0)
+	    if ((sz = OF_getprop(node, prop,
+			  output, sizeof(output[0]) * OFMEM_REGIONS)) <= 0)
 		panic("Physical memory map not found");
 	}
 
+	return (sz);
+}
+
+/*
+ * This is called during powerpc_init, before the system is really initialized.
+ * It shall provide the total and the available regions of RAM.
+ * Both lists must have a zero-size entry as terminator.
+ * The available regions need not take the kernel into account, but needs
+ * to provide space for two additional entry beyond the terminating one.
+ */
+void
+ofw_mem_regions(struct mem_region **memp, int *memsz,
+		struct mem_region **availp, int *availsz)
+{
+	phandle_t phandle;
+	int asz, msz, fsz;
+	int i, j;
+	int still_merging;
+
+	asz = msz = 0;
+
+	/*
+	 * Get memory.
+	 */
+	phandle = OF_finddevice("/memory");
+	if (phandle == -1)
+		phandle = OF_finddevice("/memory at 0");
+
+	msz = parse_ofw_memory(phandle, "reg", OFmem);
+	asz = parse_ofw_memory(phandle, "available", OFavail);
+
 	*memp = OFmem;
 	*memsz = msz / sizeof(struct mem_region);
 	
-
 	/*
 	 * OFavail may have overlapping regions - collapse these
 	 * and copy out remaining regions to OFfree

Modified: projects/ppc64/sys/powerpc/aim64/mmu_oea64.c
==============================================================================
--- projects/ppc64/sys/powerpc/aim64/mmu_oea64.c	Wed Jul 29 21:09:03 2009	(r195951)
+++ projects/ppc64/sys/powerpc/aim64/mmu_oea64.c	Wed Jul 29 21:36:40 2009	(r195952)
@@ -820,6 +820,38 @@ moea64_bridge_bootstrap(mmu_t mmup, vm_o
 		phys_avail_count++;
 		physsz += regions[i].mr_size;
 	}
+
+	/* Check for overlap with the kernel and exception vectors */
+	for (j = 0; j < 2*phys_avail_count; j+=2) {
+		if (phys_avail[j] < EXC_LAST)
+			phys_avail[j] += EXC_LAST;
+
+		if (kernelstart >= phys_avail[j] &&
+		    kernelstart < phys_avail[j+1]) {
+			if (kernelend < phys_avail[j+1]) {
+				phys_avail[2*phys_avail_count] =
+				    (kernelend & ~PAGE_MASK) + PAGE_SIZE;
+				phys_avail[2*phys_avail_count + 1] =
+				    phys_avail[j+1];
+				phys_avail_count++;
+			}
+
+			phys_avail[j+1] = kernelstart & ~PAGE_MASK;
+		}
+
+		if (kernelend >= phys_avail[j] &&
+		    kernelend < phys_avail[j+1]) {
+			if (kernelstart > phys_avail[j]) {
+				phys_avail[2*phys_avail_count] = phys_avail[j];
+				phys_avail[2*phys_avail_count + 1] =
+				    kernelstart & ~PAGE_MASK;
+				phys_avail_count++;
+			}
+
+			phys_avail[j] = (kernelend & ~PAGE_MASK) + PAGE_SIZE;
+		}
+	}
+
 	physmem = btoc(physsz);
 
 	/*


More information about the svn-src-projects mailing list