1
2#ifndef _ASM_X86_SEGMENT_H
3#define _ASM_X86_SEGMENT_H
4
5#include <linux/const.h>
6#include <asm/alternative.h>
7
8
9
10
11
12#define GDT_ENTRY(flags, base, limit) \
13 ((((base) & _AC(0xff000000,ULL)) << (56-24)) | \
14 (((flags) & _AC(0x0000f0ff,ULL)) << 40) | \
15 (((limit) & _AC(0x000f0000,ULL)) << (48-16)) | \
16 (((base) & _AC(0x00ffffff,ULL)) << 16) | \
17 (((limit) & _AC(0x0000ffff,ULL))))
18
19
20
21#define GDT_ENTRY_BOOT_CS 2
22#define GDT_ENTRY_BOOT_DS 3
23#define GDT_ENTRY_BOOT_TSS 4
24#define __BOOT_CS (GDT_ENTRY_BOOT_CS*8)
25#define __BOOT_DS (GDT_ENTRY_BOOT_DS*8)
26#define __BOOT_TSS (GDT_ENTRY_BOOT_TSS*8)
27
28
29
30
31
32#define SEGMENT_RPL_MASK 0x3
33
34
35#define USER_RPL 0x3
36
37
38#define SEGMENT_TI_MASK 0x4
39
40#define SEGMENT_LDT 0x4
41
42#define SEGMENT_GDT 0x0
43
44#define GDT_ENTRY_INVALID_SEG 0
45
46#ifdef CONFIG_X86_32
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91#define GDT_ENTRY_TLS_MIN 6
92#define GDT_ENTRY_TLS_MAX (GDT_ENTRY_TLS_MIN + GDT_ENTRY_TLS_ENTRIES - 1)
93
94#define GDT_ENTRY_KERNEL_CS 12
95#define GDT_ENTRY_KERNEL_DS 13
96#define GDT_ENTRY_DEFAULT_USER_CS 14
97#define GDT_ENTRY_DEFAULT_USER_DS 15
98#define GDT_ENTRY_TSS 16
99#define GDT_ENTRY_LDT 17
100#define GDT_ENTRY_PNPBIOS_CS32 18
101#define GDT_ENTRY_PNPBIOS_CS16 19
102#define GDT_ENTRY_PNPBIOS_DS 20
103#define GDT_ENTRY_PNPBIOS_TS1 21
104#define GDT_ENTRY_PNPBIOS_TS2 22
105#define GDT_ENTRY_APMBIOS_BASE 23
106
107#define GDT_ENTRY_ESPFIX_SS 26
108#define GDT_ENTRY_PERCPU 27
109#define GDT_ENTRY_STACK_CANARY 28
110
111#define GDT_ENTRY_DOUBLEFAULT_TSS 31
112
113
114
115
116#define GDT_ENTRIES 32
117
118
119
120
121
122#define __KERNEL_CS (GDT_ENTRY_KERNEL_CS*8)
123#define __KERNEL_DS (GDT_ENTRY_KERNEL_DS*8)
124#define __USER_DS (GDT_ENTRY_DEFAULT_USER_DS*8 + 3)
125#define __USER_CS (GDT_ENTRY_DEFAULT_USER_CS*8 + 3)
126#define __ESPFIX_SS (GDT_ENTRY_ESPFIX_SS*8)
127
128
129#define PNP_CS32 (GDT_ENTRY_PNPBIOS_CS32*8)
130
131#define PNP_CS16 (GDT_ENTRY_PNPBIOS_CS16*8)
132
133
134#define SEGMENT_IS_PNP_CODE(x) (((x) & 0xf4) == PNP_CS32)
135
136
137#define PNP_DS (GDT_ENTRY_PNPBIOS_DS*8)
138
139#define PNP_TS1 (GDT_ENTRY_PNPBIOS_TS1*8)
140
141#define PNP_TS2 (GDT_ENTRY_PNPBIOS_TS2*8)
142
143#ifdef CONFIG_SMP
144# define __KERNEL_PERCPU (GDT_ENTRY_PERCPU*8)
145#else
146# define __KERNEL_PERCPU 0
147#endif
148
149#ifdef CONFIG_STACKPROTECTOR
150# define __KERNEL_STACK_CANARY (GDT_ENTRY_STACK_CANARY*8)
151#else
152# define __KERNEL_STACK_CANARY 0
153#endif
154
155#else
156
157#include <asm/cache.h>
158
159#define GDT_ENTRY_KERNEL32_CS 1
160#define GDT_ENTRY_KERNEL_CS 2
161#define GDT_ENTRY_KERNEL_DS 3
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177#define GDT_ENTRY_DEFAULT_USER32_CS 4
178#define GDT_ENTRY_DEFAULT_USER_DS 5
179#define GDT_ENTRY_DEFAULT_USER_CS 6
180
181
182#define GDT_ENTRY_TSS 8
183
184#define GDT_ENTRY_LDT 10
185
186#define GDT_ENTRY_TLS_MIN 12
187#define GDT_ENTRY_TLS_MAX 14
188
189#define GDT_ENTRY_CPUNODE 15
190
191
192
193
194#define GDT_ENTRIES 16
195
196
197
198
199
200
201
202#define __KERNEL32_CS (GDT_ENTRY_KERNEL32_CS*8)
203#define __KERNEL_CS (GDT_ENTRY_KERNEL_CS*8)
204#define __KERNEL_DS (GDT_ENTRY_KERNEL_DS*8)
205#define __USER32_CS (GDT_ENTRY_DEFAULT_USER32_CS*8 + 3)
206#define __USER_DS (GDT_ENTRY_DEFAULT_USER_DS*8 + 3)
207#define __USER32_DS __USER_DS
208#define __USER_CS (GDT_ENTRY_DEFAULT_USER_CS*8 + 3)
209#define __CPUNODE_SEG (GDT_ENTRY_CPUNODE*8 + 3)
210
211#endif
212
213#ifndef CONFIG_PARAVIRT_XXL
214# define get_kernel_rpl() 0
215#endif
216
217#define IDT_ENTRIES 256
218#define NUM_EXCEPTION_VECTORS 32
219
220
221#define EXCEPTION_ERRCODE_MASK 0x00027d00
222
223#define GDT_SIZE (GDT_ENTRIES*8)
224#define GDT_ENTRY_TLS_ENTRIES 3
225#define TLS_SIZE (GDT_ENTRY_TLS_ENTRIES* 8)
226
227#ifdef CONFIG_X86_64
228
229
230#define VDSO_CPUNODE_BITS 12
231#define VDSO_CPUNODE_MASK 0xfff
232
233#ifndef __ASSEMBLY__
234
235
236
237static inline unsigned long vdso_encode_cpunode(int cpu, unsigned long node)
238{
239 return (node << VDSO_CPUNODE_BITS) | cpu;
240}
241
242static inline void vdso_read_cpunode(unsigned *cpu, unsigned *node)
243{
244 unsigned int p;
245
246
247
248
249
250
251
252
253
254 alternative_io ("lsl %[seg],%[p]",
255 ".byte 0xf3,0x0f,0xc7,0xf8",
256 X86_FEATURE_RDPID,
257 [p] "=a" (p), [seg] "r" (__CPUNODE_SEG));
258
259 if (cpu)
260 *cpu = (p & VDSO_CPUNODE_MASK);
261 if (node)
262 *node = (p >> VDSO_CPUNODE_BITS);
263}
264
265#endif
266#endif
267
268#ifdef __KERNEL__
269
270
271
272
273
274
275
276
277#define EARLY_IDT_HANDLER_SIZE 9
278
279
280
281
282
283
284
285#define XEN_EARLY_IDT_HANDLER_SIZE 8
286
287#ifndef __ASSEMBLY__
288
289extern const char early_idt_handler_array[NUM_EXCEPTION_VECTORS][EARLY_IDT_HANDLER_SIZE];
290extern void early_ignore_irq(void);
291
292#if defined(CONFIG_X86_64) && defined(CONFIG_XEN_PV)
293extern const char xen_early_idt_handler_array[NUM_EXCEPTION_VECTORS][XEN_EARLY_IDT_HANDLER_SIZE];
294#endif
295
296
297
298
299
300
301
302
303#define __loadsegment_simple(seg, value) \
304do { \
305 unsigned short __val = (value); \
306 \
307 asm volatile(" \n" \
308 "1: movl %k0,%%" #seg " \n" \
309 \
310 ".section .fixup,\"ax\" \n" \
311 "2: xorl %k0,%k0 \n" \
312 " jmp 1b \n" \
313 ".previous \n" \
314 \
315 _ASM_EXTABLE(1b, 2b) \
316 \
317 : "+r" (__val) : : "memory"); \
318} while (0)
319
320#define __loadsegment_ss(value) __loadsegment_simple(ss, (value))
321#define __loadsegment_ds(value) __loadsegment_simple(ds, (value))
322#define __loadsegment_es(value) __loadsegment_simple(es, (value))
323
324#ifdef CONFIG_X86_32
325
326
327
328
329
330#define __loadsegment_fs(value) __loadsegment_simple(fs, (value))
331#define __loadsegment_gs(value) __loadsegment_simple(gs, (value))
332
333#else
334
335static inline void __loadsegment_fs(unsigned short value)
336{
337 asm volatile(" \n"
338 "1: movw %0, %%fs \n"
339 "2: \n"
340
341 _ASM_EXTABLE_HANDLE(1b, 2b, ex_handler_clear_fs)
342
343 : : "rm" (value) : "memory");
344}
345
346
347
348#endif
349
350#define loadsegment(seg, value) __loadsegment_ ## seg (value)
351
352
353
354
355#define savesegment(seg, value) \
356 asm("mov %%" #seg ",%0":"=r" (value) : : "memory")
357
358
359
360
361#ifdef CONFIG_X86_32
362# ifdef CONFIG_X86_32_LAZY_GS
363# define get_user_gs(regs) (u16)({ unsigned long v; savesegment(gs, v); v; })
364# define set_user_gs(regs, v) loadsegment(gs, (unsigned long)(v))
365# define task_user_gs(tsk) ((tsk)->thread.gs)
366# define lazy_save_gs(v) savesegment(gs, (v))
367# define lazy_load_gs(v) loadsegment(gs, (v))
368# else
369# define get_user_gs(regs) (u16)((regs)->gs)
370# define set_user_gs(regs, v) do { (regs)->gs = (v); } while (0)
371# define task_user_gs(tsk) (task_pt_regs(tsk)->gs)
372# define lazy_save_gs(v) do { } while (0)
373# define lazy_load_gs(v) do { } while (0)
374# endif
375#endif
376
377#endif
378#endif
379
380#endif
381