blob: 586b34c00c489a2d3d495a904c00b158a1abfba4 [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.
Andi Kleen7bf36bb2006-04-07 19:50:00 +0200183 *
184 * When user can change the frames always force IRET. That is because
185 * it deals with uncanonical addresses better. SYSRET has trouble
186 * with them due to bugs in both AMD and Intel CPUs.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700187 */
188
189ENTRY(system_call)
Jan Beulich7effaa82005-09-12 18:49:24 +0200190 CFI_STARTPROC simple
191 CFI_DEF_CFA rsp,0
192 CFI_REGISTER rip,rcx
193 /*CFI_REGISTER rflags,r11*/
Linus Torvalds1da177e2005-04-16 15:20:36 -0700194 swapgs
195 movq %rsp,%gs:pda_oldrsp
196 movq %gs:pda_kernelstack,%rsp
197 sti
198 SAVE_ARGS 8,1
199 movq %rax,ORIG_RAX-ARGOFFSET(%rsp)
Jan Beulich7effaa82005-09-12 18:49:24 +0200200 movq %rcx,RIP-ARGOFFSET(%rsp)
201 CFI_REL_OFFSET rip,RIP-ARGOFFSET
Linus Torvalds1da177e2005-04-16 15:20:36 -0700202 GET_THREAD_INFO(%rcx)
203 testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP),threadinfo_flags(%rcx)
Jan Beulich7effaa82005-09-12 18:49:24 +0200204 CFI_REMEMBER_STATE
Linus Torvalds1da177e2005-04-16 15:20:36 -0700205 jnz tracesys
206 cmpq $__NR_syscall_max,%rax
207 ja badsys
208 movq %r10,%rcx
209 call *sys_call_table(,%rax,8) # XXX: rip relative
210 movq %rax,RAX-ARGOFFSET(%rsp)
211/*
212 * Syscall return path ending with SYSRET (fast path)
213 * Has incomplete stack frame and undefined top of stack.
214 */
215 .globl ret_from_sys_call
216ret_from_sys_call:
Andi Kleen11b854b2005-04-16 15:25:02 -0700217 movl $_TIF_ALLWORK_MASK,%edi
Linus Torvalds1da177e2005-04-16 15:20:36 -0700218 /* edi: flagmask */
219sysret_check:
220 GET_THREAD_INFO(%rcx)
221 cli
222 movl threadinfo_flags(%rcx),%edx
223 andl %edi,%edx
Jan Beulich7effaa82005-09-12 18:49:24 +0200224 CFI_REMEMBER_STATE
Linus Torvalds1da177e2005-04-16 15:20:36 -0700225 jnz sysret_careful
226 movq RIP-ARGOFFSET(%rsp),%rcx
Jan Beulich7effaa82005-09-12 18:49:24 +0200227 CFI_REGISTER rip,rcx
Linus Torvalds1da177e2005-04-16 15:20:36 -0700228 RESTORE_ARGS 0,-ARG_SKIP,1
Jan Beulich7effaa82005-09-12 18:49:24 +0200229 /*CFI_REGISTER rflags,r11*/
Linus Torvalds1da177e2005-04-16 15:20:36 -0700230 movq %gs:pda_oldrsp,%rsp
231 swapgs
232 sysretq
233
234 /* Handle reschedules */
235 /* edx: work, edi: workmask */
236sysret_careful:
Jan Beulich7effaa82005-09-12 18:49:24 +0200237 CFI_RESTORE_STATE
Linus Torvalds1da177e2005-04-16 15:20:36 -0700238 bt $TIF_NEED_RESCHED,%edx
239 jnc sysret_signal
240 sti
241 pushq %rdi
Jan Beulich7effaa82005-09-12 18:49:24 +0200242 CFI_ADJUST_CFA_OFFSET 8
Linus Torvalds1da177e2005-04-16 15:20:36 -0700243 call schedule
244 popq %rdi
Jan Beulich7effaa82005-09-12 18:49:24 +0200245 CFI_ADJUST_CFA_OFFSET -8
Linus Torvalds1da177e2005-04-16 15:20:36 -0700246 jmp sysret_check
247
248 /* Handle a signal */
249sysret_signal:
250 sti
Andi Kleen10ffdbb2005-05-16 21:53:19 -0700251 testl $(_TIF_SIGPENDING|_TIF_NOTIFY_RESUME|_TIF_SINGLESTEP),%edx
252 jz 1f
253
254 /* Really a signal */
255 /* edx: work flags (arg3) */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700256 leaq do_notify_resume(%rip),%rax
257 leaq -ARGOFFSET(%rsp),%rdi # &pt_regs -> arg1
258 xorl %esi,%esi # oldset -> arg2
259 call ptregscall_common
Andi Kleen10ffdbb2005-05-16 21:53:19 -07002601: movl $_TIF_NEED_RESCHED,%edi
Andi Kleen7bf36bb2006-04-07 19:50:00 +0200261 /* Use IRET because user could have changed frame. This
262 works because ptregscall_common has called FIXUP_TOP_OF_STACK. */
263 cli
264 jmp int_with_check
Linus Torvalds1da177e2005-04-16 15:20:36 -0700265
Jan Beulich7effaa82005-09-12 18:49:24 +0200266badsys:
267 movq $-ENOSYS,RAX-ARGOFFSET(%rsp)
268 jmp ret_from_sys_call
269
Linus Torvalds1da177e2005-04-16 15:20:36 -0700270 /* Do syscall tracing */
271tracesys:
Jan Beulich7effaa82005-09-12 18:49:24 +0200272 CFI_RESTORE_STATE
Linus Torvalds1da177e2005-04-16 15:20:36 -0700273 SAVE_REST
274 movq $-ENOSYS,RAX(%rsp)
275 FIXUP_TOP_OF_STACK %rdi
276 movq %rsp,%rdi
277 call syscall_trace_enter
278 LOAD_ARGS ARGOFFSET /* reload args from stack in case ptrace changed it */
279 RESTORE_REST
280 cmpq $__NR_syscall_max,%rax
281 ja 1f
282 movq %r10,%rcx /* fixup for C */
283 call *sys_call_table(,%rax,8)
Andi Kleen822ff012006-05-30 22:48:03 +02002841: movq %rax,RAX-ARGOFFSET(%rsp)
Andi Kleen7bf36bb2006-04-07 19:50:00 +0200285 /* Use IRET because user could have changed frame */
286 jmp int_ret_from_sys_call
Jan Beulich7effaa82005-09-12 18:49:24 +0200287 CFI_ENDPROC
Linus Torvalds1da177e2005-04-16 15:20:36 -0700288
Linus Torvalds1da177e2005-04-16 15:20:36 -0700289/*
290 * Syscall return path ending with IRET.
291 * Has correct top of stack, but partial stack frame.
292 */
Jan Beulich7effaa82005-09-12 18:49:24 +0200293ENTRY(int_ret_from_sys_call)
294 CFI_STARTPROC simple
295 CFI_DEF_CFA rsp,SS+8-ARGOFFSET
296 /*CFI_REL_OFFSET ss,SS-ARGOFFSET*/
297 CFI_REL_OFFSET rsp,RSP-ARGOFFSET
298 /*CFI_REL_OFFSET rflags,EFLAGS-ARGOFFSET*/
299 /*CFI_REL_OFFSET cs,CS-ARGOFFSET*/
300 CFI_REL_OFFSET rip,RIP-ARGOFFSET
301 CFI_REL_OFFSET rdx,RDX-ARGOFFSET
302 CFI_REL_OFFSET rcx,RCX-ARGOFFSET
303 CFI_REL_OFFSET rax,RAX-ARGOFFSET
304 CFI_REL_OFFSET rdi,RDI-ARGOFFSET
305 CFI_REL_OFFSET rsi,RSI-ARGOFFSET
306 CFI_REL_OFFSET r8,R8-ARGOFFSET
307 CFI_REL_OFFSET r9,R9-ARGOFFSET
308 CFI_REL_OFFSET r10,R10-ARGOFFSET
309 CFI_REL_OFFSET r11,R11-ARGOFFSET
Linus Torvalds1da177e2005-04-16 15:20:36 -0700310 cli
311 testl $3,CS-ARGOFFSET(%rsp)
312 je retint_restore_args
313 movl $_TIF_ALLWORK_MASK,%edi
314 /* edi: mask to check */
315int_with_check:
316 GET_THREAD_INFO(%rcx)
317 movl threadinfo_flags(%rcx),%edx
318 andl %edi,%edx
319 jnz int_careful
Andi Kleenbf2fcc62006-01-11 22:44:06 +0100320 andl $~TS_COMPAT,threadinfo_status(%rcx)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700321 jmp retint_swapgs
322
323 /* Either reschedule or signal or syscall exit tracking needed. */
324 /* First do a reschedule test. */
325 /* edx: work, edi: workmask */
326int_careful:
327 bt $TIF_NEED_RESCHED,%edx
328 jnc int_very_careful
329 sti
330 pushq %rdi
Jan Beulich7effaa82005-09-12 18:49:24 +0200331 CFI_ADJUST_CFA_OFFSET 8
Linus Torvalds1da177e2005-04-16 15:20:36 -0700332 call schedule
333 popq %rdi
Jan Beulich7effaa82005-09-12 18:49:24 +0200334 CFI_ADJUST_CFA_OFFSET -8
Andi Kleencdd219c2005-04-16 15:25:04 -0700335 cli
Linus Torvalds1da177e2005-04-16 15:20:36 -0700336 jmp int_with_check
337
338 /* handle signals and tracing -- both require a full stack frame */
339int_very_careful:
340 sti
341 SAVE_REST
342 /* Check for syscall exit trace */
343 testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP),%edx
344 jz int_signal
345 pushq %rdi
Jan Beulich7effaa82005-09-12 18:49:24 +0200346 CFI_ADJUST_CFA_OFFSET 8
Linus Torvalds1da177e2005-04-16 15:20:36 -0700347 leaq 8(%rsp),%rdi # &ptregs -> arg1
348 call syscall_trace_leave
349 popq %rdi
Jan Beulich7effaa82005-09-12 18:49:24 +0200350 CFI_ADJUST_CFA_OFFSET -8
Andi Kleen36c11042005-04-16 15:25:01 -0700351 andl $~(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP),%edi
Andi Kleenbe9e6872005-05-01 08:58:51 -0700352 cli
Linus Torvalds1da177e2005-04-16 15:20:36 -0700353 jmp int_restore_rest
354
355int_signal:
356 testl $(_TIF_NOTIFY_RESUME|_TIF_SIGPENDING|_TIF_SINGLESTEP),%edx
357 jz 1f
358 movq %rsp,%rdi # &ptregs -> arg1
359 xorl %esi,%esi # oldset -> arg2
360 call do_notify_resume
3611: movl $_TIF_NEED_RESCHED,%edi
362int_restore_rest:
363 RESTORE_REST
Andi Kleenbe9e6872005-05-01 08:58:51 -0700364 cli
Linus Torvalds1da177e2005-04-16 15:20:36 -0700365 jmp int_with_check
366 CFI_ENDPROC
367
368/*
369 * Certain special system calls that need to save a complete full stack frame.
370 */
371
372 .macro PTREGSCALL label,func,arg
373 .globl \label
374\label:
375 leaq \func(%rip),%rax
376 leaq -ARGOFFSET+8(%rsp),\arg /* 8 for return address */
377 jmp ptregscall_common
378 .endm
379
Jan Beulich7effaa82005-09-12 18:49:24 +0200380 CFI_STARTPROC
381
Linus Torvalds1da177e2005-04-16 15:20:36 -0700382 PTREGSCALL stub_clone, sys_clone, %r8
383 PTREGSCALL stub_fork, sys_fork, %rdi
384 PTREGSCALL stub_vfork, sys_vfork, %rdi
385 PTREGSCALL stub_rt_sigsuspend, sys_rt_sigsuspend, %rdx
386 PTREGSCALL stub_sigaltstack, sys_sigaltstack, %rdx
387 PTREGSCALL stub_iopl, sys_iopl, %rsi
388
389ENTRY(ptregscall_common)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700390 popq %r11
Jan Beulich7effaa82005-09-12 18:49:24 +0200391 CFI_ADJUST_CFA_OFFSET -8
392 CFI_REGISTER rip, r11
Linus Torvalds1da177e2005-04-16 15:20:36 -0700393 SAVE_REST
394 movq %r11, %r15
Jan Beulich7effaa82005-09-12 18:49:24 +0200395 CFI_REGISTER rip, r15
Linus Torvalds1da177e2005-04-16 15:20:36 -0700396 FIXUP_TOP_OF_STACK %r11
397 call *%rax
398 RESTORE_TOP_OF_STACK %r11
399 movq %r15, %r11
Jan Beulich7effaa82005-09-12 18:49:24 +0200400 CFI_REGISTER rip, r11
Linus Torvalds1da177e2005-04-16 15:20:36 -0700401 RESTORE_REST
402 pushq %r11
Jan Beulich7effaa82005-09-12 18:49:24 +0200403 CFI_ADJUST_CFA_OFFSET 8
404 CFI_REL_OFFSET rip, 0
Linus Torvalds1da177e2005-04-16 15:20:36 -0700405 ret
406 CFI_ENDPROC
407
408ENTRY(stub_execve)
409 CFI_STARTPROC
410 popq %r11
Jan Beulich7effaa82005-09-12 18:49:24 +0200411 CFI_ADJUST_CFA_OFFSET -8
412 CFI_REGISTER rip, r11
Linus Torvalds1da177e2005-04-16 15:20:36 -0700413 SAVE_REST
Linus Torvalds1da177e2005-04-16 15:20:36 -0700414 FIXUP_TOP_OF_STACK %r11
415 call sys_execve
Linus Torvalds1da177e2005-04-16 15:20:36 -0700416 RESTORE_TOP_OF_STACK %r11
Linus Torvalds1da177e2005-04-16 15:20:36 -0700417 movq %rax,RAX(%rsp)
418 RESTORE_REST
419 jmp int_ret_from_sys_call
420 CFI_ENDPROC
421
422/*
423 * sigreturn is special because it needs to restore all registers on return.
424 * This cannot be done with SYSRET, so use the IRET return path instead.
425 */
426ENTRY(stub_rt_sigreturn)
427 CFI_STARTPROC
Jan Beulich7effaa82005-09-12 18:49:24 +0200428 addq $8, %rsp
429 CFI_ADJUST_CFA_OFFSET -8
Linus Torvalds1da177e2005-04-16 15:20:36 -0700430 SAVE_REST
431 movq %rsp,%rdi
432 FIXUP_TOP_OF_STACK %r11
433 call sys_rt_sigreturn
434 movq %rax,RAX(%rsp) # fixme, this could be done at the higher layer
435 RESTORE_REST
436 jmp int_ret_from_sys_call
437 CFI_ENDPROC
438
Jan Beulich7effaa82005-09-12 18:49:24 +0200439/*
440 * initial frame state for interrupts and exceptions
441 */
442 .macro _frame ref
443 CFI_STARTPROC simple
444 CFI_DEF_CFA rsp,SS+8-\ref
445 /*CFI_REL_OFFSET ss,SS-\ref*/
446 CFI_REL_OFFSET rsp,RSP-\ref
447 /*CFI_REL_OFFSET rflags,EFLAGS-\ref*/
448 /*CFI_REL_OFFSET cs,CS-\ref*/
449 CFI_REL_OFFSET rip,RIP-\ref
450 .endm
451
452/* initial frame state for interrupts (and exceptions without error code) */
453#define INTR_FRAME _frame RIP
454/* initial frame state for exceptions with error code (and interrupts with
455 vector already pushed) */
456#define XCPT_FRAME _frame ORIG_RAX
457
Linus Torvalds1da177e2005-04-16 15:20:36 -0700458/*
459 * Interrupt entry/exit.
460 *
461 * Interrupt entry points save only callee clobbered registers in fast path.
462 *
463 * Entry runs with interrupts off.
464 */
465
466/* 0(%rsp): interrupt number */
467 .macro interrupt func
Linus Torvalds1da177e2005-04-16 15:20:36 -0700468 cld
469#ifdef CONFIG_DEBUG_INFO
470 SAVE_ALL
471 movq %rsp,%rdi
472 /*
473 * Setup a stack frame pointer. This allows gdb to trace
474 * back to the original stack.
475 */
476 movq %rsp,%rbp
477 CFI_DEF_CFA_REGISTER rbp
478#else
479 SAVE_ARGS
480 leaq -ARGOFFSET(%rsp),%rdi # arg1 for handler
481#endif
482 testl $3,CS(%rdi)
483 je 1f
484 swapgs
Andi Kleen3829ee62005-07-28 21:15:48 -07004851: incl %gs:pda_irqcount # RED-PEN should check preempt count
Linus Torvalds1da177e2005-04-16 15:20:36 -0700486 movq %gs:pda_irqstackptr,%rax
Jan Beulich7effaa82005-09-12 18:49:24 +0200487 cmoveq %rax,%rsp /*todo This needs CFI annotation! */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700488 pushq %rdi # save old stack
Jan Beulich91522a92006-02-03 21:51:44 +0100489#ifndef CONFIG_DEBUG_INFO
Jan Beulich7effaa82005-09-12 18:49:24 +0200490 CFI_ADJUST_CFA_OFFSET 8
Jan Beulich91522a92006-02-03 21:51:44 +0100491#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700492 call \func
493 .endm
494
495ENTRY(common_interrupt)
Jan Beulich7effaa82005-09-12 18:49:24 +0200496 XCPT_FRAME
Linus Torvalds1da177e2005-04-16 15:20:36 -0700497 interrupt do_IRQ
498 /* 0(%rsp): oldrsp-ARGOFFSET */
Jan Beulich7effaa82005-09-12 18:49:24 +0200499ret_from_intr:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700500 popq %rdi
Jan Beulich91522a92006-02-03 21:51:44 +0100501#ifndef CONFIG_DEBUG_INFO
Jan Beulich7effaa82005-09-12 18:49:24 +0200502 CFI_ADJUST_CFA_OFFSET -8
Jan Beulich91522a92006-02-03 21:51:44 +0100503#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700504 cli
Andi Kleen3829ee62005-07-28 21:15:48 -0700505 decl %gs:pda_irqcount
Linus Torvalds1da177e2005-04-16 15:20:36 -0700506#ifdef CONFIG_DEBUG_INFO
507 movq RBP(%rdi),%rbp
Jan Beulich7effaa82005-09-12 18:49:24 +0200508 CFI_DEF_CFA_REGISTER rsp
Linus Torvalds1da177e2005-04-16 15:20:36 -0700509#endif
Jan Beulich7effaa82005-09-12 18:49:24 +0200510 leaq ARGOFFSET(%rdi),%rsp /*todo This needs CFI annotation! */
511exit_intr:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700512 GET_THREAD_INFO(%rcx)
513 testl $3,CS-ARGOFFSET(%rsp)
514 je retint_kernel
515
516 /* Interrupt came from user space */
517 /*
518 * Has a correct top of stack, but a partial stack frame
519 * %rcx: thread info. Interrupts off.
520 */
521retint_with_reschedule:
522 movl $_TIF_WORK_MASK,%edi
Jan Beulich7effaa82005-09-12 18:49:24 +0200523retint_check:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700524 movl threadinfo_flags(%rcx),%edx
525 andl %edi,%edx
Jan Beulich7effaa82005-09-12 18:49:24 +0200526 CFI_REMEMBER_STATE
Linus Torvalds1da177e2005-04-16 15:20:36 -0700527 jnz retint_careful
528retint_swapgs:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700529 swapgs
530retint_restore_args:
531 cli
532 RESTORE_ARGS 0,8,0
533iret_label:
534 iretq
535
536 .section __ex_table,"a"
537 .quad iret_label,bad_iret
538 .previous
539 .section .fixup,"ax"
540 /* force a signal here? this matches i386 behaviour */
541 /* running with kernel gs */
542bad_iret:
Andi Kleen3076a492006-03-25 16:31:55 +0100543 movq $11,%rdi /* SIGSEGV */
Andi Kleen2391c4b2006-02-16 23:42:01 +0100544 sti
Linus Torvalds1da177e2005-04-16 15:20:36 -0700545 jmp do_exit
546 .previous
547
Jan Beulich7effaa82005-09-12 18:49:24 +0200548 /* edi: workmask, edx: work */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700549retint_careful:
Jan Beulich7effaa82005-09-12 18:49:24 +0200550 CFI_RESTORE_STATE
Linus Torvalds1da177e2005-04-16 15:20:36 -0700551 bt $TIF_NEED_RESCHED,%edx
552 jnc retint_signal
553 sti
554 pushq %rdi
Jan Beulich7effaa82005-09-12 18:49:24 +0200555 CFI_ADJUST_CFA_OFFSET 8
Linus Torvalds1da177e2005-04-16 15:20:36 -0700556 call schedule
557 popq %rdi
Jan Beulich7effaa82005-09-12 18:49:24 +0200558 CFI_ADJUST_CFA_OFFSET -8
Linus Torvalds1da177e2005-04-16 15:20:36 -0700559 GET_THREAD_INFO(%rcx)
560 cli
561 jmp retint_check
562
563retint_signal:
Andi Kleen10ffdbb2005-05-16 21:53:19 -0700564 testl $(_TIF_SIGPENDING|_TIF_NOTIFY_RESUME|_TIF_SINGLESTEP),%edx
565 jz retint_swapgs
Linus Torvalds1da177e2005-04-16 15:20:36 -0700566 sti
567 SAVE_REST
568 movq $-1,ORIG_RAX(%rsp)
Andi Kleen3829ee62005-07-28 21:15:48 -0700569 xorl %esi,%esi # oldset
Linus Torvalds1da177e2005-04-16 15:20:36 -0700570 movq %rsp,%rdi # &pt_regs
571 call do_notify_resume
572 RESTORE_REST
573 cli
Andi Kleen10ffdbb2005-05-16 21:53:19 -0700574 movl $_TIF_NEED_RESCHED,%edi
Andi Kleenbe9e6872005-05-01 08:58:51 -0700575 GET_THREAD_INFO(%rcx)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700576 jmp retint_check
577
578#ifdef CONFIG_PREEMPT
579 /* Returning to kernel space. Check if we need preemption */
580 /* rcx: threadinfo. interrupts off. */
581 .p2align
582retint_kernel:
583 cmpl $0,threadinfo_preempt_count(%rcx)
584 jnz retint_restore_args
585 bt $TIF_NEED_RESCHED,threadinfo_flags(%rcx)
586 jnc retint_restore_args
587 bt $9,EFLAGS-ARGOFFSET(%rsp) /* interrupts off? */
588 jnc retint_restore_args
589 call preempt_schedule_irq
590 jmp exit_intr
591#endif
592 CFI_ENDPROC
593
594/*
595 * APIC interrupts.
596 */
597 .macro apicinterrupt num,func
Jan Beulich7effaa82005-09-12 18:49:24 +0200598 INTR_FRAME
Linus Torvalds1da177e2005-04-16 15:20:36 -0700599 pushq $\num-256
Jan Beulich7effaa82005-09-12 18:49:24 +0200600 CFI_ADJUST_CFA_OFFSET 8
Linus Torvalds1da177e2005-04-16 15:20:36 -0700601 interrupt \func
602 jmp ret_from_intr
603 CFI_ENDPROC
604 .endm
605
606ENTRY(thermal_interrupt)
607 apicinterrupt THERMAL_APIC_VECTOR,smp_thermal_interrupt
608
Jacob Shin89b831e2005-11-05 17:25:53 +0100609ENTRY(threshold_interrupt)
610 apicinterrupt THRESHOLD_APIC_VECTOR,mce_threshold_interrupt
611
Linus Torvalds1da177e2005-04-16 15:20:36 -0700612#ifdef CONFIG_SMP
613ENTRY(reschedule_interrupt)
614 apicinterrupt RESCHEDULE_VECTOR,smp_reschedule_interrupt
615
Andi Kleene5bc8b62005-09-12 18:49:24 +0200616 .macro INVALIDATE_ENTRY num
617ENTRY(invalidate_interrupt\num)
618 apicinterrupt INVALIDATE_TLB_VECTOR_START+\num,smp_invalidate_interrupt
619 .endm
620
621 INVALIDATE_ENTRY 0
622 INVALIDATE_ENTRY 1
623 INVALIDATE_ENTRY 2
624 INVALIDATE_ENTRY 3
625 INVALIDATE_ENTRY 4
626 INVALIDATE_ENTRY 5
627 INVALIDATE_ENTRY 6
628 INVALIDATE_ENTRY 7
Linus Torvalds1da177e2005-04-16 15:20:36 -0700629
630ENTRY(call_function_interrupt)
631 apicinterrupt CALL_FUNCTION_VECTOR,smp_call_function_interrupt
632#endif
633
634#ifdef CONFIG_X86_LOCAL_APIC
635ENTRY(apic_timer_interrupt)
636 apicinterrupt LOCAL_TIMER_VECTOR,smp_apic_timer_interrupt
637
638ENTRY(error_interrupt)
639 apicinterrupt ERROR_APIC_VECTOR,smp_error_interrupt
640
641ENTRY(spurious_interrupt)
642 apicinterrupt SPURIOUS_APIC_VECTOR,smp_spurious_interrupt
643#endif
644
645/*
646 * Exception entry points.
647 */
648 .macro zeroentry sym
Jan Beulich7effaa82005-09-12 18:49:24 +0200649 INTR_FRAME
Linus Torvalds1da177e2005-04-16 15:20:36 -0700650 pushq $0 /* push error code/oldrax */
Jan Beulich7effaa82005-09-12 18:49:24 +0200651 CFI_ADJUST_CFA_OFFSET 8
Linus Torvalds1da177e2005-04-16 15:20:36 -0700652 pushq %rax /* push real oldrax to the rdi slot */
Jan Beulich7effaa82005-09-12 18:49:24 +0200653 CFI_ADJUST_CFA_OFFSET 8
Linus Torvalds1da177e2005-04-16 15:20:36 -0700654 leaq \sym(%rip),%rax
655 jmp error_entry
Jan Beulich7effaa82005-09-12 18:49:24 +0200656 CFI_ENDPROC
Linus Torvalds1da177e2005-04-16 15:20:36 -0700657 .endm
658
659 .macro errorentry sym
Jan Beulich7effaa82005-09-12 18:49:24 +0200660 XCPT_FRAME
Linus Torvalds1da177e2005-04-16 15:20:36 -0700661 pushq %rax
Jan Beulich7effaa82005-09-12 18:49:24 +0200662 CFI_ADJUST_CFA_OFFSET 8
Linus Torvalds1da177e2005-04-16 15:20:36 -0700663 leaq \sym(%rip),%rax
664 jmp error_entry
Jan Beulich7effaa82005-09-12 18:49:24 +0200665 CFI_ENDPROC
Linus Torvalds1da177e2005-04-16 15:20:36 -0700666 .endm
667
668 /* error code is on the stack already */
669 /* handle NMI like exceptions that can happen everywhere */
Jan Beulichb556b352006-01-11 22:43:00 +0100670 .macro paranoidentry sym, ist=0
Linus Torvalds1da177e2005-04-16 15:20:36 -0700671 SAVE_ALL
672 cld
673 movl $1,%ebx
674 movl $MSR_GS_BASE,%ecx
675 rdmsr
676 testl %edx,%edx
677 js 1f
678 swapgs
679 xorl %ebx,%ebx
Jan Beulichb556b352006-01-11 22:43:00 +01006801:
681 .if \ist
682 movq %gs:pda_data_offset, %rbp
683 .endif
684 movq %rsp,%rdi
Linus Torvalds1da177e2005-04-16 15:20:36 -0700685 movq ORIG_RAX(%rsp),%rsi
686 movq $-1,ORIG_RAX(%rsp)
Jan Beulichb556b352006-01-11 22:43:00 +0100687 .if \ist
Andi Kleen5f8efbb2006-01-16 01:56:39 +0100688 subq $EXCEPTION_STKSZ, per_cpu__init_tss + TSS_ist + (\ist - 1) * 8(%rbp)
Jan Beulichb556b352006-01-11 22:43:00 +0100689 .endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700690 call \sym
Jan Beulichb556b352006-01-11 22:43:00 +0100691 .if \ist
Andi Kleen5f8efbb2006-01-16 01:56:39 +0100692 addq $EXCEPTION_STKSZ, per_cpu__init_tss + TSS_ist + (\ist - 1) * 8(%rbp)
Jan Beulichb556b352006-01-11 22:43:00 +0100693 .endif
Andi Kleen6fefb0d2005-04-16 15:25:03 -0700694 cli
Linus Torvalds1da177e2005-04-16 15:20:36 -0700695 .endm
696
697/*
698 * Exception entry point. This expects an error code/orig_rax on the stack
699 * and the exception handler in %rax.
700 */
701ENTRY(error_entry)
Jan Beulich7effaa82005-09-12 18:49:24 +0200702 _frame RDI
Linus Torvalds1da177e2005-04-16 15:20:36 -0700703 /* rdi slot contains rax, oldrax contains error code */
704 cld
705 subq $14*8,%rsp
706 CFI_ADJUST_CFA_OFFSET (14*8)
707 movq %rsi,13*8(%rsp)
708 CFI_REL_OFFSET rsi,RSI
709 movq 14*8(%rsp),%rsi /* load rax from rdi slot */
710 movq %rdx,12*8(%rsp)
711 CFI_REL_OFFSET rdx,RDX
712 movq %rcx,11*8(%rsp)
713 CFI_REL_OFFSET rcx,RCX
714 movq %rsi,10*8(%rsp) /* store rax */
715 CFI_REL_OFFSET rax,RAX
716 movq %r8, 9*8(%rsp)
717 CFI_REL_OFFSET r8,R8
718 movq %r9, 8*8(%rsp)
719 CFI_REL_OFFSET r9,R9
720 movq %r10,7*8(%rsp)
721 CFI_REL_OFFSET r10,R10
722 movq %r11,6*8(%rsp)
723 CFI_REL_OFFSET r11,R11
724 movq %rbx,5*8(%rsp)
725 CFI_REL_OFFSET rbx,RBX
726 movq %rbp,4*8(%rsp)
727 CFI_REL_OFFSET rbp,RBP
728 movq %r12,3*8(%rsp)
729 CFI_REL_OFFSET r12,R12
730 movq %r13,2*8(%rsp)
731 CFI_REL_OFFSET r13,R13
732 movq %r14,1*8(%rsp)
733 CFI_REL_OFFSET r14,R14
734 movq %r15,(%rsp)
735 CFI_REL_OFFSET r15,R15
736 xorl %ebx,%ebx
737 testl $3,CS(%rsp)
738 je error_kernelspace
739error_swapgs:
740 swapgs
741error_sti:
742 movq %rdi,RDI(%rsp)
743 movq %rsp,%rdi
744 movq ORIG_RAX(%rsp),%rsi /* get error code */
745 movq $-1,ORIG_RAX(%rsp)
746 call *%rax
747 /* ebx: no swapgs flag (1: don't need swapgs, 0: need it) */
748error_exit:
749 movl %ebx,%eax
750 RESTORE_REST
751 cli
752 GET_THREAD_INFO(%rcx)
753 testl %eax,%eax
754 jne retint_kernel
755 movl threadinfo_flags(%rcx),%edx
756 movl $_TIF_WORK_MASK,%edi
757 andl %edi,%edx
758 jnz retint_careful
759 swapgs
760 RESTORE_ARGS 0,8,0
Jan Beulich505cc4e2006-01-11 22:42:20 +0100761 jmp iret_label
Linus Torvalds1da177e2005-04-16 15:20:36 -0700762 CFI_ENDPROC
763
764error_kernelspace:
765 incl %ebx
766 /* There are two places in the kernel that can potentially fault with
767 usergs. Handle them here. The exception handlers after
768 iret run with kernel gs again, so don't set the user space flag.
769 B stepping K8s sometimes report an truncated RIP for IRET
770 exceptions returning to compat mode. Check for these here too. */
771 leaq iret_label(%rip),%rbp
772 cmpq %rbp,RIP(%rsp)
773 je error_swapgs
774 movl %ebp,%ebp /* zero extend */
775 cmpq %rbp,RIP(%rsp)
776 je error_swapgs
777 cmpq $gs_change,RIP(%rsp)
778 je error_swapgs
779 jmp error_sti
780
781 /* Reload gs selector with exception handling */
782 /* edi: new selector */
783ENTRY(load_gs_index)
Jan Beulich7effaa82005-09-12 18:49:24 +0200784 CFI_STARTPROC
Linus Torvalds1da177e2005-04-16 15:20:36 -0700785 pushf
Jan Beulich7effaa82005-09-12 18:49:24 +0200786 CFI_ADJUST_CFA_OFFSET 8
Linus Torvalds1da177e2005-04-16 15:20:36 -0700787 cli
788 swapgs
789gs_change:
790 movl %edi,%gs
7912: mfence /* workaround */
792 swapgs
793 popf
Jan Beulich7effaa82005-09-12 18:49:24 +0200794 CFI_ADJUST_CFA_OFFSET -8
Linus Torvalds1da177e2005-04-16 15:20:36 -0700795 ret
Jan Beulich7effaa82005-09-12 18:49:24 +0200796 CFI_ENDPROC
Linus Torvalds1da177e2005-04-16 15:20:36 -0700797
798 .section __ex_table,"a"
799 .align 8
800 .quad gs_change,bad_gs
801 .previous
802 .section .fixup,"ax"
803 /* running with kernelgs */
804bad_gs:
805 swapgs /* switch back to user gs */
806 xorl %eax,%eax
807 movl %eax,%gs
808 jmp 2b
809 .previous
810
811/*
812 * Create a kernel thread.
813 *
814 * C extern interface:
815 * extern long kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
816 *
817 * asm input arguments:
818 * rdi: fn, rsi: arg, rdx: flags
819 */
820ENTRY(kernel_thread)
821 CFI_STARTPROC
822 FAKE_STACK_FRAME $child_rip
823 SAVE_ALL
824
825 # rdi: flags, rsi: usp, rdx: will be &pt_regs
826 movq %rdx,%rdi
827 orq kernel_thread_flags(%rip),%rdi
828 movq $-1, %rsi
829 movq %rsp, %rdx
830
831 xorl %r8d,%r8d
832 xorl %r9d,%r9d
833
834 # clone now
835 call do_fork
836 movq %rax,RAX(%rsp)
837 xorl %edi,%edi
838
839 /*
840 * It isn't worth to check for reschedule here,
841 * so internally to the x86_64 port you can rely on kernel_thread()
842 * not to reschedule the child before returning, this avoids the need
843 * of hacks for example to fork off the per-CPU idle tasks.
844 * [Hopefully no generic code relies on the reschedule -AK]
845 */
846 RESTORE_ALL
847 UNFAKE_STACK_FRAME
848 ret
849 CFI_ENDPROC
850
851
852child_rip:
853 /*
854 * Here we are in the child and the registers are set as they were
855 * at kernel_thread() invocation in the parent.
856 */
857 movq %rdi, %rax
858 movq %rsi, %rdi
859 call *%rax
860 # exit
Andi Kleen3829ee62005-07-28 21:15:48 -0700861 xorl %edi, %edi
Linus Torvalds1da177e2005-04-16 15:20:36 -0700862 call do_exit
863
864/*
865 * execve(). This function needs to use IRET, not SYSRET, to set up all state properly.
866 *
867 * C extern interface:
868 * extern long execve(char *name, char **argv, char **envp)
869 *
870 * asm input arguments:
871 * rdi: name, rsi: argv, rdx: envp
872 *
873 * We want to fallback into:
874 * extern long sys_execve(char *name, char **argv,char **envp, struct pt_regs regs)
875 *
876 * do_sys_execve asm fallback arguments:
877 * rdi: name, rsi: argv, rdx: envp, fake frame on the stack
878 */
879ENTRY(execve)
880 CFI_STARTPROC
881 FAKE_STACK_FRAME $0
882 SAVE_ALL
883 call sys_execve
884 movq %rax, RAX(%rsp)
885 RESTORE_REST
886 testq %rax,%rax
887 je int_ret_from_sys_call
888 RESTORE_ARGS
889 UNFAKE_STACK_FRAME
890 ret
891 CFI_ENDPROC
892
Prasanna S Panchamukhi0f2fbdc2005-09-06 15:19:28 -0700893KPROBE_ENTRY(page_fault)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700894 errorentry do_page_fault
Prasanna S Panchamukhi0f2fbdc2005-09-06 15:19:28 -0700895 .previous .text
Linus Torvalds1da177e2005-04-16 15:20:36 -0700896
897ENTRY(coprocessor_error)
898 zeroentry do_coprocessor_error
899
900ENTRY(simd_coprocessor_error)
901 zeroentry do_simd_coprocessor_error
902
903ENTRY(device_not_available)
904 zeroentry math_state_restore
905
906 /* runs on exception stack */
Prasanna S Panchamukhi0f2fbdc2005-09-06 15:19:28 -0700907KPROBE_ENTRY(debug)
Jan Beulich7effaa82005-09-12 18:49:24 +0200908 INTR_FRAME
Linus Torvalds1da177e2005-04-16 15:20:36 -0700909 pushq $0
910 CFI_ADJUST_CFA_OFFSET 8
Andi Kleen5f8efbb2006-01-16 01:56:39 +0100911 paranoidentry do_debug, DEBUG_STACK
Linus Torvalds1da177e2005-04-16 15:20:36 -0700912 jmp paranoid_exit
913 CFI_ENDPROC
Prasanna S Panchamukhi0f2fbdc2005-09-06 15:19:28 -0700914 .previous .text
Linus Torvalds1da177e2005-04-16 15:20:36 -0700915
916 /* runs on exception stack */
Andi Kleeneddb6fb2006-02-03 21:50:41 +0100917KPROBE_ENTRY(nmi)
Jan Beulich7effaa82005-09-12 18:49:24 +0200918 INTR_FRAME
Linus Torvalds1da177e2005-04-16 15:20:36 -0700919 pushq $-1
Jan Beulich7effaa82005-09-12 18:49:24 +0200920 CFI_ADJUST_CFA_OFFSET 8
Linus Torvalds1da177e2005-04-16 15:20:36 -0700921 paranoidentry do_nmi
Andi Kleen6fefb0d2005-04-16 15:25:03 -0700922 /*
923 * "Paranoid" exit path from exception stack.
924 * Paranoid because this is used by NMIs and cannot take
925 * any kernel state for granted.
926 * We don't do kernel preemption checks here, because only
927 * NMI should be common and it does not enable IRQs and
928 * cannot get reschedule ticks.
929 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700930 /* ebx: no swapgs flag */
931paranoid_exit:
932 testl %ebx,%ebx /* swapgs needed? */
933 jnz paranoid_restore
Andi Kleen6fefb0d2005-04-16 15:25:03 -0700934 testl $3,CS(%rsp)
935 jnz paranoid_userspace
Linus Torvalds1da177e2005-04-16 15:20:36 -0700936paranoid_swapgs:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700937 swapgs
938paranoid_restore:
939 RESTORE_ALL 8
940 iretq
941paranoid_userspace:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700942 GET_THREAD_INFO(%rcx)
Andi Kleen6fefb0d2005-04-16 15:25:03 -0700943 movl threadinfo_flags(%rcx),%ebx
944 andl $_TIF_WORK_MASK,%ebx
Andi Kleen11b854b2005-04-16 15:25:02 -0700945 jz paranoid_swapgs
Andi Kleen6fefb0d2005-04-16 15:25:03 -0700946 movq %rsp,%rdi /* &pt_regs */
947 call sync_regs
948 movq %rax,%rsp /* switch stack for scheduling */
949 testl $_TIF_NEED_RESCHED,%ebx
950 jnz paranoid_schedule
951 movl %ebx,%edx /* arg3: thread flags */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700952 sti
Andi Kleen6fefb0d2005-04-16 15:25:03 -0700953 xorl %esi,%esi /* arg2: oldset */
954 movq %rsp,%rdi /* arg1: &pt_regs */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700955 call do_notify_resume
Andi Kleen6fefb0d2005-04-16 15:25:03 -0700956 cli
957 jmp paranoid_userspace
958paranoid_schedule:
Andi Kleen11b854b2005-04-16 15:25:02 -0700959 sti
960 call schedule
Andi Kleen6fefb0d2005-04-16 15:25:03 -0700961 cli
962 jmp paranoid_userspace
Linus Torvalds1da177e2005-04-16 15:20:36 -0700963 CFI_ENDPROC
Andi Kleeneddb6fb2006-02-03 21:50:41 +0100964 .previous .text
Andi Kleen6fefb0d2005-04-16 15:25:03 -0700965
Prasanna S Panchamukhi0f2fbdc2005-09-06 15:19:28 -0700966KPROBE_ENTRY(int3)
Jan Beulichb556b352006-01-11 22:43:00 +0100967 INTR_FRAME
968 pushq $0
969 CFI_ADJUST_CFA_OFFSET 8
Andi Kleen5f8efbb2006-01-16 01:56:39 +0100970 paranoidentry do_int3, DEBUG_STACK
Jan Beulichb556b352006-01-11 22:43:00 +0100971 jmp paranoid_exit
972 CFI_ENDPROC
Prasanna S Panchamukhi0f2fbdc2005-09-06 15:19:28 -0700973 .previous .text
Linus Torvalds1da177e2005-04-16 15:20:36 -0700974
975ENTRY(overflow)
976 zeroentry do_overflow
977
978ENTRY(bounds)
979 zeroentry do_bounds
980
981ENTRY(invalid_op)
982 zeroentry do_invalid_op
983
984ENTRY(coprocessor_segment_overrun)
985 zeroentry do_coprocessor_segment_overrun
986
987ENTRY(reserved)
988 zeroentry do_reserved
989
990 /* runs on exception stack */
991ENTRY(double_fault)
Jan Beulich7effaa82005-09-12 18:49:24 +0200992 XCPT_FRAME
Linus Torvalds1da177e2005-04-16 15:20:36 -0700993 paranoidentry do_double_fault
Linus Torvalds1da177e2005-04-16 15:20:36 -0700994 jmp paranoid_exit
995 CFI_ENDPROC
996
997ENTRY(invalid_TSS)
998 errorentry do_invalid_TSS
999
1000ENTRY(segment_not_present)
1001 errorentry do_segment_not_present
1002
1003 /* runs on exception stack */
1004ENTRY(stack_segment)
Jan Beulich7effaa82005-09-12 18:49:24 +02001005 XCPT_FRAME
Linus Torvalds1da177e2005-04-16 15:20:36 -07001006 paranoidentry do_stack_segment
Linus Torvalds1da177e2005-04-16 15:20:36 -07001007 jmp paranoid_exit
1008 CFI_ENDPROC
1009
Prasanna S Panchamukhi0f2fbdc2005-09-06 15:19:28 -07001010KPROBE_ENTRY(general_protection)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001011 errorentry do_general_protection
Prasanna S Panchamukhi0f2fbdc2005-09-06 15:19:28 -07001012 .previous .text
Linus Torvalds1da177e2005-04-16 15:20:36 -07001013
1014ENTRY(alignment_check)
1015 errorentry do_alignment_check
1016
1017ENTRY(divide_error)
1018 zeroentry do_divide_error
1019
1020ENTRY(spurious_interrupt_bug)
1021 zeroentry do_spurious_interrupt_bug
1022
1023#ifdef CONFIG_X86_MCE
1024 /* runs on exception stack */
1025ENTRY(machine_check)
Jan Beulich7effaa82005-09-12 18:49:24 +02001026 INTR_FRAME
Linus Torvalds1da177e2005-04-16 15:20:36 -07001027 pushq $0
1028 CFI_ADJUST_CFA_OFFSET 8
1029 paranoidentry do_machine_check
1030 jmp paranoid_exit
1031 CFI_ENDPROC
1032#endif
1033
Andi Kleened6b6762005-07-28 21:15:49 -07001034ENTRY(call_softirq)
Jan Beulich7effaa82005-09-12 18:49:24 +02001035 CFI_STARTPROC
Andi Kleened6b6762005-07-28 21:15:49 -07001036 movq %gs:pda_irqstackptr,%rax
Jan Beulichbd9cb642006-01-11 22:43:21 +01001037 movq %rsp,%rdx
1038 CFI_DEF_CFA_REGISTER rdx
Andi Kleened6b6762005-07-28 21:15:49 -07001039 incl %gs:pda_irqcount
1040 cmove %rax,%rsp
Jan Beulichbd9cb642006-01-11 22:43:21 +01001041 pushq %rdx
1042 /*todo CFI_DEF_CFA_EXPRESSION ...*/
Andi Kleened6b6762005-07-28 21:15:49 -07001043 call __do_softirq
Jan Beulichbd9cb642006-01-11 22:43:21 +01001044 popq %rsp
Jan Beulich7effaa82005-09-12 18:49:24 +02001045 CFI_DEF_CFA_REGISTER rsp
Andi Kleened6b6762005-07-28 21:15:49 -07001046 decl %gs:pda_irqcount
Andi Kleened6b6762005-07-28 21:15:49 -07001047 ret
Jan Beulich7effaa82005-09-12 18:49:24 +02001048 CFI_ENDPROC