PatchworkOS  19e446b
A non-POSIX operating system.
Loading...
Searching...
No Matches
cpu.h
Go to the documentation of this file.
1#pragma once
2
3#ifndef __ASSEMBLER__
4#include <kernel/config.h>
6#include <kernel/cpu/tss.h>
7
8#include <assert.h>
9#include <stdint.h>
10#include <sys/proc.h>
11
12typedef struct cpu cpu_t;
13#endif
14
15/**
16 * @brief CPU
17 * @defgroup kernel_cpu CPU Management
18 * @ingroup kernel
19 *
20 * @{
21 */
22
23/**
24 * @brief The offset of the `self` member in the `cpu_t` structure.
25 */
26#define CPU_OFFSET_SELF 0x0
27
28/**
29 * @brief The offset of the `syscall_ctx_t` pointer in the `cpu_t` structure.
30 */
31#define CPU_OFFSET_SYSCALL_RSP 0x10
32
33/**
34 * @brief The offset of the `userRsp` member in the `cpu_t` structure.
35 */
36#define CPU_OFFSET_USER_RSP 0x18
37
38#ifndef __ASSEMBLER__
39
40/**
41 * @brief The offset of the `id` member in the `cpu_t` structure.
42 *
43 * Needed to access the CPU ID from assembly code.
44 */
45#define CPU_OFFSET_ID 0x8
46
47/**
48 * @brief Maximum number of CPUs supported.
49 */
50#define CPU_MAX UINT8_MAX
51
52/**
53 * @brief ID of the bootstrap CPU.
54 */
55#define CPU_ID_BOOTSTRAP 0
56
57/**
58 * @brief Invalid CPU ID.
59 */
60#define CPU_ID_INVALID UINT16_MAX
61
62/**
63 * @brief Type used to identify a CPU.
64 */
66
67/**
68 * @brief CPU stack canary value.
69 *
70 * Placed at the bottom of CPU stacks, we then check in the interrupt handler if any of the stacks have overflowed by
71 * checking if its canary has been modified.
72 */
73#define CPU_STACK_CANARY 0x1234567890ABCDEFULL
74
75/**
76 * @brief CPU structure.
77 * @struct cpu_t
78 *
79 * We allocate the stack buffers inside the `cpu_t` structure to avoid memory allocation during early boot.
80 *
81 * Must be stored aligned to a page boundary.
82 */
103
104static_assert(offsetof(cpu_t, self) == CPU_OFFSET_SELF,
105 "CPU_OFFSET_SELF does not match the offset of the self field in cpu_t");
106
107static_assert(offsetof(cpu_t, id) == CPU_OFFSET_ID, "CPU_OFFSET_ID does not match the offset of the id field in cpu_t");
108
109static_assert(offsetof(cpu_t, syscallRsp) == CPU_OFFSET_SYSCALL_RSP,
110 "CPU_OFFSET_SYSCALL_RSP does not match the offset of the syscallRsp field in cpu_t");
111
112static_assert(offsetof(cpu_t, userRsp) == CPU_OFFSET_USER_RSP,
113 "CPU_OFFSET_USER_RSP does not match the offset of the userRsp field in cpu_t");
114
115/**
116 * @brief Array of pointers to cpu_t structures for each CPU, indexed by CPU ID.
117 *
118 * We make this global since its accessed very frequently, so its a slight optimization.
119 */
120extern cpu_t* _cpus[CPU_MAX];
121
122/**
123 * @brief The number of CPUs currently identified.
124 *
125 * Use `cpu_amount()` over this variable.
126 */
127extern uint16_t _cpuAmount;
128
129/**
130 * @brief Initializes a CPU structure.
131 *
132 * Will note initialize percpu data, use `percpu_update()` after calling this function.
133 *
134 * @param cpu The CPU structure to initialize.
135 */
136void cpu_init(cpu_t* cpu);
137
138/**
139 * @brief Checks the current CPU for stack overflows.
140 *
141 * Checks the canary values at the bottom of each CPU stack and if its been modified panics.
142 */
144
145/**
146 * @brief Halts all other CPUs.
147 *
148 * @return On success, `0`. On failure, `ERR` and `errno` is set.
149 */
151
152/**
153 * @brief Gets the top of the interrupt stack for the current CPU.
154 *
155 * Usefull as we might need to retrieve the interrupt stack in assembly, so this avoid code duplication.
156 *
157 * @return The top of the interrupt stack.
158 */
160
161/**
162 * @brief Gets the number of identified CPUs.
163 *
164 * Use this over `_cpuAmount`.
165 *
166 * @return The number of identified CPUs.
167 */
168static inline uint16_t cpu_amount(void)
169{
170 return _cpuAmount;
171}
172
173/**
174 * @brief Gets a CPU structure by its ID.
175 *
176 * @param id The ID of the CPU to get.
177 * @return A pointer to the CPU structure, or `NULL` if no CPU with the given ID exists.
178 */
179static inline cpu_t* cpu_get_by_id(cpu_id_t id)
180{
181 if (id >= _cpuAmount)
182 {
183 return NULL;
184 }
185 return _cpus[id];
186}
187
188/**
189 * @brief Gets the next CPU in the CPU array.
190 *
191 * Wraps around to the first CPU if the current CPU is the last one.
192 *
193 * @param current The current CPU.
194 * @return A pointer to the next CPU.
195 */
196static inline cpu_t* cpu_get_next(cpu_t* current)
197{
198 cpu_id_t nextId = current->id + 1;
199 if (nextId >= _cpuAmount)
200 {
201 nextId = 0;
202 }
203 return _cpus[nextId];
204}
205
206/**
207 * @brief Macro to iterate over all CPUs.
208 *
209 * The main reason for using this macro is to avoid changes the the internal implementation of how CPUs are stored
210 * affecting other parts of the code.
211 *
212 * @param cpu Loop variable, a pointer to the current `cpu_t`.
213 */
214#define CPU_FOR_EACH(cpu) \
215 for (cpu_id_t _cpuId = 0; _cpuId < _cpuAmount; _cpuId++) \
216 for (cpu = _cpus[_cpuId]; cpu != NULL; cpu = NULL)
217
218#endif
219
220/** @} */
static char * id
Definition dwm.c:20
#define CONFIG_PERCPU_SIZE
Per-CPU data size configuration.
Definition config.h:173
#define CONFIG_INTERRUPT_STACK_PAGES
Interrupt stack configuration.
Definition config.h:21
static cpu_t * cpu_get_next(cpu_t *current)
Gets the next CPU in the CPU array.
Definition cpu.h:196
uint64_t cpu_halt_others(void)
Halts all other CPUs.
Definition cpu.c:115
void cpu_stacks_overflow_check(void)
Checks the current CPU for stack overflows.
Definition cpu.c:83
uintptr_t cpu_interrupt_stack_top(void)
Gets the top of the interrupt stack for the current CPU.
Definition cpu.c:124
#define CPU_OFFSET_SYSCALL_RSP
The offset of the syscall_ctx_t pointer in the cpu_t structure.
Definition cpu.h:31
uint16_t cpu_id_t
Type used to identify a CPU.
Definition cpu.h:65
void cpu_init(cpu_t *cpu)
Initializes a CPU structure.
Definition cpu.c:27
#define CPU_OFFSET_SELF
The offset of the self member in the cpu_t structure.
Definition cpu.h:26
#define CPU_MAX
Maximum number of CPUs supported.
Definition cpu.h:50
#define CPU_OFFSET_USER_RSP
The offset of the userRsp member in the cpu_t structure.
Definition cpu.h:36
cpu_t * _cpus[CPU_MAX]
Array of pointers to cpu_t structures for each CPU, indexed by CPU ID.
Definition cpu.c:24
#define CPU_OFFSET_ID
The offset of the id member in the cpu_t structure.
Definition cpu.h:45
static uint16_t cpu_amount(void)
Gets the number of identified CPUs.
Definition cpu.h:168
uint16_t _cpuAmount
The number of CPUs currently identified.
Definition cpu.c:25
static cpu_t * cpu_get_by_id(cpu_id_t id)
Gets a CPU structure by its ID.
Definition cpu.h:179
#define NULL
Pointer error value.
Definition NULL.h:25
#define PAGE_SIZE
The size of a memory page in bytes.
Definition PAGE_SIZE.h:8
#define offsetof(type, member)
Definition stddef.h:16
__UINT64_TYPE__ uint64_t
Definition stdint.h:17
__UINT8_TYPE__ uint8_t
Definition stdint.h:11
__UINTPTR_TYPE__ uintptr_t
Definition stdint.h:43
__UINT16_TYPE__ uint16_t
Definition stdint.h:13
CPU structure.
Definition cpu.h:84
uint16_t cli
The CLI depth counter used in cli_push() and cli_pop().
Definition cpu.h:91
cpu_id_t id
Definition cpu.h:86
uint8_t interruptStackBuffer[CONFIG_INTERRUPT_STACK_PAGES *PAGE_SIZE] ALIGNED(PAGE_SIZE)
uint64_t oldRflags
The rflags value before disabling interrupts.
Definition cpu.h:90
stack_pointer_t exceptionStack
Definition cpu.h:93
tss_t tss
Definition cpu.h:92
uint8_t nmiStackBuffer[CONFIG_INTERRUPT_STACK_PAGES *PAGE_SIZE] ALIGNED(PAGE_SIZE)
uint8_t doubleFaultStackBuffer[CONFIG_INTERRUPT_STACK_PAGES *PAGE_SIZE] ALIGNED(PAGE_SIZE)
uint8_t exceptionStackBuffer[CONFIG_INTERRUPT_STACK_PAGES *PAGE_SIZE] ALIGNED(PAGE_SIZE)
uint8_t percpu[CONFIG_PERCPU_SIZE] ALIGNED(PAGE_SIZE)
Buffer used for per-CPU data.
uint64_t userRsp
Definition cpu.h:88
stack_pointer_t interruptStack
Definition cpu.h:96
uint64_t syscallRsp
Definition cpu.h:87
stack_pointer_t nmiStack
Definition cpu.h:95
stack_pointer_t doubleFaultStack
Definition cpu.h:94
volatile bool inInterrupt
Definition cpu.h:89
cpu_t * self
Definition cpu.h:85
Structure to define a stack in memory.
Task State Segment structure.
Definition tss.h:94