blob: 300555bc56b36e2f3b8ac641df942e4d0787d37d [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>
44
45 .code64
46
Andi Kleendc37db42005-04-16 15:25:05 -070047#ifndef CONFIG_PREEMPT
Linus Torvalds1da177e2005-04-16 15:20:36 -070048#define retint_kernel retint_restore_args
49#endif
50
51/*
52 * C code is not supposed to know about undefined top of stack. Every time
53 * a C function with an pt_regs argument is called from the SYSCALL based
54 * fast path FIXUP_TOP_OF_STACK is needed.
55 * RESTORE_TOP_OF_STACK syncs the syscall state after any possible ptregs
56 * manipulation.
57 */
58
59 /* %rsp:at FRAMEEND */
60 .macro FIXUP_TOP_OF_STACK tmp
61 movq %gs:pda_oldrsp,\tmp
62 movq \tmp,RSP(%rsp)
63 movq $__USER_DS,SS(%rsp)
64 movq $__USER_CS,CS(%rsp)
65 movq $-1,RCX(%rsp)
66 movq R11(%rsp),\tmp /* get eflags */
67 movq \tmp,EFLAGS(%rsp)
68 .endm
69
70 .macro RESTORE_TOP_OF_STACK tmp,offset=0
71 movq RSP-\offset(%rsp),\tmp
72 movq \tmp,%gs:pda_oldrsp
73 movq EFLAGS-\offset(%rsp),\tmp
74 movq \tmp,R11-\offset(%rsp)
75 .endm
76
77 .macro FAKE_STACK_FRAME child_rip
78 /* push in order ss, rsp, eflags, cs, rip */
Andi Kleen3829ee62005-07-28 21:15:48 -070079 xorl %eax, %eax
Linus Torvalds1da177e2005-04-16 15:20:36 -070080 pushq %rax /* ss */
81 CFI_ADJUST_CFA_OFFSET 8
Jan Beulich7effaa82005-09-12 18:49:24 +020082 /*CFI_REL_OFFSET ss,0*/
Linus Torvalds1da177e2005-04-16 15:20:36 -070083 pushq %rax /* rsp */
84 CFI_ADJUST_CFA_OFFSET 8
Jan Beulich7effaa82005-09-12 18:49:24 +020085 CFI_REL_OFFSET rsp,0
Linus Torvalds1da177e2005-04-16 15:20:36 -070086 pushq $(1<<9) /* eflags - interrupts on */
87 CFI_ADJUST_CFA_OFFSET 8
Jan Beulich7effaa82005-09-12 18:49:24 +020088 /*CFI_REL_OFFSET rflags,0*/
Linus Torvalds1da177e2005-04-16 15:20:36 -070089 pushq $__KERNEL_CS /* cs */
90 CFI_ADJUST_CFA_OFFSET 8
Jan Beulich7effaa82005-09-12 18:49:24 +020091 /*CFI_REL_OFFSET cs,0*/
Linus Torvalds1da177e2005-04-16 15:20:36 -070092 pushq \child_rip /* rip */
93 CFI_ADJUST_CFA_OFFSET 8
Jan Beulich7effaa82005-09-12 18:49:24 +020094 CFI_REL_OFFSET rip,0
Linus Torvalds1da177e2005-04-16 15:20:36 -070095 pushq %rax /* orig rax */
96 CFI_ADJUST_CFA_OFFSET 8
97 .endm
98
99 .macro UNFAKE_STACK_FRAME
100 addq $8*6, %rsp
101 CFI_ADJUST_CFA_OFFSET -(6*8)
102 .endm
103
Jan Beulich7effaa82005-09-12 18:49:24 +0200104 .macro CFI_DEFAULT_STACK start=1
105 .if \start
106 CFI_STARTPROC simple
107 CFI_DEF_CFA rsp,SS+8
108 .else
109 CFI_DEF_CFA_OFFSET SS+8
110 .endif
111 CFI_REL_OFFSET r15,R15
112 CFI_REL_OFFSET r14,R14
113 CFI_REL_OFFSET r13,R13
114 CFI_REL_OFFSET r12,R12
115 CFI_REL_OFFSET rbp,RBP
116 CFI_REL_OFFSET rbx,RBX
117 CFI_REL_OFFSET r11,R11
118 CFI_REL_OFFSET r10,R10
119 CFI_REL_OFFSET r9,R9
120 CFI_REL_OFFSET r8,R8
121 CFI_REL_OFFSET rax,RAX
122 CFI_REL_OFFSET rcx,RCX
123 CFI_REL_OFFSET rdx,RDX
124 CFI_REL_OFFSET rsi,RSI
125 CFI_REL_OFFSET rdi,RDI
126 CFI_REL_OFFSET rip,RIP
127 /*CFI_REL_OFFSET cs,CS*/
128 /*CFI_REL_OFFSET rflags,EFLAGS*/
129 CFI_REL_OFFSET rsp,RSP
130 /*CFI_REL_OFFSET ss,SS*/
Linus Torvalds1da177e2005-04-16 15:20:36 -0700131 .endm
132/*
133 * A newly forked process directly context switches into this.
134 */
135/* rdi: prev */
136ENTRY(ret_from_fork)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700137 CFI_DEFAULT_STACK
138 call schedule_tail
139 GET_THREAD_INFO(%rcx)
140 testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT),threadinfo_flags(%rcx)
141 jnz rff_trace
142rff_action:
143 RESTORE_REST
144 testl $3,CS-ARGOFFSET(%rsp) # from kernel_thread?
145 je int_ret_from_sys_call
146 testl $_TIF_IA32,threadinfo_flags(%rcx)
147 jnz int_ret_from_sys_call
148 RESTORE_TOP_OF_STACK %rdi,ARGOFFSET
149 jmp ret_from_sys_call
150rff_trace:
151 movq %rsp,%rdi
152 call syscall_trace_leave
153 GET_THREAD_INFO(%rcx)
154 jmp rff_action
155 CFI_ENDPROC
156
157/*
158 * System call entry. Upto 6 arguments in registers are supported.
159 *
160 * SYSCALL does not save anything on the stack and does not change the
161 * stack pointer.
162 */
163
164/*
165 * Register setup:
166 * rax system call number
167 * rdi arg0
168 * rcx return address for syscall/sysret, C arg3
169 * rsi arg1
170 * rdx arg2
171 * r10 arg3 (--> moved to rcx for C)
172 * r8 arg4
173 * r9 arg5
174 * r11 eflags for syscall/sysret, temporary for C
175 * r12-r15,rbp,rbx saved by C code, not touched.
176 *
177 * Interrupts are off on entry.
178 * Only called from user space.
179 *
180 * XXX if we had a free scratch register we could save the RSP into the stack frame
181 * and report it properly in ps. Unfortunately we haven't.
182 */
183
184ENTRY(system_call)
Jan Beulich7effaa82005-09-12 18:49:24 +0200185 CFI_STARTPROC simple
186 CFI_DEF_CFA rsp,0
187 CFI_REGISTER rip,rcx
188 /*CFI_REGISTER rflags,r11*/
Linus Torvalds1da177e2005-04-16 15:20:36 -0700189 swapgs
190 movq %rsp,%gs:pda_oldrsp
191 movq %gs:pda_kernelstack,%rsp
192 sti
193 SAVE_ARGS 8,1
194 movq %rax,ORIG_RAX-ARGOFFSET(%rsp)
Jan Beulich7effaa82005-09-12 18:49:24 +0200195 movq %rcx,RIP-ARGOFFSET(%rsp)
196 CFI_REL_OFFSET rip,RIP-ARGOFFSET
Linus Torvalds1da177e2005-04-16 15:20:36 -0700197 GET_THREAD_INFO(%rcx)
198 testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP),threadinfo_flags(%rcx)
Jan Beulich7effaa82005-09-12 18:49:24 +0200199 CFI_REMEMBER_STATE
Linus Torvalds1da177e2005-04-16 15:20:36 -0700200 jnz tracesys
201 cmpq $__NR_syscall_max,%rax
202 ja badsys
203 movq %r10,%rcx
204 call *sys_call_table(,%rax,8) # XXX: rip relative
205 movq %rax,RAX-ARGOFFSET(%rsp)
206/*
207 * Syscall return path ending with SYSRET (fast path)
208 * Has incomplete stack frame and undefined top of stack.
209 */
210 .globl ret_from_sys_call
211ret_from_sys_call:
Andi Kleen11b854b2005-04-16 15:25:02 -0700212 movl $_TIF_ALLWORK_MASK,%edi
Linus Torvalds1da177e2005-04-16 15:20:36 -0700213 /* edi: flagmask */
214sysret_check:
215 GET_THREAD_INFO(%rcx)
216 cli
217 movl threadinfo_flags(%rcx),%edx
218 andl %edi,%edx
Jan Beulich7effaa82005-09-12 18:49:24 +0200219 CFI_REMEMBER_STATE
Linus Torvalds1da177e2005-04-16 15:20:36 -0700220 jnz sysret_careful
221 movq RIP-ARGOFFSET(%rsp),%rcx
Jan Beulich7effaa82005-09-12 18:49:24 +0200222 CFI_REGISTER rip,rcx
Linus Torvalds1da177e2005-04-16 15:20:36 -0700223 RESTORE_ARGS 0,-ARG_SKIP,1
Jan Beulich7effaa82005-09-12 18:49:24 +0200224 /*CFI_REGISTER rflags,r11*/
Linus Torvalds1da177e2005-04-16 15:20:36 -0700225 movq %gs:pda_oldrsp,%rsp
226 swapgs
227 sysretq
228
229 /* Handle reschedules */
230 /* edx: work, edi: workmask */
231sysret_careful:
Jan Beulich7effaa82005-09-12 18:49:24 +0200232 CFI_RESTORE_STATE
Linus Torvalds1da177e2005-04-16 15:20:36 -0700233 bt $TIF_NEED_RESCHED,%edx
234 jnc sysret_signal
235 sti
236 pushq %rdi
Jan Beulich7effaa82005-09-12 18:49:24 +0200237 CFI_ADJUST_CFA_OFFSET 8
Linus Torvalds1da177e2005-04-16 15:20:36 -0700238 call schedule
239 popq %rdi
Jan Beulich7effaa82005-09-12 18:49:24 +0200240 CFI_ADJUST_CFA_OFFSET -8
Linus Torvalds1da177e2005-04-16 15:20:36 -0700241 jmp sysret_check
242
243 /* Handle a signal */
244sysret_signal:
245 sti
Andi Kleen10ffdbb2005-05-16 21:53:19 -0700246 testl $(_TIF_SIGPENDING|_TIF_NOTIFY_RESUME|_TIF_SINGLESTEP),%edx
247 jz 1f
248
249 /* Really a signal */
250 /* edx: work flags (arg3) */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700251 leaq do_notify_resume(%rip),%rax
252 leaq -ARGOFFSET(%rsp),%rdi # &pt_regs -> arg1
253 xorl %esi,%esi # oldset -> arg2
254 call ptregscall_common
Andi Kleen10ffdbb2005-05-16 21:53:19 -07002551: movl $_TIF_NEED_RESCHED,%edi
Linus Torvalds1da177e2005-04-16 15:20:36 -0700256 jmp sysret_check
257
Jan Beulich7effaa82005-09-12 18:49:24 +0200258badsys:
259 movq $-ENOSYS,RAX-ARGOFFSET(%rsp)
260 jmp ret_from_sys_call
261
Linus Torvalds1da177e2005-04-16 15:20:36 -0700262 /* Do syscall tracing */
263tracesys:
Jan Beulich7effaa82005-09-12 18:49:24 +0200264 CFI_RESTORE_STATE
Linus Torvalds1da177e2005-04-16 15:20:36 -0700265 SAVE_REST
266 movq $-ENOSYS,RAX(%rsp)
267 FIXUP_TOP_OF_STACK %rdi
268 movq %rsp,%rdi
269 call syscall_trace_enter
270 LOAD_ARGS ARGOFFSET /* reload args from stack in case ptrace changed it */
271 RESTORE_REST
272 cmpq $__NR_syscall_max,%rax
273 ja 1f
274 movq %r10,%rcx /* fixup for C */
275 call *sys_call_table(,%rax,8)
276 movq %rax,RAX-ARGOFFSET(%rsp)
2771: SAVE_REST
278 movq %rsp,%rdi
279 call syscall_trace_leave
280 RESTORE_TOP_OF_STACK %rbx
281 RESTORE_REST
282 jmp ret_from_sys_call
Jan Beulich7effaa82005-09-12 18:49:24 +0200283 CFI_ENDPROC
Linus Torvalds1da177e2005-04-16 15:20:36 -0700284
Linus Torvalds1da177e2005-04-16 15:20:36 -0700285/*
286 * Syscall return path ending with IRET.
287 * Has correct top of stack, but partial stack frame.
288 */
Jan Beulich7effaa82005-09-12 18:49:24 +0200289ENTRY(int_ret_from_sys_call)
290 CFI_STARTPROC simple
291 CFI_DEF_CFA rsp,SS+8-ARGOFFSET
292 /*CFI_REL_OFFSET ss,SS-ARGOFFSET*/
293 CFI_REL_OFFSET rsp,RSP-ARGOFFSET
294 /*CFI_REL_OFFSET rflags,EFLAGS-ARGOFFSET*/
295 /*CFI_REL_OFFSET cs,CS-ARGOFFSET*/
296 CFI_REL_OFFSET rip,RIP-ARGOFFSET
297 CFI_REL_OFFSET rdx,RDX-ARGOFFSET
298 CFI_REL_OFFSET rcx,RCX-ARGOFFSET
299 CFI_REL_OFFSET rax,RAX-ARGOFFSET
300 CFI_REL_OFFSET rdi,RDI-ARGOFFSET
301 CFI_REL_OFFSET rsi,RSI-ARGOFFSET
302 CFI_REL_OFFSET r8,R8-ARGOFFSET
303 CFI_REL_OFFSET r9,R9-ARGOFFSET
304 CFI_REL_OFFSET r10,R10-ARGOFFSET
305 CFI_REL_OFFSET r11,R11-ARGOFFSET
Linus Torvalds1da177e2005-04-16 15:20:36 -0700306 cli
307 testl $3,CS-ARGOFFSET(%rsp)
308 je retint_restore_args
309 movl $_TIF_ALLWORK_MASK,%edi
310 /* edi: mask to check */
311int_with_check:
312 GET_THREAD_INFO(%rcx)
313 movl threadinfo_flags(%rcx),%edx
314 andl %edi,%edx
315 jnz int_careful
Andi Kleenbf2fcc62006-01-11 22:44:06 +0100316 andl $~TS_COMPAT,threadinfo_status(%rcx)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700317 jmp retint_swapgs
318
319 /* Either reschedule or signal or syscall exit tracking needed. */
320 /* First do a reschedule test. */
321 /* edx: work, edi: workmask */
322int_careful:
323 bt $TIF_NEED_RESCHED,%edx
324 jnc int_very_careful
325 sti
326 pushq %rdi
Jan Beulich7effaa82005-09-12 18:49:24 +0200327 CFI_ADJUST_CFA_OFFSET 8
Linus Torvalds1da177e2005-04-16 15:20:36 -0700328 call schedule
329 popq %rdi
Jan Beulich7effaa82005-09-12 18:49:24 +0200330 CFI_ADJUST_CFA_OFFSET -8
Andi Kleencdd219c2005-04-16 15:25:04 -0700331 cli
Linus Torvalds1da177e2005-04-16 15:20:36 -0700332 jmp int_with_check
333
334 /* handle signals and tracing -- both require a full stack frame */
335int_very_careful:
336 sti
337 SAVE_REST
338 /* Check for syscall exit trace */
339 testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP),%edx
340 jz int_signal
341 pushq %rdi
Jan Beulich7effaa82005-09-12 18:49:24 +0200342 CFI_ADJUST_CFA_OFFSET 8
Linus Torvalds1da177e2005-04-16 15:20:36 -0700343 leaq 8(%rsp),%rdi # &ptregs -> arg1
344 call syscall_trace_leave
345 popq %rdi
Jan Beulich7effaa82005-09-12 18:49:24 +0200346 CFI_ADJUST_CFA_OFFSET -8
Andi Kleen36c11042005-04-16 15:25:01 -0700347 andl $~(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP),%edi
Andi Kleenbe9e6872005-05-01 08:58:51 -0700348 cli
Linus Torvalds1da177e2005-04-16 15:20:36 -0700349 jmp int_restore_rest
350
351int_signal:
352 testl $(_TIF_NOTIFY_RESUME|_TIF_SIGPENDING|_TIF_SINGLESTEP),%edx
353 jz 1f
354 movq %rsp,%rdi # &ptregs -> arg1
355 xorl %esi,%esi # oldset -> arg2
356 call do_notify_resume
3571: movl $_TIF_NEED_RESCHED,%edi
358int_restore_rest:
359 RESTORE_REST
Andi Kleenbe9e6872005-05-01 08:58:51 -0700360 cli
Linus Torvalds1da177e2005-04-16 15:20:36 -0700361 jmp int_with_check
362 CFI_ENDPROC
363
364/*
365 * Certain special system calls that need to save a complete full stack frame.
366 */
367
368 .macro PTREGSCALL label,func,arg
369 .globl \label
370\label:
371 leaq \func(%rip),%rax
372 leaq -ARGOFFSET+8(%rsp),\arg /* 8 for return address */
373 jmp ptregscall_common
374 .endm
375
Jan Beulich7effaa82005-09-12 18:49:24 +0200376 CFI_STARTPROC
377
Linus Torvalds1da177e2005-04-16 15:20:36 -0700378 PTREGSCALL stub_clone, sys_clone, %r8
379 PTREGSCALL stub_fork, sys_fork, %rdi
380 PTREGSCALL stub_vfork, sys_vfork, %rdi
381 PTREGSCALL stub_rt_sigsuspend, sys_rt_sigsuspend, %rdx
382 PTREGSCALL stub_sigaltstack, sys_sigaltstack, %rdx
383 PTREGSCALL stub_iopl, sys_iopl, %rsi
384
385ENTRY(ptregscall_common)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700386 popq %r11
Jan Beulich7effaa82005-09-12 18:49:24 +0200387 CFI_ADJUST_CFA_OFFSET -8
388 CFI_REGISTER rip, r11
Linus Torvalds1da177e2005-04-16 15:20:36 -0700389 SAVE_REST
390 movq %r11, %r15
Jan Beulich7effaa82005-09-12 18:49:24 +0200391 CFI_REGISTER rip, r15
Linus Torvalds1da177e2005-04-16 15:20:36 -0700392 FIXUP_TOP_OF_STACK %r11
393 call *%rax
394 RESTORE_TOP_OF_STACK %r11
395 movq %r15, %r11
Jan Beulich7effaa82005-09-12 18:49:24 +0200396 CFI_REGISTER rip, r11
Linus Torvalds1da177e2005-04-16 15:20:36 -0700397 RESTORE_REST
398 pushq %r11
Jan Beulich7effaa82005-09-12 18:49:24 +0200399 CFI_ADJUST_CFA_OFFSET 8
400 CFI_REL_OFFSET rip, 0
Linus Torvalds1da177e2005-04-16 15:20:36 -0700401 ret
402 CFI_ENDPROC
403
404ENTRY(stub_execve)
405 CFI_STARTPROC
406 popq %r11
Jan Beulich7effaa82005-09-12 18:49:24 +0200407 CFI_ADJUST_CFA_OFFSET -8
408 CFI_REGISTER rip, r11
Linus Torvalds1da177e2005-04-16 15:20:36 -0700409 SAVE_REST
410 movq %r11, %r15
Jan Beulich7effaa82005-09-12 18:49:24 +0200411 CFI_REGISTER rip, r15
Linus Torvalds1da177e2005-04-16 15:20:36 -0700412 FIXUP_TOP_OF_STACK %r11
413 call sys_execve
414 GET_THREAD_INFO(%rcx)
415 bt $TIF_IA32,threadinfo_flags(%rcx)
Jan Beulich7effaa82005-09-12 18:49:24 +0200416 CFI_REMEMBER_STATE
Linus Torvalds1da177e2005-04-16 15:20:36 -0700417 jc exec_32bit
418 RESTORE_TOP_OF_STACK %r11
419 movq %r15, %r11
Jan Beulich7effaa82005-09-12 18:49:24 +0200420 CFI_REGISTER rip, r11
Linus Torvalds1da177e2005-04-16 15:20:36 -0700421 RESTORE_REST
Jan Beulich7effaa82005-09-12 18:49:24 +0200422 pushq %r11
423 CFI_ADJUST_CFA_OFFSET 8
424 CFI_REL_OFFSET rip, 0
Linus Torvalds1da177e2005-04-16 15:20:36 -0700425 ret
426
427exec_32bit:
Jan Beulich7effaa82005-09-12 18:49:24 +0200428 CFI_RESTORE_STATE
Linus Torvalds1da177e2005-04-16 15:20:36 -0700429 movq %rax,RAX(%rsp)
430 RESTORE_REST
431 jmp int_ret_from_sys_call
432 CFI_ENDPROC
433
434/*
435 * sigreturn is special because it needs to restore all registers on return.
436 * This cannot be done with SYSRET, so use the IRET return path instead.
437 */
438ENTRY(stub_rt_sigreturn)
439 CFI_STARTPROC
Jan Beulich7effaa82005-09-12 18:49:24 +0200440 addq $8, %rsp
441 CFI_ADJUST_CFA_OFFSET -8
Linus Torvalds1da177e2005-04-16 15:20:36 -0700442 SAVE_REST
443 movq %rsp,%rdi
444 FIXUP_TOP_OF_STACK %r11
445 call sys_rt_sigreturn
446 movq %rax,RAX(%rsp) # fixme, this could be done at the higher layer
447 RESTORE_REST
448 jmp int_ret_from_sys_call
449 CFI_ENDPROC
450
Jan Beulich7effaa82005-09-12 18:49:24 +0200451/*
452 * initial frame state for interrupts and exceptions
453 */
454 .macro _frame ref
455 CFI_STARTPROC simple
456 CFI_DEF_CFA rsp,SS+8-\ref
457 /*CFI_REL_OFFSET ss,SS-\ref*/
458 CFI_REL_OFFSET rsp,RSP-\ref
459 /*CFI_REL_OFFSET rflags,EFLAGS-\ref*/
460 /*CFI_REL_OFFSET cs,CS-\ref*/
461 CFI_REL_OFFSET rip,RIP-\ref
462 .endm
463
464/* initial frame state for interrupts (and exceptions without error code) */
465#define INTR_FRAME _frame RIP
466/* initial frame state for exceptions with error code (and interrupts with
467 vector already pushed) */
468#define XCPT_FRAME _frame ORIG_RAX
469
Linus Torvalds1da177e2005-04-16 15:20:36 -0700470/*
471 * Interrupt entry/exit.
472 *
473 * Interrupt entry points save only callee clobbered registers in fast path.
474 *
475 * Entry runs with interrupts off.
476 */
477
478/* 0(%rsp): interrupt number */
479 .macro interrupt func
Linus Torvalds1da177e2005-04-16 15:20:36 -0700480 cld
481#ifdef CONFIG_DEBUG_INFO
482 SAVE_ALL
483 movq %rsp,%rdi
484 /*
485 * Setup a stack frame pointer. This allows gdb to trace
486 * back to the original stack.
487 */
488 movq %rsp,%rbp
489 CFI_DEF_CFA_REGISTER rbp
490#else
491 SAVE_ARGS
492 leaq -ARGOFFSET(%rsp),%rdi # arg1 for handler
493#endif
494 testl $3,CS(%rdi)
495 je 1f
496 swapgs
Andi Kleen3829ee62005-07-28 21:15:48 -07004971: incl %gs:pda_irqcount # RED-PEN should check preempt count
Linus Torvalds1da177e2005-04-16 15:20:36 -0700498 movq %gs:pda_irqstackptr,%rax
Jan Beulich7effaa82005-09-12 18:49:24 +0200499 cmoveq %rax,%rsp /*todo This needs CFI annotation! */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700500 pushq %rdi # save old stack
Jan Beulich7effaa82005-09-12 18:49:24 +0200501 CFI_ADJUST_CFA_OFFSET 8
Linus Torvalds1da177e2005-04-16 15:20:36 -0700502 call \func
503 .endm
504
505ENTRY(common_interrupt)
Jan Beulich7effaa82005-09-12 18:49:24 +0200506 XCPT_FRAME
Linus Torvalds1da177e2005-04-16 15:20:36 -0700507 interrupt do_IRQ
508 /* 0(%rsp): oldrsp-ARGOFFSET */
Jan Beulich7effaa82005-09-12 18:49:24 +0200509ret_from_intr:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700510 popq %rdi
Jan Beulich7effaa82005-09-12 18:49:24 +0200511 CFI_ADJUST_CFA_OFFSET -8
Linus Torvalds1da177e2005-04-16 15:20:36 -0700512 cli
Andi Kleen3829ee62005-07-28 21:15:48 -0700513 decl %gs:pda_irqcount
Linus Torvalds1da177e2005-04-16 15:20:36 -0700514#ifdef CONFIG_DEBUG_INFO
515 movq RBP(%rdi),%rbp
Jan Beulich7effaa82005-09-12 18:49:24 +0200516 CFI_DEF_CFA_REGISTER rsp
Linus Torvalds1da177e2005-04-16 15:20:36 -0700517#endif
Jan Beulich7effaa82005-09-12 18:49:24 +0200518 leaq ARGOFFSET(%rdi),%rsp /*todo This needs CFI annotation! */
519exit_intr:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700520 GET_THREAD_INFO(%rcx)
521 testl $3,CS-ARGOFFSET(%rsp)
522 je retint_kernel
523
524 /* Interrupt came from user space */
525 /*
526 * Has a correct top of stack, but a partial stack frame
527 * %rcx: thread info. Interrupts off.
528 */
529retint_with_reschedule:
530 movl $_TIF_WORK_MASK,%edi
Jan Beulich7effaa82005-09-12 18:49:24 +0200531retint_check:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700532 movl threadinfo_flags(%rcx),%edx
533 andl %edi,%edx
Jan Beulich7effaa82005-09-12 18:49:24 +0200534 CFI_REMEMBER_STATE
Linus Torvalds1da177e2005-04-16 15:20:36 -0700535 jnz retint_careful
536retint_swapgs:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700537 swapgs
538retint_restore_args:
539 cli
540 RESTORE_ARGS 0,8,0
541iret_label:
542 iretq
543
544 .section __ex_table,"a"
545 .quad iret_label,bad_iret
546 .previous
547 .section .fixup,"ax"
548 /* force a signal here? this matches i386 behaviour */
549 /* running with kernel gs */
550bad_iret:
551 movq $-9999,%rdi /* better code? */
552 jmp do_exit
553 .previous
554
Jan Beulich7effaa82005-09-12 18:49:24 +0200555 /* edi: workmask, edx: work */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700556retint_careful:
Jan Beulich7effaa82005-09-12 18:49:24 +0200557 CFI_RESTORE_STATE
Linus Torvalds1da177e2005-04-16 15:20:36 -0700558 bt $TIF_NEED_RESCHED,%edx
559 jnc retint_signal
560 sti
561 pushq %rdi
Jan Beulich7effaa82005-09-12 18:49:24 +0200562 CFI_ADJUST_CFA_OFFSET 8
Linus Torvalds1da177e2005-04-16 15:20:36 -0700563 call schedule
564 popq %rdi
Jan Beulich7effaa82005-09-12 18:49:24 +0200565 CFI_ADJUST_CFA_OFFSET -8
Linus Torvalds1da177e2005-04-16 15:20:36 -0700566 GET_THREAD_INFO(%rcx)
567 cli
568 jmp retint_check
569
570retint_signal:
Andi Kleen10ffdbb2005-05-16 21:53:19 -0700571 testl $(_TIF_SIGPENDING|_TIF_NOTIFY_RESUME|_TIF_SINGLESTEP),%edx
572 jz retint_swapgs
Linus Torvalds1da177e2005-04-16 15:20:36 -0700573 sti
574 SAVE_REST
575 movq $-1,ORIG_RAX(%rsp)
Andi Kleen3829ee62005-07-28 21:15:48 -0700576 xorl %esi,%esi # oldset
Linus Torvalds1da177e2005-04-16 15:20:36 -0700577 movq %rsp,%rdi # &pt_regs
578 call do_notify_resume
579 RESTORE_REST
580 cli
Andi Kleen10ffdbb2005-05-16 21:53:19 -0700581 movl $_TIF_NEED_RESCHED,%edi
Andi Kleenbe9e6872005-05-01 08:58:51 -0700582 GET_THREAD_INFO(%rcx)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700583 jmp retint_check
584
585#ifdef CONFIG_PREEMPT
586 /* Returning to kernel space. Check if we need preemption */
587 /* rcx: threadinfo. interrupts off. */
588 .p2align
589retint_kernel:
590 cmpl $0,threadinfo_preempt_count(%rcx)
591 jnz retint_restore_args
592 bt $TIF_NEED_RESCHED,threadinfo_flags(%rcx)
593 jnc retint_restore_args
594 bt $9,EFLAGS-ARGOFFSET(%rsp) /* interrupts off? */
595 jnc retint_restore_args
596 call preempt_schedule_irq
597 jmp exit_intr
598#endif
599 CFI_ENDPROC
600
601/*
602 * APIC interrupts.
603 */
604 .macro apicinterrupt num,func
Jan Beulich7effaa82005-09-12 18:49:24 +0200605 INTR_FRAME
Linus Torvalds1da177e2005-04-16 15:20:36 -0700606 pushq $\num-256
Jan Beulich7effaa82005-09-12 18:49:24 +0200607 CFI_ADJUST_CFA_OFFSET 8
Linus Torvalds1da177e2005-04-16 15:20:36 -0700608 interrupt \func
609 jmp ret_from_intr
610 CFI_ENDPROC
611 .endm
612
613ENTRY(thermal_interrupt)
614 apicinterrupt THERMAL_APIC_VECTOR,smp_thermal_interrupt
615
Jacob Shin89b831e2005-11-05 17:25:53 +0100616ENTRY(threshold_interrupt)
617 apicinterrupt THRESHOLD_APIC_VECTOR,mce_threshold_interrupt
618
Linus Torvalds1da177e2005-04-16 15:20:36 -0700619#ifdef CONFIG_SMP
620ENTRY(reschedule_interrupt)
621 apicinterrupt RESCHEDULE_VECTOR,smp_reschedule_interrupt
622
Andi Kleene5bc8b62005-09-12 18:49:24 +0200623 .macro INVALIDATE_ENTRY num
624ENTRY(invalidate_interrupt\num)
625 apicinterrupt INVALIDATE_TLB_VECTOR_START+\num,smp_invalidate_interrupt
626 .endm
627
628 INVALIDATE_ENTRY 0
629 INVALIDATE_ENTRY 1
630 INVALIDATE_ENTRY 2
631 INVALIDATE_ENTRY 3
632 INVALIDATE_ENTRY 4
633 INVALIDATE_ENTRY 5
634 INVALIDATE_ENTRY 6
635 INVALIDATE_ENTRY 7
Linus Torvalds1da177e2005-04-16 15:20:36 -0700636
637ENTRY(call_function_interrupt)
638 apicinterrupt CALL_FUNCTION_VECTOR,smp_call_function_interrupt
639#endif
640
641#ifdef CONFIG_X86_LOCAL_APIC
642ENTRY(apic_timer_interrupt)
643 apicinterrupt LOCAL_TIMER_VECTOR,smp_apic_timer_interrupt
644
645ENTRY(error_interrupt)
646 apicinterrupt ERROR_APIC_VECTOR,smp_error_interrupt
647
648ENTRY(spurious_interrupt)
649 apicinterrupt SPURIOUS_APIC_VECTOR,smp_spurious_interrupt
650#endif
651
652/*
653 * Exception entry points.
654 */
655 .macro zeroentry sym
Jan Beulich7effaa82005-09-12 18:49:24 +0200656 INTR_FRAME
Linus Torvalds1da177e2005-04-16 15:20:36 -0700657 pushq $0 /* push error code/oldrax */
Jan Beulich7effaa82005-09-12 18:49:24 +0200658 CFI_ADJUST_CFA_OFFSET 8
Linus Torvalds1da177e2005-04-16 15:20:36 -0700659 pushq %rax /* push real oldrax to the rdi slot */
Jan Beulich7effaa82005-09-12 18:49:24 +0200660 CFI_ADJUST_CFA_OFFSET 8
Linus Torvalds1da177e2005-04-16 15:20:36 -0700661 leaq \sym(%rip),%rax
662 jmp error_entry
Jan Beulich7effaa82005-09-12 18:49:24 +0200663 CFI_ENDPROC
Linus Torvalds1da177e2005-04-16 15:20:36 -0700664 .endm
665
666 .macro errorentry sym
Jan Beulich7effaa82005-09-12 18:49:24 +0200667 XCPT_FRAME
Linus Torvalds1da177e2005-04-16 15:20:36 -0700668 pushq %rax
Jan Beulich7effaa82005-09-12 18:49:24 +0200669 CFI_ADJUST_CFA_OFFSET 8
Linus Torvalds1da177e2005-04-16 15:20:36 -0700670 leaq \sym(%rip),%rax
671 jmp error_entry
Jan Beulich7effaa82005-09-12 18:49:24 +0200672 CFI_ENDPROC
Linus Torvalds1da177e2005-04-16 15:20:36 -0700673 .endm
674
675 /* error code is on the stack already */
676 /* handle NMI like exceptions that can happen everywhere */
Jan Beulichb556b352006-01-11 22:43:00 +0100677#ifndef DEBUG_IST
678# define DEBUG_IST 0
679#endif
680 .macro paranoidentry sym, ist=0
Linus Torvalds1da177e2005-04-16 15:20:36 -0700681 SAVE_ALL
682 cld
683 movl $1,%ebx
684 movl $MSR_GS_BASE,%ecx
685 rdmsr
686 testl %edx,%edx
687 js 1f
688 swapgs
689 xorl %ebx,%ebx
Jan Beulichb556b352006-01-11 22:43:00 +01006901:
691 .if \ist
692 movq %gs:pda_data_offset, %rbp
693 .endif
694 movq %rsp,%rdi
Linus Torvalds1da177e2005-04-16 15:20:36 -0700695 movq ORIG_RAX(%rsp),%rsi
696 movq $-1,ORIG_RAX(%rsp)
Jan Beulichb556b352006-01-11 22:43:00 +0100697 .if \ist
698 subq $EXCEPTION_STACK_SIZE, per_cpu__init_tss + TSS_ist + (\ist - 1) * 8(%rbp)
699 .endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700700 call \sym
Jan Beulichb556b352006-01-11 22:43:00 +0100701 .if \ist
702 addq $EXCEPTION_STACK_SIZE, per_cpu__init_tss + TSS_ist + (\ist - 1) * 8(%rbp)
703 .endif
Andi Kleen6fefb0d2005-04-16 15:25:03 -0700704 cli
Linus Torvalds1da177e2005-04-16 15:20:36 -0700705 .endm
706
707/*
708 * Exception entry point. This expects an error code/orig_rax on the stack
709 * and the exception handler in %rax.
710 */
711ENTRY(error_entry)
Jan Beulich7effaa82005-09-12 18:49:24 +0200712 _frame RDI
Linus Torvalds1da177e2005-04-16 15:20:36 -0700713 /* rdi slot contains rax, oldrax contains error code */
714 cld
715 subq $14*8,%rsp
716 CFI_ADJUST_CFA_OFFSET (14*8)
717 movq %rsi,13*8(%rsp)
718 CFI_REL_OFFSET rsi,RSI
719 movq 14*8(%rsp),%rsi /* load rax from rdi slot */
720 movq %rdx,12*8(%rsp)
721 CFI_REL_OFFSET rdx,RDX
722 movq %rcx,11*8(%rsp)
723 CFI_REL_OFFSET rcx,RCX
724 movq %rsi,10*8(%rsp) /* store rax */
725 CFI_REL_OFFSET rax,RAX
726 movq %r8, 9*8(%rsp)
727 CFI_REL_OFFSET r8,R8
728 movq %r9, 8*8(%rsp)
729 CFI_REL_OFFSET r9,R9
730 movq %r10,7*8(%rsp)
731 CFI_REL_OFFSET r10,R10
732 movq %r11,6*8(%rsp)
733 CFI_REL_OFFSET r11,R11
734 movq %rbx,5*8(%rsp)
735 CFI_REL_OFFSET rbx,RBX
736 movq %rbp,4*8(%rsp)
737 CFI_REL_OFFSET rbp,RBP
738 movq %r12,3*8(%rsp)
739 CFI_REL_OFFSET r12,R12
740 movq %r13,2*8(%rsp)
741 CFI_REL_OFFSET r13,R13
742 movq %r14,1*8(%rsp)
743 CFI_REL_OFFSET r14,R14
744 movq %r15,(%rsp)
745 CFI_REL_OFFSET r15,R15
746 xorl %ebx,%ebx
747 testl $3,CS(%rsp)
748 je error_kernelspace
749error_swapgs:
750 swapgs
751error_sti:
752 movq %rdi,RDI(%rsp)
753 movq %rsp,%rdi
754 movq ORIG_RAX(%rsp),%rsi /* get error code */
755 movq $-1,ORIG_RAX(%rsp)
756 call *%rax
757 /* ebx: no swapgs flag (1: don't need swapgs, 0: need it) */
758error_exit:
759 movl %ebx,%eax
760 RESTORE_REST
761 cli
762 GET_THREAD_INFO(%rcx)
763 testl %eax,%eax
764 jne retint_kernel
765 movl threadinfo_flags(%rcx),%edx
766 movl $_TIF_WORK_MASK,%edi
767 andl %edi,%edx
768 jnz retint_careful
769 swapgs
770 RESTORE_ARGS 0,8,0
Jan Beulich505cc4e2006-01-11 22:42:20 +0100771 jmp iret_label
Linus Torvalds1da177e2005-04-16 15:20:36 -0700772 CFI_ENDPROC
773
774error_kernelspace:
775 incl %ebx
776 /* There are two places in the kernel that can potentially fault with
777 usergs. Handle them here. The exception handlers after
778 iret run with kernel gs again, so don't set the user space flag.
779 B stepping K8s sometimes report an truncated RIP for IRET
780 exceptions returning to compat mode. Check for these here too. */
781 leaq iret_label(%rip),%rbp
782 cmpq %rbp,RIP(%rsp)
783 je error_swapgs
784 movl %ebp,%ebp /* zero extend */
785 cmpq %rbp,RIP(%rsp)
786 je error_swapgs
787 cmpq $gs_change,RIP(%rsp)
788 je error_swapgs
789 jmp error_sti
790
791 /* Reload gs selector with exception handling */
792 /* edi: new selector */
793ENTRY(load_gs_index)
Jan Beulich7effaa82005-09-12 18:49:24 +0200794 CFI_STARTPROC
Linus Torvalds1da177e2005-04-16 15:20:36 -0700795 pushf
Jan Beulich7effaa82005-09-12 18:49:24 +0200796 CFI_ADJUST_CFA_OFFSET 8
Linus Torvalds1da177e2005-04-16 15:20:36 -0700797 cli
798 swapgs
799gs_change:
800 movl %edi,%gs
8012: mfence /* workaround */
802 swapgs
803 popf
Jan Beulich7effaa82005-09-12 18:49:24 +0200804 CFI_ADJUST_CFA_OFFSET -8
Linus Torvalds1da177e2005-04-16 15:20:36 -0700805 ret
Jan Beulich7effaa82005-09-12 18:49:24 +0200806 CFI_ENDPROC
Linus Torvalds1da177e2005-04-16 15:20:36 -0700807
808 .section __ex_table,"a"
809 .align 8
810 .quad gs_change,bad_gs
811 .previous
812 .section .fixup,"ax"
813 /* running with kernelgs */
814bad_gs:
815 swapgs /* switch back to user gs */
816 xorl %eax,%eax
817 movl %eax,%gs
818 jmp 2b
819 .previous
820
821/*
822 * Create a kernel thread.
823 *
824 * C extern interface:
825 * extern long kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
826 *
827 * asm input arguments:
828 * rdi: fn, rsi: arg, rdx: flags
829 */
830ENTRY(kernel_thread)
831 CFI_STARTPROC
832 FAKE_STACK_FRAME $child_rip
833 SAVE_ALL
834
835 # rdi: flags, rsi: usp, rdx: will be &pt_regs
836 movq %rdx,%rdi
837 orq kernel_thread_flags(%rip),%rdi
838 movq $-1, %rsi
839 movq %rsp, %rdx
840
841 xorl %r8d,%r8d
842 xorl %r9d,%r9d
843
844 # clone now
845 call do_fork
846 movq %rax,RAX(%rsp)
847 xorl %edi,%edi
848
849 /*
850 * It isn't worth to check for reschedule here,
851 * so internally to the x86_64 port you can rely on kernel_thread()
852 * not to reschedule the child before returning, this avoids the need
853 * of hacks for example to fork off the per-CPU idle tasks.
854 * [Hopefully no generic code relies on the reschedule -AK]
855 */
856 RESTORE_ALL
857 UNFAKE_STACK_FRAME
858 ret
859 CFI_ENDPROC
860
861
862child_rip:
863 /*
864 * Here we are in the child and the registers are set as they were
865 * at kernel_thread() invocation in the parent.
866 */
867 movq %rdi, %rax
868 movq %rsi, %rdi
869 call *%rax
870 # exit
Andi Kleen3829ee62005-07-28 21:15:48 -0700871 xorl %edi, %edi
Linus Torvalds1da177e2005-04-16 15:20:36 -0700872 call do_exit
873
874/*
875 * execve(). This function needs to use IRET, not SYSRET, to set up all state properly.
876 *
877 * C extern interface:
878 * extern long execve(char *name, char **argv, char **envp)
879 *
880 * asm input arguments:
881 * rdi: name, rsi: argv, rdx: envp
882 *
883 * We want to fallback into:
884 * extern long sys_execve(char *name, char **argv,char **envp, struct pt_regs regs)
885 *
886 * do_sys_execve asm fallback arguments:
887 * rdi: name, rsi: argv, rdx: envp, fake frame on the stack
888 */
889ENTRY(execve)
890 CFI_STARTPROC
891 FAKE_STACK_FRAME $0
892 SAVE_ALL
893 call sys_execve
894 movq %rax, RAX(%rsp)
895 RESTORE_REST
896 testq %rax,%rax
897 je int_ret_from_sys_call
898 RESTORE_ARGS
899 UNFAKE_STACK_FRAME
900 ret
901 CFI_ENDPROC
902
Prasanna S Panchamukhi0f2fbdc2005-09-06 15:19:28 -0700903KPROBE_ENTRY(page_fault)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700904 errorentry do_page_fault
Prasanna S Panchamukhi0f2fbdc2005-09-06 15:19:28 -0700905 .previous .text
Linus Torvalds1da177e2005-04-16 15:20:36 -0700906
907ENTRY(coprocessor_error)
908 zeroentry do_coprocessor_error
909
910ENTRY(simd_coprocessor_error)
911 zeroentry do_simd_coprocessor_error
912
913ENTRY(device_not_available)
914 zeroentry math_state_restore
915
916 /* runs on exception stack */
Prasanna S Panchamukhi0f2fbdc2005-09-06 15:19:28 -0700917KPROBE_ENTRY(debug)
Jan Beulich7effaa82005-09-12 18:49:24 +0200918 INTR_FRAME
Linus Torvalds1da177e2005-04-16 15:20:36 -0700919 pushq $0
920 CFI_ADJUST_CFA_OFFSET 8
Jan Beulichb556b352006-01-11 22:43:00 +0100921 paranoidentry do_debug, DEBUG_IST
Linus Torvalds1da177e2005-04-16 15:20:36 -0700922 jmp paranoid_exit
923 CFI_ENDPROC
Prasanna S Panchamukhi0f2fbdc2005-09-06 15:19:28 -0700924 .previous .text
Linus Torvalds1da177e2005-04-16 15:20:36 -0700925
926 /* runs on exception stack */
927ENTRY(nmi)
Jan Beulich7effaa82005-09-12 18:49:24 +0200928 INTR_FRAME
Linus Torvalds1da177e2005-04-16 15:20:36 -0700929 pushq $-1
Jan Beulich7effaa82005-09-12 18:49:24 +0200930 CFI_ADJUST_CFA_OFFSET 8
Linus Torvalds1da177e2005-04-16 15:20:36 -0700931 paranoidentry do_nmi
Andi Kleen6fefb0d2005-04-16 15:25:03 -0700932 /*
933 * "Paranoid" exit path from exception stack.
934 * Paranoid because this is used by NMIs and cannot take
935 * any kernel state for granted.
936 * We don't do kernel preemption checks here, because only
937 * NMI should be common and it does not enable IRQs and
938 * cannot get reschedule ticks.
939 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700940 /* ebx: no swapgs flag */
941paranoid_exit:
942 testl %ebx,%ebx /* swapgs needed? */
943 jnz paranoid_restore
Andi Kleen6fefb0d2005-04-16 15:25:03 -0700944 testl $3,CS(%rsp)
945 jnz paranoid_userspace
Linus Torvalds1da177e2005-04-16 15:20:36 -0700946paranoid_swapgs:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700947 swapgs
948paranoid_restore:
949 RESTORE_ALL 8
950 iretq
951paranoid_userspace:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700952 GET_THREAD_INFO(%rcx)
Andi Kleen6fefb0d2005-04-16 15:25:03 -0700953 movl threadinfo_flags(%rcx),%ebx
954 andl $_TIF_WORK_MASK,%ebx
Andi Kleen11b854b2005-04-16 15:25:02 -0700955 jz paranoid_swapgs
Andi Kleen6fefb0d2005-04-16 15:25:03 -0700956 movq %rsp,%rdi /* &pt_regs */
957 call sync_regs
958 movq %rax,%rsp /* switch stack for scheduling */
959 testl $_TIF_NEED_RESCHED,%ebx
960 jnz paranoid_schedule
961 movl %ebx,%edx /* arg3: thread flags */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700962 sti
Andi Kleen6fefb0d2005-04-16 15:25:03 -0700963 xorl %esi,%esi /* arg2: oldset */
964 movq %rsp,%rdi /* arg1: &pt_regs */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700965 call do_notify_resume
Andi Kleen6fefb0d2005-04-16 15:25:03 -0700966 cli
967 jmp paranoid_userspace
968paranoid_schedule:
Andi Kleen11b854b2005-04-16 15:25:02 -0700969 sti
970 call schedule
Andi Kleen6fefb0d2005-04-16 15:25:03 -0700971 cli
972 jmp paranoid_userspace
Linus Torvalds1da177e2005-04-16 15:20:36 -0700973 CFI_ENDPROC
Andi Kleen6fefb0d2005-04-16 15:25:03 -0700974
Prasanna S Panchamukhi0f2fbdc2005-09-06 15:19:28 -0700975KPROBE_ENTRY(int3)
Jan Beulichb556b352006-01-11 22:43:00 +0100976 INTR_FRAME
977 pushq $0
978 CFI_ADJUST_CFA_OFFSET 8
979 paranoidentry do_int3, DEBUG_IST
980 jmp paranoid_exit
981 CFI_ENDPROC
Prasanna S Panchamukhi0f2fbdc2005-09-06 15:19:28 -0700982 .previous .text
Linus Torvalds1da177e2005-04-16 15:20:36 -0700983
984ENTRY(overflow)
985 zeroentry do_overflow
986
987ENTRY(bounds)
988 zeroentry do_bounds
989
990ENTRY(invalid_op)
991 zeroentry do_invalid_op
992
993ENTRY(coprocessor_segment_overrun)
994 zeroentry do_coprocessor_segment_overrun
995
996ENTRY(reserved)
997 zeroentry do_reserved
998
999 /* runs on exception stack */
1000ENTRY(double_fault)
Jan Beulich7effaa82005-09-12 18:49:24 +02001001 XCPT_FRAME
Linus Torvalds1da177e2005-04-16 15:20:36 -07001002 paranoidentry do_double_fault
Linus Torvalds1da177e2005-04-16 15:20:36 -07001003 jmp paranoid_exit
1004 CFI_ENDPROC
1005
1006ENTRY(invalid_TSS)
1007 errorentry do_invalid_TSS
1008
1009ENTRY(segment_not_present)
1010 errorentry do_segment_not_present
1011
1012 /* runs on exception stack */
1013ENTRY(stack_segment)
Jan Beulich7effaa82005-09-12 18:49:24 +02001014 XCPT_FRAME
Linus Torvalds1da177e2005-04-16 15:20:36 -07001015 paranoidentry do_stack_segment
Linus Torvalds1da177e2005-04-16 15:20:36 -07001016 jmp paranoid_exit
1017 CFI_ENDPROC
1018
Prasanna S Panchamukhi0f2fbdc2005-09-06 15:19:28 -07001019KPROBE_ENTRY(general_protection)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001020 errorentry do_general_protection
Prasanna S Panchamukhi0f2fbdc2005-09-06 15:19:28 -07001021 .previous .text
Linus Torvalds1da177e2005-04-16 15:20:36 -07001022
1023ENTRY(alignment_check)
1024 errorentry do_alignment_check
1025
1026ENTRY(divide_error)
1027 zeroentry do_divide_error
1028
1029ENTRY(spurious_interrupt_bug)
1030 zeroentry do_spurious_interrupt_bug
1031
1032#ifdef CONFIG_X86_MCE
1033 /* runs on exception stack */
1034ENTRY(machine_check)
Jan Beulich7effaa82005-09-12 18:49:24 +02001035 INTR_FRAME
Linus Torvalds1da177e2005-04-16 15:20:36 -07001036 pushq $0
1037 CFI_ADJUST_CFA_OFFSET 8
1038 paranoidentry do_machine_check
1039 jmp paranoid_exit
1040 CFI_ENDPROC
1041#endif
1042
1043ENTRY(call_debug)
1044 zeroentry do_call_debug
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