Changeset View
Changeset View
Standalone View
Standalone View
head/sys/powerpc/ofw/ofw_machdep.c
Show First 20 Lines • Show All 219 Lines • ▼ Show 20 Lines | parse_ofw_memory(phandle_t node, const char *prop, struct mem_region *output) | ||||
} | } | ||||
sz = j*sizeof(output[0]); | sz = j*sizeof(output[0]); | ||||
return (sz); | return (sz); | ||||
} | } | ||||
#ifdef FDT | #ifdef FDT | ||||
static int | static int | ||||
excise_fdt_reserved(struct mem_region *avail, int asz) | excise_reserved_regions(struct mem_region *avail, int asz, | ||||
struct mem_region *exclude, int esz) | |||||
{ | { | ||||
struct { | |||||
uint64_t address; | |||||
uint64_t size; | |||||
} fdtmap[32]; | |||||
ssize_t fdtmapsize; | |||||
phandle_t chosen; | |||||
int i, j, k; | int i, j, k; | ||||
chosen = OF_finddevice("/chosen"); | |||||
fdtmapsize = OF_getprop(chosen, "fdtmemreserv", fdtmap, sizeof(fdtmap)); | |||||
for (j = 0; j < fdtmapsize/sizeof(fdtmap[0]); j++) { | |||||
fdtmap[j].address = be64toh(fdtmap[j].address) & ~PAGE_MASK; | |||||
fdtmap[j].size = round_page(be64toh(fdtmap[j].size)); | |||||
} | |||||
KASSERT(j*sizeof(fdtmap[0]) < sizeof(fdtmap), | |||||
("Exceeded number of FDT reservations")); | |||||
/* Add a virtual entry for the FDT itself */ | |||||
if (fdt != NULL) { | |||||
fdtmap[j].address = (vm_offset_t)fdt & ~PAGE_MASK; | |||||
fdtmap[j].size = round_page(fdt_totalsize(fdt)); | |||||
fdtmapsize += sizeof(fdtmap[0]); | |||||
} | |||||
for (i = 0; i < asz; i++) { | for (i = 0; i < asz; i++) { | ||||
for (j = 0; j < fdtmapsize/sizeof(fdtmap[0]); j++) { | for (j = 0; j < esz; j++) { | ||||
/* | /* | ||||
* Case 1: Exclusion region encloses complete | * Case 1: Exclusion region encloses complete | ||||
* available entry. Drop it and move on. | * available entry. Drop it and move on. | ||||
*/ | */ | ||||
if (fdtmap[j].address <= avail[i].mr_start && | if (exclude[j].mr_start <= avail[i].mr_start && | ||||
fdtmap[j].address + fdtmap[j].size >= | exclude[j].mr_start + exclude[j].mr_size >= | ||||
avail[i].mr_start + avail[i].mr_size) { | avail[i].mr_start + avail[i].mr_size) { | ||||
for (k = i+1; k < asz; k++) | for (k = i+1; k < asz; k++) | ||||
avail[k-1] = avail[k]; | avail[k-1] = avail[k]; | ||||
asz--; | asz--; | ||||
i--; /* Repeat some entries */ | i--; /* Repeat some entries */ | ||||
continue; | continue; | ||||
} | } | ||||
/* | /* | ||||
* Case 2: Exclusion region starts in available entry. | * Case 2: Exclusion region starts in available entry. | ||||
* Trim it to where the entry begins and append | * Trim it to where the entry begins and append | ||||
* a new available entry with the region after | * a new available entry with the region after | ||||
* the excluded region, if any. | * the excluded region, if any. | ||||
*/ | */ | ||||
if (fdtmap[j].address >= avail[i].mr_start && | if (exclude[j].mr_start >= avail[i].mr_start && | ||||
fdtmap[j].address < avail[i].mr_start + | exclude[j].mr_start < avail[i].mr_start + | ||||
avail[i].mr_size) { | avail[i].mr_size) { | ||||
if (fdtmap[j].address + fdtmap[j].size < | if (exclude[j].mr_start + exclude[j].mr_size < | ||||
avail[i].mr_start + avail[i].mr_size) { | avail[i].mr_start + avail[i].mr_size) { | ||||
avail[asz].mr_start = | avail[asz].mr_start = | ||||
fdtmap[j].address + fdtmap[j].size; | exclude[j].mr_start + exclude[j].mr_size; | ||||
avail[asz].mr_size = avail[i].mr_start + | avail[asz].mr_size = avail[i].mr_start + | ||||
avail[i].mr_size - | avail[i].mr_size - | ||||
avail[asz].mr_start; | avail[asz].mr_start; | ||||
asz++; | asz++; | ||||
} | } | ||||
avail[i].mr_size = fdtmap[j].address - | avail[i].mr_size = exclude[j].mr_start - | ||||
avail[i].mr_start; | avail[i].mr_start; | ||||
} | } | ||||
/* | /* | ||||
* Case 3: Exclusion region ends in available entry. | * Case 3: Exclusion region ends in available entry. | ||||
* Move start point to where the exclusion zone ends. | * Move start point to where the exclusion zone ends. | ||||
* The case of a contained exclusion zone has already | * The case of a contained exclusion zone has already | ||||
* been caught in case 2. | * been caught in case 2. | ||||
*/ | */ | ||||
if (fdtmap[j].address + fdtmap[j].size >= | if (exclude[j].mr_start + exclude[j].mr_size >= | ||||
avail[i].mr_start && fdtmap[j].address + | avail[i].mr_start && exclude[j].mr_start + | ||||
fdtmap[j].size < avail[i].mr_start + | exclude[j].mr_size < avail[i].mr_start + | ||||
avail[i].mr_size) { | avail[i].mr_size) { | ||||
avail[i].mr_size += avail[i].mr_start; | avail[i].mr_size += avail[i].mr_start; | ||||
avail[i].mr_start = | avail[i].mr_start = | ||||
fdtmap[j].address + fdtmap[j].size; | exclude[j].mr_start + exclude[j].mr_size; | ||||
avail[i].mr_size -= avail[i].mr_start; | avail[i].mr_size -= avail[i].mr_start; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
return (asz); | return (asz); | ||||
} | } | ||||
static int | |||||
excise_initrd_region(struct mem_region *avail, int asz) | |||||
{ | |||||
phandle_t chosen; | |||||
uint64_t start, end; | |||||
ssize_t size; | |||||
struct mem_region initrdmap[1]; | |||||
chosen = OF_finddevice("/chosen"); | |||||
size = OF_getprop(chosen, "linux,initrd-start", &start, sizeof(start)); | |||||
if (size <= 0) | |||||
return (asz); | |||||
size = OF_getprop(chosen, "linux,initrd-end", &end, sizeof(end)); | |||||
if (size <= 0) | |||||
return (asz); | |||||
initrdmap[0].mr_start = start; | |||||
initrdmap[0].mr_size = end - start; | |||||
asz = excise_reserved_regions(avail, asz, initrdmap, 1); | |||||
return (asz); | |||||
} | |||||
static int | |||||
excise_fdt_reserved(struct mem_region *avail, int asz) | |||||
{ | |||||
struct mem_region fdtmap[32]; | |||||
ssize_t fdtmapsize; | |||||
phandle_t chosen; | |||||
int j, fdtentries; | |||||
chosen = OF_finddevice("/chosen"); | |||||
fdtmapsize = OF_getprop(chosen, "fdtmemreserv", fdtmap, sizeof(fdtmap)); | |||||
for (j = 0; j < fdtmapsize/sizeof(fdtmap[0]); j++) { | |||||
fdtmap[j].mr_start = be64toh(fdtmap[j].mr_start) & ~PAGE_MASK; | |||||
fdtmap[j].mr_size = round_page(be64toh(fdtmap[j].mr_size)); | |||||
} | |||||
KASSERT(j*sizeof(fdtmap[0]) < sizeof(fdtmap), | |||||
("Exceeded number of FDT reservations")); | |||||
/* Add a virtual entry for the FDT itself */ | |||||
if (fdt != NULL) { | |||||
fdtmap[j].mr_start = (vm_offset_t)fdt & ~PAGE_MASK; | |||||
fdtmap[j].mr_size = round_page(fdt_totalsize(fdt)); | |||||
fdtmapsize += sizeof(fdtmap[0]); | |||||
} | |||||
fdtentries = fdtmapsize/sizeof(fdtmap[0]); | |||||
asz = excise_reserved_regions(avail, asz, fdtmap, fdtentries); | |||||
return (asz); | |||||
} | |||||
#endif | #endif | ||||
/* | /* | ||||
* This is called during powerpc_init, before the system is really initialized. | * This is called during powerpc_init, before the system is really initialized. | ||||
* It shall provide the total and the available regions of RAM. | * It shall provide the total and the available regions of RAM. | ||||
* The available regions need not take the kernel into account. | * The available regions need not take the kernel into account. | ||||
*/ | */ | ||||
void | void | ||||
Show All 37 Lines | else | ||||
res = parse_ofw_memory(phandle, "reg", &availp[asz]); | res = parse_ofw_memory(phandle, "reg", &availp[asz]); | ||||
asz += res/sizeof(struct mem_region); | asz += res/sizeof(struct mem_region); | ||||
} | } | ||||
#ifdef FDT | #ifdef FDT | ||||
phandle = OF_finddevice("/chosen"); | phandle = OF_finddevice("/chosen"); | ||||
if (OF_hasprop(phandle, "fdtmemreserv")) | if (OF_hasprop(phandle, "fdtmemreserv")) | ||||
asz = excise_fdt_reserved(availp, asz); | asz = excise_fdt_reserved(availp, asz); | ||||
/* If the kernel is being loaded through kexec, initrd region is listed | |||||
* in /chosen but the region is not marked as reserved, so, we might exclude | |||||
* it here. | |||||
*/ | |||||
if (OF_hasprop(phandle, "linux,initrd-start")) | |||||
asz = excise_initrd_region(availp, asz); | |||||
#endif | #endif | ||||
*memsz = msz; | *memsz = msz; | ||||
*availsz = asz; | *availsz = asz; | ||||
} | } | ||||
void | void | ||||
OF_initial_setup(void *fdt_ptr, void *junk, int (*openfirm)(void *)) | OF_initial_setup(void *fdt_ptr, void *junk, int (*openfirm)(void *)) | ||||
▲ Show 20 Lines • Show All 303 Lines • Show Last 20 Lines |