xref: /haiku/headers/private/kernel/arch/x86/descriptors.h (revision b55a57da7173b9af0432bd3e148d03f06161d036)
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_DESCRIPTORS_H
9 #define _KERNEL_ARCH_x86_DESCRIPTORS_H
10 
11 
12 #define KERNEL_CODE_SEG	0x8
13 #define KERNEL_DATA_SEG	0x10
14 
15 #define USER_CODE_SEG	0x1b
16 #define USER_DATA_SEG	0x23
17 
18 #define APM_CODE32_SEGMENT	0x28
19 #define APM_CODE16_SEGMENT	0x30
20 #define APM_DATA_SEGMENT	0x38
21 
22 #define BIOS_DATA_SEGMENT	0x40
23 
24 #ifndef _ASSEMBLER
25 	// this file can also be included from assembler as well
26 	// (and is in arch_interrupts.S)
27 
28 #define DOUBLE_FAULT_TSS_BASE_SEGMENT 9
29 #define TSS_BASE_SEGMENT (DOUBLE_FAULT_TSS_BASE_SEGMENT + smp_get_num_cpus())
30 #define TLS_BASE_SEGMENT (TSS_BASE_SEGMENT + smp_get_num_cpus())
31 #define APM_BASE_SEGMENT (TLS_BASE_SEGMENT + smp_get_num_cpus())
32 
33 
34 // defines entries in the GDT/LDT
35 
36 typedef struct segment_descriptor {
37 	uint16 limit_00_15;				// bit	 0 - 15
38 	uint16 base_00_15;				//		16 - 31
39 	uint32 base_23_16 : 8;			//		 0 -  7
40 	uint32 type : 4;				//		 8 - 11
41 	uint32 desc_type : 1;			//		12		(0 = system, 1 = code/data)
42 	uint32 privilege_level : 2;		//		13 - 14
43 	uint32 present : 1;				//		15
44 	uint32 limit_19_16 : 4;			//		16 - 19
45 	uint32 available : 1;			//		20
46 	uint32 zero : 1;				//		21
47 	uint32 d_b : 1;					//		22
48 	uint32 granularity : 1;			//		23
49 	uint32 base_31_24 : 8;			//		24 - 31
50 } segment_descriptor;
51 
52 enum descriptor_privilege_levels {
53 	DPL_KERNEL = 0,
54 	DPL_USER = 3,
55 };
56 
57 enum descriptor_types {
58 	// segment types
59 	DT_CODE_EXECUTE_ONLY = 0x8,
60 	DT_CODE_ACCESSED = 0x9,
61 	DT_CODE_READABLE = 0xa,
62 	DT_CODE_CONFORM = 0xc,
63 	DT_DATA_READ_ONLY = 0x0,
64 	DT_DATA_ACCESSED = 0x1,
65 	DT_DATA_WRITEABLE = 0x2,
66 	DT_DATA_EXPANSION_DOWN = 0x4,
67 
68 	DT_TSS = 9,
69 		/* non busy, 32 bit */
70 
71 	// descriptor types
72 	DT_SYSTEM_SEGMENT = 0,
73 	DT_CODE_DATA_SEGMENT = 1,
74 };
75 
76 static inline void
77 clear_segment_descriptor(struct segment_descriptor *desc)
78 {
79 	*(long long *)desc = 0;
80 }
81 
82 
83 static inline void
84 set_segment_descriptor_base(struct segment_descriptor *desc, addr_t base)
85 {
86 	desc->base_00_15 = (addr_t)base & 0xffff;	// base is 32 bits long
87 	desc->base_23_16 = ((addr_t)base >> 16) & 0xff;
88 	desc->base_31_24 = ((addr_t)base >> 24) & 0xff;
89 }
90 
91 
92 static inline void
93 set_segment_descriptor(struct segment_descriptor *desc, addr_t base, uint32 limit,
94 	uint8 type, uint8 privilegeLevel)
95 {
96 	set_segment_descriptor_base(desc, base);
97 
98 	// limit is 20 bits long
99 	if (limit & 0xfff00000) {
100 		desc->limit_00_15 = ((addr_t)limit >> 12) & 0x0ffff;
101 		desc->limit_19_16 = ((addr_t)limit >> 28) & 0xf;
102 		desc->granularity = 1;	// 4 KB granularity
103 	} else {
104 		desc->limit_00_15 = (addr_t)limit & 0x0ffff;
105 		desc->limit_19_16 = ((addr_t)limit >> 16) & 0xf;
106 		desc->granularity = 0;	// 1 byte granularity
107 	}
108 		limit >>= 12;
109 
110 
111 	desc->type = type;
112 	desc->desc_type = DT_CODE_DATA_SEGMENT;
113 	desc->privilege_level = privilegeLevel;
114 
115 	desc->present = 1;
116 	desc->available = 0;	// system available bit is currently not used
117 	desc->d_b = 1;			// 32-bit code
118 
119 	desc->zero = 0;
120 }
121 
122 
123 static inline void
124 set_tss_descriptor(struct segment_descriptor *desc, addr_t base, uint32 limit)
125 {
126 	// the TSS descriptor has a special layout different from the standard descriptor
127 	set_segment_descriptor_base(desc, base);
128 
129 	desc->limit_00_15 = (addr_t)limit & 0x0ffff;
130 	desc->limit_19_16 = 0;
131 
132 	desc->type = DT_TSS;
133 	desc->desc_type = DT_SYSTEM_SEGMENT;
134 	desc->privilege_level = DPL_KERNEL;
135 
136 	desc->present = 1;
137 	desc->granularity = 0;	// 1 Byte granularity
138 	desc->available = 0;	// system available bit is currently not used
139 	desc->d_b = 0;
140 
141 	desc->zero = 0;
142 }
143 
144 #endif	/* _ASSEMBLER */
145 
146 #endif	/* _KERNEL_ARCH_x86_DESCRIPTORS_H */
147