]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blame - arch/x86_64/kernel/entry.S
[PATCH] lockdep: irqtrace cleanup of include/asm-i386/irqflags.h
[mirror_ubuntu-bionic-kernel.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
1da177e4
LT
31#include <linux/linkage.h>
32#include <asm/segment.h>
33#include <asm/smp.h>
34#include <asm/cache.h>
35#include <asm/errno.h>
36#include <asm/dwarf2.h>
37#include <asm/calling.h>
e2d5df93 38#include <asm/asm-offsets.h>
1da177e4
LT
39#include <asm/msr.h>
40#include <asm/unistd.h>
41#include <asm/thread_info.h>
42#include <asm/hw_irq.h>
5f8efbb9 43#include <asm/page.h>
1da177e4
LT
44
45 .code64
46
dc37db4d 47#ifndef CONFIG_PREEMPT
1da177e4
LT
48#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 */
3829ee6b 79 xorl %eax, %eax
1da177e4
LT
80 pushq %rax /* ss */
81 CFI_ADJUST_CFA_OFFSET 8
7effaa88 82 /*CFI_REL_OFFSET ss,0*/
1da177e4
LT
83 pushq %rax /* rsp */
84 CFI_ADJUST_CFA_OFFSET 8
7effaa88 85 CFI_REL_OFFSET rsp,0
1da177e4
LT
86 pushq $(1<<9) /* eflags - interrupts on */
87 CFI_ADJUST_CFA_OFFSET 8
7effaa88 88 /*CFI_REL_OFFSET rflags,0*/
1da177e4
LT
89 pushq $__KERNEL_CS /* cs */
90 CFI_ADJUST_CFA_OFFSET 8
7effaa88 91 /*CFI_REL_OFFSET cs,0*/
1da177e4
LT
92 pushq \child_rip /* rip */
93 CFI_ADJUST_CFA_OFFSET 8
7effaa88 94 CFI_REL_OFFSET rip,0
1da177e4
LT
95 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
7effaa88
JB
104 .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*/
1da177e4
LT
131 .endm
132/*
133 * A newly forked process directly context switches into this.
134 */
135/* rdi: prev */
136ENTRY(ret_from_fork)
1da177e4
LT
137 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
4b787e0b 156END(ret_from_fork)
1da177e4
LT
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.
7bf36bbc
AK
183 *
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.
1da177e4
LT
187 */
188
189ENTRY(system_call)
7effaa88 190 CFI_STARTPROC simple
dffead4e 191 CFI_DEF_CFA rsp,PDA_STACKOFFSET
7effaa88
JB
192 CFI_REGISTER rip,rcx
193 /*CFI_REGISTER rflags,r11*/
1da177e4
LT
194 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)
7effaa88
JB
200 movq %rcx,RIP-ARGOFFSET(%rsp)
201 CFI_REL_OFFSET rip,RIP-ARGOFFSET
1da177e4
LT
202 GET_THREAD_INFO(%rcx)
203 testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP),threadinfo_flags(%rcx)
7effaa88 204 CFI_REMEMBER_STATE
1da177e4
LT
205 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:
11b854b2 217 movl $_TIF_ALLWORK_MASK,%edi
1da177e4
LT
218 /* edi: flagmask */
219sysret_check:
220 GET_THREAD_INFO(%rcx)
221 cli
222 movl threadinfo_flags(%rcx),%edx
223 andl %edi,%edx
7effaa88 224 CFI_REMEMBER_STATE
1da177e4
LT
225 jnz sysret_careful
226 movq RIP-ARGOFFSET(%rsp),%rcx
7effaa88 227 CFI_REGISTER rip,rcx
1da177e4 228 RESTORE_ARGS 0,-ARG_SKIP,1
7effaa88 229 /*CFI_REGISTER rflags,r11*/
1da177e4
LT
230 movq %gs:pda_oldrsp,%rsp
231 swapgs
232 sysretq
233
234 /* Handle reschedules */
235 /* edx: work, edi: workmask */
236sysret_careful:
7effaa88 237 CFI_RESTORE_STATE
1da177e4
LT
238 bt $TIF_NEED_RESCHED,%edx
239 jnc sysret_signal
240 sti
241 pushq %rdi
7effaa88 242 CFI_ADJUST_CFA_OFFSET 8
1da177e4
LT
243 call schedule
244 popq %rdi
7effaa88 245 CFI_ADJUST_CFA_OFFSET -8
1da177e4
LT
246 jmp sysret_check
247
248 /* Handle a signal */
249sysret_signal:
250 sti
10ffdbb8
AK
251 testl $(_TIF_SIGPENDING|_TIF_NOTIFY_RESUME|_TIF_SINGLESTEP),%edx
252 jz 1f
253
254 /* Really a signal */
255 /* edx: work flags (arg3) */
1da177e4
LT
256 leaq do_notify_resume(%rip),%rax
257 leaq -ARGOFFSET(%rsp),%rdi # &pt_regs -> arg1
258 xorl %esi,%esi # oldset -> arg2
259 call ptregscall_common
10ffdbb8 2601: movl $_TIF_NEED_RESCHED,%edi
7bf36bbc
AK
261 /* 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
1da177e4 265
7effaa88
JB
266badsys:
267 movq $-ENOSYS,RAX-ARGOFFSET(%rsp)
268 jmp ret_from_sys_call
269
1da177e4
LT
270 /* Do syscall tracing */
271tracesys:
7effaa88 272 CFI_RESTORE_STATE
1da177e4
LT
273 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)
822ff019 2841: movq %rax,RAX-ARGOFFSET(%rsp)
7bf36bbc
AK
285 /* Use IRET because user could have changed frame */
286 jmp int_ret_from_sys_call
7effaa88 287 CFI_ENDPROC
4b787e0b 288END(system_call)
1da177e4 289
1da177e4
LT
290/*
291 * Syscall return path ending with IRET.
292 * Has correct top of stack, but partial stack frame.
293 */
7effaa88
JB
294ENTRY(int_ret_from_sys_call)
295 CFI_STARTPROC simple
296 CFI_DEF_CFA rsp,SS+8-ARGOFFSET
297 /*CFI_REL_OFFSET ss,SS-ARGOFFSET*/
298 CFI_REL_OFFSET rsp,RSP-ARGOFFSET
299 /*CFI_REL_OFFSET rflags,EFLAGS-ARGOFFSET*/
300 /*CFI_REL_OFFSET cs,CS-ARGOFFSET*/
301 CFI_REL_OFFSET rip,RIP-ARGOFFSET
302 CFI_REL_OFFSET rdx,RDX-ARGOFFSET
303 CFI_REL_OFFSET rcx,RCX-ARGOFFSET
304 CFI_REL_OFFSET rax,RAX-ARGOFFSET
305 CFI_REL_OFFSET rdi,RDI-ARGOFFSET
306 CFI_REL_OFFSET rsi,RSI-ARGOFFSET
307 CFI_REL_OFFSET r8,R8-ARGOFFSET
308 CFI_REL_OFFSET r9,R9-ARGOFFSET
309 CFI_REL_OFFSET r10,R10-ARGOFFSET
310 CFI_REL_OFFSET r11,R11-ARGOFFSET
1da177e4
LT
311 cli
312 testl $3,CS-ARGOFFSET(%rsp)
313 je retint_restore_args
314 movl $_TIF_ALLWORK_MASK,%edi
315 /* edi: mask to check */
316int_with_check:
317 GET_THREAD_INFO(%rcx)
318 movl threadinfo_flags(%rcx),%edx
319 andl %edi,%edx
320 jnz int_careful
bf2fcc6f 321 andl $~TS_COMPAT,threadinfo_status(%rcx)
1da177e4
LT
322 jmp retint_swapgs
323
324 /* Either reschedule or signal or syscall exit tracking needed. */
325 /* First do a reschedule test. */
326 /* edx: work, edi: workmask */
327int_careful:
328 bt $TIF_NEED_RESCHED,%edx
329 jnc int_very_careful
330 sti
331 pushq %rdi
7effaa88 332 CFI_ADJUST_CFA_OFFSET 8
1da177e4
LT
333 call schedule
334 popq %rdi
7effaa88 335 CFI_ADJUST_CFA_OFFSET -8
cdd219cd 336 cli
1da177e4
LT
337 jmp int_with_check
338
339 /* handle signals and tracing -- both require a full stack frame */
340int_very_careful:
341 sti
342 SAVE_REST
343 /* Check for syscall exit trace */
344 testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP),%edx
345 jz int_signal
346 pushq %rdi
7effaa88 347 CFI_ADJUST_CFA_OFFSET 8
1da177e4
LT
348 leaq 8(%rsp),%rdi # &ptregs -> arg1
349 call syscall_trace_leave
350 popq %rdi
7effaa88 351 CFI_ADJUST_CFA_OFFSET -8
36c1104e 352 andl $~(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP),%edi
be9e6870 353 cli
1da177e4
LT
354 jmp int_restore_rest
355
356int_signal:
357 testl $(_TIF_NOTIFY_RESUME|_TIF_SIGPENDING|_TIF_SINGLESTEP),%edx
358 jz 1f
359 movq %rsp,%rdi # &ptregs -> arg1
360 xorl %esi,%esi # oldset -> arg2
361 call do_notify_resume
3621: movl $_TIF_NEED_RESCHED,%edi
363int_restore_rest:
364 RESTORE_REST
be9e6870 365 cli
1da177e4
LT
366 jmp int_with_check
367 CFI_ENDPROC
4b787e0b 368END(int_ret_from_sys_call)
1da177e4
LT
369
370/*
371 * Certain special system calls that need to save a complete full stack frame.
372 */
373
374 .macro PTREGSCALL label,func,arg
375 .globl \label
376\label:
377 leaq \func(%rip),%rax
378 leaq -ARGOFFSET+8(%rsp),\arg /* 8 for return address */
379 jmp ptregscall_common
4b787e0b 380END(\label)
1da177e4
LT
381 .endm
382
7effaa88
JB
383 CFI_STARTPROC
384
1da177e4
LT
385 PTREGSCALL stub_clone, sys_clone, %r8
386 PTREGSCALL stub_fork, sys_fork, %rdi
387 PTREGSCALL stub_vfork, sys_vfork, %rdi
388 PTREGSCALL stub_rt_sigsuspend, sys_rt_sigsuspend, %rdx
389 PTREGSCALL stub_sigaltstack, sys_sigaltstack, %rdx
390 PTREGSCALL stub_iopl, sys_iopl, %rsi
391
392ENTRY(ptregscall_common)
1da177e4 393 popq %r11
7effaa88
JB
394 CFI_ADJUST_CFA_OFFSET -8
395 CFI_REGISTER rip, r11
1da177e4
LT
396 SAVE_REST
397 movq %r11, %r15
7effaa88 398 CFI_REGISTER rip, r15
1da177e4
LT
399 FIXUP_TOP_OF_STACK %r11
400 call *%rax
401 RESTORE_TOP_OF_STACK %r11
402 movq %r15, %r11
7effaa88 403 CFI_REGISTER rip, r11
1da177e4
LT
404 RESTORE_REST
405 pushq %r11
7effaa88
JB
406 CFI_ADJUST_CFA_OFFSET 8
407 CFI_REL_OFFSET rip, 0
1da177e4
LT
408 ret
409 CFI_ENDPROC
4b787e0b 410END(ptregscall_common)
1da177e4
LT
411
412ENTRY(stub_execve)
413 CFI_STARTPROC
414 popq %r11
7effaa88
JB
415 CFI_ADJUST_CFA_OFFSET -8
416 CFI_REGISTER rip, r11
1da177e4 417 SAVE_REST
1da177e4
LT
418 FIXUP_TOP_OF_STACK %r11
419 call sys_execve
1da177e4 420 RESTORE_TOP_OF_STACK %r11
1da177e4
LT
421 movq %rax,RAX(%rsp)
422 RESTORE_REST
423 jmp int_ret_from_sys_call
424 CFI_ENDPROC
4b787e0b 425END(stub_execve)
1da177e4
LT
426
427/*
428 * sigreturn is special because it needs to restore all registers on return.
429 * This cannot be done with SYSRET, so use the IRET return path instead.
430 */
431ENTRY(stub_rt_sigreturn)
432 CFI_STARTPROC
7effaa88
JB
433 addq $8, %rsp
434 CFI_ADJUST_CFA_OFFSET -8
1da177e4
LT
435 SAVE_REST
436 movq %rsp,%rdi
437 FIXUP_TOP_OF_STACK %r11
438 call sys_rt_sigreturn
439 movq %rax,RAX(%rsp) # fixme, this could be done at the higher layer
440 RESTORE_REST
441 jmp int_ret_from_sys_call
442 CFI_ENDPROC
4b787e0b 443END(stub_rt_sigreturn)
1da177e4 444
7effaa88
JB
445/*
446 * initial frame state for interrupts and exceptions
447 */
448 .macro _frame ref
449 CFI_STARTPROC simple
450 CFI_DEF_CFA rsp,SS+8-\ref
451 /*CFI_REL_OFFSET ss,SS-\ref*/
452 CFI_REL_OFFSET rsp,RSP-\ref
453 /*CFI_REL_OFFSET rflags,EFLAGS-\ref*/
454 /*CFI_REL_OFFSET cs,CS-\ref*/
455 CFI_REL_OFFSET rip,RIP-\ref
456 .endm
457
458/* initial frame state for interrupts (and exceptions without error code) */
459#define INTR_FRAME _frame RIP
460/* initial frame state for exceptions with error code (and interrupts with
461 vector already pushed) */
462#define XCPT_FRAME _frame ORIG_RAX
463
1da177e4
LT
464/*
465 * Interrupt entry/exit.
466 *
467 * Interrupt entry points save only callee clobbered registers in fast path.
468 *
469 * Entry runs with interrupts off.
470 */
471
472/* 0(%rsp): interrupt number */
473 .macro interrupt func
1da177e4 474 cld
1da177e4
LT
475 SAVE_ARGS
476 leaq -ARGOFFSET(%rsp),%rdi # arg1 for handler
1de9c3f6
JB
477 pushq %rbp
478 CFI_ADJUST_CFA_OFFSET 8
479 CFI_REL_OFFSET rbp, 0
480 movq %rsp,%rbp
481 CFI_DEF_CFA_REGISTER rbp
1da177e4
LT
482 testl $3,CS(%rdi)
483 je 1f
484 swapgs
3829ee6b 4851: incl %gs:pda_irqcount # RED-PEN should check preempt count
1de9c3f6 486 cmoveq %gs:pda_irqstackptr,%rsp
1da177e4
LT
487 call \func
488 .endm
489
490ENTRY(common_interrupt)
7effaa88 491 XCPT_FRAME
1da177e4
LT
492 interrupt do_IRQ
493 /* 0(%rsp): oldrsp-ARGOFFSET */
7effaa88 494ret_from_intr:
1da177e4 495 cli
3829ee6b 496 decl %gs:pda_irqcount
1de9c3f6 497 leaveq
7effaa88 498 CFI_DEF_CFA_REGISTER rsp
1de9c3f6 499 CFI_ADJUST_CFA_OFFSET -8
7effaa88 500exit_intr:
1da177e4
LT
501 GET_THREAD_INFO(%rcx)
502 testl $3,CS-ARGOFFSET(%rsp)
503 je retint_kernel
504
505 /* Interrupt came from user space */
506 /*
507 * Has a correct top of stack, but a partial stack frame
508 * %rcx: thread info. Interrupts off.
509 */
510retint_with_reschedule:
511 movl $_TIF_WORK_MASK,%edi
7effaa88 512retint_check:
1da177e4
LT
513 movl threadinfo_flags(%rcx),%edx
514 andl %edi,%edx
7effaa88 515 CFI_REMEMBER_STATE
1da177e4
LT
516 jnz retint_careful
517retint_swapgs:
1da177e4
LT
518 swapgs
519retint_restore_args:
520 cli
521 RESTORE_ARGS 0,8,0
522iret_label:
523 iretq
524
525 .section __ex_table,"a"
526 .quad iret_label,bad_iret
527 .previous
528 .section .fixup,"ax"
529 /* force a signal here? this matches i386 behaviour */
530 /* running with kernel gs */
531bad_iret:
3076a492 532 movq $11,%rdi /* SIGSEGV */
2391c4b5 533 sti
1da177e4
LT
534 jmp do_exit
535 .previous
536
7effaa88 537 /* edi: workmask, edx: work */
1da177e4 538retint_careful:
7effaa88 539 CFI_RESTORE_STATE
1da177e4
LT
540 bt $TIF_NEED_RESCHED,%edx
541 jnc retint_signal
542 sti
543 pushq %rdi
7effaa88 544 CFI_ADJUST_CFA_OFFSET 8
1da177e4
LT
545 call schedule
546 popq %rdi
7effaa88 547 CFI_ADJUST_CFA_OFFSET -8
1da177e4
LT
548 GET_THREAD_INFO(%rcx)
549 cli
550 jmp retint_check
551
552retint_signal:
10ffdbb8
AK
553 testl $(_TIF_SIGPENDING|_TIF_NOTIFY_RESUME|_TIF_SINGLESTEP),%edx
554 jz retint_swapgs
1da177e4
LT
555 sti
556 SAVE_REST
557 movq $-1,ORIG_RAX(%rsp)
3829ee6b 558 xorl %esi,%esi # oldset
1da177e4
LT
559 movq %rsp,%rdi # &pt_regs
560 call do_notify_resume
561 RESTORE_REST
562 cli
10ffdbb8 563 movl $_TIF_NEED_RESCHED,%edi
be9e6870 564 GET_THREAD_INFO(%rcx)
1da177e4
LT
565 jmp retint_check
566
567#ifdef CONFIG_PREEMPT
568 /* Returning to kernel space. Check if we need preemption */
569 /* rcx: threadinfo. interrupts off. */
570 .p2align
571retint_kernel:
572 cmpl $0,threadinfo_preempt_count(%rcx)
573 jnz retint_restore_args
574 bt $TIF_NEED_RESCHED,threadinfo_flags(%rcx)
575 jnc retint_restore_args
576 bt $9,EFLAGS-ARGOFFSET(%rsp) /* interrupts off? */
577 jnc retint_restore_args
578 call preempt_schedule_irq
579 jmp exit_intr
580#endif
4b787e0b 581
1da177e4 582 CFI_ENDPROC
4b787e0b 583END(common_interrupt)
1da177e4
LT
584
585/*
586 * APIC interrupts.
587 */
588 .macro apicinterrupt num,func
7effaa88 589 INTR_FRAME
19eadf98 590 pushq $~(\num)
7effaa88 591 CFI_ADJUST_CFA_OFFSET 8
1da177e4
LT
592 interrupt \func
593 jmp ret_from_intr
594 CFI_ENDPROC
595 .endm
596
597ENTRY(thermal_interrupt)
598 apicinterrupt THERMAL_APIC_VECTOR,smp_thermal_interrupt
4b787e0b 599END(thermal_interrupt)
1da177e4 600
89b831ef
JS
601ENTRY(threshold_interrupt)
602 apicinterrupt THRESHOLD_APIC_VECTOR,mce_threshold_interrupt
4b787e0b 603END(threshold_interrupt)
89b831ef 604
1da177e4
LT
605#ifdef CONFIG_SMP
606ENTRY(reschedule_interrupt)
607 apicinterrupt RESCHEDULE_VECTOR,smp_reschedule_interrupt
4b787e0b 608END(reschedule_interrupt)
1da177e4 609
e5bc8b6b
AK
610 .macro INVALIDATE_ENTRY num
611ENTRY(invalidate_interrupt\num)
612 apicinterrupt INVALIDATE_TLB_VECTOR_START+\num,smp_invalidate_interrupt
4b787e0b 613END(invalidate_interrupt\num)
e5bc8b6b
AK
614 .endm
615
616 INVALIDATE_ENTRY 0
617 INVALIDATE_ENTRY 1
618 INVALIDATE_ENTRY 2
619 INVALIDATE_ENTRY 3
620 INVALIDATE_ENTRY 4
621 INVALIDATE_ENTRY 5
622 INVALIDATE_ENTRY 6
623 INVALIDATE_ENTRY 7
1da177e4
LT
624
625ENTRY(call_function_interrupt)
626 apicinterrupt CALL_FUNCTION_VECTOR,smp_call_function_interrupt
4b787e0b 627END(call_function_interrupt)
1da177e4
LT
628#endif
629
630#ifdef CONFIG_X86_LOCAL_APIC
631ENTRY(apic_timer_interrupt)
632 apicinterrupt LOCAL_TIMER_VECTOR,smp_apic_timer_interrupt
4b787e0b 633END(apic_timer_interrupt)
1da177e4
LT
634
635ENTRY(error_interrupt)
636 apicinterrupt ERROR_APIC_VECTOR,smp_error_interrupt
4b787e0b 637END(error_interrupt)
1da177e4
LT
638
639ENTRY(spurious_interrupt)
640 apicinterrupt SPURIOUS_APIC_VECTOR,smp_spurious_interrupt
4b787e0b 641END(spurious_interrupt)
1da177e4
LT
642#endif
643
644/*
645 * Exception entry points.
646 */
647 .macro zeroentry sym
7effaa88 648 INTR_FRAME
1da177e4 649 pushq $0 /* push error code/oldrax */
7effaa88 650 CFI_ADJUST_CFA_OFFSET 8
1da177e4 651 pushq %rax /* push real oldrax to the rdi slot */
7effaa88 652 CFI_ADJUST_CFA_OFFSET 8
1da177e4
LT
653 leaq \sym(%rip),%rax
654 jmp error_entry
7effaa88 655 CFI_ENDPROC
1da177e4
LT
656 .endm
657
658 .macro errorentry sym
7effaa88 659 XCPT_FRAME
1da177e4 660 pushq %rax
7effaa88 661 CFI_ADJUST_CFA_OFFSET 8
1da177e4
LT
662 leaq \sym(%rip),%rax
663 jmp error_entry
7effaa88 664 CFI_ENDPROC
1da177e4
LT
665 .endm
666
667 /* error code is on the stack already */
668 /* handle NMI like exceptions that can happen everywhere */
b556b35e 669 .macro paranoidentry sym, ist=0
1da177e4
LT
670 SAVE_ALL
671 cld
672 movl $1,%ebx
673 movl $MSR_GS_BASE,%ecx
674 rdmsr
675 testl %edx,%edx
676 js 1f
677 swapgs
678 xorl %ebx,%ebx
b556b35e
JB
6791:
680 .if \ist
681 movq %gs:pda_data_offset, %rbp
682 .endif
683 movq %rsp,%rdi
1da177e4
LT
684 movq ORIG_RAX(%rsp),%rsi
685 movq $-1,ORIG_RAX(%rsp)
b556b35e 686 .if \ist
5f8efbb9 687 subq $EXCEPTION_STKSZ, per_cpu__init_tss + TSS_ist + (\ist - 1) * 8(%rbp)
b556b35e 688 .endif
1da177e4 689 call \sym
b556b35e 690 .if \ist
5f8efbb9 691 addq $EXCEPTION_STKSZ, per_cpu__init_tss + TSS_ist + (\ist - 1) * 8(%rbp)
b556b35e 692 .endif
6fefb0d1 693 cli
1da177e4
LT
694 .endm
695
696/*
697 * Exception entry point. This expects an error code/orig_rax on the stack
698 * and the exception handler in %rax.
699 */
700ENTRY(error_entry)
7effaa88 701 _frame RDI
1da177e4
LT
702 /* rdi slot contains rax, oldrax contains error code */
703 cld
704 subq $14*8,%rsp
705 CFI_ADJUST_CFA_OFFSET (14*8)
706 movq %rsi,13*8(%rsp)
707 CFI_REL_OFFSET rsi,RSI
708 movq 14*8(%rsp),%rsi /* load rax from rdi slot */
709 movq %rdx,12*8(%rsp)
710 CFI_REL_OFFSET rdx,RDX
711 movq %rcx,11*8(%rsp)
712 CFI_REL_OFFSET rcx,RCX
713 movq %rsi,10*8(%rsp) /* store rax */
714 CFI_REL_OFFSET rax,RAX
715 movq %r8, 9*8(%rsp)
716 CFI_REL_OFFSET r8,R8
717 movq %r9, 8*8(%rsp)
718 CFI_REL_OFFSET r9,R9
719 movq %r10,7*8(%rsp)
720 CFI_REL_OFFSET r10,R10
721 movq %r11,6*8(%rsp)
722 CFI_REL_OFFSET r11,R11
723 movq %rbx,5*8(%rsp)
724 CFI_REL_OFFSET rbx,RBX
725 movq %rbp,4*8(%rsp)
726 CFI_REL_OFFSET rbp,RBP
727 movq %r12,3*8(%rsp)
728 CFI_REL_OFFSET r12,R12
729 movq %r13,2*8(%rsp)
730 CFI_REL_OFFSET r13,R13
731 movq %r14,1*8(%rsp)
732 CFI_REL_OFFSET r14,R14
733 movq %r15,(%rsp)
734 CFI_REL_OFFSET r15,R15
735 xorl %ebx,%ebx
736 testl $3,CS(%rsp)
737 je error_kernelspace
738error_swapgs:
739 swapgs
740error_sti:
741 movq %rdi,RDI(%rsp)
742 movq %rsp,%rdi
743 movq ORIG_RAX(%rsp),%rsi /* get error code */
744 movq $-1,ORIG_RAX(%rsp)
745 call *%rax
746 /* ebx: no swapgs flag (1: don't need swapgs, 0: need it) */
747error_exit:
748 movl %ebx,%eax
749 RESTORE_REST
750 cli
751 GET_THREAD_INFO(%rcx)
752 testl %eax,%eax
753 jne retint_kernel
754 movl threadinfo_flags(%rcx),%edx
755 movl $_TIF_WORK_MASK,%edi
756 andl %edi,%edx
757 jnz retint_careful
758 swapgs
759 RESTORE_ARGS 0,8,0
505cc4e1 760 jmp iret_label
1da177e4
LT
761 CFI_ENDPROC
762
763error_kernelspace:
764 incl %ebx
765 /* There are two places in the kernel that can potentially fault with
766 usergs. Handle them here. The exception handlers after
767 iret run with kernel gs again, so don't set the user space flag.
768 B stepping K8s sometimes report an truncated RIP for IRET
769 exceptions returning to compat mode. Check for these here too. */
770 leaq iret_label(%rip),%rbp
771 cmpq %rbp,RIP(%rsp)
772 je error_swapgs
773 movl %ebp,%ebp /* zero extend */
774 cmpq %rbp,RIP(%rsp)
775 je error_swapgs
776 cmpq $gs_change,RIP(%rsp)
777 je error_swapgs
778 jmp error_sti
4b787e0b 779END(error_entry)
1da177e4
LT
780
781 /* Reload gs selector with exception handling */
782 /* edi: new selector */
783ENTRY(load_gs_index)
7effaa88 784 CFI_STARTPROC
1da177e4 785 pushf
7effaa88 786 CFI_ADJUST_CFA_OFFSET 8
1da177e4
LT
787 cli
788 swapgs
789gs_change:
790 movl %edi,%gs
7912: mfence /* workaround */
792 swapgs
793 popf
7effaa88 794 CFI_ADJUST_CFA_OFFSET -8
1da177e4 795 ret
7effaa88 796 CFI_ENDPROC
4b787e0b 797ENDPROC(load_gs_index)
1da177e4
LT
798
799 .section __ex_table,"a"
800 .align 8
801 .quad gs_change,bad_gs
802 .previous
803 .section .fixup,"ax"
804 /* running with kernelgs */
805bad_gs:
806 swapgs /* switch back to user gs */
807 xorl %eax,%eax
808 movl %eax,%gs
809 jmp 2b
810 .previous
811
812/*
813 * Create a kernel thread.
814 *
815 * C extern interface:
816 * extern long kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
817 *
818 * asm input arguments:
819 * rdi: fn, rsi: arg, rdx: flags
820 */
821ENTRY(kernel_thread)
822 CFI_STARTPROC
823 FAKE_STACK_FRAME $child_rip
824 SAVE_ALL
825
826 # rdi: flags, rsi: usp, rdx: will be &pt_regs
827 movq %rdx,%rdi
828 orq kernel_thread_flags(%rip),%rdi
829 movq $-1, %rsi
830 movq %rsp, %rdx
831
832 xorl %r8d,%r8d
833 xorl %r9d,%r9d
834
835 # clone now
836 call do_fork
837 movq %rax,RAX(%rsp)
838 xorl %edi,%edi
839
840 /*
841 * It isn't worth to check for reschedule here,
842 * so internally to the x86_64 port you can rely on kernel_thread()
843 * not to reschedule the child before returning, this avoids the need
844 * of hacks for example to fork off the per-CPU idle tasks.
845 * [Hopefully no generic code relies on the reschedule -AK]
846 */
847 RESTORE_ALL
848 UNFAKE_STACK_FRAME
849 ret
850 CFI_ENDPROC
4b787e0b 851ENDPROC(kernel_thread)
1da177e4
LT
852
853child_rip:
854 /*
855 * Here we are in the child and the registers are set as they were
856 * at kernel_thread() invocation in the parent.
857 */
858 movq %rdi, %rax
859 movq %rsi, %rdi
860 call *%rax
861 # exit
3829ee6b 862 xorl %edi, %edi
1da177e4 863 call do_exit
4b787e0b 864ENDPROC(child_rip)
1da177e4
LT
865
866/*
867 * execve(). This function needs to use IRET, not SYSRET, to set up all state properly.
868 *
869 * C extern interface:
870 * extern long execve(char *name, char **argv, char **envp)
871 *
872 * asm input arguments:
873 * rdi: name, rsi: argv, rdx: envp
874 *
875 * We want to fallback into:
876 * extern long sys_execve(char *name, char **argv,char **envp, struct pt_regs regs)
877 *
878 * do_sys_execve asm fallback arguments:
879 * rdi: name, rsi: argv, rdx: envp, fake frame on the stack
880 */
881ENTRY(execve)
882 CFI_STARTPROC
883 FAKE_STACK_FRAME $0
884 SAVE_ALL
885 call sys_execve
886 movq %rax, RAX(%rsp)
887 RESTORE_REST
888 testq %rax,%rax
889 je int_ret_from_sys_call
890 RESTORE_ARGS
891 UNFAKE_STACK_FRAME
892 ret
893 CFI_ENDPROC
4b787e0b 894ENDPROC(execve)
1da177e4 895
0f2fbdcb 896KPROBE_ENTRY(page_fault)
1da177e4 897 errorentry do_page_fault
4b787e0b 898END(page_fault)
0f2fbdcb 899 .previous .text
1da177e4
LT
900
901ENTRY(coprocessor_error)
902 zeroentry do_coprocessor_error
4b787e0b 903END(coprocessor_error)
1da177e4
LT
904
905ENTRY(simd_coprocessor_error)
906 zeroentry do_simd_coprocessor_error
4b787e0b 907END(simd_coprocessor_error)
1da177e4
LT
908
909ENTRY(device_not_available)
910 zeroentry math_state_restore
4b787e0b 911END(device_not_available)
1da177e4
LT
912
913 /* runs on exception stack */
0f2fbdcb 914KPROBE_ENTRY(debug)
7effaa88 915 INTR_FRAME
1da177e4
LT
916 pushq $0
917 CFI_ADJUST_CFA_OFFSET 8
5f8efbb9 918 paranoidentry do_debug, DEBUG_STACK
1da177e4
LT
919 jmp paranoid_exit
920 CFI_ENDPROC
4b787e0b 921END(debug)
0f2fbdcb 922 .previous .text
1da177e4
LT
923
924 /* runs on exception stack */
eddb6fb9 925KPROBE_ENTRY(nmi)
7effaa88 926 INTR_FRAME
1da177e4 927 pushq $-1
7effaa88 928 CFI_ADJUST_CFA_OFFSET 8
1da177e4 929 paranoidentry do_nmi
6fefb0d1
AK
930 /*
931 * "Paranoid" exit path from exception stack.
932 * Paranoid because this is used by NMIs and cannot take
933 * any kernel state for granted.
934 * We don't do kernel preemption checks here, because only
935 * NMI should be common and it does not enable IRQs and
936 * cannot get reschedule ticks.
937 */
1da177e4
LT
938 /* ebx: no swapgs flag */
939paranoid_exit:
940 testl %ebx,%ebx /* swapgs needed? */
941 jnz paranoid_restore
6fefb0d1
AK
942 testl $3,CS(%rsp)
943 jnz paranoid_userspace
1da177e4 944paranoid_swapgs:
1da177e4
LT
945 swapgs
946paranoid_restore:
947 RESTORE_ALL 8
948 iretq
949paranoid_userspace:
1da177e4 950 GET_THREAD_INFO(%rcx)
6fefb0d1
AK
951 movl threadinfo_flags(%rcx),%ebx
952 andl $_TIF_WORK_MASK,%ebx
11b854b2 953 jz paranoid_swapgs
6fefb0d1
AK
954 movq %rsp,%rdi /* &pt_regs */
955 call sync_regs
956 movq %rax,%rsp /* switch stack for scheduling */
957 testl $_TIF_NEED_RESCHED,%ebx
958 jnz paranoid_schedule
959 movl %ebx,%edx /* arg3: thread flags */
1da177e4 960 sti
6fefb0d1
AK
961 xorl %esi,%esi /* arg2: oldset */
962 movq %rsp,%rdi /* arg1: &pt_regs */
1da177e4 963 call do_notify_resume
6fefb0d1
AK
964 cli
965 jmp paranoid_userspace
966paranoid_schedule:
11b854b2
AK
967 sti
968 call schedule
6fefb0d1
AK
969 cli
970 jmp paranoid_userspace
1da177e4 971 CFI_ENDPROC
4b787e0b 972END(nmi)
eddb6fb9 973 .previous .text
6fefb0d1 974
0f2fbdcb 975KPROBE_ENTRY(int3)
b556b35e
JB
976 INTR_FRAME
977 pushq $0
978 CFI_ADJUST_CFA_OFFSET 8
5f8efbb9 979 paranoidentry do_int3, DEBUG_STACK
b556b35e
JB
980 jmp paranoid_exit
981 CFI_ENDPROC
4b787e0b 982END(int3)
0f2fbdcb 983 .previous .text
1da177e4
LT
984
985ENTRY(overflow)
986 zeroentry do_overflow
4b787e0b 987END(overflow)
1da177e4
LT
988
989ENTRY(bounds)
990 zeroentry do_bounds
4b787e0b 991END(bounds)
1da177e4
LT
992
993ENTRY(invalid_op)
994 zeroentry do_invalid_op
4b787e0b 995END(invalid_op)
1da177e4
LT
996
997ENTRY(coprocessor_segment_overrun)
998 zeroentry do_coprocessor_segment_overrun
4b787e0b 999END(coprocessor_segment_overrun)
1da177e4
LT
1000
1001ENTRY(reserved)
1002 zeroentry do_reserved
4b787e0b 1003END(reserved)
1da177e4
LT
1004
1005 /* runs on exception stack */
1006ENTRY(double_fault)
7effaa88 1007 XCPT_FRAME
1da177e4 1008 paranoidentry do_double_fault
1da177e4
LT
1009 jmp paranoid_exit
1010 CFI_ENDPROC
4b787e0b 1011END(double_fault)
1da177e4
LT
1012
1013ENTRY(invalid_TSS)
1014 errorentry do_invalid_TSS
4b787e0b 1015END(invalid_TSS)
1da177e4
LT
1016
1017ENTRY(segment_not_present)
1018 errorentry do_segment_not_present
4b787e0b 1019END(segment_not_present)
1da177e4
LT
1020
1021 /* runs on exception stack */
1022ENTRY(stack_segment)
7effaa88 1023 XCPT_FRAME
1da177e4 1024 paranoidentry do_stack_segment
1da177e4
LT
1025 jmp paranoid_exit
1026 CFI_ENDPROC
4b787e0b 1027END(stack_segment)
1da177e4 1028
0f2fbdcb 1029KPROBE_ENTRY(general_protection)
1da177e4 1030 errorentry do_general_protection
4b787e0b 1031END(general_protection)
0f2fbdcb 1032 .previous .text
1da177e4
LT
1033
1034ENTRY(alignment_check)
1035 errorentry do_alignment_check
4b787e0b 1036END(alignment_check)
1da177e4
LT
1037
1038ENTRY(divide_error)
1039 zeroentry do_divide_error
4b787e0b 1040END(divide_error)
1da177e4
LT
1041
1042ENTRY(spurious_interrupt_bug)
1043 zeroentry do_spurious_interrupt_bug
4b787e0b 1044END(spurious_interrupt_bug)
1da177e4
LT
1045
1046#ifdef CONFIG_X86_MCE
1047 /* runs on exception stack */
1048ENTRY(machine_check)
7effaa88 1049 INTR_FRAME
1da177e4
LT
1050 pushq $0
1051 CFI_ADJUST_CFA_OFFSET 8
1052 paranoidentry do_machine_check
1053 jmp paranoid_exit
1054 CFI_ENDPROC
4b787e0b 1055END(machine_check)
1da177e4
LT
1056#endif
1057
ed6b676c 1058ENTRY(call_softirq)
7effaa88 1059 CFI_STARTPROC
ed6b676c 1060 movq %gs:pda_irqstackptr,%rax
bd9cb64d
JB
1061 movq %rsp,%rdx
1062 CFI_DEF_CFA_REGISTER rdx
ed6b676c
AK
1063 incl %gs:pda_irqcount
1064 cmove %rax,%rsp
bd9cb64d
JB
1065 pushq %rdx
1066 /*todo CFI_DEF_CFA_EXPRESSION ...*/
ed6b676c 1067 call __do_softirq
bd9cb64d 1068 popq %rsp
7effaa88 1069 CFI_DEF_CFA_REGISTER rsp
ed6b676c 1070 decl %gs:pda_irqcount
ed6b676c 1071 ret
7effaa88 1072 CFI_ENDPROC
4b787e0b 1073ENDPROC(call_softirq)
b538ed27
JB
1074
1075#ifdef CONFIG_STACK_UNWIND
1076ENTRY(arch_unwind_init_running)
1077 CFI_STARTPROC
1078 movq %r15, R15(%rdi)
1079 movq %r14, R14(%rdi)
1080 xchgq %rsi, %rdx
1081 movq %r13, R13(%rdi)
1082 movq %r12, R12(%rdi)
1083 xorl %eax, %eax
1084 movq %rbp, RBP(%rdi)
1085 movq %rbx, RBX(%rdi)
1086 movq (%rsp), %rcx
1087 movq %rax, R11(%rdi)
1088 movq %rax, R10(%rdi)
1089 movq %rax, R9(%rdi)
1090 movq %rax, R8(%rdi)
1091 movq %rax, RAX(%rdi)
1092 movq %rax, RCX(%rdi)
1093 movq %rax, RDX(%rdi)
1094 movq %rax, RSI(%rdi)
1095 movq %rax, RDI(%rdi)
1096 movq %rax, ORIG_RAX(%rdi)
1097 movq %rcx, RIP(%rdi)
1098 leaq 8(%rsp), %rcx
1099 movq $__KERNEL_CS, CS(%rdi)
1100 movq %rax, EFLAGS(%rdi)
1101 movq %rcx, RSP(%rdi)
1102 movq $__KERNEL_DS, SS(%rdi)
1103 jmpq *%rdx
1104 CFI_ENDPROC
1105ENDPROC(arch_unwind_init_running)
1106#endif