PatchworkOS  dbbdc99
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 kernel_smp SMP
19 * @ingroup kernel
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{
35 cli_push();
36
37 if (cpu_amount() > 1)
38 {
39 LOG_INFO("other cpus already started\n");
40 cli_pop();
41 return;
42 }
43
45
47 LOG_INFO("bootstrap cpu already started\n");
48
50 if (madt == NULL)
51 {
52 panic(NULL, "MADT table not found");
53 }
54
56 MADT_FOR_EACH(madt, lapic)
57 {
59 {
60 continue;
61 }
62
63 if (!(lapic->flags & PROCESSOR_LOCAL_APIC_ENABLED))
64 {
65 continue;
66 }
67
68 cpu_t* cpu =
70 if (cpu == NULL)
71 {
72 panic(NULL, "Failed to allocate memory for cpu with lapicid %d", (uint64_t)lapic->apicId);
73 }
74 memset(cpu, 0, sizeof(cpu_t));
75
76 LOG_DEBUG("starting cpu with lapicid %d\n", (uint64_t)lapic->apicId);
78
80 {
81 panic(NULL, "Timeout waiting for cpu with lapicid %d to start", (uint64_t)lapic->apicId);
82 }
83 }
84
85 LOG_INFO("started %u additional cpu(s)\n", cpu_amount() - 1);
86
88
89 cli_pop();
90}
91
92/** @} */
93
95{
96 switch (event->type)
97 {
100 break;
101 default:
102 break;
103 }
104
105 return 0;
106}
107
108MODULE_INFO("SMP Bootstrap", "Kai Norberg", "Symmetric Multiprocessing support via APIC", OS_VERSION, "MIT",
109 "BOOT_ALWAYS");
#define assert(expression)
Definition assert.h:29
#define CLOCKS_PER_SEC
Definition clock_t.h:15
#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:259
#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
static void cli_pop(void)
Decrements the CLI depth, re-enabling interrupts if depth reaches zero and interrupts were enabled pr...
Definition cli.h:42
static void cli_push(void)
Increments the CLI depth, disabling interrupts if depth was zero.
Definition cli.h:24
#define SELF
Macro to access data in the current cpu.
Definition percpu.h:85
static uint16_t cpu_amount(void)
Gets the number of identified CPUs.
Definition cpu.h:168
#define CPU_ID_BOOTSTRAP
ID of the bootstrap CPU.
Definition cpu.h:55
lapic_t PERCPU _pcpu_lapic
The per-CPU local APIC structure.
NORETURN void panic(const interrupt_frame_t *frame, const char *format,...)
Panic the kernel, printing a message and halting.
Definition panic.c:292
#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, size_t alignment, pml_flags_t pmlFlags, vmm_alloc_flags_t allocFlags)
Allocates and maps virtual memory in a given address space.
Definition vmm.c:153
@ VMM_ALLOC_OVERWRITE
If any page is already mapped, overwrite the mapping.
Definition vmm.h:122
#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
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:76
void trampoline_deinit(void)
Deinitializes the trampoline by restoring the original contents of the trampoline memory location.
Definition trampoline.c:61
uint64_t trampoline_wait_ready(clock_t timeout)
Waits for the currently starting CPU to signal that it is ready.
Definition trampoline.c:89
void trampoline_init(void)
Initializes the trampoline by copying the trampoline code to its designated memory location.
Definition trampoline.c:24
static void smp_start_others(void)
Starts the other CPUs in the system.
Definition smp.c:33
#define NULL
Pointer error value.
Definition NULL.h:25
#define ERR
Integer error value.
Definition ERR.h:17
#define PAGE_SIZE
The size of a memory page in bytes.
Definition PAGE_SIZE.h:8
uint64_t _module_procedure(const module_event_t *event)
Definition smp.c:94
__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:84
interrupt_controller_type_t type
Definition tables.h:130
lapic_id_t lapicId
Definition lapic.h:127
Multiple APIC Description Table.
Definition tables.h:180
module_event_type_t type
Definition module.h:268
Processor Local APIC.
Definition tables.h:151
interrupt_controller_header_t header
Definition tables.h:152