Zephyr API Documentation 4.2.99
A Scalable Open Source RTOS
Loading...
Searching...
No Matches
segmentation.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2016 Intel Corporation
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7#ifndef ZEPHYR_INCLUDE_ARCH_X86_IA32_SEGMENTATION_H_
8#define ZEPHYR_INCLUDE_ARCH_X86_IA32_SEGMENTATION_H_
9
10#include <zephyr/types.h>
11
12/* Host gen_idt uses this header as well, don't depend on toolchain.h */
13#ifndef __packed
14#define __packed __attribute__((packed))
15#endif
16
17#ifdef __cplusplus
18extern "C" {
19#endif
20
21/* NOTE: We currently do not have definitions for 16-bit segment, currently
22 * assume everything we are working with is 32-bit
23 */
24
25#define SEG_TYPE_LDT 0x2
26#define SEG_TYPE_TASK_GATE 0x5
27#define SEG_TYPE_TSS 0x9
28#define SEG_TYPE_TSS_BUSY 0xB
29#define SEG_TYPE_CALL_GATE 0xC
30#define SEG_TYPE_IRQ_GATE 0xE
31#define SEG_TYPE_TRAP_GATE 0xF
32
33#define DT_GRAN_BYTE 0
34#define DT_GRAN_PAGE 1
35
36#define DT_READABLE 1
37#define DT_NON_READABLE 0
38
39#define DT_WRITABLE 1
40#define DT_NON_WRITABLE 0
41
42#define DT_EXPAND_DOWN 1
43#define DT_EXPAND_UP 0
44
45#define DT_CONFORM 1
46#define DT_NONCONFORM 0
47
48#define DT_TYPE_SYSTEM 0
49#define DT_TYPE_CODEDATA 1
50
51#ifndef _ASMLANGUAGE
52
53/* Section 8.2.1 of IA architecture SW developer manual, Vol 3. */
96
97#define SEG_SELECTOR(index, table, dpl) (index << 3 | table << 2 | dpl)
98
99/* References
100 *
101 * Section 5.8.3 (Call gates)
102 * Section 7.2.2 (TSS Descriptor)
103 * Section 3.4.5 (Segment descriptors)
104 * Section 6.11 (IDT Descriptors)
105 *
106 * IA architecture SW developer manual, Vol 3.
107 */
108struct __packed segment_descriptor {
109
110 /* First DWORD: 0-15 */
111 union {
112 /* IRQ, call, trap gates */
114
115 /* Task gates */
117
118 /* Everything else */
120 };
121
122 /* First DWORD: 16-31 */
123 union {
124 /* Call/Task/Interrupt/Trap gates */
126
127 /* TSS/LDT/Segments */
128 uint16_t base_low; /* Bits 0-15 */
129 };
130
131 /* Second DWORD: 0-7 */
132 union {
133 /* TSS/LDT/Segments */
134 uint8_t base_mid; /* Bits 16-23 */
135
136 /* Task gates */
138
139 /* IRQ/Trap/Call Gates */
140 struct {
141 /* Reserved except in case of call gates */
143
144 /* Bits 5-7 0 0 0 per CPU manual */
146 };
147 };
148
149 /* Second DWORD: 8-15 */
150 union {
151 /* Code or data Segments */
152 struct {
153 /* Set by the processor, init to 0 */
155
156 /* executable ? readable : writable */
158 /* executable ? conforming : direction */
160 /* 1=code 0=data */
162
163 /* Next 3 fields actually common to all */
164
165 /* 1=code or data, 0=system type */
167
170 };
171
172 /* System types */
173 struct {
174 /* One of the SEG_TYPE_* macros above */
176
177 /* Alas, C doesn't let you do a union of the first
178 * 4 bits of a bitfield and put the rest outside of it,
179 * it ends up getting padded.
180 */
182 };
183 };
184
185 /* Second DWORD: 16-31 */
186 union {
187 /* Call/IRQ/trap gates */
189
190 /* Task Gates */
192
193 /* segment/LDT/TSS */
194 struct {
196
197 /* flags */
198 uint8_t avl:1; /* CPU ignores this */
199
200 /* 1=Indicates 64-bit code segment in IA-32e mode */
201 uint8_t flags_l:1; /* L field */
202
203 uint8_t db:1; /* D/B field 1=32-bit 0=16-bit*/
205
206 uint8_t base_hi; /* Bits 24-31 */
207 };
208 };
209
210};
211
212
213/* Address of this passed to lidt/lgdt.
214 * IA manual calls this a 'pseudo descriptor'.
215 */
220
221
222/*
223 * Full linear address (segment selector+offset), for far jumps/calls
224 */
225struct __packed far_ptr {
227 void *offset;
230};
231
232
233#define DT_ZERO_ENTRY { { 0 } }
234
235/* NOTE: the below macros only work for fixed addresses provided at build time.
236 * Base addresses or offsets cannot be &some_variable, as pointer values are not
237 * known until link time and the compiler has to split the address into various
238 * fields in the segment selector well before that.
239 *
240 * If you really need to put &some_variable as the base address in some
241 * segment descriptor, you will either need to do the assignment at runtime
242 * or implement some tool to populate values post-link like gen_idt does.
243 */
244#define _LIMIT_AND_BASE(base_p, limit_p, granularity_p) \
245 .base_low = (((uint32_t)base_p) & 0xFFFF), \
246 .base_mid = (((base_p) >> 16) & 0xFF), \
247 .base_hi = (((base_p) >> 24) & 0xFF), \
248 .limit_low = ((limit_p) & 0xFFFF), \
249 .limit_hi = (((limit_p) >> 16) & 0xF), \
250 .granularity = (granularity_p), \
251 .flags_l = 0, \
252 .db = 1, \
253 .avl = 0
254
255#define _SEGMENT_AND_OFFSET(segment_p, offset_p) \
256 .segment_selector = (segment_p), \
257 .offset_low = ((offset_p) & 0xFFFF), \
258 .offset_hi = ((offset_p) >> 16)
259
260#define _DESC_COMMON(dpl_p) \
261 .dpl = (dpl_p), \
262 .present = 1
263
264#define _SYS_DESC(type_p) \
265 .type = type_p, \
266 .descriptor_type = 0
267
268#define DT_CODE_SEG_ENTRY(base_p, limit_p, granularity_p, dpl_p, readable_p, \
269 conforming_p) \
270 { \
271 _DESC_COMMON(dpl_p), \
272 _LIMIT_AND_BASE(base_p, limit_p, granularity_p), \
273 .accessed = 0, \
274 .rw = (readable_p), \
275 .cd = (conforming_p), \
276 .executable = 1, \
277 .descriptor_type = 1 \
278 }
279
280#define DT_DATA_SEG_ENTRY(base_p, limit_p, granularity_p, dpl_p, writable_p, \
281 direction_p) \
282 { \
283 _DESC_COMMON(dpl_p), \
284 _LIMIT_AND_BASE(base_p, limit_p, granularity_p), \
285 .accessed = 0, \
286 .rw = (writable_p), \
287 .cd = (direction_p), \
288 .executable = 0, \
289 .descriptor_type = 1 \
290 }
291
292#define DT_LDT_ENTRY(base_p, limit_p, granularity_p, dpl_p) \
293 { \
294 _DESC_COMMON(dpl_p), \
295 _LIMIT_AND_BASE(base_p, limit_p, granularity_p), \
296 _SYS_DESC(SEG_TYPE_LDT) \
297 }
298
299#define DT_TSS_ENTRY(base_p, limit_p, granularity_p, dpl_p) \
300 { \
301 _DESC_COMMON(dpl_p), \
302 _LIMIT_AND_BASE(base_p, limit_p, granularity_p), \
303 _SYS_DESC(SEG_TYPE_TSS) \
304 }
305
306/* "standard" TSS segments that don't stuff extra data past the end of the
307 * TSS struct
308 */
309#define DT_TSS_STD_ENTRY(base_p, dpl_p) \
310 DT_TSS_ENTRY(base_p, sizeof(struct task_state_segment), DT_GRAN_BYTE, \
311 dpl_p)
312
313#define DT_TASK_GATE_ENTRY(segment_p, dpl_p) \
314 { \
315 _DESC_COMMON(dpl_p), \
316 _SYS_DESC(SEG_TYPE_TASK_GATE), \
317 .segment_selector = (segment_p) \
318 }
319
320#define DT_IRQ_GATE_ENTRY(segment_p, offset_p, dpl_p) \
321 { \
322 _DESC_COMMON(dpl_p), \
323 _SEGMENT_AND_OFFSET(segment_p, offset_p), \
324 _SYS_DESC(SEG_TYPE_IRQ_GATE), \
325 .always_0_0 = 0 \
326 }
327
328#define DT_TRAP_GATE_ENTRY(segment_p, offset_p, dpl_p) \
329 { \
330 _DESC_COMMON(dpl_p), \
331 _SEGMENT_AND_OFFSET(segment_p, offset_p), \
332 _SYS_DESC(SEG_TYPE_TRAP_GATE), \
333 .always_0_0 = 0 \
334 }
335
336#define DT_CALL_GATE_ENTRY(segment_p, offset_p, dpl_p, param_count_p) \
337 { \
338 _DESC_COMMON(dpl_p), \
339 _SEGMENT_AND_OFFSET(segment_p, offset_p), \
340 _SYS_DESC(SEG_TYPE_TRAP_GATE), \
341 .reserved_or_param = (param_count_p), \
342 .always_0_0 = 0 \
343 }
344
345#define DTE_BASE(dt_entry) ((dt_entry)->base_low | \
346 ((dt_entry)->base_mid << 16) | \
347 ((dt_entry)->base_hi << 24))
348
349#define DTE_LIMIT(dt_entry) ((dt_entry)->limit_low | \
350 ((dt_entry)->limit_hi << 16))
351
352#define DTE_OFFSET(dt_entry) ((dt_entry)->offset_low | \
353 ((dt_entry)->offset_hi << 16))
354
355#define DT_INIT(entries) { sizeof(entries) - 1, &entries[0] }
356
357#ifdef CONFIG_SET_GDT
358/* This is either the ROM-based GDT in crt0.S or generated by gen_gdt.py,
359 * depending on CONFIG_GDT_DYNAMIC
360 */
361extern struct pseudo_descriptor _gdt;
362#endif
363
364extern const struct pseudo_descriptor z_idt;
365
375static inline void z_sd_set_seg_offset(struct segment_descriptor *sd,
376 uint16_t segment_selector,
377 uint32_t offset)
378{
379 sd->offset_low = offset & 0xFFFFU;
380 sd->offset_hi = offset >> 16U;
381 sd->segment_selector = segment_selector;
382 sd->always_0_0 = 0U;
383}
384
385
394static inline void z_init_irq_gate(struct segment_descriptor *sd,
395 uint16_t seg_selector, uint32_t offset,
396 uint32_t dpl)
397{
398 z_sd_set_seg_offset(sd, seg_selector, offset);
399 sd->dpl = dpl;
401 sd->present = 1U;
403}
404
410static inline void _set_tss(uint16_t sel)
411{
412 __asm__ __volatile__ ("ltr %0" :: "r" (sel));
413}
414
415
421static inline uint16_t _get_tss(void)
422{
423 uint16_t sel;
424
425 __asm__ __volatile__ ("str %0" : "=r" (sel));
426 return sel;
427}
428
429
435static inline void _get_gdt(struct pseudo_descriptor *gdt)
436{
437 __asm__ __volatile__ ("sgdt %0" : "=m" (*gdt));
438}
439
440
446static inline void _get_idt(struct pseudo_descriptor *idt)
447{
448 __asm__ __volatile__ ("sidt %0" : "=m" (*idt));
449}
450
451
457static inline uint16_t _get_ldt(void)
458{
459 uint16_t ret;
460
461 __asm__ __volatile__ ("sldt %0" : "=m" (ret));
462 return ret;
463}
464
465
471static inline void _set_ldt(uint16_t ldt)
472{
473 __asm__ __volatile__ ("lldt %0" :: "m" (ldt));
474
475}
476
485static inline void _set_gdt(const struct pseudo_descriptor *gdt)
486{
487 __asm__ __volatile__ ("lgdt %0" :: "m" (*gdt));
488}
489
490
496static inline void z_set_idt(const struct pseudo_descriptor *idt)
497{
498 __asm__ __volatile__ ("lidt %0" :: "m" (*idt));
499}
500
501
507static inline uint16_t _get_cs(void)
508{
509 uint16_t cs = 0U;
510
511 __asm__ __volatile__ ("mov %%cs, %0" : "=r" (cs));
512 return cs;
513}
514
515
521static inline uint16_t _get_ds(void)
522{
523 uint16_t ds = 0U;
524
525 __asm__ __volatile__ ("mov %%ds, %0" : "=r" (ds));
526 return ds;
527}
528
529
530#endif /* _ASMLANGUAGE */
531
532#ifdef __cplusplus
533}
534#endif
535
536#endif /* ZEPHYR_INCLUDE_ARCH_X86_IA32_SEGMENTATION_H_ */
#define SEG_TYPE_IRQ_GATE
Definition segmentation.h:30
#define DT_TYPE_SYSTEM
Definition segmentation.h:48
__UINT32_TYPE__ uint32_t
Definition stdint.h:90
__UINT8_TYPE__ uint8_t
Definition stdint.h:88
__UINT16_TYPE__ uint16_t
Definition stdint.h:89
Definition segmentation.h:225
void * offset
Far pointer offset, unused when invoking a task.
Definition segmentation.h:227
uint16_t sel
Far pointer segment/gate selector.
Definition segmentation.h:229
Definition segmentation.h:216
uint16_t size
Definition segmentation.h:217
struct segment_descriptor * entries
Definition segmentation.h:218
Definition segmentation.h:108
uint8_t always_0_0
Definition segmentation.h:145
uint16_t reserved_task_gate_2
Definition segmentation.h:191
uint16_t base_low
Definition segmentation.h:128
uint8_t cd
Definition segmentation.h:159
uint8_t reserved_task_gate_1
Definition segmentation.h:137
uint8_t base_hi
Definition segmentation.h:206
uint8_t db
Definition segmentation.h:203
uint8_t executable
Definition segmentation.h:161
uint8_t rw
Definition segmentation.h:157
uint8_t avl
Definition segmentation.h:198
uint8_t present
Definition segmentation.h:169
uint8_t reserved_or_param
Definition segmentation.h:142
uint16_t offset_hi
Definition segmentation.h:188
uint8_t type
Definition segmentation.h:175
uint8_t descriptor_type
Definition segmentation.h:166
uint8_t base_mid
Definition segmentation.h:134
uint8_t flags_l
Definition segmentation.h:201
uint8_t accessed
Definition segmentation.h:154
uint16_t offset_low
Definition segmentation.h:119
uint16_t limit_low
Definition segmentation.h:113
uint8_t use_other_union
Definition segmentation.h:181
uint16_t reserved_task_gate_0
Definition segmentation.h:116
uint8_t limit_hi
Definition segmentation.h:195
uint16_t segment_selector
Definition segmentation.h:125
uint8_t granularity
Definition segmentation.h:204
uint8_t dpl
Definition segmentation.h:168
Definition segmentation.h:54
uint16_t ss
Definition segmentation.h:81
uint16_t reserved_9
Definition segmentation.h:86
uint16_t cs
Definition segmentation.h:79
uint16_t reserved_12
Definition segmentation.h:92
uint32_t ebp
Definition segmentation.h:74
uint32_t esp2
Definition segmentation.h:63
uint16_t ss1
Definition segmentation.h:61
uint32_t esi
Definition segmentation.h:75
uint16_t reserved_10
Definition segmentation.h:88
uint32_t edi
Definition segmentation.h:76
uint16_t reserved_4
Definition segmentation.h:65
uint32_t edx
Definition segmentation.h:71
uint32_t ecx
Definition segmentation.h:70
uint32_t cr3
Definition segmentation.h:66
uint16_t iomap
Definition segmentation.h:93
uint16_t reserved_3
Definition segmentation.h:62
uint16_t backlink
Definition segmentation.h:55
uint16_t es
Definition segmentation.h:77
uint16_t ss0
Definition segmentation.h:58
uint32_t ebx
Definition segmentation.h:72
uint16_t fs
Definition segmentation.h:85
uint16_t reserved_2
Definition segmentation.h:59
uint32_t esp1
Definition segmentation.h:60
uint32_t eip
Definition segmentation.h:67
uint16_t reserved_8
Definition segmentation.h:84
uint32_t eflags
Definition segmentation.h:68
uint16_t ldt_ss
Definition segmentation.h:89
uint16_t ds
Definition segmentation.h:83
uint16_t gs
Definition segmentation.h:87
uint16_t ss2
Definition segmentation.h:64
uint32_t eax
Definition segmentation.h:69
uint16_t reserved_5
Definition segmentation.h:78
uint16_t reserved_1
Definition segmentation.h:56
uint16_t reserved_6
Definition segmentation.h:80
uint8_t t
Definition segmentation.h:91
uint16_t reserved_7
Definition segmentation.h:82
uint32_t esp0
Definition segmentation.h:57
uint16_t reserved_11
Definition segmentation.h:90
uint32_t esp
Definition segmentation.h:73
uint32_t ssp
Definition segmentation.h:94