Message ID | 1430990797.81316.574009132670.1.gpush@pablo |
---|---|
State | Superseded |
Headers | show |
Jeremy Kerr <jk@ozlabs.org> writes: > Linux supports a newer memory reservation layout in the device-tree, > where each reservation is represented by a subnode under a top-level > "reserved-memory" node. > > This change adds these nodes, using the mem_region names as the property > names (minus any cell addresses). The reserved-memory node looks like > this: > > / { > name = "reserved-memory"; > ranges; > #address-cells = <0x2>; > #size-cells = <0x2>; > > ibm,firmware-code@30000000 { > reg = <0x0 0x30000000 0x0 0x200000>; > }; With this patch I get this with my mambo tests (have zImage.epapr in ~/skiboot and run make check). It seems as though we're getting some logs about the reserved memory? 14871833: (14871833): [14868998,5] INIT: Loading kernel 14875859: (14875859): [14872142,5] Assuming kernel at 0x20000000 14881057: (14881057): [14876086,5] INIT: Kernel loaded, size: 0 bytes (0 = unkno wn preload) 14885549: (14885549): [14881346,5] INIT: 32-bit kernel entry at 0x2001015c 14903544: (14903544): [14886769,3] OCC: No HOMER detected, assuming no pstates 14907601: (14907601): [14903797,3] ELOG: Error getting buffer to log error 19603894: (19603894): [19597505,5] INIT: Starting kernel at 0x2001015c, fdt at 0 x30203a78 (size 0x13c8) 382722408: (382722405): [382718055,3] OPAL: Trying a CPU re-init with flags: 0x1 382731228: (382731225): [382723646,3] SLW: Not found on chip 0 382735345: (382735342): [382731481,3] ELOG: Error getting buffer to log error 387826830: (387826825): [ 0.000000] OPAL V3 detected ! 387871856: (387871851): [ 0.000000] Reserved memory: failed to reserve memory for node 'ibm,firmware-stacks@31a00000': base 0x0000000031a00000, size 0 MiB 388038641: (388038636): [ 0.000000] Reserved memory: failed to reserve memory for node 'ibm,firmware-data@30e00000': base 0x0000000030e00000, size 12 MiB 388204211: (388204206): [ 0.000000] Reserved memory: failed to reserve memory for node 'ibm,firmware-heap@30200000': base 0x0000000030200000, size 12 MiB 388369776: (388369771): [ 0.000000] Reserved memory: failed to reserve memory for node 'ibm,firmware-code@30000000': base 0x0000000030000000, size 2 MiB 388534158: (388534153): [ 0.000000] Reserved memory: failed to reserve memory for node 'ibm,firmware-allocs-memory@39a00000': base 0x0000000039a00000, size 1 MiB Are ^ the result of trying to reserve it twice? 388711270: (388711265): [ 0.000000] Using PowerNV machine description 388778417: (388778412): [ 0.000000] bootconsole [udbg0] enabled 388839611: (388839606): [ 0.000000] CPU maps initialized for 1 thread per cor e 388924402: (388924397): -> smp_release_cpus() 388954297: (388954292): spinning_secondaries = 0 388986268: (388986263): <- smp_release_cpus() 389019235: (389019230): [ 0.000000] Starting Linux PPC64 #2 SMP Fri Jan 23 15 :52:55 AEDT 2015 389113000: (389112995): [ 0.000000] ----------------------------------------- ------------ 389202007: (389202002): [ 0.000000] ppc64_pft_size = 0x0 389269246: (389269241): [ 0.000000] physicalMemorySize = 0x4000000 0 389345236: (389345231): [ 0.000000] htab_address = 0xc000000 03f000000 389430689: (389430684): [ 0.000000] htab_hash_mask = 0x1ffff 389502540: (389502535): [ 0.000000] ----------------------------------------- ------------ 389588423: (389588418): <- setup_system() 389617776: (389617771): [ 0.000000] Linux version 3.17.2 (stewart@ka1) (gcc v ersion 4.8.3 (Buildroot 2014.08-git-g1455c21) ) #2 SMP Fri Jan 23 15:52:55 AEDT 2015
Hi Stewart, > 387871856: (387871851): [ 0.000000] Reserved memory: failed to reserve memory > for node 'ibm,firmware-stacks@31a00000': base 0x0000000031a00000, size 0 MiB > 388038641: (388038636): [ 0.000000] Reserved memory: failed to reserve memory > for node 'ibm,firmware-data@30e00000': base 0x0000000030e00000, size 12 MiB > 388204211: (388204206): [ 0.000000] Reserved memory: failed to reserve memory > for node 'ibm,firmware-heap@30200000': base 0x0000000030200000, size 12 MiB > 388369776: (388369771): [ 0.000000] Reserved memory: failed to reserve memory > for node 'ibm,firmware-code@30000000': base 0x0000000030000000, size 2 MiB > 388534158: (388534153): [ 0.000000] Reserved memory: failed to reserve memory > for node 'ibm,firmware-allocs-memory@39a00000': base 0x0000000039a00000, size 1 > MiB > > Are ^ the result of trying to reserve it twice? Yes - the change I've posted adds the node-style reservations alongside the property-style reservations. Since current kernels support both, we'll get those messages reported. Ben - if we've supported the node-style reservations in Linux for long enough, perhaps we should remove the property-style ones in OPAL? Regards, Jeremy
Jeremy Kerr <jk@ozlabs.org> writes: > Hi Stewart, > >> 387871856: (387871851): [ 0.000000] Reserved memory: failed to reserve memory >> for node 'ibm,firmware-stacks@31a00000': base 0x0000000031a00000, size 0 MiB >> 388038641: (388038636): [ 0.000000] Reserved memory: failed to reserve memory >> for node 'ibm,firmware-data@30e00000': base 0x0000000030e00000, size 12 MiB >> 388204211: (388204206): [ 0.000000] Reserved memory: failed to reserve memory >> for node 'ibm,firmware-heap@30200000': base 0x0000000030200000, size 12 MiB >> 388369776: (388369771): [ 0.000000] Reserved memory: failed to reserve memory >> for node 'ibm,firmware-code@30000000': base 0x0000000030000000, size 2 MiB >> 388534158: (388534153): [ 0.000000] Reserved memory: failed to reserve memory >> for node 'ibm,firmware-allocs-memory@39a00000': base 0x0000000039a00000, size 1 >> MiB >> >> Are ^ the result of trying to reserve it twice? > > Yes - the change I've posted adds the node-style reservations alongside > the property-style reservations. Since current kernels support both, > we'll get those messages reported. > > Ben - if we've supported the node-style reservations in Linux for long > enough, perhaps we should remove the property-style ones in OPAL? We should probably go back and pick a "this is the earliest upstream" and other such variants (such as PowerKVM 2.1) and assemble that somewhere.
Hi all, > Yes - the change I've posted adds the node-style reservations alongside > the property-style reservations. Since current kernels support both, > we'll get those messages reported. In fact, these are conflicting with the even-older /memreserve/ entries in the fdt header! Perhaps we'd be best with a series of checks in Linux, where we detect (and use) the latest style of reservation (reserved-memory --> reserved-ranges --> /memreserve/), and ignore the rest. Regards, Jeremy
diff --git a/core/mem_region.c b/core/mem_region.c index 3cc8ae0..56601e0 100644 --- a/core/mem_region.c +++ b/core/mem_region.c @@ -918,11 +918,30 @@ void mem_region_release_unused(void) unlock(&mem_region_lock); } +static void mem_region_add_dt_reserved_node(struct dt_node *parent, + struct mem_region *region) +{ + struct dt_node *node; + char *name, *p; + + name = strdup(region->name); + + /* remove any cell addresses in the region name; we have our own cell + * addresses here */ + p = strchr(name, '@'); + if (p) + *p = '\0'; + + node = dt_new_addr(parent, name, region->start); + dt_add_property_u64s(node, "reg", region->start, region->len); +} + void mem_region_add_dt_reserved(void) { int names_len, ranges_len, len; struct mem_region *region; void *names, *ranges; + struct dt_node *node; uint64_t *range; char *name; @@ -936,6 +955,12 @@ void mem_region_add_dt_reserved(void) mem_regions_finalised = true; unlock(&mem_region_lock); + /* establish top-level reservation node */ + node = dt_new(dt_root, "reserved-memory"); + dt_add_property_cells(node, "#address-cells", 2); + dt_add_property_cells(node, "#size-cells", 2); + dt_add_property(node, "ranges", NULL, 0); + /* First pass: calculate length of property data */ list_for_each(®ions, region, list) { if (!region_is_reserved(region)) @@ -961,6 +986,8 @@ void mem_region_add_dt_reserved(void) (long long)(region->start + region->len - 1), region->name); + mem_region_add_dt_reserved_node(node, region); + range[0] = cpu_to_fdt64(region->start); range[1] = cpu_to_fdt64(region->len); range += 2; diff --git a/core/test/run-mem_region_reservations.c b/core/test/run-mem_region_reservations.c index b33827f..8be3e67 100644 --- a/core/test/run-mem_region_reservations.c +++ b/core/test/run-mem_region_reservations.c @@ -108,13 +108,83 @@ static struct { { "test.3", 0x4000, false }, }; -int main(void) +static void check_property_reservations(void) { const struct dt_property *names, *ranges; - struct mem_region *r; - unsigned int i, l, c; - uint64_t *rangep; + unsigned int i, l; const char *name; + uint64_t *rangep; + + /* check dt properties */ + names = dt_find_property(dt_root, "reserved-names"); + ranges = dt_find_property(dt_root, "reserved-ranges"); + + assert(names && ranges); + + /* walk through names & ranges properies, ensuring that the test + * regions are all present */ + for (name = names->prop, rangep = (uint64_t *)ranges->prop; + name < names->prop + names->len; + name += l, rangep += 2) { + uint64_t addr; + + addr = dt_get_number(rangep, 2); + l = strlen(name) + 1; + + for (i = 0; i < ARRAY_SIZE(test_regions); i++) { + if (strcmp(test_regions[i].name, name)) + continue; + assert(test_regions[i].addr == addr); + assert(!test_regions[i].found); + test_regions[i].found = true; + } + } + + for (i = 0; i < ARRAY_SIZE(test_regions); i++) { + assert(test_regions[i].found); + test_regions[i].found = false; + } +} + +static void check_node_reservations(void) +{ + struct dt_node *parent, *node; + unsigned int i; + + parent = dt_find_by_name(dt_root, "reserved-memory"); + assert(parent); + + assert(dt_prop_get_cell(parent, "#address-cells", 0) == 2); + assert(dt_prop_get_cell(parent, "#size-cells", 0) == 2); + dt_require_property(parent, "ranges", 0); + + dt_for_each_child(parent, node) { + uint64_t addr, size; + + addr = dt_get_address(node, 0, &size); + + for (i = 0; i < ARRAY_SIZE(test_regions); i++) { + if (strncmp(test_regions[i].name, node->name, + strlen(test_regions[i].name))) + continue; + + assert(!test_regions[i].found); + assert(test_regions[i].addr == addr); + assert(size = 0x1000); + test_regions[i].found = true; + } + } + + for (i = 0; i < ARRAY_SIZE(test_regions); i++) { + assert(test_regions[i].found); + test_regions[i].found = false; + } +} + +int main(void) +{ + struct mem_region *r; + unsigned int i; void *buf; /* Use malloc for the heap, so valgrind can find issues. */ @@ -146,33 +216,11 @@ int main(void) r = new_region("test.4", 0x5000, 0x1000, NULL, REGION_RESERVED); assert(!add_region(r)); - /* check dt properties */ - names = dt_find_property(dt_root, "reserved-names"); - ranges = dt_find_property(dt_root, "reserved-ranges"); - - assert(names && ranges); - - /* walk through names & ranges properies, ensuring that the test - * regions are all present */ - for (name = names->prop, rangep = (uint64_t *)ranges->prop, c = 0; - name < names->prop + names->len; - name += l, rangep += 2) { - uint64_t addr; - - addr = dt_get_number(rangep, 2); - l = strlen(name) + 1; - - for (i = 0; i < ARRAY_SIZE(test_regions); i++) { - if (strcmp(test_regions[i].name, name)) - continue; - assert(test_regions[i].addr == addr); - assert(!test_regions[i].found); - test_regions[i].found = true; - c++; - } - } + /* check old property-style reservations */ + check_property_reservations(); - assert(c == ARRAY_SIZE(test_regions)); + /* and new node-style reservations */ + check_node_reservations(); dt_free(dt_root); free((void *)(long)skiboot_heap.start); diff --git a/doc/device-tree/reserved-memory.txt b/doc/device-tree/reserved-memory.txt new file mode 100644 index 0000000..48e32d4 --- /dev/null +++ b/doc/device-tree/reserved-memory.txt @@ -0,0 +1,26 @@ +reserved-memory device tree nodes + +OPAL exposes reserved memory through a top-level reserved-memory node, +containing subnodes that represent each reserved memory region. + +This follows the Linux specification for the /reserved-memory node, +described in the kernel source tree, in: + + Documentation/devicetree/bindings/reserved-memory/reserved-memory.txt + +The top-level /reserved-memory node contains: + + #size-cells = <2> + #address-cells = <2> + - addresses and sizes are all 64-bits + + ranges; + - the empty ranges node indicates no translation of physical + addresses in the subnodes. + +The sub-nodes under the /reserved-memory node contain: + + reg = <address size> + - the address and size of the reserved memory region. The address + and size values are two cells each, as sig +
Linux supports a newer memory reservation layout in the device-tree, where each reservation is represented by a subnode under a top-level "reserved-memory" node. This change adds these nodes, using the mem_region names as the property names (minus any cell addresses). The reserved-memory node looks like this: / { name = "reserved-memory"; ranges; #address-cells = <0x2>; #size-cells = <0x2>; ibm,firmware-code@30000000 { reg = <0x0 0x30000000 0x0 0x200000>; }; ibm,firmware-data@30e00000 { reg = <0x0 0x30e00000 0x0 0xc00000>; }; ibm,firmware-stacks@31a00000 { reg = <0x0 0x31a00000 0x0 0x8000000>; }; ibm,firmware-allocs-memory@39a00000 { reg = <0x0 0x39a00000 0x0 0x1c0200>; }; ibm,firmware-heap@30200000 { reg = <0x0 0x30200000 0x0 0xc00000>; }; }; We keep the property-style reservation information (reserved-names and reserved-ranges) unchanged. Signed-off-by: Jeremy Kerr <jk@ozlabs.org> --- core/mem_region.c | 27 ++++++ core/test/run-mem_region_reservations.c | 108 +++++++++++++++++------- doc/device-tree/reserved-memory.txt | 26 +++++ 3 files changed, 131 insertions(+), 30 deletions(-)