miniOS
x86_64 hobby kernel with SMP, VFS, and POSIX process model
Toggle main menu visibility
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). */
46
extern
uint32_t
smp_cpu_count
;
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). */
50
extern
uint8_t
smp_lapic_ids
[
MAX_CPUS
];
51
52
/* ------------------------------------------------------------------ */
53
/* Per-CPU state (cpu_t) */
54
/* ------------------------------------------------------------------ */
55
56
/* Forward declare thread struct (defined in sched.h) */
57
struct
thread
;
58
67
typedef
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. */
93
uint64_t
pending_free_pml4
;
94
}
cpu_t
;
95
96
/* Global array of cpu_t, indexed 0..smp_cpu_count-1.
97
Index 0 = BSP. Static allocation, sized by MAX_CPUS. */
98
extern
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(); */
104
static
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
118
void
cpu_enable_sse
(
void
);
119
131
void
per_cpu_init
(
uint32_t
cpu_id);
132
133
/* ------------------------------------------------------------------ */
134
/* ACPI / SMP boot API */
135
/* ------------------------------------------------------------------ */
136
146
void
acpi_find_madt
(
uint64_t
mb_info_phys);
147
156
void
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). */
165
extern
volatile
uint32_t
smp_aps_ready
;
166
177
void
per_cpu_update_rsp0
(
uint64_t
rsp0);
178
186
void
ap_barrier_checkin
(
void
);
187
196
void
smp_wait_for_aps
(
void
);
197
206
void
lapic_timer_init_ap
(
void
);
207
209
210
#endif
/* _MINIOS_ARCH_X86_64_SMP_H_ */
lapic_timer_init_ap
void lapic_timer_init_ap(void)
Start the LAPIC timer on the calling AP.
Definition
lapic.c:271
smp_aps_ready
volatile uint32_t smp_aps_ready
Definition
smp_boot.c:44
cpu_enable_sse
void cpu_enable_sse(void)
Enable SSE/SSE2 on the calling CPU.
Definition
main.c:134
acpi_find_madt
void acpi_find_madt(uint64_t mb_info_phys)
Parse ACPI MADT and populate smp_lapic_ids[]/smp_cpu_count.
Definition
acpi.c:204
ap_barrier_checkin
void ap_barrier_checkin(void)
Signal that this AP has completed its CPU init.
Definition
smp_boot.c:48
per_cpu_init
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
cpu_local
static cpu_t * cpu_local(void)
Definition
smp.h:104
g_cpus
cpu_t g_cpus[MAX_CPUS]
Definition
per_cpu.c:49
smp_cpu_count
uint32_t smp_cpu_count
Definition
acpi.c:32
MAX_CPUS
#define MAX_CPUS
Definition
smp.h:42
smp_lapic_ids
uint8_t smp_lapic_ids[MAX_CPUS]
Definition
acpi.c:33
smp_boot_aps
void smp_boot_aps(void)
Send INIT-SIPI-SIPI sequence to all non-BSP CPUs.
Definition
smp_boot.c:166
per_cpu_update_rsp0
void per_cpu_update_rsp0(uint64_t rsp0)
Update this CPU's TSS RSP0 and cpu_t.kstack_top.
Definition
per_cpu.c:55
smp_wait_for_aps
void smp_wait_for_aps(void)
Block until all APs have checked in at the rendezvous barrier.
Definition
smp_boot.c:55
cpu_t
Definition
smp.h:67
cpu_t::kstack_top
uint64_t kstack_top
Definition
smp.h:81
cpu_t::kstack_base
uint8_t * kstack_base
Definition
smp.h:72
cpu_t::lapic_id
uint32_t lapic_id
Definition
smp.h:70
cpu_t::current_thread
struct thread * current_thread
Definition
smp.h:80
cpu_t::user_rsp_scratch
uint64_t user_rsp_scratch
Definition
smp.h:82
cpu_t::run_queue_tail
struct thread * run_queue_tail
Definition
smp.h:78
cpu_t::pending_free_pml4
uint64_t pending_free_pml4
Definition
smp.h:93
cpu_t::queue_depth
uint32_t queue_depth
Definition
smp.h:79
cpu_t::run_queue_head
struct thread * run_queue_head
Definition
smp.h:77
cpu_t::idle_thread
struct thread * idle_thread
Definition
smp.h:71
cpu_t::cpu_id
uint32_t cpu_id
Definition
smp.h:69
cpu_t::self
struct cpu_t * self
Definition
smp.h:68
thread
Definition
sched.h:96
types.h
uint32_t
unsigned int uint32_t
Definition
types.h:34
uint64_t
unsigned long int uint64_t
Definition
types.h:37
uint8_t
unsigned char uint8_t
Definition
types.h:28
include
miniOS
arch
x86_64
smp.h
Generated by
1.18.0