xref: /haiku/headers/private/kernel/arch/x86/64/descriptors.h (revision 27b32ee02c3ba1278e17c41fdd2c1768062ee99e)
1 /*
2  * Copyright 2012, Alex Smith, alex@alex-smith.me.uk.
3  * Distributed under the terms of the MIT License.
4  */
5 #ifndef _KERNEL_ARCH_X86_64_DESCRIPTORS_H
6 #define _KERNEL_ARCH_X86_64_DESCRIPTORS_H
7 
8 
9 // Segment definitions.
10 // Note that the ordering of these is important to SYSCALL/SYSRET.
11 #define KERNEL_CODE_SEGMENT		1
12 #define KERNEL_DATA_SEGMENT		2
13 #define USER32_CODE_SEGMENT		3
14 #define USER_DATA_SEGMENT		4
15 #define USER_CODE_SEGMENT		5
16 
17 #define BOOT_GDT_SEGMENT_COUNT	(USER_CODE_SEGMENT + 1)
18 
19 #define KERNEL_CODE_SELECTOR	((KERNEL_CODE_SEGMENT << 3) | DPL_KERNEL)
20 #define KERNEL_DATA_SELECTOR	((KERNEL_DATA_SEGMENT << 3) | DPL_KERNEL)
21 
22 #define USER32_CODE_SELECTOR	((USER32_CODE_SEGMENT << 3) | DPL_USER)
23 #define USER_CODE_SELECTOR		((USER_CODE_SEGMENT << 3) | DPL_USER)
24 #define USER_DATA_SELECTOR		((USER_DATA_SEGMENT << 3) | DPL_USER)
25 
26 
27 #ifndef _ASSEMBLER
28 
29 
30 // Structure of a segment descriptor.
31 struct segment_descriptor {
32 	uint32 limit0 : 16;
33 	uint32 base0 : 24;
34 	uint32 type : 4;
35 	uint32 desc_type : 1;
36 	uint32 dpl : 2;
37 	uint32 present : 1;
38 	uint32 limit1 : 4;
39 	uint32 available : 1;
40 	uint32 long_mode : 1;
41 	uint32 d_b : 1;
42 	uint32 granularity : 1;
43 	uint32 base1 : 8;
44 } _PACKED;
45 
46 struct tss {
47 	uint32 _reserved1;
48 	uint64 sp0;
49 	uint64 sp1;
50 	uint64 sp2;
51 	uint64 _reserved2;
52 	uint64 ist1;
53 	uint64 ist2;
54 	uint64 ist3;
55 	uint64 ist4;
56 	uint64 ist5;
57 	uint64 ist6;
58 	uint64 ist7;
59 	uint64 _reserved3;
60 	uint16 _reserved4;
61 	uint16 io_map_base;
62 } _PACKED;
63 
64 
65 static inline void
clear_segment_descriptor(segment_descriptor * desc)66 clear_segment_descriptor(segment_descriptor* desc)
67 {
68 	*(uint64*)desc = 0;
69 }
70 
71 
72 static inline void
set_segment_descriptor(segment_descriptor * desc,uint8 type,uint8 dpl)73 set_segment_descriptor(segment_descriptor* desc, uint8 type, uint8 dpl)
74 {
75 	clear_segment_descriptor(desc);
76 
77 	// In 64-bit mode the CPU ignores the base/limit of code/data segments,
78 	// it always treats base as 0 and does no limit checks.
79 	desc->base0 = 0;
80 	desc->base1 = 0;
81 	desc->limit0 = 0xffff;
82 	desc->limit1 = 0xf;
83 	desc->granularity = 1;
84 
85 	desc->type = type;
86 	desc->desc_type = DT_CODE_DATA_SEGMENT;
87 	desc->dpl = dpl;
88 	desc->present = 1;
89 
90 	desc->long_mode = (type & DT_CODE_EXECUTE_ONLY) ? 1 : 0;
91 		// Must be set to 1 for code segments only.
92 }
93 
94 
95 unsigned x86_64_set_user_tls_segment_base(int cpu, addr_t base);
96 
97 
98 #endif	/* _ASSEMBLER */
99 
100 #endif	/* _KERNEL_ARCH_X86_64_DESCRIPTORS_H */
101