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
clear_segment_descriptor(segment_descriptor * desc)95 clear_segment_descriptor(segment_descriptor* desc)
96 {
97 *(long long*)desc = 0;
98 }
99
100
101 static inline void
set_segment_descriptor_base(segment_descriptor * desc,addr_t base)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
set_segment_descriptor(segment_descriptor * desc,addr_t base,uint32 limit,uint8 type,uint8 privilegeLevel)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
set_tss_descriptor(segment_descriptor * desc,addr_t base,uint32 limit)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*
get_gdt(int32 cpu)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