Voxia OS v0.0.1
Hobby Project Operating System Targeting x86-64
Loading...
Searching...
No Matches
core.c
Go to the documentation of this file.
1#include "core.h"
2#include "autoconf.h"
3#include "hal/acpi/acpi.h"
4#include "hal/acpi/hpet.h"
5#include "hal/apic/apic.h"
6#include "hal/cpu/interrupt.h"
7#include "hal/cpu/msr.h"
8#include "hal/cpu/paging.h"
9#include "hal/timer/timer.h"
10#include "init/init.h"
11#include "libk/serial.h"
13#include "memory/vm_manager.h"
14#include "procc/scheduler.h"
15#include "sys/syscall.h"
16#include <ioforge/ioforge.h>
17#include <str.h>
18#include <type.h>
19
20#define INIT_CORE_MAGIC 0x00EEDDAB
21#define INIT_CORE_ENTRYPOINT 0x8000
22
25
26extern char __cpu_trampoline_start[];
27extern char __cpu_trampoline_end[];
28
29extern void initGdt(init_context_t* _);
30extern void initSIMD(init_context_t* _);
31extern void initTimer(init_context_t* _);
32
34
35each_core_data core_data[VOXIA_MAX_CORE] = {0};
36
37extern uint8_t ap_stack_top[VOXIA_MAX_CORE][65536];
38
40 core_data[id].canary = (id + 0x56) ^ 0x595e9fbd94fda766;
41 core_data[id].core_id = id;
42 core_data[id].usleep_trigerred = false;
43 core_data[id].scheduler = vxGetSchedulerCore(id);
44 core_data[id].workqueue_count = 0;
45 core_data[id].kernel_rsp =
46 (uintptr_t)ap_stack_top[id] + sizeof(ap_stack_top[id]);
47 core_data[id].user_rsp = 0;
48
49 const uintptr_t core_data_addr = (uintptr_t)&core_data[id];
50 msrSetGSBase(core_data_addr);
52}
53
58
61
66
67extern void vxInitializeAPICTimer();
68extern void init_simd();
69extern void setup_gdt(int core);
70
72static volatile uint8_t active_core_count = 1;
73
74__attribute__((no_stack_protector, noreturn))
75__attribute__((section(".cpu_trampoline"))) void
76cpuTrampolinePhase2(uint64_t core_id);
77
78__attribute__((no_stack_protector, noreturn))
79__attribute__((section(".cpu_trampoline"))) void
80cpuTrampolinePhase2(uint64_t core_id) {
81 __atomic_fetch_add(&active_core_count, 1, __ATOMIC_SEQ_CST);
82
84 setup_gdt((uint8_t)core_id);
85 update_core_gs((uint8_t)core_id);
87
88 irq_setup((uint8_t)core_id);
90 init_simd();
92
95 serial2_printf("core %d %d successfully running\n", core_id,
97 vxGetCpuInfo((uint8_t)core_id)->status = Active;
98
100
101 for (;;)
102 __asm__ volatile("hlt");
103}
104
106
108 uint32_t eax, ebx, ecx, edx;
109 __asm__ volatile("cpuid"
110 : "=a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx)
111 : "a"(1));
112 return (ebx >> 24) & 0xFF;
113}
114
115static void sipi_sequential(uint32_t apic_id, uint64_t entrypoint_addr) {
116 __asm__ volatile("mfence" ::: "memory");
117
118 uint8_t vector = (entrypoint_addr >> 12) & 0xFF;
119
120 if (!x2_apic_supported) {
121 // INIT assert
122 apic_write(APIC_ICR_HIGH, apic_id << 24);
123 apic_write(APIC_ICR_LOW, (0b101 << 8) | (1 << 14));
124 vxHPETSleep(ms2ns(10));
125
126 while (apic_read(APIC_ICR_LOW) & (1 << 12))
127 __asm__ volatile("pause");
128
129 // INIT deassert
130 apic_write(APIC_ICR_HIGH, apic_id << 24);
131 apic_write(APIC_ICR_LOW, (0b101 << 8));
132 vxHPETSleep(ms2ns(10));
133
134 while (apic_read(APIC_ICR_LOW) & (1 << 12))
135 __asm__ volatile("pause");
136
137 // SIPI #1
138 apic_write(APIC_ICR_HIGH, apic_id << 24);
139 apic_write(APIC_ICR_LOW, (0b110 << 8) | vector);
140 vxHPETSleep(ms2ns(10));
141
142 while (apic_read(APIC_ICR_LOW) & (1 << 12))
143 __asm__ volatile("pause");
144
145 // SIPI #2
146 apic_write(APIC_ICR_HIGH, apic_id << 24);
147 apic_write(APIC_ICR_LOW, (0b110 << 8) | vector);
148 vxHPETSleep(ms2ns(10));
149
150 while (apic_read(APIC_ICR_LOW) & (1 << 12))
151 __asm__ volatile("pause");
152
153 } else {
154 uint64_t icr;
155
156 // INIT assert
157 icr = 0;
158 icr |= (0b101ULL << 8);
159 icr |= (1ULL << 14);
160 icr |= ((uint64_t)apic_id << 32);
161 LOG_DEBUG("APIC", "ICR INIT assert = 0x%x", icr);
162 vxWRSR(0x830, icr);
163 vxHPETSleep(ms2ns(10));
164 LOG_DEBUG("APIC", "INIT assert OK");
165
166 // SIPI #1
167 icr = 0;
168 icr |= (0b110ULL << 8);
169 icr |= (uint8_t)vector;
170 icr |= ((uint64_t)apic_id << 32);
171 LOG_DEBUG("APIC", "ICR SIPI #1 = 0x%x", icr);
172 vxWRSR(0x830, icr);
173 vxHPETSleep(ms2ns(1));
174 LOG_DEBUG("APIC", "SIPI #1 OK");
175
176 // SIPI #2
177 icr = 0;
178 icr |= (0b110ULL << 8);
179 icr |= (uint8_t)vector;
180 icr |= ((uint64_t)apic_id << 32);
181 LOG_DEBUG("APIC", "ICR SIPI #2 = 0x%x", icr);
182 vxWRSR(0x830, icr);
183 vxHPETSleep(ms2ns(1));
184 LOG_DEBUG("APIC", "SIPI #2 OK");
185 }
186}
187
188INIT(Core) {
189 LOG_INFO("CORE", "preparing to send IPI");
190 multicore_start = true;
191
192 // 0x8000 - 0x9000 used for entry point in each core
193 uintptr_t entrypoint_addr = INIT_CORE_ENTRYPOINT;
196 size_t aligned_size = (size + BLOCK_SIZE - 1) / BLOCK_SIZE;
197
199 entrypoint_addr, aligned_size, 0x3);
201 memcopy((void*)entrypoint_addr,
203
204 // prepare trampoline
205 volatile uint64_t* trampoline_data =
207 trampoline_data[1] = INIT_CORE_MAGIC;
208 trampoline_data[2] = (uintptr_t)paging_get_highest_page_map();
209
210 auto bsp_id = (int)get_bsp_apic_id();
211
212 auto jum_core = vxGetNumberOfCores();
213 LOG_DEBUG("CORE", "terdeteksi %d core", jum_core);
214 for (uint8_t i = 0; i < jum_core; i++) {
215 if (i == bsp_id)
216 continue;
217
218 auto core_info = vxGetCpuInfo(i);
219 auto cpu_id = core_info->apicid;
220
221 uint64_t pstack = (uint64_t)phys_base_alloc(5);
223 5); // 8kb
225 0b111);
227
228 LOG_DEBUG("CORE", "stack untuk core %d = 0x%x", cpu_id, stack);
229 auto stack_top = stack + 5 * BLOCK_SIZE;
230
231 // Allocate separate data page for each core to avoid collisions
232 uintptr_t per_core_data_paddr = (uintptr_t)phys_base_alloc(1);
233 uintptr_t per_core_data_vaddr =
236 per_core_data_vaddr, per_core_data_paddr, 1,
237 0b111);
239 vma_register(get_kernel_vmm_page(), per_core_data_paddr, per_core_data_vaddr,
240 BLOCK_SIZE);
241
242 volatile uint64_t* core_handshake =
243 (volatile uint64_t*)per_core_data_vaddr;
244 core_handshake[0] = (uint64_t)cpuTrampolinePhase2;
245 core_handshake[1] = stack_top;
246 core_handshake[2] = 0;
247
248 // Update trampoline data for this core
249 trampoline_data[3] = (uint64_t)per_core_data_vaddr;
250
251 LOG_DEBUG("CORE", "kirim sipi ke CPU Core %d", cpu_id);
252
253 sipi_sequential(cpu_id, entrypoint_addr);
254
255 while (__atomic_load_n(&core_handshake[2], __ATOMIC_SEQ_CST) ==
256 0) {
257 vxHPETSleep(us2ns(100));
258 }
259 }
260
261 LOG_INFO("core", "active core count %d", active_core_count);
263}
264
struct cpu_core * vxGetCpuInfo(uint8_t apicid)
Definition acpi.c:21
uint8_t vxGetNumberOfCores()
Definition acpi.c:45
@ Active
Definition acpi.h:66
uint8_t x2_apic_supported
Definition apic.c:16
void apicInitialize()
Definition apic.c:62
void apic_write(uint32_t reg, uint32_t value)
Definition apic.c:40
uint32_t apic_read(uint32_t reg)
Definition apic.c:49
#define APIC_ICR_LOW
Definition apic.h:11
#define APIC_ICR_HIGH
Definition apic.h:12
uint8_t vxGetActiveCoreCount()
Definition core.c:265
uintptr_t __stack_chk_guard
Definition sanitizer.c:6
#define INIT_CORE_MAGIC
Definition core.c:20
char _binary_hal_cpu_core_ap_bin_start[]
void vxInitializeAPICTimer()
Definition apic_timer.c:148
#define INIT_CORE_ENTRYPOINT
Definition core.c:21
char __cpu_trampoline_end[]
each_core_data * get_current_core_data(void)
Definition core.c:54
char _binary_hal_cpu_core_ap_bin_end[]
void initGdt(init_context_t *_)
void initTimer(init_context_t *_)
void setup_gdt(int core)
uint8_t ap_stack_top[VOXIA_MAX_CORE][65536]
each_core_data core_data[VOXIA_MAX_CORE]
Definition core.c:35
static uint32_t get_bsp_apic_id(void)
Definition core.c:107
char __cpu_trampoline_start[]
void init_simd()
Definition simd.c:11
void initSIMD(init_context_t *_)
static void sipi_sequential(uint32_t apic_id, uint64_t entrypoint_addr)
Definition core.c:115
static volatile uint8_t active_core_count
Definition core.c:72
each_core_data * vxGetCoreDataByCoreID(uint8_t core_id)
Definition core.c:62
void update_core_gs(uint8_t id)
Definition core.c:39
boolean_t multicore_start
Definition core.c:105
void vxHPETSleep(uint64_t ns)
Definition hpet.c:86
#define us2ns(us)
Definition hpet.h:13
#define ms2ns(ms)
Definition hpet.h:12
uint8_t get_current_core_cpuid()
thread_id id
Definition thread.h:1
uint64_t stack
Definition thread.h:13
typedef __attribute__
Definition msi.c:47
#define INIT(fn)
Definition init.h:26
void irq_setup(uint16_t core)
Definition interrupt.c:125
void serial2_printf(const char *fmt,...)
each_core_data
Definition core.h:32
uintptr_t msrReadGSBase()
Definition msr.c:31
void vxWRSR(uint32_t msr, uint64_t value)
Definition msr.c:3
void msrSetGSBase(uint64_t base)
Definition msr.c:23
void msrSetKernelGSBase(uint64_t base)
Definition msr.c:40
void paging_reload(page_t p)
Definition paging.c:457
page_t paging_get_highest_page_map(void)
Definition paging.c:463
void vxMultipleMmap(page_t page_dir, uint64_t virt, uint64_t phys, uint64_t size, uint64_t flags)
Definition paging.c:340
void * phys_base_alloc(uint64_t block)
#define BLOCK_SIZE
scheduler_core_t * vxGetSchedulerCore(uint16_t core)
Definition scheduler.c:21
void vxStartScheduler(void)
Definition scheduler.c:293
void serial_setup(void)
Definition serial.c:46
#define LOG_INFO(mod, fmt,...)
Definition serial.h:20
#define LOG_DEBUG(mod, fmt,...)
Definition serial.h:22
void memcopy(void *dest, void *src, size_t size)
cpu_core_status_t status
Definition acpi.h:69
void syscall_init(void)
Definition syscall.c:15
void setup_timer_interrupt()
Definition timer.c:26
unsigned int uint32_t
Definition type.h:19
#define KERNEL_API
Definition type.h:93
uint8_t boolean_t
Definition type.h:89
unsigned long uintptr_t
Definition type.h:73
unsigned long uint64_t
Definition type.h:25
unsigned char uint8_t
Definition type.h:7
#define vector(T)
Definition vector.h:11
uintptr_t vma_lookup_free_vaddr(struct virtual_memory_page *page, mem_vma_region region, size_t size)
Definition vm_manager.c:156
void vma_register(struct virtual_memory_page *page, uintptr_t phys_address, uintptr_t virt_addr, size_t size)
Definition vm_manager.c:101
struct virtual_memory_page * get_kernel_vmm_page()
int core
Definition vm_manager.h:5
@ VMA_REGION_A
Definition vm_manager.h:13
size_t size
Definition vnode.h:3