summaryrefslogtreecommitdiffstats
path: root/sys/powerpc
diff options
context:
space:
mode:
authorgrehan <grehan@FreeBSD.org>2003-12-10 08:55:53 +0000
committergrehan <grehan@FreeBSD.org>2003-12-10 08:55:53 +0000
commit012e342c0dad3de6f450d6b9bc67917489de2698 (patch)
tree633a278533556d3c432bdf93efb3f9ea45c35057 /sys/powerpc
parent3d7c0818ff9a800a708a48bf7845055719e5d4de (diff)
downloadFreeBSD-src-012e342c0dad3de6f450d6b9bc67917489de2698.zip
FreeBSD-src-012e342c0dad3de6f450d6b9bc67917489de2698.tar.gz
- removed obsolete ppc_exit/ppc_boot functions
- OpenFirmware returns overlapping memory regions. Use a simple brute force algorithm to merge these into non-overlapping regions. This fixes bugs in reporting of available memory and also prevents pages from being added twice in the VM system.
Diffstat (limited to 'sys/powerpc')
-rw-r--r--sys/powerpc/aim/ofw_machdep.c79
-rw-r--r--sys/powerpc/include/powerpc.h2
-rw-r--r--sys/powerpc/powerpc/ofw_machdep.c79
3 files changed, 122 insertions, 38 deletions
diff --git a/sys/powerpc/aim/ofw_machdep.c b/sys/powerpc/aim/ofw_machdep.c
index 6216045..15b04a0 100644
--- a/sys/powerpc/aim/ofw_machdep.c
+++ b/sys/powerpc/aim/ofw_machdep.c
@@ -57,6 +57,7 @@ __FBSDID("$FreeBSD$");
#define OFMEM_REGIONS 32
static struct mem_region OFmem[OFMEM_REGIONS + 1], OFavail[OFMEM_REGIONS + 3];
+static struct mem_region OFfree[OFMEM_REGIONS + 3];
extern long ofmsr;
extern struct pmap ofw_pmap;
@@ -64,6 +65,29 @@ extern int pmap_bootstrapped;
static int (*ofwcall)(void *);
/*
+ * Memory region utilities: determine if two regions overlap,
+ * and merge two overlapping regions into one
+ */
+static int
+memr_overlap(struct mem_region *r1, struct mem_region *r2)
+{
+ if ((r1->mr_start + r1->mr_size) < r2->mr_start ||
+ (r2->mr_start + r2->mr_size) < r1->mr_start)
+ return (FALSE);
+
+ return (TRUE);
+}
+
+static void
+memr_merge(struct mem_region *from, struct mem_region *to)
+{
+ int end;
+ end = imax(to->mr_start + to->mr_size, from->mr_start + from->mr_size);
+ to->mr_start = imin(from->mr_start, to->mr_start);
+ 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.
@@ -75,7 +99,9 @@ mem_regions(struct mem_region **memp, int *memsz,
struct mem_region **availp, int *availsz)
{
int phandle;
- int asz, msz;
+ int asz, msz, fsz;
+ int i, j;
+ int still_merging;
/*
* Get memory.
@@ -90,8 +116,40 @@ mem_regions(struct mem_region **memp, int *memsz,
panic("no memory?");
*memp = OFmem;
*memsz = msz / sizeof(struct mem_region);
- *availp = OFavail;
- *availsz = asz / sizeof(struct mem_region);
+
+ /*
+ * OFavail may have overlapping regions - collapse these
+ * and copy out remaining regions to OFfree
+ */
+ asz /= sizeof(struct mem_region);
+ do {
+ still_merging = FALSE;
+ for (i = 0; i < asz; i++) {
+ if (OFavail[i].mr_size == 0)
+ continue;
+ for (j = i+1; j < asz; j++) {
+ if (OFavail[j].mr_size == 0)
+ continue;
+ if (memr_overlap(&OFavail[j], &OFavail[i])) {
+ memr_merge(&OFavail[j], &OFavail[i]);
+ /* mark inactive */
+ OFavail[j].mr_size = 0;
+ still_merging = TRUE;
+ }
+ }
+ }
+ } while (still_merging == TRUE);
+
+ /* evict inactive ranges */
+ for (i = 0, fsz = 0; i < asz; i++) {
+ if (OFavail[i].mr_size != 0) {
+ OFfree[fsz] = OFavail[i];
+ fsz++;
+ }
+ }
+
+ *availp = OFfree;
+ *availsz = fsz;
}
void
@@ -159,21 +217,6 @@ openfirmware(void *args)
}
void
-ppc_exit()
-{
-
- OF_exit();
-}
-
-void
-ppc_boot(str)
- char *str;
-{
-
- OF_boot(str);
-}
-
-void
OF_halt()
{
int retval; /* dummy, this may not be needed */
diff --git a/sys/powerpc/include/powerpc.h b/sys/powerpc/include/powerpc.h
index 1f7992c..a2fa346 100644
--- a/sys/powerpc/include/powerpc.h
+++ b/sys/powerpc/include/powerpc.h
@@ -47,10 +47,8 @@ void mem_regions(struct mem_region **, int *, struct mem_region **, int *);
*
* Not sure whether boot itself should be implementation dependent instead. XXX
*/
-void ppc_exit(void);
void OF_halt(void);
void OF_reboot(void);
-void ppc_boot(char *bootspec);
int dk_match(char *name);
diff --git a/sys/powerpc/powerpc/ofw_machdep.c b/sys/powerpc/powerpc/ofw_machdep.c
index 6216045..15b04a0 100644
--- a/sys/powerpc/powerpc/ofw_machdep.c
+++ b/sys/powerpc/powerpc/ofw_machdep.c
@@ -57,6 +57,7 @@ __FBSDID("$FreeBSD$");
#define OFMEM_REGIONS 32
static struct mem_region OFmem[OFMEM_REGIONS + 1], OFavail[OFMEM_REGIONS + 3];
+static struct mem_region OFfree[OFMEM_REGIONS + 3];
extern long ofmsr;
extern struct pmap ofw_pmap;
@@ -64,6 +65,29 @@ extern int pmap_bootstrapped;
static int (*ofwcall)(void *);
/*
+ * Memory region utilities: determine if two regions overlap,
+ * and merge two overlapping regions into one
+ */
+static int
+memr_overlap(struct mem_region *r1, struct mem_region *r2)
+{
+ if ((r1->mr_start + r1->mr_size) < r2->mr_start ||
+ (r2->mr_start + r2->mr_size) < r1->mr_start)
+ return (FALSE);
+
+ return (TRUE);
+}
+
+static void
+memr_merge(struct mem_region *from, struct mem_region *to)
+{
+ int end;
+ end = imax(to->mr_start + to->mr_size, from->mr_start + from->mr_size);
+ to->mr_start = imin(from->mr_start, to->mr_start);
+ 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.
@@ -75,7 +99,9 @@ mem_regions(struct mem_region **memp, int *memsz,
struct mem_region **availp, int *availsz)
{
int phandle;
- int asz, msz;
+ int asz, msz, fsz;
+ int i, j;
+ int still_merging;
/*
* Get memory.
@@ -90,8 +116,40 @@ mem_regions(struct mem_region **memp, int *memsz,
panic("no memory?");
*memp = OFmem;
*memsz = msz / sizeof(struct mem_region);
- *availp = OFavail;
- *availsz = asz / sizeof(struct mem_region);
+
+ /*
+ * OFavail may have overlapping regions - collapse these
+ * and copy out remaining regions to OFfree
+ */
+ asz /= sizeof(struct mem_region);
+ do {
+ still_merging = FALSE;
+ for (i = 0; i < asz; i++) {
+ if (OFavail[i].mr_size == 0)
+ continue;
+ for (j = i+1; j < asz; j++) {
+ if (OFavail[j].mr_size == 0)
+ continue;
+ if (memr_overlap(&OFavail[j], &OFavail[i])) {
+ memr_merge(&OFavail[j], &OFavail[i]);
+ /* mark inactive */
+ OFavail[j].mr_size = 0;
+ still_merging = TRUE;
+ }
+ }
+ }
+ } while (still_merging == TRUE);
+
+ /* evict inactive ranges */
+ for (i = 0, fsz = 0; i < asz; i++) {
+ if (OFavail[i].mr_size != 0) {
+ OFfree[fsz] = OFavail[i];
+ fsz++;
+ }
+ }
+
+ *availp = OFfree;
+ *availsz = fsz;
}
void
@@ -159,21 +217,6 @@ openfirmware(void *args)
}
void
-ppc_exit()
-{
-
- OF_exit();
-}
-
-void
-ppc_boot(str)
- char *str;
-{
-
- OF_boot(str);
-}
-
-void
OF_halt()
{
int retval; /* dummy, this may not be needed */
OpenPOWER on IntegriCloud