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