From: Pingfan Liu <piliu@xxxxxxxxxx> This patch always forces the first core onlined due to some subsystem needs cpu0. After core0, a hole may follow, then comes the crashed core. Signed-off-by: Pingfan Liu <piliu@xxxxxxxxxx> Cc: Michael Ellerman <mpe@xxxxxxxxxxxxxx> Cc: Nicholas Piggin <npiggin@xxxxxxxxx> Cc: Christophe Leroy <christophe.leroy@xxxxxxxxxx> Cc: Mahesh Salgaonkar <mahesh@xxxxxxxxxxxxx> Cc: Wen Xiong <wenxiong@xxxxxxxxxx> Cc: Baoquan He <bhe@xxxxxxxxxx> Cc: Ming Lei <ming.lei@xxxxxxxxxx> Cc: Sourabh Jain <sourabhjain@xxxxxxxxxxxxx> Cc: Hari Bathini <hbathini@xxxxxxxxxxxxx> Cc: kexec@xxxxxxxxxxxxxxxxxxx To: linuxppc-dev@xxxxxxxxxxxxxxxx --- arch/powerpc/include/asm/smp.h | 1 + arch/powerpc/kernel/paca.c | 7 +++++-- arch/powerpc/kernel/prom.c | 6 ++++++ arch/powerpc/kernel/setup-common.c | 24 ++++++++++++++++++++---- 4 files changed, 32 insertions(+), 6 deletions(-) diff --git a/arch/powerpc/include/asm/smp.h b/arch/powerpc/include/asm/smp.h index aaaa576d0e15..f01c7891b0d7 100644 --- a/arch/powerpc/include/asm/smp.h +++ b/arch/powerpc/include/asm/smp.h @@ -27,6 +27,7 @@ extern int boot_cpuid; extern int boot_cpu_hwid; /* PPC64 only */ +extern int threads_in_core; extern int spinning_secondaries; extern u32 *cpu_to_phys_id; extern bool coregroup_enabled; diff --git a/arch/powerpc/kernel/paca.c b/arch/powerpc/kernel/paca.c index 840c74dd17d6..1fe0fd2a6021 100644 --- a/arch/powerpc/kernel/paca.c +++ b/arch/powerpc/kernel/paca.c @@ -242,9 +242,12 @@ static int __initdata paca_struct_size; void __init allocate_paca_ptrs(void) { - paca_last_cpu_num = nr_cpu_ids; + unsigned int cnt; - paca_ptrs_size = sizeof(struct paca_struct *) * paca_last_cpu_num; + /* paca_ptrs should be big enough to hold boot cpu */ + cnt = max((unsigned int)ALIGN(boot_cpuid + 1, threads_in_core), nr_cpu_ids); + paca_last_cpu_num = cnt; + paca_ptrs_size = sizeof(struct paca_struct *) * cnt; paca_ptrs = memblock_alloc_raw(paca_ptrs_size, SMP_CACHE_BYTES); if (!paca_ptrs) panic("Failed to allocate %d bytes for paca pointers\n", diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index 0b5878c3125b..e1a671156941 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c @@ -371,9 +371,15 @@ static int __init early_init_dt_scan_cpus(unsigned long node, DBG("boot cpu: logical %d physical %d\n", found, be32_to_cpu(intserv[found_thread])); boot_cpuid = found; + /* This forces all threads in a core to be onlined */ + set_nr_cpu_ids(ALIGN(nr_cpu_ids, nthreads)); + /* Core 0 is always onlined and assure enough room for boot core */ + if (nthreads -1 < boot_cpuid && nr_cpu_ids < 2 * nthreads) + set_nr_cpu_ids(2 * nthreads); if (IS_ENABLED(CONFIG_PPC64)) boot_cpu_hwid = be32_to_cpu(intserv[found_thread]); + threads_in_core = nthreads; /* * PAPR defines "logical" PVR values for cpus that diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c index f9f5f313abf0..b70474e1b5fe 100644 --- a/arch/powerpc/kernel/setup-common.c +++ b/arch/powerpc/kernel/setup-common.c @@ -86,6 +86,7 @@ EXPORT_SYMBOL(machine_id); int boot_cpuid = -1; EXPORT_SYMBOL_GPL(boot_cpuid); +int __initdata threads_in_core = 1; #ifdef CONFIG_PPC64 int boot_cpu_hwid = -1; @@ -448,8 +449,9 @@ u32 *cpu_to_phys_id = NULL; void __init smp_setup_cpu_maps(void) { struct device_node *dn; - int cpu = 0; + int cpu_onlined = 0, cpu = 0; int nthreads = 1; + bool bootcpu_covered = false; DBG("smp_setup_cpu_maps()\n"); @@ -484,7 +486,19 @@ void __init smp_setup_cpu_maps(void) nthreads = len / sizeof(int); - for (j = 0; j < nthreads && cpu < nr_cpu_ids; j++) { + if (!bootcpu_covered) { + if (cpu == ALIGN_DOWN(boot_cpuid, nthreads)) { + bootcpu_covered = true; + goto scan; + + /* Reserve the last online slot for boot core */ + } else if (cpu >= nr_cpu_ids - nthreads && !bootcpu_covered) { + cpu += nthreads; + continue; + } + } +scan: + for (j = 0; j < nthreads && cpu_onlined < nr_cpu_ids; j++) { bool avail; DBG(" thread %d -> cpu %d (hard id %d)\n", @@ -499,9 +513,10 @@ void __init smp_setup_cpu_maps(void) set_cpu_possible(cpu, true); cpu_to_phys_id[cpu] = be32_to_cpu(intserv[j]); cpu++; + cpu_onlined++; } - if (cpu >= nr_cpu_ids) { + if (cpu_onlined >= nr_cpu_ids) { of_node_put(dn); break; } @@ -547,7 +562,8 @@ void __init smp_setup_cpu_maps(void) printk(KERN_INFO "Partition configured for %d cpus.\n", maxcpus); - for (cpu = 0; cpu < maxcpus; cpu++) + /* Bits below #cpu have been set */ + for (; cpu < maxcpus; cpu++) set_cpu_possible(cpu, true); out: of_node_put(dn); -- 2.31.1 _______________________________________________ kexec mailing list kexec@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/kexec