From: Pingfan Liu <pi...@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 <pi...@redhat.com>
Cc: Michael Ellerman <m...@ellerman.id.au>
Cc: Nicholas Piggin <npig...@gmail.com>
Cc: Christophe Leroy <christophe.le...@csgroup.eu>
Cc: Mahesh Salgaonkar <mah...@linux.ibm.com>
Cc: Wen Xiong <wenxi...@us.ibm.com>
Cc: Baoquan He <b...@redhat.com>
Cc: Ming Lei <ming....@redhat.com>
Cc: Sourabh Jain <sourabhj...@linux.ibm.com>
Cc: Hari Bathini <hbath...@linux.ibm.com>
Cc: ke...@lists.infradead.org
To: linuxppc-dev@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

Reply via email to