xref: /haiku/headers/private/kernel/arch/x86/64/descriptors.h (revision 99d027cd0238c1d86da86d7c3f4200509ccc61a6)
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_SEG		0x08
12 #define KERNEL_DATA_SEG		0x10
13 #define USER_DATA_SEG		0x1b
14 #define USER_CODE_SEG		0x23
15 
16 
17 #ifndef _ASSEMBLER
18 
19 
20 #define TSS_BASE_SEGMENT	5
21 #define TSS_SEGMENT(cpu)	(TSS_BASE_SEGMENT + cpu * 2)
22 
23 
24 // Structure of a segment descriptor.
25 struct segment_descriptor {
26 	uint32 limit0 : 16;
27 	uint32 base0 : 24;
28 	uint32 type : 4;
29 	uint32 desc_type : 1;
30 	uint32 dpl : 2;
31 	uint32 present : 1;
32 	uint32 limit1 : 4;
33 	uint32 available : 1;
34 	uint32 long_mode : 1;
35 	uint32 d_b : 1;
36 	uint32 granularity : 1;
37 	uint32 base1 : 8;
38 } _PACKED;
39 
40 // Structure of a TSS segment descriptor.
41 struct tss_descriptor {
42 	uint32 limit0 : 16;
43 	uint32 base0 : 24;
44 	uint32 type : 4;
45 	uint32 desc_type : 1;
46 	uint32 dpl : 2;
47 	uint32 present : 1;
48 	uint32 limit1 : 4;
49 	uint32 available : 1;
50 	uint32 unused1 : 2;
51 	uint32 granularity : 1;
52 	uint32 base1 : 8;
53 	uint32 base2 : 32;
54 	uint32 unused2 : 32;
55 } _PACKED;
56 
57 // Structure of an interrupt descriptor.
58 struct interrupt_descriptor {
59 	uint32 base0 : 16;
60 	uint32 sel : 16;
61 	uint32 ist : 3;
62 	uint32 unused1 : 5;
63 	uint32 type : 4;
64 	uint32 unused2 : 1;
65 	uint32 dpl : 2;
66 	uint32 present : 1;
67 	uint32 base1 : 16;
68 	uint32 base2 : 32;
69 	uint32 reserved : 32;
70 } _PACKED;
71 
72 struct gdt_idt_descr {
73 	uint16 limit;
74 	addr_t base;
75 } _PACKED;
76 
77 struct tss {
78 	uint32 _reserved1;
79 	uint64 sp0;
80 	uint64 sp1;
81 	uint64 sp2;
82 	uint64 _reserved2;
83 	uint64 ist1;
84 	uint64 ist2;
85 	uint64 ist3;
86 	uint64 ist4;
87 	uint64 ist5;
88 	uint64 ist6;
89 	uint64 ist7;
90 	uint64 _reserved3;
91 	uint16 _reserved4;
92 	uint16 io_map_base;
93 } _PACKED;
94 
95 
96 static inline void
97 clear_segment_descriptor(segment_descriptor* desc)
98 {
99 	*(uint64*)desc = 0;
100 }
101 
102 
103 static inline void
104 set_segment_descriptor(segment_descriptor* desc, uint8 type, uint8 dpl)
105 {
106 	clear_segment_descriptor(desc);
107 
108 	// In 64-bit mode the CPU ignores the base/limit of code/data segments,
109 	// it always treats base as 0 and does no limit checks.
110 	desc->base0 = 0;
111 	desc->base1 = 0;
112 	desc->limit0 = 0xffff;
113 	desc->limit1 = 0xf;
114 	desc->granularity = 1;
115 
116 	desc->type = type;
117 	desc->desc_type = DT_CODE_DATA_SEGMENT;
118 	desc->dpl = dpl;
119 	desc->present = 1;
120 
121 	desc->long_mode = (type & DT_CODE_EXECUTE_ONLY) ? 1 : 0;
122 		// Must be set to 1 for code segments only.
123 }
124 
125 
126 static inline void
127 set_tss_descriptor(segment_descriptor* _desc, uint64 base, uint32 limit)
128 {
129 	clear_segment_descriptor(_desc);
130 	clear_segment_descriptor(&_desc[1]);
131 
132 	// The TSS descriptor is a special format in 64-bit mode, it is 16 bytes
133 	// instead of 8.
134 	tss_descriptor* desc = (tss_descriptor*)_desc;
135 
136 	desc->base0 = base & 0xffffff;
137 	desc->base1 = (base >> 24) & 0xff;
138 	desc->base2 = (base >> 32);
139 	desc->limit0 = limit & 0xffff;
140 	desc->limit1 = (limit >> 16) & 0xf;
141 
142 	desc->present = 1;
143 	desc->type = DT_TSS;
144 	desc->desc_type = DT_SYSTEM_SEGMENT;
145 	desc->dpl = DPL_KERNEL;
146 }
147 
148 
149 static inline void
150 set_interrupt_descriptor(interrupt_descriptor* desc, uint64 addr, uint32 type,
151 	uint16 seg, uint32 dpl, uint32 ist)
152 {
153 	desc->base0 = addr & 0xffff;
154 	desc->base1 = (addr >> 16) & 0xffff;
155 	desc->base2 = (addr >> 32) & 0xffffffff;
156 	desc->sel = seg;
157 	desc->ist = ist;
158 	desc->type = type;
159 	desc->dpl = dpl;
160 	desc->present = 1;
161 	desc->unused1 = 0;
162 	desc->unused2 = 0;
163 	desc->reserved = 0;
164 }
165 
166 
167 #endif	/* _ASSEMBLER */
168 
169 #endif	/* _KERNEL_ARCH_X86_64_DESCRIPTORS_H */
170