[PATCH] x86_64: Don't call do_exit with interrupts disabled after IRET exception
[deliverable/linux.git] / arch / x86_64 / kernel / entry.S
CommitLineData
1da177e4
LT
1/*
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>
e2d5df93 39#include <asm/asm-offsets.h>
1da177e4
LT
40#include <asm/msr.h>
41#include <asm/unistd.h>
42#include <asm/thread_info.h>
43#include <asm/hw_irq.h>
5f8efbb9 44#include <asm/page.h>
1da177e4
LT
45
46 .code64
47
dc37db4d 48#ifndef CONFIG_PREEMPT
1da177e4
LT
49#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 */
3829ee6b 80 xorl %eax, %eax
1da177e4
LT
81 pushq %rax /* ss */
82 CFI_ADJUST_CFA_OFFSET 8
7effaa88 83 /*CFI_REL_OFFSET ss,0*/
1da177e4
LT
84 pushq %rax /* rsp */
85 CFI_ADJUST_CFA_OFFSET 8
7effaa88 86 CFI_REL_OFFSET rsp,0
1da177e4
LT
87 pushq $(1<<9) /* eflags - interrupts on */
88 CFI_ADJUST_CFA_OFFSET 8
7effaa88 89 /*CFI_REL_OFFSET rflags,0*/
1da177e4
LT
90 pushq $__KERNEL_CS /* cs */
91 CFI_ADJUST_CFA_OFFSET 8
7effaa88 92 /*CFI_REL_OFFSET cs,0*/
1da177e4
LT
93 pushq \child_rip /* rip */
94 CFI_ADJUST_CFA_OFFSET 8
7effaa88 95 CFI_REL_OFFSET rip,0
1da177e4
LT
96 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
7effaa88
JB
105 .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*/
1da177e4
LT
132 .endm
133/*
134 * A newly forked process directly context switches into this.
135 */
136/* rdi: prev */
137ENTRY(ret_from_fork)
1da177e4
LT
138 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)
7effaa88
JB
186 CFI_STARTPROC simple
187 CFI_DEF_CFA rsp,0
188 CFI_REGISTER rip,rcx
189 /*CFI_REGISTER rflags,r11*/
1da177e4
LT
190 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)
7effaa88
JB
196 movq %rcx,RIP-ARGOFFSET(%rsp)
197 CFI_REL_OFFSET rip,RIP-ARGOFFSET
1da177e4
LT
198 GET_THREAD_INFO(%rcx)
199 testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP),threadinfo_flags(%rcx)
7effaa88 200 CFI_REMEMBER_STATE
1da177e4
LT
201 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:
11b854b2 213 movl $_TIF_ALLWORK_MASK,%edi
1da177e4
LT
214 /* edi: flagmask */
215sysret_check:
216 GET_THREAD_INFO(%rcx)
217 cli
218 movl threadinfo_flags(%rcx),%edx
219 andl %edi,%edx
7effaa88 220 CFI_REMEMBER_STATE
1da177e4
LT
221 jnz sysret_careful
222 movq RIP-ARGOFFSET(%rsp),%rcx
7effaa88 223 CFI_REGISTER rip,rcx
1da177e4 224 RESTORE_ARGS 0,-ARG_SKIP,1
7effaa88 225 /*CFI_REGISTER rflags,r11*/
1da177e4
LT
226 movq %gs:pda_oldrsp,%rsp
227 swapgs
228 sysretq
229
230 /* Handle reschedules */
231 /* edx: work, edi: workmask */
232sysret_careful:
7effaa88 233 CFI_RESTORE_STATE
1da177e4
LT
234 bt $TIF_NEED_RESCHED,%edx
235 jnc sysret_signal
236 sti
237 pushq %rdi
7effaa88 238 CFI_ADJUST_CFA_OFFSET 8
1da177e4
LT
239 call schedule
240 popq %rdi
7effaa88 241 CFI_ADJUST_CFA_OFFSET -8
1da177e4
LT
242 jmp sysret_check
243
244 /* Handle a signal */
245sysret_signal:
246 sti
10ffdbb8
AK
247 testl $(_TIF_SIGPENDING|_TIF_NOTIFY_RESUME|_TIF_SINGLESTEP),%edx
248 jz 1f
249
250 /* Really a signal */
251 /* edx: work flags (arg3) */
1da177e4
LT
252 leaq do_notify_resume(%rip),%rax
253 leaq -ARGOFFSET(%rsp),%rdi # &pt_regs -> arg1
254 xorl %esi,%esi # oldset -> arg2
255 call ptregscall_common
10ffdbb8 2561: movl $_TIF_NEED_RESCHED,%edi
1da177e4
LT
257 jmp sysret_check
258
7effaa88
JB
259badsys:
260 movq $-ENOSYS,RAX-ARGOFFSET(%rsp)
261 jmp ret_from_sys_call
262
1da177e4
LT
263 /* Do syscall tracing */
264tracesys:
7effaa88 265 CFI_RESTORE_STATE
1da177e4
LT
266 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
7effaa88 284 CFI_ENDPROC
1da177e4 285
1da177e4
LT
286/*
287 * Syscall return path ending with IRET.
288 * Has correct top of stack, but partial stack frame.
289 */
7effaa88
JB
290ENTRY(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
1da177e4
LT
307 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
bf2fcc6f 317 andl $~TS_COMPAT,threadinfo_status(%rcx)
1da177e4
LT
318 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
7effaa88 328 CFI_ADJUST_CFA_OFFSET 8
1da177e4
LT
329 call schedule
330 popq %rdi
7effaa88 331 CFI_ADJUST_CFA_OFFSET -8
cdd219cd 332 cli
1da177e4
LT
333 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
7effaa88 343 CFI_ADJUST_CFA_OFFSET 8
1da177e4
LT
344 leaq 8(%rsp),%rdi # &ptregs -> arg1
345 call syscall_trace_leave
346 popq %rdi
7effaa88 347 CFI_ADJUST_CFA_OFFSET -8
36c1104e 348 andl $~(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP),%edi
be9e6870 349 cli
1da177e4
LT
350 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
be9e6870 361 cli
1da177e4
LT
362 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
7effaa88
JB
377 CFI_STARTPROC
378
1da177e4
LT
379 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)
1da177e4 387 popq %r11
7effaa88
JB
388 CFI_ADJUST_CFA_OFFSET -8
389 CFI_REGISTER rip, r11
1da177e4
LT
390 SAVE_REST
391 movq %r11, %r15
7effaa88 392 CFI_REGISTER rip, r15
1da177e4
LT
393 FIXUP_TOP_OF_STACK %r11
394 call *%rax
395 RESTORE_TOP_OF_STACK %r11
396 movq %r15, %r11
7effaa88 397 CFI_REGISTER rip, r11
1da177e4
LT
398 RESTORE_REST
399 pushq %r11
7effaa88
JB
400 CFI_ADJUST_CFA_OFFSET 8
401 CFI_REL_OFFSET rip, 0
1da177e4
LT
402 ret
403 CFI_ENDPROC
404
405ENTRY(stub_execve)
406 CFI_STARTPROC
407 popq %r11
7effaa88
JB
408 CFI_ADJUST_CFA_OFFSET -8
409 CFI_REGISTER rip, r11
1da177e4
LT
410 SAVE_REST
411 movq %r11, %r15
7effaa88 412 CFI_REGISTER rip, r15
1da177e4
LT
413 FIXUP_TOP_OF_STACK %r11
414 call sys_execve
415 GET_THREAD_INFO(%rcx)
416 bt $TIF_IA32,threadinfo_flags(%rcx)
7effaa88 417 CFI_REMEMBER_STATE
1da177e4
LT
418 jc exec_32bit
419 RESTORE_TOP_OF_STACK %r11
420 movq %r15, %r11
7effaa88 421 CFI_REGISTER rip, r11
1da177e4 422 RESTORE_REST
7effaa88
JB
423 pushq %r11
424 CFI_ADJUST_CFA_OFFSET 8
425 CFI_REL_OFFSET rip, 0
1da177e4
LT
426 ret
427
428exec_32bit:
7effaa88 429 CFI_RESTORE_STATE
1da177e4
LT
430 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
7effaa88
JB
441 addq $8, %rsp
442 CFI_ADJUST_CFA_OFFSET -8
1da177e4
LT
443 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
7effaa88
JB
452/*
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
1da177e4
LT
471/*
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
1da177e4
LT
481 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
3829ee6b 4981: incl %gs:pda_irqcount # RED-PEN should check preempt count
1da177e4 499 movq %gs:pda_irqstackptr,%rax
7effaa88 500 cmoveq %rax,%rsp /*todo This needs CFI annotation! */
1da177e4 501 pushq %rdi # save old stack
91522a96 502#ifndef CONFIG_DEBUG_INFO
7effaa88 503 CFI_ADJUST_CFA_OFFSET 8
91522a96 504#endif
1da177e4
LT
505 call \func
506 .endm
507
508ENTRY(common_interrupt)
7effaa88 509 XCPT_FRAME
1da177e4
LT
510 interrupt do_IRQ
511 /* 0(%rsp): oldrsp-ARGOFFSET */
7effaa88 512ret_from_intr:
1da177e4 513 popq %rdi
91522a96 514#ifndef CONFIG_DEBUG_INFO
7effaa88 515 CFI_ADJUST_CFA_OFFSET -8
91522a96 516#endif
1da177e4 517 cli
3829ee6b 518 decl %gs:pda_irqcount
1da177e4
LT
519#ifdef CONFIG_DEBUG_INFO
520 movq RBP(%rdi),%rbp
7effaa88 521 CFI_DEF_CFA_REGISTER rsp
1da177e4 522#endif
7effaa88
JB
523 leaq ARGOFFSET(%rdi),%rsp /*todo This needs CFI annotation! */
524exit_intr:
1da177e4
LT
525 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
7effaa88 536retint_check:
1da177e4
LT
537 movl threadinfo_flags(%rcx),%edx
538 andl %edi,%edx
7effaa88 539 CFI_REMEMBER_STATE
1da177e4
LT
540 jnz retint_careful
541retint_swapgs:
1da177e4
LT
542 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? */
2391c4b5 557 sti
1da177e4
LT
558 jmp do_exit
559 .previous
560
7effaa88 561 /* edi: workmask, edx: work */
1da177e4 562retint_careful:
7effaa88 563 CFI_RESTORE_STATE
1da177e4
LT
564 bt $TIF_NEED_RESCHED,%edx
565 jnc retint_signal
566 sti
567 pushq %rdi
7effaa88 568 CFI_ADJUST_CFA_OFFSET 8
1da177e4
LT
569 call schedule
570 popq %rdi
7effaa88 571 CFI_ADJUST_CFA_OFFSET -8
1da177e4
LT
572 GET_THREAD_INFO(%rcx)
573 cli
574 jmp retint_check
575
576retint_signal:
10ffdbb8
AK
577 testl $(_TIF_SIGPENDING|_TIF_NOTIFY_RESUME|_TIF_SINGLESTEP),%edx
578 jz retint_swapgs
1da177e4
LT
579 sti
580 SAVE_REST
581 movq $-1,ORIG_RAX(%rsp)
3829ee6b 582 xorl %esi,%esi # oldset
1da177e4
LT
583 movq %rsp,%rdi # &pt_regs
584 call do_notify_resume
585 RESTORE_REST
586 cli
10ffdbb8 587 movl $_TIF_NEED_RESCHED,%edi
be9e6870 588 GET_THREAD_INFO(%rcx)
1da177e4
LT
589 jmp retint_check
590
591#ifdef CONFIG_PREEMPT
592 /* Returning to kernel space. Check if we need preemption */
593 /* rcx: threadinfo. interrupts off. */
594 .p2align
595retint_kernel:
596 cmpl $0,threadinfo_preempt_count(%rcx)
597 jnz retint_restore_args
598 bt $TIF_NEED_RESCHED,threadinfo_flags(%rcx)
599 jnc retint_restore_args
600 bt $9,EFLAGS-ARGOFFSET(%rsp) /* interrupts off? */
601 jnc retint_restore_args
602 call preempt_schedule_irq
603 jmp exit_intr
604#endif
605 CFI_ENDPROC
606
607/*
608 * APIC interrupts.
609 */
610 .macro apicinterrupt num,func
7effaa88 611 INTR_FRAME
1da177e4 612 pushq $\num-256
7effaa88 613 CFI_ADJUST_CFA_OFFSET 8
1da177e4
LT
614 interrupt \func
615 jmp ret_from_intr
616 CFI_ENDPROC
617 .endm
618
619ENTRY(thermal_interrupt)
620 apicinterrupt THERMAL_APIC_VECTOR,smp_thermal_interrupt
621
89b831ef
JS
622ENTRY(threshold_interrupt)
623 apicinterrupt THRESHOLD_APIC_VECTOR,mce_threshold_interrupt
624
1da177e4
LT
625#ifdef CONFIG_SMP
626ENTRY(reschedule_interrupt)
627 apicinterrupt RESCHEDULE_VECTOR,smp_reschedule_interrupt
628
e5bc8b6b
AK
629 .macro INVALIDATE_ENTRY num
630ENTRY(invalidate_interrupt\num)
631 apicinterrupt INVALIDATE_TLB_VECTOR_START+\num,smp_invalidate_interrupt
632 .endm
633
634 INVALIDATE_ENTRY 0
635 INVALIDATE_ENTRY 1
636 INVALIDATE_ENTRY 2
637 INVALIDATE_ENTRY 3
638 INVALIDATE_ENTRY 4
639 INVALIDATE_ENTRY 5
640 INVALIDATE_ENTRY 6
641 INVALIDATE_ENTRY 7
1da177e4
LT
642
643ENTRY(call_function_interrupt)
644 apicinterrupt CALL_FUNCTION_VECTOR,smp_call_function_interrupt
645#endif
646
647#ifdef CONFIG_X86_LOCAL_APIC
648ENTRY(apic_timer_interrupt)
649 apicinterrupt LOCAL_TIMER_VECTOR,smp_apic_timer_interrupt
650
651ENTRY(error_interrupt)
652 apicinterrupt ERROR_APIC_VECTOR,smp_error_interrupt
653
654ENTRY(spurious_interrupt)
655 apicinterrupt SPURIOUS_APIC_VECTOR,smp_spurious_interrupt
656#endif
657
658/*
659 * Exception entry points.
660 */
661 .macro zeroentry sym
7effaa88 662 INTR_FRAME
1da177e4 663 pushq $0 /* push error code/oldrax */
7effaa88 664 CFI_ADJUST_CFA_OFFSET 8
1da177e4 665 pushq %rax /* push real oldrax to the rdi slot */
7effaa88 666 CFI_ADJUST_CFA_OFFSET 8
1da177e4
LT
667 leaq \sym(%rip),%rax
668 jmp error_entry
7effaa88 669 CFI_ENDPROC
1da177e4
LT
670 .endm
671
672 .macro errorentry sym
7effaa88 673 XCPT_FRAME
1da177e4 674 pushq %rax
7effaa88 675 CFI_ADJUST_CFA_OFFSET 8
1da177e4
LT
676 leaq \sym(%rip),%rax
677 jmp error_entry
7effaa88 678 CFI_ENDPROC
1da177e4
LT
679 .endm
680
681 /* error code is on the stack already */
682 /* handle NMI like exceptions that can happen everywhere */
b556b35e 683 .macro paranoidentry sym, ist=0
1da177e4
LT
684 SAVE_ALL
685 cld
686 movl $1,%ebx
687 movl $MSR_GS_BASE,%ecx
688 rdmsr
689 testl %edx,%edx
690 js 1f
691 swapgs
692 xorl %ebx,%ebx
b556b35e
JB
6931:
694 .if \ist
695 movq %gs:pda_data_offset, %rbp
696 .endif
697 movq %rsp,%rdi
1da177e4
LT
698 movq ORIG_RAX(%rsp),%rsi
699 movq $-1,ORIG_RAX(%rsp)
b556b35e 700 .if \ist
5f8efbb9 701 subq $EXCEPTION_STKSZ, per_cpu__init_tss + TSS_ist + (\ist - 1) * 8(%rbp)
b556b35e 702 .endif
1da177e4 703 call \sym
b556b35e 704 .if \ist
5f8efbb9 705 addq $EXCEPTION_STKSZ, per_cpu__init_tss + TSS_ist + (\ist - 1) * 8(%rbp)
b556b35e 706 .endif
6fefb0d1 707 cli
1da177e4
LT
708 .endm
709
710/*
711 * Exception entry point. This expects an error code/orig_rax on the stack
712 * and the exception handler in %rax.
713 */
714ENTRY(error_entry)
7effaa88 715 _frame RDI
1da177e4
LT
716 /* rdi slot contains rax, oldrax contains error code */
717 cld
718 subq $14*8,%rsp
719 CFI_ADJUST_CFA_OFFSET (14*8)
720 movq %rsi,13*8(%rsp)
721 CFI_REL_OFFSET rsi,RSI
722 movq 14*8(%rsp),%rsi /* load rax from rdi slot */
723 movq %rdx,12*8(%rsp)
724 CFI_REL_OFFSET rdx,RDX
725 movq %rcx,11*8(%rsp)
726 CFI_REL_OFFSET rcx,RCX
727 movq %rsi,10*8(%rsp) /* store rax */
728 CFI_REL_OFFSET rax,RAX
729 movq %r8, 9*8(%rsp)
730 CFI_REL_OFFSET r8,R8
731 movq %r9, 8*8(%rsp)
732 CFI_REL_OFFSET r9,R9
733 movq %r10,7*8(%rsp)
734 CFI_REL_OFFSET r10,R10
735 movq %r11,6*8(%rsp)
736 CFI_REL_OFFSET r11,R11
737 movq %rbx,5*8(%rsp)
738 CFI_REL_OFFSET rbx,RBX
739 movq %rbp,4*8(%rsp)
740 CFI_REL_OFFSET rbp,RBP
741 movq %r12,3*8(%rsp)
742 CFI_REL_OFFSET r12,R12
743 movq %r13,2*8(%rsp)
744 CFI_REL_OFFSET r13,R13
745 movq %r14,1*8(%rsp)
746 CFI_REL_OFFSET r14,R14
747 movq %r15,(%rsp)
748 CFI_REL_OFFSET r15,R15
749 xorl %ebx,%ebx
750 testl $3,CS(%rsp)
751 je error_kernelspace
752error_swapgs:
753 swapgs
754error_sti:
755 movq %rdi,RDI(%rsp)
756 movq %rsp,%rdi
757 movq ORIG_RAX(%rsp),%rsi /* get error code */
758 movq $-1,ORIG_RAX(%rsp)
759 call *%rax
760 /* ebx: no swapgs flag (1: don't need swapgs, 0: need it) */
761error_exit:
762 movl %ebx,%eax
763 RESTORE_REST
764 cli
765 GET_THREAD_INFO(%rcx)
766 testl %eax,%eax
767 jne retint_kernel
768 movl threadinfo_flags(%rcx),%edx
769 movl $_TIF_WORK_MASK,%edi
770 andl %edi,%edx
771 jnz retint_careful
772 swapgs
773 RESTORE_ARGS 0,8,0
505cc4e1 774 jmp iret_label
1da177e4
LT
775 CFI_ENDPROC
776
777error_kernelspace:
778 incl %ebx
779 /* There are two places in the kernel that can potentially fault with
780 usergs. Handle them here. The exception handlers after
781 iret run with kernel gs again, so don't set the user space flag.
782 B stepping K8s sometimes report an truncated RIP for IRET
783 exceptions returning to compat mode. Check for these here too. */
784 leaq iret_label(%rip),%rbp
785 cmpq %rbp,RIP(%rsp)
786 je error_swapgs
787 movl %ebp,%ebp /* zero extend */
788 cmpq %rbp,RIP(%rsp)
789 je error_swapgs
790 cmpq $gs_change,RIP(%rsp)
791 je error_swapgs
792 jmp error_sti
793
794 /* Reload gs selector with exception handling */
795 /* edi: new selector */
796ENTRY(load_gs_index)
7effaa88 797 CFI_STARTPROC
1da177e4 798 pushf
7effaa88 799 CFI_ADJUST_CFA_OFFSET 8
1da177e4
LT
800 cli
801 swapgs
802gs_change:
803 movl %edi,%gs
8042: mfence /* workaround */
805 swapgs
806 popf
7effaa88 807 CFI_ADJUST_CFA_OFFSET -8
1da177e4 808 ret
7effaa88 809 CFI_ENDPROC
1da177e4
LT
810
811 .section __ex_table,"a"
812 .align 8
813 .quad gs_change,bad_gs
814 .previous
815 .section .fixup,"ax"
816 /* running with kernelgs */
817bad_gs:
818 swapgs /* switch back to user gs */
819 xorl %eax,%eax
820 movl %eax,%gs
821 jmp 2b
822 .previous
823
824/*
825 * Create a kernel thread.
826 *
827 * C extern interface:
828 * extern long kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
829 *
830 * asm input arguments:
831 * rdi: fn, rsi: arg, rdx: flags
832 */
833ENTRY(kernel_thread)
834 CFI_STARTPROC
835 FAKE_STACK_FRAME $child_rip
836 SAVE_ALL
837
838 # rdi: flags, rsi: usp, rdx: will be &pt_regs
839 movq %rdx,%rdi
840 orq kernel_thread_flags(%rip),%rdi
841 movq $-1, %rsi
842 movq %rsp, %rdx
843
844 xorl %r8d,%r8d
845 xorl %r9d,%r9d
846
847 # clone now
848 call do_fork
849 movq %rax,RAX(%rsp)
850 xorl %edi,%edi
851
852 /*
853 * It isn't worth to check for reschedule here,
854 * so internally to the x86_64 port you can rely on kernel_thread()
855 * not to reschedule the child before returning, this avoids the need
856 * of hacks for example to fork off the per-CPU idle tasks.
857 * [Hopefully no generic code relies on the reschedule -AK]
858 */
859 RESTORE_ALL
860 UNFAKE_STACK_FRAME
861 ret
862 CFI_ENDPROC
863
864
865child_rip:
866 /*
867 * Here we are in the child and the registers are set as they were
868 * at kernel_thread() invocation in the parent.
869 */
870 movq %rdi, %rax
871 movq %rsi, %rdi
872 call *%rax
873 # exit
3829ee6b 874 xorl %edi, %edi
1da177e4
LT
875 call do_exit
876
877/*
878 * execve(). This function needs to use IRET, not SYSRET, to set up all state properly.
879 *
880 * C extern interface:
881 * extern long execve(char *name, char **argv, char **envp)
882 *
883 * asm input arguments:
884 * rdi: name, rsi: argv, rdx: envp
885 *
886 * We want to fallback into:
887 * extern long sys_execve(char *name, char **argv,char **envp, struct pt_regs regs)
888 *
889 * do_sys_execve asm fallback arguments:
890 * rdi: name, rsi: argv, rdx: envp, fake frame on the stack
891 */
892ENTRY(execve)
893 CFI_STARTPROC
894 FAKE_STACK_FRAME $0
895 SAVE_ALL
896 call sys_execve
897 movq %rax, RAX(%rsp)
898 RESTORE_REST
899 testq %rax,%rax
900 je int_ret_from_sys_call
901 RESTORE_ARGS
902 UNFAKE_STACK_FRAME
903 ret
904 CFI_ENDPROC
905
0f2fbdcb 906KPROBE_ENTRY(page_fault)
1da177e4 907 errorentry do_page_fault
0f2fbdcb 908 .previous .text
1da177e4
LT
909
910ENTRY(coprocessor_error)
911 zeroentry do_coprocessor_error
912
913ENTRY(simd_coprocessor_error)
914 zeroentry do_simd_coprocessor_error
915
916ENTRY(device_not_available)
917 zeroentry math_state_restore
918
919 /* runs on exception stack */
0f2fbdcb 920KPROBE_ENTRY(debug)
7effaa88 921 INTR_FRAME
1da177e4
LT
922 pushq $0
923 CFI_ADJUST_CFA_OFFSET 8
5f8efbb9 924 paranoidentry do_debug, DEBUG_STACK
1da177e4
LT
925 jmp paranoid_exit
926 CFI_ENDPROC
0f2fbdcb 927 .previous .text
1da177e4
LT
928
929 /* runs on exception stack */
eddb6fb9 930KPROBE_ENTRY(nmi)
7effaa88 931 INTR_FRAME
1da177e4 932 pushq $-1
7effaa88 933 CFI_ADJUST_CFA_OFFSET 8
1da177e4 934 paranoidentry do_nmi
6fefb0d1
AK
935 /*
936 * "Paranoid" exit path from exception stack.
937 * Paranoid because this is used by NMIs and cannot take
938 * any kernel state for granted.
939 * We don't do kernel preemption checks here, because only
940 * NMI should be common and it does not enable IRQs and
941 * cannot get reschedule ticks.
942 */
1da177e4
LT
943 /* ebx: no swapgs flag */
944paranoid_exit:
945 testl %ebx,%ebx /* swapgs needed? */
946 jnz paranoid_restore
6fefb0d1
AK
947 testl $3,CS(%rsp)
948 jnz paranoid_userspace
1da177e4 949paranoid_swapgs:
1da177e4
LT
950 swapgs
951paranoid_restore:
952 RESTORE_ALL 8
953 iretq
954paranoid_userspace:
1da177e4 955 GET_THREAD_INFO(%rcx)
6fefb0d1
AK
956 movl threadinfo_flags(%rcx),%ebx
957 andl $_TIF_WORK_MASK,%ebx
11b854b2 958 jz paranoid_swapgs
6fefb0d1
AK
959 movq %rsp,%rdi /* &pt_regs */
960 call sync_regs
961 movq %rax,%rsp /* switch stack for scheduling */
962 testl $_TIF_NEED_RESCHED,%ebx
963 jnz paranoid_schedule
964 movl %ebx,%edx /* arg3: thread flags */
1da177e4 965 sti
6fefb0d1
AK
966 xorl %esi,%esi /* arg2: oldset */
967 movq %rsp,%rdi /* arg1: &pt_regs */
1da177e4 968 call do_notify_resume
6fefb0d1
AK
969 cli
970 jmp paranoid_userspace
971paranoid_schedule:
11b854b2
AK
972 sti
973 call schedule
6fefb0d1
AK
974 cli
975 jmp paranoid_userspace
1da177e4 976 CFI_ENDPROC
eddb6fb9 977 .previous .text
6fefb0d1 978
0f2fbdcb 979KPROBE_ENTRY(int3)
b556b35e
JB
980 INTR_FRAME
981 pushq $0
982 CFI_ADJUST_CFA_OFFSET 8
5f8efbb9 983 paranoidentry do_int3, DEBUG_STACK
b556b35e
JB
984 jmp paranoid_exit
985 CFI_ENDPROC
0f2fbdcb 986 .previous .text
1da177e4
LT
987
988ENTRY(overflow)
989 zeroentry do_overflow
990
991ENTRY(bounds)
992 zeroentry do_bounds
993
994ENTRY(invalid_op)
995 zeroentry do_invalid_op
996
997ENTRY(coprocessor_segment_overrun)
998 zeroentry do_coprocessor_segment_overrun
999
1000ENTRY(reserved)
1001 zeroentry do_reserved
1002
1003 /* runs on exception stack */
1004ENTRY(double_fault)
7effaa88 1005 XCPT_FRAME
1da177e4 1006 paranoidentry do_double_fault
1da177e4
LT
1007 jmp paranoid_exit
1008 CFI_ENDPROC
1009
1010ENTRY(invalid_TSS)
1011 errorentry do_invalid_TSS
1012
1013ENTRY(segment_not_present)
1014 errorentry do_segment_not_present
1015
1016 /* runs on exception stack */
1017ENTRY(stack_segment)
7effaa88 1018 XCPT_FRAME
1da177e4 1019 paranoidentry do_stack_segment
1da177e4
LT
1020 jmp paranoid_exit
1021 CFI_ENDPROC
1022
0f2fbdcb 1023KPROBE_ENTRY(general_protection)
1da177e4 1024 errorentry do_general_protection
0f2fbdcb 1025 .previous .text
1da177e4
LT
1026
1027ENTRY(alignment_check)
1028 errorentry do_alignment_check
1029
1030ENTRY(divide_error)
1031 zeroentry do_divide_error
1032
1033ENTRY(spurious_interrupt_bug)
1034 zeroentry do_spurious_interrupt_bug
1035
1036#ifdef CONFIG_X86_MCE
1037 /* runs on exception stack */
1038ENTRY(machine_check)
7effaa88 1039 INTR_FRAME
1da177e4
LT
1040 pushq $0
1041 CFI_ADJUST_CFA_OFFSET 8
1042 paranoidentry do_machine_check
1043 jmp paranoid_exit
1044 CFI_ENDPROC
1045#endif
1046
ed6b676c 1047ENTRY(call_softirq)
7effaa88 1048 CFI_STARTPROC
ed6b676c 1049 movq %gs:pda_irqstackptr,%rax
bd9cb64d
JB
1050 movq %rsp,%rdx
1051 CFI_DEF_CFA_REGISTER rdx
ed6b676c
AK
1052 incl %gs:pda_irqcount
1053 cmove %rax,%rsp
bd9cb64d
JB
1054 pushq %rdx
1055 /*todo CFI_DEF_CFA_EXPRESSION ...*/
ed6b676c 1056 call __do_softirq
bd9cb64d 1057 popq %rsp
7effaa88 1058 CFI_DEF_CFA_REGISTER rsp
ed6b676c 1059 decl %gs:pda_irqcount
ed6b676c 1060 ret
7effaa88 1061 CFI_ENDPROC
This page took 0.15651 seconds and 5 git commands to generate.