From 012e342c0dad3de6f450d6b9bc67917489de2698 Mon Sep 17 00:00:00 2001 From: grehan Date: Wed, 10 Dec 2003 08:55:53 +0000 Subject: - 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. --- sys/powerpc/aim/ofw_machdep.c | 79 ++++++++++++++++++++++++++++++--------- sys/powerpc/include/powerpc.h | 2 - sys/powerpc/powerpc/ofw_machdep.c | 79 ++++++++++++++++++++++++++++++--------- 3 files changed, 122 insertions(+), 38 deletions(-) (limited to 'sys/powerpc') 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 */ -- cgit v1.1