// SPDX-License-Identifier: GPL-2.0-only /* * Boot secondary CPUs * * Copyright (C) 2023, Ventana Micro Systems Inc., Andrew Jones */ #include #include #include #include #include #include #include #include #include cpumask_t cpu_present_mask; cpumask_t cpu_online_mask; cpumask_t cpu_idle_mask; static cpumask_t cpu_started; secondary_func_t secondary_cinit(struct secondary_data *data) { struct thread_info *info; __mmu_enable(data->satp); thread_info_init(); info = current_thread_info(); set_cpu_online(info->cpu, true); smp_send_event(); return data->func; } static void __smp_boot_secondary(int cpu, secondary_func_t func) { struct secondary_data *sp = alloc_pages(1) + SZ_8K - 16; struct sbiret ret; sp -= sizeof(struct secondary_data); sp->satp = csr_read(CSR_SATP); sp->stvec = csr_read(CSR_STVEC); sp->func = func; ret = sbi_hart_start(cpus[cpu].hartid, (unsigned long)&secondary_entry, __pa(sp)); assert(ret.error == SBI_SUCCESS); } void smp_boot_secondary(int cpu, void (*func)(void)) { int ret = cpumask_test_and_set_cpu(cpu, &cpu_started); assert_msg(!ret, "CPU%d already boot once", cpu); __smp_boot_secondary(cpu, func); while (!cpu_online(cpu)) smp_wait_for_event(); } void smp_boot_secondary_nofail(int cpu, void (*func)(void)) { int ret = cpumask_test_and_set_cpu(cpu, &cpu_started); if (!ret) __smp_boot_secondary(cpu, func); while (!cpu_online(cpu)) smp_wait_for_event(); }