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