xref: /haiku/headers/private/kernel/arch/x86/64/descriptors.h (revision fce4895d1884da5ae6fb299d23c735c598e690b1)
1 /*
2  * Copyright 2012, Alex Smith, alex@alex-smith.me.uk.
3  * Distributed under the terms of the MIT License.
4  */
5 #ifndef _KERNEL_ARCH_X86_64_DESCRIPTORS_H
6 #define _KERNEL_ARCH_X86_64_DESCRIPTORS_H
7 
8 
9 // Segment definitions.
10 // Note that the ordering of these is important to SYSCALL/SYSRET.
11 #define KERNEL_CODE_SEGMENT		1
12 #define KERNEL_DATA_SEGMENT		2
13 #define USER_DATA_SEGMENT		3
14 #define USER_CODE_SEGMENT		4
15 
16 #define BOOT_GDT_SEGMENT_COUNT	(USER_CODE_SEGMENT + 1)
17 
18 #define KERNEL_CODE_SELECTOR	((KERNEL_CODE_SEGMENT << 3) | DPL_KERNEL)
19 #define KERNEL_DATA_SELECTOR	((KERNEL_DATA_SEGMENT << 3) | DPL_KERNEL)
20 
21 #define USER_CODE_SELECTOR	((USER_CODE_SEGMENT << 3) | DPL_USER)
22 #define USER_DATA_SELECTOR	((USER_DATA_SEGMENT << 3) | DPL_USER)
23 
24 
25 #ifndef _ASSEMBLER
26 
27 
28 // Structure of a segment descriptor.
29 struct segment_descriptor {
30 	uint32 limit0 : 16;
31 	uint32 base0 : 24;
32 	uint32 type : 4;
33 	uint32 desc_type : 1;
34 	uint32 dpl : 2;
35 	uint32 present : 1;
36 	uint32 limit1 : 4;
37 	uint32 available : 1;
38 	uint32 long_mode : 1;
39 	uint32 d_b : 1;
40 	uint32 granularity : 1;
41 	uint32 base1 : 8;
42 } _PACKED;
43 
44 struct tss {
45 	uint32 _reserved1;
46 	uint64 sp0;
47 	uint64 sp1;
48 	uint64 sp2;
49 	uint64 _reserved2;
50 	uint64 ist1;
51 	uint64 ist2;
52 	uint64 ist3;
53 	uint64 ist4;
54 	uint64 ist5;
55 	uint64 ist6;
56 	uint64 ist7;
57 	uint64 _reserved3;
58 	uint16 _reserved4;
59 	uint16 io_map_base;
60 } _PACKED;
61 
62 
63 static inline void
64 clear_segment_descriptor(segment_descriptor* desc)
65 {
66 	*(uint64*)desc = 0;
67 }
68 
69 
70 static inline void
71 set_segment_descriptor(segment_descriptor* desc, uint8 type, uint8 dpl)
72 {
73 	clear_segment_descriptor(desc);
74 
75 	// In 64-bit mode the CPU ignores the base/limit of code/data segments,
76 	// it always treats base as 0 and does no limit checks.
77 	desc->base0 = 0;
78 	desc->base1 = 0;
79 	desc->limit0 = 0xffff;
80 	desc->limit1 = 0xf;
81 	desc->granularity = 1;
82 
83 	desc->type = type;
84 	desc->desc_type = DT_CODE_DATA_SEGMENT;
85 	desc->dpl = dpl;
86 	desc->present = 1;
87 
88 	desc->long_mode = (type & DT_CODE_EXECUTE_ONLY) ? 1 : 0;
89 		// Must be set to 1 for code segments only.
90 }
91 
92 
93 #endif	/* _ASSEMBLER */
94 
95 #endif	/* _KERNEL_ARCH_X86_64_DESCRIPTORS_H */
96