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/asm/system.h | |
parent | f8a6b2b9cee298a9663cbe38ce1eb5240987cb62 (diff) | |
parent | 58105ef1857112a186696c9b8957020090226a28 (diff) |
Merge branch 'core/percpu' into x86/core
Diffstat (limited to 'arch/x86/include/asm/system.h')
-rw-r--r-- | arch/x86/include/asm/system.h | 38 |
1 files changed, 38 insertions, 0 deletions
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; |