PatchworkOS
Loading...
Searching...
No Matches
smp.c
Go to the documentation of this file.
1#include <kernel/cpu/smp.h>
2
4#include <kernel/cpu/cpu.h>
8#include <kernel/log/log.h>
9#include <kernel/log/panic.h>
10#include <kernel/mem/vmm.h>
11
12#include <kernel/cpu/regs.h>
13#include <kernel/defs.h>
14
15#include <assert.h>
16#include <stdatomic.h>
17#include <stdint.h>
18
19static cpu_t bootstrapCpu ALIGNED(PAGE_SIZE) = {0};
20
21cpu_t* _cpus[CPU_MAX] = {&bootstrapCpu};
22uint16_t _cpuAmount = 1; // Start with 1 for the bootstrap CPU
23
24static atomic_uint16_t haltedAmount = ATOMIC_VAR_INIT(0);
25
30
32{
33 _cpus[CPU_ID_BOOTSTRAP] = &bootstrapCpu;
34 if (cpu_init(&bootstrapCpu, CPU_ID_BOOTSTRAP) == ERR)
35 {
36 panic(NULL, "Failed to initialize bootstrap cpu");
37 }
38}
39
41{
43
44 bootstrapCpu.lapicId = lapic_self_id();
45 LOG_INFO("bootstrap cpu %u with lapicid %u, ready\n", (uint64_t)bootstrapCpu.id, (uint64_t)bootstrapCpu.lapicId);
46
48 if (madt == NULL)
49 {
50 // Technically we dont need to panic here we could just assume the system is single cpu but the rest of the os
51 // needs the madt anyway so we might as well.
52 panic(NULL, "MADT table not found");
53 }
54
56 MADT_FOR_EACH(madt, lapic)
57 {
58 if (lapic->header.type != INTERRUPT_CONTROLLER_PROCESSOR_LOCAL_APIC || bootstrapCpu.lapicId == lapic->apicId)
59 {
60 continue;
61 }
62
64 {
65 // We need the _cpus to be page aligned so its stacks are also page aligned.
67 _cpus[newId] =
69 if (_cpus[newId] == NULL)
70 {
71 panic(NULL, "Failed to allocate memory for cpu %d with lapicid %d", (uint64_t)newId,
72 (uint64_t)lapic->apicId);
73 }
74 memset(_cpus[newId], 0, sizeof(cpu_t));
75
77
79 {
80 panic(NULL, "Timeout waiting for cpu %d with lapicid %d to start", (uint64_t)newId,
81 (uint64_t)lapic->apicId);
82 }
83 }
84 }
85
87}
88
90{
91 (void)frame; // Unused
92
94
95 while (1)
96 {
97 asm volatile("cli");
98 asm volatile("hlt");
99 }
100}
101
103{
104 const cpu_t* self = smp_self_unsafe();
105 for (uint8_t id = 0; id < _cpuAmount; id++)
106 {
107 if (self->id != id)
108 {
109 lapic_send_ipi(_cpus[id]->lapicId, INTERRUPT_HALT);
110 }
111 }
112}
static madt_t * madt
Definition apic.c:18
#define CLOCKS_PER_SEC
Definition clock_t.h:15
static atomic_uint64_t newId
Definition fb.c:15
#define PROCESSOR_LOCAL_APIC_ENABLED
Definition tables.h:143
sdt_header_t * acpi_tables_lookup(const char *signature, uint64_t n)
Lookup the n'th table matching the signature.
Definition tables.c:266
#define INTERRUPT_CONTROLLER_PROCESSOR_LOCAL_APIC
Definition tables.h:123
#define MADT_FOR_EACH(madt, ic)
Iterate over all MADT interrupt controllers.
Definition tables.h:195
#define MADT_SIGNATURE
MADT table signature.
Definition tables.h:204
@ INTERRUPT_HALT
Halt the CPU.
Definition interrupt.h:138
void smp_bootstrap_init(void)
Initializes the bootstrap CPU structure.
Definition smp.c:31
static cpu_t * smp_self_unsafe(void)
Returns a pointer to the cpu_t structure of the current CPU.
Definition smp.h:90
void smp_bootstrap_init_early(void)
Early initialization of the bootstrap CPU.
Definition smp.c:26
cpu_t * _cpus[CPU_MAX]
Array of pointers to cpu_t structures for each CPU.
Definition smp.c:21
void smp_others_init(void)
Initializes the other CPUs.
Definition smp.c:40
uint16_t _cpuAmount
The number of CPUs currently identified.
Definition smp.c:22
void smp_halt_others(void)
Halts all CPUs except the current one.
Definition smp.c:102
void trampoline_send_startup_ipi(cpu_t *cpu, cpuid_t cpuId, lapic_id_t lapicId)
Sends the startup IPI to a CPU to start it up.
Definition trampoline.c:63
void trampoline_deinit(void)
Deinitializes the trampoline by restoring the original contents of the trampoline memory location.
Definition trampoline.c:51
uint64_t trampoline_wait_ready(clock_t timeout)
Waits for the currently starting CPU to signal that it is ready.
Definition trampoline.c:75
void trampoline_init(void)
Initializes the trampoline by copying the trampoline code to its designated memory location.
Definition trampoline.c:23
#define CPU_MAX
Maximum number of CPUs supported.
Definition cpu_id.h:14
uint64_t cpu_init(cpu_t *cpu, cpuid_t id)
Initializes a CPU structure as part of the boot process.
Definition cpu.c:16
#define CPU_ID_BOOTSTRAP
ID of the bootstrap CPU.
Definition cpu_id.h:19
uint16_t cpuid_t
Type used to identify a CPU.
Definition cpu_id.h:29
#define ALIGNED(alignment)
GCC aligned attribute.
Definition defs.h:22
lapic_id_t lapic_self_id(void)
Get the lapic id of the current cpu.
Definition apic.c:171
void lapic_send_ipi(lapic_id_t id, interrupt_t vector)
Send an Inter-Processor Interrupt (IPI) to a local apic.
Definition apic.c:225
NORETURN void panic(const interrupt_frame_t *frame, const char *format,...)
Panic the kernel, printing a message and halting.
Definition panic.c:362
#define LOG_INFO(format,...)
Definition log.h:87
@ PML_PRESENT
@ PML_WRITE
@ PML_GLOBAL
void * vmm_alloc(space_t *space, void *virtAddr, uint64_t length, pml_flags_t pmlFlags, vmm_alloc_flags_t allocFlags)
Allocates and maps virtual memory in a given address space.
Definition vmm.c:168
@ VMM_ALLOC_FAIL_IF_MAPPED
If set and any page is already mapped, fail and set errno to EEXIST.
Definition vmm.h:124
#define PAGE_SIZE
Memory page size.
Definition proc.h:140
#define NULL
Pointer error value.
Definition NULL.h:23
#define ERR
Integer error value.
Definition ERR.h:17
#define MSR_CPU_ID
Definition regs.h:13
static void msr_write(uint32_t msr, uint64_t value)
Definition regs.h:71
static void smp_halt_ipi(interrupt_frame_t *frame)
Definition smp.c:89
static atomic_uint16_t haltedAmount
Definition smp.c:24
#define ATOMIC_VAR_INIT(value)
Definition stdatomic.h:74
#define atomic_fetch_add(object, operand)
Definition stdatomic.h:283
__UINT64_TYPE__ uint64_t
Definition stdint.h:17
__UINT8_TYPE__ uint8_t
Definition stdint.h:11
__UINT16_TYPE__ uint16_t
Definition stdint.h:13
_PUBLIC void * memset(void *s, int c, size_t n)
Definition memset.c:4
CPU structure.
Definition cpu.h:42
cpuid_t id
Definition cpu.h:43
interrupt_controller_type_t type
Definition tables.h:132
Trap Frame Structure.
Definition interrupt.h:42
Multiple APIC Description Table.
Definition tables.h:182
Processor Local APIC.
Definition tables.h:153
interrupt_controller_header_t header
Definition tables.h:154