21static inline uint8_t my_lapic_id(
void) {
23 return (uint8_t)(x >> 24);
27static void install_trampoline(
void) {
42 for (uintptr_t off = 0; off < 4096; off += 64) {
43 __asm__
volatile(
"clflush (%0)" ::
"r"((
char*)virt + off) :
"memory");
45 __asm__
volatile(
"invlpg (%0)" ::
"r"(virt) :
"memory");
48#define CPU_STACK_SIZE (24*1024)
54 uint8_t my_id = my_lapic_id();
74 cpus[i].lapic_ID = aid;
89 cpus[i].schedulerEnabled =
false;
90 cpus[i].currentThread = NULL;
93 cpus[i].lapic_ID = aid;
97 cpus[i].VirtStackTop = stack;
103 cpus[i].schedulePending =
false;
106 kmemset(&
cpus[i].CurrentDeferredRoutine, 0,
sizeof(
cpus[i].CurrentDeferredRoutine));
112static void send_startup_ipis(uint8_t apic_id) {
136 install_trampoline();
141 for (uint32_t i = 0; i <
cpu_count; i++) {
157 uint64_t ap_main_addr = (uint64_t)&
APMain;
158 kmemcpy((
void*)virt, &ap_main_addr,
sizeof(ap_main_addr));
167 kmemcpy((
void*)virt, &cr3,
sizeof(cr3));
175 uintptr_t cpuAddress = (uintptr_t)
cpus;
176 kmemcpy((
void*)virt, &cpuAddress,
sizeof(cpuAddress));
179 uint8_t my_id = my_lapic_id();
180 for (uint32_t i = 0; i <
cpu_count; i++) {
182 if (aid == my_id)
continue;
183 send_startup_ipis(aid);
197 uint8_t ProcessorNumber
205 if (
cpus[i].lapic_ID == ProcessorNumber)
return &
cpus[i];
214 uint8_t myid = my_lapic_id();
216 static uint64_t g_ipiSeq = 1;
219 __asm__
volatile(
"mfence" :::
"memory");
222 if (
cpus[i].lapic_ID == myid)
continue;
225 cpus[i].IpiAction = action;
226 cpus[i].IpiParameter = parameter;
228 cpus[i].IpiSeq = seq;
238 while (*(
volatile uint64_t*)&
cpus[i].IpiSeq == seq) {
BOOT_INFO boot_info_local
void APMain(void)
---------------— FUNCTIONS ---------------—
void lapic_send_ipi(uint8_t apic_id, uint8_t vector, uint32_t flags)
uint32_t lapic_mmio_read(uint32_t off)
FORCEINLINE uint64_t InterlockedIncrementU64(volatile uint64_t *target)
struct _PROCESSOR PROCESSOR
FORCEINLINE void __writemsr(uint32_t msr, uint64_t value)
FORCEINLINE void __pause(void)
bool MeDisableInterrupts(void)
void MeEnableInterrupts(IN bool EnabledBefore)
uint8_t apic_list[MAX_CPUS]
PMMPTE MiGetPtePointer(IN uintptr_t va)
FORCEINLINE uint8_t MeGetActiveProcessorCount(void)
#define AP_TRAMP_PML4_OFFSET
struct _IPI_PARAMS IPI_PARAMS
#define AP_TRAMP_CPUS_OFFSET
#define AP_TRAMP_APMAIN_OFFSET
struct _SMP_BOOTINFO SMP_BOOTINFO
enum _CPU_ACTION CPU_ACTION
FORCEINLINE void * kmemcpy(void *dest, const void *src, size_t len)
FORCEINLINE void * kmemset(void *dest, int64_t val, uint64_t len)
#define PhysicalMemoryOffset
#define MI_WRITE_PTE(_PtePointer, _Va, _Pa, _Flags)
void * MiCreateKernelStack(IN bool LargeStack)
void pit_sleep_ms(uint32_t ms)
PPROCESSOR MeGetProcessorBlock(uint8_t ProcessorNumber)
void MhInitializeSMP(uint8_t *apic_list, uint32_t cpu_count, uint32_t lapicAddress)
uint8_t g_apic_list[MAX_CPUS]
uint8_t _binary_build_ap_trampoline_bin_end[]
uint8_t _binary_build_ap_trampoline_bin_start[]
void MhSendActionToCpusAndWait(CPU_ACTION action, IPI_PARAMS parameter)