aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/entry_32.S
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/kernel/entry_32.S')
-rw-r--r--arch/x86/kernel/entry_32.S162
1 files changed, 139 insertions, 23 deletions
diff --git a/arch/x86/kernel/entry_32.S b/arch/x86/kernel/entry_32.S
index c778e4fa55a2..109792bc7cfa 100644
--- a/arch/x86/kernel/entry_32.S
+++ b/arch/x86/kernel/entry_32.S
@@ -51,14 +51,25 @@
51#include <asm/percpu.h> 51#include <asm/percpu.h>
52#include <asm/dwarf2.h> 52#include <asm/dwarf2.h>
53#include <asm/processor-flags.h> 53#include <asm/processor-flags.h>
54#include "irq_vectors.h" 54#include <asm/ftrace.h>
55#include <asm/irq_vectors.h>
56
57/* Avoid __ASSEMBLER__'ifying <linux/audit.h> just for this. */
58#include <linux/elf-em.h>
59#define AUDIT_ARCH_I386 (EM_386|__AUDIT_ARCH_LE)
60#define __AUDIT_ARCH_LE 0x40000000
61
62#ifndef CONFIG_AUDITSYSCALL
63#define sysenter_audit syscall_trace_entry
64#define sysexit_audit syscall_exit_work
65#endif
55 66
56/* 67/*
57 * We use macros for low-level operations which need to be overridden 68 * We use macros for low-level operations which need to be overridden
58 * for paravirtualization. The following will never clobber any registers: 69 * for paravirtualization. The following will never clobber any registers:
59 * INTERRUPT_RETURN (aka. "iret") 70 * INTERRUPT_RETURN (aka. "iret")
60 * GET_CR0_INTO_EAX (aka. "movl %cr0, %eax") 71 * GET_CR0_INTO_EAX (aka. "movl %cr0, %eax")
61 * ENABLE_INTERRUPTS_SYSCALL_RET (aka "sti; sysexit"). 72 * ENABLE_INTERRUPTS_SYSEXIT (aka "sti; sysexit").
62 * 73 *
63 * For DISABLE_INTERRUPTS/ENABLE_INTERRUPTS (aka "cli"/"sti"), you must 74 * For DISABLE_INTERRUPTS/ENABLE_INTERRUPTS (aka "cli"/"sti"), you must
64 * specify what registers can be overwritten (CLBR_NONE, CLBR_EAX/EDX/ECX/ANY). 75 * specify what registers can be overwritten (CLBR_NONE, CLBR_EAX/EDX/ECX/ANY).
@@ -331,8 +342,9 @@ sysenter_past_esp:
331 GET_THREAD_INFO(%ebp) 342 GET_THREAD_INFO(%ebp)
332 343
333 /* Note, _TIF_SECCOMP is bit number 8, and so it needs testw and not testb */ 344 /* Note, _TIF_SECCOMP is bit number 8, and so it needs testw and not testb */
334 testw $(_TIF_SYSCALL_EMU|_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT),TI_flags(%ebp) 345 testw $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%ebp)
335 jnz syscall_trace_entry 346 jnz sysenter_audit
347sysenter_do_call:
336 cmpl $(nr_syscalls), %eax 348 cmpl $(nr_syscalls), %eax
337 jae syscall_badsys 349 jae syscall_badsys
338 call *sys_call_table(,%eax,4) 350 call *sys_call_table(,%eax,4)
@@ -342,14 +354,54 @@ sysenter_past_esp:
342 TRACE_IRQS_OFF 354 TRACE_IRQS_OFF
343 movl TI_flags(%ebp), %ecx 355 movl TI_flags(%ebp), %ecx
344 testw $_TIF_ALLWORK_MASK, %cx 356 testw $_TIF_ALLWORK_MASK, %cx
345 jne syscall_exit_work 357 jne sysexit_audit
358sysenter_exit:
346/* if something modifies registers it must also disable sysexit */ 359/* if something modifies registers it must also disable sysexit */
347 movl PT_EIP(%esp), %edx 360 movl PT_EIP(%esp), %edx
348 movl PT_OLDESP(%esp), %ecx 361 movl PT_OLDESP(%esp), %ecx
349 xorl %ebp,%ebp 362 xorl %ebp,%ebp
350 TRACE_IRQS_ON 363 TRACE_IRQS_ON
3511: mov PT_FS(%esp), %fs 3641: mov PT_FS(%esp), %fs
352 ENABLE_INTERRUPTS_SYSCALL_RET 365 ENABLE_INTERRUPTS_SYSEXIT
366
367#ifdef CONFIG_AUDITSYSCALL
368sysenter_audit:
369 testw $(_TIF_WORK_SYSCALL_ENTRY & ~_TIF_SYSCALL_AUDIT),TI_flags(%ebp)
370 jnz syscall_trace_entry
371 addl $4,%esp
372 CFI_ADJUST_CFA_OFFSET -4
373 /* %esi already in 8(%esp) 6th arg: 4th syscall arg */
374 /* %edx already in 4(%esp) 5th arg: 3rd syscall arg */
375 /* %ecx already in 0(%esp) 4th arg: 2nd syscall arg */
376 movl %ebx,%ecx /* 3rd arg: 1st syscall arg */
377 movl %eax,%edx /* 2nd arg: syscall number */
378 movl $AUDIT_ARCH_I386,%eax /* 1st arg: audit arch */
379 call audit_syscall_entry
380 pushl %ebx
381 CFI_ADJUST_CFA_OFFSET 4
382 movl PT_EAX(%esp),%eax /* reload syscall number */
383 jmp sysenter_do_call
384
385sysexit_audit:
386 testw $(_TIF_ALLWORK_MASK & ~_TIF_SYSCALL_AUDIT), %cx
387 jne syscall_exit_work
388 TRACE_IRQS_ON
389 ENABLE_INTERRUPTS(CLBR_ANY)
390 movl %eax,%edx /* second arg, syscall return value */
391 cmpl $0,%eax /* is it < 0? */
392 setl %al /* 1 if so, 0 if not */
393 movzbl %al,%eax /* zero-extend that */
394 inc %eax /* first arg, 0->1(AUDITSC_SUCCESS), 1->2(AUDITSC_FAILURE) */
395 call audit_syscall_exit
396 DISABLE_INTERRUPTS(CLBR_ANY)
397 TRACE_IRQS_OFF
398 movl TI_flags(%ebp), %ecx
399 testw $(_TIF_ALLWORK_MASK & ~_TIF_SYSCALL_AUDIT), %cx
400 jne syscall_exit_work
401 movl PT_EAX(%esp),%eax /* reload syscall return value */
402 jmp sysenter_exit
403#endif
404
353 CFI_ENDPROC 405 CFI_ENDPROC
354.pushsection .fixup,"ax" 406.pushsection .fixup,"ax"
3552: movl $0,PT_FS(%esp) 4072: movl $0,PT_FS(%esp)
@@ -369,7 +421,7 @@ ENTRY(system_call)
369 GET_THREAD_INFO(%ebp) 421 GET_THREAD_INFO(%ebp)
370 # system call tracing in operation / emulation 422 # system call tracing in operation / emulation
371 /* Note, _TIF_SECCOMP is bit number 8, and so it needs testw and not testb */ 423 /* Note, _TIF_SECCOMP is bit number 8, and so it needs testw and not testb */
372 testw $(_TIF_SYSCALL_EMU|_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT),TI_flags(%ebp) 424 testw $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%ebp)
373 jnz syscall_trace_entry 425 jnz syscall_trace_entry
374 cmpl $(nr_syscalls), %eax 426 cmpl $(nr_syscalls), %eax
375 jae syscall_badsys 427 jae syscall_badsys
@@ -382,10 +434,6 @@ syscall_exit:
382 # setting need_resched or sigpending 434 # setting need_resched or sigpending
383 # between sampling and the iret 435 # between sampling and the iret
384 TRACE_IRQS_OFF 436 TRACE_IRQS_OFF
385 testl $X86_EFLAGS_TF,PT_EFLAGS(%esp) # If tracing set singlestep flag on exit
386 jz no_singlestep
387 orl $_TIF_SINGLESTEP,TI_flags(%ebp)
388no_singlestep:
389 movl TI_flags(%ebp), %ecx 437 movl TI_flags(%ebp), %ecx
390 testw $_TIF_ALLWORK_MASK, %cx # current->work 438 testw $_TIF_ALLWORK_MASK, %cx # current->work
391 jne syscall_exit_work 439 jne syscall_exit_work
@@ -513,12 +561,8 @@ END(work_pending)
513syscall_trace_entry: 561syscall_trace_entry:
514 movl $-ENOSYS,PT_EAX(%esp) 562 movl $-ENOSYS,PT_EAX(%esp)
515 movl %esp, %eax 563 movl %esp, %eax
516 xorl %edx,%edx 564 call syscall_trace_enter
517 call do_syscall_trace 565 /* What it returned is what we'll actually use. */
518 cmpl $0, %eax
519 jne resume_userspace # ret != 0 -> running under PTRACE_SYSEMU,
520 # so must skip actual syscall
521 movl PT_ORIG_EAX(%esp), %eax
522 cmpl $(nr_syscalls), %eax 566 cmpl $(nr_syscalls), %eax
523 jnae syscall_call 567 jnae syscall_call
524 jmp syscall_exit 568 jmp syscall_exit
@@ -527,14 +571,13 @@ END(syscall_trace_entry)
527 # perform syscall exit tracing 571 # perform syscall exit tracing
528 ALIGN 572 ALIGN
529syscall_exit_work: 573syscall_exit_work:
530 testb $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP), %cl 574 testb $_TIF_WORK_SYSCALL_EXIT, %cl
531 jz work_pending 575 jz work_pending
532 TRACE_IRQS_ON 576 TRACE_IRQS_ON
533 ENABLE_INTERRUPTS(CLBR_ANY) # could let do_syscall_trace() call 577 ENABLE_INTERRUPTS(CLBR_ANY) # could let syscall_trace_leave() call
534 # schedule() instead 578 # schedule() instead
535 movl %esp, %eax 579 movl %esp, %eax
536 movl $1, %edx 580 call syscall_trace_leave
537 call do_syscall_trace
538 jmp resume_userspace 581 jmp resume_userspace
539END(syscall_exit_work) 582END(syscall_exit_work)
540 CFI_ENDPROC 583 CFI_ENDPROC
@@ -874,10 +917,10 @@ ENTRY(native_iret)
874.previous 917.previous
875END(native_iret) 918END(native_iret)
876 919
877ENTRY(native_irq_enable_syscall_ret) 920ENTRY(native_irq_enable_sysexit)
878 sti 921 sti
879 sysexit 922 sysexit
880END(native_irq_enable_syscall_ret) 923END(native_irq_enable_sysexit)
881#endif 924#endif
882 925
883KPROBE_ENTRY(int3) 926KPROBE_ENTRY(int3)
@@ -1023,7 +1066,9 @@ ENDPROC(kernel_thread_helper)
1023ENTRY(xen_sysenter_target) 1066ENTRY(xen_sysenter_target)
1024 RING0_INT_FRAME 1067 RING0_INT_FRAME
1025 addl $5*4, %esp /* remove xen-provided frame */ 1068 addl $5*4, %esp /* remove xen-provided frame */
1069 CFI_ADJUST_CFA_OFFSET -5*4
1026 jmp sysenter_past_esp 1070 jmp sysenter_past_esp
1071 CFI_ENDPROC
1027 1072
1028ENTRY(xen_hypervisor_callback) 1073ENTRY(xen_hypervisor_callback)
1029 CFI_STARTPROC 1074 CFI_STARTPROC
@@ -1110,6 +1155,77 @@ ENDPROC(xen_failsafe_callback)
1110 1155
1111#endif /* CONFIG_XEN */ 1156#endif /* CONFIG_XEN */
1112 1157
1158#ifdef CONFIG_FTRACE
1159#ifdef CONFIG_DYNAMIC_FTRACE
1160
1161ENTRY(mcount)
1162 pushl %eax
1163 pushl %ecx
1164 pushl %edx
1165 movl 0xc(%esp), %eax
1166 subl $MCOUNT_INSN_SIZE, %eax
1167
1168.globl mcount_call
1169mcount_call:
1170 call ftrace_stub
1171
1172 popl %edx
1173 popl %ecx
1174 popl %eax
1175
1176 ret
1177END(mcount)
1178
1179ENTRY(ftrace_caller)
1180 pushl %eax
1181 pushl %ecx
1182 pushl %edx
1183 movl 0xc(%esp), %eax
1184 movl 0x4(%ebp), %edx
1185 subl $MCOUNT_INSN_SIZE, %eax
1186
1187.globl ftrace_call
1188ftrace_call:
1189 call ftrace_stub
1190
1191 popl %edx
1192 popl %ecx
1193 popl %eax
1194
1195.globl ftrace_stub
1196ftrace_stub:
1197 ret
1198END(ftrace_caller)
1199
1200#else /* ! CONFIG_DYNAMIC_FTRACE */
1201
1202ENTRY(mcount)
1203 cmpl $ftrace_stub, ftrace_trace_function
1204 jnz trace
1205.globl ftrace_stub
1206ftrace_stub:
1207 ret
1208
1209 /* taken from glibc */
1210trace:
1211 pushl %eax
1212 pushl %ecx
1213 pushl %edx
1214 movl 0xc(%esp), %eax
1215 movl 0x4(%ebp), %edx
1216 subl $MCOUNT_INSN_SIZE, %eax
1217
1218 call *ftrace_trace_function
1219
1220 popl %edx
1221 popl %ecx
1222 popl %eax
1223
1224 jmp ftrace_stub
1225END(mcount)
1226#endif /* CONFIG_DYNAMIC_FTRACE */
1227#endif /* CONFIG_FTRACE */
1228
1113.section .rodata,"a" 1229.section .rodata,"a"
1114#include "syscall_table_32.S" 1230#include "syscall_table_32.S"
1115 1231