1 #include "smp.h"
2 #include <common/cpu.h>
3 #include <common/kprint.h>
4 #include <common/spinlock.h>
5 #include <driver/interrupt/apic/apic.h>
6 #include <exception/gate.h>
7 #include <mm/slab.h>
8 #include <process/process.h>
9
10 #include <process/preempt.h>
11 #include <sched/sched.h>
12 #include <driver/acpi/acpi.h>
13 #include <driver/interrupt/apic/apic.h>
14 #include "ipi.h"
15
16 static void __smp_kick_cpu_handler(uint64_t irq_num, uint64_t param, struct pt_regs *regs);
17
18 static spinlock_t multi_core_starting_lock = {1}; // 多核启动锁
19
20 static struct acpi_Processor_Local_APIC_Structure_t *proc_local_apic_structs[MAX_SUPPORTED_PROCESSOR_NUM];
21 static uint32_t total_processor_num = 0;
22 static int current_starting_cpu = 0;
23
24 static int num_cpu_started = 1;
25
26 // kick cpu 功能所使用的中断向量号
27 #define KICK_CPU_IRQ_NUM 0xc8
28
smp_init()29 void smp_init()
30 {
31 spin_init(&multi_core_starting_lock); // 初始化多核启动锁
32 ul tmp_vaddr[MAX_SUPPORTED_PROCESSOR_NUM] = {0};
33
34 apic_get_ics(ACPI_ICS_TYPE_PROCESSOR_LOCAL_APIC, tmp_vaddr, &total_processor_num);
35
36 // kdebug("processor num=%d", total_processor_num);
37 for (int i = 0; i < total_processor_num; ++i)
38 {
39 io_mfence();
40 proc_local_apic_structs[i] = (struct acpi_Processor_Local_APIC_Structure_t *)(tmp_vaddr[i]);
41 }
42
43 // 将引导程序复制到物理地址0x20000处
44 memcpy((unsigned char *)phys_2_virt(0x20000), _apu_boot_start,
45 (unsigned long)&_apu_boot_end - (unsigned long)&_apu_boot_start);
46 io_mfence();
47 // 设置多核IPI中断门
48 for (int i = 200; i < 210; ++i)
49 set_intr_gate(i, 0, SMP_interrupt_table[i - 200]);
50 memset((void *)SMP_IPI_desc, 0, sizeof(irq_desc_t) * SMP_IRQ_NUM);
51
52 io_mfence();
53
54 io_mfence();
55 ipi_send_IPI(DEST_PHYSICAL, IDLE, ICR_LEVEL_DE_ASSERT, EDGE_TRIGGER, 0x00, ICR_INIT, ICR_ALL_EXCLUDE_Self, 0x00);
56
57 kdebug("total_processor_num=%d", total_processor_num);
58 // 注册接收kick_cpu功能的处理函数。(向量号200)
59 ipi_regiserIPI(KICK_CPU_IRQ_NUM, NULL, &__smp_kick_cpu_handler, NULL, NULL, "IPI kick cpu");
60
61 int core_to_start = 0;
62 // total_processor_num = 3;
63 for (int i = 0; i < total_processor_num; ++i) // i从1开始,不初始化bsp
64 {
65 io_mfence();
66
67 // 跳过BSP
68 kdebug("[core %d] acpi processor UID=%d, APIC ID=%d, flags=%#010lx", i,
69 proc_local_apic_structs[i]->ACPI_Processor_UID, proc_local_apic_structs[i]->local_apic_id,
70 proc_local_apic_structs[i]->flags);
71 if (proc_local_apic_structs[i]->local_apic_id == 0)
72 {
73 // --total_processor_num;
74 continue;
75 }
76 if (!((proc_local_apic_structs[i]->flags & 0x1) || (proc_local_apic_structs[i]->flags & 0x2)))
77 {
78 // --total_processor_num;
79 kdebug("processor %d cannot be enabled.", proc_local_apic_structs[i]->ACPI_Processor_UID);
80 continue;
81 }
82 ++core_to_start;
83 // continue;
84 io_mfence();
85 spin_lock(&multi_core_starting_lock);
86 preempt_enable(); // 由于ap处理器的pcb与bsp的不同,因此ap处理器放锁时,bsp的自旋锁持有计数不会发生改变,需要手动恢复preempt
87 // count
88 current_starting_cpu = proc_local_apic_structs[i]->ACPI_Processor_UID;
89 io_mfence();
90 // 为每个AP处理器分配栈空间
91 cpu_core_info[current_starting_cpu].stack_start = (uint64_t)kmalloc(STACK_SIZE, 0) + STACK_SIZE;
92 cpu_core_info[current_starting_cpu].ist_stack_start = (uint64_t)(kmalloc(STACK_SIZE, 0)) + STACK_SIZE;
93 io_mfence();
94 memset((void *)cpu_core_info[current_starting_cpu].stack_start - STACK_SIZE, 0, STACK_SIZE);
95 memset((void *)cpu_core_info[current_starting_cpu].ist_stack_start - STACK_SIZE, 0, STACK_SIZE);
96 io_mfence();
97
98 // 设置ap处理器的中断栈及内核栈中的cpu_id
99 ((struct process_control_block *)(cpu_core_info[current_starting_cpu].stack_start - STACK_SIZE))->cpu_id =
100 proc_local_apic_structs[i]->local_apic_id;
101 ((struct process_control_block *)(cpu_core_info[current_starting_cpu].ist_stack_start - STACK_SIZE))->cpu_id =
102 proc_local_apic_structs[i]->local_apic_id;
103
104 cpu_core_info[current_starting_cpu].tss_vaddr = (uint64_t)&initial_tss[current_starting_cpu];
105
106 memset(&initial_tss[current_starting_cpu], 0, sizeof(struct tss_struct));
107
108 set_tss_descriptor(10 + (current_starting_cpu * 2), (void *)(cpu_core_info[current_starting_cpu].tss_vaddr));
109 io_mfence();
110 set_tss64(
111 (uint *)cpu_core_info[current_starting_cpu].tss_vaddr, cpu_core_info[current_starting_cpu].stack_start,
112 cpu_core_info[current_starting_cpu].stack_start, cpu_core_info[current_starting_cpu].stack_start,
113 cpu_core_info[current_starting_cpu].ist_stack_start, cpu_core_info[current_starting_cpu].ist_stack_start,
114 cpu_core_info[current_starting_cpu].ist_stack_start, cpu_core_info[current_starting_cpu].ist_stack_start,
115 cpu_core_info[current_starting_cpu].ist_stack_start, cpu_core_info[current_starting_cpu].ist_stack_start,
116 cpu_core_info[current_starting_cpu].ist_stack_start);
117 io_mfence();
118
119 // 连续发送两次start-up IPI
120 ipi_send_IPI(DEST_PHYSICAL, IDLE, ICR_LEVEL_DE_ASSERT, EDGE_TRIGGER, 0x20, ICR_Start_up, ICR_No_Shorthand,
121 proc_local_apic_structs[i]->local_apic_id);
122 io_mfence();
123 ipi_send_IPI(DEST_PHYSICAL, IDLE, ICR_LEVEL_DE_ASSERT, EDGE_TRIGGER, 0x20, ICR_Start_up, ICR_No_Shorthand,
124 proc_local_apic_structs[i]->local_apic_id);
125 }
126 io_mfence();
127 while (num_cpu_started != (core_to_start + 1))
128 pause();
129
130 kinfo("Cleaning page table remapping...\n");
131
132 // 由于ap处理器初始化过程需要用到0x00处的地址,因此初始化完毕后才取消内存地址的重映射
133 uint64_t *global_CR3 = get_CR3();
134 for (int i = 0; i < 256; ++i)
135 {
136 io_mfence();
137 *(ul *)(phys_2_virt(global_CR3) + i) = 0UL;
138 }
139 kdebug("init proc's preempt_count=%ld", current_pcb->preempt_count);
140 kinfo("Successfully cleaned page table remapping!\n");
141 }
142
143 /**
144 * @brief AP处理器启动后执行的第一个函数
145 *
146 */
smp_ap_start()147 void smp_ap_start()
148 {
149
150 // 切换栈基地址
151 // uint64_t stack_start = (uint64_t)kmalloc(STACK_SIZE, 0) + STACK_SIZE;
152 __asm__ __volatile__("movq %0, %%rbp \n\t" ::"m"(cpu_core_info[current_starting_cpu].stack_start) : "memory");
153 __asm__ __volatile__("movq %0, %%rsp \n\t" ::"m"(cpu_core_info[current_starting_cpu].stack_start) : "memory");
154
155 ksuccess("AP core %d successfully started!", current_starting_cpu);
156 io_mfence();
157 ++num_cpu_started;
158
159 apic_init_ap_core_local_apic();
160
161 // ============ 为ap处理器初始化IDLE进程 =============
162 memset(current_pcb, 0, sizeof(struct process_control_block));
163
164 barrier();
165 current_pcb->state = PROC_RUNNING;
166 current_pcb->flags = PF_KTHREAD;
167 current_pcb->mm = &initial_mm;
168
169 list_init(¤t_pcb->list);
170 current_pcb->addr_limit = KERNEL_BASE_LINEAR_ADDR;
171 current_pcb->priority = 2;
172 current_pcb->virtual_runtime = 0;
173
174 current_pcb->thread = (struct thread_struct *)(current_pcb + 1); // 将线程结构体放置在pcb后方
175 current_pcb->thread->rbp = cpu_core_info[current_starting_cpu].stack_start;
176 current_pcb->thread->rsp = cpu_core_info[current_starting_cpu].stack_start;
177 current_pcb->thread->fs = KERNEL_DS;
178 current_pcb->thread->gs = KERNEL_DS;
179 current_pcb->cpu_id = current_starting_cpu;
180
181 initial_proc[proc_current_cpu_id] = current_pcb;
182 barrier();
183 load_TR(10 + current_starting_cpu * 2);
184 current_pcb->preempt_count = 0;
185
186 sched_set_cpu_idle(current_starting_cpu, current_pcb);
187
188 io_mfence();
189 spin_unlock(&multi_core_starting_lock);
190 preempt_disable(); // 由于ap处理器的pcb与bsp的不同,因此ap处理器放锁时,需要手动恢复preempt count
191 io_mfence();
192 current_pcb->flags |= PF_NEED_SCHED;
193 sti();
194 apic_timer_ap_core_init();
195 sched();
196
197 while (1)
198 {
199 // kdebug("123");
200 hlt();
201 }
202
203 while (1)
204 {
205 printk_color(BLACK, WHITE, "CPU:%d IDLE process.\n", proc_current_cpu_id);
206 }
207 while (1) // 这里要循环hlt,原因是当收到中断后,核心会被唤醒,处理完中断之后不会自动hlt
208 hlt();
209 }
210
211 /**
212 * @brief kick_cpu 核心间通信的处理函数
213 *
214 * @param irq_num
215 * @param param
216 * @param regs
217 */
__smp_kick_cpu_handler(uint64_t irq_num,uint64_t param,struct pt_regs * regs)218 static void __smp_kick_cpu_handler(uint64_t irq_num, uint64_t param, struct pt_regs *regs)
219 {
220 if (user_mode(regs))
221 return;
222 sched();
223 }
224
225 /**
226 * @brief 使得指定的cpu核心立即运行调度
227 *
228 * @param cpu_id cpu核心号
229 */
kick_cpu(uint32_t cpu_id)230 int kick_cpu(uint32_t cpu_id)
231 {
232 if (cpu_id >= MAX_CPU_NUM)
233 {
234 return -EINVAL;
235 }
236 ipi_send_IPI(DEST_PHYSICAL, IDLE, ICR_LEVEL_DE_ASSERT, EDGE_TRIGGER, KICK_CPU_IRQ_NUM, ICR_APIC_FIXED,
237 ICR_ALL_EXCLUDE_Self, 0);
238 return 0;
239 }
240
241 /**
242 * @brief 获取当前全部的cpu数目
243 *
244 * @return uint32_t
245 */
smp_get_total_cpu()246 uint32_t smp_get_total_cpu()
247 {
248 return num_cpu_started;
249 }