199106986SGuo Ren // SPDX-License-Identifier: GPL-2.0 299106986SGuo Ren 399106986SGuo Ren #include <linux/module.h> 499106986SGuo Ren #include <linux/init.h> 599106986SGuo Ren #include <linux/kernel.h> 699106986SGuo Ren #include <linux/mm.h> 799106986SGuo Ren #include <linux/sched.h> 899106986SGuo Ren #include <linux/kernel_stat.h> 999106986SGuo Ren #include <linux/notifier.h> 1099106986SGuo Ren #include <linux/cpu.h> 1199106986SGuo Ren #include <linux/percpu.h> 1299106986SGuo Ren #include <linux/delay.h> 1399106986SGuo Ren #include <linux/err.h> 1499106986SGuo Ren #include <linux/irq.h> 1599106986SGuo Ren #include <linux/irqdomain.h> 1699106986SGuo Ren #include <linux/of.h> 1799106986SGuo Ren #include <linux/sched/task_stack.h> 1899106986SGuo Ren #include <linux/sched/mm.h> 19859e5f45SGuo Ren #include <linux/sched/hotplug.h> 2099106986SGuo Ren #include <asm/irq.h> 2199106986SGuo Ren #include <asm/traps.h> 2299106986SGuo Ren #include <asm/sections.h> 2399106986SGuo Ren #include <asm/mmu_context.h> 2499106986SGuo Ren #include <asm/pgalloc.h> 2512879bdaSGuo Ren #ifdef CONFIG_CPU_HAS_FPU 2612879bdaSGuo Ren #include <abi/fpu.h> 2712879bdaSGuo Ren #endif 2899106986SGuo Ren 2999106986SGuo Ren struct ipi_data_struct { 3099106986SGuo Ren unsigned long bits ____cacheline_aligned; 3199106986SGuo Ren }; 3299106986SGuo Ren static DEFINE_PER_CPU(struct ipi_data_struct, ipi_data); 3399106986SGuo Ren 3499106986SGuo Ren enum ipi_message_type { 3599106986SGuo Ren IPI_EMPTY, 3699106986SGuo Ren IPI_RESCHEDULE, 3799106986SGuo Ren IPI_CALL_FUNC, 3899106986SGuo Ren IPI_MAX 3999106986SGuo Ren }; 4099106986SGuo Ren 4199106986SGuo Ren static irqreturn_t handle_ipi(int irq, void *dev) 4299106986SGuo Ren { 4399106986SGuo Ren while (true) { 4499106986SGuo Ren unsigned long ops; 4599106986SGuo Ren 4699106986SGuo Ren ops = xchg(&this_cpu_ptr(&ipi_data)->bits, 0); 4799106986SGuo Ren if (ops == 0) 4899106986SGuo Ren return IRQ_HANDLED; 4999106986SGuo Ren 5099106986SGuo Ren if (ops & (1 << IPI_RESCHEDULE)) 5199106986SGuo Ren scheduler_ipi(); 5299106986SGuo Ren 5399106986SGuo Ren if (ops & (1 << IPI_CALL_FUNC)) 5499106986SGuo Ren generic_smp_call_function_interrupt(); 5599106986SGuo Ren 5699106986SGuo Ren BUG_ON((ops >> IPI_MAX) != 0); 5799106986SGuo Ren } 5899106986SGuo Ren 5999106986SGuo Ren return IRQ_HANDLED; 6099106986SGuo Ren } 6199106986SGuo Ren 6299106986SGuo Ren static void (*send_arch_ipi)(const struct cpumask *mask); 6399106986SGuo Ren 6499106986SGuo Ren static int ipi_irq; 6599106986SGuo Ren void __init set_send_ipi(void (*func)(const struct cpumask *mask), int irq) 6699106986SGuo Ren { 6799106986SGuo Ren if (send_arch_ipi) 6899106986SGuo Ren return; 6999106986SGuo Ren 7099106986SGuo Ren send_arch_ipi = func; 7199106986SGuo Ren ipi_irq = irq; 7299106986SGuo Ren } 7399106986SGuo Ren 7499106986SGuo Ren static void 7599106986SGuo Ren send_ipi_message(const struct cpumask *to_whom, enum ipi_message_type operation) 7699106986SGuo Ren { 7799106986SGuo Ren int i; 7899106986SGuo Ren 7999106986SGuo Ren for_each_cpu(i, to_whom) 8099106986SGuo Ren set_bit(operation, &per_cpu_ptr(&ipi_data, i)->bits); 8199106986SGuo Ren 8299106986SGuo Ren smp_mb(); 8399106986SGuo Ren send_arch_ipi(to_whom); 8499106986SGuo Ren } 8599106986SGuo Ren 8699106986SGuo Ren void arch_send_call_function_ipi_mask(struct cpumask *mask) 8799106986SGuo Ren { 8899106986SGuo Ren send_ipi_message(mask, IPI_CALL_FUNC); 8999106986SGuo Ren } 9099106986SGuo Ren 9199106986SGuo Ren void arch_send_call_function_single_ipi(int cpu) 9299106986SGuo Ren { 9399106986SGuo Ren send_ipi_message(cpumask_of(cpu), IPI_CALL_FUNC); 9499106986SGuo Ren } 9599106986SGuo Ren 9699106986SGuo Ren static void ipi_stop(void *unused) 9799106986SGuo Ren { 9899106986SGuo Ren while (1); 9999106986SGuo Ren } 10099106986SGuo Ren 10199106986SGuo Ren void smp_send_stop(void) 10299106986SGuo Ren { 10399106986SGuo Ren on_each_cpu(ipi_stop, NULL, 1); 10499106986SGuo Ren } 10599106986SGuo Ren 10699106986SGuo Ren void smp_send_reschedule(int cpu) 10799106986SGuo Ren { 10899106986SGuo Ren send_ipi_message(cpumask_of(cpu), IPI_RESCHEDULE); 10999106986SGuo Ren } 11099106986SGuo Ren 11199106986SGuo Ren void __init smp_prepare_boot_cpu(void) 11299106986SGuo Ren { 11399106986SGuo Ren } 11499106986SGuo Ren 11599106986SGuo Ren void __init smp_prepare_cpus(unsigned int max_cpus) 11699106986SGuo Ren { 11799106986SGuo Ren } 11899106986SGuo Ren 11999106986SGuo Ren static int ipi_dummy_dev; 120859e5f45SGuo Ren 12199106986SGuo Ren void __init setup_smp_ipi(void) 12299106986SGuo Ren { 12399106986SGuo Ren int rc; 12499106986SGuo Ren 12599106986SGuo Ren if (ipi_irq == 0) 126c9492737SGuo Ren return; 12799106986SGuo Ren 12899106986SGuo Ren rc = request_percpu_irq(ipi_irq, handle_ipi, "IPI Interrupt", 12999106986SGuo Ren &ipi_dummy_dev); 13099106986SGuo Ren if (rc) 13199106986SGuo Ren panic("%s IRQ request failed\n", __func__); 13299106986SGuo Ren 133859e5f45SGuo Ren enable_percpu_irq(ipi_irq, 0); 13499106986SGuo Ren } 13599106986SGuo Ren 13699106986SGuo Ren void __init setup_smp(void) 13799106986SGuo Ren { 13899106986SGuo Ren struct device_node *node = NULL; 13999106986SGuo Ren int cpu; 14099106986SGuo Ren 141398539ddSYangtao Li for_each_of_cpu_node(node) { 14299106986SGuo Ren if (!of_device_is_available(node)) 14399106986SGuo Ren continue; 14499106986SGuo Ren 14599106986SGuo Ren if (of_property_read_u32(node, "reg", &cpu)) 14699106986SGuo Ren continue; 14799106986SGuo Ren 14899106986SGuo Ren if (cpu >= NR_CPUS) 14999106986SGuo Ren continue; 15099106986SGuo Ren 15199106986SGuo Ren set_cpu_possible(cpu, true); 15299106986SGuo Ren set_cpu_present(cpu, true); 15399106986SGuo Ren } 15499106986SGuo Ren } 15599106986SGuo Ren 15699106986SGuo Ren extern void _start_smp_secondary(void); 15799106986SGuo Ren 15899106986SGuo Ren volatile unsigned int secondary_hint; 15999106986SGuo Ren volatile unsigned int secondary_ccr; 16099106986SGuo Ren volatile unsigned int secondary_stack; 16199106986SGuo Ren 162*aefd9461SGuo Ren unsigned long secondary_msa1; 163*aefd9461SGuo Ren 16499106986SGuo Ren int __cpu_up(unsigned int cpu, struct task_struct *tidle) 16599106986SGuo Ren { 166859e5f45SGuo Ren unsigned long mask = 1 << cpu; 16799106986SGuo Ren 1680f231dcfSGuo Ren secondary_stack = 1690f231dcfSGuo Ren (unsigned int) task_stack_page(tidle) + THREAD_SIZE - 8; 17099106986SGuo Ren secondary_hint = mfcr("cr31"); 17199106986SGuo Ren secondary_ccr = mfcr("cr18"); 172*aefd9461SGuo Ren secondary_msa1 = read_mmu_msa1(); 17399106986SGuo Ren 17499106986SGuo Ren /* 17599106986SGuo Ren * Because other CPUs are in reset status, we must flush data 17699106986SGuo Ren * from cache to out and secondary CPUs use them in 17799106986SGuo Ren * csky_start_secondary(void) 17899106986SGuo Ren */ 17999106986SGuo Ren mtcr("cr17", 0x22); 18099106986SGuo Ren 181859e5f45SGuo Ren if (mask & mfcr("cr<29, 0>")) { 182859e5f45SGuo Ren send_arch_ipi(cpumask_of(cpu)); 183859e5f45SGuo Ren } else { 18499106986SGuo Ren /* Enable cpu in SMP reset ctrl reg */ 185859e5f45SGuo Ren mask |= mfcr("cr<29, 0>"); 186859e5f45SGuo Ren mtcr("cr<29, 0>", mask); 187859e5f45SGuo Ren } 18899106986SGuo Ren 18999106986SGuo Ren /* Wait for the cpu online */ 19099106986SGuo Ren while (!cpu_online(cpu)); 19199106986SGuo Ren 19299106986SGuo Ren secondary_stack = 0; 19399106986SGuo Ren 19499106986SGuo Ren return 0; 19599106986SGuo Ren } 19699106986SGuo Ren 19799106986SGuo Ren void __init smp_cpus_done(unsigned int max_cpus) 19899106986SGuo Ren { 19999106986SGuo Ren } 20099106986SGuo Ren 20199106986SGuo Ren int setup_profiling_timer(unsigned int multiplier) 20299106986SGuo Ren { 20399106986SGuo Ren return -EINVAL; 20499106986SGuo Ren } 20599106986SGuo Ren 20699106986SGuo Ren void csky_start_secondary(void) 20799106986SGuo Ren { 20899106986SGuo Ren struct mm_struct *mm = &init_mm; 20999106986SGuo Ren unsigned int cpu = smp_processor_id(); 21099106986SGuo Ren 21199106986SGuo Ren mtcr("cr31", secondary_hint); 21299106986SGuo Ren mtcr("cr18", secondary_ccr); 21399106986SGuo Ren 21499106986SGuo Ren mtcr("vbr", vec_base); 21599106986SGuo Ren 21699106986SGuo Ren flush_tlb_all(); 21799106986SGuo Ren write_mmu_pagemask(0); 21899106986SGuo Ren TLBMISS_HANDLER_SETUP_PGD(swapper_pg_dir); 21999106986SGuo Ren TLBMISS_HANDLER_SETUP_PGD_KERNEL(swapper_pg_dir); 22099106986SGuo Ren 22199106986SGuo Ren #ifdef CONFIG_CPU_HAS_FPU 22299106986SGuo Ren init_fpu(); 22399106986SGuo Ren #endif 22499106986SGuo Ren 225859e5f45SGuo Ren enable_percpu_irq(ipi_irq, 0); 22699106986SGuo Ren 22799106986SGuo Ren mmget(mm); 22899106986SGuo Ren mmgrab(mm); 22999106986SGuo Ren current->active_mm = mm; 23099106986SGuo Ren cpumask_set_cpu(cpu, mm_cpumask(mm)); 23199106986SGuo Ren 23299106986SGuo Ren notify_cpu_starting(cpu); 23399106986SGuo Ren set_cpu_online(cpu, true); 23499106986SGuo Ren 23599106986SGuo Ren pr_info("CPU%u Online: %s...\n", cpu, __func__); 23699106986SGuo Ren 23799106986SGuo Ren local_irq_enable(); 23899106986SGuo Ren preempt_disable(); 23999106986SGuo Ren cpu_startup_entry(CPUHP_AP_ONLINE_IDLE); 24099106986SGuo Ren } 241859e5f45SGuo Ren 242859e5f45SGuo Ren #ifdef CONFIG_HOTPLUG_CPU 243859e5f45SGuo Ren int __cpu_disable(void) 244859e5f45SGuo Ren { 245859e5f45SGuo Ren unsigned int cpu = smp_processor_id(); 246859e5f45SGuo Ren 247859e5f45SGuo Ren set_cpu_online(cpu, false); 248859e5f45SGuo Ren 249859e5f45SGuo Ren irq_migrate_all_off_this_cpu(); 250859e5f45SGuo Ren 251859e5f45SGuo Ren clear_tasks_mm_cpumask(cpu); 252859e5f45SGuo Ren 253859e5f45SGuo Ren return 0; 254859e5f45SGuo Ren } 255859e5f45SGuo Ren 256859e5f45SGuo Ren void __cpu_die(unsigned int cpu) 257859e5f45SGuo Ren { 258859e5f45SGuo Ren if (!cpu_wait_death(cpu, 5)) { 259859e5f45SGuo Ren pr_crit("CPU%u: shutdown failed\n", cpu); 260859e5f45SGuo Ren return; 261859e5f45SGuo Ren } 262859e5f45SGuo Ren pr_notice("CPU%u: shutdown\n", cpu); 263859e5f45SGuo Ren } 264859e5f45SGuo Ren 265859e5f45SGuo Ren void arch_cpu_idle_dead(void) 266859e5f45SGuo Ren { 267859e5f45SGuo Ren idle_task_exit(); 268859e5f45SGuo Ren 269859e5f45SGuo Ren cpu_report_death(); 270859e5f45SGuo Ren 271859e5f45SGuo Ren while (!secondary_stack) 272859e5f45SGuo Ren arch_cpu_idle(); 273859e5f45SGuo Ren 274859e5f45SGuo Ren local_irq_disable(); 275859e5f45SGuo Ren 276859e5f45SGuo Ren asm volatile( 277859e5f45SGuo Ren "mov sp, %0\n" 278859e5f45SGuo Ren "mov r8, %0\n" 279859e5f45SGuo Ren "jmpi csky_start_secondary" 280859e5f45SGuo Ren : 281859e5f45SGuo Ren : "r" (secondary_stack)); 282859e5f45SGuo Ren } 283859e5f45SGuo Ren #endif 284