1 /*
2 * Copyright (c) 2023 Institute of Parallel And Distributed Systems (IPADS), Shanghai Jiao Tong University (SJTU)
3 * Licensed under the Mulan PSL v2.
4 * You can use this software according to the terms and conditions of the Mulan PSL v2.
5 * You may obtain a copy of Mulan PSL v2 at:
6 * http://license.coscl.org.cn/MulanPSL2
7 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
8 * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
9 * PURPOSE.
10 * See the Mulan PSL v2 for more details.
11 */
12 #include <common/vars.h>
13 #include <common/kprint.h>
14 #include <mm/mm.h>
15 #include <arch/machine/smp.h>
16 #include <arch/mmu.h>
17 #include <common/types.h>
18 #include <arch/tools.h>
19 #include <irq/ipi.h>
20
21 volatile char cpu_status[PLAT_CPU_NUM] = {cpu_hang};
22
23 struct per_cpu_info cpu_info[PLAT_CPU_NUM] __attribute__((aligned(64)));
24 u64 ctr_el0;
25
enable_smp_cores(paddr_t boot_flag)26 void enable_smp_cores(paddr_t boot_flag)
27 {
28 int i = 0;
29 long *secondary_boot_flag;
30
31 /* Set current cpu status */
32 cpu_status[smp_get_cpu_id()] = cpu_run;
33 secondary_boot_flag = (long *)phys_to_virt(boot_flag);
34 for (i = 0; i < PLAT_CPU_NUM; i++) {
35 secondary_boot_flag[i] = 1;
36 flush_dcache_area((u64)secondary_boot_flag,
37 (u64)sizeof(u64) * PLAT_CPU_NUM);
38 asm volatile("dsb sy");
39 while (cpu_status[i] == cpu_hang)
40 ;
41 kinfo("CPU %d is active\n", i);
42 }
43 /* wait all cpu to boot */
44 kinfo("All %d CPUs are active\n", PLAT_CPU_NUM);
45 init_ipi_data();
46 }
47
smp_get_cpu_id(void)48 inline u32 smp_get_cpu_id(void)
49 {
50 return get_per_cpu_info() - cpu_info;
51 }
52
get_per_cpu_info(void)53 inline struct per_cpu_info *get_per_cpu_info(void)
54 {
55 struct per_cpu_info *info;
56
57 asm volatile("mrs %0, tpidr_el1" : "=r"(info));
58
59 return info;
60 }
61
read_ctr(void)62 static inline u64 read_ctr(void)
63 {
64 u64 reg;
65
66 asm volatile("mrs %0, ctr_el0" : "=r"(reg)::"memory");
67 return reg;
68 }
69
init_per_cpu_info(u32 cpuid)70 void init_per_cpu_info(u32 cpuid)
71 {
72 struct per_cpu_info *info;
73
74 if (cpuid == 0)
75 ctr_el0 = read_ctr();
76
77 info = &cpu_info[cpuid];
78
79 info->cur_exec_ctx = 0;
80
81 info->cpu_stack = (char *)(KSTACKx_ADDR(cpuid) + CPU_STACK_SIZE);
82
83 info->fpu_owner = NULL;
84 info->fpu_disable = 0;
85
86 asm volatile("msr tpidr_el1, %0" ::"r"(info));
87 }
88
smp_get_mpidr(void)89 u64 smp_get_mpidr(void)
90 {
91 u64 mpidr = 0;
92
93 asm volatile("mrs %0, mpidr_el1" : "=r"(mpidr));
94 return mpidr;
95 }
96
smp_print_status(u32 cpuid)97 void smp_print_status(u32 cpuid)
98 {
99 }
100