Rearchitect platform memory map parsing to make it less
Open Firmware-centric: - Keep the static list of regions in platform.c instead of ofw_machdep.c - Move various merging and sorting operations to platform.c as well - Move apple_hacks code out of ofw_machdep.c and into platform_powermac.c, where it belongs - Move CHRP-specific dynamic-reconfiguration memory parsing into platform_chrp.c instead of pretending it is shared code
This commit is contained in:
parent
02ef3f33de
commit
c1cb22d755
@ -45,8 +45,8 @@ __FBSDID("$FreeBSD$");
|
||||
extern uint32_t *bootinfo;
|
||||
|
||||
static int bare_probe(platform_t);
|
||||
static void bare_mem_regions(platform_t, struct mem_region **phys, int *physsz,
|
||||
struct mem_region **avail, int *availsz);
|
||||
static void bare_mem_regions(platform_t, struct mem_region *phys, int *physsz,
|
||||
struct mem_region *avail, int *availsz);
|
||||
static u_long bare_timebase_freq(platform_t, struct cpuref *cpuref);
|
||||
|
||||
static void bare_reset(platform_t);
|
||||
@ -80,8 +80,8 @@ bare_probe(platform_t plat)
|
||||
}
|
||||
|
||||
void
|
||||
bare_mem_regions(platform_t plat, struct mem_region **phys, int *physsz,
|
||||
struct mem_region **avail, int *availsz)
|
||||
bare_mem_regions(platform_t plat, struct mem_region *phys, int *physsz,
|
||||
struct mem_region *avail, int *availsz)
|
||||
{
|
||||
|
||||
ofw_mem_regions(phys, physsz, avail, availsz);
|
||||
|
@ -45,7 +45,7 @@ boolean_t OF_bootstrap(void);
|
||||
|
||||
void OF_reboot(void);
|
||||
|
||||
void ofw_mem_regions(struct mem_region **, int *, struct mem_region **, int *);
|
||||
void ofw_mem_regions(struct mem_region *, int *, struct mem_region *, int *);
|
||||
void ofw_quiesce(void); /* Must be called before VM is up! */
|
||||
void ofw_save_trap_vec(char *);
|
||||
|
||||
|
@ -72,8 +72,8 @@ static int cpu, maxcpu;
|
||||
|
||||
static int mpc85xx_probe(platform_t);
|
||||
static int mpc85xx_attach(platform_t);
|
||||
static void mpc85xx_mem_regions(platform_t, struct mem_region **phys,
|
||||
int *physsz, struct mem_region **avail, int *availsz);
|
||||
static void mpc85xx_mem_regions(platform_t, struct mem_region *phys,
|
||||
int *physsz, struct mem_region *avail, int *availsz);
|
||||
static u_long mpc85xx_timebase_freq(platform_t, struct cpuref *cpuref);
|
||||
static int mpc85xx_smp_first_cpu(platform_t, struct cpuref *cpuref);
|
||||
static int mpc85xx_smp_next_cpu(platform_t, struct cpuref *cpuref);
|
||||
@ -201,8 +201,8 @@ mpc85xx_attach(platform_t plat)
|
||||
}
|
||||
|
||||
void
|
||||
mpc85xx_mem_regions(platform_t plat, struct mem_region **phys, int *physsz,
|
||||
struct mem_region **avail, int *availsz)
|
||||
mpc85xx_mem_regions(platform_t plat, struct mem_region *phys, int *physsz,
|
||||
struct mem_region *avail, int *availsz)
|
||||
{
|
||||
|
||||
ofw_mem_regions(phys, physsz, avail, availsz);
|
||||
|
@ -61,11 +61,6 @@ __FBSDID("$FreeBSD$");
|
||||
#include <machine/ofw_machdep.h>
|
||||
#include <machine/trap.h>
|
||||
|
||||
static struct mem_region OFmem[PHYS_AVAIL_SZ], OFavail[PHYS_AVAIL_SZ];
|
||||
static struct mem_region OFfree[PHYS_AVAIL_SZ];
|
||||
|
||||
static int apple_hacks;
|
||||
|
||||
#ifdef AIM
|
||||
extern register_t ofmsr[5];
|
||||
extern void *openfirmware_entry;
|
||||
@ -80,7 +75,7 @@ static int openfirmware(void *args);
|
||||
__inline void
|
||||
ofw_save_trap_vec(char *save_trap_vec)
|
||||
{
|
||||
if (apple_hacks)
|
||||
if (!ofw_real_mode)
|
||||
return;
|
||||
|
||||
bcopy((void *)EXC_RST, save_trap_vec, EXC_LAST - EXC_RST);
|
||||
@ -89,7 +84,7 @@ ofw_save_trap_vec(char *save_trap_vec)
|
||||
static __inline void
|
||||
ofw_restore_trap_vec(char *restore_trap_vec)
|
||||
{
|
||||
if (apple_hacks)
|
||||
if (!ofw_real_mode)
|
||||
return;
|
||||
|
||||
bcopy(restore_trap_vec, (void *)EXC_RST, EXC_LAST - EXC_RST);
|
||||
@ -104,7 +99,7 @@ register_t ofw_sprg0_save;
|
||||
static __inline void
|
||||
ofw_sprg_prepare(void)
|
||||
{
|
||||
if (!apple_hacks)
|
||||
if (ofw_real_mode)
|
||||
return;
|
||||
|
||||
/*
|
||||
@ -126,8 +121,10 @@ ofw_sprg_prepare(void)
|
||||
static __inline void
|
||||
ofw_sprg_restore(void)
|
||||
{
|
||||
if (!apple_hacks)
|
||||
#if 0
|
||||
if (ofw_real_mode)
|
||||
return;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Note that SPRG1-3 contents are irrelevant. They are scratch
|
||||
@ -140,50 +137,6 @@ ofw_sprg_restore(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* 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)
|
||||
{
|
||||
vm_offset_t end;
|
||||
end = ulmax(to->mr_start + to->mr_size, from->mr_start + from->mr_size);
|
||||
to->mr_start = ulmin(from->mr_start, to->mr_start);
|
||||
to->mr_size = end - to->mr_start;
|
||||
}
|
||||
|
||||
/*
|
||||
* Quick sort callout for comparing memory regions.
|
||||
*/
|
||||
static int mr_cmp(const void *a, const void *b);
|
||||
|
||||
static int
|
||||
mr_cmp(const void *a, const void *b)
|
||||
{
|
||||
const struct mem_region *regiona;
|
||||
const struct mem_region *regionb;
|
||||
|
||||
regiona = a;
|
||||
regionb = b;
|
||||
if (regiona->mr_start < regionb->mr_start)
|
||||
return (-1);
|
||||
else if (regiona->mr_start > regionb->mr_start)
|
||||
return (1);
|
||||
else
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
parse_ofw_memory(phandle_t node, const char *prop, struct mem_region *output)
|
||||
{
|
||||
@ -208,14 +161,6 @@ parse_ofw_memory(phandle_t node, const char *prop, struct mem_region *output)
|
||||
sizeof(size_cells)) < (ssize_t)sizeof(size_cells))
|
||||
size_cells = 1;
|
||||
|
||||
/*
|
||||
* On Apple hardware, address_cells is always 1 for "available",
|
||||
* even when it is explicitly set to 2. All memory above 4 GB
|
||||
* also needs to be added by hand to the available list.
|
||||
*/
|
||||
if (strcmp(prop, "available") == 0 && apple_hacks)
|
||||
address_cells = 1;
|
||||
|
||||
/*
|
||||
* Get memory.
|
||||
*/
|
||||
@ -267,103 +212,9 @@ parse_ofw_memory(phandle_t node, const char *prop, struct mem_region *output)
|
||||
}
|
||||
sz = j*sizeof(output[0]);
|
||||
|
||||
#ifdef __powerpc64__
|
||||
if (strcmp(prop, "available") == 0 && apple_hacks) {
|
||||
/* Add in regions above 4 GB to the available list */
|
||||
struct mem_region himem[16];
|
||||
int hisz;
|
||||
|
||||
hisz = parse_ofw_memory(node, "reg", himem);
|
||||
for (i = 0; i < hisz/sizeof(himem[0]); i++) {
|
||||
if (himem[i].mr_start > BUS_SPACE_MAXADDR_32BIT) {
|
||||
output[j].mr_start = himem[i].mr_start;
|
||||
output[j].mr_size = himem[i].mr_size;
|
||||
j++;
|
||||
}
|
||||
}
|
||||
sz = j*sizeof(output[0]);
|
||||
}
|
||||
#endif
|
||||
|
||||
return (sz);
|
||||
}
|
||||
|
||||
static int
|
||||
parse_drconf_memory(int *msz, int *asz, struct mem_region *ofmem,
|
||||
struct mem_region *ofavail)
|
||||
{
|
||||
phandle_t phandle;
|
||||
vm_offset_t base;
|
||||
int i, idx, len, lasz, lmsz, res;
|
||||
uint32_t lmb_size[2];
|
||||
unsigned long *dmem, flags;
|
||||
|
||||
lmsz = *msz;
|
||||
lasz = *asz;
|
||||
|
||||
phandle = OF_finddevice("/ibm,dynamic-reconfiguration-memory");
|
||||
if (phandle == -1)
|
||||
/* No drconf node, return. */
|
||||
return (0);
|
||||
|
||||
res = OF_getprop(phandle, "ibm,lmb-size", lmb_size, sizeof(lmb_size));
|
||||
if (res == -1)
|
||||
return (0);
|
||||
printf("Logical Memory Block size: %d MB\n", lmb_size[1] >> 20);
|
||||
|
||||
/* Parse the /ibm,dynamic-memory.
|
||||
The first position gives the # of entries. The next two words
|
||||
reflect the address of the memory block. The next four words are
|
||||
the DRC index, reserved, list index and flags.
|
||||
(see PAPR C.6.6.2 ibm,dynamic-reconfiguration-memory)
|
||||
|
||||
#el Addr DRC-idx res list-idx flags
|
||||
-------------------------------------------------
|
||||
| 4 | 8 | 4 | 4 | 4 | 4 |....
|
||||
-------------------------------------------------
|
||||
*/
|
||||
|
||||
len = OF_getproplen(phandle, "ibm,dynamic-memory");
|
||||
if (len > 0) {
|
||||
|
||||
/* We have to use a variable length array on the stack
|
||||
since we have very limited stack space.
|
||||
*/
|
||||
cell_t arr[len/sizeof(cell_t)];
|
||||
|
||||
res = OF_getprop(phandle, "ibm,dynamic-memory", &arr,
|
||||
sizeof(arr));
|
||||
if (res == -1)
|
||||
return (0);
|
||||
|
||||
/* Number of elements */
|
||||
idx = arr[0];
|
||||
|
||||
/* First address. */
|
||||
dmem = (void*)&arr[1];
|
||||
|
||||
for (i = 0; i < idx; i++) {
|
||||
base = *dmem;
|
||||
dmem += 2;
|
||||
flags = *dmem;
|
||||
/* Use region only if available and not reserved. */
|
||||
if ((flags & 0x8) && !(flags & 0x80)) {
|
||||
ofmem[lmsz].mr_start = base;
|
||||
ofmem[lmsz].mr_size = (vm_size_t)lmb_size[1];
|
||||
ofavail[lasz].mr_start = base;
|
||||
ofavail[lasz].mr_size = (vm_size_t)lmb_size[1];
|
||||
lmsz++;
|
||||
lasz++;
|
||||
}
|
||||
dmem++;
|
||||
}
|
||||
}
|
||||
|
||||
*msz = lmsz;
|
||||
*asz = lasz;
|
||||
|
||||
return (1);
|
||||
}
|
||||
/*
|
||||
* This is called during powerpc_init, before the system is really initialized.
|
||||
* It shall provide the total and the available regions of RAM.
|
||||
@ -372,14 +223,12 @@ parse_drconf_memory(int *msz, int *asz, struct mem_region *ofmem,
|
||||
* 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)
|
||||
ofw_mem_regions(struct mem_region *memp, int *memsz,
|
||||
struct mem_region *availp, int *availsz)
|
||||
{
|
||||
phandle_t phandle;
|
||||
vm_offset_t maxphysaddr;
|
||||
int asz, msz, fsz;
|
||||
int i, j, res;
|
||||
int still_merging;
|
||||
int asz, msz;
|
||||
int res;
|
||||
char name[31];
|
||||
|
||||
asz = msz = 0;
|
||||
@ -394,72 +243,18 @@ ofw_mem_regions(struct mem_region **memp, int *memsz,
|
||||
if (strncmp(name, "memory", sizeof(name)) != 0)
|
||||
continue;
|
||||
|
||||
res = parse_ofw_memory(phandle, "reg", &OFmem[msz]);
|
||||
res = parse_ofw_memory(phandle, "reg", &memp[msz]);
|
||||
msz += res/sizeof(struct mem_region);
|
||||
if (OF_getproplen(phandle, "available") >= 0)
|
||||
res = parse_ofw_memory(phandle, "available",
|
||||
&OFavail[asz]);
|
||||
&availp[asz]);
|
||||
else
|
||||
res = parse_ofw_memory(phandle, "reg", &OFavail[asz]);
|
||||
res = parse_ofw_memory(phandle, "reg", &availp[asz]);
|
||||
asz += res/sizeof(struct mem_region);
|
||||
}
|
||||
|
||||
/* Check for memory in ibm,dynamic-reconfiguration-memory */
|
||||
parse_drconf_memory(&msz, &asz, OFmem, OFavail);
|
||||
|
||||
qsort(OFmem, msz, sizeof(*OFmem), mr_cmp);
|
||||
qsort(OFavail, asz, sizeof(*OFavail), mr_cmp);
|
||||
|
||||
*memp = OFmem;
|
||||
*memsz = msz;
|
||||
|
||||
/*
|
||||
* On some firmwares (SLOF), some memory may be marked available that
|
||||
* doesn't actually exist. This manifests as an extension of the last
|
||||
* available segment past the end of physical memory, so truncate that
|
||||
* one.
|
||||
*/
|
||||
maxphysaddr = 0;
|
||||
for (i = 0; i < msz; i++)
|
||||
if (OFmem[i].mr_start + OFmem[i].mr_size > maxphysaddr)
|
||||
maxphysaddr = OFmem[i].mr_start + OFmem[i].mr_size;
|
||||
|
||||
if (OFavail[asz - 1].mr_start + OFavail[asz - 1].mr_size > maxphysaddr)
|
||||
OFavail[asz - 1].mr_size = maxphysaddr -
|
||||
OFavail[asz - 1].mr_start;
|
||||
|
||||
/*
|
||||
* OFavail may have overlapping regions - collapse these
|
||||
* and copy out remaining regions to OFfree
|
||||
*/
|
||||
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;
|
||||
*availsz = asz;
|
||||
}
|
||||
|
||||
#ifdef AIM
|
||||
@ -509,9 +304,6 @@ OF_bootstrap()
|
||||
OF_init(fdt);
|
||||
}
|
||||
|
||||
/* Apple firmware has some bugs. Check for a "mac-io" alias. */
|
||||
apple_hacks = (OF_finddevice("mac-io") != -1) ? 1 : 0;
|
||||
|
||||
return (status);
|
||||
}
|
||||
|
||||
|
@ -57,8 +57,8 @@ extern void *ap_pcpu;
|
||||
|
||||
static int powermac_probe(platform_t);
|
||||
static int powermac_attach(platform_t);
|
||||
void powermac_mem_regions(platform_t, struct mem_region **phys, int *physsz,
|
||||
struct mem_region **avail, int *availsz);
|
||||
void powermac_mem_regions(platform_t, struct mem_region *phys, int *physsz,
|
||||
struct mem_region *avail, int *availsz);
|
||||
static u_long powermac_timebase_freq(platform_t, struct cpuref *cpuref);
|
||||
static int powermac_smp_first_cpu(platform_t, struct cpuref *cpuref);
|
||||
static int powermac_smp_next_cpu(platform_t, struct cpuref *cpuref);
|
||||
@ -114,10 +114,60 @@ powermac_probe(platform_t plat)
|
||||
}
|
||||
|
||||
void
|
||||
powermac_mem_regions(platform_t plat, struct mem_region **phys, int *physsz,
|
||||
struct mem_region **avail, int *availsz)
|
||||
powermac_mem_regions(platform_t plat, struct mem_region *phys, int *physsz,
|
||||
struct mem_region *avail, int *availsz)
|
||||
{
|
||||
ofw_mem_regions(phys,physsz,avail,availsz);
|
||||
phandle_t memory;
|
||||
cell_t memoryprop[PHYS_AVAIL_SZ * 2];
|
||||
ssize_t propsize, i, j;
|
||||
int physacells = 1;
|
||||
|
||||
memory = OF_finddevice("/memory");
|
||||
|
||||
/* "reg" has variable #address-cells, but #size-cells is always 1 */
|
||||
OF_getprop(OF_parent(memory), "#address-cells", &physacells,
|
||||
sizeof(physacells));
|
||||
|
||||
propsize = OF_getprop(memory, "reg", memoryprop, sizeof(memoryprop));
|
||||
propsize /= sizeof(cell_t);
|
||||
for (i = 0, j = 0; i < propsize; i += physacells+1, j++) {
|
||||
phys[j].mr_start = memoryprop[i];
|
||||
if (physacells == 2) {
|
||||
#ifndef __powerpc64__
|
||||
/* On 32-bit PPC, ignore regions starting above 4 GB */
|
||||
if (memoryprop[i] != 0) {
|
||||
j--;
|
||||
continue;
|
||||
}
|
||||
#else
|
||||
phys[j].mr_start <<= 32;
|
||||
#endif
|
||||
phys[j].mr_start |= memoryprop[i+1];
|
||||
}
|
||||
phys[j].mr_size = memoryprop[i + physacells];
|
||||
}
|
||||
*physsz = j;
|
||||
|
||||
/* "available" always has #address-cells = 1 */
|
||||
propsize = OF_getprop(memory, "available", memoryprop,
|
||||
sizeof(memoryprop));
|
||||
propsize /= sizeof(cell_t);
|
||||
for (i = 0, j = 0; i < propsize; i += 2, j++) {
|
||||
avail[j].mr_start = memoryprop[i];
|
||||
avail[j].mr_size = memoryprop[i + 1];
|
||||
}
|
||||
|
||||
#ifdef __powerpc64__
|
||||
/* Add in regions above 4 GB to the available list */
|
||||
for (i = 0; i < *physsz; i++) {
|
||||
if (phys[i].mr_start > BUS_SPACE_MAXADDR_32BIT) {
|
||||
avail[j].mr_start = phys[i].mr_start;
|
||||
avail[j].mr_size = phys[i].mr_size;
|
||||
j++;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
*availsz = j;
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -64,17 +64,93 @@ static char plat_name[64] = "";
|
||||
SYSCTL_STRING(_hw, OID_AUTO, platform, CTLFLAG_RD | CTLFLAG_TUN,
|
||||
plat_name, 0, "Platform currently in use");
|
||||
|
||||
static struct mem_region *pregions = NULL;
|
||||
static struct mem_region *aregions = NULL;
|
||||
static struct mem_region pregions[PHYS_AVAIL_SZ];
|
||||
static struct mem_region aregions[PHYS_AVAIL_SZ];
|
||||
static int npregions, naregions;
|
||||
|
||||
/*
|
||||
* 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)
|
||||
{
|
||||
vm_offset_t end;
|
||||
end = ulmax(to->mr_start + to->mr_size, from->mr_start + from->mr_size);
|
||||
to->mr_start = ulmin(from->mr_start, to->mr_start);
|
||||
to->mr_size = end - to->mr_start;
|
||||
}
|
||||
|
||||
/*
|
||||
* Quick sort callout for comparing memory regions.
|
||||
*/
|
||||
static int
|
||||
mr_cmp(const void *a, const void *b)
|
||||
{
|
||||
const struct mem_region *regiona, *regionb;
|
||||
|
||||
regiona = a;
|
||||
regionb = b;
|
||||
if (regiona->mr_start < regionb->mr_start)
|
||||
return (-1);
|
||||
else if (regiona->mr_start > regionb->mr_start)
|
||||
return (1);
|
||||
else
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
mem_regions(struct mem_region **phys, int *physsz, struct mem_region **avail,
|
||||
int *availsz)
|
||||
{
|
||||
if (pregions == NULL)
|
||||
PLATFORM_MEM_REGIONS(plat_obj, &pregions, &npregions,
|
||||
&aregions, &naregions);
|
||||
int i, j, still_merging;
|
||||
|
||||
if (npregions == 0) {
|
||||
PLATFORM_MEM_REGIONS(plat_obj, &pregions[0], &npregions,
|
||||
aregions, &naregions);
|
||||
qsort(pregions, npregions, sizeof(*pregions), mr_cmp);
|
||||
qsort(aregions, naregions, sizeof(*aregions), mr_cmp);
|
||||
|
||||
/* Remove overlapping available regions */
|
||||
do {
|
||||
still_merging = FALSE;
|
||||
for (i = 0; i < naregions; i++) {
|
||||
if (aregions[i].mr_size == 0)
|
||||
continue;
|
||||
for (j = i+1; j < naregions; j++) {
|
||||
if (aregions[j].mr_size == 0)
|
||||
continue;
|
||||
if (!memr_overlap(&aregions[j],
|
||||
&aregions[i]))
|
||||
continue;
|
||||
|
||||
memr_merge(&aregions[j], &aregions[i]);
|
||||
/* mark inactive */
|
||||
aregions[j].mr_size = 0;
|
||||
still_merging = TRUE;
|
||||
}
|
||||
}
|
||||
} while (still_merging == TRUE);
|
||||
|
||||
/* Collapse zero-length available regions */
|
||||
for (i = 0; i < naregions; i++) {
|
||||
if (aregions[i].mr_size == 0) {
|
||||
memcpy(&aregions[i], &aregions[i+1],
|
||||
(naregions - i - 1)*sizeof(*aregions));
|
||||
naregions--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*phys = pregions;
|
||||
*avail = aregions;
|
||||
@ -87,9 +163,11 @@ mem_valid(vm_offset_t addr, int len)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (pregions == NULL)
|
||||
PLATFORM_MEM_REGIONS(plat_obj, &pregions, &npregions,
|
||||
&aregions, &naregions);
|
||||
if (npregions == 0) {
|
||||
struct mem_region *p, *a;
|
||||
int na, np;
|
||||
mem_regions(&p, &np, &a, &na);
|
||||
}
|
||||
|
||||
for (i = 0; i < npregions; i++)
|
||||
if ((addr >= pregions[i].mr_start)
|
||||
|
@ -120,9 +120,9 @@ METHOD int attach {
|
||||
|
||||
METHOD void mem_regions {
|
||||
platform_t _plat;
|
||||
struct mem_region **_memp;
|
||||
struct mem_region *_memp;
|
||||
int *_memsz;
|
||||
struct mem_region **_availp;
|
||||
struct mem_region *_availp;
|
||||
int *_availsz;
|
||||
};
|
||||
|
||||
|
@ -58,8 +58,8 @@ extern void *ap_pcpu;
|
||||
|
||||
static int ps3_probe(platform_t);
|
||||
static int ps3_attach(platform_t);
|
||||
static void ps3_mem_regions(platform_t, struct mem_region **phys, int *physsz,
|
||||
struct mem_region **avail, int *availsz);
|
||||
static void ps3_mem_regions(platform_t, struct mem_region *phys, int *physsz,
|
||||
struct mem_region *avail, int *availsz);
|
||||
static vm_offset_t ps3_real_maxaddr(platform_t);
|
||||
static u_long ps3_timebase_freq(platform_t, struct cpuref *cpuref);
|
||||
#ifdef SMP
|
||||
@ -107,11 +107,30 @@ ps3_probe(platform_t plat)
|
||||
return (BUS_PROBE_NOWILDCARD);
|
||||
}
|
||||
|
||||
#define MEM_REGIONS 2
|
||||
static struct mem_region avail_regions[MEM_REGIONS];
|
||||
|
||||
static int
|
||||
ps3_attach(platform_t plat)
|
||||
{
|
||||
uint64_t junk;
|
||||
int count;
|
||||
struct mem_region avail_regions[2];
|
||||
|
||||
ps3_mem_regions(plat, NULL, NULL, avail_regions, &count);
|
||||
|
||||
lv1_allocate_memory(avail_regions[1].mr_size, 24 /* 16 MB pages */,
|
||||
0, 0x04 /* any address */, &avail_regions[1].mr_start, &junk);
|
||||
|
||||
pmap_mmu_install("mmu_ps3", BUS_PROBE_SPECIFIC);
|
||||
cpu_idle_hook = ps3_cpu_idle;
|
||||
|
||||
/* Set a breakpoint to make NULL an invalid address */
|
||||
lv1_set_dabr(0x7 /* read and write, MMU on */, 2 /* kernel accesses */);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
ps3_mem_regions(platform_t plat, struct mem_region *phys, int *physsz,
|
||||
struct mem_region *avail_regions, int *availsz)
|
||||
{
|
||||
uint64_t lpar_id, junk, ppe_id;
|
||||
|
||||
@ -133,26 +152,12 @@ ps3_attach(platform_t plat)
|
||||
/* Convert to maximum amount we can allocate in 16 MB pages */
|
||||
avail_regions[1].mr_size -= avail_regions[0].mr_size;
|
||||
avail_regions[1].mr_size -= avail_regions[1].mr_size % (16*1024*1024);
|
||||
*availsz = 2;
|
||||
|
||||
lv1_allocate_memory(avail_regions[1].mr_size, 24 /* 16 MB pages */,
|
||||
0, 0x04 /* any address */, &avail_regions[1].mr_start, &junk);
|
||||
|
||||
pmap_mmu_install("mmu_ps3", BUS_PROBE_SPECIFIC);
|
||||
cpu_idle_hook = ps3_cpu_idle;
|
||||
|
||||
/* Set a breakpoint to make NULL an invalid address */
|
||||
lv1_set_dabr(0x7 /* read and write, MMU on */, 2 /* kernel accesses */);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
ps3_mem_regions(platform_t plat, struct mem_region **phys, int *physsz,
|
||||
struct mem_region **avail, int *availsz)
|
||||
{
|
||||
|
||||
*phys = *avail = avail_regions;
|
||||
*physsz = *availsz = MEM_REGIONS;
|
||||
if (phys != NULL) {
|
||||
memcpy(phys, avail_regions, sizeof(*phys)*2);
|
||||
*physsz = 2;
|
||||
}
|
||||
}
|
||||
|
||||
static u_long
|
||||
@ -241,7 +246,12 @@ ps3_reset(platform_t plat)
|
||||
static vm_offset_t
|
||||
ps3_real_maxaddr(platform_t plat)
|
||||
{
|
||||
return (avail_regions[0].mr_start + avail_regions[0].mr_size);
|
||||
struct mem_region *phys, *avail;
|
||||
int nphys, navail;
|
||||
|
||||
mem_regions(&phys, &nphys, &avail, &navail);
|
||||
|
||||
return (phys[0].mr_start + phys[0].mr_size);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -65,8 +65,8 @@ static vm_offset_t realmaxaddr = VM_MAX_ADDRESS;
|
||||
|
||||
static int chrp_probe(platform_t);
|
||||
static int chrp_attach(platform_t);
|
||||
void chrp_mem_regions(platform_t, struct mem_region **phys, int *physsz,
|
||||
struct mem_region **avail, int *availsz);
|
||||
void chrp_mem_regions(platform_t, struct mem_region *phys, int *physsz,
|
||||
struct mem_region *avail, int *availsz);
|
||||
static vm_offset_t chrp_real_maxaddr(platform_t);
|
||||
static u_long chrp_timebase_freq(platform_t, struct cpuref *cpuref);
|
||||
static int chrp_smp_first_cpu(platform_t, struct cpuref *cpuref);
|
||||
@ -157,11 +157,107 @@ chrp_attach(platform_t plat)
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
chrp_mem_regions(platform_t plat, struct mem_region **phys, int *physsz,
|
||||
struct mem_region **avail, int *availsz)
|
||||
static int
|
||||
parse_drconf_memory(int *msz, int *asz, struct mem_region *ofmem,
|
||||
struct mem_region *ofavail)
|
||||
{
|
||||
ofw_mem_regions(phys,physsz,avail,availsz);
|
||||
phandle_t phandle;
|
||||
vm_offset_t base;
|
||||
int i, idx, len, lasz, lmsz, res;
|
||||
uint32_t lmb_size[2];
|
||||
unsigned long *dmem, flags;
|
||||
|
||||
lmsz = *msz;
|
||||
lasz = *asz;
|
||||
|
||||
phandle = OF_finddevice("/ibm,dynamic-reconfiguration-memory");
|
||||
if (phandle == -1)
|
||||
/* No drconf node, return. */
|
||||
return (0);
|
||||
|
||||
res = OF_getprop(phandle, "ibm,lmb-size", lmb_size, sizeof(lmb_size));
|
||||
if (res == -1)
|
||||
return (0);
|
||||
printf("Logical Memory Block size: %d MB\n", lmb_size[1] >> 20);
|
||||
|
||||
/* Parse the /ibm,dynamic-memory.
|
||||
The first position gives the # of entries. The next two words
|
||||
reflect the address of the memory block. The next four words are
|
||||
the DRC index, reserved, list index and flags.
|
||||
(see PAPR C.6.6.2 ibm,dynamic-reconfiguration-memory)
|
||||
|
||||
#el Addr DRC-idx res list-idx flags
|
||||
-------------------------------------------------
|
||||
| 4 | 8 | 4 | 4 | 4 | 4 |....
|
||||
-------------------------------------------------
|
||||
*/
|
||||
|
||||
len = OF_getproplen(phandle, "ibm,dynamic-memory");
|
||||
if (len > 0) {
|
||||
|
||||
/* We have to use a variable length array on the stack
|
||||
since we have very limited stack space.
|
||||
*/
|
||||
cell_t arr[len/sizeof(cell_t)];
|
||||
|
||||
res = OF_getprop(phandle, "ibm,dynamic-memory", &arr,
|
||||
sizeof(arr));
|
||||
if (res == -1)
|
||||
return (0);
|
||||
|
||||
/* Number of elements */
|
||||
idx = arr[0];
|
||||
|
||||
/* First address. */
|
||||
dmem = (void*)&arr[1];
|
||||
|
||||
for (i = 0; i < idx; i++) {
|
||||
base = *dmem;
|
||||
dmem += 2;
|
||||
flags = *dmem;
|
||||
/* Use region only if available and not reserved. */
|
||||
if ((flags & 0x8) && !(flags & 0x80)) {
|
||||
ofmem[lmsz].mr_start = base;
|
||||
ofmem[lmsz].mr_size = (vm_size_t)lmb_size[1];
|
||||
ofavail[lasz].mr_start = base;
|
||||
ofavail[lasz].mr_size = (vm_size_t)lmb_size[1];
|
||||
lmsz++;
|
||||
lasz++;
|
||||
}
|
||||
dmem++;
|
||||
}
|
||||
}
|
||||
|
||||
*msz = lmsz;
|
||||
*asz = lasz;
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
void
|
||||
chrp_mem_regions(platform_t plat, struct mem_region *phys, int *physsz,
|
||||
struct mem_region *avail, int *availsz)
|
||||
{
|
||||
vm_offset_t maxphysaddr;
|
||||
int i;
|
||||
|
||||
ofw_mem_regions(phys, physsz, avail, availsz);
|
||||
parse_drconf_memory(physsz, availsz, phys, avail);
|
||||
|
||||
/*
|
||||
* On some firmwares (SLOF), some memory may be marked available that
|
||||
* doesn't actually exist. This manifests as an extension of the last
|
||||
* available segment past the end of physical memory, so truncate that
|
||||
* one.
|
||||
*/
|
||||
maxphysaddr = 0;
|
||||
for (i = 0; i < *physsz; i++)
|
||||
if (phys[i].mr_start + phys[i].mr_size > maxphysaddr)
|
||||
maxphysaddr = phys[i].mr_start + phys[i].mr_size;
|
||||
|
||||
for (i = 0; i < *availsz; i++)
|
||||
if (avail[i].mr_start + avail[i].mr_size > maxphysaddr)
|
||||
avail[i].mr_size = maxphysaddr - avail[i].mr_start;
|
||||
}
|
||||
|
||||
static vm_offset_t
|
||||
|
@ -56,8 +56,8 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
static int wii_probe(platform_t);
|
||||
static int wii_attach(platform_t);
|
||||
static void wii_mem_regions(platform_t, struct mem_region **,
|
||||
int *, struct mem_region **, int *);
|
||||
static void wii_mem_regions(platform_t, struct mem_region *,
|
||||
int *, struct mem_region *, int *);
|
||||
static unsigned long wii_timebase_freq(platform_t, struct cpuref *);
|
||||
static void wii_reset(platform_t);
|
||||
static void wii_cpu_idle(sbintime_t);
|
||||
@ -107,12 +107,9 @@ wii_attach(platform_t plat)
|
||||
return (0);
|
||||
}
|
||||
|
||||
#define MEM_REGIONS 2
|
||||
static struct mem_region avail_regions[MEM_REGIONS];
|
||||
|
||||
static void
|
||||
wii_mem_regions(platform_t plat, struct mem_region **phys, int *physsz,
|
||||
struct mem_region **avail, int *availsz)
|
||||
wii_mem_regions(platform_t plat, struct mem_region *phys, int *physsz,
|
||||
struct mem_region *avail_regions, int *availsz)
|
||||
{
|
||||
/* 24MB 1T-SRAM */
|
||||
avail_regions[0].mr_start = 0x00000000;
|
||||
@ -139,8 +136,8 @@ wii_mem_regions(platform_t plat, struct mem_region **phys, int *physsz,
|
||||
*/
|
||||
avail_regions[1].mr_size -= WIIIPC_IOH_LEN + 1;
|
||||
|
||||
*phys = *avail = avail_regions;
|
||||
*physsz = *availsz = MEM_REGIONS;
|
||||
memcpy(phys, avail, 2*sizeof(*avail);
|
||||
*physsz = *availsz = 2;
|
||||
}
|
||||
|
||||
static u_long
|
||||
|
Loading…
Reference in New Issue
Block a user