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