diff options
author | Ingo Molnar <mingo@elte.hu> | 2009-02-13 03:45:09 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-02-13 03:45:09 -0500 |
commit | ab639f3593f0b5e4439d549831442c18c3baf989 (patch) | |
tree | 118743e94e5dc86c835dbc1f1d3bf1612f4ae740 /arch/x86/include | |
parent | f8a6b2b9cee298a9663cbe38ce1eb5240987cb62 (diff) | |
parent | 58105ef1857112a186696c9b8957020090226a28 (diff) |
Merge branch 'core/percpu' into x86/core
Diffstat (limited to 'arch/x86/include')
-rw-r--r-- | arch/x86/include/asm/a.out-core.h | 2 | ||||
-rw-r--r-- | arch/x86/include/asm/elf.h | 15 | ||||
-rw-r--r-- | arch/x86/include/asm/mmu_context.h | 2 | ||||
-rw-r--r-- | arch/x86/include/asm/percpu.h | 22 | ||||
-rw-r--r-- | arch/x86/include/asm/processor.h | 6 | ||||
-rw-r--r-- | arch/x86/include/asm/ptrace.h | 4 | ||||
-rw-r--r-- | arch/x86/include/asm/segment.h | 9 | ||||
-rw-r--r-- | arch/x86/include/asm/stackprotector.h | 96 | ||||
-rw-r--r-- | arch/x86/include/asm/syscalls.h | 20 | ||||
-rw-r--r-- | arch/x86/include/asm/system.h | 38 | ||||
-rw-r--r-- | arch/x86/include/asm/traps.h | 2 | ||||
-rw-r--r-- | arch/x86/include/asm/uaccess.h | 33 | ||||
-rw-r--r-- | arch/x86/include/asm/uv/uv.h | 3 |
13 files changed, 222 insertions, 30 deletions
diff --git a/arch/x86/include/asm/a.out-core.h b/arch/x86/include/asm/a.out-core.h index 3c601f8224be..bb70e397aa84 100644 --- a/arch/x86/include/asm/a.out-core.h +++ b/arch/x86/include/asm/a.out-core.h | |||
@@ -55,7 +55,7 @@ static inline void aout_dump_thread(struct pt_regs *regs, struct user *dump) | |||
55 | dump->regs.ds = (u16)regs->ds; | 55 | dump->regs.ds = (u16)regs->ds; |
56 | dump->regs.es = (u16)regs->es; | 56 | dump->regs.es = (u16)regs->es; |
57 | dump->regs.fs = (u16)regs->fs; | 57 | dump->regs.fs = (u16)regs->fs; |
58 | savesegment(gs, dump->regs.gs); | 58 | dump->regs.gs = get_user_gs(regs); |
59 | dump->regs.orig_ax = regs->orig_ax; | 59 | dump->regs.orig_ax = regs->orig_ax; |
60 | dump->regs.ip = regs->ip; | 60 | dump->regs.ip = regs->ip; |
61 | dump->regs.cs = (u16)regs->cs; | 61 | dump->regs.cs = (u16)regs->cs; |
diff --git a/arch/x86/include/asm/elf.h b/arch/x86/include/asm/elf.h index f51a3ddde01a..83c1bc8d2e8a 100644 --- a/arch/x86/include/asm/elf.h +++ b/arch/x86/include/asm/elf.h | |||
@@ -112,7 +112,7 @@ extern unsigned int vdso_enabled; | |||
112 | * now struct_user_regs, they are different) | 112 | * now struct_user_regs, they are different) |
113 | */ | 113 | */ |
114 | 114 | ||
115 | #define ELF_CORE_COPY_REGS(pr_reg, regs) \ | 115 | #define ELF_CORE_COPY_REGS_COMMON(pr_reg, regs) \ |
116 | do { \ | 116 | do { \ |
117 | pr_reg[0] = regs->bx; \ | 117 | pr_reg[0] = regs->bx; \ |
118 | pr_reg[1] = regs->cx; \ | 118 | pr_reg[1] = regs->cx; \ |
@@ -124,7 +124,6 @@ do { \ | |||
124 | pr_reg[7] = regs->ds & 0xffff; \ | 124 | pr_reg[7] = regs->ds & 0xffff; \ |
125 | pr_reg[8] = regs->es & 0xffff; \ | 125 | pr_reg[8] = regs->es & 0xffff; \ |
126 | pr_reg[9] = regs->fs & 0xffff; \ | 126 | pr_reg[9] = regs->fs & 0xffff; \ |
127 | savesegment(gs, pr_reg[10]); \ | ||
128 | pr_reg[11] = regs->orig_ax; \ | 127 | pr_reg[11] = regs->orig_ax; \ |
129 | pr_reg[12] = regs->ip; \ | 128 | pr_reg[12] = regs->ip; \ |
130 | pr_reg[13] = regs->cs & 0xffff; \ | 129 | pr_reg[13] = regs->cs & 0xffff; \ |
@@ -133,6 +132,18 @@ do { \ | |||
133 | pr_reg[16] = regs->ss & 0xffff; \ | 132 | pr_reg[16] = regs->ss & 0xffff; \ |
134 | } while (0); | 133 | } while (0); |
135 | 134 | ||
135 | #define ELF_CORE_COPY_REGS(pr_reg, regs) \ | ||
136 | do { \ | ||
137 | ELF_CORE_COPY_REGS_COMMON(pr_reg, regs);\ | ||
138 | pr_reg[10] = get_user_gs(regs); \ | ||
139 | } while (0); | ||
140 | |||
141 | #define ELF_CORE_COPY_KERNEL_REGS(pr_reg, regs) \ | ||
142 | do { \ | ||
143 | ELF_CORE_COPY_REGS_COMMON(pr_reg, regs);\ | ||
144 | savesegment(gs, pr_reg[10]); \ | ||
145 | } while (0); | ||
146 | |||
136 | #define ELF_PLATFORM (utsname()->machine) | 147 | #define ELF_PLATFORM (utsname()->machine) |
137 | #define set_personality_64bit() do { } while (0) | 148 | #define set_personality_64bit() do { } while (0) |
138 | 149 | ||
diff --git a/arch/x86/include/asm/mmu_context.h b/arch/x86/include/asm/mmu_context.h index 52948df9cd1d..f923203dc39a 100644 --- a/arch/x86/include/asm/mmu_context.h +++ b/arch/x86/include/asm/mmu_context.h | |||
@@ -79,7 +79,7 @@ do { \ | |||
79 | #ifdef CONFIG_X86_32 | 79 | #ifdef CONFIG_X86_32 |
80 | #define deactivate_mm(tsk, mm) \ | 80 | #define deactivate_mm(tsk, mm) \ |
81 | do { \ | 81 | do { \ |
82 | loadsegment(gs, 0); \ | 82 | lazy_load_gs(0); \ |
83 | } while (0) | 83 | } while (0) |
84 | #else | 84 | #else |
85 | #define deactivate_mm(tsk, mm) \ | 85 | #define deactivate_mm(tsk, mm) \ |
diff --git a/arch/x86/include/asm/percpu.h b/arch/x86/include/asm/percpu.h index 0b64af4f13ac..aee103b26d01 100644 --- a/arch/x86/include/asm/percpu.h +++ b/arch/x86/include/asm/percpu.h | |||
@@ -34,6 +34,12 @@ | |||
34 | #define PER_CPU_VAR(var) per_cpu__##var | 34 | #define PER_CPU_VAR(var) per_cpu__##var |
35 | #endif /* SMP */ | 35 | #endif /* SMP */ |
36 | 36 | ||
37 | #ifdef CONFIG_X86_64_SMP | ||
38 | #define INIT_PER_CPU_VAR(var) init_per_cpu__##var | ||
39 | #else | ||
40 | #define INIT_PER_CPU_VAR(var) per_cpu__##var | ||
41 | #endif | ||
42 | |||
37 | #else /* ...!ASSEMBLY */ | 43 | #else /* ...!ASSEMBLY */ |
38 | 44 | ||
39 | #include <linux/stringify.h> | 45 | #include <linux/stringify.h> |
@@ -45,6 +51,22 @@ | |||
45 | #define __percpu_arg(x) "%" #x | 51 | #define __percpu_arg(x) "%" #x |
46 | #endif | 52 | #endif |
47 | 53 | ||
54 | /* | ||
55 | * Initialized pointers to per-cpu variables needed for the boot | ||
56 | * processor need to use these macros to get the proper address | ||
57 | * offset from __per_cpu_load on SMP. | ||
58 | * | ||
59 | * There also must be an entry in vmlinux_64.lds.S | ||
60 | */ | ||
61 | #define DECLARE_INIT_PER_CPU(var) \ | ||
62 | extern typeof(per_cpu_var(var)) init_per_cpu_var(var) | ||
63 | |||
64 | #ifdef CONFIG_X86_64_SMP | ||
65 | #define init_per_cpu_var(var) init_per_cpu__##var | ||
66 | #else | ||
67 | #define init_per_cpu_var(var) per_cpu_var(var) | ||
68 | #endif | ||
69 | |||
48 | /* For arch-specific code, we can use direct single-insn ops (they | 70 | /* For arch-specific code, we can use direct single-insn ops (they |
49 | * don't give an lvalue though). */ | 71 | * don't give an lvalue though). */ |
50 | extern void __bad_percpu_size(void); | 72 | extern void __bad_percpu_size(void); |
diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index a6643f68fbb1..a0133838b67c 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h | |||
@@ -393,8 +393,14 @@ union irq_stack_union { | |||
393 | }; | 393 | }; |
394 | 394 | ||
395 | DECLARE_PER_CPU(union irq_stack_union, irq_stack_union); | 395 | DECLARE_PER_CPU(union irq_stack_union, irq_stack_union); |
396 | DECLARE_INIT_PER_CPU(irq_stack_union); | ||
397 | |||
396 | DECLARE_PER_CPU(char *, irq_stack_ptr); | 398 | DECLARE_PER_CPU(char *, irq_stack_ptr); |
399 | #else /* X86_64 */ | ||
400 | #ifdef CONFIG_CC_STACKPROTECTOR | ||
401 | DECLARE_PER_CPU(unsigned long, stack_canary); | ||
397 | #endif | 402 | #endif |
403 | #endif /* X86_64 */ | ||
398 | 404 | ||
399 | extern void print_cpu_info(struct cpuinfo_x86 *); | 405 | extern void print_cpu_info(struct cpuinfo_x86 *); |
400 | extern unsigned int xstate_size; | 406 | extern unsigned int xstate_size; |
diff --git a/arch/x86/include/asm/ptrace.h b/arch/x86/include/asm/ptrace.h index 6d34d954c228..e304b66abeea 100644 --- a/arch/x86/include/asm/ptrace.h +++ b/arch/x86/include/asm/ptrace.h | |||
@@ -28,7 +28,7 @@ struct pt_regs { | |||
28 | int xds; | 28 | int xds; |
29 | int xes; | 29 | int xes; |
30 | int xfs; | 30 | int xfs; |
31 | /* int gs; */ | 31 | int xgs; |
32 | long orig_eax; | 32 | long orig_eax; |
33 | long eip; | 33 | long eip; |
34 | int xcs; | 34 | int xcs; |
@@ -50,7 +50,7 @@ struct pt_regs { | |||
50 | unsigned long ds; | 50 | unsigned long ds; |
51 | unsigned long es; | 51 | unsigned long es; |
52 | unsigned long fs; | 52 | unsigned long fs; |
53 | /* int gs; */ | 53 | unsigned long gs; |
54 | unsigned long orig_ax; | 54 | unsigned long orig_ax; |
55 | unsigned long ip; | 55 | unsigned long ip; |
56 | unsigned long cs; | 56 | unsigned long cs; |
diff --git a/arch/x86/include/asm/segment.h b/arch/x86/include/asm/segment.h index 1dc1b51ac623..14e0ed86a6f9 100644 --- a/arch/x86/include/asm/segment.h +++ b/arch/x86/include/asm/segment.h | |||
@@ -61,7 +61,7 @@ | |||
61 | * | 61 | * |
62 | * 26 - ESPFIX small SS | 62 | * 26 - ESPFIX small SS |
63 | * 27 - per-cpu [ offset to per-cpu data area ] | 63 | * 27 - per-cpu [ offset to per-cpu data area ] |
64 | * 28 - unused | 64 | * 28 - stack_canary-20 [ for stack protector ] |
65 | * 29 - unused | 65 | * 29 - unused |
66 | * 30 - unused | 66 | * 30 - unused |
67 | * 31 - TSS for double fault handler | 67 | * 31 - TSS for double fault handler |
@@ -95,6 +95,13 @@ | |||
95 | #define __KERNEL_PERCPU 0 | 95 | #define __KERNEL_PERCPU 0 |
96 | #endif | 96 | #endif |
97 | 97 | ||
98 | #define GDT_ENTRY_STACK_CANARY (GDT_ENTRY_KERNEL_BASE + 16) | ||
99 | #ifdef CONFIG_CC_STACKPROTECTOR | ||
100 | #define __KERNEL_STACK_CANARY (GDT_ENTRY_STACK_CANARY * 8) | ||
101 | #else | ||
102 | #define __KERNEL_STACK_CANARY 0 | ||
103 | #endif | ||
104 | |||
98 | #define GDT_ENTRY_DOUBLEFAULT_TSS 31 | 105 | #define GDT_ENTRY_DOUBLEFAULT_TSS 31 |
99 | 106 | ||
100 | /* | 107 | /* |
diff --git a/arch/x86/include/asm/stackprotector.h b/arch/x86/include/asm/stackprotector.h index 36a700acaf2b..c2d742c6e15f 100644 --- a/arch/x86/include/asm/stackprotector.h +++ b/arch/x86/include/asm/stackprotector.h | |||
@@ -1,8 +1,54 @@ | |||
1 | /* | ||
2 | * GCC stack protector support. | ||
3 | * | ||
4 | * Stack protector works by putting predefined pattern at the start of | ||
5 | * the stack frame and verifying that it hasn't been overwritten when | ||
6 | * returning from the function. The pattern is called stack canary | ||
7 | * and unfortunately gcc requires it to be at a fixed offset from %gs. | ||
8 | * On x86_64, the offset is 40 bytes and on x86_32 20 bytes. x86_64 | ||
9 | * and x86_32 use segment registers differently and thus handles this | ||
10 | * requirement differently. | ||
11 | * | ||
12 | * On x86_64, %gs is shared by percpu area and stack canary. All | ||
13 | * percpu symbols are zero based and %gs points to the base of percpu | ||
14 | * area. The first occupant of the percpu area is always | ||
15 | * irq_stack_union which contains stack_canary at offset 40. Userland | ||
16 | * %gs is always saved and restored on kernel entry and exit using | ||
17 | * swapgs, so stack protector doesn't add any complexity there. | ||
18 | * | ||
19 | * On x86_32, it's slightly more complicated. As in x86_64, %gs is | ||
20 | * used for userland TLS. Unfortunately, some processors are much | ||
21 | * slower at loading segment registers with different value when | ||
22 | * entering and leaving the kernel, so the kernel uses %fs for percpu | ||
23 | * area and manages %gs lazily so that %gs is switched only when | ||
24 | * necessary, usually during task switch. | ||
25 | * | ||
26 | * As gcc requires the stack canary at %gs:20, %gs can't be managed | ||
27 | * lazily if stack protector is enabled, so the kernel saves and | ||
28 | * restores userland %gs on kernel entry and exit. This behavior is | ||
29 | * controlled by CONFIG_X86_32_LAZY_GS and accessors are defined in | ||
30 | * system.h to hide the details. | ||
31 | */ | ||
32 | |||
1 | #ifndef _ASM_STACKPROTECTOR_H | 33 | #ifndef _ASM_STACKPROTECTOR_H |
2 | #define _ASM_STACKPROTECTOR_H 1 | 34 | #define _ASM_STACKPROTECTOR_H 1 |
3 | 35 | ||
36 | #ifdef CONFIG_CC_STACKPROTECTOR | ||
37 | |||
4 | #include <asm/tsc.h> | 38 | #include <asm/tsc.h> |
5 | #include <asm/processor.h> | 39 | #include <asm/processor.h> |
40 | #include <asm/percpu.h> | ||
41 | #include <asm/system.h> | ||
42 | #include <asm/desc.h> | ||
43 | #include <linux/random.h> | ||
44 | |||
45 | /* | ||
46 | * 24 byte read-only segment initializer for stack canary. Linker | ||
47 | * can't handle the address bit shifting. Address will be set in | ||
48 | * head_32 for boot CPU and setup_per_cpu_areas() for others. | ||
49 | */ | ||
50 | #define GDT_STACK_CANARY_INIT \ | ||
51 | [GDT_ENTRY_STACK_CANARY] = { { { 0x00000018, 0x00409000 } } }, | ||
6 | 52 | ||
7 | /* | 53 | /* |
8 | * Initialize the stackprotector canary value. | 54 | * Initialize the stackprotector canary value. |
@@ -15,12 +61,9 @@ static __always_inline void boot_init_stack_canary(void) | |||
15 | u64 canary; | 61 | u64 canary; |
16 | u64 tsc; | 62 | u64 tsc; |
17 | 63 | ||
18 | /* | 64 | #ifdef CONFIG_X86_64 |
19 | * Build time only check to make sure the stack_canary is at | ||
20 | * offset 40 in the pda; this is a gcc ABI requirement | ||
21 | */ | ||
22 | BUILD_BUG_ON(offsetof(union irq_stack_union, stack_canary) != 40); | 65 | BUILD_BUG_ON(offsetof(union irq_stack_union, stack_canary) != 40); |
23 | 66 | #endif | |
24 | /* | 67 | /* |
25 | * We both use the random pool and the current TSC as a source | 68 | * We both use the random pool and the current TSC as a source |
26 | * of randomness. The TSC only matters for very early init, | 69 | * of randomness. The TSC only matters for very early init, |
@@ -32,7 +75,50 @@ static __always_inline void boot_init_stack_canary(void) | |||
32 | canary += tsc + (tsc << 32UL); | 75 | canary += tsc + (tsc << 32UL); |
33 | 76 | ||
34 | current->stack_canary = canary; | 77 | current->stack_canary = canary; |
78 | #ifdef CONFIG_X86_64 | ||
35 | percpu_write(irq_stack_union.stack_canary, canary); | 79 | percpu_write(irq_stack_union.stack_canary, canary); |
80 | #else | ||
81 | percpu_write(stack_canary, canary); | ||
82 | #endif | ||
36 | } | 83 | } |
37 | 84 | ||
85 | static inline void setup_stack_canary_segment(int cpu) | ||
86 | { | ||
87 | #ifdef CONFIG_X86_32 | ||
88 | unsigned long canary = (unsigned long)&per_cpu(stack_canary, cpu) - 20; | ||
89 | struct desc_struct *gdt_table = get_cpu_gdt_table(cpu); | ||
90 | struct desc_struct desc; | ||
91 | |||
92 | desc = gdt_table[GDT_ENTRY_STACK_CANARY]; | ||
93 | desc.base0 = canary & 0xffff; | ||
94 | desc.base1 = (canary >> 16) & 0xff; | ||
95 | desc.base2 = (canary >> 24) & 0xff; | ||
96 | write_gdt_entry(gdt_table, GDT_ENTRY_STACK_CANARY, &desc, DESCTYPE_S); | ||
97 | #endif | ||
98 | } | ||
99 | |||
100 | static inline void load_stack_canary_segment(void) | ||
101 | { | ||
102 | #ifdef CONFIG_X86_32 | ||
103 | asm("mov %0, %%gs" : : "r" (__KERNEL_STACK_CANARY) : "memory"); | ||
104 | #endif | ||
105 | } | ||
106 | |||
107 | #else /* CC_STACKPROTECTOR */ | ||
108 | |||
109 | #define GDT_STACK_CANARY_INIT | ||
110 | |||
111 | /* dummy boot_init_stack_canary() is defined in linux/stackprotector.h */ | ||
112 | |||
113 | static inline void setup_stack_canary_segment(int cpu) | ||
114 | { } | ||
115 | |||
116 | static inline void load_stack_canary_segment(void) | ||
117 | { | ||
118 | #ifdef CONFIG_X86_32 | ||
119 | asm volatile ("mov %0, %%gs" : : "r" (0)); | ||
38 | #endif | 120 | #endif |
121 | } | ||
122 | |||
123 | #endif /* CC_STACKPROTECTOR */ | ||
124 | #endif /* _ASM_STACKPROTECTOR_H */ | ||
diff --git a/arch/x86/include/asm/syscalls.h b/arch/x86/include/asm/syscalls.h index c0b0bda754ee..68b1be10cfad 100644 --- a/arch/x86/include/asm/syscalls.h +++ b/arch/x86/include/asm/syscalls.h | |||
@@ -29,21 +29,21 @@ asmlinkage int sys_get_thread_area(struct user_desc __user *); | |||
29 | /* X86_32 only */ | 29 | /* X86_32 only */ |
30 | #ifdef CONFIG_X86_32 | 30 | #ifdef CONFIG_X86_32 |
31 | /* kernel/process_32.c */ | 31 | /* kernel/process_32.c */ |
32 | asmlinkage int sys_fork(struct pt_regs); | 32 | int sys_fork(struct pt_regs *); |
33 | asmlinkage int sys_clone(struct pt_regs); | 33 | int sys_clone(struct pt_regs *); |
34 | asmlinkage int sys_vfork(struct pt_regs); | 34 | int sys_vfork(struct pt_regs *); |
35 | asmlinkage int sys_execve(struct pt_regs); | 35 | int sys_execve(struct pt_regs *); |
36 | 36 | ||
37 | /* kernel/signal_32.c */ | 37 | /* kernel/signal_32.c */ |
38 | asmlinkage int sys_sigsuspend(int, int, old_sigset_t); | 38 | asmlinkage int sys_sigsuspend(int, int, old_sigset_t); |
39 | asmlinkage int sys_sigaction(int, const struct old_sigaction __user *, | 39 | asmlinkage int sys_sigaction(int, const struct old_sigaction __user *, |
40 | struct old_sigaction __user *); | 40 | struct old_sigaction __user *); |
41 | asmlinkage int sys_sigaltstack(unsigned long); | 41 | int sys_sigaltstack(struct pt_regs *); |
42 | asmlinkage unsigned long sys_sigreturn(unsigned long); | 42 | unsigned long sys_sigreturn(struct pt_regs *); |
43 | asmlinkage int sys_rt_sigreturn(unsigned long); | 43 | long sys_rt_sigreturn(struct pt_regs *); |
44 | 44 | ||
45 | /* kernel/ioport.c */ | 45 | /* kernel/ioport.c */ |
46 | asmlinkage long sys_iopl(unsigned long); | 46 | long sys_iopl(struct pt_regs *); |
47 | 47 | ||
48 | /* kernel/sys_i386_32.c */ | 48 | /* kernel/sys_i386_32.c */ |
49 | asmlinkage long sys_mmap2(unsigned long, unsigned long, unsigned long, | 49 | asmlinkage long sys_mmap2(unsigned long, unsigned long, unsigned long, |
@@ -59,8 +59,8 @@ struct oldold_utsname; | |||
59 | asmlinkage int sys_olduname(struct oldold_utsname __user *); | 59 | asmlinkage int sys_olduname(struct oldold_utsname __user *); |
60 | 60 | ||
61 | /* kernel/vm86_32.c */ | 61 | /* kernel/vm86_32.c */ |
62 | asmlinkage int sys_vm86old(struct pt_regs); | 62 | int sys_vm86old(struct pt_regs *); |
63 | asmlinkage int sys_vm86(struct pt_regs); | 63 | int sys_vm86(struct pt_regs *); |
64 | 64 | ||
65 | #else /* CONFIG_X86_32 */ | 65 | #else /* CONFIG_X86_32 */ |
66 | 66 | ||
diff --git a/arch/x86/include/asm/system.h b/arch/x86/include/asm/system.h index c22383743f36..c00bfdbdd456 100644 --- a/arch/x86/include/asm/system.h +++ b/arch/x86/include/asm/system.h | |||
@@ -23,6 +23,20 @@ struct task_struct *__switch_to(struct task_struct *prev, | |||
23 | 23 | ||
24 | #ifdef CONFIG_X86_32 | 24 | #ifdef CONFIG_X86_32 |
25 | 25 | ||
26 | #ifdef CONFIG_CC_STACKPROTECTOR | ||
27 | #define __switch_canary \ | ||
28 | "movl %P[task_canary](%[next]), %%ebx\n\t" \ | ||
29 | "movl %%ebx, "__percpu_arg([stack_canary])"\n\t" | ||
30 | #define __switch_canary_oparam \ | ||
31 | , [stack_canary] "=m" (per_cpu_var(stack_canary)) | ||
32 | #define __switch_canary_iparam \ | ||
33 | , [task_canary] "i" (offsetof(struct task_struct, stack_canary)) | ||
34 | #else /* CC_STACKPROTECTOR */ | ||
35 | #define __switch_canary | ||
36 | #define __switch_canary_oparam | ||
37 | #define __switch_canary_iparam | ||
38 | #endif /* CC_STACKPROTECTOR */ | ||
39 | |||
26 | /* | 40 | /* |
27 | * Saving eflags is important. It switches not only IOPL between tasks, | 41 | * Saving eflags is important. It switches not only IOPL between tasks, |
28 | * it also protects other tasks from NT leaking through sysenter etc. | 42 | * it also protects other tasks from NT leaking through sysenter etc. |
@@ -44,6 +58,7 @@ do { \ | |||
44 | "movl %[next_sp],%%esp\n\t" /* restore ESP */ \ | 58 | "movl %[next_sp],%%esp\n\t" /* restore ESP */ \ |
45 | "movl $1f,%[prev_ip]\n\t" /* save EIP */ \ | 59 | "movl $1f,%[prev_ip]\n\t" /* save EIP */ \ |
46 | "pushl %[next_ip]\n\t" /* restore EIP */ \ | 60 | "pushl %[next_ip]\n\t" /* restore EIP */ \ |
61 | __switch_canary \ | ||
47 | "jmp __switch_to\n" /* regparm call */ \ | 62 | "jmp __switch_to\n" /* regparm call */ \ |
48 | "1:\t" \ | 63 | "1:\t" \ |
49 | "popl %%ebp\n\t" /* restore EBP */ \ | 64 | "popl %%ebp\n\t" /* restore EBP */ \ |
@@ -58,6 +73,8 @@ do { \ | |||
58 | "=b" (ebx), "=c" (ecx), "=d" (edx), \ | 73 | "=b" (ebx), "=c" (ecx), "=d" (edx), \ |
59 | "=S" (esi), "=D" (edi) \ | 74 | "=S" (esi), "=D" (edi) \ |
60 | \ | 75 | \ |
76 | __switch_canary_oparam \ | ||
77 | \ | ||
61 | /* input parameters: */ \ | 78 | /* input parameters: */ \ |
62 | : [next_sp] "m" (next->thread.sp), \ | 79 | : [next_sp] "m" (next->thread.sp), \ |
63 | [next_ip] "m" (next->thread.ip), \ | 80 | [next_ip] "m" (next->thread.ip), \ |
@@ -66,6 +83,8 @@ do { \ | |||
66 | [prev] "a" (prev), \ | 83 | [prev] "a" (prev), \ |
67 | [next] "d" (next) \ | 84 | [next] "d" (next) \ |
68 | \ | 85 | \ |
86 | __switch_canary_iparam \ | ||
87 | \ | ||
69 | : /* reloaded segment registers */ \ | 88 | : /* reloaded segment registers */ \ |
70 | "memory"); \ | 89 | "memory"); \ |
71 | } while (0) | 90 | } while (0) |
@@ -182,6 +201,25 @@ extern void native_load_gs_index(unsigned); | |||
182 | #define savesegment(seg, value) \ | 201 | #define savesegment(seg, value) \ |
183 | asm("mov %%" #seg ",%0":"=r" (value) : : "memory") | 202 | asm("mov %%" #seg ",%0":"=r" (value) : : "memory") |
184 | 203 | ||
204 | /* | ||
205 | * x86_32 user gs accessors. | ||
206 | */ | ||
207 | #ifdef CONFIG_X86_32 | ||
208 | #ifdef CONFIG_X86_32_LAZY_GS | ||
209 | #define get_user_gs(regs) (u16)({unsigned long v; savesegment(gs, v); v;}) | ||
210 | #define set_user_gs(regs, v) loadsegment(gs, (unsigned long)(v)) | ||
211 | #define task_user_gs(tsk) ((tsk)->thread.gs) | ||
212 | #define lazy_save_gs(v) savesegment(gs, (v)) | ||
213 | #define lazy_load_gs(v) loadsegment(gs, (v)) | ||
214 | #else /* X86_32_LAZY_GS */ | ||
215 | #define get_user_gs(regs) (u16)((regs)->gs) | ||
216 | #define set_user_gs(regs, v) do { (regs)->gs = (v); } while (0) | ||
217 | #define task_user_gs(tsk) (task_pt_regs(tsk)->gs) | ||
218 | #define lazy_save_gs(v) do { } while (0) | ||
219 | #define lazy_load_gs(v) do { } while (0) | ||
220 | #endif /* X86_32_LAZY_GS */ | ||
221 | #endif /* X86_32 */ | ||
222 | |||
185 | static inline unsigned long get_limit(unsigned long segment) | 223 | static inline unsigned long get_limit(unsigned long segment) |
186 | { | 224 | { |
187 | unsigned long __limit; | 225 | unsigned long __limit; |
diff --git a/arch/x86/include/asm/traps.h b/arch/x86/include/asm/traps.h index cf3bb053da0b..0d5342515b86 100644 --- a/arch/x86/include/asm/traps.h +++ b/arch/x86/include/asm/traps.h | |||
@@ -41,7 +41,7 @@ dotraplinkage void do_int3(struct pt_regs *, long); | |||
41 | dotraplinkage void do_overflow(struct pt_regs *, long); | 41 | dotraplinkage void do_overflow(struct pt_regs *, long); |
42 | dotraplinkage void do_bounds(struct pt_regs *, long); | 42 | dotraplinkage void do_bounds(struct pt_regs *, long); |
43 | dotraplinkage void do_invalid_op(struct pt_regs *, long); | 43 | dotraplinkage void do_invalid_op(struct pt_regs *, long); |
44 | dotraplinkage void do_device_not_available(struct pt_regs); | 44 | dotraplinkage void do_device_not_available(struct pt_regs *, long); |
45 | dotraplinkage void do_coprocessor_segment_overrun(struct pt_regs *, long); | 45 | dotraplinkage void do_coprocessor_segment_overrun(struct pt_regs *, long); |
46 | dotraplinkage void do_invalid_TSS(struct pt_regs *, long); | 46 | dotraplinkage void do_invalid_TSS(struct pt_regs *, long); |
47 | dotraplinkage void do_segment_not_present(struct pt_regs *, long); | 47 | dotraplinkage void do_segment_not_present(struct pt_regs *, long); |
diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h index 0ec6de4bcb0b..b685ece89d5c 100644 --- a/arch/x86/include/asm/uaccess.h +++ b/arch/x86/include/asm/uaccess.h | |||
@@ -186,7 +186,7 @@ extern int __get_user_bad(void); | |||
186 | 186 | ||
187 | 187 | ||
188 | #ifdef CONFIG_X86_32 | 188 | #ifdef CONFIG_X86_32 |
189 | #define __put_user_asm_u64(x, addr, err) \ | 189 | #define __put_user_asm_u64(x, addr, err, errret) \ |
190 | asm volatile("1: movl %%eax,0(%2)\n" \ | 190 | asm volatile("1: movl %%eax,0(%2)\n" \ |
191 | "2: movl %%edx,4(%2)\n" \ | 191 | "2: movl %%edx,4(%2)\n" \ |
192 | "3:\n" \ | 192 | "3:\n" \ |
@@ -197,7 +197,7 @@ extern int __get_user_bad(void); | |||
197 | _ASM_EXTABLE(1b, 4b) \ | 197 | _ASM_EXTABLE(1b, 4b) \ |
198 | _ASM_EXTABLE(2b, 4b) \ | 198 | _ASM_EXTABLE(2b, 4b) \ |
199 | : "=r" (err) \ | 199 | : "=r" (err) \ |
200 | : "A" (x), "r" (addr), "i" (-EFAULT), "0" (err)) | 200 | : "A" (x), "r" (addr), "i" (errret), "0" (err)) |
201 | 201 | ||
202 | #define __put_user_asm_ex_u64(x, addr) \ | 202 | #define __put_user_asm_ex_u64(x, addr) \ |
203 | asm volatile("1: movl %%eax,0(%1)\n" \ | 203 | asm volatile("1: movl %%eax,0(%1)\n" \ |
@@ -211,8 +211,8 @@ extern int __get_user_bad(void); | |||
211 | asm volatile("call __put_user_8" : "=a" (__ret_pu) \ | 211 | asm volatile("call __put_user_8" : "=a" (__ret_pu) \ |
212 | : "A" ((typeof(*(ptr)))(x)), "c" (ptr) : "ebx") | 212 | : "A" ((typeof(*(ptr)))(x)), "c" (ptr) : "ebx") |
213 | #else | 213 | #else |
214 | #define __put_user_asm_u64(x, ptr, retval) \ | 214 | #define __put_user_asm_u64(x, ptr, retval, errret) \ |
215 | __put_user_asm(x, ptr, retval, "q", "", "Zr", -EFAULT) | 215 | __put_user_asm(x, ptr, retval, "q", "", "Zr", errret) |
216 | #define __put_user_asm_ex_u64(x, addr) \ | 216 | #define __put_user_asm_ex_u64(x, addr) \ |
217 | __put_user_asm_ex(x, addr, "q", "", "Zr") | 217 | __put_user_asm_ex(x, addr, "q", "", "Zr") |
218 | #define __put_user_x8(x, ptr, __ret_pu) __put_user_x(8, x, ptr, __ret_pu) | 218 | #define __put_user_x8(x, ptr, __ret_pu) __put_user_x(8, x, ptr, __ret_pu) |
@@ -289,7 +289,8 @@ do { \ | |||
289 | __put_user_asm(x, ptr, retval, "l", "k", "ir", errret); \ | 289 | __put_user_asm(x, ptr, retval, "l", "k", "ir", errret); \ |
290 | break; \ | 290 | break; \ |
291 | case 8: \ | 291 | case 8: \ |
292 | __put_user_asm_u64((__typeof__(*ptr))(x), ptr, retval); \ | 292 | __put_user_asm_u64((__typeof__(*ptr))(x), ptr, retval, \ |
293 | errret); \ | ||
293 | break; \ | 294 | break; \ |
294 | default: \ | 295 | default: \ |
295 | __put_user_bad(); \ | 296 | __put_user_bad(); \ |
@@ -525,8 +526,6 @@ struct __large_struct { unsigned long buf[100]; }; | |||
525 | */ | 526 | */ |
526 | #define get_user_try uaccess_try | 527 | #define get_user_try uaccess_try |
527 | #define get_user_catch(err) uaccess_catch(err) | 528 | #define get_user_catch(err) uaccess_catch(err) |
528 | #define put_user_try uaccess_try | ||
529 | #define put_user_catch(err) uaccess_catch(err) | ||
530 | 529 | ||
531 | #define get_user_ex(x, ptr) do { \ | 530 | #define get_user_ex(x, ptr) do { \ |
532 | unsigned long __gue_val; \ | 531 | unsigned long __gue_val; \ |
@@ -534,9 +533,29 @@ struct __large_struct { unsigned long buf[100]; }; | |||
534 | (x) = (__force __typeof__(*(ptr)))__gue_val; \ | 533 | (x) = (__force __typeof__(*(ptr)))__gue_val; \ |
535 | } while (0) | 534 | } while (0) |
536 | 535 | ||
536 | #ifdef CONFIG_X86_WP_WORKS_OK | ||
537 | |||
538 | #define put_user_try uaccess_try | ||
539 | #define put_user_catch(err) uaccess_catch(err) | ||
540 | |||
537 | #define put_user_ex(x, ptr) \ | 541 | #define put_user_ex(x, ptr) \ |
538 | __put_user_size_ex((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr))) | 542 | __put_user_size_ex((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr))) |
539 | 543 | ||
544 | #else /* !CONFIG_X86_WP_WORKS_OK */ | ||
545 | |||
546 | #define put_user_try do { \ | ||
547 | int __uaccess_err = 0; | ||
548 | |||
549 | #define put_user_catch(err) \ | ||
550 | (err) |= __uaccess_err; \ | ||
551 | } while (0) | ||
552 | |||
553 | #define put_user_ex(x, ptr) do { \ | ||
554 | __uaccess_err |= __put_user(x, ptr); \ | ||
555 | } while (0) | ||
556 | |||
557 | #endif /* CONFIG_X86_WP_WORKS_OK */ | ||
558 | |||
540 | /* | 559 | /* |
541 | * movsl can be slow when source and dest are not both 8-byte aligned | 560 | * movsl can be slow when source and dest are not both 8-byte aligned |
542 | */ | 561 | */ |
diff --git a/arch/x86/include/asm/uv/uv.h b/arch/x86/include/asm/uv/uv.h index 8ac1d7e312f3..8242bf965812 100644 --- a/arch/x86/include/asm/uv/uv.h +++ b/arch/x86/include/asm/uv/uv.h | |||
@@ -3,6 +3,9 @@ | |||
3 | 3 | ||
4 | enum uv_system_type {UV_NONE, UV_LEGACY_APIC, UV_X2APIC, UV_NON_UNIQUE_APIC}; | 4 | enum uv_system_type {UV_NONE, UV_LEGACY_APIC, UV_X2APIC, UV_NON_UNIQUE_APIC}; |
5 | 5 | ||
6 | struct cpumask; | ||
7 | struct mm_struct; | ||
8 | |||
6 | #ifdef CONFIG_X86_UV | 9 | #ifdef CONFIG_X86_UV |
7 | 10 | ||
8 | extern enum uv_system_type get_uv_system_type(void); | 11 | extern enum uv_system_type get_uv_system_type(void); |