1 /* 2 * SMP initialisation and IPI support 3 * Based on arch/arm64/kernel/smp.c 4 * 5 * Copyright (C) 2012 ARM Ltd. 6 * Copyright (C) 2015 Regents of the University of California 7 * Copyright (C) 2017 SiFive 8 * 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License version 2 as 11 * published by the Free Software Foundation. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 */ 18 19 #include <linux/module.h> 20 #include <linux/init.h> 21 #include <linux/kernel.h> 22 #include <linux/mm.h> 23 #include <linux/sched.h> 24 #include <linux/kernel_stat.h> 25 #include <linux/notifier.h> 26 #include <linux/cpu.h> 27 #include <linux/percpu.h> 28 #include <linux/delay.h> 29 #include <linux/err.h> 30 #include <linux/irq.h> 31 #include <linux/of.h> 32 #include <linux/sched/task_stack.h> 33 #include <asm/irq.h> 34 #include <asm/mmu_context.h> 35 #include <asm/tlbflush.h> 36 #include <asm/sections.h> 37 #include <asm/sbi.h> 38 39 void *__cpu_up_stack_pointer[NR_CPUS]; 40 void *__cpu_up_task_pointer[NR_CPUS]; 41 42 void __init smp_prepare_boot_cpu(void) 43 { 44 } 45 46 void __init smp_prepare_cpus(unsigned int max_cpus) 47 { 48 } 49 50 void __init setup_smp(void) 51 { 52 struct device_node *dn = NULL; 53 int hart, im_okay_therefore_i_am = 0; 54 55 while ((dn = of_find_node_by_type(dn, "cpu"))) { 56 hart = riscv_of_processor_hart(dn); 57 if (hart >= 0) { 58 set_cpu_possible(hart, true); 59 set_cpu_present(hart, true); 60 if (hart == smp_processor_id()) { 61 BUG_ON(im_okay_therefore_i_am); 62 im_okay_therefore_i_am = 1; 63 } 64 } 65 } 66 67 BUG_ON(!im_okay_therefore_i_am); 68 } 69 70 int __cpu_up(unsigned int cpu, struct task_struct *tidle) 71 { 72 tidle->thread_info.cpu = cpu; 73 74 /* 75 * On RISC-V systems, all harts boot on their own accord. Our _start 76 * selects the first hart to boot the kernel and causes the remainder 77 * of the harts to spin in a loop waiting for their stack pointer to be 78 * setup by that main hart. Writing __cpu_up_stack_pointer signals to 79 * the spinning harts that they can continue the boot process. 80 */ 81 smp_mb(); 82 __cpu_up_stack_pointer[cpu] = task_stack_page(tidle) + THREAD_SIZE; 83 __cpu_up_task_pointer[cpu] = tidle; 84 85 while (!cpu_online(cpu)) 86 cpu_relax(); 87 88 return 0; 89 } 90 91 void __init smp_cpus_done(unsigned int max_cpus) 92 { 93 } 94 95 /* 96 * C entry point for a secondary processor. 97 */ 98 asmlinkage void __init smp_callin(void) 99 { 100 struct mm_struct *mm = &init_mm; 101 102 /* All kernel threads share the same mm context. */ 103 atomic_inc(&mm->mm_count); 104 current->active_mm = mm; 105 106 trap_init(); 107 notify_cpu_starting(smp_processor_id()); 108 set_cpu_online(smp_processor_id(), 1); 109 local_flush_tlb_all(); 110 local_irq_enable(); 111 preempt_disable(); 112 cpu_startup_entry(CPUHP_AP_ONLINE_IDLE); 113 } 114