miniOS
x86_64 hobby kernel with SMP, VFS, and POSIX process model
Loading...
Searching...
No Matches
segment.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
23#ifndef _MINIOS_ARCH_X86_64_SEGMENT_H_
24#define _MINIOS_ARCH_X86_64_SEGMENT_H_
25
26#ifndef ASM_SOURCE
27
28#include <miniOS/types.h>
29
30// ********************************************************
31// CPU privilege levels
32// ********************************************************
33
34#define KERN_PRIVILEGE_LEVEL 0
35#define USER_PRIVILEGE_LEVEL 3
36
37// ********************************************************
38// x86 segment types
39// ********************************************************
40
41#define GDT_CS_TYPE 0x9A // present, system, Ring 0, r-x
42#define GDT_DS_TYPE 0x92 // present, system, Ring 0, rw-
43#define GDT_TSS_TYPE 0x89 // present, system, Ring 0, 32-bit TSS
44#define GDT_LDT_TYPE 0x82 // present, system, Ring 0, LDT
45
46#define USER_CS_TYPE 0xFA // present, non-system, Ring 3, r-x
47#define USER_DS_TYPE 0xF2 // present, non-system, Ring 3, rw-
48
49// ********************************************************
50// Global Descriptor Tables
51// ********************************************************
52
53// The NULL descriptor doesn't get a number ;-)
54#define GDT_CS_INDEX 1 // Kernel code segment
55#define GDT_DS_INDEX 2 // Kernel data segment
56#define USER_DS_INDEX 3 // User mode data segment (before UserCS for SYSRET STAR formula)
57#define USER_CS_INDEX 4 // User mode code segment
58#define GDT_TSS_INDEX 5 // Task state selector segment
59#define GDT_LDT_INDEX 6 // Local Descriptor Table
60
61// ********************************************************
62// Precomputed segment register values (selector values)
63// ********************************************************
64
65/* Kernel selectors: RPL=0, TI=0 (GDT) */
66#define KERNEL_CS_SEL SEG_REG_VAL(KERN_PRIVILEGE_LEVEL, 0, GDT_CS_INDEX) /* 0x08 */
67#define KERNEL_SS_SEL SEG_REG_VAL(KERN_PRIVILEGE_LEVEL, 0, GDT_DS_INDEX) /* 0x10 */
68
69/* User selectors: RPL=3, TI=0 (GDT). *
70 * USER_DS_INDEX=3 (0x1B) placed before USER_CS_INDEX=4 (0x23) in GDT for *
71 * SYSRETQ STAR formula: CS=STAR[63:48]+16, SS=STAR[63:48]+8. */
72#define USER_CS_SEL SEG_REG_VAL(USER_PRIVILEGE_LEVEL, 0, USER_CS_INDEX) /* 0x23 */
73#define USER_DS_SEL SEG_REG_VAL(USER_PRIVILEGE_LEVEL, 0, USER_DS_INDEX) /* 0x1B */
74
75// ********************************************************
76// RFLAGS constants
77// ********************************************************
78
79/* RFLAGS_IF: RFLAGS value with only IF (bit 1) and reserved bit 1 set. *
80 * Used as initial rflags for all kernel and user threads so that *
81 * hlt/sti sequences work correctly and user code runs with interrupts on. */
82#define RFLAGS_IF 0x202ULL
83
84#define GDT_CS SEG_REG_VAL(KERN_PRIVILEGE_LEVEL, 0, GDT_CS_INDEX)
85#define GDT_DS SEG_REG_VAL(KERN_PRIVILEGE_LEVEL, 0, GDT_DS_INDEX)
86#define GDT_TSS SEG_REG_VAL(KERN_PRIVILEGE_LEVEL, 0, GDT_TSS_INDEX)
87#define GDT_LDT SEG_REG_VAL(KERN_PRIVILEGE_LEVEL, 0, GDT_LDT_INDEX)
88
89// ********************************************************
90// Local Descriptor Table
91// ********************************************************
92
93#define NR_LDT_ENTRIES 2
94
95#define LDT_CS_INDEX 0 // Process code segment
96#define LDT_DS_INDEX 1 // Process data segment
97
98/* Structure is also used in IA-32e mode, however in that case all addresses can be set to 0 */
112
113#define __BUILD_SEG_DESC(base_addr, limit, _access, _long_mode, _size, _granularity) \
114 ((struct segment_descriptor) { \
115 .limit_15_0 = (limit) & 0xffff, \
116 .limit_19_16 = ((limit) >> 16) & 0xf, \
117 .base_addr_15_0 = (base_addr) & 0xffff, \
118 .base_addr_23_16 = ((base_addr) >> 16) & 0xff, \
119 .base_addr_31_24 = ((base_addr) >> 24) & 0xff, \
120 .u = 0, \
121 .long_mode = (_long_mode), \
122 .size = (_size), \
123 .granularity = (_granularity), \
124 .access = (_access) \
125 })
126
127/* Build a byte granular segment descriptor. */
128#define BUILD_SEG_DESC(base_addr, limit, access, long_mode, size) \
129 __BUILD_SEG_DESC(base_addr, limit, access, long_mode, size, 0)
130
131/* Build a 4KB granular segment descriptor. */
132#define BUILD_4KB_SEG_DESC(base_addr, limit, access, long_mode, size) \
133 __BUILD_SEG_DESC(base_addr, (limit >> 12), access, long_mode, size, 1)
134
135#define SEG_ADDR(seg_desc) \
136 (((seg_desc)->base_addr_31_24 << 24) | \
137 ((seg_desc)->base_addr_23_16 << 16) | \
138 (seg_desc)->base_15_0)
139
140#define SEG_SIZE(seg_desc) \
141 ((seg_desc)->granularity ? \
142 ((((seg_desc)->limit_19_16 << 16) | (seg_desc)->limit_15_0) << 12) : \
143 (((seg_desc)->limit_19_16 << 16) | (seg_desc)->limit_15_0))
144
145#endif
146
147// Construct segment register value
148#define SEG_REG_VAL(privilege, in_ldt, segment_index) \
149 (((segment_index) << 3) | ((in_ldt) << 2) | (privilege))
150
151// Return Request Privilege level of the specified segment selector
152#define SEG_REG_RPL(seg_reg_val) ((seg_reg_val) & 0x3)
153
154#define restore_system_segments \
155 pushq %rax; \
156 mov $GDT_DS, %ax; \
157 mov %ax, %ds; \
158 mov %ax, %es; \
159 mov %ax, %fs; \
160 mov %ax, %gs; \
161 popq %rax;
162
163#endif
Definition segment.h:99
uint8_t size
Definition segment.h:108
uint8_t u
Definition segment.h:106
uint16_t base_addr_15_0
Definition segment.h:101
uint8_t base_addr_31_24
Definition segment.h:110
uint8_t base_addr_23_16
Definition segment.h:102
uint8_t long_mode
Definition segment.h:107
uint8_t access
Definition segment.h:104
uint16_t limit_15_0
Definition segment.h:100
uint8_t granularity
Definition segment.h:109
uint8_t limit_19_16
Definition segment.h:105
unsigned short uint16_t
Definition types.h:31
unsigned char uint8_t
Definition types.h:28
typedef __attribute__