blob: b150c87a08c6b3131909d8af5b567699e58ce098 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * linux/arch/x86_64/entry.S
3 *
4 * Copyright (C) 1991, 1992 Linus Torvalds
5 * Copyright (C) 2000, 2001, 2002 Andi Kleen SuSE Labs
6 * Copyright (C) 2000 Pavel Machek <pavel@suse.cz>
7 *
8 * $Id$
9 */
10
11/*
12 * entry.S contains the system-call and fault low-level handling routines.
13 *
14 * NOTE: This code handles signal-recognition, which happens every time
15 * after an interrupt and after each system call.
16 *
17 * Normal syscalls and interrupts don't save a full stack frame, this is
18 * only done for syscall tracing, signals or fork/exec et.al.
19 *
20 * A note on terminology:
21 * - top of stack: Architecture defined interrupt frame from SS to RIP
22 * at the top of the kernel process stack.
23 * - partial stack frame: partially saved registers upto R11.
24 * - full stack frame: Like partial stack frame, but all register saved.
25 *
26 * TODO:
27 * - schedule it carefully for the final hardware.
28 */
29
30#define ASSEMBLY 1
31#include <linux/config.h>
32#include <linux/linkage.h>
33#include <asm/segment.h>
34#include <asm/smp.h>
35#include <asm/cache.h>
36#include <asm/errno.h>
37#include <asm/dwarf2.h>
38#include <asm/calling.h>
Sam Ravnborge2d5df92005-09-09 21:28:48 +020039#include <asm/asm-offsets.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070040#include <asm/msr.h>
41#include <asm/unistd.h>
42#include <asm/thread_info.h>
43#include <asm/hw_irq.h>
Andi Kleen5f8efbb2006-01-16 01:56:39 +010044#include <asm/page.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070045
46 .code64
47
Andi Kleendc37db42005-04-16 15:25:05 -070048#ifndef CONFIG_PREEMPT
Linus Torvalds1da177e2005-04-16 15:20:36 -070049#define retint_kernel retint_restore_args
50#endif
51
52/*
53 * C code is not supposed to know about undefined top of stack. Every time
54 * a C function with an pt_regs argument is called from the SYSCALL based
55 * fast path FIXUP_TOP_OF_STACK is needed.
56 * RESTORE_TOP_OF_STACK syncs the syscall state after any possible ptregs
57 * manipulation.
58 */
59
60 /* %rsp:at FRAMEEND */
61 .macro FIXUP_TOP_OF_STACK tmp
62 movq %gs:pda_oldrsp,\tmp
63 movq \tmp,RSP(%rsp)
64 movq $__USER_DS,SS(%rsp)
65 movq $__USER_CS,CS(%rsp)
66 movq $-1,RCX(%rsp)
67 movq R11(%rsp),\tmp /* get eflags */
68 movq \tmp,EFLAGS(%rsp)
69 .endm
70
71 .macro RESTORE_TOP_OF_STACK tmp,offset=0
72 movq RSP-\offset(%rsp),\tmp
73 movq \tmp,%gs:pda_oldrsp
74 movq EFLAGS-\offset(%rsp),\tmp
75 movq \tmp,R11-\offset(%rsp)
76 .endm
77
78 .macro FAKE_STACK_FRAME child_rip
79 /* push in order ss, rsp, eflags, cs, rip */
Andi Kleen3829ee62005-07-28 21:15:48 -070080 xorl %eax, %eax
Linus Torvalds1da177e2005-04-16 15:20:36 -070081 pushq %rax /* ss */
82 CFI_ADJUST_CFA_OFFSET 8
Jan Beulich7effaa82005-09-12 18:49:24 +020083 /*CFI_REL_OFFSET ss,0*/
Linus Torvalds1da177e2005-04-16 15:20:36 -070084 pushq %rax /* rsp */
85 CFI_ADJUST_CFA_OFFSET 8
Jan Beulich7effaa82005-09-12 18:49:24 +020086 CFI_REL_OFFSET rsp,0
Linus Torvalds1da177e2005-04-16 15:20:36 -070087 pushq $(1<<9) /* eflags - interrupts on */
88 CFI_ADJUST_CFA_OFFSET 8
Jan Beulich7effaa82005-09-12 18:49:24 +020089 /*CFI_REL_OFFSET rflags,0*/
Linus Torvalds1da177e2005-04-16 15:20:36 -070090 pushq $__KERNEL_CS /* cs */
91 CFI_ADJUST_CFA_OFFSET 8
Jan Beulich7effaa82005-09-12 18:49:24 +020092 /*CFI_REL_OFFSET cs,0*/
Linus Torvalds1da177e2005-04-16 15:20:36 -070093 pushq \child_rip /* rip */
94 CFI_ADJUST_CFA_OFFSET 8
Jan Beulich7effaa82005-09-12 18:49:24 +020095 CFI_REL_OFFSET rip,0
Linus Torvalds1da177e2005-04-16 15:20:36 -070096 pushq %rax /* orig rax */
97 CFI_ADJUST_CFA_OFFSET 8
98 .endm
99
100 .macro UNFAKE_STACK_FRAME
101 addq $8*6, %rsp
102 CFI_ADJUST_CFA_OFFSET -(6*8)
103 .endm
104
Jan Beulich7effaa82005-09-12 18:49:24 +0200105 .macro CFI_DEFAULT_STACK start=1
106 .if \start
107 CFI_STARTPROC simple
108 CFI_DEF_CFA rsp,SS+8
109 .else
110 CFI_DEF_CFA_OFFSET SS+8
111 .endif
112 CFI_REL_OFFSET r15,R15
113 CFI_REL_OFFSET r14,R14
114 CFI_REL_OFFSET r13,R13
115 CFI_REL_OFFSET r12,R12
116 CFI_REL_OFFSET rbp,RBP
117 CFI_REL_OFFSET rbx,RBX
118 CFI_REL_OFFSET r11,R11
119 CFI_REL_OFFSET r10,R10
120 CFI_REL_OFFSET r9,R9
121 CFI_REL_OFFSET r8,R8
122 CFI_REL_OFFSET rax,RAX
123 CFI_REL_OFFSET rcx,RCX
124 CFI_REL_OFFSET rdx,RDX
125 CFI_REL_OFFSET rsi,RSI
126 CFI_REL_OFFSET rdi,RDI
127 CFI_REL_OFFSET rip,RIP
128 /*CFI_REL_OFFSET cs,CS*/
129 /*CFI_REL_OFFSET rflags,EFLAGS*/
130 CFI_REL_OFFSET rsp,RSP
131 /*CFI_REL_OFFSET ss,SS*/
Linus Torvalds1da177e2005-04-16 15:20:36 -0700132 .endm
133/*
134 * A newly forked process directly context switches into this.
135 */
136/* rdi: prev */
137ENTRY(ret_from_fork)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700138 CFI_DEFAULT_STACK
139 call schedule_tail
140 GET_THREAD_INFO(%rcx)
141 testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT),threadinfo_flags(%rcx)
142 jnz rff_trace
143rff_action:
144 RESTORE_REST
145 testl $3,CS-ARGOFFSET(%rsp) # from kernel_thread?
146 je int_ret_from_sys_call
147 testl $_TIF_IA32,threadinfo_flags(%rcx)
148 jnz int_ret_from_sys_call
149 RESTORE_TOP_OF_STACK %rdi,ARGOFFSET
150 jmp ret_from_sys_call
151rff_trace:
152 movq %rsp,%rdi
153 call syscall_trace_leave
154 GET_THREAD_INFO(%rcx)
155 jmp rff_action
156 CFI_ENDPROC
157
158/*
159 * System call entry. Upto 6 arguments in registers are supported.
160 *
161 * SYSCALL does not save anything on the stack and does not change the
162 * stack pointer.
163 */
164
165/*
166 * Register setup:
167 * rax system call number
168 * rdi arg0
169 * rcx return address for syscall/sysret, C arg3
170 * rsi arg1
171 * rdx arg2
172 * r10 arg3 (--> moved to rcx for C)
173 * r8 arg4
174 * r9 arg5
175 * r11 eflags for syscall/sysret, temporary for C
176 * r12-r15,rbp,rbx saved by C code, not touched.
177 *
178 * Interrupts are off on entry.
179 * Only called from user space.
180 *
181 * XXX if we had a free scratch register we could save the RSP into the stack frame
182 * and report it properly in ps. Unfortunately we haven't.
183 */
184
185ENTRY(system_call)
Jan Beulich7effaa82005-09-12 18:49:24 +0200186 CFI_STARTPROC simple
187 CFI_DEF_CFA rsp,0
188 CFI_REGISTER rip,rcx
189 /*CFI_REGISTER rflags,r11*/
Linus Torvalds1da177e2005-04-16 15:20:36 -0700190 swapgs
191 movq %rsp,%gs:pda_oldrsp
192 movq %gs:pda_kernelstack,%rsp
193 sti
194 SAVE_ARGS 8,1
195 movq %rax,ORIG_RAX-ARGOFFSET(%rsp)
Jan Beulich7effaa82005-09-12 18:49:24 +0200196 movq %rcx,RIP-ARGOFFSET(%rsp)
197 CFI_REL_OFFSET rip,RIP-ARGOFFSET
Linus Torvalds1da177e2005-04-16 15:20:36 -0700198 GET_THREAD_INFO(%rcx)
199 testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP),threadinfo_flags(%rcx)
Jan Beulich7effaa82005-09-12 18:49:24 +0200200 CFI_REMEMBER_STATE
Linus Torvalds1da177e2005-04-16 15:20:36 -0700201 jnz tracesys
202 cmpq $__NR_syscall_max,%rax
203 ja badsys
204 movq %r10,%rcx
205 call *sys_call_table(,%rax,8) # XXX: rip relative
206 movq %rax,RAX-ARGOFFSET(%rsp)
207/*
208 * Syscall return path ending with SYSRET (fast path)
209 * Has incomplete stack frame and undefined top of stack.
210 */
211 .globl ret_from_sys_call
212ret_from_sys_call:
Andi Kleen11b854b2005-04-16 15:25:02 -0700213 movl $_TIF_ALLWORK_MASK,%edi
Linus Torvalds1da177e2005-04-16 15:20:36 -0700214 /* edi: flagmask */
215sysret_check:
216 GET_THREAD_INFO(%rcx)
217 cli
218 movl threadinfo_flags(%rcx),%edx
219 andl %edi,%edx
Jan Beulich7effaa82005-09-12 18:49:24 +0200220 CFI_REMEMBER_STATE
Linus Torvalds1da177e2005-04-16 15:20:36 -0700221 jnz sysret_careful
222 movq RIP-ARGOFFSET(%rsp),%rcx
Jan Beulich7effaa82005-09-12 18:49:24 +0200223 CFI_REGISTER rip,rcx
Linus Torvalds1da177e2005-04-16 15:20:36 -0700224 RESTORE_ARGS 0,-ARG_SKIP,1
Jan Beulich7effaa82005-09-12 18:49:24 +0200225 /*CFI_REGISTER rflags,r11*/
Linus Torvalds1da177e2005-04-16 15:20:36 -0700226 movq %gs:pda_oldrsp,%rsp
227 swapgs
228 sysretq
229
230 /* Handle reschedules */
231 /* edx: work, edi: workmask */
232sysret_careful:
Jan Beulich7effaa82005-09-12 18:49:24 +0200233 CFI_RESTORE_STATE
Linus Torvalds1da177e2005-04-16 15:20:36 -0700234 bt $TIF_NEED_RESCHED,%edx
235 jnc sysret_signal
236 sti
237 pushq %rdi
Jan Beulich7effaa82005-09-12 18:49:24 +0200238 CFI_ADJUST_CFA_OFFSET 8
Linus Torvalds1da177e2005-04-16 15:20:36 -0700239 call schedule
240 popq %rdi
Jan Beulich7effaa82005-09-12 18:49:24 +0200241 CFI_ADJUST_CFA_OFFSET -8
Linus Torvalds1da177e2005-04-16 15:20:36 -0700242 jmp sysret_check
243
244 /* Handle a signal */
245sysret_signal:
246 sti
Andi Kleen10ffdbb2005-05-16 21:53:19 -0700247 testl $(_TIF_SIGPENDING|_TIF_NOTIFY_RESUME|_TIF_SINGLESTEP),%edx
248 jz 1f
249
250 /* Really a signal */
251 /* edx: work flags (arg3) */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700252 leaq do_notify_resume(%rip),%rax
253 leaq -ARGOFFSET(%rsp),%rdi # &pt_regs -> arg1
254 xorl %esi,%esi # oldset -> arg2
255 call ptregscall_common
Andi Kleen10ffdbb2005-05-16 21:53:19 -07002561: movl $_TIF_NEED_RESCHED,%edi
Linus Torvalds1da177e2005-04-16 15:20:36 -0700257 jmp sysret_check
258
Jan Beulich7effaa82005-09-12 18:49:24 +0200259badsys:
260 movq $-ENOSYS,RAX-ARGOFFSET(%rsp)
261 jmp ret_from_sys_call
262
Linus Torvalds1da177e2005-04-16 15:20:36 -0700263 /* Do syscall tracing */
264tracesys:
Jan Beulich7effaa82005-09-12 18:49:24 +0200265 CFI_RESTORE_STATE
Linus Torvalds1da177e2005-04-16 15:20:36 -0700266 SAVE_REST
267 movq $-ENOSYS,RAX(%rsp)
268 FIXUP_TOP_OF_STACK %rdi
269 movq %rsp,%rdi
270 call syscall_trace_enter
271 LOAD_ARGS ARGOFFSET /* reload args from stack in case ptrace changed it */
272 RESTORE_REST
273 cmpq $__NR_syscall_max,%rax
274 ja 1f
275 movq %r10,%rcx /* fixup for C */
276 call *sys_call_table(,%rax,8)
277 movq %rax,RAX-ARGOFFSET(%rsp)
2781: SAVE_REST
279 movq %rsp,%rdi
280 call syscall_trace_leave
281 RESTORE_TOP_OF_STACK %rbx
282 RESTORE_REST
283 jmp ret_from_sys_call
Jan Beulich7effaa82005-09-12 18:49:24 +0200284 CFI_ENDPROC
Linus Torvalds1da177e2005-04-16 15:20:36 -0700285
Linus Torvalds1da177e2005-04-16 15:20:36 -0700286/*
287 * Syscall return path ending with IRET.
288 * Has correct top of stack, but partial stack frame.
289 */
Jan Beulich7effaa82005-09-12 18:49:24 +0200290ENTRY(int_ret_from_sys_call)
291 CFI_STARTPROC simple
292 CFI_DEF_CFA rsp,SS+8-ARGOFFSET
293 /*CFI_REL_OFFSET ss,SS-ARGOFFSET*/
294 CFI_REL_OFFSET rsp,RSP-ARGOFFSET
295 /*CFI_REL_OFFSET rflags,EFLAGS-ARGOFFSET*/
296 /*CFI_REL_OFFSET cs,CS-ARGOFFSET*/
297 CFI_REL_OFFSET rip,RIP-ARGOFFSET
298 CFI_REL_OFFSET rdx,RDX-ARGOFFSET
299 CFI_REL_OFFSET rcx,RCX-ARGOFFSET
300 CFI_REL_OFFSET rax,RAX-ARGOFFSET
301 CFI_REL_OFFSET rdi,RDI-ARGOFFSET
302 CFI_REL_OFFSET rsi,RSI-ARGOFFSET
303 CFI_REL_OFFSET r8,R8-ARGOFFSET
304 CFI_REL_OFFSET r9,R9-ARGOFFSET
305 CFI_REL_OFFSET r10,R10-ARGOFFSET
306 CFI_REL_OFFSET r11,R11-ARGOFFSET
Linus Torvalds1da177e2005-04-16 15:20:36 -0700307 cli
308 testl $3,CS-ARGOFFSET(%rsp)
309 je retint_restore_args
310 movl $_TIF_ALLWORK_MASK,%edi
311 /* edi: mask to check */
312int_with_check:
313 GET_THREAD_INFO(%rcx)
314 movl threadinfo_flags(%rcx),%edx
315 andl %edi,%edx
316 jnz int_careful
Andi Kleenbf2fcc62006-01-11 22:44:06 +0100317 andl $~TS_COMPAT,threadinfo_status(%rcx)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700318 jmp retint_swapgs
319
320 /* Either reschedule or signal or syscall exit tracking needed. */
321 /* First do a reschedule test. */
322 /* edx: work, edi: workmask */
323int_careful:
324 bt $TIF_NEED_RESCHED,%edx
325 jnc int_very_careful
326 sti
327 pushq %rdi
Jan Beulich7effaa82005-09-12 18:49:24 +0200328 CFI_ADJUST_CFA_OFFSET 8
Linus Torvalds1da177e2005-04-16 15:20:36 -0700329 call schedule
330 popq %rdi
Jan Beulich7effaa82005-09-12 18:49:24 +0200331 CFI_ADJUST_CFA_OFFSET -8
Andi Kleencdd219c2005-04-16 15:25:04 -0700332 cli
Linus Torvalds1da177e2005-04-16 15:20:36 -0700333 jmp int_with_check
334
335 /* handle signals and tracing -- both require a full stack frame */
336int_very_careful:
337 sti
338 SAVE_REST
339 /* Check for syscall exit trace */
340 testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP),%edx
341 jz int_signal
342 pushq %rdi
Jan Beulich7effaa82005-09-12 18:49:24 +0200343 CFI_ADJUST_CFA_OFFSET 8
Linus Torvalds1da177e2005-04-16 15:20:36 -0700344 leaq 8(%rsp),%rdi # &ptregs -> arg1
345 call syscall_trace_leave
346 popq %rdi
Jan Beulich7effaa82005-09-12 18:49:24 +0200347 CFI_ADJUST_CFA_OFFSET -8
Andi Kleen36c11042005-04-16 15:25:01 -0700348 andl $~(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP),%edi
Andi Kleenbe9e6872005-05-01 08:58:51 -0700349 cli
Linus Torvalds1da177e2005-04-16 15:20:36 -0700350 jmp int_restore_rest
351
352int_signal:
353 testl $(_TIF_NOTIFY_RESUME|_TIF_SIGPENDING|_TIF_SINGLESTEP),%edx
354 jz 1f
355 movq %rsp,%rdi # &ptregs -> arg1
356 xorl %esi,%esi # oldset -> arg2
357 call do_notify_resume
3581: movl $_TIF_NEED_RESCHED,%edi
359int_restore_rest:
360 RESTORE_REST
Andi Kleenbe9e6872005-05-01 08:58:51 -0700361 cli
Linus Torvalds1da177e2005-04-16 15:20:36 -0700362 jmp int_with_check
363 CFI_ENDPROC
364
365/*
366 * Certain special system calls that need to save a complete full stack frame.
367 */
368
369 .macro PTREGSCALL label,func,arg
370 .globl \label
371\label:
372 leaq \func(%rip),%rax
373 leaq -ARGOFFSET+8(%rsp),\arg /* 8 for return address */
374 jmp ptregscall_common
375 .endm
376
Jan Beulich7effaa82005-09-12 18:49:24 +0200377 CFI_STARTPROC
378
Linus Torvalds1da177e2005-04-16 15:20:36 -0700379 PTREGSCALL stub_clone, sys_clone, %r8
380 PTREGSCALL stub_fork, sys_fork, %rdi
381 PTREGSCALL stub_vfork, sys_vfork, %rdi
382 PTREGSCALL stub_rt_sigsuspend, sys_rt_sigsuspend, %rdx
383 PTREGSCALL stub_sigaltstack, sys_sigaltstack, %rdx
384 PTREGSCALL stub_iopl, sys_iopl, %rsi
385
386ENTRY(ptregscall_common)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700387 popq %r11
Jan Beulich7effaa82005-09-12 18:49:24 +0200388 CFI_ADJUST_CFA_OFFSET -8
389 CFI_REGISTER rip, r11
Linus Torvalds1da177e2005-04-16 15:20:36 -0700390 SAVE_REST
391 movq %r11, %r15
Jan Beulich7effaa82005-09-12 18:49:24 +0200392 CFI_REGISTER rip, r15
Linus Torvalds1da177e2005-04-16 15:20:36 -0700393 FIXUP_TOP_OF_STACK %r11
394 call *%rax
395 RESTORE_TOP_OF_STACK %r11
396 movq %r15, %r11
Jan Beulich7effaa82005-09-12 18:49:24 +0200397 CFI_REGISTER rip, r11
Linus Torvalds1da177e2005-04-16 15:20:36 -0700398 RESTORE_REST
399 pushq %r11
Jan Beulich7effaa82005-09-12 18:49:24 +0200400 CFI_ADJUST_CFA_OFFSET 8
401 CFI_REL_OFFSET rip, 0
Linus Torvalds1da177e2005-04-16 15:20:36 -0700402 ret
403 CFI_ENDPROC
404
405ENTRY(stub_execve)
406 CFI_STARTPROC
407 popq %r11
Jan Beulich7effaa82005-09-12 18:49:24 +0200408 CFI_ADJUST_CFA_OFFSET -8
409 CFI_REGISTER rip, r11
Linus Torvalds1da177e2005-04-16 15:20:36 -0700410 SAVE_REST
411 movq %r11, %r15
Jan Beulich7effaa82005-09-12 18:49:24 +0200412 CFI_REGISTER rip, r15
Linus Torvalds1da177e2005-04-16 15:20:36 -0700413 FIXUP_TOP_OF_STACK %r11
414 call sys_execve
415 GET_THREAD_INFO(%rcx)
416 bt $TIF_IA32,threadinfo_flags(%rcx)
Jan Beulich7effaa82005-09-12 18:49:24 +0200417 CFI_REMEMBER_STATE
Linus Torvalds1da177e2005-04-16 15:20:36 -0700418 jc exec_32bit
419 RESTORE_TOP_OF_STACK %r11
420 movq %r15, %r11
Jan Beulich7effaa82005-09-12 18:49:24 +0200421 CFI_REGISTER rip, r11
Linus Torvalds1da177e2005-04-16 15:20:36 -0700422 RESTORE_REST
Jan Beulich7effaa82005-09-12 18:49:24 +0200423 pushq %r11
424 CFI_ADJUST_CFA_OFFSET 8
425 CFI_REL_OFFSET rip, 0
Linus Torvalds1da177e2005-04-16 15:20:36 -0700426 ret
427
428exec_32bit:
Jan Beulich7effaa82005-09-12 18:49:24 +0200429 CFI_RESTORE_STATE
Linus Torvalds1da177e2005-04-16 15:20:36 -0700430 movq %rax,RAX(%rsp)
431 RESTORE_REST
432 jmp int_ret_from_sys_call
433 CFI_ENDPROC
434
435/*
436 * sigreturn is special because it needs to restore all registers on return.
437 * This cannot be done with SYSRET, so use the IRET return path instead.
438 */
439ENTRY(stub_rt_sigreturn)
440 CFI_STARTPROC
Jan Beulich7effaa82005-09-12 18:49:24 +0200441 addq $8, %rsp
442 CFI_ADJUST_CFA_OFFSET -8
Linus Torvalds1da177e2005-04-16 15:20:36 -0700443 SAVE_REST
444 movq %rsp,%rdi
445 FIXUP_TOP_OF_STACK %r11
446 call sys_rt_sigreturn
447 movq %rax,RAX(%rsp) # fixme, this could be done at the higher layer
448 RESTORE_REST
449 jmp int_ret_from_sys_call
450 CFI_ENDPROC
451
Jan Beulich7effaa82005-09-12 18:49:24 +0200452/*
453 * initial frame state for interrupts and exceptions
454 */
455 .macro _frame ref
456 CFI_STARTPROC simple
457 CFI_DEF_CFA rsp,SS+8-\ref
458 /*CFI_REL_OFFSET ss,SS-\ref*/
459 CFI_REL_OFFSET rsp,RSP-\ref
460 /*CFI_REL_OFFSET rflags,EFLAGS-\ref*/
461 /*CFI_REL_OFFSET cs,CS-\ref*/
462 CFI_REL_OFFSET rip,RIP-\ref
463 .endm
464
465/* initial frame state for interrupts (and exceptions without error code) */
466#define INTR_FRAME _frame RIP
467/* initial frame state for exceptions with error code (and interrupts with
468 vector already pushed) */
469#define XCPT_FRAME _frame ORIG_RAX
470
Linus Torvalds1da177e2005-04-16 15:20:36 -0700471/*
472 * Interrupt entry/exit.
473 *
474 * Interrupt entry points save only callee clobbered registers in fast path.
475 *
476 * Entry runs with interrupts off.
477 */
478
479/* 0(%rsp): interrupt number */
480 .macro interrupt func
Linus Torvalds1da177e2005-04-16 15:20:36 -0700481 cld
482#ifdef CONFIG_DEBUG_INFO
483 SAVE_ALL
484 movq %rsp,%rdi
485 /*
486 * Setup a stack frame pointer. This allows gdb to trace
487 * back to the original stack.
488 */
489 movq %rsp,%rbp
490 CFI_DEF_CFA_REGISTER rbp
491#else
492 SAVE_ARGS
493 leaq -ARGOFFSET(%rsp),%rdi # arg1 for handler
494#endif
495 testl $3,CS(%rdi)
496 je 1f
497 swapgs
Andi Kleen3829ee62005-07-28 21:15:48 -07004981: incl %gs:pda_irqcount # RED-PEN should check preempt count
Linus Torvalds1da177e2005-04-16 15:20:36 -0700499 movq %gs:pda_irqstackptr,%rax
Jan Beulich7effaa82005-09-12 18:49:24 +0200500 cmoveq %rax,%rsp /*todo This needs CFI annotation! */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700501 pushq %rdi # save old stack
Jan Beulich91522a92006-02-03 21:51:44 +0100502#ifndef CONFIG_DEBUG_INFO
Jan Beulich7effaa82005-09-12 18:49:24 +0200503 CFI_ADJUST_CFA_OFFSET 8
Jan Beulich91522a92006-02-03 21:51:44 +0100504#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700505 call \func
506 .endm
507
508ENTRY(common_interrupt)
Jan Beulich7effaa82005-09-12 18:49:24 +0200509 XCPT_FRAME
Linus Torvalds1da177e2005-04-16 15:20:36 -0700510 interrupt do_IRQ
511 /* 0(%rsp): oldrsp-ARGOFFSET */
Jan Beulich7effaa82005-09-12 18:49:24 +0200512ret_from_intr:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700513 popq %rdi
Jan Beulich91522a92006-02-03 21:51:44 +0100514#ifndef CONFIG_DEBUG_INFO
Jan Beulich7effaa82005-09-12 18:49:24 +0200515 CFI_ADJUST_CFA_OFFSET -8
Jan Beulich91522a92006-02-03 21:51:44 +0100516#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700517 cli
Andi Kleen3829ee62005-07-28 21:15:48 -0700518 decl %gs:pda_irqcount
Linus Torvalds1da177e2005-04-16 15:20:36 -0700519#ifdef CONFIG_DEBUG_INFO
520 movq RBP(%rdi),%rbp
Jan Beulich7effaa82005-09-12 18:49:24 +0200521 CFI_DEF_CFA_REGISTER rsp
Linus Torvalds1da177e2005-04-16 15:20:36 -0700522#endif
Jan Beulich7effaa82005-09-12 18:49:24 +0200523 leaq ARGOFFSET(%rdi),%rsp /*todo This needs CFI annotation! */
524exit_intr:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700525 GET_THREAD_INFO(%rcx)
526 testl $3,CS-ARGOFFSET(%rsp)
527 je retint_kernel
528
529 /* Interrupt came from user space */
530 /*
531 * Has a correct top of stack, but a partial stack frame
532 * %rcx: thread info. Interrupts off.
533 */
534retint_with_reschedule:
535 movl $_TIF_WORK_MASK,%edi
Jan Beulich7effaa82005-09-12 18:49:24 +0200536retint_check:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700537 movl threadinfo_flags(%rcx),%edx
538 andl %edi,%edx
Jan Beulich7effaa82005-09-12 18:49:24 +0200539 CFI_REMEMBER_STATE
Linus Torvalds1da177e2005-04-16 15:20:36 -0700540 jnz retint_careful
541retint_swapgs:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700542 swapgs
543retint_restore_args:
544 cli
545 RESTORE_ARGS 0,8,0
546iret_label:
547 iretq
548
549 .section __ex_table,"a"
550 .quad iret_label,bad_iret
551 .previous
552 .section .fixup,"ax"
553 /* force a signal here? this matches i386 behaviour */
554 /* running with kernel gs */
555bad_iret:
556 movq $-9999,%rdi /* better code? */
557 jmp do_exit
558 .previous
559
Jan Beulich7effaa82005-09-12 18:49:24 +0200560 /* edi: workmask, edx: work */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700561retint_careful:
Jan Beulich7effaa82005-09-12 18:49:24 +0200562 CFI_RESTORE_STATE
Linus Torvalds1da177e2005-04-16 15:20:36 -0700563 bt $TIF_NEED_RESCHED,%edx
564 jnc retint_signal
565 sti
566 pushq %rdi
Jan Beulich7effaa82005-09-12 18:49:24 +0200567 CFI_ADJUST_CFA_OFFSET 8
Linus Torvalds1da177e2005-04-16 15:20:36 -0700568 call schedule
569 popq %rdi
Jan Beulich7effaa82005-09-12 18:49:24 +0200570 CFI_ADJUST_CFA_OFFSET -8
Linus Torvalds1da177e2005-04-16 15:20:36 -0700571 GET_THREAD_INFO(%rcx)
572 cli
573 jmp retint_check
574
575retint_signal:
Andi Kleen10ffdbb2005-05-16 21:53:19 -0700576 testl $(_TIF_SIGPENDING|_TIF_NOTIFY_RESUME|_TIF_SINGLESTEP),%edx
577 jz retint_swapgs
Linus Torvalds1da177e2005-04-16 15:20:36 -0700578 sti
579 SAVE_REST
580 movq $-1,ORIG_RAX(%rsp)
Andi Kleen3829ee62005-07-28 21:15:48 -0700581 xorl %esi,%esi # oldset
Linus Torvalds1da177e2005-04-16 15:20:36 -0700582 movq %rsp,%rdi # &pt_regs
583 call do_notify_resume
584 RESTORE_REST
585 cli
Andi Kleen10ffdbb2005-05-16 21:53:19 -0700586 movl $_TIF_NEED_RESCHED,%edi
Andi Kleenbe9e6872005-05-01 08:58:51 -0700587 GET_THREAD_INFO(%rcx)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700588 jmp retint_check
589
590#ifdef CONFIG_PREEMPT
591 /* Returning to kernel space. Check if we need preemption */
592 /* rcx: threadinfo. interrupts off. */
593 .p2align
594retint_kernel:
595 cmpl $0,threadinfo_preempt_count(%rcx)
596 jnz retint_restore_args
597 bt $TIF_NEED_RESCHED,threadinfo_flags(%rcx)
598 jnc retint_restore_args
599 bt $9,EFLAGS-ARGOFFSET(%rsp) /* interrupts off? */
600 jnc retint_restore_args
601 call preempt_schedule_irq
602 jmp exit_intr
603#endif
604 CFI_ENDPROC
605
606/*
607 * APIC interrupts.
608 */
609 .macro apicinterrupt num,func
Jan Beulich7effaa82005-09-12 18:49:24 +0200610 INTR_FRAME
Linus Torvalds1da177e2005-04-16 15:20:36 -0700611 pushq $\num-256
Jan Beulich7effaa82005-09-12 18:49:24 +0200612 CFI_ADJUST_CFA_OFFSET 8
Linus Torvalds1da177e2005-04-16 15:20:36 -0700613 interrupt \func
614 jmp ret_from_intr
615 CFI_ENDPROC
616 .endm
617
618ENTRY(thermal_interrupt)
619 apicinterrupt THERMAL_APIC_VECTOR,smp_thermal_interrupt
620
Jacob Shin89b831e2005-11-05 17:25:53 +0100621ENTRY(threshold_interrupt)
622 apicinterrupt THRESHOLD_APIC_VECTOR,mce_threshold_interrupt
623
Linus Torvalds1da177e2005-04-16 15:20:36 -0700624#ifdef CONFIG_SMP
625ENTRY(reschedule_interrupt)
626 apicinterrupt RESCHEDULE_VECTOR,smp_reschedule_interrupt
627
Andi Kleene5bc8b62005-09-12 18:49:24 +0200628 .macro INVALIDATE_ENTRY num
629ENTRY(invalidate_interrupt\num)
630 apicinterrupt INVALIDATE_TLB_VECTOR_START+\num,smp_invalidate_interrupt
631 .endm
632
633 INVALIDATE_ENTRY 0
634 INVALIDATE_ENTRY 1
635 INVALIDATE_ENTRY 2
636 INVALIDATE_ENTRY 3
637 INVALIDATE_ENTRY 4
638 INVALIDATE_ENTRY 5
639 INVALIDATE_ENTRY 6
640 INVALIDATE_ENTRY 7
Linus Torvalds1da177e2005-04-16 15:20:36 -0700641
642ENTRY(call_function_interrupt)
643 apicinterrupt CALL_FUNCTION_VECTOR,smp_call_function_interrupt
644#endif
645
646#ifdef CONFIG_X86_LOCAL_APIC
647ENTRY(apic_timer_interrupt)
648 apicinterrupt LOCAL_TIMER_VECTOR,smp_apic_timer_interrupt
649
650ENTRY(error_interrupt)
651 apicinterrupt ERROR_APIC_VECTOR,smp_error_interrupt
652
653ENTRY(spurious_interrupt)
654 apicinterrupt SPURIOUS_APIC_VECTOR,smp_spurious_interrupt
655#endif
656
657/*
658 * Exception entry points.
659 */
660 .macro zeroentry sym
Jan Beulich7effaa82005-09-12 18:49:24 +0200661 INTR_FRAME
Linus Torvalds1da177e2005-04-16 15:20:36 -0700662 pushq $0 /* push error code/oldrax */
Jan Beulich7effaa82005-09-12 18:49:24 +0200663 CFI_ADJUST_CFA_OFFSET 8
Linus Torvalds1da177e2005-04-16 15:20:36 -0700664 pushq %rax /* push real oldrax to the rdi slot */
Jan Beulich7effaa82005-09-12 18:49:24 +0200665 CFI_ADJUST_CFA_OFFSET 8
Linus Torvalds1da177e2005-04-16 15:20:36 -0700666 leaq \sym(%rip),%rax
667 jmp error_entry
Jan Beulich7effaa82005-09-12 18:49:24 +0200668 CFI_ENDPROC
Linus Torvalds1da177e2005-04-16 15:20:36 -0700669 .endm
670
671 .macro errorentry sym
Jan Beulich7effaa82005-09-12 18:49:24 +0200672 XCPT_FRAME
Linus Torvalds1da177e2005-04-16 15:20:36 -0700673 pushq %rax
Jan Beulich7effaa82005-09-12 18:49:24 +0200674 CFI_ADJUST_CFA_OFFSET 8
Linus Torvalds1da177e2005-04-16 15:20:36 -0700675 leaq \sym(%rip),%rax
676 jmp error_entry
Jan Beulich7effaa82005-09-12 18:49:24 +0200677 CFI_ENDPROC
Linus Torvalds1da177e2005-04-16 15:20:36 -0700678 .endm
679
680 /* error code is on the stack already */
681 /* handle NMI like exceptions that can happen everywhere */
Jan Beulichb556b352006-01-11 22:43:00 +0100682 .macro paranoidentry sym, ist=0
Linus Torvalds1da177e2005-04-16 15:20:36 -0700683 SAVE_ALL
684 cld
685 movl $1,%ebx
686 movl $MSR_GS_BASE,%ecx
687 rdmsr
688 testl %edx,%edx
689 js 1f
690 swapgs
691 xorl %ebx,%ebx
Jan Beulichb556b352006-01-11 22:43:00 +01006921:
693 .if \ist
694 movq %gs:pda_data_offset, %rbp
695 .endif
696 movq %rsp,%rdi
Linus Torvalds1da177e2005-04-16 15:20:36 -0700697 movq ORIG_RAX(%rsp),%rsi
698 movq $-1,ORIG_RAX(%rsp)
Jan Beulichb556b352006-01-11 22:43:00 +0100699 .if \ist
Andi Kleen5f8efbb2006-01-16 01:56:39 +0100700 subq $EXCEPTION_STKSZ, per_cpu__init_tss + TSS_ist + (\ist - 1) * 8(%rbp)
Jan Beulichb556b352006-01-11 22:43:00 +0100701 .endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700702 call \sym
Jan Beulichb556b352006-01-11 22:43:00 +0100703 .if \ist
Andi Kleen5f8efbb2006-01-16 01:56:39 +0100704 addq $EXCEPTION_STKSZ, per_cpu__init_tss + TSS_ist + (\ist - 1) * 8(%rbp)
Jan Beulichb556b352006-01-11 22:43:00 +0100705 .endif
Andi Kleen6fefb0d2005-04-16 15:25:03 -0700706 cli
Linus Torvalds1da177e2005-04-16 15:20:36 -0700707 .endm
708
709/*
710 * Exception entry point. This expects an error code/orig_rax on the stack
711 * and the exception handler in %rax.
712 */
713ENTRY(error_entry)
Jan Beulich7effaa82005-09-12 18:49:24 +0200714 _frame RDI
Linus Torvalds1da177e2005-04-16 15:20:36 -0700715 /* rdi slot contains rax, oldrax contains error code */
716 cld
717 subq $14*8,%rsp
718 CFI_ADJUST_CFA_OFFSET (14*8)
719 movq %rsi,13*8(%rsp)
720 CFI_REL_OFFSET rsi,RSI
721 movq 14*8(%rsp),%rsi /* load rax from rdi slot */
722 movq %rdx,12*8(%rsp)
723 CFI_REL_OFFSET rdx,RDX
724 movq %rcx,11*8(%rsp)
725 CFI_REL_OFFSET rcx,RCX
726 movq %rsi,10*8(%rsp) /* store rax */
727 CFI_REL_OFFSET rax,RAX
728 movq %r8, 9*8(%rsp)
729 CFI_REL_OFFSET r8,R8
730 movq %r9, 8*8(%rsp)
731 CFI_REL_OFFSET r9,R9
732 movq %r10,7*8(%rsp)
733 CFI_REL_OFFSET r10,R10
734 movq %r11,6*8(%rsp)
735 CFI_REL_OFFSET r11,R11
736 movq %rbx,5*8(%rsp)
737 CFI_REL_OFFSET rbx,RBX
738 movq %rbp,4*8(%rsp)
739 CFI_REL_OFFSET rbp,RBP
740 movq %r12,3*8(%rsp)
741 CFI_REL_OFFSET r12,R12
742 movq %r13,2*8(%rsp)
743 CFI_REL_OFFSET r13,R13
744 movq %r14,1*8(%rsp)
745 CFI_REL_OFFSET r14,R14
746 movq %r15,(%rsp)
747 CFI_REL_OFFSET r15,R15
748 xorl %ebx,%ebx
749 testl $3,CS(%rsp)
750 je error_kernelspace
751error_swapgs:
752 swapgs
753error_sti:
754 movq %rdi,RDI(%rsp)
755 movq %rsp,%rdi
756 movq ORIG_RAX(%rsp),%rsi /* get error code */
757 movq $-1,ORIG_RAX(%rsp)
758 call *%rax
759 /* ebx: no swapgs flag (1: don't need swapgs, 0: need it) */
760error_exit:
761 movl %ebx,%eax
762 RESTORE_REST
763 cli
764 GET_THREAD_INFO(%rcx)
765 testl %eax,%eax
766 jne retint_kernel
767 movl threadinfo_flags(%rcx),%edx
768 movl $_TIF_WORK_MASK,%edi
769 andl %edi,%edx
770 jnz retint_careful
771 swapgs
772 RESTORE_ARGS 0,8,0
Jan Beulich505cc4e2006-01-11 22:42:20 +0100773 jmp iret_label
Linus Torvalds1da177e2005-04-16 15:20:36 -0700774 CFI_ENDPROC
775
776error_kernelspace:
777 incl %ebx
778 /* There are two places in the kernel that can potentially fault with
779 usergs. Handle them here. The exception handlers after
780 iret run with kernel gs again, so don't set the user space flag.
781 B stepping K8s sometimes report an truncated RIP for IRET
782 exceptions returning to compat mode. Check for these here too. */
783 leaq iret_label(%rip),%rbp
784 cmpq %rbp,RIP(%rsp)
785 je error_swapgs
786 movl %ebp,%ebp /* zero extend */
787 cmpq %rbp,RIP(%rsp)
788 je error_swapgs
789 cmpq $gs_change,RIP(%rsp)
790 je error_swapgs
791 jmp error_sti
792
793 /* Reload gs selector with exception handling */
794 /* edi: new selector */
795ENTRY(load_gs_index)
Jan Beulich7effaa82005-09-12 18:49:24 +0200796 CFI_STARTPROC
Linus Torvalds1da177e2005-04-16 15:20:36 -0700797 pushf
Jan Beulich7effaa82005-09-12 18:49:24 +0200798 CFI_ADJUST_CFA_OFFSET 8
Linus Torvalds1da177e2005-04-16 15:20:36 -0700799 cli
800 swapgs
801gs_change:
802 movl %edi,%gs
8032: mfence /* workaround */
804 swapgs
805 popf
Jan Beulich7effaa82005-09-12 18:49:24 +0200806 CFI_ADJUST_CFA_OFFSET -8
Linus Torvalds1da177e2005-04-16 15:20:36 -0700807 ret
Jan Beulich7effaa82005-09-12 18:49:24 +0200808 CFI_ENDPROC
Linus Torvalds1da177e2005-04-16 15:20:36 -0700809
810 .section __ex_table,"a"
811 .align 8
812 .quad gs_change,bad_gs
813 .previous
814 .section .fixup,"ax"
815 /* running with kernelgs */
816bad_gs:
817 swapgs /* switch back to user gs */
818 xorl %eax,%eax
819 movl %eax,%gs
820 jmp 2b
821 .previous
822
823/*
824 * Create a kernel thread.
825 *
826 * C extern interface:
827 * extern long kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
828 *
829 * asm input arguments:
830 * rdi: fn, rsi: arg, rdx: flags
831 */
832ENTRY(kernel_thread)
833 CFI_STARTPROC
834 FAKE_STACK_FRAME $child_rip
835 SAVE_ALL
836
837 # rdi: flags, rsi: usp, rdx: will be &pt_regs
838 movq %rdx,%rdi
839 orq kernel_thread_flags(%rip),%rdi
840 movq $-1, %rsi
841 movq %rsp, %rdx
842
843 xorl %r8d,%r8d
844 xorl %r9d,%r9d
845
846 # clone now
847 call do_fork
848 movq %rax,RAX(%rsp)
849 xorl %edi,%edi
850
851 /*
852 * It isn't worth to check for reschedule here,
853 * so internally to the x86_64 port you can rely on kernel_thread()
854 * not to reschedule the child before returning, this avoids the need
855 * of hacks for example to fork off the per-CPU idle tasks.
856 * [Hopefully no generic code relies on the reschedule -AK]
857 */
858 RESTORE_ALL
859 UNFAKE_STACK_FRAME
860 ret
861 CFI_ENDPROC
862
863
864child_rip:
865 /*
866 * Here we are in the child and the registers are set as they were
867 * at kernel_thread() invocation in the parent.
868 */
869 movq %rdi, %rax
870 movq %rsi, %rdi
871 call *%rax
872 # exit
Andi Kleen3829ee62005-07-28 21:15:48 -0700873 xorl %edi, %edi
Linus Torvalds1da177e2005-04-16 15:20:36 -0700874 call do_exit
875
876/*
877 * execve(). This function needs to use IRET, not SYSRET, to set up all state properly.
878 *
879 * C extern interface:
880 * extern long execve(char *name, char **argv, char **envp)
881 *
882 * asm input arguments:
883 * rdi: name, rsi: argv, rdx: envp
884 *
885 * We want to fallback into:
886 * extern long sys_execve(char *name, char **argv,char **envp, struct pt_regs regs)
887 *
888 * do_sys_execve asm fallback arguments:
889 * rdi: name, rsi: argv, rdx: envp, fake frame on the stack
890 */
891ENTRY(execve)
892 CFI_STARTPROC
893 FAKE_STACK_FRAME $0
894 SAVE_ALL
895 call sys_execve
896 movq %rax, RAX(%rsp)
897 RESTORE_REST
898 testq %rax,%rax
899 je int_ret_from_sys_call
900 RESTORE_ARGS
901 UNFAKE_STACK_FRAME
902 ret
903 CFI_ENDPROC
904
Prasanna S Panchamukhi0f2fbdc2005-09-06 15:19:28 -0700905KPROBE_ENTRY(page_fault)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700906 errorentry do_page_fault
Prasanna S Panchamukhi0f2fbdc2005-09-06 15:19:28 -0700907 .previous .text
Linus Torvalds1da177e2005-04-16 15:20:36 -0700908
909ENTRY(coprocessor_error)
910 zeroentry do_coprocessor_error
911
912ENTRY(simd_coprocessor_error)
913 zeroentry do_simd_coprocessor_error
914
915ENTRY(device_not_available)
916 zeroentry math_state_restore
917
918 /* runs on exception stack */
Prasanna S Panchamukhi0f2fbdc2005-09-06 15:19:28 -0700919KPROBE_ENTRY(debug)
Jan Beulich7effaa82005-09-12 18:49:24 +0200920 INTR_FRAME
Linus Torvalds1da177e2005-04-16 15:20:36 -0700921 pushq $0
922 CFI_ADJUST_CFA_OFFSET 8
Andi Kleen5f8efbb2006-01-16 01:56:39 +0100923 paranoidentry do_debug, DEBUG_STACK
Linus Torvalds1da177e2005-04-16 15:20:36 -0700924 jmp paranoid_exit
925 CFI_ENDPROC
Prasanna S Panchamukhi0f2fbdc2005-09-06 15:19:28 -0700926 .previous .text
Linus Torvalds1da177e2005-04-16 15:20:36 -0700927
928 /* runs on exception stack */
Andi Kleeneddb6fb2006-02-03 21:50:41 +0100929KPROBE_ENTRY(nmi)
Jan Beulich7effaa82005-09-12 18:49:24 +0200930 INTR_FRAME
Linus Torvalds1da177e2005-04-16 15:20:36 -0700931 pushq $-1
Jan Beulich7effaa82005-09-12 18:49:24 +0200932 CFI_ADJUST_CFA_OFFSET 8
Linus Torvalds1da177e2005-04-16 15:20:36 -0700933 paranoidentry do_nmi
Andi Kleen6fefb0d2005-04-16 15:25:03 -0700934 /*
935 * "Paranoid" exit path from exception stack.
936 * Paranoid because this is used by NMIs and cannot take
937 * any kernel state for granted.
938 * We don't do kernel preemption checks here, because only
939 * NMI should be common and it does not enable IRQs and
940 * cannot get reschedule ticks.
941 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700942 /* ebx: no swapgs flag */
943paranoid_exit:
944 testl %ebx,%ebx /* swapgs needed? */
945 jnz paranoid_restore
Andi Kleen6fefb0d2005-04-16 15:25:03 -0700946 testl $3,CS(%rsp)
947 jnz paranoid_userspace
Linus Torvalds1da177e2005-04-16 15:20:36 -0700948paranoid_swapgs:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700949 swapgs
950paranoid_restore:
951 RESTORE_ALL 8
952 iretq
953paranoid_userspace:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700954 GET_THREAD_INFO(%rcx)
Andi Kleen6fefb0d2005-04-16 15:25:03 -0700955 movl threadinfo_flags(%rcx),%ebx
956 andl $_TIF_WORK_MASK,%ebx
Andi Kleen11b854b2005-04-16 15:25:02 -0700957 jz paranoid_swapgs
Andi Kleen6fefb0d2005-04-16 15:25:03 -0700958 movq %rsp,%rdi /* &pt_regs */
959 call sync_regs
960 movq %rax,%rsp /* switch stack for scheduling */
961 testl $_TIF_NEED_RESCHED,%ebx
962 jnz paranoid_schedule
963 movl %ebx,%edx /* arg3: thread flags */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700964 sti
Andi Kleen6fefb0d2005-04-16 15:25:03 -0700965 xorl %esi,%esi /* arg2: oldset */
966 movq %rsp,%rdi /* arg1: &pt_regs */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700967 call do_notify_resume
Andi Kleen6fefb0d2005-04-16 15:25:03 -0700968 cli
969 jmp paranoid_userspace
970paranoid_schedule:
Andi Kleen11b854b2005-04-16 15:25:02 -0700971 sti
972 call schedule
Andi Kleen6fefb0d2005-04-16 15:25:03 -0700973 cli
974 jmp paranoid_userspace
Linus Torvalds1da177e2005-04-16 15:20:36 -0700975 CFI_ENDPROC
Andi Kleeneddb6fb2006-02-03 21:50:41 +0100976 .previous .text
Andi Kleen6fefb0d2005-04-16 15:25:03 -0700977
Prasanna S Panchamukhi0f2fbdc2005-09-06 15:19:28 -0700978KPROBE_ENTRY(int3)
Jan Beulichb556b352006-01-11 22:43:00 +0100979 INTR_FRAME
980 pushq $0
981 CFI_ADJUST_CFA_OFFSET 8
Andi Kleen5f8efbb2006-01-16 01:56:39 +0100982 paranoidentry do_int3, DEBUG_STACK
Jan Beulichb556b352006-01-11 22:43:00 +0100983 jmp paranoid_exit
984 CFI_ENDPROC
Prasanna S Panchamukhi0f2fbdc2005-09-06 15:19:28 -0700985 .previous .text
Linus Torvalds1da177e2005-04-16 15:20:36 -0700986
987ENTRY(overflow)
988 zeroentry do_overflow
989
990ENTRY(bounds)
991 zeroentry do_bounds
992
993ENTRY(invalid_op)
994 zeroentry do_invalid_op
995
996ENTRY(coprocessor_segment_overrun)
997 zeroentry do_coprocessor_segment_overrun
998
999ENTRY(reserved)
1000 zeroentry do_reserved
1001
1002 /* runs on exception stack */
1003ENTRY(double_fault)
Jan Beulich7effaa82005-09-12 18:49:24 +02001004 XCPT_FRAME
Linus Torvalds1da177e2005-04-16 15:20:36 -07001005 paranoidentry do_double_fault
Linus Torvalds1da177e2005-04-16 15:20:36 -07001006 jmp paranoid_exit
1007 CFI_ENDPROC
1008
1009ENTRY(invalid_TSS)
1010 errorentry do_invalid_TSS
1011
1012ENTRY(segment_not_present)
1013 errorentry do_segment_not_present
1014
1015 /* runs on exception stack */
1016ENTRY(stack_segment)
Jan Beulich7effaa82005-09-12 18:49:24 +02001017 XCPT_FRAME
Linus Torvalds1da177e2005-04-16 15:20:36 -07001018 paranoidentry do_stack_segment
Linus Torvalds1da177e2005-04-16 15:20:36 -07001019 jmp paranoid_exit
1020 CFI_ENDPROC
1021
Prasanna S Panchamukhi0f2fbdc2005-09-06 15:19:28 -07001022KPROBE_ENTRY(general_protection)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001023 errorentry do_general_protection
Prasanna S Panchamukhi0f2fbdc2005-09-06 15:19:28 -07001024 .previous .text
Linus Torvalds1da177e2005-04-16 15:20:36 -07001025
1026ENTRY(alignment_check)
1027 errorentry do_alignment_check
1028
1029ENTRY(divide_error)
1030 zeroentry do_divide_error
1031
1032ENTRY(spurious_interrupt_bug)
1033 zeroentry do_spurious_interrupt_bug
1034
1035#ifdef CONFIG_X86_MCE
1036 /* runs on exception stack */
1037ENTRY(machine_check)
Jan Beulich7effaa82005-09-12 18:49:24 +02001038 INTR_FRAME
Linus Torvalds1da177e2005-04-16 15:20:36 -07001039 pushq $0
1040 CFI_ADJUST_CFA_OFFSET 8
1041 paranoidentry do_machine_check
1042 jmp paranoid_exit
1043 CFI_ENDPROC
1044#endif
1045
Andi Kleened6b6762005-07-28 21:15:49 -07001046ENTRY(call_softirq)
Jan Beulich7effaa82005-09-12 18:49:24 +02001047 CFI_STARTPROC
Andi Kleened6b6762005-07-28 21:15:49 -07001048 movq %gs:pda_irqstackptr,%rax
Jan Beulichbd9cb642006-01-11 22:43:21 +01001049 movq %rsp,%rdx
1050 CFI_DEF_CFA_REGISTER rdx
Andi Kleened6b6762005-07-28 21:15:49 -07001051 incl %gs:pda_irqcount
1052 cmove %rax,%rsp
Jan Beulichbd9cb642006-01-11 22:43:21 +01001053 pushq %rdx
1054 /*todo CFI_DEF_CFA_EXPRESSION ...*/
Andi Kleened6b6762005-07-28 21:15:49 -07001055 call __do_softirq
Jan Beulichbd9cb642006-01-11 22:43:21 +01001056 popq %rsp
Jan Beulich7effaa82005-09-12 18:49:24 +02001057 CFI_DEF_CFA_REGISTER rsp
Andi Kleened6b6762005-07-28 21:15:49 -07001058 decl %gs:pda_irqcount
Andi Kleened6b6762005-07-28 21:15:49 -07001059 ret
Jan Beulich7effaa82005-09-12 18:49:24 +02001060 CFI_ENDPROC