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> 2108e875c1SCatalin Marinas #include <linux/delay.h> 2208e875c1SCatalin Marinas #include <linux/init.h> 2308e875c1SCatalin Marinas #include <linux/spinlock.h> 2408e875c1SCatalin Marinas #include <linux/sched.h> 2508e875c1SCatalin Marinas #include <linux/interrupt.h> 2608e875c1SCatalin Marinas #include <linux/cache.h> 2708e875c1SCatalin Marinas #include <linux/profile.h> 2808e875c1SCatalin Marinas #include <linux/errno.h> 2908e875c1SCatalin Marinas #include <linux/mm.h> 3008e875c1SCatalin Marinas #include <linux/err.h> 3108e875c1SCatalin Marinas #include <linux/cpu.h> 3208e875c1SCatalin Marinas #include <linux/smp.h> 3308e875c1SCatalin Marinas #include <linux/seq_file.h> 3408e875c1SCatalin Marinas #include <linux/irq.h> 3508e875c1SCatalin Marinas #include <linux/percpu.h> 3608e875c1SCatalin Marinas #include <linux/clockchips.h> 3708e875c1SCatalin Marinas #include <linux/completion.h> 3808e875c1SCatalin Marinas #include <linux/of.h> 39eb631bb5SLarry Bassel #include <linux/irq_work.h> 4008e875c1SCatalin Marinas 41e039ee4eSAndre Przywara #include <asm/alternative.h> 4208e875c1SCatalin Marinas #include <asm/atomic.h> 4308e875c1SCatalin Marinas #include <asm/cacheflush.h> 44df857416SMark Rutland #include <asm/cpu.h> 4508e875c1SCatalin Marinas #include <asm/cputype.h> 46cd1aebf5SMark Rutland #include <asm/cpu_ops.h> 4708e875c1SCatalin Marinas #include <asm/mmu_context.h> 481a2db300SGanapatrao Kulkarni #include <asm/numa.h> 4908e875c1SCatalin Marinas #include <asm/pgtable.h> 5008e875c1SCatalin Marinas #include <asm/pgalloc.h> 5108e875c1SCatalin Marinas #include <asm/processor.h> 524c7aa002SJavi Merino #include <asm/smp_plat.h> 5308e875c1SCatalin Marinas #include <asm/sections.h> 5408e875c1SCatalin Marinas #include <asm/tlbflush.h> 5508e875c1SCatalin Marinas #include <asm/ptrace.h> 56377bcff9SJonas Rabenstein #include <asm/virt.h> 5708e875c1SCatalin Marinas 5845ed695aSNicolas Pitre #define CREATE_TRACE_POINTS 5945ed695aSNicolas Pitre #include <trace/events/ipi.h> 6045ed695aSNicolas Pitre 61*57c82954SMark Rutland DEFINE_PER_CPU_READ_MOSTLY(int, cpu_number); 62*57c82954SMark Rutland EXPORT_PER_CPU_SYMBOL(cpu_number); 63*57c82954SMark Rutland 6408e875c1SCatalin Marinas /* 6508e875c1SCatalin Marinas * as from 2.5, kernels no longer have an init_tasks structure 6608e875c1SCatalin Marinas * so we need some other way of telling a new secondary core 6708e875c1SCatalin Marinas * where to place its SVC stack 6808e875c1SCatalin Marinas */ 6908e875c1SCatalin Marinas struct secondary_data secondary_data; 70bb905274SSuzuki K Poulose /* Number of CPUs which aren't online, but looping in kernel text. */ 71bb905274SSuzuki K Poulose int cpus_stuck_in_kernel; 7208e875c1SCatalin Marinas 7308e875c1SCatalin Marinas enum ipi_msg_type { 7408e875c1SCatalin Marinas IPI_RESCHEDULE, 7508e875c1SCatalin Marinas IPI_CALL_FUNC, 7608e875c1SCatalin Marinas IPI_CPU_STOP, 771f85008eSLorenzo Pieralisi IPI_TIMER, 78eb631bb5SLarry Bassel IPI_IRQ_WORK, 795e89c55eSLorenzo Pieralisi IPI_WAKEUP 8008e875c1SCatalin Marinas }; 8108e875c1SCatalin Marinas 82ac1ad20fSSuzuki K Poulose #ifdef CONFIG_ARM64_VHE 83ac1ad20fSSuzuki K Poulose 84ac1ad20fSSuzuki K Poulose /* Whether the boot CPU is running in HYP mode or not*/ 85ac1ad20fSSuzuki K Poulose static bool boot_cpu_hyp_mode; 86ac1ad20fSSuzuki K Poulose 87ac1ad20fSSuzuki K Poulose static inline void save_boot_cpu_run_el(void) 88ac1ad20fSSuzuki K Poulose { 89ac1ad20fSSuzuki K Poulose boot_cpu_hyp_mode = is_kernel_in_hyp_mode(); 90ac1ad20fSSuzuki K Poulose } 91ac1ad20fSSuzuki K Poulose 92ac1ad20fSSuzuki K Poulose static inline bool is_boot_cpu_in_hyp_mode(void) 93ac1ad20fSSuzuki K Poulose { 94ac1ad20fSSuzuki K Poulose return boot_cpu_hyp_mode; 95ac1ad20fSSuzuki K Poulose } 96ac1ad20fSSuzuki K Poulose 97ac1ad20fSSuzuki K Poulose /* 98ac1ad20fSSuzuki K Poulose * Verify that a secondary CPU is running the kernel at the same 99ac1ad20fSSuzuki K Poulose * EL as that of the boot CPU. 100ac1ad20fSSuzuki K Poulose */ 101ac1ad20fSSuzuki K Poulose void verify_cpu_run_el(void) 102ac1ad20fSSuzuki K Poulose { 103ac1ad20fSSuzuki K Poulose bool in_el2 = is_kernel_in_hyp_mode(); 104ac1ad20fSSuzuki K Poulose bool boot_cpu_el2 = is_boot_cpu_in_hyp_mode(); 105ac1ad20fSSuzuki K Poulose 106ac1ad20fSSuzuki K Poulose if (in_el2 ^ boot_cpu_el2) { 107ac1ad20fSSuzuki K Poulose pr_crit("CPU%d: mismatched Exception Level(EL%d) with boot CPU(EL%d)\n", 108ac1ad20fSSuzuki K Poulose smp_processor_id(), 109ac1ad20fSSuzuki K Poulose in_el2 ? 2 : 1, 110ac1ad20fSSuzuki K Poulose boot_cpu_el2 ? 2 : 1); 111ac1ad20fSSuzuki K Poulose cpu_panic_kernel(); 112ac1ad20fSSuzuki K Poulose } 113ac1ad20fSSuzuki K Poulose } 114ac1ad20fSSuzuki K Poulose 115ac1ad20fSSuzuki K Poulose #else 116ac1ad20fSSuzuki K Poulose static inline void save_boot_cpu_run_el(void) {} 117ac1ad20fSSuzuki K Poulose #endif 118ac1ad20fSSuzuki K Poulose 119bb905274SSuzuki K Poulose #ifdef CONFIG_HOTPLUG_CPU 120bb905274SSuzuki K Poulose static int op_cpu_kill(unsigned int cpu); 121bb905274SSuzuki K Poulose #else 122bb905274SSuzuki K Poulose static inline int op_cpu_kill(unsigned int cpu) 123bb905274SSuzuki K Poulose { 124bb905274SSuzuki K Poulose return -ENOSYS; 125bb905274SSuzuki K Poulose } 126bb905274SSuzuki K Poulose #endif 127bb905274SSuzuki K Poulose 128bb905274SSuzuki K Poulose 12908e875c1SCatalin Marinas /* 13008e875c1SCatalin Marinas * Boot a secondary CPU, and assign it the specified idle task. 13108e875c1SCatalin Marinas * This also gives us the initial stack to use for this CPU. 13208e875c1SCatalin Marinas */ 133b8c6453aSPaul Gortmaker static int boot_secondary(unsigned int cpu, struct task_struct *idle) 13408e875c1SCatalin Marinas { 135652af899SMark Rutland if (cpu_ops[cpu]->cpu_boot) 136652af899SMark Rutland return cpu_ops[cpu]->cpu_boot(cpu); 13708e875c1SCatalin Marinas 138652af899SMark Rutland return -EOPNOTSUPP; 13908e875c1SCatalin Marinas } 14008e875c1SCatalin Marinas 14108e875c1SCatalin Marinas static DECLARE_COMPLETION(cpu_running); 14208e875c1SCatalin Marinas 143b8c6453aSPaul Gortmaker int __cpu_up(unsigned int cpu, struct task_struct *idle) 14408e875c1SCatalin Marinas { 14508e875c1SCatalin Marinas int ret; 146bb905274SSuzuki K Poulose long status; 14708e875c1SCatalin Marinas 14808e875c1SCatalin Marinas /* 14908e875c1SCatalin Marinas * We need to tell the secondary core where to find its stack and the 15008e875c1SCatalin Marinas * page tables. 15108e875c1SCatalin Marinas */ 15208e875c1SCatalin Marinas secondary_data.stack = task_stack_page(idle) + THREAD_START_SP; 153bb905274SSuzuki K Poulose update_cpu_boot_status(CPU_MMU_OFF); 15408e875c1SCatalin Marinas __flush_dcache_area(&secondary_data, sizeof(secondary_data)); 15508e875c1SCatalin Marinas 15608e875c1SCatalin Marinas /* 15708e875c1SCatalin Marinas * Now bring the CPU into our world. 15808e875c1SCatalin Marinas */ 15908e875c1SCatalin Marinas ret = boot_secondary(cpu, idle); 16008e875c1SCatalin Marinas if (ret == 0) { 16108e875c1SCatalin Marinas /* 16208e875c1SCatalin Marinas * CPU was successfully started, wait for it to come online or 16308e875c1SCatalin Marinas * time out. 16408e875c1SCatalin Marinas */ 16508e875c1SCatalin Marinas wait_for_completion_timeout(&cpu_running, 16608e875c1SCatalin Marinas msecs_to_jiffies(1000)); 16708e875c1SCatalin Marinas 16808e875c1SCatalin Marinas if (!cpu_online(cpu)) { 16908e875c1SCatalin Marinas pr_crit("CPU%u: failed to come online\n", cpu); 17008e875c1SCatalin Marinas ret = -EIO; 17108e875c1SCatalin Marinas } 17208e875c1SCatalin Marinas } else { 17308e875c1SCatalin Marinas pr_err("CPU%u: failed to boot: %d\n", cpu, ret); 17408e875c1SCatalin Marinas } 17508e875c1SCatalin Marinas 17608e875c1SCatalin Marinas secondary_data.stack = NULL; 177bb905274SSuzuki K Poulose status = READ_ONCE(secondary_data.status); 178bb905274SSuzuki K Poulose if (ret && status) { 179bb905274SSuzuki K Poulose 180bb905274SSuzuki K Poulose if (status == CPU_MMU_OFF) 181bb905274SSuzuki K Poulose status = READ_ONCE(__early_cpu_boot_status); 182bb905274SSuzuki K Poulose 183bb905274SSuzuki K Poulose switch (status) { 184bb905274SSuzuki K Poulose default: 185bb905274SSuzuki K Poulose pr_err("CPU%u: failed in unknown state : 0x%lx\n", 186bb905274SSuzuki K Poulose cpu, status); 187bb905274SSuzuki K Poulose break; 188bb905274SSuzuki K Poulose case CPU_KILL_ME: 189bb905274SSuzuki K Poulose if (!op_cpu_kill(cpu)) { 190bb905274SSuzuki K Poulose pr_crit("CPU%u: died during early boot\n", cpu); 191bb905274SSuzuki K Poulose break; 192bb905274SSuzuki K Poulose } 193bb905274SSuzuki K Poulose /* Fall through */ 194bb905274SSuzuki K Poulose pr_crit("CPU%u: may not have shut down cleanly\n", cpu); 195bb905274SSuzuki K Poulose case CPU_STUCK_IN_KERNEL: 196bb905274SSuzuki K Poulose pr_crit("CPU%u: is stuck in kernel\n", cpu); 197bb905274SSuzuki K Poulose cpus_stuck_in_kernel++; 198bb905274SSuzuki K Poulose break; 199bb905274SSuzuki K Poulose case CPU_PANIC_KERNEL: 200bb905274SSuzuki K Poulose panic("CPU%u detected unsupported configuration\n", cpu); 201bb905274SSuzuki K Poulose } 202bb905274SSuzuki K Poulose } 20308e875c1SCatalin Marinas 20408e875c1SCatalin Marinas return ret; 20508e875c1SCatalin Marinas } 20608e875c1SCatalin Marinas 20708e875c1SCatalin Marinas /* 20808e875c1SCatalin Marinas * This is the secondary CPU boot entry. We're using this CPUs 20908e875c1SCatalin Marinas * idle thread stack, but a set of temporary page tables. 21008e875c1SCatalin Marinas */ 211b8c6453aSPaul Gortmaker asmlinkage void secondary_start_kernel(void) 21208e875c1SCatalin Marinas { 21308e875c1SCatalin Marinas struct mm_struct *mm = &init_mm; 214580efaa7SMark Rutland unsigned int cpu; 215580efaa7SMark Rutland 216580efaa7SMark Rutland cpu = task_cpu(current); 217580efaa7SMark Rutland set_my_cpu_offset(per_cpu_offset(cpu)); 21808e875c1SCatalin Marinas 21908e875c1SCatalin Marinas /* 22008e875c1SCatalin Marinas * All kernel threads share the same mm context; grab a 22108e875c1SCatalin Marinas * reference and switch to it. 22208e875c1SCatalin Marinas */ 22308e875c1SCatalin Marinas atomic_inc(&mm->mm_count); 22408e875c1SCatalin Marinas current->active_mm = mm; 22508e875c1SCatalin Marinas 22608e875c1SCatalin Marinas /* 22708e875c1SCatalin Marinas * TTBR0 is only used for the identity mapping at this stage. Make it 22808e875c1SCatalin Marinas * point to zero page to avoid speculatively fetching new entries. 22908e875c1SCatalin Marinas */ 2309e8e865bSMark Rutland cpu_uninstall_idmap(); 23108e875c1SCatalin Marinas 23208e875c1SCatalin Marinas preempt_disable(); 23308e875c1SCatalin Marinas trace_hardirqs_off(); 23408e875c1SCatalin Marinas 235dbb4e152SSuzuki K. Poulose /* 236dbb4e152SSuzuki K. Poulose * If the system has established the capabilities, make sure 237dbb4e152SSuzuki K. Poulose * this CPU ticks all of those. If it doesn't, the CPU will 238dbb4e152SSuzuki K. Poulose * fail to come online. 239dbb4e152SSuzuki K. Poulose */ 240c47a1900SSuzuki K Poulose check_local_cpu_capabilities(); 241dbb4e152SSuzuki K. Poulose 242652af899SMark Rutland if (cpu_ops[cpu]->cpu_postboot) 243652af899SMark Rutland cpu_ops[cpu]->cpu_postboot(); 24408e875c1SCatalin Marinas 24508e875c1SCatalin Marinas /* 246df857416SMark Rutland * Log the CPU info before it is marked online and might get read. 247df857416SMark Rutland */ 248df857416SMark Rutland cpuinfo_store_cpu(); 249df857416SMark Rutland 250df857416SMark Rutland /* 2517ade67b5SMarc Zyngier * Enable GIC and timers. 2527ade67b5SMarc Zyngier */ 2537ade67b5SMarc Zyngier notify_cpu_starting(cpu); 2547ade67b5SMarc Zyngier 255c18df0adSDavid Daney store_cpu_topology(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 */ 26264f17818SSuzuki K. Poulose pr_info("CPU%u: Booted secondary processor [%08x]\n", 26364f17818SSuzuki K. Poulose cpu, read_cpuid_id()); 264bb905274SSuzuki K Poulose update_cpu_boot_status(CPU_BOOT_SUCCESS); 26508e875c1SCatalin Marinas set_cpu_online(cpu, true); 266b3770b32SWill Deacon complete(&cpu_running); 26708e875c1SCatalin Marinas 26853ae3acdSCatalin Marinas local_irq_enable(); 269b3bf6aa7SCatalin Marinas local_async_enable(); 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 3099327e2c6SMark Rutland /* 3109327e2c6SMark Rutland * Take this CPU offline. Once we clear this, we can't return, 3119327e2c6SMark Rutland * and we must not schedule until we're ready to give up the cpu. 3129327e2c6SMark Rutland */ 3139327e2c6SMark Rutland set_cpu_online(cpu, false); 3149327e2c6SMark Rutland 3159327e2c6SMark Rutland /* 3169327e2c6SMark Rutland * OK - migrate IRQs away from this CPU 3179327e2c6SMark Rutland */ 318217d453dSYang Yingliang irq_migrate_all_off_this_cpu(); 319217d453dSYang Yingliang 3209327e2c6SMark Rutland return 0; 3219327e2c6SMark Rutland } 3229327e2c6SMark Rutland 323c814ca02SAshwin Chaugule static int op_cpu_kill(unsigned int cpu) 324c814ca02SAshwin Chaugule { 325c814ca02SAshwin Chaugule /* 326c814ca02SAshwin Chaugule * If we have no means of synchronising with the dying CPU, then assume 327c814ca02SAshwin Chaugule * that it is really dead. We can only wait for an arbitrary length of 328c814ca02SAshwin Chaugule * time and hope that it's dead, so let's skip the wait and just hope. 329c814ca02SAshwin Chaugule */ 330c814ca02SAshwin Chaugule if (!cpu_ops[cpu]->cpu_kill) 3316b99c68cSMark Rutland return 0; 332c814ca02SAshwin Chaugule 333c814ca02SAshwin Chaugule return cpu_ops[cpu]->cpu_kill(cpu); 334c814ca02SAshwin Chaugule } 335c814ca02SAshwin Chaugule 3369327e2c6SMark Rutland /* 3379327e2c6SMark Rutland * called on the thread which is asking for a CPU to be shutdown - 3389327e2c6SMark Rutland * waits until shutdown has completed, or it is timed out. 3399327e2c6SMark Rutland */ 3409327e2c6SMark Rutland void __cpu_die(unsigned int cpu) 3419327e2c6SMark Rutland { 3426b99c68cSMark Rutland int err; 3436b99c68cSMark Rutland 34405981277SPaul E. McKenney if (!cpu_wait_death(cpu, 5)) { 3459327e2c6SMark Rutland pr_crit("CPU%u: cpu didn't die\n", cpu); 3469327e2c6SMark Rutland return; 3479327e2c6SMark Rutland } 3489327e2c6SMark Rutland pr_notice("CPU%u: shutdown\n", cpu); 349c814ca02SAshwin Chaugule 350c814ca02SAshwin Chaugule /* 351c814ca02SAshwin Chaugule * Now that the dying CPU is beyond the point of no return w.r.t. 352c814ca02SAshwin Chaugule * in-kernel synchronisation, try to get the firwmare to help us to 353c814ca02SAshwin Chaugule * verify that it has really left the kernel before we consider 354c814ca02SAshwin Chaugule * clobbering anything it might still be using. 355c814ca02SAshwin Chaugule */ 3566b99c68cSMark Rutland err = op_cpu_kill(cpu); 3576b99c68cSMark Rutland if (err) 3586b99c68cSMark Rutland pr_warn("CPU%d may not have shut down cleanly: %d\n", 3596b99c68cSMark Rutland cpu, err); 3609327e2c6SMark Rutland } 3619327e2c6SMark Rutland 3629327e2c6SMark Rutland /* 3639327e2c6SMark Rutland * Called from the idle thread for the CPU which has been shutdown. 3649327e2c6SMark Rutland * 3659327e2c6SMark Rutland * Note that we disable IRQs here, but do not re-enable them 3669327e2c6SMark Rutland * before returning to the caller. This is also the behaviour 3679327e2c6SMark Rutland * of the other hotplug-cpu capable cores, so presumably coming 3689327e2c6SMark Rutland * out of idle fixes this. 3699327e2c6SMark Rutland */ 3709327e2c6SMark Rutland void cpu_die(void) 3719327e2c6SMark Rutland { 3729327e2c6SMark Rutland unsigned int cpu = smp_processor_id(); 3739327e2c6SMark Rutland 3749327e2c6SMark Rutland idle_task_exit(); 3759327e2c6SMark Rutland 3769327e2c6SMark Rutland local_irq_disable(); 3779327e2c6SMark Rutland 3789327e2c6SMark Rutland /* Tell __cpu_die() that this CPU is now safe to dispose of */ 37905981277SPaul E. McKenney (void)cpu_report_death(); 3809327e2c6SMark Rutland 3819327e2c6SMark Rutland /* 3829327e2c6SMark Rutland * Actually shutdown the CPU. This must never fail. The specific hotplug 3839327e2c6SMark Rutland * mechanism must perform all required cache maintenance to ensure that 3849327e2c6SMark Rutland * no dirty lines are lost in the process of shutting down the CPU. 3859327e2c6SMark Rutland */ 3869327e2c6SMark Rutland cpu_ops[cpu]->cpu_die(cpu); 3879327e2c6SMark Rutland 3889327e2c6SMark Rutland BUG(); 3899327e2c6SMark Rutland } 3909327e2c6SMark Rutland #endif 3919327e2c6SMark Rutland 392fce6361fSSuzuki K Poulose /* 393fce6361fSSuzuki K Poulose * Kill the calling secondary CPU, early in bringup before it is turned 394fce6361fSSuzuki K Poulose * online. 395fce6361fSSuzuki K Poulose */ 396fce6361fSSuzuki K Poulose void cpu_die_early(void) 397fce6361fSSuzuki K Poulose { 398fce6361fSSuzuki K Poulose int cpu = smp_processor_id(); 399fce6361fSSuzuki K Poulose 400fce6361fSSuzuki K Poulose pr_crit("CPU%d: will not boot\n", cpu); 401fce6361fSSuzuki K Poulose 402fce6361fSSuzuki K Poulose /* Mark this CPU absent */ 403fce6361fSSuzuki K Poulose set_cpu_present(cpu, 0); 404fce6361fSSuzuki K Poulose 405fce6361fSSuzuki K Poulose #ifdef CONFIG_HOTPLUG_CPU 406bb905274SSuzuki K Poulose update_cpu_boot_status(CPU_KILL_ME); 407fce6361fSSuzuki K Poulose /* Check if we can park ourselves */ 408fce6361fSSuzuki K Poulose if (cpu_ops[cpu] && cpu_ops[cpu]->cpu_die) 409fce6361fSSuzuki K Poulose cpu_ops[cpu]->cpu_die(cpu); 410fce6361fSSuzuki K Poulose #endif 411bb905274SSuzuki K Poulose update_cpu_boot_status(CPU_STUCK_IN_KERNEL); 412fce6361fSSuzuki K Poulose 413fce6361fSSuzuki K Poulose cpu_park_loop(); 414fce6361fSSuzuki K Poulose } 415fce6361fSSuzuki K Poulose 416377bcff9SJonas Rabenstein static void __init hyp_mode_check(void) 417377bcff9SJonas Rabenstein { 418377bcff9SJonas Rabenstein if (is_hyp_mode_available()) 419377bcff9SJonas Rabenstein pr_info("CPU: All CPU(s) started at EL2\n"); 420377bcff9SJonas Rabenstein else if (is_hyp_mode_mismatched()) 421377bcff9SJonas Rabenstein WARN_TAINT(1, TAINT_CPU_OUT_OF_SPEC, 422377bcff9SJonas Rabenstein "CPU: CPUs started in inconsistent modes"); 423377bcff9SJonas Rabenstein else 424377bcff9SJonas Rabenstein pr_info("CPU: All CPU(s) started at EL1\n"); 425377bcff9SJonas Rabenstein } 426377bcff9SJonas Rabenstein 42708e875c1SCatalin Marinas void __init smp_cpus_done(unsigned int max_cpus) 42808e875c1SCatalin Marinas { 429326b16dbSWill Deacon pr_info("SMP: Total of %d processors activated.\n", num_online_cpus()); 4303a75578eSSuzuki K. Poulose setup_cpu_features(); 431377bcff9SJonas Rabenstein hyp_mode_check(); 432377bcff9SJonas Rabenstein apply_alternatives_all(); 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(); 444ac1ad20fSSuzuki K Poulose save_boot_cpu_run_el(); 445c47a1900SSuzuki K Poulose /* 446c47a1900SSuzuki K Poulose * Run the errata work around checks on the boot CPU, once we have 447c47a1900SSuzuki K Poulose * initialised the cpu feature infrastructure from 448c47a1900SSuzuki K Poulose * cpuinfo_store_boot_cpu() above. 449c47a1900SSuzuki K Poulose */ 450c47a1900SSuzuki K Poulose update_cpu_errata_workarounds(); 45108e875c1SCatalin Marinas } 45208e875c1SCatalin Marinas 4530f078336SLorenzo Pieralisi static u64 __init of_get_cpu_mpidr(struct device_node *dn) 4540f078336SLorenzo Pieralisi { 4550f078336SLorenzo Pieralisi const __be32 *cell; 4560f078336SLorenzo Pieralisi u64 hwid; 4570f078336SLorenzo Pieralisi 4580f078336SLorenzo Pieralisi /* 4590f078336SLorenzo Pieralisi * A cpu node with missing "reg" property is 4600f078336SLorenzo Pieralisi * considered invalid to build a cpu_logical_map 4610f078336SLorenzo Pieralisi * entry. 4620f078336SLorenzo Pieralisi */ 4630f078336SLorenzo Pieralisi cell = of_get_property(dn, "reg", NULL); 4640f078336SLorenzo Pieralisi if (!cell) { 4650f078336SLorenzo Pieralisi pr_err("%s: missing reg property\n", dn->full_name); 4660f078336SLorenzo Pieralisi return INVALID_HWID; 4670f078336SLorenzo Pieralisi } 4680f078336SLorenzo Pieralisi 4690f078336SLorenzo Pieralisi hwid = of_read_number(cell, of_n_addr_cells(dn)); 4700f078336SLorenzo Pieralisi /* 4710f078336SLorenzo Pieralisi * Non affinity bits must be set to 0 in the DT 4720f078336SLorenzo Pieralisi */ 4730f078336SLorenzo Pieralisi if (hwid & ~MPIDR_HWID_BITMASK) { 4740f078336SLorenzo Pieralisi pr_err("%s: invalid reg property\n", dn->full_name); 4750f078336SLorenzo Pieralisi return INVALID_HWID; 4760f078336SLorenzo Pieralisi } 4770f078336SLorenzo Pieralisi return hwid; 4780f078336SLorenzo Pieralisi } 4790f078336SLorenzo Pieralisi 4800f078336SLorenzo Pieralisi /* 4810f078336SLorenzo Pieralisi * Duplicate MPIDRs are a recipe for disaster. Scan all initialized 4820f078336SLorenzo Pieralisi * entries and check for duplicates. If any is found just ignore the 4830f078336SLorenzo Pieralisi * cpu. cpu_logical_map was initialized to INVALID_HWID to avoid 4840f078336SLorenzo Pieralisi * matching valid MPIDR values. 4850f078336SLorenzo Pieralisi */ 4860f078336SLorenzo Pieralisi static bool __init is_mpidr_duplicate(unsigned int cpu, u64 hwid) 4870f078336SLorenzo Pieralisi { 4880f078336SLorenzo Pieralisi unsigned int i; 4890f078336SLorenzo Pieralisi 4900f078336SLorenzo Pieralisi for (i = 1; (i < cpu) && (i < NR_CPUS); i++) 4910f078336SLorenzo Pieralisi if (cpu_logical_map(i) == hwid) 4920f078336SLorenzo Pieralisi return true; 4930f078336SLorenzo Pieralisi return false; 4940f078336SLorenzo Pieralisi } 4950f078336SLorenzo Pieralisi 49608e875c1SCatalin Marinas /* 497819a8826SLorenzo Pieralisi * Initialize cpu operations for a logical cpu and 498819a8826SLorenzo Pieralisi * set it in the possible mask on success 499819a8826SLorenzo Pieralisi */ 500819a8826SLorenzo Pieralisi static int __init smp_cpu_setup(int cpu) 501819a8826SLorenzo Pieralisi { 502819a8826SLorenzo Pieralisi if (cpu_read_ops(cpu)) 503819a8826SLorenzo Pieralisi return -ENODEV; 504819a8826SLorenzo Pieralisi 505819a8826SLorenzo Pieralisi if (cpu_ops[cpu]->cpu_init(cpu)) 506819a8826SLorenzo Pieralisi return -ENODEV; 507819a8826SLorenzo Pieralisi 508819a8826SLorenzo Pieralisi set_cpu_possible(cpu, true); 509819a8826SLorenzo Pieralisi 510819a8826SLorenzo Pieralisi return 0; 511819a8826SLorenzo Pieralisi } 512819a8826SLorenzo Pieralisi 5130f078336SLorenzo Pieralisi static bool bootcpu_valid __initdata; 5140f078336SLorenzo Pieralisi static unsigned int cpu_count = 1; 5150f078336SLorenzo Pieralisi 5160f078336SLorenzo Pieralisi #ifdef CONFIG_ACPI 5170f078336SLorenzo Pieralisi /* 5180f078336SLorenzo Pieralisi * acpi_map_gic_cpu_interface - parse processor MADT entry 5190f078336SLorenzo Pieralisi * 5200f078336SLorenzo Pieralisi * Carry out sanity checks on MADT processor entry and initialize 5210f078336SLorenzo Pieralisi * cpu_logical_map on success 5220f078336SLorenzo Pieralisi */ 5230f078336SLorenzo Pieralisi static void __init 5240f078336SLorenzo Pieralisi acpi_map_gic_cpu_interface(struct acpi_madt_generic_interrupt *processor) 5250f078336SLorenzo Pieralisi { 5260f078336SLorenzo Pieralisi u64 hwid = processor->arm_mpidr; 5270f078336SLorenzo Pieralisi 528f9058929SHanjun Guo if (!(processor->flags & ACPI_MADT_ENABLED)) { 529f9058929SHanjun Guo pr_debug("skipping disabled CPU entry with 0x%llx MPIDR\n", hwid); 5300f078336SLorenzo Pieralisi return; 5310f078336SLorenzo Pieralisi } 5320f078336SLorenzo Pieralisi 533f9058929SHanjun Guo if (hwid & ~MPIDR_HWID_BITMASK || hwid == INVALID_HWID) { 534f9058929SHanjun Guo pr_err("skipping CPU entry with invalid MPIDR 0x%llx\n", hwid); 5350f078336SLorenzo Pieralisi return; 5360f078336SLorenzo Pieralisi } 5370f078336SLorenzo Pieralisi 5380f078336SLorenzo Pieralisi if (is_mpidr_duplicate(cpu_count, hwid)) { 5390f078336SLorenzo Pieralisi pr_err("duplicate CPU MPIDR 0x%llx in MADT\n", hwid); 5400f078336SLorenzo Pieralisi return; 5410f078336SLorenzo Pieralisi } 5420f078336SLorenzo Pieralisi 5430f078336SLorenzo Pieralisi /* Check if GICC structure of boot CPU is available in the MADT */ 5440f078336SLorenzo Pieralisi if (cpu_logical_map(0) == hwid) { 5450f078336SLorenzo Pieralisi if (bootcpu_valid) { 5460f078336SLorenzo Pieralisi pr_err("duplicate boot CPU MPIDR: 0x%llx in MADT\n", 5470f078336SLorenzo Pieralisi hwid); 5480f078336SLorenzo Pieralisi return; 5490f078336SLorenzo Pieralisi } 5500f078336SLorenzo Pieralisi bootcpu_valid = true; 551baa5567cSLorenzo Pieralisi early_map_cpu_to_node(0, acpi_numa_get_nid(0, hwid)); 5520f078336SLorenzo Pieralisi return; 5530f078336SLorenzo Pieralisi } 5540f078336SLorenzo Pieralisi 5550f078336SLorenzo Pieralisi if (cpu_count >= NR_CPUS) 5560f078336SLorenzo Pieralisi return; 5570f078336SLorenzo Pieralisi 5580f078336SLorenzo Pieralisi /* map the logical cpu id to cpu MPIDR */ 5590f078336SLorenzo Pieralisi cpu_logical_map(cpu_count) = hwid; 5600f078336SLorenzo Pieralisi 5615e89c55eSLorenzo Pieralisi /* 5625e89c55eSLorenzo Pieralisi * Set-up the ACPI parking protocol cpu entries 5635e89c55eSLorenzo Pieralisi * while initializing the cpu_logical_map to 5645e89c55eSLorenzo Pieralisi * avoid parsing MADT entries multiple times for 5655e89c55eSLorenzo Pieralisi * nothing (ie a valid cpu_logical_map entry should 5665e89c55eSLorenzo Pieralisi * contain a valid parking protocol data set to 5675e89c55eSLorenzo Pieralisi * initialize the cpu if the parking protocol is 5685e89c55eSLorenzo Pieralisi * the only available enable method). 5695e89c55eSLorenzo Pieralisi */ 5705e89c55eSLorenzo Pieralisi acpi_set_mailbox_entry(cpu_count, processor); 5715e89c55eSLorenzo Pieralisi 572d8b47fcaSHanjun Guo early_map_cpu_to_node(cpu_count, acpi_numa_get_nid(cpu_count, hwid)); 573d8b47fcaSHanjun Guo 5740f078336SLorenzo Pieralisi cpu_count++; 5750f078336SLorenzo Pieralisi } 5760f078336SLorenzo Pieralisi 5770f078336SLorenzo Pieralisi static int __init 5780f078336SLorenzo Pieralisi acpi_parse_gic_cpu_interface(struct acpi_subtable_header *header, 5790f078336SLorenzo Pieralisi const unsigned long end) 5800f078336SLorenzo Pieralisi { 5810f078336SLorenzo Pieralisi struct acpi_madt_generic_interrupt *processor; 5820f078336SLorenzo Pieralisi 5830f078336SLorenzo Pieralisi processor = (struct acpi_madt_generic_interrupt *)header; 58499e3e3aeSAl Stone if (BAD_MADT_GICC_ENTRY(processor, end)) 5850f078336SLorenzo Pieralisi return -EINVAL; 5860f078336SLorenzo Pieralisi 5870f078336SLorenzo Pieralisi acpi_table_print_madt_entry(header); 5880f078336SLorenzo Pieralisi 5890f078336SLorenzo Pieralisi acpi_map_gic_cpu_interface(processor); 5900f078336SLorenzo Pieralisi 5910f078336SLorenzo Pieralisi return 0; 5920f078336SLorenzo Pieralisi } 5930f078336SLorenzo Pieralisi #else 5940f078336SLorenzo Pieralisi #define acpi_table_parse_madt(...) do { } while (0) 5950f078336SLorenzo Pieralisi #endif 5960f078336SLorenzo Pieralisi 597819a8826SLorenzo Pieralisi /* 5984c7aa002SJavi Merino * Enumerate the possible CPU set from the device tree and build the 5994c7aa002SJavi Merino * cpu logical map array containing MPIDR values related to logical 6004c7aa002SJavi Merino * cpus. Assumes that cpu_logical_map(0) has already been initialized. 60108e875c1SCatalin Marinas */ 60229b8302bSJisheng Zhang static void __init of_parse_and_init_cpus(void) 60308e875c1SCatalin Marinas { 60408e875c1SCatalin Marinas struct device_node *dn = NULL; 60508e875c1SCatalin Marinas 60608e875c1SCatalin Marinas while ((dn = of_find_node_by_type(dn, "cpu"))) { 6070f078336SLorenzo Pieralisi u64 hwid = of_get_cpu_mpidr(dn); 6084c7aa002SJavi Merino 6090f078336SLorenzo Pieralisi if (hwid == INVALID_HWID) 6104c7aa002SJavi Merino goto next; 6114c7aa002SJavi Merino 6120f078336SLorenzo Pieralisi if (is_mpidr_duplicate(cpu_count, hwid)) { 6134c7aa002SJavi Merino pr_err("%s: duplicate cpu reg properties in the DT\n", 6144c7aa002SJavi Merino dn->full_name); 6154c7aa002SJavi Merino goto next; 6164c7aa002SJavi Merino } 6174c7aa002SJavi Merino 6184c7aa002SJavi Merino /* 6194c7aa002SJavi Merino * The numbering scheme requires that the boot CPU 6204c7aa002SJavi Merino * must be assigned logical id 0. Record it so that 6214c7aa002SJavi Merino * the logical map built from DT is validated and can 6224c7aa002SJavi Merino * be used. 6234c7aa002SJavi Merino */ 6244c7aa002SJavi Merino if (hwid == cpu_logical_map(0)) { 6254c7aa002SJavi Merino if (bootcpu_valid) { 6264c7aa002SJavi Merino pr_err("%s: duplicate boot cpu reg property in DT\n", 6274c7aa002SJavi Merino dn->full_name); 6284c7aa002SJavi Merino goto next; 6294c7aa002SJavi Merino } 6304c7aa002SJavi Merino 6314c7aa002SJavi Merino bootcpu_valid = true; 6327ba5f605SZhen Lei early_map_cpu_to_node(0, of_node_to_nid(dn)); 6334c7aa002SJavi Merino 6344c7aa002SJavi Merino /* 6354c7aa002SJavi Merino * cpu_logical_map has already been 6364c7aa002SJavi Merino * initialized and the boot cpu doesn't need 6374c7aa002SJavi Merino * the enable-method so continue without 6384c7aa002SJavi Merino * incrementing cpu. 6394c7aa002SJavi Merino */ 6404c7aa002SJavi Merino continue; 6414c7aa002SJavi Merino } 6424c7aa002SJavi Merino 6430f078336SLorenzo Pieralisi if (cpu_count >= NR_CPUS) 64408e875c1SCatalin Marinas goto next; 64508e875c1SCatalin Marinas 6464c7aa002SJavi Merino pr_debug("cpu logical map 0x%llx\n", hwid); 6470f078336SLorenzo Pieralisi cpu_logical_map(cpu_count) = hwid; 6481a2db300SGanapatrao Kulkarni 6491a2db300SGanapatrao Kulkarni early_map_cpu_to_node(cpu_count, of_node_to_nid(dn)); 65008e875c1SCatalin Marinas next: 6510f078336SLorenzo Pieralisi cpu_count++; 6520f078336SLorenzo Pieralisi } 65308e875c1SCatalin Marinas } 65408e875c1SCatalin Marinas 6550f078336SLorenzo Pieralisi /* 6560f078336SLorenzo Pieralisi * Enumerate the possible CPU set from the device tree or ACPI and build the 6570f078336SLorenzo Pieralisi * cpu logical map array containing MPIDR values related to logical 6580f078336SLorenzo Pieralisi * cpus. Assumes that cpu_logical_map(0) has already been initialized. 6590f078336SLorenzo Pieralisi */ 6600f078336SLorenzo Pieralisi void __init smp_init_cpus(void) 6610f078336SLorenzo Pieralisi { 6620f078336SLorenzo Pieralisi int i; 6630f078336SLorenzo Pieralisi 6640f078336SLorenzo Pieralisi if (acpi_disabled) 6650f078336SLorenzo Pieralisi of_parse_and_init_cpus(); 6660f078336SLorenzo Pieralisi else 6670f078336SLorenzo Pieralisi /* 6680f078336SLorenzo Pieralisi * do a walk of MADT to determine how many CPUs 6690f078336SLorenzo Pieralisi * we have including disabled CPUs, and get information 6700f078336SLorenzo Pieralisi * we need for SMP init 6710f078336SLorenzo Pieralisi */ 6720f078336SLorenzo Pieralisi acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_INTERRUPT, 6730f078336SLorenzo Pieralisi acpi_parse_gic_cpu_interface, 0); 6740f078336SLorenzo Pieralisi 67550ee91bdSKefeng Wang if (cpu_count > nr_cpu_ids) 67650ee91bdSKefeng Wang pr_warn("Number of cores (%d) exceeds configured maximum of %d - clipping\n", 67750ee91bdSKefeng Wang cpu_count, nr_cpu_ids); 6784c7aa002SJavi Merino 6794c7aa002SJavi Merino if (!bootcpu_valid) { 6800f078336SLorenzo Pieralisi pr_err("missing boot CPU MPIDR, not enabling secondaries\n"); 6814c7aa002SJavi Merino return; 6824c7aa002SJavi Merino } 6834c7aa002SJavi Merino 6844c7aa002SJavi Merino /* 685819a8826SLorenzo Pieralisi * We need to set the cpu_logical_map entries before enabling 686819a8826SLorenzo Pieralisi * the cpus so that cpu processor description entries (DT cpu nodes 687819a8826SLorenzo Pieralisi * and ACPI MADT entries) can be retrieved by matching the cpu hwid 688819a8826SLorenzo Pieralisi * with entries in cpu_logical_map while initializing the cpus. 689819a8826SLorenzo Pieralisi * If the cpu set-up fails, invalidate the cpu_logical_map entry. 6904c7aa002SJavi Merino */ 69150ee91bdSKefeng Wang for (i = 1; i < nr_cpu_ids; i++) { 692819a8826SLorenzo Pieralisi if (cpu_logical_map(i) != INVALID_HWID) { 693819a8826SLorenzo Pieralisi if (smp_cpu_setup(i)) 694819a8826SLorenzo Pieralisi cpu_logical_map(i) = INVALID_HWID; 695819a8826SLorenzo Pieralisi } 696819a8826SLorenzo Pieralisi } 69708e875c1SCatalin Marinas } 69808e875c1SCatalin Marinas 69908e875c1SCatalin Marinas void __init smp_prepare_cpus(unsigned int max_cpus) 70008e875c1SCatalin Marinas { 701cd1aebf5SMark Rutland int err; 70244dbcc93SSuzuki K Poulose unsigned int cpu; 703c18df0adSDavid Daney unsigned int this_cpu; 70408e875c1SCatalin Marinas 705f6e763b9SMark Brown init_cpu_topology(); 706f6e763b9SMark Brown 707c18df0adSDavid Daney this_cpu = smp_processor_id(); 708c18df0adSDavid Daney store_cpu_topology(this_cpu); 709c18df0adSDavid Daney numa_store_cpu_info(this_cpu); 710f6e763b9SMark Brown 71108e875c1SCatalin Marinas /* 712e75118a7SSuzuki K Poulose * If UP is mandated by "nosmp" (which implies "maxcpus=0"), don't set 713e75118a7SSuzuki K Poulose * secondary CPUs present. 714e75118a7SSuzuki K Poulose */ 715e75118a7SSuzuki K Poulose if (max_cpus == 0) 716e75118a7SSuzuki K Poulose return; 717e75118a7SSuzuki K Poulose 718e75118a7SSuzuki K Poulose /* 71908e875c1SCatalin Marinas * Initialise the present map (which describes the set of CPUs 72008e875c1SCatalin Marinas * actually populated at the present time) and release the 72108e875c1SCatalin Marinas * secondaries from the bootloader. 72208e875c1SCatalin Marinas */ 72308e875c1SCatalin Marinas for_each_possible_cpu(cpu) { 72408e875c1SCatalin Marinas 725*57c82954SMark Rutland per_cpu(cpu_number, cpu) = cpu; 726*57c82954SMark Rutland 727d329de3fSMarc Zyngier if (cpu == smp_processor_id()) 72808e875c1SCatalin Marinas continue; 72908e875c1SCatalin Marinas 730cd1aebf5SMark Rutland if (!cpu_ops[cpu]) 731d329de3fSMarc Zyngier continue; 732d329de3fSMarc Zyngier 733cd1aebf5SMark Rutland err = cpu_ops[cpu]->cpu_prepare(cpu); 734d329de3fSMarc Zyngier if (err) 735d329de3fSMarc Zyngier continue; 73608e875c1SCatalin Marinas 73708e875c1SCatalin Marinas set_cpu_present(cpu, true); 738c18df0adSDavid Daney numa_store_cpu_info(cpu); 73908e875c1SCatalin Marinas } 74008e875c1SCatalin Marinas } 74108e875c1SCatalin Marinas 74236310736SFrederic Weisbecker void (*__smp_cross_call)(const struct cpumask *, unsigned int); 74308e875c1SCatalin Marinas 74408e875c1SCatalin Marinas void __init set_smp_cross_call(void (*fn)(const struct cpumask *, unsigned int)) 74508e875c1SCatalin Marinas { 74645ed695aSNicolas Pitre __smp_cross_call = fn; 74708e875c1SCatalin Marinas } 74808e875c1SCatalin Marinas 74945ed695aSNicolas Pitre static const char *ipi_types[NR_IPI] __tracepoint_string = { 75045ed695aSNicolas Pitre #define S(x,s) [x] = s 75108e875c1SCatalin Marinas S(IPI_RESCHEDULE, "Rescheduling interrupts"), 75208e875c1SCatalin Marinas S(IPI_CALL_FUNC, "Function call interrupts"), 75308e875c1SCatalin Marinas S(IPI_CPU_STOP, "CPU stop interrupts"), 7541f85008eSLorenzo Pieralisi S(IPI_TIMER, "Timer broadcast interrupts"), 755eb631bb5SLarry Bassel S(IPI_IRQ_WORK, "IRQ work interrupts"), 7565e89c55eSLorenzo Pieralisi S(IPI_WAKEUP, "CPU wake-up interrupts"), 75708e875c1SCatalin Marinas }; 75808e875c1SCatalin Marinas 75945ed695aSNicolas Pitre static void smp_cross_call(const struct cpumask *target, unsigned int ipinr) 76045ed695aSNicolas Pitre { 76145ed695aSNicolas Pitre trace_ipi_raise(target, ipi_types[ipinr]); 76245ed695aSNicolas Pitre __smp_cross_call(target, ipinr); 76345ed695aSNicolas Pitre } 76445ed695aSNicolas Pitre 76508e875c1SCatalin Marinas void show_ipi_list(struct seq_file *p, int prec) 76608e875c1SCatalin Marinas { 76708e875c1SCatalin Marinas unsigned int cpu, i; 76808e875c1SCatalin Marinas 76908e875c1SCatalin Marinas for (i = 0; i < NR_IPI; i++) { 77045ed695aSNicolas Pitre seq_printf(p, "%*s%u:%s", prec - 1, "IPI", i, 77108e875c1SCatalin Marinas prec >= 4 ? " " : ""); 77267317c26SSudeep KarkadaNagesha for_each_online_cpu(cpu) 77308e875c1SCatalin Marinas seq_printf(p, "%10u ", 77408e875c1SCatalin Marinas __get_irq_stat(cpu, ipi_irqs[i])); 77508e875c1SCatalin Marinas seq_printf(p, " %s\n", ipi_types[i]); 77608e875c1SCatalin Marinas } 77708e875c1SCatalin Marinas } 77808e875c1SCatalin Marinas 77908e875c1SCatalin Marinas u64 smp_irq_stat_cpu(unsigned int cpu) 78008e875c1SCatalin Marinas { 78108e875c1SCatalin Marinas u64 sum = 0; 78208e875c1SCatalin Marinas int i; 78308e875c1SCatalin Marinas 78408e875c1SCatalin Marinas for (i = 0; i < NR_IPI; i++) 78508e875c1SCatalin Marinas sum += __get_irq_stat(cpu, ipi_irqs[i]); 78608e875c1SCatalin Marinas 78708e875c1SCatalin Marinas return sum; 78808e875c1SCatalin Marinas } 78908e875c1SCatalin Marinas 79045ed695aSNicolas Pitre void arch_send_call_function_ipi_mask(const struct cpumask *mask) 79145ed695aSNicolas Pitre { 79245ed695aSNicolas Pitre smp_cross_call(mask, IPI_CALL_FUNC); 79345ed695aSNicolas Pitre } 79445ed695aSNicolas Pitre 79545ed695aSNicolas Pitre void arch_send_call_function_single_ipi(int cpu) 79645ed695aSNicolas Pitre { 7970aaf0daeSJiang Liu smp_cross_call(cpumask_of(cpu), IPI_CALL_FUNC); 79845ed695aSNicolas Pitre } 79945ed695aSNicolas Pitre 8005e89c55eSLorenzo Pieralisi #ifdef CONFIG_ARM64_ACPI_PARKING_PROTOCOL 8015e89c55eSLorenzo Pieralisi void arch_send_wakeup_ipi_mask(const struct cpumask *mask) 8025e89c55eSLorenzo Pieralisi { 8035e89c55eSLorenzo Pieralisi smp_cross_call(mask, IPI_WAKEUP); 8045e89c55eSLorenzo Pieralisi } 8055e89c55eSLorenzo Pieralisi #endif 8065e89c55eSLorenzo Pieralisi 80745ed695aSNicolas Pitre #ifdef CONFIG_IRQ_WORK 80845ed695aSNicolas Pitre void arch_irq_work_raise(void) 80945ed695aSNicolas Pitre { 81045ed695aSNicolas Pitre if (__smp_cross_call) 81145ed695aSNicolas Pitre smp_cross_call(cpumask_of(smp_processor_id()), IPI_IRQ_WORK); 81245ed695aSNicolas Pitre } 81345ed695aSNicolas Pitre #endif 81445ed695aSNicolas Pitre 81508e875c1SCatalin Marinas /* 81608e875c1SCatalin Marinas * ipi_cpu_stop - handle IPI from smp_send_stop() 81708e875c1SCatalin Marinas */ 81808e875c1SCatalin Marinas static void ipi_cpu_stop(unsigned int cpu) 81908e875c1SCatalin Marinas { 82008e875c1SCatalin Marinas set_cpu_online(cpu, false); 82108e875c1SCatalin Marinas 82208e875c1SCatalin Marinas local_irq_disable(); 82308e875c1SCatalin Marinas 82408e875c1SCatalin Marinas while (1) 82508e875c1SCatalin Marinas cpu_relax(); 82608e875c1SCatalin Marinas } 82708e875c1SCatalin Marinas 82808e875c1SCatalin Marinas /* 82908e875c1SCatalin Marinas * Main handler for inter-processor interrupts 83008e875c1SCatalin Marinas */ 83108e875c1SCatalin Marinas void handle_IPI(int ipinr, struct pt_regs *regs) 83208e875c1SCatalin Marinas { 83308e875c1SCatalin Marinas unsigned int cpu = smp_processor_id(); 83408e875c1SCatalin Marinas struct pt_regs *old_regs = set_irq_regs(regs); 83508e875c1SCatalin Marinas 83645ed695aSNicolas Pitre if ((unsigned)ipinr < NR_IPI) { 837be081d9bSStephen Boyd trace_ipi_entry_rcuidle(ipi_types[ipinr]); 83845ed695aSNicolas Pitre __inc_irq_stat(cpu, ipi_irqs[ipinr]); 83945ed695aSNicolas Pitre } 84008e875c1SCatalin Marinas 84108e875c1SCatalin Marinas switch (ipinr) { 84208e875c1SCatalin Marinas case IPI_RESCHEDULE: 84308e875c1SCatalin Marinas scheduler_ipi(); 84408e875c1SCatalin Marinas break; 84508e875c1SCatalin Marinas 84608e875c1SCatalin Marinas case IPI_CALL_FUNC: 84708e875c1SCatalin Marinas irq_enter(); 84808e875c1SCatalin Marinas generic_smp_call_function_interrupt(); 84908e875c1SCatalin Marinas irq_exit(); 85008e875c1SCatalin Marinas break; 85108e875c1SCatalin Marinas 85208e875c1SCatalin Marinas case IPI_CPU_STOP: 85308e875c1SCatalin Marinas irq_enter(); 85408e875c1SCatalin Marinas ipi_cpu_stop(cpu); 85508e875c1SCatalin Marinas irq_exit(); 85608e875c1SCatalin Marinas break; 85708e875c1SCatalin Marinas 8581f85008eSLorenzo Pieralisi #ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST 8591f85008eSLorenzo Pieralisi case IPI_TIMER: 8601f85008eSLorenzo Pieralisi irq_enter(); 8611f85008eSLorenzo Pieralisi tick_receive_broadcast(); 8621f85008eSLorenzo Pieralisi irq_exit(); 8631f85008eSLorenzo Pieralisi break; 8641f85008eSLorenzo Pieralisi #endif 8651f85008eSLorenzo Pieralisi 866eb631bb5SLarry Bassel #ifdef CONFIG_IRQ_WORK 867eb631bb5SLarry Bassel case IPI_IRQ_WORK: 868eb631bb5SLarry Bassel irq_enter(); 869eb631bb5SLarry Bassel irq_work_run(); 870eb631bb5SLarry Bassel irq_exit(); 871eb631bb5SLarry Bassel break; 872eb631bb5SLarry Bassel #endif 873eb631bb5SLarry Bassel 8745e89c55eSLorenzo Pieralisi #ifdef CONFIG_ARM64_ACPI_PARKING_PROTOCOL 8755e89c55eSLorenzo Pieralisi case IPI_WAKEUP: 8765e89c55eSLorenzo Pieralisi WARN_ONCE(!acpi_parking_protocol_valid(cpu), 8775e89c55eSLorenzo Pieralisi "CPU%u: Wake-up IPI outside the ACPI parking protocol\n", 8785e89c55eSLorenzo Pieralisi cpu); 8795e89c55eSLorenzo Pieralisi break; 8805e89c55eSLorenzo Pieralisi #endif 8815e89c55eSLorenzo Pieralisi 88208e875c1SCatalin Marinas default: 88308e875c1SCatalin Marinas pr_crit("CPU%u: Unknown IPI message 0x%x\n", cpu, ipinr); 88408e875c1SCatalin Marinas break; 88508e875c1SCatalin Marinas } 88645ed695aSNicolas Pitre 88745ed695aSNicolas Pitre if ((unsigned)ipinr < NR_IPI) 888be081d9bSStephen Boyd trace_ipi_exit_rcuidle(ipi_types[ipinr]); 88908e875c1SCatalin Marinas set_irq_regs(old_regs); 89008e875c1SCatalin Marinas } 89108e875c1SCatalin Marinas 89208e875c1SCatalin Marinas void smp_send_reschedule(int cpu) 89308e875c1SCatalin Marinas { 89408e875c1SCatalin Marinas smp_cross_call(cpumask_of(cpu), IPI_RESCHEDULE); 89508e875c1SCatalin Marinas } 89608e875c1SCatalin Marinas 8971f85008eSLorenzo Pieralisi #ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST 8981f85008eSLorenzo Pieralisi void tick_broadcast(const struct cpumask *mask) 8991f85008eSLorenzo Pieralisi { 9001f85008eSLorenzo Pieralisi smp_cross_call(mask, IPI_TIMER); 9011f85008eSLorenzo Pieralisi } 9021f85008eSLorenzo Pieralisi #endif 9031f85008eSLorenzo Pieralisi 90408e875c1SCatalin Marinas void smp_send_stop(void) 90508e875c1SCatalin Marinas { 90608e875c1SCatalin Marinas unsigned long timeout; 90708e875c1SCatalin Marinas 90808e875c1SCatalin Marinas if (num_online_cpus() > 1) { 90908e875c1SCatalin Marinas cpumask_t mask; 91008e875c1SCatalin Marinas 91108e875c1SCatalin Marinas cpumask_copy(&mask, cpu_online_mask); 912434ed7f4SRusty Russell cpumask_clear_cpu(smp_processor_id(), &mask); 91308e875c1SCatalin Marinas 91482611c14SJan Glauber if (system_state == SYSTEM_BOOTING || 91582611c14SJan Glauber system_state == SYSTEM_RUNNING) 91682611c14SJan Glauber pr_crit("SMP: stopping secondary CPUs\n"); 91708e875c1SCatalin Marinas smp_cross_call(&mask, IPI_CPU_STOP); 91808e875c1SCatalin Marinas } 91908e875c1SCatalin Marinas 92008e875c1SCatalin Marinas /* Wait up to one second for other CPUs to stop */ 92108e875c1SCatalin Marinas timeout = USEC_PER_SEC; 92208e875c1SCatalin Marinas while (num_online_cpus() > 1 && timeout--) 92308e875c1SCatalin Marinas udelay(1); 92408e875c1SCatalin Marinas 92508e875c1SCatalin Marinas if (num_online_cpus() > 1) 92682611c14SJan Glauber pr_warning("SMP: failed to stop secondary CPUs %*pbl\n", 92782611c14SJan Glauber cpumask_pr_args(cpu_online_mask)); 92808e875c1SCatalin Marinas } 92908e875c1SCatalin Marinas 93008e875c1SCatalin Marinas /* 93108e875c1SCatalin Marinas * not supported here 93208e875c1SCatalin Marinas */ 93308e875c1SCatalin Marinas int setup_profiling_timer(unsigned int multiplier) 93408e875c1SCatalin Marinas { 93508e875c1SCatalin Marinas return -EINVAL; 93608e875c1SCatalin Marinas } 9375c492c3fSJames Morse 9385c492c3fSJames Morse static bool have_cpu_die(void) 9395c492c3fSJames Morse { 9405c492c3fSJames Morse #ifdef CONFIG_HOTPLUG_CPU 9415c492c3fSJames Morse int any_cpu = raw_smp_processor_id(); 9425c492c3fSJames Morse 9435c492c3fSJames Morse if (cpu_ops[any_cpu]->cpu_die) 9445c492c3fSJames Morse return true; 9455c492c3fSJames Morse #endif 9465c492c3fSJames Morse return false; 9475c492c3fSJames Morse } 9485c492c3fSJames Morse 9495c492c3fSJames Morse bool cpus_are_stuck_in_kernel(void) 9505c492c3fSJames Morse { 9515c492c3fSJames Morse bool smp_spin_tables = (num_possible_cpus() > 1 && !have_cpu_die()); 9525c492c3fSJames Morse 9535c492c3fSJames Morse return !!cpus_stuck_in_kernel || smp_spin_tables; 9545c492c3fSJames Morse } 955