[PATCHv10 3/3] powerpc/smp: Allow hole in paca_ptrs to accommodate boot_cpu
Pingfan Liu
kernelfans at gmail.com
Tue Dec 26 18:41:47 PST 2023
From: Pingfan Liu <piliu at redhat.com>
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 at redhat.com>
Cc: Michael Ellerman <mpe at ellerman.id.au>
Cc: Nicholas Piggin <npiggin at gmail.com>
Cc: Christophe Leroy <christophe.leroy at csgroup.eu>
Cc: Mahesh Salgaonkar <mahesh at linux.ibm.com>
Cc: Wen Xiong <wenxiong at us.ibm.com>
Cc: Baoquan He <bhe at redhat.com>
Cc: Ming Lei <ming.lei at redhat.com>
Cc: Sourabh Jain <sourabhjain at linux.ibm.com>
Cc: Hari Bathini <hbathini at linux.ibm.com>
Cc: kexec at lists.infradead.org
To: linuxppc-dev at lists.ozlabs.org
---
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
More information about the kexec
mailing list