PatchworkOS  c9fea19
A non-POSIX operating system.
Loading...
Searching...
No Matches
tss.h
Go to the documentation of this file.
1#pragma once
2
4
5#include <kernel/defs.h>
6#include <stdint.h>
7
8/**
9 * @brief Task State Segment
10 * @defgroup kernel_cpu_tss TSS
11 * @ingroup kernel_cpu
12 *
13 * The Task State Segment is more or less deprecated, we use it only to tell the cpu what stack pointer to use when
14 * handling interrupts. This is done using the Interrupt Stack Table (IST).
15 *
16 * @see [OSDev Wiki TTS](https://wiki.osdev.org/Task_State_Segment)
17 *
18 * @{
19 */
20
21/**
22 * @brief Interrupt Stack Table indices.
23 */
36
37/**
38 * @brief The IST index to use for exceptions.
39 */
40#define TSS_IST_EXCEPTION TSS_IST1
41
42/**
43 * @brief The IST index to use for double faults.
44 */
45#define TSS_IST_DOUBLE_FAULT TSS_IST2
46
47/**
48 * @brief The IST index to use for non-maskable interrupts.
49 */
50#define TSS_IST_NMI TSS_IST3
51
52/**
53 * @brief The IST index to use for other interrupts.
54 */
55#define TSS_IST_INTERRUPT TSS_IST4
56
57/**
58 * @brief Task State Segment structure.
59 * @struct tss_t
60 *
61 * The `rsp*` members store the stack to use when switching to a higher privilege level, we dont use these.
62 *
63 * Instead we have a total of 4 stacks used while in kernel space, 34 per-cpu stacks and 1 per-thread stack. Of course
64 * there is also the user stack used while in user space. But that is not relevant to the TSS and instead handled by the
65 * system call code.
66 *
67 * ## The per-cpu stacks
68 *
69 * The per-cpu stacks are:
70 * - Exception stack, used while handling exceptions, specified in ist[0].
71 * - Double fault stack, used while handling double faults, specified in ist[1].
72 * - Non-maskable interrupt stack, used while handling NMIs, specified in ist[2].
73 * - Interrupt stack, used while handling all other interrupts, specified in ist[3].
74 *
75 * We need four stacks as its possible for an exception to occur during an interrupt, for a double
76 * fault to occur during an exception, and of course Non-maskable interrupts can occur at any time, therefore we must
77 * ensure that in the worst case where each of these occur recursively we have a separate stack for each level.
78 *
79 * ## The per-thread stack
80 *
81 * The per-thread stack is called the "kernel stack" and is used while the thread is in kernel space and NOT handling an
82 * exception or interrupt. In effect this is used in system calls, boot, inital thread loading and if the thread is a
83 * kernel thread it is used all the time. This stack is not handled by the TSS, instead the system call code is
84 * responsible for switching to this stack when entering kernel space from user space.
85 *
86 * ## The Interrupt Stack Table
87 *
88 * The IST works by having the CPU check the IST index specified in the IDT gate for that interrupt or exception, if it
89 * has a non zero IST index it will then load that stack pointer from `ist[index - 1]` and switch to that stack before
90 * calling the interrupt or exception handler. This happens regardless of the current privilege level.
91 *
92 */
93typedef struct PACKED tss
94{
96 uint64_t rsp0; ///< Stack pointer to load when switching to ring 0, unused.
97 uint64_t rsp1; ///< Stack pointer to load when switching to ring 1, unused.
98 uint64_t rsp2; ///< Stack pointer to load when switching to ring 2, unused.
100 uint64_t ist[TSS_IST_COUNT]; ///< Interrupt Stack Table
103 uint16_t iopb; ///< Offset to the I/O permission bitmap, we set this to the size of the TSS to disable the bitmap.
104} tss_t;
105
106/**
107 * @brief Load the TSS.
108 *
109 * Loads the TSS using the `ltr` instruction, the TSS must already be present in the GDT.
110 */
111extern void tss_load(void);
112
113/**
114 * @brief Initialize a TSS structure.
115 *
116 * @param tss The TSS structure to initialize.
117 */
118void tss_init(tss_t* tss);
119
120/**
121 * @brief Load a stack into an IST entry.
122 *
123 * @param tss The TSS structure to load the IST into.
124 * @param ist The IST index to load the stack into.
125 * @param stack The stack to load into the TSS.
126 */
128
129/** @} */
void tss_ist_load(tss_t *tss, tss_ist_t ist, stack_pointer_t *stack)
Load a stack into an IST entry.
Definition tss.c:21
void tss_init(tss_t *tss)
Initialize a TSS structure.
Definition tss.c:5
tss_ist_t
Interrupt Stack Table indices.
Definition tss.h:25
void tss_load(void)
Load the TSS.
@ TSS_IST_COUNT
Definition tss.h:34
@ TSS_IST7
Definition tss.h:33
@ TSS_IST3
Definition tss.h:29
@ TSS_IST2
Definition tss.h:28
@ TSS_IST5
Definition tss.h:31
@ TSS_IST_NONE
Definition tss.h:26
@ TSS_IST6
Definition tss.h:32
@ TSS_IST1
Definition tss.h:27
@ TSS_IST4
Definition tss.h:30
#define PACKED
GCC packed attribute.
Definition defs.h:32
static pmm_stack_t stack
Definition pmm.c:38
__UINT32_TYPE__ uint32_t
Definition stdint.h:15
__UINT64_TYPE__ uint64_t
Definition stdint.h:17
__UINT16_TYPE__ uint16_t
Definition stdint.h:13
Structure to define a stack in memory.
Task State Segment structure.
Definition tss.h:94
uint32_t reserved1
Definition tss.h:95
uint64_t reserved2
Definition tss.h:99
uint64_t rsp1
Stack pointer to load when switching to ring 1, unused.
Definition tss.h:97
uint16_t iopb
Offset to the I/O permission bitmap, we set this to the size of the TSS to disable the bitmap.
Definition tss.h:103
uint64_t rsp0
Stack pointer to load when switching to ring 0, unused.
Definition tss.h:96
uint64_t reserved3
Definition tss.h:101
uint64_t rsp2
Stack pointer to load when switching to ring 2, unused.
Definition tss.h:98
uint16_t reserved4
Definition tss.h:102