miniOS
x86_64 hobby kernel with SMP, VFS, and POSIX process model
Loading...
Searching...
No Matches
smp.h
Go to the documentation of this file.
1// MIT License
2//
3// Copyright (c) 2026 Christian Spoo
4//
5// Permission is hereby granted, free of charge, to any person obtaining a copy
6// of this software and associated documentation files (the "Software"), to deal
7// in the Software without restriction, including without limitation the rights
8// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9// copies of the Software, and to permit persons to whom the Software is
10// furnished to do so, subject to the following conditions:
11//
12// The above copyright notice and this permission notice shall be included in all
13// copies or substantial portions of the Software.
14//
15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21// SOFTWARE.
22
33
34#ifndef _MINIOS_ARCH_X86_64_SMP_H_
35#define _MINIOS_ARCH_X86_64_SMP_H_
36
37#include <miniOS/types.h>
38
39/* Maximum CPUs this kernel supports. Override at compile time with
40 -DMAX_CPUS=N. Sizes all per-CPU arrays. */
41#ifndef MAX_CPUS
42#define MAX_CPUS 8
43#endif
44
45/* Number of CPUs found by acpi_find_madt(). Includes BSP (cpu_id 0). */
47
48/* LAPIC IDs of all detected CPUs, indexed 0..smp_cpu_count-1.
49 Index 0 is always the BSP (the CPU running kernel_main). */
51
52/* ------------------------------------------------------------------ */
53/* Per-CPU state (cpu_t) */
54/* ------------------------------------------------------------------ */
55
56/* Forward declare thread struct (defined in sched.h) */
57struct thread;
58
67typedef struct cpu_t {
68 struct cpu_t *self; /* gs:0 — self pointer for cpu_local() */
69 uint32_t cpu_id; /* logical CPU index (0 = BSP) */
70 uint32_t lapic_id; /* hardware LAPIC ID from MADT */
71 struct thread *idle_thread; /* per-CPU idle thread */
72 uint8_t *kstack_base; /* base of this CPU's boot/idle kernel stack */
73 /* Per-CPU run queue.
74 Circular singly-linked list via thread->next.
75 idle_thread is always in the queue as the sentinel node.
76 queue_depth counts only non-idle RUNNABLE/BLOCKED threads. */
77 struct thread *run_queue_head; /* first thread in round-robin queue */
78 struct thread *run_queue_tail; /* last thread (tail->next == head) */
79 uint32_t queue_depth; /* count of non-idle threads on this CPU */
80 struct thread *current_thread; /* thread currently running on this CPU — gs:56 */
81 uint64_t kstack_top; /* per-CPU kernel stack top for SYSCALL/TSS RSP0 — gs:64 */
82 uint64_t user_rsp_scratch;/* per-CPU scratch: user RSP at SYSCALL entry — gs:72 */
83 /* PML4 physical address of an exited thread's address space, freed by
84 * sched_schedule() right after THIS CPU's own CR3 has moved off of it —
85 * never by sched_exit_current() itself, which runs with that same PML4
86 * still loaded in CR3. Freeing it there would return its physical frames
87 * (PML4 itself and everything beneath it) to the pool while this CPU is
88 * still translating every memory access through them; another CPU's
89 * concurrent pmm_alloc_frame() can then hand one of those frames out and
90 * zero/overwrite it (e.g. vmm_new_address_space()'s memset for a new,
91 * unrelated process), corrupting this CPU's live page tables out from
92 * under it. 0 = nothing pending. */
95
96/* Global array of cpu_t, indexed 0..smp_cpu_count-1.
97 Index 0 = BSP. Static allocation, sized by MAX_CPUS. */
98extern cpu_t g_cpus[MAX_CPUS];
99
100/* cpu_local() — return pointer to the current CPU's cpu_t.
101 Reads gs:0 (the self-pointer installed by per_cpu_init).
102 Works without explicit cpu_id because GS.base = &g_cpus[cpu_id].
103 Usage: cpu_t *cpu = cpu_local(); */
104static inline cpu_t *cpu_local(void) {
105 cpu_t *p;
106 __asm__ volatile("mov %%gs:0, %0" : "=r"(p) :: "memory");
107 return p;
108}
109
118void cpu_enable_sse(void);
119
131void per_cpu_init(uint32_t cpu_id);
132
133/* ------------------------------------------------------------------ */
134/* ACPI / SMP boot API */
135/* ------------------------------------------------------------------ */
136
146void acpi_find_madt(uint64_t mb_info_phys);
147
156void smp_boot_aps(void);
157
158/* ------------------------------------------------------------------ */
159/* SMP rendezvous barrier */
160/* ------------------------------------------------------------------ */
161
162/* AP rendezvous barrier counter.
163 Each AP atomically increments this when its per-CPU init is complete.
164 BSP waits until smp_aps_ready == smp_cpu_count - 1 (all APs checked in). */
165extern volatile uint32_t smp_aps_ready;
166
178
186void ap_barrier_checkin(void);
187
196void smp_wait_for_aps(void);
197
206void lapic_timer_init_ap(void);
207
209
210#endif /* _MINIOS_ARCH_X86_64_SMP_H_ */
void lapic_timer_init_ap(void)
Start the LAPIC timer on the calling AP.
Definition lapic.c:271
volatile uint32_t smp_aps_ready
Definition smp_boot.c:44
void cpu_enable_sse(void)
Enable SSE/SSE2 on the calling CPU.
Definition main.c:134
void acpi_find_madt(uint64_t mb_info_phys)
Parse ACPI MADT and populate smp_lapic_ids[]/smp_cpu_count.
Definition acpi.c:204
void ap_barrier_checkin(void)
Signal that this AP has completed its CPU init.
Definition smp_boot.c:48
void per_cpu_init(uint32_t cpu_id)
Initialise per-CPU GDT, TSS, IDT, and GS base for one CPU.
Definition per_cpu.c:61
static cpu_t * cpu_local(void)
Definition smp.h:104
cpu_t g_cpus[MAX_CPUS]
Definition per_cpu.c:49
uint32_t smp_cpu_count
Definition acpi.c:32
#define MAX_CPUS
Definition smp.h:42
uint8_t smp_lapic_ids[MAX_CPUS]
Definition acpi.c:33
void smp_boot_aps(void)
Send INIT-SIPI-SIPI sequence to all non-BSP CPUs.
Definition smp_boot.c:166
void per_cpu_update_rsp0(uint64_t rsp0)
Update this CPU's TSS RSP0 and cpu_t.kstack_top.
Definition per_cpu.c:55
void smp_wait_for_aps(void)
Block until all APs have checked in at the rendezvous barrier.
Definition smp_boot.c:55
Definition smp.h:67
uint64_t kstack_top
Definition smp.h:81
uint8_t * kstack_base
Definition smp.h:72
uint32_t lapic_id
Definition smp.h:70
struct thread * current_thread
Definition smp.h:80
uint64_t user_rsp_scratch
Definition smp.h:82
struct thread * run_queue_tail
Definition smp.h:78
uint64_t pending_free_pml4
Definition smp.h:93
uint32_t queue_depth
Definition smp.h:79
struct thread * run_queue_head
Definition smp.h:77
struct thread * idle_thread
Definition smp.h:71
uint32_t cpu_id
Definition smp.h:69
struct cpu_t * self
Definition smp.h:68
Definition sched.h:96
unsigned int uint32_t
Definition types.h:34
unsigned long int uint64_t
Definition types.h:37
unsigned char uint8_t
Definition types.h:28