PatchworkOS  da8a090
A non-POSIX operating system.
Loading...
Searching...
No Matches
stack_pointer.h
Go to the documentation of this file.
1#pragma once
2
5
6#include <stdint.h>
7
8/**
9 * @brief Helpers for managing stacks.
10 * @defgroup kernel_cpu_stack_pointer Stack Pointer
11 * @ingroup kernel_cpu
12 *
13 * @{
14 */
15
16/**
17 * @brief The amount of guard pages to use for stacks.
18 */
19#define STACK_POINTER_GUARD_PAGES 1
20
21/**
22 * @brief Structure to define a stack in memory.
23 *
24 * A stack is defined as a region of page aligned memory that includes a guard page to catch stack overflows. The region
25 * of memory starts unmapped and when a page fault occurs within the stack region a new page is mapped to the faulting
26 * address.
27 *
28 * The guard page is always the page just below the bottom of the stack, and is never mapped. If a thread tries to
29 * access the guard page a page fault will occur, which can be used to detect stack overflows.
30 *
31 * The exception to the above is when using `stack_pointer_init_buffer()` to create a stack from a provided buffer, in
32 * this case there is no guard page and the entire region starts mapped.
33 *
34 * Note that in x86 the stack grows downwards, so we start at the top and grow towards the bottom and that the "push"
35 * operation moves the stack pointer first then writes to the location of the stack pointer, this means we actually set
36 * the inital stack pointer to be the address just outside the top of the stack.
37 */
38typedef struct
39{
40 uintptr_t top; ///< The top of the stack, this address is not inclusive.
41 uintptr_t bottom; ///< The bottom of the stack, this address is inclusive.
42 uintptr_t guardTop; ///< The top of the guard page, this address is inclusive.
43 uintptr_t guardBottom; ///< The bottom of the guard page, this address is inclusive.
44 uintptr_t lastPageFault; ///< The last page that caused a page fault, used to prevent infinite loops.
46
47/**
48 * @brief Initializes a stack pointer structure, does not allocate or map any memory.
49 *
50 * This is used to create stacks that grow dynamically, for example the kernel and user stacks of a thread.
51 *
52 * @param stack The stack pointer structure to initialize.
53 * @param maxAddress The maximum address the stack will start at, must be page aligned.
54 * @param maxPages The maximum amount of pages the stack can grow to, must not be 0.
55 * @return On success, `0`. On failure, `ERR` and `errno` is set.
56 */
58
59/**
60 * @brief Initializes a stack pointer structure using a provided buffer, does not allocate or map any memory.
61 *
62 * This is used to create stacks that do not grow dynamically, for example the exception and double fault stacks of a
63 * CPU.
64 *
65 * These stacks will not have a guard page.
66 *
67 * Will not take ownership of the provided buffer.
68 *
69 * @param stack The stack pointer structure to initialize.
70 * @param buffer The buffer to use for the stack, must be page aligned.
71 * @param pages The amount of pages the stack will use, must not be 0.
72 * @return On success, `0`. On failure, `ERR` and `errno` is set.
73 */
75
76/**
77 * @brief Deinitializes a stack pointer structure and unmaps any mapped memory.
78 *
79 * @param stack The stack pointer structure to deinitialize.
80 * @param thread The thread that owns the stack, used to get the address space to unmap the memory from.
81 */
83
84/**
85 * @brief Deinitializes a stack pointer structure that was initialized using `stack_pointer_init_buffer()`.
86 *
87 * This will not unmap any memory as the memory was provided by the caller.
88 *
89 * @param stack The stack pointer structure to deinitialize.
90 */
92
93/**
94 * @brief Check if an region is within the stack.
95 *
96 * @param stack The stack pointer structure.
97 * @param addr The starting address of the region.
98 * @param length The length of the region, in bytes.
99 * @return `true` if the region is within the stack, `false` otherwise.
100 */
102
103/**
104 * @brief Check if an region overlaps the guard.
105 *
106 * @param stack The stack pointer structure.
107 * @param addr The starting address of the region.
108 * @param length The length of the region, in bytes.
109 * @return `true` if the region overlaps the guard, `false` otherwise.
110 */
112
113/**
114 * @brief Poke the stack to ensure that a page fault will occur at the given offset.
115 *
116 * Used to avoid recursive page faults when handling stack overflows. For example, to grow the stack we need the virtual
117 * memory manager, but what if we run out of stack while in the VMM? We use this function to make sure the VMM will
118 * never run out of stack, to avoid this situation.
119 *
120 * @param offset The max offset from the current stack pointer to poke, in bytes. Will poke every PAGE_SIZE bytes up to
121 * the offset.
122 */
123void stack_pointer_poke(uint64_t offset);
124
125/** @} */
void stack_pointer_deinit_buffer(stack_pointer_t *stack)
Deinitializes a stack pointer structure that was initialized using stack_pointer_init_buffer().
uint64_t stack_pointer_init_buffer(stack_pointer_t *stack, void *buffer, uint64_t pages)
Initializes a stack pointer structure using a provided buffer, does not allocate or map any memory.
void stack_pointer_deinit(stack_pointer_t *stack, thread_t *thread)
Deinitializes a stack pointer structure and unmaps any mapped memory.
bool stack_pointer_overlaps_guard(stack_pointer_t *stack, uintptr_t addr, uint64_t length)
Check if an region overlaps the guard.
uint64_t stack_pointer_init(stack_pointer_t *stack, uintptr_t maxAddress, uint64_t maxPages)
Initializes a stack pointer structure, does not allocate or map any memory.
bool stack_pointer_is_in_stack(stack_pointer_t *stack, uintptr_t addr, uint64_t length)
Check if an region is within the stack.
void stack_pointer_poke(uint64_t offset)
Poke the stack to ensure that a page fault will occur at the given offset.
uint64_t maxPages
Definition mem.c:16
EFI_PHYSICAL_ADDRESS buffer
Definition mem.c:15
static pmm_stack_t stack
Definition pmm.c:38
__UINT64_TYPE__ uint64_t
Definition stdint.h:17
__UINTPTR_TYPE__ uintptr_t
Definition stdint.h:43
Structure to define a stack in memory.
uintptr_t top
The top of the stack, this address is not inclusive.
uintptr_t guardTop
The top of the guard page, this address is inclusive.
uintptr_t bottom
The bottom of the stack, this address is inclusive.
uintptr_t guardBottom
The bottom of the guard page, this address is inclusive.
uintptr_t lastPageFault
The last page that caused a page fault, used to prevent infinite loops.
Thread of execution structure.
Definition thread.h:63