xref: /haiku/headers/private/kernel/arch/x86/32/descriptors.h (revision 68ea01249e1e2088933cb12f9c28d4e5c5d1c9ef)
1 /*
2  * Copyright 2002-2006, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Copyright 2001-2002, Travis Geiselbrecht. All rights reserved.
6  * Distributed under the terms of the NewOS License.
7  */
8 #ifndef _KERNEL_ARCH_X86_32_DESCRIPTORS_H
9 #define _KERNEL_ARCH_X86_32_DESCRIPTORS_H
10 
11 
12 // Segments common for all CPUs.
13 #define KERNEL_CODE_SEGMENT			1
14 #define KERNEL_DATA_SEGMENT			2
15 
16 #define USER_CODE_SEGMENT			3
17 #define USER_DATA_SEGMENT			4
18 
19 #define BOOT_GDT_SEGMENT_COUNT		(USER_DATA_SEGMENT + 2) // match x86_64
20 
21 #define APM_CODE32_SEGMENT			5
22 #define APM_CODE16_SEGMENT			6
23 #define APM_DATA_SEGMENT			7
24 
25 #define BIOS_DATA_SEGMENT			8
26 
27 // Per-CPU segments.
28 #define TSS_SEGMENT					9
29 #define DOUBLE_FAULT_TSS_SEGMENT	10
30 #define KERNEL_TLS_SEGMENT			11
31 #define USER_TLS_SEGMENT			12
32 #define APM_SEGMENT					13
33 
34 #define GDT_SEGMENT_COUNT			14
35 
36 
37 #define KERNEL_CODE_SELECTOR	((KERNEL_CODE_SEGMENT << 3) | DPL_KERNEL)
38 #define KERNEL_DATA_SELECTOR	((KERNEL_DATA_SEGMENT << 3) | DPL_KERNEL)
39 
40 #define USER_CODE_SELECTOR	((USER_CODE_SEGMENT << 3) | DPL_USER)
41 #define USER_DATA_SELECTOR	((USER_DATA_SEGMENT << 3) | DPL_USER)
42 
43 #define KERNEL_TLS_SELECTOR	((KERNEL_TLS_SEGMENT << 3) | DPL_KERNEL)
44 
45 
46 #ifndef _ASSEMBLER
47 	// this file can also be included from assembler as well
48 	// (and is in arch_interrupts.S)
49 
50 // defines entries in the GDT/LDT
51 
52 struct segment_descriptor {
53 	uint16 limit_00_15;				// bit	 0 - 15
54 	uint16 base_00_15;				//		16 - 31
55 	uint32 base_23_16 : 8;			//		 0 -  7
56 	uint32 type : 4;				//		 8 - 11
57 	uint32 desc_type : 1;			//		12		(0 = system, 1 = code/data)
58 	uint32 privilege_level : 2;		//		13 - 14
59 	uint32 present : 1;				//		15
60 	uint32 limit_19_16 : 4;			//		16 - 19
61 	uint32 available : 1;			//		20
62 	uint32 zero : 1;				//		21
63 	uint32 d_b : 1;					//		22
64 	uint32 granularity : 1;			//		23
65 	uint32 base_31_24 : 8;			//		24 - 31
66 };
67 
68 struct interrupt_descriptor {
69 	uint32 a;
70 	uint32 b;
71 };
72 
73 struct tss {
74 	uint16 prev_task;
75 	uint16 unused0;
76 	uint32 sp0;
77 	uint32 ss0;
78 	uint32 sp1;
79 	uint32 ss1;
80 	uint32 sp2;
81 	uint32 ss2;
82 	uint32 cr3;
83 	uint32 eip, eflags, eax, ecx, edx, ebx, esp, ebp, esi, edi;
84 	uint32 es, cs, ss, ds, fs, gs;
85 	uint32 ldt_seg_selector;
86 	uint16 unused1;
87 	uint16 io_map_base;
88 };
89 
90 typedef segment_descriptor global_descriptor_table[GDT_SEGMENT_COUNT];
91 extern global_descriptor_table gGDTs[];
92 
93 
94 static inline void
95 clear_segment_descriptor(segment_descriptor* desc)
96 {
97 	*(long long*)desc = 0;
98 }
99 
100 
101 static inline void
102 set_segment_descriptor_base(segment_descriptor* desc, addr_t base)
103 {
104 	desc->base_00_15 = (addr_t)base & 0xffff;	// base is 32 bits long
105 	desc->base_23_16 = ((addr_t)base >> 16) & 0xff;
106 	desc->base_31_24 = ((addr_t)base >> 24) & 0xff;
107 }
108 
109 
110 static inline void
111 set_segment_descriptor(segment_descriptor* desc, addr_t base, uint32 limit,
112 	uint8 type, uint8 privilegeLevel)
113 {
114 	set_segment_descriptor_base(desc, base);
115 
116 	// limit is 20 bits long
117 	if (limit & 0xfff00000) {
118 		desc->limit_00_15 = ((addr_t)limit >> 12) & 0x0ffff;
119 		desc->limit_19_16 = ((addr_t)limit >> 28) & 0xf;
120 		desc->granularity = 1;	// 4 KB granularity
121 	} else {
122 		desc->limit_00_15 = (addr_t)limit & 0x0ffff;
123 		desc->limit_19_16 = ((addr_t)limit >> 16) & 0xf;
124 		desc->granularity = 0;	// 1 byte granularity
125 	}
126 
127 	desc->type = type;
128 	desc->desc_type = DT_CODE_DATA_SEGMENT;
129 	desc->privilege_level = privilegeLevel;
130 
131 	desc->present = 1;
132 	desc->available = 0;	// system available bit is currently not used
133 	desc->d_b = 1;			// 32-bit code
134 
135 	desc->zero = 0;
136 }
137 
138 
139 static inline void
140 set_tss_descriptor(segment_descriptor* desc, addr_t base, uint32 limit)
141 {
142 	// the TSS descriptor has a special layout different from the standard descriptor
143 	set_segment_descriptor_base(desc, base);
144 
145 	desc->limit_00_15 = (addr_t)limit & 0x0ffff;
146 	desc->limit_19_16 = 0;
147 
148 	desc->type = DT_TSS;
149 	desc->desc_type = DT_SYSTEM_SEGMENT;
150 	desc->privilege_level = DPL_KERNEL;
151 
152 	desc->present = 1;
153 	desc->granularity = 0;	// 1 Byte granularity
154 	desc->available = 0;	// system available bit is currently not used
155 	desc->d_b = 0;
156 
157 	desc->zero = 0;
158 }
159 
160 
161 static inline segment_descriptor*
162 get_gdt(int32 cpu)
163 {
164 	return gGDTs[cpu];
165 }
166 
167 
168 #endif	/* _ASSEMBLER */
169 
170 #endif	/* _KERNEL_ARCH_X86_32_DESCRIPTORS_H */
171