1 | /* |
---|
2 | * hal_segmentation.h - Segmentation-related values and structures |
---|
3 | * |
---|
4 | * Copyright (c) 2017 Maxime Villard |
---|
5 | * |
---|
6 | * This file is part of ALMOS-MKH. |
---|
7 | * |
---|
8 | * ALMOS-MKH is free software; you can redistribute it and/or modify it |
---|
9 | * under the terms of the GNU General Public License as published by |
---|
10 | * the Free Software Foundation; version 2.0 of the License. |
---|
11 | * |
---|
12 | * ALMOS-MKH is distributed in the hope that it will be useful, but |
---|
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
---|
15 | * General Public License for more details. |
---|
16 | * |
---|
17 | * You should have received a copy of the GNU General Public License |
---|
18 | * along with ALMOS-MKH.; if not, write to the Free Software Foundation, |
---|
19 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
---|
20 | */ |
---|
21 | |
---|
22 | /* |
---|
23 | * The GDT has NGDT_MEM entries of 8-byte-sized, static memory entries. Then |
---|
24 | * there is a certain number of 16-byte-sized TSS entries, one for each CPU. |
---|
25 | */ |
---|
26 | #define GDT_NULL_SEL 0 /* Null descriptor */ |
---|
27 | #define GDT_KCODE_SEL 1 /* Kernel code descriptor */ |
---|
28 | #define GDT_KDATA_SEL 2 /* Kernel data descriptor */ |
---|
29 | #define GDT_UCODE_SEL 3 /* User code descriptor */ |
---|
30 | #define GDT_UDATA_SEL 4 /* User data descriptor */ |
---|
31 | #define NGDT_MEM 6 /* aligned */ |
---|
32 | |
---|
33 | #define GDT_CPU0TSS_SEL 0 /* cpu0's tss */ |
---|
34 | #define NGDT_DYN (256 - (NGDT_MEM / 2) * 16) |
---|
35 | |
---|
36 | /* |
---|
37 | * GDT Selectors Privileges |
---|
38 | */ |
---|
39 | #define ISPL(s) ((s) & SEL_RPL) |
---|
40 | #define USERMODE(c, f) (ISPL(c) == SEL_UPL) |
---|
41 | #define KERNELMODE(c, f) (ISPL(c) == SEL_KPL) |
---|
42 | #define SEL_KPL 0 /* kernel privilege level */ |
---|
43 | #define SEL_UPL 3 /* user privilege level */ |
---|
44 | #define SEL_RPL 3 /* requester's privilege level mask */ |
---|
45 | #define SEL_LDT 4 /* local descriptor table */ |
---|
46 | |
---|
47 | #define SYSSEL_START (NGDT_MEM * 8) |
---|
48 | |
---|
49 | /* Create a selector, with an index and a privilege */ |
---|
50 | #define GDT_FIXED_SEL(s,r) (((s) << 3) | r) |
---|
51 | #define GDT_DYNAM_SEL(s,r) ((SYSSEL_START + ((s) << 4)) | r) |
---|
52 | |
---|
53 | #ifndef x86_ASM |
---|
54 | |
---|
55 | /* |
---|
56 | * Offsets. |
---|
57 | */ |
---|
58 | #define GDT_ADDR_MEM(s,i) \ |
---|
59 | ((struct gdt_memseg *)((s) + ((i) << 3))) |
---|
60 | #define GDT_ADDR_SYS(s,i) \ |
---|
61 | ((struct gdt_sysseg *)((s) + (SYSSEL_START + ((i) << 4)))) |
---|
62 | |
---|
63 | /* |
---|
64 | * System segment descriptor (16 bytes): used for TSS and LDT. |
---|
65 | */ |
---|
66 | struct gdt_sysseg { |
---|
67 | uint64_t sd_lolimit:16; /* segment extent (lsb) */ |
---|
68 | uint64_t sd_lobase:24; /* segment base address (lsb) */ |
---|
69 | uint64_t sd_type:5; /* segment type */ |
---|
70 | uint64_t sd_dpl:2; /* segment descriptor priority level */ |
---|
71 | uint64_t sd_p:1; /* segment descriptor present */ |
---|
72 | uint64_t sd_hilimit:4; /* segment extent (msb) */ |
---|
73 | uint64_t sd_xx1:3; /* avl, long and def32 (not used) */ |
---|
74 | uint64_t sd_gran:1; /* limit granularity (byte/page) */ |
---|
75 | uint64_t sd_hibase:40; /* segment base address (msb) */ |
---|
76 | uint64_t sd_xx2:8; /* reserved */ |
---|
77 | uint64_t sd_zero:5; /* must be zero */ |
---|
78 | uint64_t sd_xx3:19; /* reserved */ |
---|
79 | } __packed; |
---|
80 | |
---|
81 | /* |
---|
82 | * Memory segment descriptor (8 bytes): used for cs, ds, etc. |
---|
83 | */ |
---|
84 | struct gdt_memseg { |
---|
85 | unsigned sd_lolimit:16; /* segment extent (lsb) */ |
---|
86 | unsigned sd_lobase:24; /* segment base address (lsb) */ |
---|
87 | unsigned sd_type:5; /* segment type */ |
---|
88 | unsigned sd_dpl:2; /* segment descriptor priority level */ |
---|
89 | unsigned sd_p:1; /* segment descriptor present */ |
---|
90 | unsigned sd_hilimit:4; /* segment extent (msb) */ |
---|
91 | unsigned sd_avl:1; /* available */ |
---|
92 | unsigned sd_long:1; /* long mode */ |
---|
93 | unsigned sd_def32:1; /* default 32 vs 16 bit size */ |
---|
94 | unsigned sd_gran:1; /* limit granularity (byte/page) */ |
---|
95 | unsigned sd_hibase:8; /* segment base address (msb) */ |
---|
96 | } __packed; |
---|
97 | |
---|
98 | /* |
---|
99 | * Common part of the above structures. Used to walk descriptor tables. |
---|
100 | */ |
---|
101 | struct common_segment_descriptor { |
---|
102 | unsigned sdc_lolimit:16; |
---|
103 | unsigned sdc_lobase:24; |
---|
104 | unsigned sdc_type:5; |
---|
105 | unsigned sdc_other:19; |
---|
106 | } __packed; |
---|
107 | |
---|
108 | /* |
---|
109 | * IDT descriptors (16 bytes). |
---|
110 | */ |
---|
111 | struct idt_seg { |
---|
112 | uint64_t gd_looffset:16;/* gate offset (lsb) */ |
---|
113 | uint64_t gd_selector:16;/* gate segment selector */ |
---|
114 | uint64_t gd_ist:3; /* IST select */ |
---|
115 | uint64_t gd_xx1:5; /* reserved */ |
---|
116 | uint64_t gd_type:5; /* segment type */ |
---|
117 | uint64_t gd_dpl:2; /* segment descriptor priority level */ |
---|
118 | uint64_t gd_p:1; /* segment descriptor present */ |
---|
119 | uint64_t gd_hioffset:48;/* gate offset (msb) */ |
---|
120 | uint64_t gd_xx2:8; /* reserved */ |
---|
121 | uint64_t gd_zero:5; /* must be zero */ |
---|
122 | uint64_t gd_xx3:19; /* reserved */ |
---|
123 | } __packed; |
---|
124 | |
---|
125 | /* |
---|
126 | * Region descriptors, used to load gdt/idt tables before segments yet exist. |
---|
127 | */ |
---|
128 | struct region_descriptor { |
---|
129 | uint16_t rd_limit; /* segment extent */ |
---|
130 | uint64_t rd_base; /* base address */ |
---|
131 | } __packed; |
---|
132 | |
---|
133 | struct tss { |
---|
134 | uint32_t tss_reserved1; |
---|
135 | uint64_t tss_rsp0; |
---|
136 | uint64_t tss_rsp1; |
---|
137 | uint64_t tss_rsp3; |
---|
138 | uint32_t tss_reserved2; |
---|
139 | uint32_t tss_reserved3; |
---|
140 | uint64_t tss_ist[7]; |
---|
141 | uint32_t tss_reserved4; |
---|
142 | uint32_t tss_reserved5; |
---|
143 | uint32_t tss_iobase; |
---|
144 | } __packed; |
---|
145 | |
---|
146 | #define IOMAP_INVALOFF 0xffff |
---|
147 | |
---|
148 | void lgdt(struct region_descriptor *); |
---|
149 | void lidt(struct region_descriptor *); |
---|
150 | void ltr(uint16_t); |
---|
151 | |
---|
152 | #endif /* !x86_ASM */ |
---|
153 | |
---|
154 | /* system segments and gate types */ |
---|
155 | #define SDT_SYSNULL 0 /* system null */ |
---|
156 | #define SDT_SYS286TSS 1 /* system 286 TSS available */ |
---|
157 | #define SDT_SYSLDT 2 /* system local descriptor table */ |
---|
158 | #define SDT_SYS286BSY 3 /* system 286 TSS busy */ |
---|
159 | #define SDT_SYS286CGT 4 /* system 286 call gate */ |
---|
160 | #define SDT_SYSTASKGT 5 /* system task gate */ |
---|
161 | #define SDT_SYS286IGT 6 /* system 286 interrupt gate */ |
---|
162 | #define SDT_SYS286TGT 7 /* system 286 trap gate */ |
---|
163 | #define SDT_SYSNULL2 8 /* system null again */ |
---|
164 | #define SDT_SYS386TSS 9 /* system 386 TSS available */ |
---|
165 | #define SDT_SYSNULL3 10 /* system null again */ |
---|
166 | #define SDT_SYS386BSY 11 /* system 386 TSS busy */ |
---|
167 | #define SDT_SYS386CGT 12 /* system 386 call gate */ |
---|
168 | #define SDT_SYSNULL4 13 /* system null again */ |
---|
169 | #define SDT_SYS386IGT 14 /* system 386 interrupt gate */ |
---|
170 | #define SDT_SYS386TGT 15 /* system 386 trap gate */ |
---|
171 | |
---|
172 | /* memory segment types */ |
---|
173 | #define SDT_MEMRO 16 /* memory read only */ |
---|
174 | #define SDT_MEMROA 17 /* memory read only accessed */ |
---|
175 | #define SDT_MEMRW 18 /* memory read write */ |
---|
176 | #define SDT_MEMRWA 19 /* memory read write accessed */ |
---|
177 | #define SDT_MEMROD 20 /* memory read only expand dwn limit */ |
---|
178 | #define SDT_MEMRODA 21 /* memory read only expand dwn limit accessed */ |
---|
179 | #define SDT_MEMRWD 22 /* memory read write expand dwn limit */ |
---|
180 | #define SDT_MEMRWDA 23 /* memory read write expand dwn limit accessed */ |
---|
181 | #define SDT_MEME 24 /* memory execute only */ |
---|
182 | #define SDT_MEMEA 25 /* memory execute only accessed */ |
---|
183 | #define SDT_MEMER 26 /* memory execute read */ |
---|
184 | #define SDT_MEMERA 27 /* memory execute read accessed */ |
---|
185 | #define SDT_MEMEC 28 /* memory execute only conforming */ |
---|
186 | #define SDT_MEMEAC 29 /* memory execute only accessed conforming */ |
---|
187 | #define SDT_MEMERC 30 /* memory execute read conforming */ |
---|
188 | #define SDT_MEMERAC 31 /* memory execute read accessed conforming */ |
---|
189 | |
---|
190 | /* |
---|
191 | * Entries in the Interrupt Descriptor Table (IDT) |
---|
192 | */ |
---|
193 | #define CPUVEC_MIN 0 |
---|
194 | #define CPUVEC_MAX 32 /* reserved entries for CPU exceptions */ |
---|
195 | #define LAPICVEC_MIN CPUVEC_MAX |
---|
196 | #define LAPICVEC_MAX (LAPICVEC_MIN + 1) |
---|
197 | |
---|
198 | #define NIDT 256 /* total number of IDT entries */ |
---|
199 | |
---|