PatchworkOS  3984a1d
A non-POSIX operating system.
Loading...
Searching...
No Matches
smp.c
Go to the documentation of this file.
1#include "trampoline.h"
2
3#include <kernel/cpu/cpu.h>
5#include <kernel/log/log.h>
6#include <kernel/log/panic.h>
7#include <kernel/mem/vmm.h>
10
11#include <kernel/cpu/regs.h>
12#include <sys/defs.h>
13
14#include <stdint.h>
15
16/**
17 * @brief Symmetric Multiprocessing support via APIC.
18 * @defgroup modules_smp SMP
19 * @ingroup modules
20 *
21 * Symmetric Multiprocessing (SMP) support is implemented using the Advanced Programmable Interrupt Controller (APIC)
22 * system.
23 *
24 * SMP initialization will panic if it, at any point, fails. This is because error recovery during CPU initialization is
25 * way outside the scope of my patience.
26 *
27 * @{
28 */
29
30/**
31 * @brief Starts the other CPUs in the system.
32 */
33static void smp_start_others(void)
34{
36
37 if (cpu_amount() > 1)
38 {
39 LOG_INFO("other cpus already started\n");
41 return;
42 }
43
45
48
51
52 LOG_INFO("bootstrap cpu already started\n");
53
55 if (madt == NULL)
56 {
57 panic(NULL, "MADT table not found");
58 }
59
62 {
63 if (lapic->header.type != INTERRUPT_CONTROLLER_PROCESSOR_LOCAL_APIC || bootstrapLapic->lapicId == lapic->apicId)
64 {
65 continue;
66 }
67
68 if (!(lapic->flags & PROCESSOR_LOCAL_APIC_ENABLED))
69 {
70 continue;
71 }
72
74 if (cpu == NULL)
75 {
76 panic(NULL, "Failed to allocate memory for cpu with lapicid %d", (uint64_t)lapic->apicId);
77 }
78 memset(cpu, 0, sizeof(cpu_t));
79
80 LOG_DEBUG("starting cpu with lapicid %d\n", (uint64_t)lapic->apicId);
82
84 {
85 panic(NULL, "Timeout waiting for cpu with lapicid %d to start", (uint64_t)lapic->apicId);
86 }
87 }
88
89 LOG_INFO("started %u additional cpu(s)\n", cpu_amount() - 1);
90
92
94}
95
96/** @} */
97
99{
100 switch (event->type)
101 {
104 break;
105 default:
106 break;
107 }
108
109 return 0;
110}
111
112MODULE_INFO("SMP Bootstrap", "Kai Norberg", "Symmetric Multiprocessing support via APIC", OS_VERSION, "MIT",
113 "BOOT_ALWAYS");
#define assert(expression)
Definition assert.h:29
int64_t y
Definition main.c:153
#define CLOCKS_PER_SEC
Definition clock_t.h:15
void interrupt_disable(void)
Disable interrupts and increment the disableDepth.
Definition interrupt.c:25
void interrupt_enable(void)
Decrement the CLI depth and enable interrupts if depth reaches zero and interrupts were previously en...
Definition interrupt.c:37
static cpu_t * cpu_get_unsafe(void)
Gets the current CPU structure without disabling interrupts.
Definition cpu.h:299
static uint16_t cpu_amount(void)
Gets the number of identified CPUs.
Definition cpu.h:244
#define CPU_ID_BOOTSTRAP
ID of the bootstrap CPU.
Definition cpu.h:56
NORETURN void panic(const interrupt_frame_t *frame, const char *format,...)
Panic the kernel, printing a message and halting.
Definition panic.c:267
#define LOG_INFO(format,...)
Definition log.h:91
#define LOG_DEBUG(format,...)
Definition log.h:85
@ PML_PRESENT
@ PML_WRITE
@ PML_GLOBAL
void * vmm_alloc(space_t *space, void *virtAddr, size_t length, pml_flags_t pmlFlags, vmm_alloc_flags_t allocFlags)
Allocates and maps virtual memory in a given address space.
Definition vmm.c:163
@ VMM_ALLOC_OVERWRITE
If any page is already mapped, overwrite the mapping.
Definition vmm.h:123
#define MODULE_INFO(_name, _author, _description, _version, _licence, _deviceTypes)
Macro to define module information.
Definition module.h:200
@ MODULE_EVENT_LOAD
Definition module.h:239
#define NULL
Pointer error value.
Definition NULL.h:23
#define ERR
Integer error value.
Definition ERR.h:17
#define PROCESSOR_LOCAL_APIC_ENABLED
Definition tables.h:141
#define INTERRUPT_CONTROLLER_PROCESSOR_LOCAL_APIC
Definition tables.h:121
sdt_header_t * acpi_tables_lookup(const char *signature, uint64_t minSize, uint64_t n)
Lookup the n'th table matching the signature.
Definition tables.c:261
#define MADT_FOR_EACH(madt, ic)
Iterate over all MADT interrupt controllers.
Definition tables.h:193
#define MADT_SIGNATURE
MADT table signature.
Definition tables.h:202
lapic_t * lapic_get(uint32_t cpuId)
Get the lapic data for the specified CPU.
Definition lapic.c:49
void trampoline_send_startup_ipi(cpu_t *cpu, lapic_id_t lapicId)
Sends the startup IPI to a CPU to start it up.
Definition trampoline.c:73
void trampoline_deinit(void)
Deinitializes the trampoline by restoring the original contents of the trampoline memory location.
Definition trampoline.c:58
uint64_t trampoline_wait_ready(clock_t timeout)
Waits for the currently starting CPU to signal that it is ready.
Definition trampoline.c:86
void trampoline_init(void)
Initializes the trampoline by copying the trampoline code to its designated memory location.
Definition trampoline.c:23
static void smp_start_others(void)
Starts the other CPUs in the system.
Definition smp.c:33
uint64_t _module_procedure(const module_event_t *event)
Definition smp.c:98
__UINT64_TYPE__ uint64_t
Definition stdint.h:17
_PUBLIC void * memset(void *s, int c, size_t n)
Definition memset.c:4
CPU structure.
Definition cpu.h:122
Local APIC Structure.
Definition lapic.h:123
Multiple APIC Description Table.
Definition tables.h:180
module_event_type_t type
Definition module.h:268
Processor Local APIC.
Definition tables.h:151