1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Boot secondary CPUs 4 * 5 * Copyright (C) 2023, Ventana Micro Systems Inc., Andrew Jones <ajones@ventanamicro.com> 6 */ 7 #include <libcflat.h> 8 #include <alloc.h> 9 #include <cpumask.h> 10 #include <asm/csr.h> 11 #include <asm/page.h> 12 #include <asm/processor.h> 13 #include <asm/sbi.h> 14 #include <asm/smp.h> 15 16 cpumask_t cpu_present_mask; 17 cpumask_t cpu_online_mask; 18 cpumask_t cpu_idle_mask; 19 20 static cpumask_t cpu_started; 21 22 secondary_func_t secondary_cinit(struct secondary_data *data) 23 { 24 struct thread_info *info; 25 26 thread_info_init(); 27 info = current_thread_info(); 28 set_cpu_online(info->cpu, true); 29 smp_send_event(); 30 31 return data->func; 32 } 33 34 static void __smp_boot_secondary(int cpu, secondary_func_t func) 35 { 36 struct secondary_data *sp = memalign(16, SZ_8K) + SZ_8K - 16; 37 struct sbiret ret; 38 39 sp -= sizeof(struct secondary_data); 40 sp->stvec = csr_read(CSR_STVEC); 41 sp->func = func; 42 43 ret = sbi_hart_start(cpus[cpu].hartid, (unsigned long)&secondary_entry, __pa(sp)); 44 assert(ret.error == SBI_SUCCESS); 45 } 46 47 void smp_boot_secondary(int cpu, void (*func)(void)) 48 { 49 int ret = cpumask_test_and_set_cpu(cpu, &cpu_started); 50 51 assert_msg(!ret, "CPU%d already boot once", cpu); 52 __smp_boot_secondary(cpu, func); 53 54 while (!cpu_online(cpu)) 55 smp_wait_for_event(); 56 } 57 58 void smp_boot_secondary_nofail(int cpu, void (*func)(void)) 59 { 60 int ret = cpumask_test_and_set_cpu(cpu, &cpu_started); 61 62 if (!ret) 63 __smp_boot_secondary(cpu, func); 64 65 while (!cpu_online(cpu)) 66 smp_wait_for_event(); 67 } 68