108e875c1SCatalin Marinas /* 208e875c1SCatalin Marinas * SMP initialisation and IPI support 308e875c1SCatalin Marinas * Based on arch/arm/kernel/smp.c 408e875c1SCatalin Marinas * 508e875c1SCatalin Marinas * Copyright (C) 2012 ARM Ltd. 608e875c1SCatalin Marinas * 708e875c1SCatalin Marinas * This program is free software; you can redistribute it and/or modify 808e875c1SCatalin Marinas * it under the terms of the GNU General Public License version 2 as 908e875c1SCatalin Marinas * published by the Free Software Foundation. 1008e875c1SCatalin Marinas * 1108e875c1SCatalin Marinas * This program is distributed in the hope that it will be useful, 1208e875c1SCatalin Marinas * but WITHOUT ANY WARRANTY; without even the implied warranty of 1308e875c1SCatalin Marinas * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1408e875c1SCatalin Marinas * GNU General Public License for more details. 1508e875c1SCatalin Marinas * 1608e875c1SCatalin Marinas * You should have received a copy of the GNU General Public License 1708e875c1SCatalin Marinas * along with this program. If not, see <http://www.gnu.org/licenses/>. 1808e875c1SCatalin Marinas */ 1908e875c1SCatalin Marinas 200f078336SLorenzo Pieralisi #include <linux/acpi.h> 21f5df2696SJames Morse #include <linux/arm_sdei.h> 2208e875c1SCatalin Marinas #include <linux/delay.h> 2308e875c1SCatalin Marinas #include <linux/init.h> 2408e875c1SCatalin Marinas #include <linux/spinlock.h> 2568e21be2SIngo Molnar #include <linux/sched/mm.h> 26ef8bd77fSIngo Molnar #include <linux/sched/hotplug.h> 2768db0cf1SIngo Molnar #include <linux/sched/task_stack.h> 2808e875c1SCatalin Marinas #include <linux/interrupt.h> 2908e875c1SCatalin Marinas #include <linux/cache.h> 3008e875c1SCatalin Marinas #include <linux/profile.h> 3108e875c1SCatalin Marinas #include <linux/errno.h> 3208e875c1SCatalin Marinas #include <linux/mm.h> 3308e875c1SCatalin Marinas #include <linux/err.h> 3408e875c1SCatalin Marinas #include <linux/cpu.h> 3508e875c1SCatalin Marinas #include <linux/smp.h> 3608e875c1SCatalin Marinas #include <linux/seq_file.h> 3708e875c1SCatalin Marinas #include <linux/irq.h> 38e7932188SJulien Thierry #include <linux/irqchip/arm-gic-v3.h> 3908e875c1SCatalin Marinas #include <linux/percpu.h> 4008e875c1SCatalin Marinas #include <linux/clockchips.h> 4108e875c1SCatalin Marinas #include <linux/completion.h> 4208e875c1SCatalin Marinas #include <linux/of.h> 43eb631bb5SLarry Bassel #include <linux/irq_work.h> 4478fd584cSAKASHI Takahiro #include <linux/kexec.h> 4508e875c1SCatalin Marinas 46e039ee4eSAndre Przywara #include <asm/alternative.h> 4708e875c1SCatalin Marinas #include <asm/atomic.h> 4808e875c1SCatalin Marinas #include <asm/cacheflush.h> 49df857416SMark Rutland #include <asm/cpu.h> 5008e875c1SCatalin Marinas #include <asm/cputype.h> 51cd1aebf5SMark Rutland #include <asm/cpu_ops.h> 520fbeb318SJames Morse #include <asm/daifflags.h> 5308e875c1SCatalin Marinas #include <asm/mmu_context.h> 541a2db300SGanapatrao Kulkarni #include <asm/numa.h> 5508e875c1SCatalin Marinas #include <asm/pgtable.h> 5608e875c1SCatalin Marinas #include <asm/pgalloc.h> 5708e875c1SCatalin Marinas #include <asm/processor.h> 584c7aa002SJavi Merino #include <asm/smp_plat.h> 5908e875c1SCatalin Marinas #include <asm/sections.h> 6008e875c1SCatalin Marinas #include <asm/tlbflush.h> 6108e875c1SCatalin Marinas #include <asm/ptrace.h> 62377bcff9SJonas Rabenstein #include <asm/virt.h> 6308e875c1SCatalin Marinas 6445ed695aSNicolas Pitre #define CREATE_TRACE_POINTS 6545ed695aSNicolas Pitre #include <trace/events/ipi.h> 6645ed695aSNicolas Pitre 6757c82954SMark Rutland DEFINE_PER_CPU_READ_MOSTLY(int, cpu_number); 6857c82954SMark Rutland EXPORT_PER_CPU_SYMBOL(cpu_number); 6957c82954SMark Rutland 7008e875c1SCatalin Marinas /* 7108e875c1SCatalin Marinas * as from 2.5, kernels no longer have an init_tasks structure 7208e875c1SCatalin Marinas * so we need some other way of telling a new secondary core 7308e875c1SCatalin Marinas * where to place its SVC stack 7408e875c1SCatalin Marinas */ 7508e875c1SCatalin Marinas struct secondary_data secondary_data; 76bb905274SSuzuki K Poulose /* Number of CPUs which aren't online, but looping in kernel text. */ 77bb905274SSuzuki K Poulose int cpus_stuck_in_kernel; 7808e875c1SCatalin Marinas 7908e875c1SCatalin Marinas enum ipi_msg_type { 8008e875c1SCatalin Marinas IPI_RESCHEDULE, 8108e875c1SCatalin Marinas IPI_CALL_FUNC, 8208e875c1SCatalin Marinas IPI_CPU_STOP, 8378fd584cSAKASHI Takahiro IPI_CPU_CRASH_STOP, 841f85008eSLorenzo Pieralisi IPI_TIMER, 85eb631bb5SLarry Bassel IPI_IRQ_WORK, 865e89c55eSLorenzo Pieralisi IPI_WAKEUP 8708e875c1SCatalin Marinas }; 8808e875c1SCatalin Marinas 89bb905274SSuzuki K Poulose #ifdef CONFIG_HOTPLUG_CPU 90bb905274SSuzuki K Poulose static int op_cpu_kill(unsigned int cpu); 91bb905274SSuzuki K Poulose #else 92bb905274SSuzuki K Poulose static inline int op_cpu_kill(unsigned int cpu) 93bb905274SSuzuki K Poulose { 94bb905274SSuzuki K Poulose return -ENOSYS; 95bb905274SSuzuki K Poulose } 96bb905274SSuzuki K Poulose #endif 97bb905274SSuzuki K Poulose 98bb905274SSuzuki K Poulose 9908e875c1SCatalin Marinas /* 10008e875c1SCatalin Marinas * Boot a secondary CPU, and assign it the specified idle task. 10108e875c1SCatalin Marinas * This also gives us the initial stack to use for this CPU. 10208e875c1SCatalin Marinas */ 103b8c6453aSPaul Gortmaker static int boot_secondary(unsigned int cpu, struct task_struct *idle) 10408e875c1SCatalin Marinas { 105652af899SMark Rutland if (cpu_ops[cpu]->cpu_boot) 106652af899SMark Rutland return cpu_ops[cpu]->cpu_boot(cpu); 10708e875c1SCatalin Marinas 108652af899SMark Rutland return -EOPNOTSUPP; 10908e875c1SCatalin Marinas } 11008e875c1SCatalin Marinas 11108e875c1SCatalin Marinas static DECLARE_COMPLETION(cpu_running); 11208e875c1SCatalin Marinas 113b8c6453aSPaul Gortmaker int __cpu_up(unsigned int cpu, struct task_struct *idle) 11408e875c1SCatalin Marinas { 11508e875c1SCatalin Marinas int ret; 116bb905274SSuzuki K Poulose long status; 11708e875c1SCatalin Marinas 11808e875c1SCatalin Marinas /* 11908e875c1SCatalin Marinas * We need to tell the secondary core where to find its stack and the 12008e875c1SCatalin Marinas * page tables. 12108e875c1SCatalin Marinas */ 122c02433ddSMark Rutland secondary_data.task = idle; 12334be98f4SArd Biesheuvel secondary_data.stack = task_stack_page(idle) + THREAD_SIZE; 124bb905274SSuzuki K Poulose update_cpu_boot_status(CPU_MMU_OFF); 12508e875c1SCatalin Marinas __flush_dcache_area(&secondary_data, sizeof(secondary_data)); 12608e875c1SCatalin Marinas 12708e875c1SCatalin Marinas /* 12808e875c1SCatalin Marinas * Now bring the CPU into our world. 12908e875c1SCatalin Marinas */ 13008e875c1SCatalin Marinas ret = boot_secondary(cpu, idle); 13108e875c1SCatalin Marinas if (ret == 0) { 13208e875c1SCatalin Marinas /* 13308e875c1SCatalin Marinas * CPU was successfully started, wait for it to come online or 13408e875c1SCatalin Marinas * time out. 13508e875c1SCatalin Marinas */ 13608e875c1SCatalin Marinas wait_for_completion_timeout(&cpu_running, 13708e875c1SCatalin Marinas msecs_to_jiffies(1000)); 13808e875c1SCatalin Marinas 13908e875c1SCatalin Marinas if (!cpu_online(cpu)) { 14008e875c1SCatalin Marinas pr_crit("CPU%u: failed to come online\n", cpu); 14108e875c1SCatalin Marinas ret = -EIO; 14208e875c1SCatalin Marinas } 14308e875c1SCatalin Marinas } else { 14408e875c1SCatalin Marinas pr_err("CPU%u: failed to boot: %d\n", cpu, ret); 145f357b3a7SSuzuki K Poulose return ret; 14608e875c1SCatalin Marinas } 14708e875c1SCatalin Marinas 148c02433ddSMark Rutland secondary_data.task = NULL; 14908e875c1SCatalin Marinas secondary_data.stack = NULL; 150bb905274SSuzuki K Poulose status = READ_ONCE(secondary_data.status); 151bb905274SSuzuki K Poulose if (ret && status) { 152bb905274SSuzuki K Poulose 153bb905274SSuzuki K Poulose if (status == CPU_MMU_OFF) 154bb905274SSuzuki K Poulose status = READ_ONCE(__early_cpu_boot_status); 155bb905274SSuzuki K Poulose 15666f16a24SWill Deacon switch (status & CPU_BOOT_STATUS_MASK) { 157bb905274SSuzuki K Poulose default: 158bb905274SSuzuki K Poulose pr_err("CPU%u: failed in unknown state : 0x%lx\n", 159bb905274SSuzuki K Poulose cpu, status); 160bb905274SSuzuki K Poulose break; 161bb905274SSuzuki K Poulose case CPU_KILL_ME: 162bb905274SSuzuki K Poulose if (!op_cpu_kill(cpu)) { 163bb905274SSuzuki K Poulose pr_crit("CPU%u: died during early boot\n", cpu); 164bb905274SSuzuki K Poulose break; 165bb905274SSuzuki K Poulose } 166bb905274SSuzuki K Poulose /* Fall through */ 167bb905274SSuzuki K Poulose pr_crit("CPU%u: may not have shut down cleanly\n", cpu); 168bb905274SSuzuki K Poulose case CPU_STUCK_IN_KERNEL: 169bb905274SSuzuki K Poulose pr_crit("CPU%u: is stuck in kernel\n", cpu); 17066f16a24SWill Deacon if (status & CPU_STUCK_REASON_52_BIT_VA) 17166f16a24SWill Deacon pr_crit("CPU%u: does not support 52-bit VAs\n", cpu); 17266f16a24SWill Deacon if (status & CPU_STUCK_REASON_NO_GRAN) 17366f16a24SWill Deacon pr_crit("CPU%u: does not support %luK granule \n", cpu, PAGE_SIZE / SZ_1K); 174bb905274SSuzuki K Poulose cpus_stuck_in_kernel++; 175bb905274SSuzuki K Poulose break; 176bb905274SSuzuki K Poulose case CPU_PANIC_KERNEL: 177bb905274SSuzuki K Poulose panic("CPU%u detected unsupported configuration\n", cpu); 178bb905274SSuzuki K Poulose } 179bb905274SSuzuki K Poulose } 18008e875c1SCatalin Marinas 18108e875c1SCatalin Marinas return ret; 18208e875c1SCatalin Marinas } 18308e875c1SCatalin Marinas 184e7932188SJulien Thierry static void init_gic_priority_masking(void) 185e7932188SJulien Thierry { 186e7932188SJulien Thierry u32 cpuflags; 187e7932188SJulien Thierry 188e7932188SJulien Thierry if (WARN_ON(!gic_enable_sre())) 189e7932188SJulien Thierry return; 190e7932188SJulien Thierry 191e7932188SJulien Thierry cpuflags = read_sysreg(daif); 192e7932188SJulien Thierry 193e7932188SJulien Thierry WARN_ON(!(cpuflags & PSR_I_BIT)); 194e7932188SJulien Thierry 195e7932188SJulien Thierry gic_write_pmr(GIC_PRIO_IRQOFF); 196e7932188SJulien Thierry 197e7932188SJulien Thierry /* We can only unmask PSR.I if we can take aborts */ 198e7932188SJulien Thierry if (!(cpuflags & PSR_A_BIT)) 199e7932188SJulien Thierry write_sysreg(cpuflags & ~PSR_I_BIT, daif); 200e7932188SJulien Thierry } 201e7932188SJulien Thierry 20208e875c1SCatalin Marinas /* 20308e875c1SCatalin Marinas * This is the secondary CPU boot entry. We're using this CPUs 20408e875c1SCatalin Marinas * idle thread stack, but a set of temporary page tables. 20508e875c1SCatalin Marinas */ 206b154886fSZhizhou Zhang asmlinkage notrace void secondary_start_kernel(void) 20708e875c1SCatalin Marinas { 208ccaac162SMark Rutland u64 mpidr = read_cpuid_mpidr() & MPIDR_HWID_BITMASK; 20908e875c1SCatalin Marinas struct mm_struct *mm = &init_mm; 210580efaa7SMark Rutland unsigned int cpu; 211580efaa7SMark Rutland 212580efaa7SMark Rutland cpu = task_cpu(current); 213580efaa7SMark Rutland set_my_cpu_offset(per_cpu_offset(cpu)); 21408e875c1SCatalin Marinas 21508e875c1SCatalin Marinas /* 21608e875c1SCatalin Marinas * All kernel threads share the same mm context; grab a 21708e875c1SCatalin Marinas * reference and switch to it. 21808e875c1SCatalin Marinas */ 219f1f10076SVegard Nossum mmgrab(mm); 22008e875c1SCatalin Marinas current->active_mm = mm; 22108e875c1SCatalin Marinas 22208e875c1SCatalin Marinas /* 22308e875c1SCatalin Marinas * TTBR0 is only used for the identity mapping at this stage. Make it 22408e875c1SCatalin Marinas * point to zero page to avoid speculatively fetching new entries. 22508e875c1SCatalin Marinas */ 2269e8e865bSMark Rutland cpu_uninstall_idmap(); 22708e875c1SCatalin Marinas 228e7932188SJulien Thierry if (system_uses_irq_prio_masking()) 229e7932188SJulien Thierry init_gic_priority_masking(); 230e7932188SJulien Thierry 23108e875c1SCatalin Marinas preempt_disable(); 23208e875c1SCatalin Marinas trace_hardirqs_off(); 23308e875c1SCatalin Marinas 234dbb4e152SSuzuki K. Poulose /* 235dbb4e152SSuzuki K. Poulose * If the system has established the capabilities, make sure 236dbb4e152SSuzuki K. Poulose * this CPU ticks all of those. If it doesn't, the CPU will 237dbb4e152SSuzuki K. Poulose * fail to come online. 238dbb4e152SSuzuki K. Poulose */ 239c47a1900SSuzuki K Poulose check_local_cpu_capabilities(); 240dbb4e152SSuzuki K. Poulose 241652af899SMark Rutland if (cpu_ops[cpu]->cpu_postboot) 242652af899SMark Rutland cpu_ops[cpu]->cpu_postboot(); 24308e875c1SCatalin Marinas 24408e875c1SCatalin Marinas /* 245df857416SMark Rutland * Log the CPU info before it is marked online and might get read. 246df857416SMark Rutland */ 247df857416SMark Rutland cpuinfo_store_cpu(); 248df857416SMark Rutland 249df857416SMark Rutland /* 2507ade67b5SMarc Zyngier * Enable GIC and timers. 2517ade67b5SMarc Zyngier */ 2527ade67b5SMarc Zyngier notify_cpu_starting(cpu); 2537ade67b5SMarc Zyngier 254c18df0adSDavid Daney store_cpu_topology(cpu); 25597fd6016SSudeep Holla numa_add_cpu(cpu); 256f6e763b9SMark Brown 2577ade67b5SMarc Zyngier /* 25808e875c1SCatalin Marinas * OK, now it's safe to let the boot CPU continue. Wait for 25908e875c1SCatalin Marinas * the CPU migration code to notice that the CPU is online 26008e875c1SCatalin Marinas * before we continue. 26108e875c1SCatalin Marinas */ 262ccaac162SMark Rutland pr_info("CPU%u: Booted secondary processor 0x%010lx [0x%08x]\n", 263ccaac162SMark Rutland cpu, (unsigned long)mpidr, 264ccaac162SMark Rutland read_cpuid_id()); 265bb905274SSuzuki K Poulose update_cpu_boot_status(CPU_BOOT_SUCCESS); 26608e875c1SCatalin Marinas set_cpu_online(cpu, true); 267b3770b32SWill Deacon complete(&cpu_running); 26808e875c1SCatalin Marinas 26941bd5b5dSJames Morse local_daif_restore(DAIF_PROCCTX); 27053ae3acdSCatalin Marinas 27153ae3acdSCatalin Marinas /* 27208e875c1SCatalin Marinas * OK, it's off to the idle thread for us 27308e875c1SCatalin Marinas */ 274fc6d73d6SThomas Gleixner cpu_startup_entry(CPUHP_AP_ONLINE_IDLE); 27508e875c1SCatalin Marinas } 27608e875c1SCatalin Marinas 2779327e2c6SMark Rutland #ifdef CONFIG_HOTPLUG_CPU 2789327e2c6SMark Rutland static int op_cpu_disable(unsigned int cpu) 2799327e2c6SMark Rutland { 2809327e2c6SMark Rutland /* 2819327e2c6SMark Rutland * If we don't have a cpu_die method, abort before we reach the point 2829327e2c6SMark Rutland * of no return. CPU0 may not have an cpu_ops, so test for it. 2839327e2c6SMark Rutland */ 2849327e2c6SMark Rutland if (!cpu_ops[cpu] || !cpu_ops[cpu]->cpu_die) 2859327e2c6SMark Rutland return -EOPNOTSUPP; 2869327e2c6SMark Rutland 2879327e2c6SMark Rutland /* 2889327e2c6SMark Rutland * We may need to abort a hot unplug for some other mechanism-specific 2899327e2c6SMark Rutland * reason. 2909327e2c6SMark Rutland */ 2919327e2c6SMark Rutland if (cpu_ops[cpu]->cpu_disable) 2929327e2c6SMark Rutland return cpu_ops[cpu]->cpu_disable(cpu); 2939327e2c6SMark Rutland 2949327e2c6SMark Rutland return 0; 2959327e2c6SMark Rutland } 2969327e2c6SMark Rutland 2979327e2c6SMark Rutland /* 2989327e2c6SMark Rutland * __cpu_disable runs on the processor to be shutdown. 2999327e2c6SMark Rutland */ 3009327e2c6SMark Rutland int __cpu_disable(void) 3019327e2c6SMark Rutland { 3029327e2c6SMark Rutland unsigned int cpu = smp_processor_id(); 3039327e2c6SMark Rutland int ret; 3049327e2c6SMark Rutland 3059327e2c6SMark Rutland ret = op_cpu_disable(cpu); 3069327e2c6SMark Rutland if (ret) 3079327e2c6SMark Rutland return ret; 3089327e2c6SMark Rutland 3097f9545aaSSudeep Holla remove_cpu_topology(cpu); 3107f9545aaSSudeep Holla numa_remove_cpu(cpu); 3117f9545aaSSudeep Holla 3129327e2c6SMark Rutland /* 3139327e2c6SMark Rutland * Take this CPU offline. Once we clear this, we can't return, 3149327e2c6SMark Rutland * and we must not schedule until we're ready to give up the cpu. 3159327e2c6SMark Rutland */ 3169327e2c6SMark Rutland set_cpu_online(cpu, false); 3179327e2c6SMark Rutland 3189327e2c6SMark Rutland /* 3199327e2c6SMark Rutland * OK - migrate IRQs away from this CPU 3209327e2c6SMark Rutland */ 321217d453dSYang Yingliang irq_migrate_all_off_this_cpu(); 322217d453dSYang Yingliang 3239327e2c6SMark Rutland return 0; 3249327e2c6SMark Rutland } 3259327e2c6SMark Rutland 326c814ca02SAshwin Chaugule static int op_cpu_kill(unsigned int cpu) 327c814ca02SAshwin Chaugule { 328c814ca02SAshwin Chaugule /* 329c814ca02SAshwin Chaugule * If we have no means of synchronising with the dying CPU, then assume 330c814ca02SAshwin Chaugule * that it is really dead. We can only wait for an arbitrary length of 331c814ca02SAshwin Chaugule * time and hope that it's dead, so let's skip the wait and just hope. 332c814ca02SAshwin Chaugule */ 333c814ca02SAshwin Chaugule if (!cpu_ops[cpu]->cpu_kill) 3346b99c68cSMark Rutland return 0; 335c814ca02SAshwin Chaugule 336c814ca02SAshwin Chaugule return cpu_ops[cpu]->cpu_kill(cpu); 337c814ca02SAshwin Chaugule } 338c814ca02SAshwin Chaugule 3399327e2c6SMark Rutland /* 3409327e2c6SMark Rutland * called on the thread which is asking for a CPU to be shutdown - 3419327e2c6SMark Rutland * waits until shutdown has completed, or it is timed out. 3429327e2c6SMark Rutland */ 3439327e2c6SMark Rutland void __cpu_die(unsigned int cpu) 3449327e2c6SMark Rutland { 3456b99c68cSMark Rutland int err; 3466b99c68cSMark Rutland 34705981277SPaul E. McKenney if (!cpu_wait_death(cpu, 5)) { 3489327e2c6SMark Rutland pr_crit("CPU%u: cpu didn't die\n", cpu); 3499327e2c6SMark Rutland return; 3509327e2c6SMark Rutland } 3519327e2c6SMark Rutland pr_notice("CPU%u: shutdown\n", cpu); 352c814ca02SAshwin Chaugule 353c814ca02SAshwin Chaugule /* 354c814ca02SAshwin Chaugule * Now that the dying CPU is beyond the point of no return w.r.t. 355c814ca02SAshwin Chaugule * in-kernel synchronisation, try to get the firwmare to help us to 356c814ca02SAshwin Chaugule * verify that it has really left the kernel before we consider 357c814ca02SAshwin Chaugule * clobbering anything it might still be using. 358c814ca02SAshwin Chaugule */ 3596b99c68cSMark Rutland err = op_cpu_kill(cpu); 3606b99c68cSMark Rutland if (err) 3616b99c68cSMark Rutland pr_warn("CPU%d may not have shut down cleanly: %d\n", 3626b99c68cSMark Rutland cpu, err); 3639327e2c6SMark Rutland } 3649327e2c6SMark Rutland 3659327e2c6SMark Rutland /* 3669327e2c6SMark Rutland * Called from the idle thread for the CPU which has been shutdown. 3679327e2c6SMark Rutland * 3689327e2c6SMark Rutland */ 3699327e2c6SMark Rutland void cpu_die(void) 3709327e2c6SMark Rutland { 3719327e2c6SMark Rutland unsigned int cpu = smp_processor_id(); 3729327e2c6SMark Rutland 3739327e2c6SMark Rutland idle_task_exit(); 3749327e2c6SMark Rutland 3750fbeb318SJames Morse local_daif_mask(); 3769327e2c6SMark Rutland 3779327e2c6SMark Rutland /* Tell __cpu_die() that this CPU is now safe to dispose of */ 37805981277SPaul E. McKenney (void)cpu_report_death(); 3799327e2c6SMark Rutland 3809327e2c6SMark Rutland /* 3819327e2c6SMark Rutland * Actually shutdown the CPU. This must never fail. The specific hotplug 3829327e2c6SMark Rutland * mechanism must perform all required cache maintenance to ensure that 3839327e2c6SMark Rutland * no dirty lines are lost in the process of shutting down the CPU. 3849327e2c6SMark Rutland */ 3859327e2c6SMark Rutland cpu_ops[cpu]->cpu_die(cpu); 3869327e2c6SMark Rutland 3879327e2c6SMark Rutland BUG(); 3889327e2c6SMark Rutland } 3899327e2c6SMark Rutland #endif 3909327e2c6SMark Rutland 391fce6361fSSuzuki K Poulose /* 392fce6361fSSuzuki K Poulose * Kill the calling secondary CPU, early in bringup before it is turned 393fce6361fSSuzuki K Poulose * online. 394fce6361fSSuzuki K Poulose */ 395fce6361fSSuzuki K Poulose void cpu_die_early(void) 396fce6361fSSuzuki K Poulose { 397fce6361fSSuzuki K Poulose int cpu = smp_processor_id(); 398fce6361fSSuzuki K Poulose 399fce6361fSSuzuki K Poulose pr_crit("CPU%d: will not boot\n", cpu); 400fce6361fSSuzuki K Poulose 401fce6361fSSuzuki K Poulose /* Mark this CPU absent */ 402fce6361fSSuzuki K Poulose set_cpu_present(cpu, 0); 403fce6361fSSuzuki K Poulose 404fce6361fSSuzuki K Poulose #ifdef CONFIG_HOTPLUG_CPU 405bb905274SSuzuki K Poulose update_cpu_boot_status(CPU_KILL_ME); 406fce6361fSSuzuki K Poulose /* Check if we can park ourselves */ 407fce6361fSSuzuki K Poulose if (cpu_ops[cpu] && cpu_ops[cpu]->cpu_die) 408fce6361fSSuzuki K Poulose cpu_ops[cpu]->cpu_die(cpu); 409fce6361fSSuzuki K Poulose #endif 410bb905274SSuzuki K Poulose update_cpu_boot_status(CPU_STUCK_IN_KERNEL); 411fce6361fSSuzuki K Poulose 412fce6361fSSuzuki K Poulose cpu_park_loop(); 413fce6361fSSuzuki K Poulose } 414fce6361fSSuzuki K Poulose 415377bcff9SJonas Rabenstein static void __init hyp_mode_check(void) 416377bcff9SJonas Rabenstein { 417377bcff9SJonas Rabenstein if (is_hyp_mode_available()) 418377bcff9SJonas Rabenstein pr_info("CPU: All CPU(s) started at EL2\n"); 419377bcff9SJonas Rabenstein else if (is_hyp_mode_mismatched()) 420377bcff9SJonas Rabenstein WARN_TAINT(1, TAINT_CPU_OUT_OF_SPEC, 421377bcff9SJonas Rabenstein "CPU: CPUs started in inconsistent modes"); 422377bcff9SJonas Rabenstein else 423377bcff9SJonas Rabenstein pr_info("CPU: All CPU(s) started at EL1\n"); 424377bcff9SJonas Rabenstein } 425377bcff9SJonas Rabenstein 42608e875c1SCatalin Marinas void __init smp_cpus_done(unsigned int max_cpus) 42708e875c1SCatalin Marinas { 428326b16dbSWill Deacon pr_info("SMP: Total of %d processors activated.\n", num_online_cpus()); 4293a75578eSSuzuki K. Poulose setup_cpu_features(); 430377bcff9SJonas Rabenstein hyp_mode_check(); 431377bcff9SJonas Rabenstein apply_alternatives_all(); 4325ea5306cSArd Biesheuvel mark_linear_text_alias_ro(); 43308e875c1SCatalin Marinas } 43408e875c1SCatalin Marinas 43508e875c1SCatalin Marinas void __init smp_prepare_boot_cpu(void) 43608e875c1SCatalin Marinas { 4379113c2aaSSuzuki K Poulose set_my_cpu_offset(per_cpu_offset(smp_processor_id())); 438efd9e03fSCatalin Marinas /* 439efd9e03fSCatalin Marinas * Initialise the static keys early as they may be enabled by the 440efd9e03fSCatalin Marinas * cpufeature code. 441efd9e03fSCatalin Marinas */ 442efd9e03fSCatalin Marinas jump_label_init(); 4434b998ff1SSuzuki K. Poulose cpuinfo_store_boot_cpu(); 4440ceb0d56SDaniel Thompson 4450ceb0d56SDaniel Thompson /* 4460ceb0d56SDaniel Thompson * We now know enough about the boot CPU to apply the 4470ceb0d56SDaniel Thompson * alternatives that cannot wait until interrupt handling 4480ceb0d56SDaniel Thompson * and/or scheduling is enabled. 4490ceb0d56SDaniel Thompson */ 4500ceb0d56SDaniel Thompson apply_boot_alternatives(); 451e7932188SJulien Thierry 452e7932188SJulien Thierry /* Conditionally switch to GIC PMR for interrupt masking */ 453e7932188SJulien Thierry if (system_uses_irq_prio_masking()) 454e7932188SJulien Thierry init_gic_priority_masking(); 45508e875c1SCatalin Marinas } 45608e875c1SCatalin Marinas 4570f078336SLorenzo Pieralisi static u64 __init of_get_cpu_mpidr(struct device_node *dn) 4580f078336SLorenzo Pieralisi { 4590f078336SLorenzo Pieralisi const __be32 *cell; 4600f078336SLorenzo Pieralisi u64 hwid; 4610f078336SLorenzo Pieralisi 4620f078336SLorenzo Pieralisi /* 4630f078336SLorenzo Pieralisi * A cpu node with missing "reg" property is 4640f078336SLorenzo Pieralisi * considered invalid to build a cpu_logical_map 4650f078336SLorenzo Pieralisi * entry. 4660f078336SLorenzo Pieralisi */ 4670f078336SLorenzo Pieralisi cell = of_get_property(dn, "reg", NULL); 4680f078336SLorenzo Pieralisi if (!cell) { 469a270f327SRob Herring pr_err("%pOF: missing reg property\n", dn); 4700f078336SLorenzo Pieralisi return INVALID_HWID; 4710f078336SLorenzo Pieralisi } 4720f078336SLorenzo Pieralisi 4730f078336SLorenzo Pieralisi hwid = of_read_number(cell, of_n_addr_cells(dn)); 4740f078336SLorenzo Pieralisi /* 4750f078336SLorenzo Pieralisi * Non affinity bits must be set to 0 in the DT 4760f078336SLorenzo Pieralisi */ 4770f078336SLorenzo Pieralisi if (hwid & ~MPIDR_HWID_BITMASK) { 478a270f327SRob Herring pr_err("%pOF: invalid reg property\n", dn); 4790f078336SLorenzo Pieralisi return INVALID_HWID; 4800f078336SLorenzo Pieralisi } 4810f078336SLorenzo Pieralisi return hwid; 4820f078336SLorenzo Pieralisi } 4830f078336SLorenzo Pieralisi 4840f078336SLorenzo Pieralisi /* 4850f078336SLorenzo Pieralisi * Duplicate MPIDRs are a recipe for disaster. Scan all initialized 4860f078336SLorenzo Pieralisi * entries and check for duplicates. If any is found just ignore the 4870f078336SLorenzo Pieralisi * cpu. cpu_logical_map was initialized to INVALID_HWID to avoid 4880f078336SLorenzo Pieralisi * matching valid MPIDR values. 4890f078336SLorenzo Pieralisi */ 4900f078336SLorenzo Pieralisi static bool __init is_mpidr_duplicate(unsigned int cpu, u64 hwid) 4910f078336SLorenzo Pieralisi { 4920f078336SLorenzo Pieralisi unsigned int i; 4930f078336SLorenzo Pieralisi 4940f078336SLorenzo Pieralisi for (i = 1; (i < cpu) && (i < NR_CPUS); i++) 4950f078336SLorenzo Pieralisi if (cpu_logical_map(i) == hwid) 4960f078336SLorenzo Pieralisi return true; 4970f078336SLorenzo Pieralisi return false; 4980f078336SLorenzo Pieralisi } 4990f078336SLorenzo Pieralisi 50008e875c1SCatalin Marinas /* 501819a8826SLorenzo Pieralisi * Initialize cpu operations for a logical cpu and 502819a8826SLorenzo Pieralisi * set it in the possible mask on success 503819a8826SLorenzo Pieralisi */ 504819a8826SLorenzo Pieralisi static int __init smp_cpu_setup(int cpu) 505819a8826SLorenzo Pieralisi { 506819a8826SLorenzo Pieralisi if (cpu_read_ops(cpu)) 507819a8826SLorenzo Pieralisi return -ENODEV; 508819a8826SLorenzo Pieralisi 509819a8826SLorenzo Pieralisi if (cpu_ops[cpu]->cpu_init(cpu)) 510819a8826SLorenzo Pieralisi return -ENODEV; 511819a8826SLorenzo Pieralisi 512819a8826SLorenzo Pieralisi set_cpu_possible(cpu, true); 513819a8826SLorenzo Pieralisi 514819a8826SLorenzo Pieralisi return 0; 515819a8826SLorenzo Pieralisi } 516819a8826SLorenzo Pieralisi 5170f078336SLorenzo Pieralisi static bool bootcpu_valid __initdata; 5180f078336SLorenzo Pieralisi static unsigned int cpu_count = 1; 5190f078336SLorenzo Pieralisi 5200f078336SLorenzo Pieralisi #ifdef CONFIG_ACPI 521e0013aedSMark Rutland static struct acpi_madt_generic_interrupt cpu_madt_gicc[NR_CPUS]; 522e0013aedSMark Rutland 523e0013aedSMark Rutland struct acpi_madt_generic_interrupt *acpi_cpu_get_madt_gicc(int cpu) 524e0013aedSMark Rutland { 525e0013aedSMark Rutland return &cpu_madt_gicc[cpu]; 526e0013aedSMark Rutland } 527e0013aedSMark Rutland 5280f078336SLorenzo Pieralisi /* 5290f078336SLorenzo Pieralisi * acpi_map_gic_cpu_interface - parse processor MADT entry 5300f078336SLorenzo Pieralisi * 5310f078336SLorenzo Pieralisi * Carry out sanity checks on MADT processor entry and initialize 5320f078336SLorenzo Pieralisi * cpu_logical_map on success 5330f078336SLorenzo Pieralisi */ 5340f078336SLorenzo Pieralisi static void __init 5350f078336SLorenzo Pieralisi acpi_map_gic_cpu_interface(struct acpi_madt_generic_interrupt *processor) 5360f078336SLorenzo Pieralisi { 5370f078336SLorenzo Pieralisi u64 hwid = processor->arm_mpidr; 5380f078336SLorenzo Pieralisi 539f9058929SHanjun Guo if (!(processor->flags & ACPI_MADT_ENABLED)) { 540f9058929SHanjun Guo pr_debug("skipping disabled CPU entry with 0x%llx MPIDR\n", hwid); 5410f078336SLorenzo Pieralisi return; 5420f078336SLorenzo Pieralisi } 5430f078336SLorenzo Pieralisi 544f9058929SHanjun Guo if (hwid & ~MPIDR_HWID_BITMASK || hwid == INVALID_HWID) { 545f9058929SHanjun Guo pr_err("skipping CPU entry with invalid MPIDR 0x%llx\n", hwid); 5460f078336SLorenzo Pieralisi return; 5470f078336SLorenzo Pieralisi } 5480f078336SLorenzo Pieralisi 5490f078336SLorenzo Pieralisi if (is_mpidr_duplicate(cpu_count, hwid)) { 5500f078336SLorenzo Pieralisi pr_err("duplicate CPU MPIDR 0x%llx in MADT\n", hwid); 5510f078336SLorenzo Pieralisi return; 5520f078336SLorenzo Pieralisi } 5530f078336SLorenzo Pieralisi 5540f078336SLorenzo Pieralisi /* Check if GICC structure of boot CPU is available in the MADT */ 5550f078336SLorenzo Pieralisi if (cpu_logical_map(0) == hwid) { 5560f078336SLorenzo Pieralisi if (bootcpu_valid) { 5570f078336SLorenzo Pieralisi pr_err("duplicate boot CPU MPIDR: 0x%llx in MADT\n", 5580f078336SLorenzo Pieralisi hwid); 5590f078336SLorenzo Pieralisi return; 5600f078336SLorenzo Pieralisi } 5610f078336SLorenzo Pieralisi bootcpu_valid = true; 562e0013aedSMark Rutland cpu_madt_gicc[0] = *processor; 5630f078336SLorenzo Pieralisi return; 5640f078336SLorenzo Pieralisi } 5650f078336SLorenzo Pieralisi 5660f078336SLorenzo Pieralisi if (cpu_count >= NR_CPUS) 5670f078336SLorenzo Pieralisi return; 5680f078336SLorenzo Pieralisi 5690f078336SLorenzo Pieralisi /* map the logical cpu id to cpu MPIDR */ 5700f078336SLorenzo Pieralisi cpu_logical_map(cpu_count) = hwid; 5710f078336SLorenzo Pieralisi 572e0013aedSMark Rutland cpu_madt_gicc[cpu_count] = *processor; 573e0013aedSMark Rutland 5745e89c55eSLorenzo Pieralisi /* 5755e89c55eSLorenzo Pieralisi * Set-up the ACPI parking protocol cpu entries 5765e89c55eSLorenzo Pieralisi * while initializing the cpu_logical_map to 5775e89c55eSLorenzo Pieralisi * avoid parsing MADT entries multiple times for 5785e89c55eSLorenzo Pieralisi * nothing (ie a valid cpu_logical_map entry should 5795e89c55eSLorenzo Pieralisi * contain a valid parking protocol data set to 5805e89c55eSLorenzo Pieralisi * initialize the cpu if the parking protocol is 5815e89c55eSLorenzo Pieralisi * the only available enable method). 5825e89c55eSLorenzo Pieralisi */ 5835e89c55eSLorenzo Pieralisi acpi_set_mailbox_entry(cpu_count, processor); 5845e89c55eSLorenzo Pieralisi 5850f078336SLorenzo Pieralisi cpu_count++; 5860f078336SLorenzo Pieralisi } 5870f078336SLorenzo Pieralisi 5880f078336SLorenzo Pieralisi static int __init 589*60574d1eSKeith Busch acpi_parse_gic_cpu_interface(union acpi_subtable_headers *header, 5900f078336SLorenzo Pieralisi const unsigned long end) 5910f078336SLorenzo Pieralisi { 5920f078336SLorenzo Pieralisi struct acpi_madt_generic_interrupt *processor; 5930f078336SLorenzo Pieralisi 5940f078336SLorenzo Pieralisi processor = (struct acpi_madt_generic_interrupt *)header; 59599e3e3aeSAl Stone if (BAD_MADT_GICC_ENTRY(processor, end)) 5960f078336SLorenzo Pieralisi return -EINVAL; 5970f078336SLorenzo Pieralisi 598*60574d1eSKeith Busch acpi_table_print_madt_entry(&header->common); 5990f078336SLorenzo Pieralisi 6000f078336SLorenzo Pieralisi acpi_map_gic_cpu_interface(processor); 6010f078336SLorenzo Pieralisi 6020f078336SLorenzo Pieralisi return 0; 6030f078336SLorenzo Pieralisi } 604e1896249SLorenzo Pieralisi 605e1896249SLorenzo Pieralisi static void __init acpi_parse_and_init_cpus(void) 606e1896249SLorenzo Pieralisi { 607e1896249SLorenzo Pieralisi int i; 608e1896249SLorenzo Pieralisi 609e1896249SLorenzo Pieralisi /* 610e1896249SLorenzo Pieralisi * do a walk of MADT to determine how many CPUs 611e1896249SLorenzo Pieralisi * we have including disabled CPUs, and get information 612e1896249SLorenzo Pieralisi * we need for SMP init. 613e1896249SLorenzo Pieralisi */ 614e1896249SLorenzo Pieralisi acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_INTERRUPT, 615e1896249SLorenzo Pieralisi acpi_parse_gic_cpu_interface, 0); 616e1896249SLorenzo Pieralisi 617e1896249SLorenzo Pieralisi /* 618e1896249SLorenzo Pieralisi * In ACPI, SMP and CPU NUMA information is provided in separate 619e1896249SLorenzo Pieralisi * static tables, namely the MADT and the SRAT. 620e1896249SLorenzo Pieralisi * 621e1896249SLorenzo Pieralisi * Thus, it is simpler to first create the cpu logical map through 622e1896249SLorenzo Pieralisi * an MADT walk and then map the logical cpus to their node ids 623e1896249SLorenzo Pieralisi * as separate steps. 624e1896249SLorenzo Pieralisi */ 625e1896249SLorenzo Pieralisi acpi_map_cpus_to_nodes(); 626e1896249SLorenzo Pieralisi 627e1896249SLorenzo Pieralisi for (i = 0; i < nr_cpu_ids; i++) 628e1896249SLorenzo Pieralisi early_map_cpu_to_node(i, acpi_numa_get_nid(i)); 629e1896249SLorenzo Pieralisi } 6300f078336SLorenzo Pieralisi #else 631e1896249SLorenzo Pieralisi #define acpi_parse_and_init_cpus(...) do { } while (0) 6320f078336SLorenzo Pieralisi #endif 6330f078336SLorenzo Pieralisi 634819a8826SLorenzo Pieralisi /* 6354c7aa002SJavi Merino * Enumerate the possible CPU set from the device tree and build the 6364c7aa002SJavi Merino * cpu logical map array containing MPIDR values related to logical 6374c7aa002SJavi Merino * cpus. Assumes that cpu_logical_map(0) has already been initialized. 63808e875c1SCatalin Marinas */ 63929b8302bSJisheng Zhang static void __init of_parse_and_init_cpus(void) 64008e875c1SCatalin Marinas { 6413d29a9a0SDmitry Torokhov struct device_node *dn; 64208e875c1SCatalin Marinas 643de76e70aSRob Herring for_each_of_cpu_node(dn) { 6440f078336SLorenzo Pieralisi u64 hwid = of_get_cpu_mpidr(dn); 6454c7aa002SJavi Merino 6460f078336SLorenzo Pieralisi if (hwid == INVALID_HWID) 6474c7aa002SJavi Merino goto next; 6484c7aa002SJavi Merino 6490f078336SLorenzo Pieralisi if (is_mpidr_duplicate(cpu_count, hwid)) { 650a270f327SRob Herring pr_err("%pOF: duplicate cpu reg properties in the DT\n", 651a270f327SRob Herring dn); 6524c7aa002SJavi Merino goto next; 6534c7aa002SJavi Merino } 6544c7aa002SJavi Merino 6554c7aa002SJavi Merino /* 6564c7aa002SJavi Merino * The numbering scheme requires that the boot CPU 6574c7aa002SJavi Merino * must be assigned logical id 0. Record it so that 6584c7aa002SJavi Merino * the logical map built from DT is validated and can 6594c7aa002SJavi Merino * be used. 6604c7aa002SJavi Merino */ 6614c7aa002SJavi Merino if (hwid == cpu_logical_map(0)) { 6624c7aa002SJavi Merino if (bootcpu_valid) { 663a270f327SRob Herring pr_err("%pOF: duplicate boot cpu reg property in DT\n", 664a270f327SRob Herring dn); 6654c7aa002SJavi Merino goto next; 6664c7aa002SJavi Merino } 6674c7aa002SJavi Merino 6684c7aa002SJavi Merino bootcpu_valid = true; 6697ba5f605SZhen Lei early_map_cpu_to_node(0, of_node_to_nid(dn)); 6704c7aa002SJavi Merino 6714c7aa002SJavi Merino /* 6724c7aa002SJavi Merino * cpu_logical_map has already been 6734c7aa002SJavi Merino * initialized and the boot cpu doesn't need 6744c7aa002SJavi Merino * the enable-method so continue without 6754c7aa002SJavi Merino * incrementing cpu. 6764c7aa002SJavi Merino */ 6774c7aa002SJavi Merino continue; 6784c7aa002SJavi Merino } 6794c7aa002SJavi Merino 6800f078336SLorenzo Pieralisi if (cpu_count >= NR_CPUS) 68108e875c1SCatalin Marinas goto next; 68208e875c1SCatalin Marinas 6834c7aa002SJavi Merino pr_debug("cpu logical map 0x%llx\n", hwid); 6840f078336SLorenzo Pieralisi cpu_logical_map(cpu_count) = hwid; 6851a2db300SGanapatrao Kulkarni 6861a2db300SGanapatrao Kulkarni early_map_cpu_to_node(cpu_count, of_node_to_nid(dn)); 68708e875c1SCatalin Marinas next: 6880f078336SLorenzo Pieralisi cpu_count++; 6890f078336SLorenzo Pieralisi } 69008e875c1SCatalin Marinas } 69108e875c1SCatalin Marinas 6920f078336SLorenzo Pieralisi /* 6930f078336SLorenzo Pieralisi * Enumerate the possible CPU set from the device tree or ACPI and build the 6940f078336SLorenzo Pieralisi * cpu logical map array containing MPIDR values related to logical 6950f078336SLorenzo Pieralisi * cpus. Assumes that cpu_logical_map(0) has already been initialized. 6960f078336SLorenzo Pieralisi */ 6970f078336SLorenzo Pieralisi void __init smp_init_cpus(void) 6980f078336SLorenzo Pieralisi { 6990f078336SLorenzo Pieralisi int i; 7000f078336SLorenzo Pieralisi 7010f078336SLorenzo Pieralisi if (acpi_disabled) 7020f078336SLorenzo Pieralisi of_parse_and_init_cpus(); 7030f078336SLorenzo Pieralisi else 704e1896249SLorenzo Pieralisi acpi_parse_and_init_cpus(); 7050f078336SLorenzo Pieralisi 70650ee91bdSKefeng Wang if (cpu_count > nr_cpu_ids) 7079b130ad5SAlexey Dobriyan pr_warn("Number of cores (%d) exceeds configured maximum of %u - clipping\n", 70850ee91bdSKefeng Wang cpu_count, nr_cpu_ids); 7094c7aa002SJavi Merino 7104c7aa002SJavi Merino if (!bootcpu_valid) { 7110f078336SLorenzo Pieralisi pr_err("missing boot CPU MPIDR, not enabling secondaries\n"); 7124c7aa002SJavi Merino return; 7134c7aa002SJavi Merino } 7144c7aa002SJavi Merino 7154c7aa002SJavi Merino /* 716819a8826SLorenzo Pieralisi * We need to set the cpu_logical_map entries before enabling 717819a8826SLorenzo Pieralisi * the cpus so that cpu processor description entries (DT cpu nodes 718819a8826SLorenzo Pieralisi * and ACPI MADT entries) can be retrieved by matching the cpu hwid 719819a8826SLorenzo Pieralisi * with entries in cpu_logical_map while initializing the cpus. 720819a8826SLorenzo Pieralisi * If the cpu set-up fails, invalidate the cpu_logical_map entry. 7214c7aa002SJavi Merino */ 72250ee91bdSKefeng Wang for (i = 1; i < nr_cpu_ids; i++) { 723819a8826SLorenzo Pieralisi if (cpu_logical_map(i) != INVALID_HWID) { 724819a8826SLorenzo Pieralisi if (smp_cpu_setup(i)) 725819a8826SLorenzo Pieralisi cpu_logical_map(i) = INVALID_HWID; 726819a8826SLorenzo Pieralisi } 727819a8826SLorenzo Pieralisi } 72808e875c1SCatalin Marinas } 72908e875c1SCatalin Marinas 73008e875c1SCatalin Marinas void __init smp_prepare_cpus(unsigned int max_cpus) 73108e875c1SCatalin Marinas { 732cd1aebf5SMark Rutland int err; 73344dbcc93SSuzuki K Poulose unsigned int cpu; 734c18df0adSDavid Daney unsigned int this_cpu; 73508e875c1SCatalin Marinas 736f6e763b9SMark Brown init_cpu_topology(); 737f6e763b9SMark Brown 738c18df0adSDavid Daney this_cpu = smp_processor_id(); 739c18df0adSDavid Daney store_cpu_topology(this_cpu); 740c18df0adSDavid Daney numa_store_cpu_info(this_cpu); 74197fd6016SSudeep Holla numa_add_cpu(this_cpu); 742f6e763b9SMark Brown 74308e875c1SCatalin Marinas /* 744e75118a7SSuzuki K Poulose * If UP is mandated by "nosmp" (which implies "maxcpus=0"), don't set 745e75118a7SSuzuki K Poulose * secondary CPUs present. 746e75118a7SSuzuki K Poulose */ 747e75118a7SSuzuki K Poulose if (max_cpus == 0) 748e75118a7SSuzuki K Poulose return; 749e75118a7SSuzuki K Poulose 750e75118a7SSuzuki K Poulose /* 75108e875c1SCatalin Marinas * Initialise the present map (which describes the set of CPUs 75208e875c1SCatalin Marinas * actually populated at the present time) and release the 75308e875c1SCatalin Marinas * secondaries from the bootloader. 75408e875c1SCatalin Marinas */ 75508e875c1SCatalin Marinas for_each_possible_cpu(cpu) { 75608e875c1SCatalin Marinas 75757c82954SMark Rutland per_cpu(cpu_number, cpu) = cpu; 75857c82954SMark Rutland 759d329de3fSMarc Zyngier if (cpu == smp_processor_id()) 76008e875c1SCatalin Marinas continue; 76108e875c1SCatalin Marinas 762cd1aebf5SMark Rutland if (!cpu_ops[cpu]) 763d329de3fSMarc Zyngier continue; 764d329de3fSMarc Zyngier 765cd1aebf5SMark Rutland err = cpu_ops[cpu]->cpu_prepare(cpu); 766d329de3fSMarc Zyngier if (err) 767d329de3fSMarc Zyngier continue; 76808e875c1SCatalin Marinas 76908e875c1SCatalin Marinas set_cpu_present(cpu, true); 770c18df0adSDavid Daney numa_store_cpu_info(cpu); 77108e875c1SCatalin Marinas } 77208e875c1SCatalin Marinas } 77308e875c1SCatalin Marinas 77436310736SFrederic Weisbecker void (*__smp_cross_call)(const struct cpumask *, unsigned int); 77508e875c1SCatalin Marinas 77608e875c1SCatalin Marinas void __init set_smp_cross_call(void (*fn)(const struct cpumask *, unsigned int)) 77708e875c1SCatalin Marinas { 77845ed695aSNicolas Pitre __smp_cross_call = fn; 77908e875c1SCatalin Marinas } 78008e875c1SCatalin Marinas 78145ed695aSNicolas Pitre static const char *ipi_types[NR_IPI] __tracepoint_string = { 78245ed695aSNicolas Pitre #define S(x,s) [x] = s 78308e875c1SCatalin Marinas S(IPI_RESCHEDULE, "Rescheduling interrupts"), 78408e875c1SCatalin Marinas S(IPI_CALL_FUNC, "Function call interrupts"), 78508e875c1SCatalin Marinas S(IPI_CPU_STOP, "CPU stop interrupts"), 78678fd584cSAKASHI Takahiro S(IPI_CPU_CRASH_STOP, "CPU stop (for crash dump) interrupts"), 7871f85008eSLorenzo Pieralisi S(IPI_TIMER, "Timer broadcast interrupts"), 788eb631bb5SLarry Bassel S(IPI_IRQ_WORK, "IRQ work interrupts"), 7895e89c55eSLorenzo Pieralisi S(IPI_WAKEUP, "CPU wake-up interrupts"), 79008e875c1SCatalin Marinas }; 79108e875c1SCatalin Marinas 79245ed695aSNicolas Pitre static void smp_cross_call(const struct cpumask *target, unsigned int ipinr) 79345ed695aSNicolas Pitre { 79445ed695aSNicolas Pitre trace_ipi_raise(target, ipi_types[ipinr]); 79545ed695aSNicolas Pitre __smp_cross_call(target, ipinr); 79645ed695aSNicolas Pitre } 79745ed695aSNicolas Pitre 79808e875c1SCatalin Marinas void show_ipi_list(struct seq_file *p, int prec) 79908e875c1SCatalin Marinas { 80008e875c1SCatalin Marinas unsigned int cpu, i; 80108e875c1SCatalin Marinas 80208e875c1SCatalin Marinas for (i = 0; i < NR_IPI; i++) { 80345ed695aSNicolas Pitre seq_printf(p, "%*s%u:%s", prec - 1, "IPI", i, 80408e875c1SCatalin Marinas prec >= 4 ? " " : ""); 80567317c26SSudeep KarkadaNagesha for_each_online_cpu(cpu) 80608e875c1SCatalin Marinas seq_printf(p, "%10u ", 80708e875c1SCatalin Marinas __get_irq_stat(cpu, ipi_irqs[i])); 80808e875c1SCatalin Marinas seq_printf(p, " %s\n", ipi_types[i]); 80908e875c1SCatalin Marinas } 81008e875c1SCatalin Marinas } 81108e875c1SCatalin Marinas 81208e875c1SCatalin Marinas u64 smp_irq_stat_cpu(unsigned int cpu) 81308e875c1SCatalin Marinas { 81408e875c1SCatalin Marinas u64 sum = 0; 81508e875c1SCatalin Marinas int i; 81608e875c1SCatalin Marinas 81708e875c1SCatalin Marinas for (i = 0; i < NR_IPI; i++) 81808e875c1SCatalin Marinas sum += __get_irq_stat(cpu, ipi_irqs[i]); 81908e875c1SCatalin Marinas 82008e875c1SCatalin Marinas return sum; 82108e875c1SCatalin Marinas } 82208e875c1SCatalin Marinas 82345ed695aSNicolas Pitre void arch_send_call_function_ipi_mask(const struct cpumask *mask) 82445ed695aSNicolas Pitre { 82545ed695aSNicolas Pitre smp_cross_call(mask, IPI_CALL_FUNC); 82645ed695aSNicolas Pitre } 82745ed695aSNicolas Pitre 82845ed695aSNicolas Pitre void arch_send_call_function_single_ipi(int cpu) 82945ed695aSNicolas Pitre { 8300aaf0daeSJiang Liu smp_cross_call(cpumask_of(cpu), IPI_CALL_FUNC); 83145ed695aSNicolas Pitre } 83245ed695aSNicolas Pitre 8335e89c55eSLorenzo Pieralisi #ifdef CONFIG_ARM64_ACPI_PARKING_PROTOCOL 8345e89c55eSLorenzo Pieralisi void arch_send_wakeup_ipi_mask(const struct cpumask *mask) 8355e89c55eSLorenzo Pieralisi { 8365e89c55eSLorenzo Pieralisi smp_cross_call(mask, IPI_WAKEUP); 8375e89c55eSLorenzo Pieralisi } 8385e89c55eSLorenzo Pieralisi #endif 8395e89c55eSLorenzo Pieralisi 84045ed695aSNicolas Pitre #ifdef CONFIG_IRQ_WORK 84145ed695aSNicolas Pitre void arch_irq_work_raise(void) 84245ed695aSNicolas Pitre { 84345ed695aSNicolas Pitre if (__smp_cross_call) 84445ed695aSNicolas Pitre smp_cross_call(cpumask_of(smp_processor_id()), IPI_IRQ_WORK); 84545ed695aSNicolas Pitre } 84645ed695aSNicolas Pitre #endif 84745ed695aSNicolas Pitre 84808e875c1SCatalin Marinas /* 84908e875c1SCatalin Marinas * ipi_cpu_stop - handle IPI from smp_send_stop() 85008e875c1SCatalin Marinas */ 85108e875c1SCatalin Marinas static void ipi_cpu_stop(unsigned int cpu) 85208e875c1SCatalin Marinas { 85308e875c1SCatalin Marinas set_cpu_online(cpu, false); 85408e875c1SCatalin Marinas 8550fbeb318SJames Morse local_daif_mask(); 856f5df2696SJames Morse sdei_mask_local_cpu(); 85708e875c1SCatalin Marinas 85808e875c1SCatalin Marinas while (1) 85908e875c1SCatalin Marinas cpu_relax(); 86008e875c1SCatalin Marinas } 86108e875c1SCatalin Marinas 86278fd584cSAKASHI Takahiro #ifdef CONFIG_KEXEC_CORE 86378fd584cSAKASHI Takahiro static atomic_t waiting_for_crash_ipi = ATOMIC_INIT(0); 86478fd584cSAKASHI Takahiro #endif 86578fd584cSAKASHI Takahiro 86678fd584cSAKASHI Takahiro static void ipi_cpu_crash_stop(unsigned int cpu, struct pt_regs *regs) 86778fd584cSAKASHI Takahiro { 86878fd584cSAKASHI Takahiro #ifdef CONFIG_KEXEC_CORE 86978fd584cSAKASHI Takahiro crash_save_cpu(regs, cpu); 87078fd584cSAKASHI Takahiro 87178fd584cSAKASHI Takahiro atomic_dec(&waiting_for_crash_ipi); 87278fd584cSAKASHI Takahiro 87378fd584cSAKASHI Takahiro local_irq_disable(); 874f5df2696SJames Morse sdei_mask_local_cpu(); 87578fd584cSAKASHI Takahiro 87678fd584cSAKASHI Takahiro #ifdef CONFIG_HOTPLUG_CPU 87778fd584cSAKASHI Takahiro if (cpu_ops[cpu]->cpu_die) 87878fd584cSAKASHI Takahiro cpu_ops[cpu]->cpu_die(cpu); 87978fd584cSAKASHI Takahiro #endif 88078fd584cSAKASHI Takahiro 88178fd584cSAKASHI Takahiro /* just in case */ 88278fd584cSAKASHI Takahiro cpu_park_loop(); 88378fd584cSAKASHI Takahiro #endif 88478fd584cSAKASHI Takahiro } 88578fd584cSAKASHI Takahiro 88608e875c1SCatalin Marinas /* 88708e875c1SCatalin Marinas * Main handler for inter-processor interrupts 88808e875c1SCatalin Marinas */ 88908e875c1SCatalin Marinas void handle_IPI(int ipinr, struct pt_regs *regs) 89008e875c1SCatalin Marinas { 89108e875c1SCatalin Marinas unsigned int cpu = smp_processor_id(); 89208e875c1SCatalin Marinas struct pt_regs *old_regs = set_irq_regs(regs); 89308e875c1SCatalin Marinas 89445ed695aSNicolas Pitre if ((unsigned)ipinr < NR_IPI) { 895be081d9bSStephen Boyd trace_ipi_entry_rcuidle(ipi_types[ipinr]); 89645ed695aSNicolas Pitre __inc_irq_stat(cpu, ipi_irqs[ipinr]); 89745ed695aSNicolas Pitre } 89808e875c1SCatalin Marinas 89908e875c1SCatalin Marinas switch (ipinr) { 90008e875c1SCatalin Marinas case IPI_RESCHEDULE: 90108e875c1SCatalin Marinas scheduler_ipi(); 90208e875c1SCatalin Marinas break; 90308e875c1SCatalin Marinas 90408e875c1SCatalin Marinas case IPI_CALL_FUNC: 90508e875c1SCatalin Marinas irq_enter(); 90608e875c1SCatalin Marinas generic_smp_call_function_interrupt(); 90708e875c1SCatalin Marinas irq_exit(); 90808e875c1SCatalin Marinas break; 90908e875c1SCatalin Marinas 91008e875c1SCatalin Marinas case IPI_CPU_STOP: 91108e875c1SCatalin Marinas irq_enter(); 91208e875c1SCatalin Marinas ipi_cpu_stop(cpu); 91308e875c1SCatalin Marinas irq_exit(); 91408e875c1SCatalin Marinas break; 91508e875c1SCatalin Marinas 91678fd584cSAKASHI Takahiro case IPI_CPU_CRASH_STOP: 91778fd584cSAKASHI Takahiro if (IS_ENABLED(CONFIG_KEXEC_CORE)) { 91878fd584cSAKASHI Takahiro irq_enter(); 91978fd584cSAKASHI Takahiro ipi_cpu_crash_stop(cpu, regs); 92078fd584cSAKASHI Takahiro 92178fd584cSAKASHI Takahiro unreachable(); 92278fd584cSAKASHI Takahiro } 92378fd584cSAKASHI Takahiro break; 92478fd584cSAKASHI Takahiro 9251f85008eSLorenzo Pieralisi #ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST 9261f85008eSLorenzo Pieralisi case IPI_TIMER: 9271f85008eSLorenzo Pieralisi irq_enter(); 9281f85008eSLorenzo Pieralisi tick_receive_broadcast(); 9291f85008eSLorenzo Pieralisi irq_exit(); 9301f85008eSLorenzo Pieralisi break; 9311f85008eSLorenzo Pieralisi #endif 9321f85008eSLorenzo Pieralisi 933eb631bb5SLarry Bassel #ifdef CONFIG_IRQ_WORK 934eb631bb5SLarry Bassel case IPI_IRQ_WORK: 935eb631bb5SLarry Bassel irq_enter(); 936eb631bb5SLarry Bassel irq_work_run(); 937eb631bb5SLarry Bassel irq_exit(); 938eb631bb5SLarry Bassel break; 939eb631bb5SLarry Bassel #endif 940eb631bb5SLarry Bassel 9415e89c55eSLorenzo Pieralisi #ifdef CONFIG_ARM64_ACPI_PARKING_PROTOCOL 9425e89c55eSLorenzo Pieralisi case IPI_WAKEUP: 9435e89c55eSLorenzo Pieralisi WARN_ONCE(!acpi_parking_protocol_valid(cpu), 9445e89c55eSLorenzo Pieralisi "CPU%u: Wake-up IPI outside the ACPI parking protocol\n", 9455e89c55eSLorenzo Pieralisi cpu); 9465e89c55eSLorenzo Pieralisi break; 9475e89c55eSLorenzo Pieralisi #endif 9485e89c55eSLorenzo Pieralisi 94908e875c1SCatalin Marinas default: 95008e875c1SCatalin Marinas pr_crit("CPU%u: Unknown IPI message 0x%x\n", cpu, ipinr); 95108e875c1SCatalin Marinas break; 95208e875c1SCatalin Marinas } 95345ed695aSNicolas Pitre 95445ed695aSNicolas Pitre if ((unsigned)ipinr < NR_IPI) 955be081d9bSStephen Boyd trace_ipi_exit_rcuidle(ipi_types[ipinr]); 95608e875c1SCatalin Marinas set_irq_regs(old_regs); 95708e875c1SCatalin Marinas } 95808e875c1SCatalin Marinas 95908e875c1SCatalin Marinas void smp_send_reschedule(int cpu) 96008e875c1SCatalin Marinas { 96108e875c1SCatalin Marinas smp_cross_call(cpumask_of(cpu), IPI_RESCHEDULE); 96208e875c1SCatalin Marinas } 96308e875c1SCatalin Marinas 9641f85008eSLorenzo Pieralisi #ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST 9651f85008eSLorenzo Pieralisi void tick_broadcast(const struct cpumask *mask) 9661f85008eSLorenzo Pieralisi { 9671f85008eSLorenzo Pieralisi smp_cross_call(mask, IPI_TIMER); 9681f85008eSLorenzo Pieralisi } 9691f85008eSLorenzo Pieralisi #endif 9701f85008eSLorenzo Pieralisi 97108e875c1SCatalin Marinas void smp_send_stop(void) 97208e875c1SCatalin Marinas { 97308e875c1SCatalin Marinas unsigned long timeout; 97408e875c1SCatalin Marinas 97508e875c1SCatalin Marinas if (num_online_cpus() > 1) { 97608e875c1SCatalin Marinas cpumask_t mask; 97708e875c1SCatalin Marinas 97808e875c1SCatalin Marinas cpumask_copy(&mask, cpu_online_mask); 979434ed7f4SRusty Russell cpumask_clear_cpu(smp_processor_id(), &mask); 98008e875c1SCatalin Marinas 981ef284f5cSThomas Gleixner if (system_state <= SYSTEM_RUNNING) 98282611c14SJan Glauber pr_crit("SMP: stopping secondary CPUs\n"); 98308e875c1SCatalin Marinas smp_cross_call(&mask, IPI_CPU_STOP); 98408e875c1SCatalin Marinas } 98508e875c1SCatalin Marinas 98608e875c1SCatalin Marinas /* Wait up to one second for other CPUs to stop */ 98708e875c1SCatalin Marinas timeout = USEC_PER_SEC; 98808e875c1SCatalin Marinas while (num_online_cpus() > 1 && timeout--) 98908e875c1SCatalin Marinas udelay(1); 99008e875c1SCatalin Marinas 99108e875c1SCatalin Marinas if (num_online_cpus() > 1) 99282611c14SJan Glauber pr_warning("SMP: failed to stop secondary CPUs %*pbl\n", 99382611c14SJan Glauber cpumask_pr_args(cpu_online_mask)); 994f5df2696SJames Morse 995f5df2696SJames Morse sdei_mask_local_cpu(); 99608e875c1SCatalin Marinas } 99708e875c1SCatalin Marinas 99878fd584cSAKASHI Takahiro #ifdef CONFIG_KEXEC_CORE 999a88ce63bSHoeun Ryu void crash_smp_send_stop(void) 100078fd584cSAKASHI Takahiro { 1001a88ce63bSHoeun Ryu static int cpus_stopped; 100278fd584cSAKASHI Takahiro cpumask_t mask; 100378fd584cSAKASHI Takahiro unsigned long timeout; 100478fd584cSAKASHI Takahiro 1005a88ce63bSHoeun Ryu /* 1006a88ce63bSHoeun Ryu * This function can be called twice in panic path, but obviously 1007a88ce63bSHoeun Ryu * we execute this only once. 1008a88ce63bSHoeun Ryu */ 1009a88ce63bSHoeun Ryu if (cpus_stopped) 1010a88ce63bSHoeun Ryu return; 1011a88ce63bSHoeun Ryu 1012a88ce63bSHoeun Ryu cpus_stopped = 1; 1013a88ce63bSHoeun Ryu 1014f5df2696SJames Morse if (num_online_cpus() == 1) { 1015f5df2696SJames Morse sdei_mask_local_cpu(); 101678fd584cSAKASHI Takahiro return; 1017f5df2696SJames Morse } 101878fd584cSAKASHI Takahiro 101978fd584cSAKASHI Takahiro cpumask_copy(&mask, cpu_online_mask); 102078fd584cSAKASHI Takahiro cpumask_clear_cpu(smp_processor_id(), &mask); 102178fd584cSAKASHI Takahiro 102278fd584cSAKASHI Takahiro atomic_set(&waiting_for_crash_ipi, num_online_cpus() - 1); 102378fd584cSAKASHI Takahiro 102478fd584cSAKASHI Takahiro pr_crit("SMP: stopping secondary CPUs\n"); 102578fd584cSAKASHI Takahiro smp_cross_call(&mask, IPI_CPU_CRASH_STOP); 102678fd584cSAKASHI Takahiro 102778fd584cSAKASHI Takahiro /* Wait up to one second for other CPUs to stop */ 102878fd584cSAKASHI Takahiro timeout = USEC_PER_SEC; 102978fd584cSAKASHI Takahiro while ((atomic_read(&waiting_for_crash_ipi) > 0) && timeout--) 103078fd584cSAKASHI Takahiro udelay(1); 103178fd584cSAKASHI Takahiro 103278fd584cSAKASHI Takahiro if (atomic_read(&waiting_for_crash_ipi) > 0) 103378fd584cSAKASHI Takahiro pr_warning("SMP: failed to stop secondary CPUs %*pbl\n", 103478fd584cSAKASHI Takahiro cpumask_pr_args(&mask)); 1035f5df2696SJames Morse 1036f5df2696SJames Morse sdei_mask_local_cpu(); 103778fd584cSAKASHI Takahiro } 103878fd584cSAKASHI Takahiro 103978fd584cSAKASHI Takahiro bool smp_crash_stop_failed(void) 104078fd584cSAKASHI Takahiro { 104178fd584cSAKASHI Takahiro return (atomic_read(&waiting_for_crash_ipi) > 0); 104278fd584cSAKASHI Takahiro } 104378fd584cSAKASHI Takahiro #endif 104478fd584cSAKASHI Takahiro 104508e875c1SCatalin Marinas /* 104608e875c1SCatalin Marinas * not supported here 104708e875c1SCatalin Marinas */ 104808e875c1SCatalin Marinas int setup_profiling_timer(unsigned int multiplier) 104908e875c1SCatalin Marinas { 105008e875c1SCatalin Marinas return -EINVAL; 105108e875c1SCatalin Marinas } 10525c492c3fSJames Morse 10535c492c3fSJames Morse static bool have_cpu_die(void) 10545c492c3fSJames Morse { 10555c492c3fSJames Morse #ifdef CONFIG_HOTPLUG_CPU 10565c492c3fSJames Morse int any_cpu = raw_smp_processor_id(); 10575c492c3fSJames Morse 1058335d2c2dSMark Salter if (cpu_ops[any_cpu] && cpu_ops[any_cpu]->cpu_die) 10595c492c3fSJames Morse return true; 10605c492c3fSJames Morse #endif 10615c492c3fSJames Morse return false; 10625c492c3fSJames Morse } 10635c492c3fSJames Morse 10645c492c3fSJames Morse bool cpus_are_stuck_in_kernel(void) 10655c492c3fSJames Morse { 10665c492c3fSJames Morse bool smp_spin_tables = (num_possible_cpus() > 1 && !have_cpu_die()); 10675c492c3fSJames Morse 10685c492c3fSJames Morse return !!cpus_stuck_in_kernel || smp_spin_tables; 10695c492c3fSJames Morse } 1070