1 /*
2  * Copyright (c) 2009 Corey Tabaka
3  * Copyright (c) 2014 Intel Corporation
4  * Copyright (c) 2024 Travis Geiselbrecht
5  *
6  * Use of this source code is governed by a MIT-style
7  * license that can be found in the LICENSE file or at
8  * https://opensource.org/licenses/MIT
9  */
10 #pragma once
11 
12 // System Selectors
13 #define NULL_SELECTOR       0x00
14 
15 // ********* x86 selectors *********
16 // Laid out slightly differently based on 32 vs 64 bit mode
17 #if ARCH_X86_64
18 
19 #define CODE_SELECTOR       0x08
20 #define CODE_64_SELECTOR    0x10
21 #define DATA_SELECTOR       0x18
22 #define USER_CODE_32_SELECTOR   0x20
23 #define USER_DATA_32_SELECTOR   0x28
24 #define USER_CODE_64_SELECTOR   0x30
25 #define USER_DATA_64_SELECTOR   0x38
26 #define TSS_SELECTOR_BASE       0x40
27 
28 #elif ARCH_X86_32
29 
30 #define CODE_SELECTOR       0x08
31 #define DATA_SELECTOR       0x10
32 #define USER_CODE_32_SELECTOR   0x18
33 #define USER_DATA_32_SELECTOR   0x20
34 #define TSS_SELECTOR_BASE       0x28
35 
36 #else
37 #error unknown architecture
38 #endif
39 
40 // Base selector for a gs segment per cpu (SMP_MAX_CPUS)
41 #define PERCPU_SELECTOR_BASE    (TSS_SELECTOR_BASE + 8 * SMP_MAX_CPUS)
42 
43 // Worksheet of what the syscall instructions do which affects the GDT layout:
44 // SYSENTER
45 //     CS = IA32_SYSENTER_CS
46 //     SS = IA32_SYSENTER_CS + 8
47 // SYSEXIT 32
48 //     CS = IA32_SYSENTER_CS + 16
49 //     SS = IA32_SYSENTER_CS + 24
50 // SYSEXIT 64
51 //     CS = IA32_SYSENTER_CS + 32
52 //     SS = IA32_SYSENTER_CS + 40
53 
54 // SYSCALL
55 //     CS = IA32_STAR.SYSCALL_CS
56 //     SS = IA32_STAR.SYSCALL_CS + 8
57 // SYSRET 32
58 //     CS = IA32_STAR.SYSRET_CS
59 //     SS = IA32_STAR.SYSRET_CS + 8
60 // SYSRET 64
61 //     CS = IA32_STAR.SYSRET_CS + 16
62 //     SS = IA32_STAR.SYSRET_CS + 8
63 
64 // code/data segment types (S = 1)
65 // bit 0 is A (accessed)
66 // bit 1 is W (accessed)
67 // bit 2 is E (expand-down)
68 // bit 3 is data (0) vs code (1)
69 
70 // data segment types:
71 #define SEG_TYPE_DATA_RO             0x0
72 #define SEG_TYPE_DATA_RW             0x2
73 #define SEG_TYPE_DATA_RO_EXPAND_DOWN 0x4
74 #define SEG_TYPE_DATA_RW_EXPAND_DOWN 0x6
75 
76 // code segment types:
77 // bit 3 is C (conforming)
78 #define SEG_TYPE_CODE_XO             0x9
79 #define SEG_TYPE_CODE_RO             0xa
80 #define SEG_TYPE_CODE_XO_CONFORMING  0xc
81 #define SEG_TYPE_CODE_RO_CONFORMING  0xe
82 
83 // system segment types (S = 0)
84 #define SEG_TYPE_TSS_16       0x1
85 #define SEG_TYPE_LDT          0x2 // usable in 64bit
86 #define SEG_TYPE_TSS_16_BUSY  0x3
87 #define SEG_TYPE_CALL_GATE_16 0x4
88 #define SEG_TYPE_TASK_GATE    0x5
89 #define SEG_TYPE_INT_GATE_16  0x6
90 #define SEG_TYPE_TRAP_GATE_16 0x7
91 #define SEG_TYPE_TSS          0x9 // usable in 64bit
92 #define SEG_TYPE_TSS_BUSY     0xb // usable in 64bit
93 #define SEG_TYPE_CALL_GATE    0xc // usable in 64bit
94 #define SEG_TYPE_INT_GATE     0xe // usable in 64bit
95 #define SEG_TYPE_TRAP_GATE    0xf // usable in 64bit
96 
97 #ifndef ASSEMBLY
98 
99 #include <sys/types.h>
100 
101 typedef uint16_t seg_sel_t;
102 
103 void x86_set_gdt_descriptor(seg_sel_t sel, void *base, uint32_t limit,
104                      uint8_t present, uint8_t ring, uint8_t sys, uint8_t type, uint8_t gran, uint8_t bits);
105 
106 #endif
107