xref: /haiku/headers/private/kernel/arch/x86/32/descriptors.h (revision a085e81e62d7a860f809b4fb7c7bf5654c396985)
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 #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 
25 #ifndef _ASSEMBLER
26 	// this file can also be included from assembler as well
27 	// (and is in arch_interrupts.S)
28 
29 #define DOUBLE_FAULT_TSS_BASE_SEGMENT 9
30 #define TSS_BASE_SEGMENT	(DOUBLE_FAULT_TSS_BASE_SEGMENT + smp_get_num_cpus())
31 #define TLS_BASE_SEGMENT	(TSS_BASE_SEGMENT + smp_get_num_cpus())
32 #define APM_BASE_SEGMENT	(TLS_BASE_SEGMENT + smp_get_num_cpus())
33 
34 #define TSS_SEGMENT(cpu)	(TSS_BASE_SEGMENT + cpu)
35 
36 // defines entries in the GDT/LDT
37 
38 struct segment_descriptor {
39 	uint16 limit_00_15;				// bit	 0 - 15
40 	uint16 base_00_15;				//		16 - 31
41 	uint32 base_23_16 : 8;			//		 0 -  7
42 	uint32 type : 4;				//		 8 - 11
43 	uint32 desc_type : 1;			//		12		(0 = system, 1 = code/data)
44 	uint32 privilege_level : 2;		//		13 - 14
45 	uint32 present : 1;				//		15
46 	uint32 limit_19_16 : 4;			//		16 - 19
47 	uint32 available : 1;			//		20
48 	uint32 zero : 1;				//		21
49 	uint32 d_b : 1;					//		22
50 	uint32 granularity : 1;			//		23
51 	uint32 base_31_24 : 8;			//		24 - 31
52 };
53 
54 struct interrupt_descriptor {
55 	uint32 a;
56 	uint32 b;
57 };
58 
59 struct tss {
60 	uint16 prev_task;
61 	uint16 unused0;
62 	uint32 sp0;
63 	uint32 ss0;
64 	uint32 sp1;
65 	uint32 ss1;
66 	uint32 sp2;
67 	uint32 ss2;
68 	uint32 cr3;
69 	uint32 eip, eflags, eax, ecx, edx, ebx, esp, ebp, esi, edi;
70 	uint32 es, cs, ss, ds, fs, gs;
71 	uint32 ldt_seg_selector;
72 	uint16 unused1;
73 	uint16 io_map_base;
74 };
75 
76 
77 static inline void
78 clear_segment_descriptor(segment_descriptor* desc)
79 {
80 	*(long long*)desc = 0;
81 }
82 
83 
84 static inline void
85 set_segment_descriptor_base(segment_descriptor* desc, addr_t base)
86 {
87 	desc->base_00_15 = (addr_t)base & 0xffff;	// base is 32 bits long
88 	desc->base_23_16 = ((addr_t)base >> 16) & 0xff;
89 	desc->base_31_24 = ((addr_t)base >> 24) & 0xff;
90 }
91 
92 
93 static inline void
94 set_segment_descriptor(segment_descriptor* desc, addr_t base, uint32 limit,
95 	uint8 type, uint8 privilegeLevel)
96 {
97 	set_segment_descriptor_base(desc, base);
98 
99 	// limit is 20 bits long
100 	if (limit & 0xfff00000) {
101 		desc->limit_00_15 = ((addr_t)limit >> 12) & 0x0ffff;
102 		desc->limit_19_16 = ((addr_t)limit >> 28) & 0xf;
103 		desc->granularity = 1;	// 4 KB granularity
104 	} else {
105 		desc->limit_00_15 = (addr_t)limit & 0x0ffff;
106 		desc->limit_19_16 = ((addr_t)limit >> 16) & 0xf;
107 		desc->granularity = 0;	// 1 byte granularity
108 	}
109 
110 	desc->type = type;
111 	desc->desc_type = DT_CODE_DATA_SEGMENT;
112 	desc->privilege_level = privilegeLevel;
113 
114 	desc->present = 1;
115 	desc->available = 0;	// system available bit is currently not used
116 	desc->d_b = 1;			// 32-bit code
117 
118 	desc->zero = 0;
119 }
120 
121 
122 static inline void
123 set_tss_descriptor(segment_descriptor* desc, addr_t base, uint32 limit)
124 {
125 	// the TSS descriptor has a special layout different from the standard descriptor
126 	set_segment_descriptor_base(desc, base);
127 
128 	desc->limit_00_15 = (addr_t)limit & 0x0ffff;
129 	desc->limit_19_16 = 0;
130 
131 	desc->type = DT_TSS;
132 	desc->desc_type = DT_SYSTEM_SEGMENT;
133 	desc->privilege_level = DPL_KERNEL;
134 
135 	desc->present = 1;
136 	desc->granularity = 0;	// 1 Byte granularity
137 	desc->available = 0;	// system available bit is currently not used
138 	desc->d_b = 0;
139 
140 	desc->zero = 0;
141 }
142 
143 
144 #endif	/* _ASSEMBLER */
145 
146 #endif	/* _KERNEL_ARCH_X86_32_DESCRIPTORS_H */
147