1 /*
2 * Copyright (c) 2021 Intel Corporation
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/init.h>
8 #include <zephyr/kernel.h>
9 #include <ksched.h>
10 #include <zephyr/irq.h>
11 #include <zephyr/sys/atomic.h>
12 #include <zephyr/arch/riscv/irq.h>
13 #include <zephyr/drivers/pm_cpu_ops.h>
14 #include <zephyr/platform/hooks.h>
15
16 volatile struct {
17 arch_cpustart_t fn;
18 void *arg;
19 } riscv_cpu_init[CONFIG_MP_MAX_NUM_CPUS];
20
21 volatile uintptr_t __noinit riscv_cpu_wake_flag;
22 volatile uintptr_t riscv_cpu_boot_flag;
23 volatile void *riscv_cpu_sp;
24
25 extern void __start(void);
26
27 #if defined(CONFIG_RISCV_SOC_INTERRUPT_INIT)
28 void soc_interrupt_init(void);
29 #endif
30
arch_cpu_start(int cpu_num,k_thread_stack_t * stack,int sz,arch_cpustart_t fn,void * arg)31 void arch_cpu_start(int cpu_num, k_thread_stack_t *stack, int sz,
32 arch_cpustart_t fn, void *arg)
33 {
34 riscv_cpu_init[cpu_num].fn = fn;
35 riscv_cpu_init[cpu_num].arg = arg;
36
37 riscv_cpu_sp = K_KERNEL_STACK_BUFFER(stack) + sz;
38 riscv_cpu_boot_flag = 0U;
39
40 #ifdef CONFIG_PM_CPU_OPS
41 if (pm_cpu_on(cpu_num, (uintptr_t)&__start)) {
42 printk("Failed to boot secondary CPU %d\n", cpu_num);
43 return;
44 }
45 #endif
46
47 while (riscv_cpu_boot_flag == 0U) {
48 riscv_cpu_wake_flag = _kernel.cpus[cpu_num].arch.hartid;
49 }
50 }
51
arch_secondary_cpu_init(int hartid)52 void arch_secondary_cpu_init(int hartid)
53 {
54 unsigned int i;
55 unsigned int cpu_num = 0;
56
57 for (i = 0; i < CONFIG_MP_MAX_NUM_CPUS; i++) {
58 if (_kernel.cpus[i].arch.hartid == hartid) {
59 cpu_num = i;
60 }
61 }
62 csr_write(mscratch, &_kernel.cpus[cpu_num]);
63 #ifdef CONFIG_SMP
64 _kernel.cpus[cpu_num].arch.online = true;
65 #endif
66 #if defined(CONFIG_MULTITHREADING) && defined(CONFIG_THREAD_LOCAL_STORAGE)
67 __asm__("mv tp, %0" : : "r" (z_idle_threads[cpu_num].tls));
68 #endif
69 #if defined(CONFIG_RISCV_SOC_INTERRUPT_INIT)
70 soc_interrupt_init();
71 #endif
72 #ifdef CONFIG_RISCV_PMP
73 z_riscv_pmp_init();
74 #endif
75 #ifdef CONFIG_SMP
76 irq_enable(RISCV_IRQ_MSOFT);
77 #endif /* CONFIG_SMP */
78 #ifdef CONFIG_PLIC_IRQ_AFFINITY
79 /* Enable on secondary cores so that they can respond to PLIC */
80 irq_enable(RISCV_IRQ_MEXT);
81 #endif /* CONFIG_PLIC_IRQ_AFFINITY */
82 #ifdef CONFIG_SOC_PER_CORE_INIT_HOOK
83 soc_per_core_init_hook();
84 #endif /* CONFIG_SOC_PER_CORE_INIT_HOOK */
85 riscv_cpu_init[cpu_num].fn(riscv_cpu_init[cpu_num].arg);
86 }
87