xref: /xnu-8792.61.2/osfmk/i386/seg.h (revision 42e220869062b56f8d7d0726fd4c88954f87902c)
1 /*
2  * Copyright (c) 2000-2012 Apple Inc. All rights reserved.
3  *
4  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5  *
6  * This file contains Original Code and/or Modifications of Original Code
7  * as defined in and that are subject to the Apple Public Source License
8  * Version 2.0 (the 'License'). You may not use this file except in
9  * compliance with the License. The rights granted to you under the License
10  * may not be used to create, or enable the creation or redistribution of,
11  * unlawful or unlicensed copies of an Apple operating system, or to
12  * circumvent, violate, or enable the circumvention or violation of, any
13  * terms of an Apple operating system software license agreement.
14  *
15  * Please obtain a copy of the License at
16  * http://www.opensource.apple.com/apsl/ and read it before using this file.
17  *
18  * The Original Code and all software distributed under the License are
19  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23  * Please see the License for the specific language governing rights and
24  * limitations under the License.
25  *
26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27  */
28 /*
29  * @OSF_COPYRIGHT@
30  */
31 /*
32  * Mach Operating System
33  * Copyright (c) 1991,1990 Carnegie Mellon University
34  * All Rights Reserved.
35  *
36  * Permission to use, copy, modify and distribute this software and its
37  * documentation is hereby granted, provided that both the copyright
38  * notice and this permission notice appear in all copies of the
39  * software, derivative works or modified versions, and any portions
40  * thereof, and that both notices appear in supporting documentation.
41  *
42  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
43  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
44  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
45  *
46  * Carnegie Mellon requests users of this software to return to
47  *
48  *  Software Distribution Coordinator  or  [email protected]
49  *  School of Computer Science
50  *  Carnegie Mellon University
51  *  Pittsburgh PA 15213-3890
52  *
53  * any improvements or extensions that they make and grant Carnegie Mellon
54  * the rights to redistribute these changes.
55  */
56 #ifndef _I386_SEG_H_
57 #define _I386_SEG_H_
58 #ifndef __ASSEMBLER__
59 #include <stdint.h>
60 #include <mach/vm_types.h>
61 #include <mach/vm_param.h>
62 #include <architecture/i386/sel.h>
63 
64 /*
65  * i386 segmentation.
66  */
67 
68 static inline uint16_t
sel_to_selector(sel_t sel)69 sel_to_selector(sel_t   sel)
70 {
71 	union {
72 		sel_t           sel;
73 		uint16_t        selector;
74 	} tconv;
75 
76 	tconv.sel = sel;
77 
78 	return tconv.selector;
79 }
80 
81 static inline sel_t
selector_to_sel(uint16_t selector)82 selector_to_sel(uint16_t selector)
83 {
84 	union {
85 		uint16_t        selector;
86 		sel_t           sel;
87 	} tconv;
88 
89 	tconv.selector = selector;
90 
91 	return tconv.sel;
92 }
93 
94 #define LDTSZ_MAX       8192    /* maximal size of the kernel ldt in entries */
95 #define LDTSZ_DFL       (128)
96 #define LDTSZ           (LDTSZ_MAX)
97 #define LDTSZ_MIN       SEL_TO_INDEX(USER_SETTABLE)
98 /* kernel ldt entries */
99 
100 #define GDTSZ           19
101 
102 /*
103  * Interrupt table is always 256 entries long.
104  */
105 #define IDTSZ           256
106 
107 #include <sys/cdefs.h>
108 
109 /*
110  * Real segment descriptor.
111  */
112 struct real_descriptor {
113 	uint32_t        limit_low:16,   /* limit 0..15 */
114 	    base_low:16,                /* base  0..15 */
115 	    base_med:8,                 /* base  16..23 */
116 	    access:8,                   /* access byte */
117 	    limit_high:4,               /* limit 16..19 */
118 	    granularity:4,              /* granularity */
119 	    base_high:8;                /* base 24..31 */
120 };
121 struct real_descriptor64 {
122 	uint32_t        limit_low16:16, /* limit 0..15 */
123 	    base_low16:16,              /* base  0..15 */
124 	    base_med8:8,                /* base  16..23 */
125 	    access8:8,                  /* access byte */
126 	    limit_high4:4,              /* limit 16..19 */
127 	    granularity4:4,             /* granularity */
128 	    base_high8:8,               /* base 24..31 */
129 	    base_top32:32,              /* base 32..63 */
130 	    reserved32:32;              /* reserved/zero */
131 };
132 struct real_gate {
133 	uint32_t        offset_low:16,  /* offset 0..15 */
134 	    selector:16,
135 	    word_count:8,
136 	    access:8,
137 	    offset_high:16;             /* offset 16..31 */
138 };
139 struct real_gate64 {
140 	uint32_t        offset_low16:16,        /* offset 0..15 */
141 	    selector16:16,
142 	    IST:3,
143 	    zeroes5:5,
144 	    access8:8,
145 	    offset_high16:16,                   /* offset 16..31 */
146 	    offset_top32:32,                    /* offset 32..63 */
147 	    reserved32:32;                      /* reserved/zero */
148 };
149 
150 #define MAKE_REAL_DESCRIPTOR(base, lim, gran, acc) {\
151 	.limit_low = lim & 0xffff, \
152 	.limit_high = (lim >> 16) & 0xf, \
153 	.base_low = base & 0xffff, \
154 	.base_med = (base >> 16) & 0xff, \
155 	.base_high = (base >> 24) & 0xff, \
156 	.access = acc, \
157 	.granularity = gran \
158 }
159 
160 /*
161  * We build descriptors and gates in a 'fake' format to let the
162  * fields be contiguous.  We shuffle them into the real format
163  * at runtime.
164  */
165 struct fake_descriptor {
166 	uint32_t        offset:32;              /* offset */
167 	uint32_t        lim_or_seg:20;          /* limit */
168 	                                        /* or segment, for gate */
169 	uint32_t        size_or_wdct:4;         /* size/granularity */
170 	                                        /* word count, for gate */
171 	uint32_t        access:8;               /* access */
172 };
173 struct fake_descriptor64 {
174 	uint64_t        offset64;               /* offset [0..31,32..63] */
175 	uint32_t        lim_or_seg:20;          /* limit */
176 	                                        /* or segment, for gate */
177 	uint32_t        size_or_IST:4;          /* size/granularity */
178 	                                        /* IST for gates */
179 	uint32_t        access:8;               /* access */
180 	uint32_t        reserved:32;            /* reserved/zero */
181 };
182 
183 typedef struct __attribute__((packed)) {
184 	uint16_t        size;
185 	void            *ptr;
186 } x86_64_desc_register_t;
187 
188 
189 
190 /*
191  * Boot-time data for master (or only) CPU
192  */
193 extern struct real_descriptor   master_gdt[GDTSZ];
194 extern struct real_descriptor   master_ldt[];
195 extern struct i386_tss          master_ktss;
196 extern struct sysenter_stack    master_sstk;
197 
198 extern struct fake_descriptor64 master_idt64[IDTSZ];
199 extern struct x86_64_tss        master_ktss64;
200 
201 __BEGIN_DECLS
202 
203 extern char                     df_task_stack[];
204 extern char                     df_task_stack_end[];
205 extern struct i386_tss          master_dftss;
206 extern void                     df_task_start(void);
207 
208 extern char                     mc_task_stack[];
209 extern char                     mc_task_stack_end[];
210 extern struct i386_tss          master_mctss;
211 extern void                     mc_task_start(void);
212 
213 __END_DECLS
214 
215 #endif  /*__ASSEMBLER__*/
216 
217 #define SZ_64           0x2                     /* 64-bit segment */
218 #define SZ_32           0x4                     /* 32-bit segment */
219 #define SZ_G            0x8                     /* 4K limit field */
220 
221 #define ACC_A           0x01                    /* accessed */
222 #define ACC_TYPE        0x1e                    /* type field: */
223 
224 #define ACC_TYPE_SYSTEM 0x00                    /* system descriptors: */
225 
226 #define ACC_LDT         0x02                        /* LDT */
227 #define ACC_CALL_GATE_16 0x04                       /* 16-bit call gate */
228 #define ACC_TASK_GATE   0x05                        /* task gate */
229 #define ACC_TSS         0x09                        /* task segment */
230 #define ACC_CALL_GATE   0x0c                        /* call gate */
231 #define ACC_INTR_GATE   0x0e                        /* interrupt gate */
232 #define ACC_TRAP_GATE   0x0f                        /* trap gate */
233 
234 #define ACC_TSS_BUSY    0x02                        /* task busy */
235 
236 #define ACC_TYPE_USER   0x10                    /* user descriptors */
237 
238 #define ACC_DATA        0x10                        /* data */
239 #define ACC_DATA_W      0x12                        /* data, writable */
240 #define ACC_DATA_E      0x14                        /* data, expand-down */
241 #define ACC_DATA_EW     0x16                        /* data, expand-down,
242 	                                             *        writable */
243 #define ACC_CODE        0x18                        /* code */
244 #define ACC_CODE_R      0x1a                        /* code, readable */
245 #define ACC_CODE_C      0x1c                        /* code, conforming */
246 #define ACC_CODE_CR     0x1e                        /* code, conforming,
247 	                                             *  readable */
248 #define ACC_PL          0x60                    /* access rights: */
249 #define ACC_PL_K        0x00                    /* kernel access only */
250 #define ACC_PL_U        0x60                    /* user access */
251 #define ACC_P           0x80                    /* segment present */
252 
253 /*
254  * Components of a selector
255  */
256 #define SEL_LDTS        0x04                    /* local selector */
257 #define SEL_PL          0x03                    /* privilege level: */
258 #define SEL_PL_K        0x00                        /* kernel selector */
259 #define SEL_PL_U        0x03                        /* user selector */
260 
261 /*
262  * Convert selector to descriptor table index.
263  */
264 #define sel_idx(sel)    (selector_to_sel(sel).index)
265 #define SEL_TO_INDEX(s) ((s)>>3)
266 
267 #define NULL_SEG        0
268 
269 
270 /*
271  * Kernel descriptors for MACH - 64-bit flat address space.
272  */
273 #define KERNEL64_CS     0x08            /* 1:  K64 code */
274 #define SYSENTER_CS     0x0b            /*     U32 sysenter pseudo-segment */
275 #define KERNEL64_SS     0x10            /* 2:  KERNEL64_CS+8 for syscall */
276 #define USER_CS         0x1b            /* 3:  U32 code */
277 #define USER_DS         0x23            /* 4:  USER_CS+8 for sysret */
278 #define USER64_CS       0x2b            /* 5:  USER_CS+16 for sysret */
279 #define USER64_DS       USER_DS         /*     U64 data pseudo-segment */
280 #define KERNEL_LDT      0x30            /* 6:  */
281                                         /* 7:  other 8 bytes of KERNEL_LDT */
282 #define KERNEL_TSS      0x40            /* 8:  */
283                                         /* 9:  other 8 bytes of KERNEL_TSS */
284 #define KERNEL32_CS     0x50            /* 10: */
285 #define USER_LDT        0x58            /* 11: */
286                                         /* 12: other 8 bytes of USER_LDT */
287 #define KERNEL_DS       0x68            /* 13: 32-bit kernel data */
288 
289 
290 #define SYSENTER_TF_CS  (USER_CS|0x10000)
291 #define SYSENTER_DS     KERNEL64_SS     /* sysenter kernel data segment */
292 
293 #endif  /* _I386_SEG_H_ */
294 #ifdef __x86_64__
295 /*
296  * 64-bit kernel LDT descriptors
297  */
298 #define SYSCALL_CS      0x07            /* syscall pseudo-segment */
299 #define USER_CTHREAD    0x0f            /* user cthread area */
300 #define USER_SETTABLE   0x1f            /* start of user settable ldt entries */
301 #endif
302