Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
[deliverable/linux.git] / arch / x86 / kernel / entry_32.S
CommitLineData
1da177e4 1/*
1da177e4
LT
2 *
3 * Copyright (C) 1991, 1992 Linus Torvalds
4 */
5
6/*
7 * entry.S contains the system-call and fault low-level handling routines.
8 * This also contains the timer-interrupt handler, as well as all interrupts
9 * and faults that can result in a task-switch.
10 *
11 * NOTE: This code handles signal-recognition, which happens every time
12 * after a timer-interrupt and after each system call.
13 *
14 * I changed all the .align's to 4 (16 byte alignment), as that's faster
15 * on a 486.
16 *
889f21ce 17 * Stack layout in 'syscall_exit':
1da177e4
LT
18 * ptrace needs to have all regs on the stack.
19 * if the order here is changed, it needs to be
20 * updated in fork.c:copy_process, signal.c:do_signal,
21 * ptrace.c and ptrace.h
22 *
23 * 0(%esp) - %ebx
24 * 4(%esp) - %ecx
25 * 8(%esp) - %edx
26 * C(%esp) - %esi
27 * 10(%esp) - %edi
28 * 14(%esp) - %ebp
29 * 18(%esp) - %eax
30 * 1C(%esp) - %ds
31 * 20(%esp) - %es
464d1a78 32 * 24(%esp) - %fs
ccbeed3a
TH
33 * 28(%esp) - %gs saved iff !CONFIG_X86_32_LAZY_GS
34 * 2C(%esp) - orig_eax
35 * 30(%esp) - %eip
36 * 34(%esp) - %cs
37 * 38(%esp) - %eflags
38 * 3C(%esp) - %oldesp
39 * 40(%esp) - %oldss
1da177e4
LT
40 *
41 * "current" is in register %ebx during any slow entries.
42 */
43
1da177e4 44#include <linux/linkage.h>
d7e7528b 45#include <linux/err.h>
1da177e4 46#include <asm/thread_info.h>
55f327fa 47#include <asm/irqflags.h>
1da177e4
LT
48#include <asm/errno.h>
49#include <asm/segment.h>
50#include <asm/smp.h>
0341c14d 51#include <asm/page_types.h>
be44d2aa 52#include <asm/percpu.h>
fe7cacc1 53#include <asm/dwarf2.h>
ab68ed98 54#include <asm/processor-flags.h>
395a59d0 55#include <asm/ftrace.h>
9b7dc567 56#include <asm/irq_vectors.h>
40d2e763 57#include <asm/cpufeature.h>
b4ca46e4 58#include <asm/alternative-asm.h>
6837a54d 59#include <asm/asm.h>
e59d1b0a 60#include <asm/smap.h>
1da177e4 61
af0575bb
RM
62/* Avoid __ASSEMBLER__'ifying <linux/audit.h> just for this. */
63#include <linux/elf-em.h>
64#define AUDIT_ARCH_I386 (EM_386|__AUDIT_ARCH_LE)
65#define __AUDIT_ARCH_LE 0x40000000
66
67#ifndef CONFIG_AUDITSYSCALL
68#define sysenter_audit syscall_trace_entry
69#define sysexit_audit syscall_exit_work
70#endif
71
ea714547
JO
72 .section .entry.text, "ax"
73
139ec7c4
RR
74/*
75 * We use macros for low-level operations which need to be overridden
76 * for paravirtualization. The following will never clobber any registers:
77 * INTERRUPT_RETURN (aka. "iret")
78 * GET_CR0_INTO_EAX (aka. "movl %cr0, %eax")
d75cd22f 79 * ENABLE_INTERRUPTS_SYSEXIT (aka "sti; sysexit").
139ec7c4
RR
80 *
81 * For DISABLE_INTERRUPTS/ENABLE_INTERRUPTS (aka "cli"/"sti"), you must
82 * specify what registers can be overwritten (CLBR_NONE, CLBR_EAX/EDX/ECX/ANY).
83 * Allowing a register to be clobbered can shrink the paravirt replacement
84 * enough to patch inline, increasing performance.
85 */
86
1da177e4 87#ifdef CONFIG_PREEMPT
139ec7c4 88#define preempt_stop(clobbers) DISABLE_INTERRUPTS(clobbers); TRACE_IRQS_OFF
1da177e4 89#else
139ec7c4 90#define preempt_stop(clobbers)
2e04bc76 91#define resume_kernel restore_all
1da177e4
LT
92#endif
93
55f327fa
IM
94.macro TRACE_IRQS_IRET
95#ifdef CONFIG_TRACE_IRQFLAGS
ab68ed98 96 testl $X86_EFLAGS_IF,PT_EFLAGS(%esp) # interrupts off?
55f327fa
IM
97 jz 1f
98 TRACE_IRQS_ON
991:
100#endif
101.endm
102
ccbeed3a
TH
103/*
104 * User gs save/restore
105 *
106 * %gs is used for userland TLS and kernel only uses it for stack
107 * canary which is required to be at %gs:20 by gcc. Read the comment
108 * at the top of stackprotector.h for more info.
109 *
110 * Local labels 98 and 99 are used.
111 */
112#ifdef CONFIG_X86_32_LAZY_GS
113
114 /* unfortunately push/pop can't be no-op */
115.macro PUSH_GS
df5d1874 116 pushl_cfi $0
ccbeed3a
TH
117.endm
118.macro POP_GS pop=0
119 addl $(4 + \pop), %esp
120 CFI_ADJUST_CFA_OFFSET -(4 + \pop)
121.endm
122.macro POP_GS_EX
123.endm
124
125 /* all the rest are no-op */
126.macro PTGS_TO_GS
127.endm
128.macro PTGS_TO_GS_EX
129.endm
130.macro GS_TO_REG reg
131.endm
132.macro REG_TO_PTGS reg
133.endm
134.macro SET_KERNEL_GS reg
135.endm
136
137#else /* CONFIG_X86_32_LAZY_GS */
138
139.macro PUSH_GS
df5d1874 140 pushl_cfi %gs
ccbeed3a
TH
141 /*CFI_REL_OFFSET gs, 0*/
142.endm
143
144.macro POP_GS pop=0
df5d1874 14598: popl_cfi %gs
ccbeed3a
TH
146 /*CFI_RESTORE gs*/
147 .if \pop <> 0
148 add $\pop, %esp
149 CFI_ADJUST_CFA_OFFSET -\pop
150 .endif
151.endm
152.macro POP_GS_EX
153.pushsection .fixup, "ax"
15499: movl $0, (%esp)
155 jmp 98b
ccbeed3a 156.popsection
6837a54d 157 _ASM_EXTABLE(98b,99b)
ccbeed3a
TH
158.endm
159
160.macro PTGS_TO_GS
16198: mov PT_GS(%esp), %gs
162.endm
163.macro PTGS_TO_GS_EX
164.pushsection .fixup, "ax"
16599: movl $0, PT_GS(%esp)
166 jmp 98b
ccbeed3a 167.popsection
6837a54d 168 _ASM_EXTABLE(98b,99b)
ccbeed3a
TH
169.endm
170
171.macro GS_TO_REG reg
172 movl %gs, \reg
173 /*CFI_REGISTER gs, \reg*/
174.endm
175.macro REG_TO_PTGS reg
176 movl \reg, PT_GS(%esp)
177 /*CFI_REL_OFFSET gs, PT_GS*/
178.endm
179.macro SET_KERNEL_GS reg
60a5317f 180 movl $(__KERNEL_STACK_CANARY), \reg
ccbeed3a
TH
181 movl \reg, %gs
182.endm
183
184#endif /* CONFIG_X86_32_LAZY_GS */
185
f0d96110
TH
186.macro SAVE_ALL
187 cld
ccbeed3a 188 PUSH_GS
df5d1874 189 pushl_cfi %fs
f0d96110 190 /*CFI_REL_OFFSET fs, 0;*/
df5d1874 191 pushl_cfi %es
f0d96110 192 /*CFI_REL_OFFSET es, 0;*/
df5d1874 193 pushl_cfi %ds
f0d96110 194 /*CFI_REL_OFFSET ds, 0;*/
df5d1874 195 pushl_cfi %eax
f0d96110 196 CFI_REL_OFFSET eax, 0
df5d1874 197 pushl_cfi %ebp
f0d96110 198 CFI_REL_OFFSET ebp, 0
df5d1874 199 pushl_cfi %edi
f0d96110 200 CFI_REL_OFFSET edi, 0
df5d1874 201 pushl_cfi %esi
f0d96110 202 CFI_REL_OFFSET esi, 0
df5d1874 203 pushl_cfi %edx
f0d96110 204 CFI_REL_OFFSET edx, 0
df5d1874 205 pushl_cfi %ecx
f0d96110 206 CFI_REL_OFFSET ecx, 0
df5d1874 207 pushl_cfi %ebx
f0d96110
TH
208 CFI_REL_OFFSET ebx, 0
209 movl $(__USER_DS), %edx
210 movl %edx, %ds
211 movl %edx, %es
212 movl $(__KERNEL_PERCPU), %edx
464d1a78 213 movl %edx, %fs
ccbeed3a 214 SET_KERNEL_GS %edx
f0d96110 215.endm
1da177e4 216
f0d96110 217.macro RESTORE_INT_REGS
df5d1874 218 popl_cfi %ebx
f0d96110 219 CFI_RESTORE ebx
df5d1874 220 popl_cfi %ecx
f0d96110 221 CFI_RESTORE ecx
df5d1874 222 popl_cfi %edx
f0d96110 223 CFI_RESTORE edx
df5d1874 224 popl_cfi %esi
f0d96110 225 CFI_RESTORE esi
df5d1874 226 popl_cfi %edi
f0d96110 227 CFI_RESTORE edi
df5d1874 228 popl_cfi %ebp
f0d96110 229 CFI_RESTORE ebp
df5d1874 230 popl_cfi %eax
fe7cacc1 231 CFI_RESTORE eax
f0d96110 232.endm
1da177e4 233
ccbeed3a 234.macro RESTORE_REGS pop=0
f0d96110 235 RESTORE_INT_REGS
df5d1874 2361: popl_cfi %ds
f0d96110 237 /*CFI_RESTORE ds;*/
df5d1874 2382: popl_cfi %es
f0d96110 239 /*CFI_RESTORE es;*/
df5d1874 2403: popl_cfi %fs
f0d96110 241 /*CFI_RESTORE fs;*/
ccbeed3a 242 POP_GS \pop
f0d96110
TH
243.pushsection .fixup, "ax"
2444: movl $0, (%esp)
245 jmp 1b
2465: movl $0, (%esp)
247 jmp 2b
2486: movl $0, (%esp)
249 jmp 3b
f95d47ca 250.popsection
6837a54d
PA
251 _ASM_EXTABLE(1b,4b)
252 _ASM_EXTABLE(2b,5b)
253 _ASM_EXTABLE(3b,6b)
ccbeed3a 254 POP_GS_EX
f0d96110 255.endm
1da177e4 256
f0d96110
TH
257.macro RING0_INT_FRAME
258 CFI_STARTPROC simple
259 CFI_SIGNAL_FRAME
260 CFI_DEF_CFA esp, 3*4
261 /*CFI_OFFSET cs, -2*4;*/
fe7cacc1 262 CFI_OFFSET eip, -3*4
f0d96110 263.endm
fe7cacc1 264
f0d96110
TH
265.macro RING0_EC_FRAME
266 CFI_STARTPROC simple
267 CFI_SIGNAL_FRAME
268 CFI_DEF_CFA esp, 4*4
269 /*CFI_OFFSET cs, -2*4;*/
fe7cacc1 270 CFI_OFFSET eip, -3*4
f0d96110 271.endm
fe7cacc1 272
f0d96110
TH
273.macro RING0_PTREGS_FRAME
274 CFI_STARTPROC simple
275 CFI_SIGNAL_FRAME
276 CFI_DEF_CFA esp, PT_OLDESP-PT_EBX
277 /*CFI_OFFSET cs, PT_CS-PT_OLDESP;*/
278 CFI_OFFSET eip, PT_EIP-PT_OLDESP
279 /*CFI_OFFSET es, PT_ES-PT_OLDESP;*/
280 /*CFI_OFFSET ds, PT_DS-PT_OLDESP;*/
281 CFI_OFFSET eax, PT_EAX-PT_OLDESP
282 CFI_OFFSET ebp, PT_EBP-PT_OLDESP
283 CFI_OFFSET edi, PT_EDI-PT_OLDESP
284 CFI_OFFSET esi, PT_ESI-PT_OLDESP
285 CFI_OFFSET edx, PT_EDX-PT_OLDESP
286 CFI_OFFSET ecx, PT_ECX-PT_OLDESP
eb5b7b9d 287 CFI_OFFSET ebx, PT_EBX-PT_OLDESP
f0d96110 288.endm
1da177e4
LT
289
290ENTRY(ret_from_fork)
fe7cacc1 291 CFI_STARTPROC
df5d1874 292 pushl_cfi %eax
1da177e4
LT
293 call schedule_tail
294 GET_THREAD_INFO(%ebp)
df5d1874
JB
295 popl_cfi %eax
296 pushl_cfi $0x0202 # Reset kernel eflags
297 popfl_cfi
1da177e4 298 jmp syscall_exit
fe7cacc1 299 CFI_ENDPROC
47a55cd7 300END(ret_from_fork)
1da177e4 301
22e2430d
AV
302ENTRY(ret_from_kernel_thread)
303 CFI_STARTPROC
304 pushl_cfi %eax
305 call schedule_tail
6783eaa2 306 GET_THREAD_INFO(%ebp)
22e2430d
AV
307 popl_cfi %eax
308 pushl_cfi $0x0202 # Reset kernel eflags
309 popfl_cfi
310 movl PT_EBP(%esp),%eax
311 call *PT_EBX(%esp)
312 movl $0,PT_EAX(%esp)
6783eaa2 313 jmp syscall_exit
22e2430d
AV
314 CFI_ENDPROC
315ENDPROC(ret_from_kernel_thread)
6783eaa2 316
1da177e4
LT
317/*
318 * Return to user mode is not as complex as all this looks,
319 * but we want the default path for a system call return to
320 * go as quickly as possible which is why some of this is
321 * less clear than it otherwise should be.
322 */
323
324 # userspace resumption stub bypassing syscall exit tracing
325 ALIGN
fe7cacc1 326 RING0_PTREGS_FRAME
1da177e4 327ret_from_exception:
139ec7c4 328 preempt_stop(CLBR_ANY)
1da177e4
LT
329ret_from_intr:
330 GET_THREAD_INFO(%ebp)
29a2e283 331#ifdef CONFIG_VM86
eb5b7b9d
JF
332 movl PT_EFLAGS(%esp), %eax # mix EFLAGS and CS
333 movb PT_CS(%esp), %al
ab68ed98 334 andl $(X86_EFLAGS_VM | SEGMENT_RPL_MASK), %eax
29a2e283
DA
335#else
336 /*
6783eaa2 337 * We can be coming here from child spawned by kernel_thread().
29a2e283
DA
338 */
339 movl PT_CS(%esp), %eax
340 andl $SEGMENT_RPL_MASK, %eax
341#endif
78be3706
RR
342 cmpl $USER_RPL, %eax
343 jb resume_kernel # not returning to v8086 or userspace
f95d47ca 344
1da177e4 345ENTRY(resume_userspace)
c7e872e7 346 LOCKDEP_SYS_EXIT
139ec7c4 347 DISABLE_INTERRUPTS(CLBR_ANY) # make sure we don't miss an interrupt
1da177e4
LT
348 # setting need_resched or sigpending
349 # between sampling and the iret
e32e58a9 350 TRACE_IRQS_OFF
1da177e4
LT
351 movl TI_flags(%ebp), %ecx
352 andl $_TIF_WORK_MASK, %ecx # is there any work to be done on
353 # int/exception return?
354 jne work_pending
355 jmp restore_all
47a55cd7 356END(ret_from_exception)
1da177e4
LT
357
358#ifdef CONFIG_PREEMPT
359ENTRY(resume_kernel)
139ec7c4 360 DISABLE_INTERRUPTS(CLBR_ANY)
1da177e4 361need_resched:
c2daa3be
PZ
362 cmpl $0,PER_CPU_VAR(__preempt_count)
363 jnz restore_all
ab68ed98 364 testl $X86_EFLAGS_IF,PT_EFLAGS(%esp) # interrupts off (exception path) ?
1da177e4
LT
365 jz restore_all
366 call preempt_schedule_irq
367 jmp need_resched
47a55cd7 368END(resume_kernel)
1da177e4 369#endif
fe7cacc1 370 CFI_ENDPROC
1da177e4
LT
371
372/* SYSENTER_RETURN points to after the "sysenter" instruction in
373 the vsyscall page. See vsyscall-sysentry.S, which defines the symbol. */
374
375 # sysenter call handler stub
0aa97fb2 376ENTRY(ia32_sysenter_target)
fe7cacc1 377 CFI_STARTPROC simple
adf14236 378 CFI_SIGNAL_FRAME
fe7cacc1
JB
379 CFI_DEF_CFA esp, 0
380 CFI_REGISTER esp, ebp
faca6227 381 movl TSS_sysenter_sp0(%esp),%esp
1da177e4 382sysenter_past_esp:
55f327fa 383 /*
d93c870b
JF
384 * Interrupts are disabled here, but we can't trace it until
385 * enough kernel state to call TRACE_IRQS_OFF can be called - but
386 * we immediately enable interrupts at that point anyway.
55f327fa 387 */
3234282f 388 pushl_cfi $__USER_DS
fe7cacc1 389 /*CFI_REL_OFFSET ss, 0*/
df5d1874 390 pushl_cfi %ebp
fe7cacc1 391 CFI_REL_OFFSET esp, 0
df5d1874 392 pushfl_cfi
d93c870b 393 orl $X86_EFLAGS_IF, (%esp)
3234282f 394 pushl_cfi $__USER_CS
fe7cacc1 395 /*CFI_REL_OFFSET cs, 0*/
e6e5494c
IM
396 /*
397 * Push current_thread_info()->sysenter_return to the stack.
398 * A tiny bit of offset fixup is necessary - 4*4 means the 4 words
399 * pushed above; +8 corresponds to copy_thread's esp0 setting.
400 */
7bf04be8 401 pushl_cfi ((TI_sysenter_return)-THREAD_SIZE+8+4*4)(%esp)
fe7cacc1 402 CFI_REL_OFFSET eip, 0
1da177e4 403
df5d1874 404 pushl_cfi %eax
d93c870b
JF
405 SAVE_ALL
406 ENABLE_INTERRUPTS(CLBR_NONE)
407
1da177e4
LT
408/*
409 * Load the potential sixth argument from user stack.
410 * Careful about security.
411 */
412 cmpl $__PAGE_OFFSET-3,%ebp
413 jae syscall_fault
e59d1b0a 414 ASM_STAC
1da177e4 4151: movl (%ebp),%ebp
e59d1b0a 416 ASM_CLAC
d93c870b 417 movl %ebp,PT_EBP(%esp)
6837a54d 418 _ASM_EXTABLE(1b,syscall_fault)
1da177e4 419
1da177e4
LT
420 GET_THREAD_INFO(%ebp)
421
88200bc2 422 testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%ebp)
af0575bb
RM
423 jnz sysenter_audit
424sysenter_do_call:
303395ac 425 cmpl $(NR_syscalls), %eax
554086d8 426 jae sysenter_badsys
1da177e4 427 call *sys_call_table(,%eax,4)
554086d8 428sysenter_after_call:
8142b215 429 movl %eax,PT_EAX(%esp)
c7e872e7 430 LOCKDEP_SYS_EXIT
42c24fa2 431 DISABLE_INTERRUPTS(CLBR_ANY)
55f327fa 432 TRACE_IRQS_OFF
1da177e4 433 movl TI_flags(%ebp), %ecx
88200bc2 434 testl $_TIF_ALLWORK_MASK, %ecx
af0575bb
RM
435 jne sysexit_audit
436sysenter_exit:
1da177e4 437/* if something modifies registers it must also disable sysexit */
eb5b7b9d
JF
438 movl PT_EIP(%esp), %edx
439 movl PT_OLDESP(%esp), %ecx
1da177e4 440 xorl %ebp,%ebp
55f327fa 441 TRACE_IRQS_ON
464d1a78 4421: mov PT_FS(%esp), %fs
ccbeed3a 443 PTGS_TO_GS
d75cd22f 444 ENABLE_INTERRUPTS_SYSEXIT
af0575bb
RM
445
446#ifdef CONFIG_AUDITSYSCALL
447sysenter_audit:
88200bc2 448 testl $(_TIF_WORK_SYSCALL_ENTRY & ~_TIF_SYSCALL_AUDIT),TI_flags(%ebp)
af0575bb
RM
449 jnz syscall_trace_entry
450 addl $4,%esp
451 CFI_ADJUST_CFA_OFFSET -4
452 /* %esi already in 8(%esp) 6th arg: 4th syscall arg */
453 /* %edx already in 4(%esp) 5th arg: 3rd syscall arg */
454 /* %ecx already in 0(%esp) 4th arg: 2nd syscall arg */
455 movl %ebx,%ecx /* 3rd arg: 1st syscall arg */
456 movl %eax,%edx /* 2nd arg: syscall number */
457 movl $AUDIT_ARCH_I386,%eax /* 1st arg: audit arch */
b05d8447 458 call __audit_syscall_entry
df5d1874 459 pushl_cfi %ebx
af0575bb
RM
460 movl PT_EAX(%esp),%eax /* reload syscall number */
461 jmp sysenter_do_call
462
463sysexit_audit:
88200bc2 464 testl $(_TIF_ALLWORK_MASK & ~_TIF_SYSCALL_AUDIT), %ecx
af0575bb
RM
465 jne syscall_exit_work
466 TRACE_IRQS_ON
467 ENABLE_INTERRUPTS(CLBR_ANY)
468 movl %eax,%edx /* second arg, syscall return value */
d7e7528b
EP
469 cmpl $-MAX_ERRNO,%eax /* is it an error ? */
470 setbe %al /* 1 if so, 0 if not */
af0575bb 471 movzbl %al,%eax /* zero-extend that */
d7e7528b 472 call __audit_syscall_exit
af0575bb
RM
473 DISABLE_INTERRUPTS(CLBR_ANY)
474 TRACE_IRQS_OFF
475 movl TI_flags(%ebp), %ecx
88200bc2 476 testl $(_TIF_ALLWORK_MASK & ~_TIF_SYSCALL_AUDIT), %ecx
af0575bb
RM
477 jne syscall_exit_work
478 movl PT_EAX(%esp),%eax /* reload syscall return value */
479 jmp sysenter_exit
480#endif
481
fe7cacc1 482 CFI_ENDPROC
f95d47ca 483.pushsection .fixup,"ax"
464d1a78 4842: movl $0,PT_FS(%esp)
f95d47ca 485 jmp 1b
f95d47ca 486.popsection
6837a54d 487 _ASM_EXTABLE(1b,2b)
ccbeed3a 488 PTGS_TO_GS_EX
0aa97fb2 489ENDPROC(ia32_sysenter_target)
1da177e4
LT
490
491 # system call handler stub
492ENTRY(system_call)
fe7cacc1 493 RING0_INT_FRAME # can't unwind into user space anyway
e59d1b0a 494 ASM_CLAC
df5d1874 495 pushl_cfi %eax # save orig_eax
1da177e4
LT
496 SAVE_ALL
497 GET_THREAD_INFO(%ebp)
ed75e8d5 498 # system call tracing in operation / emulation
88200bc2 499 testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%ebp)
1da177e4 500 jnz syscall_trace_entry
303395ac 501 cmpl $(NR_syscalls), %eax
1da177e4
LT
502 jae syscall_badsys
503syscall_call:
504 call *sys_call_table(,%eax,4)
8142b215 505syscall_after_call:
eb5b7b9d 506 movl %eax,PT_EAX(%esp) # store the return value
1da177e4 507syscall_exit:
c7e872e7 508 LOCKDEP_SYS_EXIT
139ec7c4 509 DISABLE_INTERRUPTS(CLBR_ANY) # make sure we don't miss an interrupt
1da177e4
LT
510 # setting need_resched or sigpending
511 # between sampling and the iret
55f327fa 512 TRACE_IRQS_OFF
1da177e4 513 movl TI_flags(%ebp), %ecx
88200bc2 514 testl $_TIF_ALLWORK_MASK, %ecx # current->work
1da177e4
LT
515 jne syscall_exit_work
516
517restore_all:
2e04bc76
AH
518 TRACE_IRQS_IRET
519restore_all_notrace:
34273f41 520#ifdef CONFIG_X86_ESPFIX32
eb5b7b9d
JF
521 movl PT_EFLAGS(%esp), %eax # mix EFLAGS, SS and CS
522 # Warning: PT_OLDSS(%esp) contains the wrong/random values if we
5df24082
SS
523 # are returning to the kernel.
524 # See comments in process.c:copy_thread() for details.
eb5b7b9d
JF
525 movb PT_OLDSS(%esp), %ah
526 movb PT_CS(%esp), %al
ab68ed98 527 andl $(X86_EFLAGS_VM | (SEGMENT_TI_MASK << 8) | SEGMENT_RPL_MASK), %eax
78be3706 528 cmpl $((SEGMENT_LDT << 8) | USER_RPL), %eax
fe7cacc1 529 CFI_REMEMBER_STATE
1da177e4 530 je ldt_ss # returning to user-space with LDT SS
34273f41 531#endif
1da177e4 532restore_nocheck:
ccbeed3a 533 RESTORE_REGS 4 # skip orig_eax/error_code
f7f3d791 534irq_return:
3701d863 535 INTERRUPT_RETURN
1da177e4 536.section .fixup,"ax"
90e9f536 537ENTRY(iret_exc)
a879cbbb
LT
538 pushl $0 # no error code
539 pushl $do_iret_error
540 jmp error_code
1da177e4 541.previous
6837a54d 542 _ASM_EXTABLE(irq_return,iret_exc)
1da177e4 543
34273f41 544#ifdef CONFIG_X86_ESPFIX32
fe7cacc1 545 CFI_RESTORE_STATE
1da177e4 546ldt_ss:
d3561b7f
RR
547#ifdef CONFIG_PARAVIRT
548 /*
549 * The kernel can't run on a non-flat stack if paravirt mode
550 * is active. Rather than try to fixup the high bits of
551 * ESP, bypass this code entirely. This may break DOSemu
552 * and/or Wine support in a paravirt VM, although the option
553 * is still available to implement the setting of the high
554 * 16-bits in the INTERRUPT_RETURN paravirt-op.
555 */
93b1eab3 556 cmpl $0, pv_info+PARAVIRT_enabled
d3561b7f
RR
557 jne restore_nocheck
558#endif
559
dc4c2a0a
AH
560/*
561 * Setup and switch to ESPFIX stack
562 *
563 * We're returning to userspace with a 16 bit stack. The CPU will not
564 * restore the high word of ESP for us on executing iret... This is an
565 * "official" bug of all the x86-compatible CPUs, which we can work
566 * around to make dosemu and wine happy. We do this by preloading the
567 * high word of ESP with the high word of the userspace ESP while
568 * compensating for the offset by changing to the ESPFIX segment with
569 * a base address that matches for the difference.
570 */
72c511dd 571#define GDT_ESPFIX_SS PER_CPU_VAR(gdt_page) + (GDT_ENTRY_ESPFIX_SS * 8)
dc4c2a0a
AH
572 mov %esp, %edx /* load kernel esp */
573 mov PT_OLDESP(%esp), %eax /* load userspace esp */
574 mov %dx, %ax /* eax: new kernel esp */
575 sub %eax, %edx /* offset (low word is 0) */
dc4c2a0a 576 shr $16, %edx
72c511dd
BG
577 mov %dl, GDT_ESPFIX_SS + 4 /* bits 16..23 */
578 mov %dh, GDT_ESPFIX_SS + 7 /* bits 24..31 */
df5d1874
JB
579 pushl_cfi $__ESPFIX_SS
580 pushl_cfi %eax /* new kernel esp */
2e04bc76
AH
581 /* Disable interrupts, but do not irqtrace this section: we
582 * will soon execute iret and the tracer was already set to
583 * the irqstate after the iret */
139ec7c4 584 DISABLE_INTERRUPTS(CLBR_EAX)
dc4c2a0a 585 lss (%esp), %esp /* switch to espfix segment */
be44d2aa
SS
586 CFI_ADJUST_CFA_OFFSET -8
587 jmp restore_nocheck
34273f41 588#endif
fe7cacc1 589 CFI_ENDPROC
47a55cd7 590ENDPROC(system_call)
1da177e4
LT
591
592 # perform work that needs to be done immediately before resumption
593 ALIGN
fe7cacc1 594 RING0_PTREGS_FRAME # can't unwind into user space anyway
1da177e4
LT
595work_pending:
596 testb $_TIF_NEED_RESCHED, %cl
597 jz work_notifysig
598work_resched:
599 call schedule
c7e872e7 600 LOCKDEP_SYS_EXIT
139ec7c4 601 DISABLE_INTERRUPTS(CLBR_ANY) # make sure we don't miss an interrupt
1da177e4
LT
602 # setting need_resched or sigpending
603 # between sampling and the iret
55f327fa 604 TRACE_IRQS_OFF
1da177e4
LT
605 movl TI_flags(%ebp), %ecx
606 andl $_TIF_WORK_MASK, %ecx # is there any work to be done other
607 # than syscall tracing?
608 jz restore_all
609 testb $_TIF_NEED_RESCHED, %cl
610 jnz work_resched
611
612work_notifysig: # deal with pending signals and
613 # notify-resume requests
74b47a78 614#ifdef CONFIG_VM86
ab68ed98 615 testl $X86_EFLAGS_VM, PT_EFLAGS(%esp)
1da177e4
LT
616 movl %esp, %eax
617 jne work_notifysig_v86 # returning to kernel-space or
618 # vm86-space
969ae0bf
AV
6191:
620#else
621 movl %esp, %eax
622#endif
3596ff4e
SD
623 TRACE_IRQS_ON
624 ENABLE_INTERRUPTS(CLBR_NONE)
44fbbb3d
AV
625 movb PT_CS(%esp), %bl
626 andb $SEGMENT_RPL_MASK, %bl
627 cmpb $USER_RPL, %bl
628 jb resume_kernel
1da177e4
LT
629 xorl %edx, %edx
630 call do_notify_resume
44fbbb3d 631 jmp resume_userspace
1da177e4 632
969ae0bf 633#ifdef CONFIG_VM86
1da177e4
LT
634 ALIGN
635work_notifysig_v86:
df5d1874 636 pushl_cfi %ecx # save ti_flags for do_notify_resume
1da177e4 637 call save_v86_state # %eax contains pt_regs pointer
df5d1874 638 popl_cfi %ecx
1da177e4 639 movl %eax, %esp
969ae0bf 640 jmp 1b
74b47a78 641#endif
47a55cd7 642END(work_pending)
1da177e4
LT
643
644 # perform syscall exit tracing
645 ALIGN
646syscall_trace_entry:
eb5b7b9d 647 movl $-ENOSYS,PT_EAX(%esp)
1da177e4 648 movl %esp, %eax
d4d67150
RM
649 call syscall_trace_enter
650 /* What it returned is what we'll actually use. */
303395ac 651 cmpl $(NR_syscalls), %eax
1da177e4
LT
652 jnae syscall_call
653 jmp syscall_exit
47a55cd7 654END(syscall_trace_entry)
1da177e4
LT
655
656 # perform syscall exit tracing
657 ALIGN
658syscall_exit_work:
88200bc2 659 testl $_TIF_WORK_SYSCALL_EXIT, %ecx
1da177e4 660 jz work_pending
55f327fa 661 TRACE_IRQS_ON
d4d67150 662 ENABLE_INTERRUPTS(CLBR_ANY) # could let syscall_trace_leave() call
1da177e4
LT
663 # schedule() instead
664 movl %esp, %eax
d4d67150 665 call syscall_trace_leave
1da177e4 666 jmp resume_userspace
47a55cd7 667END(syscall_exit_work)
fe7cacc1 668 CFI_ENDPROC
1da177e4 669
fe7cacc1 670 RING0_INT_FRAME # can't unwind into user space anyway
1da177e4 671syscall_fault:
e59d1b0a 672 ASM_CLAC
1da177e4 673 GET_THREAD_INFO(%ebp)
eb5b7b9d 674 movl $-EFAULT,PT_EAX(%esp)
1da177e4 675 jmp resume_userspace
47a55cd7 676END(syscall_fault)
1da177e4 677
1da177e4 678syscall_badsys:
8142b215
SW
679 movl $-ENOSYS,%eax
680 jmp syscall_after_call
554086d8
AL
681END(syscall_badsys)
682
683sysenter_badsys:
8142b215 684 movl $-ENOSYS,%eax
554086d8 685 jmp sysenter_after_call
47a55cd7 686END(syscall_badsys)
fe7cacc1 687 CFI_ENDPROC
1da177e4 688
f0d96110 689.macro FIXUP_ESPFIX_STACK
dc4c2a0a
AH
690/*
691 * Switch back for ESPFIX stack to the normal zerobased stack
692 *
693 * We can't call C functions using the ESPFIX stack. This code reads
694 * the high word of the segment base from the GDT and swiches to the
695 * normal stack and adjusts ESP with the matching offset.
696 */
34273f41 697#ifdef CONFIG_X86_ESPFIX32
dc4c2a0a 698 /* fixup the stack */
72c511dd
BG
699 mov GDT_ESPFIX_SS + 4, %al /* bits 16..23 */
700 mov GDT_ESPFIX_SS + 7, %ah /* bits 24..31 */
dc4c2a0a
AH
701 shl $16, %eax
702 addl %esp, %eax /* the adjusted stack pointer */
df5d1874
JB
703 pushl_cfi $__KERNEL_DS
704 pushl_cfi %eax
dc4c2a0a 705 lss (%esp), %esp /* switch to the normal stack segment */
f0d96110 706 CFI_ADJUST_CFA_OFFSET -8
34273f41 707#endif
f0d96110
TH
708.endm
709.macro UNWIND_ESPFIX_STACK
34273f41 710#ifdef CONFIG_X86_ESPFIX32
f0d96110
TH
711 movl %ss, %eax
712 /* see if on espfix stack */
713 cmpw $__ESPFIX_SS, %ax
714 jne 27f
715 movl $__KERNEL_DS, %eax
716 movl %eax, %ds
717 movl %eax, %es
718 /* switch to normal stack */
719 FIXUP_ESPFIX_STACK
72027:
34273f41 721#endif
f0d96110 722.endm
1da177e4
LT
723
724/*
b7c6244f
PA
725 * Build the entry stubs and pointer table with some assembler magic.
726 * We pack 7 stubs into a single 32-byte chunk, which will fit in a
727 * single cache line on all modern x86 implementations.
1da177e4 728 */
4687518c 729.section .init.rodata,"a"
1da177e4 730ENTRY(interrupt)
ea714547 731.section .entry.text, "ax"
b7c6244f
PA
732 .p2align 5
733 .p2align CONFIG_X86_L1_CACHE_SHIFT
1da177e4 734ENTRY(irq_entries_start)
fe7cacc1 735 RING0_INT_FRAME
4687518c 736vector=FIRST_EXTERNAL_VECTOR
b7c6244f
PA
737.rept (NR_VECTORS-FIRST_EXTERNAL_VECTOR+6)/7
738 .balign 32
739 .rept 7
740 .if vector < NR_VECTORS
8665596e 741 .if vector <> FIRST_EXTERNAL_VECTOR
fe7cacc1 742 CFI_ADJUST_CFA_OFFSET -4
b7c6244f 743 .endif
df5d1874 7441: pushl_cfi $(~vector+0x80) /* Note: always in signed byte range */
8665596e 745 .if ((vector-FIRST_EXTERNAL_VECTOR)%7) <> 6
b7c6244f
PA
746 jmp 2f
747 .endif
748 .previous
1da177e4 749 .long 1b
ea714547 750 .section .entry.text, "ax"
1da177e4 751vector=vector+1
b7c6244f
PA
752 .endif
753 .endr
7542: jmp common_interrupt
1da177e4 755.endr
47a55cd7
JB
756END(irq_entries_start)
757
758.previous
759END(interrupt)
760.previous
1da177e4 761
55f327fa
IM
762/*
763 * the CPU automatically disables interrupts when executing an IRQ vector,
764 * so IRQ-flags tracing has to follow that:
765 */
b7c6244f 766 .p2align CONFIG_X86_L1_CACHE_SHIFT
1da177e4 767common_interrupt:
e59d1b0a 768 ASM_CLAC
b7c6244f 769 addl $-0x80,(%esp) /* Adjust vector into the [-256,-1] range */
1da177e4 770 SAVE_ALL
55f327fa 771 TRACE_IRQS_OFF
1da177e4
LT
772 movl %esp,%eax
773 call do_IRQ
774 jmp ret_from_intr
47a55cd7 775ENDPROC(common_interrupt)
fe7cacc1 776 CFI_ENDPROC
1da177e4 777
02cf94c3 778#define BUILD_INTERRUPT3(name, nr, fn) \
1da177e4 779ENTRY(name) \
fe7cacc1 780 RING0_INT_FRAME; \
e59d1b0a 781 ASM_CLAC; \
df5d1874 782 pushl_cfi $~(nr); \
fe7cacc1 783 SAVE_ALL; \
55f327fa 784 TRACE_IRQS_OFF \
1da177e4 785 movl %esp,%eax; \
02cf94c3 786 call fn; \
55f327fa 787 jmp ret_from_intr; \
47a55cd7
JB
788 CFI_ENDPROC; \
789ENDPROC(name)
1da177e4 790
cf910e83
SA
791
792#ifdef CONFIG_TRACING
793#define TRACE_BUILD_INTERRUPT(name, nr) \
794 BUILD_INTERRUPT3(trace_##name, nr, smp_trace_##name)
795#else
796#define TRACE_BUILD_INTERRUPT(name, nr)
797#endif
798
799#define BUILD_INTERRUPT(name, nr) \
800 BUILD_INTERRUPT3(name, nr, smp_##name); \
801 TRACE_BUILD_INTERRUPT(name, nr)
02cf94c3 802
1da177e4 803/* The include is where all of the SMP etc. interrupts come from */
1164dd00 804#include <asm/entry_arch.h>
1da177e4 805
1da177e4 806ENTRY(coprocessor_error)
fe7cacc1 807 RING0_INT_FRAME
e59d1b0a 808 ASM_CLAC
df5d1874
JB
809 pushl_cfi $0
810 pushl_cfi $do_coprocessor_error
1da177e4 811 jmp error_code
fe7cacc1 812 CFI_ENDPROC
47a55cd7 813END(coprocessor_error)
1da177e4
LT
814
815ENTRY(simd_coprocessor_error)
fe7cacc1 816 RING0_INT_FRAME
e59d1b0a 817 ASM_CLAC
df5d1874 818 pushl_cfi $0
40d2e763
BG
819#ifdef CONFIG_X86_INVD_BUG
820 /* AMD 486 bug: invd from userspace calls exception 19 instead of #GP */
df5d1874 821661: pushl_cfi $do_general_protection
40d2e763
BG
822662:
823.section .altinstructions,"a"
b4ca46e4 824 altinstruction_entry 661b, 663f, X86_FEATURE_XMM, 662b-661b, 664f-663f
40d2e763
BG
825.previous
826.section .altinstr_replacement,"ax"
827663: pushl $do_simd_coprocessor_error
828664:
829.previous
830#else
df5d1874 831 pushl_cfi $do_simd_coprocessor_error
40d2e763 832#endif
1da177e4 833 jmp error_code
fe7cacc1 834 CFI_ENDPROC
47a55cd7 835END(simd_coprocessor_error)
1da177e4
LT
836
837ENTRY(device_not_available)
fe7cacc1 838 RING0_INT_FRAME
e59d1b0a 839 ASM_CLAC
df5d1874
JB
840 pushl_cfi $-1 # mark this as an int
841 pushl_cfi $do_device_not_available
7643e9b9 842 jmp error_code
fe7cacc1 843 CFI_ENDPROC
47a55cd7 844END(device_not_available)
1da177e4 845
d3561b7f
RR
846#ifdef CONFIG_PARAVIRT
847ENTRY(native_iret)
3701d863 848 iret
6837a54d 849 _ASM_EXTABLE(native_iret, iret_exc)
47a55cd7 850END(native_iret)
d3561b7f 851
d75cd22f 852ENTRY(native_irq_enable_sysexit)
d3561b7f
RR
853 sti
854 sysexit
d75cd22f 855END(native_irq_enable_sysexit)
d3561b7f
RR
856#endif
857
1da177e4 858ENTRY(overflow)
fe7cacc1 859 RING0_INT_FRAME
e59d1b0a 860 ASM_CLAC
df5d1874
JB
861 pushl_cfi $0
862 pushl_cfi $do_overflow
1da177e4 863 jmp error_code
fe7cacc1 864 CFI_ENDPROC
47a55cd7 865END(overflow)
1da177e4
LT
866
867ENTRY(bounds)
fe7cacc1 868 RING0_INT_FRAME
e59d1b0a 869 ASM_CLAC
df5d1874
JB
870 pushl_cfi $0
871 pushl_cfi $do_bounds
1da177e4 872 jmp error_code
fe7cacc1 873 CFI_ENDPROC
47a55cd7 874END(bounds)
1da177e4
LT
875
876ENTRY(invalid_op)
fe7cacc1 877 RING0_INT_FRAME
e59d1b0a 878 ASM_CLAC
df5d1874
JB
879 pushl_cfi $0
880 pushl_cfi $do_invalid_op
1da177e4 881 jmp error_code
fe7cacc1 882 CFI_ENDPROC
47a55cd7 883END(invalid_op)
1da177e4
LT
884
885ENTRY(coprocessor_segment_overrun)
fe7cacc1 886 RING0_INT_FRAME
e59d1b0a 887 ASM_CLAC
df5d1874
JB
888 pushl_cfi $0
889 pushl_cfi $do_coprocessor_segment_overrun
1da177e4 890 jmp error_code
fe7cacc1 891 CFI_ENDPROC
47a55cd7 892END(coprocessor_segment_overrun)
1da177e4
LT
893
894ENTRY(invalid_TSS)
fe7cacc1 895 RING0_EC_FRAME
e59d1b0a 896 ASM_CLAC
df5d1874 897 pushl_cfi $do_invalid_TSS
1da177e4 898 jmp error_code
fe7cacc1 899 CFI_ENDPROC
47a55cd7 900END(invalid_TSS)
1da177e4
LT
901
902ENTRY(segment_not_present)
fe7cacc1 903 RING0_EC_FRAME
e59d1b0a 904 ASM_CLAC
df5d1874 905 pushl_cfi $do_segment_not_present
1da177e4 906 jmp error_code
fe7cacc1 907 CFI_ENDPROC
47a55cd7 908END(segment_not_present)
1da177e4
LT
909
910ENTRY(stack_segment)
fe7cacc1 911 RING0_EC_FRAME
e59d1b0a 912 ASM_CLAC
df5d1874 913 pushl_cfi $do_stack_segment
1da177e4 914 jmp error_code
fe7cacc1 915 CFI_ENDPROC
47a55cd7 916END(stack_segment)
1da177e4 917
1da177e4 918ENTRY(alignment_check)
fe7cacc1 919 RING0_EC_FRAME
e59d1b0a 920 ASM_CLAC
df5d1874 921 pushl_cfi $do_alignment_check
1da177e4 922 jmp error_code
fe7cacc1 923 CFI_ENDPROC
47a55cd7 924END(alignment_check)
1da177e4 925
d28c4393
P
926ENTRY(divide_error)
927 RING0_INT_FRAME
e59d1b0a 928 ASM_CLAC
df5d1874
JB
929 pushl_cfi $0 # no error code
930 pushl_cfi $do_divide_error
1da177e4 931 jmp error_code
fe7cacc1 932 CFI_ENDPROC
47a55cd7 933END(divide_error)
1da177e4
LT
934
935#ifdef CONFIG_X86_MCE
936ENTRY(machine_check)
fe7cacc1 937 RING0_INT_FRAME
e59d1b0a 938 ASM_CLAC
df5d1874
JB
939 pushl_cfi $0
940 pushl_cfi machine_check_vector
1da177e4 941 jmp error_code
fe7cacc1 942 CFI_ENDPROC
47a55cd7 943END(machine_check)
1da177e4
LT
944#endif
945
946ENTRY(spurious_interrupt_bug)
fe7cacc1 947 RING0_INT_FRAME
e59d1b0a 948 ASM_CLAC
df5d1874
JB
949 pushl_cfi $0
950 pushl_cfi $do_spurious_interrupt_bug
1da177e4 951 jmp error_code
fe7cacc1 952 CFI_ENDPROC
47a55cd7 953END(spurious_interrupt_bug)
1da177e4 954
5ead97c8 955#ifdef CONFIG_XEN
e2a81baf
JF
956/* Xen doesn't set %esp to be precisely what the normal sysenter
957 entrypoint expects, so fix it up before using the normal path. */
958ENTRY(xen_sysenter_target)
959 RING0_INT_FRAME
960 addl $5*4, %esp /* remove xen-provided frame */
2ddf9b7b 961 CFI_ADJUST_CFA_OFFSET -5*4
e2a81baf 962 jmp sysenter_past_esp
557d7d4e 963 CFI_ENDPROC
e2a81baf 964
5ead97c8
JF
965ENTRY(xen_hypervisor_callback)
966 CFI_STARTPROC
a349e23d 967 pushl_cfi $-1 /* orig_ax = -1 => not a system call */
5ead97c8
JF
968 SAVE_ALL
969 TRACE_IRQS_OFF
9ec2b804
JF
970
971 /* Check to see if we got the event in the critical
972 region in xen_iret_direct, after we've reenabled
973 events and checked for pending events. This simulates
974 iret instruction's behaviour where it delivers a
975 pending interrupt when enabling interrupts. */
976 movl PT_EIP(%esp),%eax
977 cmpl $xen_iret_start_crit,%eax
978 jb 1f
979 cmpl $xen_iret_end_crit,%eax
980 jae 1f
981
0f2c8769 982 jmp xen_iret_crit_fixup
e2a81baf 983
e2a81baf 984ENTRY(xen_do_upcall)
b77797fb 9851: mov %esp, %eax
5ead97c8
JF
986 call xen_evtchn_do_upcall
987 jmp ret_from_intr
988 CFI_ENDPROC
989ENDPROC(xen_hypervisor_callback)
990
991# Hypervisor uses this for application faults while it executes.
992# We get here for two reasons:
993# 1. Fault while reloading DS, ES, FS or GS
994# 2. Fault while executing IRET
995# Category 1 we fix up by reattempting the load, and zeroing the segment
996# register if the load fails.
997# Category 2 we fix up by jumping to do_iret_error. We cannot use the
998# normal Linux return path in this case because if we use the IRET hypercall
999# to pop the stack frame we end up in an infinite loop of failsafe callbacks.
1000# We distinguish between categories by maintaining a status value in EAX.
1001ENTRY(xen_failsafe_callback)
1002 CFI_STARTPROC
df5d1874 1003 pushl_cfi %eax
5ead97c8
JF
1004 movl $1,%eax
10051: mov 4(%esp),%ds
10062: mov 8(%esp),%es
10073: mov 12(%esp),%fs
10084: mov 16(%esp),%gs
a349e23d
DV
1009 /* EAX == 0 => Category 1 (Bad segment)
1010 EAX != 0 => Category 2 (Bad IRET) */
5ead97c8 1011 testl %eax,%eax
df5d1874 1012 popl_cfi %eax
5ead97c8
JF
1013 lea 16(%esp),%esp
1014 CFI_ADJUST_CFA_OFFSET -16
1015 jz 5f
a349e23d
DV
1016 jmp iret_exc
10175: pushl_cfi $-1 /* orig_ax = -1 => not a system call */
5ead97c8
JF
1018 SAVE_ALL
1019 jmp ret_from_exception
1020 CFI_ENDPROC
1021
1022.section .fixup,"ax"
10236: xorl %eax,%eax
1024 movl %eax,4(%esp)
1025 jmp 1b
10267: xorl %eax,%eax
1027 movl %eax,8(%esp)
1028 jmp 2b
10298: xorl %eax,%eax
1030 movl %eax,12(%esp)
1031 jmp 3b
10329: xorl %eax,%eax
1033 movl %eax,16(%esp)
1034 jmp 4b
1035.previous
6837a54d
PA
1036 _ASM_EXTABLE(1b,6b)
1037 _ASM_EXTABLE(2b,7b)
1038 _ASM_EXTABLE(3b,8b)
1039 _ASM_EXTABLE(4b,9b)
5ead97c8
JF
1040ENDPROC(xen_failsafe_callback)
1041
bc2b0331 1042BUILD_INTERRUPT3(xen_hvm_callback_vector, HYPERVISOR_CALLBACK_VECTOR,
38e20b07
SY
1043 xen_evtchn_do_upcall)
1044
5ead97c8 1045#endif /* CONFIG_XEN */
bc2b0331
S
1046
1047#if IS_ENABLED(CONFIG_HYPERV)
1048
1049BUILD_INTERRUPT3(hyperv_callback_vector, HYPERVISOR_CALLBACK_VECTOR,
1050 hyperv_vector_handler)
1051
1052#endif /* CONFIG_HYPERV */
5ead97c8 1053
606576ce 1054#ifdef CONFIG_FUNCTION_TRACER
d61f82d0
SR
1055#ifdef CONFIG_DYNAMIC_FTRACE
1056
1057ENTRY(mcount)
d61f82d0
SR
1058 ret
1059END(mcount)
1060
1061ENTRY(ftrace_caller)
1062 pushl %eax
1063 pushl %ecx
1064 pushl %edx
08f6fba5
SR
1065 pushl $0 /* Pass NULL as regs pointer */
1066 movl 4*4(%esp), %eax
d61f82d0 1067 movl 0x4(%ebp), %edx
1739f09e 1068 movl function_trace_op, %ecx
395a59d0 1069 subl $MCOUNT_INSN_SIZE, %eax
d61f82d0
SR
1070
1071.globl ftrace_call
1072ftrace_call:
1073 call ftrace_stub
1074
08f6fba5 1075 addl $4,%esp /* skip NULL pointer */
d61f82d0
SR
1076 popl %edx
1077 popl %ecx
1078 popl %eax
4de72395 1079ftrace_ret:
5a45cfe1
SR
1080#ifdef CONFIG_FUNCTION_GRAPH_TRACER
1081.globl ftrace_graph_call
1082ftrace_graph_call:
1083 jmp ftrace_stub
1084#endif
d61f82d0
SR
1085
1086.globl ftrace_stub
1087ftrace_stub:
1088 ret
1089END(ftrace_caller)
1090
4de72395
SR
1091ENTRY(ftrace_regs_caller)
1092 pushf /* push flags before compare (in cs location) */
4de72395
SR
1093
1094 /*
1095 * i386 does not save SS and ESP when coming from kernel.
1096 * Instead, to get sp, &regs->sp is used (see ptrace.h).
1097 * Unfortunately, that means eflags must be at the same location
1098 * as the current return ip is. We move the return ip into the
1099 * ip location, and move flags into the return ip location.
1100 */
1101 pushl 4(%esp) /* save return ip into ip slot */
4de72395
SR
1102
1103 pushl $0 /* Load 0 into orig_ax */
1104 pushl %gs
1105 pushl %fs
1106 pushl %es
1107 pushl %ds
1108 pushl %eax
1109 pushl %ebp
1110 pushl %edi
1111 pushl %esi
1112 pushl %edx
1113 pushl %ecx
1114 pushl %ebx
1115
1116 movl 13*4(%esp), %eax /* Get the saved flags */
1117 movl %eax, 14*4(%esp) /* Move saved flags into regs->flags location */
1118 /* clobbering return ip */
1119 movl $__KERNEL_CS,13*4(%esp)
1120
1121 movl 12*4(%esp), %eax /* Load ip (1st parameter) */
a5e37863 1122 subl $MCOUNT_INSN_SIZE, %eax /* Adjust ip */
e4ea3f6b 1123 movl 0x4(%ebp), %edx /* Load parent ip (2nd parameter) */
1739f09e 1124 movl function_trace_op, %ecx /* Save ftrace_pos in 3rd parameter */
e4ea3f6b 1125 pushl %esp /* Save pt_regs as 4th parameter */
4de72395
SR
1126
1127GLOBAL(ftrace_regs_call)
1128 call ftrace_stub
1129
1130 addl $4, %esp /* Skip pt_regs */
1131 movl 14*4(%esp), %eax /* Move flags back into cs */
1132 movl %eax, 13*4(%esp) /* Needed to keep addl from modifying flags */
1133 movl 12*4(%esp), %eax /* Get return ip from regs->ip */
4de72395
SR
1134 movl %eax, 14*4(%esp) /* Put return ip back for ret */
1135
1136 popl %ebx
1137 popl %ecx
1138 popl %edx
1139 popl %esi
1140 popl %edi
1141 popl %ebp
1142 popl %eax
1143 popl %ds
1144 popl %es
1145 popl %fs
1146 popl %gs
1147 addl $8, %esp /* Skip orig_ax and ip */
1148 popf /* Pop flags at end (no addl to corrupt flags) */
1149 jmp ftrace_ret
1150
4de72395
SR
1151 popf
1152 jmp ftrace_stub
d61f82d0
SR
1153#else /* ! CONFIG_DYNAMIC_FTRACE */
1154
16444a8a 1155ENTRY(mcount)
af058ab0
PA
1156 cmpl $__PAGE_OFFSET, %esp
1157 jb ftrace_stub /* Paging not enabled yet? */
1158
16444a8a
ACM
1159 cmpl $ftrace_stub, ftrace_trace_function
1160 jnz trace
fb52607a 1161#ifdef CONFIG_FUNCTION_GRAPH_TRACER
c2324b69 1162 cmpl $ftrace_stub, ftrace_graph_return
fb52607a 1163 jnz ftrace_graph_caller
e49dc19c
SR
1164
1165 cmpl $ftrace_graph_entry_stub, ftrace_graph_entry
1166 jnz ftrace_graph_caller
caf4b323 1167#endif
16444a8a
ACM
1168.globl ftrace_stub
1169ftrace_stub:
1170 ret
1171
1172 /* taken from glibc */
1173trace:
1174 pushl %eax
1175 pushl %ecx
1176 pushl %edx
1177 movl 0xc(%esp), %eax
1178 movl 0x4(%ebp), %edx
395a59d0 1179 subl $MCOUNT_INSN_SIZE, %eax
16444a8a 1180
d61f82d0 1181 call *ftrace_trace_function
16444a8a
ACM
1182
1183 popl %edx
1184 popl %ecx
1185 popl %eax
16444a8a
ACM
1186 jmp ftrace_stub
1187END(mcount)
d61f82d0 1188#endif /* CONFIG_DYNAMIC_FTRACE */
606576ce 1189#endif /* CONFIG_FUNCTION_TRACER */
16444a8a 1190
fb52607a
FW
1191#ifdef CONFIG_FUNCTION_GRAPH_TRACER
1192ENTRY(ftrace_graph_caller)
caf4b323
FW
1193 pushl %eax
1194 pushl %ecx
1195 pushl %edx
1dc1c6ad 1196 movl 0xc(%esp), %edx
caf4b323 1197 lea 0x4(%ebp), %eax
71e308a2 1198 movl (%ebp), %ecx
bb4304c7 1199 subl $MCOUNT_INSN_SIZE, %edx
caf4b323 1200 call prepare_ftrace_return
caf4b323
FW
1201 popl %edx
1202 popl %ecx
1203 popl %eax
e7d3737e 1204 ret
fb52607a 1205END(ftrace_graph_caller)
caf4b323
FW
1206
1207.globl return_to_handler
1208return_to_handler:
caf4b323 1209 pushl %eax
caf4b323 1210 pushl %edx
71e308a2 1211 movl %ebp, %eax
caf4b323 1212 call ftrace_return_to_handler
194ec341 1213 movl %eax, %ecx
caf4b323 1214 popl %edx
caf4b323 1215 popl %eax
194ec341 1216 jmp *%ecx
e7d3737e 1217#endif
16444a8a 1218
25c74b10
SA
1219#ifdef CONFIG_TRACING
1220ENTRY(trace_page_fault)
1221 RING0_EC_FRAME
1222 ASM_CLAC
1223 pushl_cfi $trace_do_page_fault
1224 jmp error_code
1225 CFI_ENDPROC
1226END(trace_page_fault)
1227#endif
1228
d211af05
AH
1229ENTRY(page_fault)
1230 RING0_EC_FRAME
e59d1b0a 1231 ASM_CLAC
df5d1874 1232 pushl_cfi $do_page_fault
d211af05
AH
1233 ALIGN
1234error_code:
ccbeed3a 1235 /* the function address is in %gs's slot on the stack */
df5d1874 1236 pushl_cfi %fs
ccbeed3a 1237 /*CFI_REL_OFFSET fs, 0*/
df5d1874 1238 pushl_cfi %es
d211af05 1239 /*CFI_REL_OFFSET es, 0*/
df5d1874 1240 pushl_cfi %ds
d211af05 1241 /*CFI_REL_OFFSET ds, 0*/
df5d1874 1242 pushl_cfi %eax
d211af05 1243 CFI_REL_OFFSET eax, 0
df5d1874 1244 pushl_cfi %ebp
d211af05 1245 CFI_REL_OFFSET ebp, 0
df5d1874 1246 pushl_cfi %edi
d211af05 1247 CFI_REL_OFFSET edi, 0
df5d1874 1248 pushl_cfi %esi
d211af05 1249 CFI_REL_OFFSET esi, 0
df5d1874 1250 pushl_cfi %edx
d211af05 1251 CFI_REL_OFFSET edx, 0
df5d1874 1252 pushl_cfi %ecx
d211af05 1253 CFI_REL_OFFSET ecx, 0
df5d1874 1254 pushl_cfi %ebx
d211af05
AH
1255 CFI_REL_OFFSET ebx, 0
1256 cld
d211af05
AH
1257 movl $(__KERNEL_PERCPU), %ecx
1258 movl %ecx, %fs
1259 UNWIND_ESPFIX_STACK
ccbeed3a
TH
1260 GS_TO_REG %ecx
1261 movl PT_GS(%esp), %edi # get the function address
d211af05
AH
1262 movl PT_ORIG_EAX(%esp), %edx # get the error code
1263 movl $-1, PT_ORIG_EAX(%esp) # no syscall to restart
ccbeed3a
TH
1264 REG_TO_PTGS %ecx
1265 SET_KERNEL_GS %ecx
d211af05
AH
1266 movl $(__USER_DS), %ecx
1267 movl %ecx, %ds
1268 movl %ecx, %es
1269 TRACE_IRQS_OFF
1270 movl %esp,%eax # pt_regs pointer
1271 call *%edi
1272 jmp ret_from_exception
1273 CFI_ENDPROC
1274END(page_fault)
1275
1276/*
1277 * Debug traps and NMI can happen at the one SYSENTER instruction
1278 * that sets up the real kernel stack. Check here, since we can't
1279 * allow the wrong stack to be used.
1280 *
1281 * "TSS_sysenter_sp0+12" is because the NMI/debug handler will have
1282 * already pushed 3 words if it hits on the sysenter instruction:
1283 * eflags, cs and eip.
1284 *
1285 * We just load the right stack, and push the three (known) values
1286 * by hand onto the new stack - while updating the return eip past
1287 * the instruction that would have done it for sysenter.
1288 */
f0d96110
TH
1289.macro FIX_STACK offset ok label
1290 cmpw $__KERNEL_CS, 4(%esp)
1291 jne \ok
1292\label:
1293 movl TSS_sysenter_sp0 + \offset(%esp), %esp
1294 CFI_DEF_CFA esp, 0
1295 CFI_UNDEFINED eip
df5d1874
JB
1296 pushfl_cfi
1297 pushl_cfi $__KERNEL_CS
1298 pushl_cfi $sysenter_past_esp
d211af05 1299 CFI_REL_OFFSET eip, 0
f0d96110 1300.endm
d211af05
AH
1301
1302ENTRY(debug)
1303 RING0_INT_FRAME
e59d1b0a 1304 ASM_CLAC
d211af05
AH
1305 cmpl $ia32_sysenter_target,(%esp)
1306 jne debug_stack_correct
f0d96110 1307 FIX_STACK 12, debug_stack_correct, debug_esp_fix_insn
d211af05 1308debug_stack_correct:
df5d1874 1309 pushl_cfi $-1 # mark this as an int
d211af05
AH
1310 SAVE_ALL
1311 TRACE_IRQS_OFF
1312 xorl %edx,%edx # error code 0
1313 movl %esp,%eax # pt_regs pointer
1314 call do_debug
1315 jmp ret_from_exception
1316 CFI_ENDPROC
1317END(debug)
1318
1319/*
1320 * NMI is doubly nasty. It can happen _while_ we're handling
1321 * a debug fault, and the debug fault hasn't yet been able to
1322 * clear up the stack. So we first check whether we got an
1323 * NMI on the sysenter entry path, but after that we need to
1324 * check whether we got an NMI on the debug path where the debug
1325 * fault happened on the sysenter path.
1326 */
1327ENTRY(nmi)
1328 RING0_INT_FRAME
e59d1b0a 1329 ASM_CLAC
34273f41 1330#ifdef CONFIG_X86_ESPFIX32
df5d1874 1331 pushl_cfi %eax
d211af05
AH
1332 movl %ss, %eax
1333 cmpw $__ESPFIX_SS, %ax
df5d1874 1334 popl_cfi %eax
d211af05 1335 je nmi_espfix_stack
34273f41 1336#endif
d211af05
AH
1337 cmpl $ia32_sysenter_target,(%esp)
1338 je nmi_stack_fixup
df5d1874 1339 pushl_cfi %eax
d211af05
AH
1340 movl %esp,%eax
1341 /* Do not access memory above the end of our stack page,
1342 * it might not exist.
1343 */
1344 andl $(THREAD_SIZE-1),%eax
1345 cmpl $(THREAD_SIZE-20),%eax
df5d1874 1346 popl_cfi %eax
d211af05
AH
1347 jae nmi_stack_correct
1348 cmpl $ia32_sysenter_target,12(%esp)
1349 je nmi_debug_stack_check
1350nmi_stack_correct:
1351 /* We have a RING0_INT_FRAME here */
df5d1874 1352 pushl_cfi %eax
d211af05 1353 SAVE_ALL
d211af05
AH
1354 xorl %edx,%edx # zero error code
1355 movl %esp,%eax # pt_regs pointer
1356 call do_nmi
2e04bc76 1357 jmp restore_all_notrace
d211af05
AH
1358 CFI_ENDPROC
1359
1360nmi_stack_fixup:
1361 RING0_INT_FRAME
f0d96110 1362 FIX_STACK 12, nmi_stack_correct, 1
d211af05
AH
1363 jmp nmi_stack_correct
1364
1365nmi_debug_stack_check:
1366 /* We have a RING0_INT_FRAME here */
1367 cmpw $__KERNEL_CS,16(%esp)
1368 jne nmi_stack_correct
1369 cmpl $debug,(%esp)
1370 jb nmi_stack_correct
1371 cmpl $debug_esp_fix_insn,(%esp)
1372 ja nmi_stack_correct
f0d96110 1373 FIX_STACK 24, nmi_stack_correct, 1
d211af05
AH
1374 jmp nmi_stack_correct
1375
34273f41 1376#ifdef CONFIG_X86_ESPFIX32
d211af05
AH
1377nmi_espfix_stack:
1378 /* We have a RING0_INT_FRAME here.
1379 *
1380 * create the pointer to lss back
1381 */
df5d1874
JB
1382 pushl_cfi %ss
1383 pushl_cfi %esp
bda3a897 1384 addl $4, (%esp)
d211af05
AH
1385 /* copy the iret frame of 12 bytes */
1386 .rept 3
df5d1874 1387 pushl_cfi 16(%esp)
d211af05 1388 .endr
df5d1874 1389 pushl_cfi %eax
d211af05 1390 SAVE_ALL
d211af05
AH
1391 FIXUP_ESPFIX_STACK # %eax == %esp
1392 xorl %edx,%edx # zero error code
1393 call do_nmi
1394 RESTORE_REGS
1395 lss 12+4(%esp), %esp # back to espfix stack
1396 CFI_ADJUST_CFA_OFFSET -24
1397 jmp irq_return
34273f41 1398#endif
d211af05
AH
1399 CFI_ENDPROC
1400END(nmi)
1401
1402ENTRY(int3)
1403 RING0_INT_FRAME
e59d1b0a 1404 ASM_CLAC
df5d1874 1405 pushl_cfi $-1 # mark this as an int
d211af05
AH
1406 SAVE_ALL
1407 TRACE_IRQS_OFF
1408 xorl %edx,%edx # zero error code
1409 movl %esp,%eax # pt_regs pointer
1410 call do_int3
1411 jmp ret_from_exception
1412 CFI_ENDPROC
1413END(int3)
1414
1415ENTRY(general_protection)
1416 RING0_EC_FRAME
df5d1874 1417 pushl_cfi $do_general_protection
d211af05
AH
1418 jmp error_code
1419 CFI_ENDPROC
1420END(general_protection)
1421
631bc487
GN
1422#ifdef CONFIG_KVM_GUEST
1423ENTRY(async_page_fault)
1424 RING0_EC_FRAME
e59d1b0a 1425 ASM_CLAC
60cf637a 1426 pushl_cfi $do_async_page_fault
631bc487
GN
1427 jmp error_code
1428 CFI_ENDPROC
2ae9d293 1429END(async_page_fault)
631bc487
GN
1430#endif
1431
This page took 0.827519 seconds and 5 git commands to generate.