Skip to content

Commit 340a4a9

Browse files
ldu4mpe
authored andcommitted
powerpc: Take in account addition CPU node when building kexec FDT
On a system with a large number of CPUs, the creation of the FDT for a kexec kernel may fail because the allocated FDT is not large enough. When this happens, such a message is displayed on the console: Unable to add ibm,processor-vadd-size property: FDT_ERR_NOSPACE The property's name may change depending when the buffer overwrite is detected. Obviously the created FDT is missing information, and it is expected that system dump or kexec kernel failed to run properly. When the FDT is allocated, the size of the FDT the kernel received at boot time is used and an extra size can be applied. Currently, only memory added after boot time is taken in account, not the CPU nodes. The extra size should take in account these additional CPU nodes and compute the required extra space. To achieve that, the size of a CPU node, including its subnode is computed once and multiplied by the number of additional CPU nodes. The assumption is that the size of the CPU node is _same_ for all the node, the only variable part should be the name "PowerPC,POWERxx@##" where "##" may vary a little. Signed-off-by: Laurent Dufour <[email protected]> [mpe: Don't shadow function name w/variable, minor coding style changes] Signed-off-by: Michael Ellerman <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent e13d23a commit 340a4a9

File tree

1 file changed

+58
-1
lines changed

1 file changed

+58
-1
lines changed

arch/powerpc/kexec/file_load_64.c

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include <asm/firmware.h>
2727
#include <asm/kexec_ranges.h>
2828
#include <asm/crashdump-ppc64.h>
29+
#include <asm/prom.h>
2930

3031
struct umem_info {
3132
u64 *buf; /* data buffer for usable-memory property */
@@ -928,6 +929,45 @@ int setup_purgatory_ppc64(struct kimage *image, const void *slave_code,
928929
return ret;
929930
}
930931

932+
/**
933+
* get_cpu_node_size - Compute the size of a CPU node in the FDT.
934+
* This should be done only once and the value is stored in
935+
* a static variable.
936+
* Returns the max size of a CPU node in the FDT.
937+
*/
938+
static unsigned int cpu_node_size(void)
939+
{
940+
static unsigned int size;
941+
struct device_node *dn;
942+
struct property *pp;
943+
944+
/*
945+
* Don't compute it twice, we are assuming that the per CPU node size
946+
* doesn't change during the system's life.
947+
*/
948+
if (size)
949+
return size;
950+
951+
dn = of_find_node_by_type(NULL, "cpu");
952+
if (WARN_ON_ONCE(!dn)) {
953+
// Unlikely to happen
954+
return 0;
955+
}
956+
957+
/*
958+
* We compute the sub node size for a CPU node, assuming it
959+
* will be the same for all.
960+
*/
961+
size += strlen(dn->name) + 5;
962+
for_each_property_of_node(dn, pp) {
963+
size += strlen(pp->name);
964+
size += pp->length;
965+
}
966+
967+
of_node_put(dn);
968+
return size;
969+
}
970+
931971
/**
932972
* kexec_extra_fdt_size_ppc64 - Return the estimated additional size needed to
933973
* setup FDT for kexec/kdump kernel.
@@ -937,6 +977,8 @@ int setup_purgatory_ppc64(struct kimage *image, const void *slave_code,
937977
*/
938978
unsigned int kexec_extra_fdt_size_ppc64(struct kimage *image)
939979
{
980+
unsigned int cpu_nodes, extra_size;
981+
struct device_node *dn;
940982
u64 usm_entries;
941983

942984
if (image->type != KEXEC_TYPE_CRASH)
@@ -949,7 +991,22 @@ unsigned int kexec_extra_fdt_size_ppc64(struct kimage *image)
949991
*/
950992
usm_entries = ((memblock_end_of_DRAM() / drmem_lmb_size()) +
951993
(2 * (resource_size(&crashk_res) / drmem_lmb_size())));
952-
return (unsigned int)(usm_entries * sizeof(u64));
994+
995+
extra_size = (unsigned int)(usm_entries * sizeof(u64));
996+
997+
/*
998+
* Get the number of CPU nodes in the current DT. This allows to
999+
* reserve places for CPU nodes added since the boot time.
1000+
*/
1001+
cpu_nodes = 0;
1002+
for_each_node_by_type(dn, "cpu") {
1003+
cpu_nodes++;
1004+
}
1005+
1006+
if (cpu_nodes > boot_cpu_node_count)
1007+
extra_size += (cpu_nodes - boot_cpu_node_count) * cpu_node_size();
1008+
1009+
return extra_size;
9531010
}
9541011

9551012
/**

0 commit comments

Comments
 (0)