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