]> err.no Git - linux-2.6/blobdiff - arch/x86/kernel/entry_64.S
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6
[linux-2.6] / arch / x86 / kernel / entry_64.S
index 6aa6932e21b172283e0a604d2391782776ed7629..89434d439605484b48a7b26ba31c55e82c9821c5 100644 (file)
 #include <asm/paravirt.h>
 #include <asm/ftrace.h>
 
+/* Avoid __ASSEMBLER__'ifying <linux/audit.h> just for this.  */
+#include <linux/elf-em.h>
+#define AUDIT_ARCH_X86_64      (EM_X86_64|__AUDIT_ARCH_64BIT|__AUDIT_ARCH_LE)
+#define __AUDIT_ARCH_64BIT 0x80000000
+#define __AUDIT_ARCH_LE           0x40000000
+
        .code64
 
 #ifdef CONFIG_FTRACE
@@ -349,9 +355,9 @@ ENTRY(system_call_after_swapgs)
        movq  %rcx,RIP-ARGOFFSET(%rsp)
        CFI_REL_OFFSET rip,RIP-ARGOFFSET
        GET_THREAD_INFO(%rcx)
-       testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP), \
-               TI_flags(%rcx)
+       testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%rcx)
        jnz tracesys
+system_call_fastpath:
        cmpq $__NR_syscall_max,%rax
        ja badsys
        movq %r10,%rcx
@@ -403,16 +409,16 @@ sysret_careful:
 sysret_signal:
        TRACE_IRQS_ON
        ENABLE_INTERRUPTS(CLBR_NONE)
-       testl $_TIF_DO_NOTIFY_MASK,%edx
-       jz    1f
-
-       /* Really a signal */
+#ifdef CONFIG_AUDITSYSCALL
+       bt $TIF_SYSCALL_AUDIT,%edx
+       jc sysret_audit
+#endif
        /* edx: work flags (arg3) */
        leaq do_notify_resume(%rip),%rax
        leaq -ARGOFFSET(%rsp),%rdi # &pt_regs -> arg1
        xorl %esi,%esi # oldset -> arg2
        call ptregscall_common
-1:     movl $_TIF_WORK_MASK,%edi
+       movl $_TIF_WORK_MASK,%edi
        /* Use IRET because user could have changed frame. This
           works because ptregscall_common has called FIXUP_TOP_OF_STACK. */
        DISABLE_INTERRUPTS(CLBR_NONE)
@@ -423,14 +429,56 @@ badsys:
        movq $-ENOSYS,RAX-ARGOFFSET(%rsp)
        jmp ret_from_sys_call
 
+#ifdef CONFIG_AUDITSYSCALL
+       /*
+        * Fast path for syscall audit without full syscall trace.
+        * We just call audit_syscall_entry() directly, and then
+        * jump back to the normal fast path.
+        */
+auditsys:
+       movq %r10,%r9                   /* 6th arg: 4th syscall arg */
+       movq %rdx,%r8                   /* 5th arg: 3rd syscall arg */
+       movq %rsi,%rcx                  /* 4th arg: 2nd syscall arg */
+       movq %rdi,%rdx                  /* 3rd arg: 1st syscall arg */
+       movq %rax,%rsi                  /* 2nd arg: syscall number */
+       movl $AUDIT_ARCH_X86_64,%edi    /* 1st arg: audit arch */
+       call audit_syscall_entry
+       LOAD_ARGS 0             /* reload call-clobbered registers */
+       jmp system_call_fastpath
+
+       /*
+        * Return fast path for syscall audit.  Call audit_syscall_exit()
+        * directly and then jump back to the fast path with TIF_SYSCALL_AUDIT
+        * masked off.
+        */
+sysret_audit:
+       movq %rax,%rsi          /* second arg, syscall return value */
+       cmpq $0,%rax            /* is it < 0? */
+       setl %al                /* 1 if so, 0 if not */
+       movzbl %al,%edi         /* zero-extend that into %edi */
+       inc %edi /* first arg, 0->1(AUDITSC_SUCCESS), 1->2(AUDITSC_FAILURE) */
+       call audit_syscall_exit
+       movl $(_TIF_ALLWORK_MASK & ~_TIF_SYSCALL_AUDIT),%edi
+       jmp sysret_check
+#endif /* CONFIG_AUDITSYSCALL */
+
        /* Do syscall tracing */
 tracesys:                       
+#ifdef CONFIG_AUDITSYSCALL
+       testl $(_TIF_WORK_SYSCALL_ENTRY & ~_TIF_SYSCALL_AUDIT),TI_flags(%rcx)
+       jz auditsys
+#endif
        SAVE_REST
        movq $-ENOSYS,RAX(%rsp) /* ptrace can change this for a bad syscall */
        FIXUP_TOP_OF_STACK %rdi
        movq %rsp,%rdi
        call syscall_trace_enter
-       LOAD_ARGS ARGOFFSET  /* reload args from stack in case ptrace changed it */
+       /*
+        * Reload arg registers from stack in case ptrace changed them.
+        * We don't reload %rax because syscall_trace_enter() returned
+        * the value it wants us to use in the table lookup.
+        */
+       LOAD_ARGS ARGOFFSET, 1
        RESTORE_REST
        cmpq $__NR_syscall_max,%rax
        ja   int_ret_from_sys_call      /* RAX(%rsp) set to -ENOSYS above */
@@ -444,6 +492,7 @@ tracesys:
  * Has correct top of stack, but partial stack frame.
  */
        .globl int_ret_from_sys_call
+       .globl int_with_check
 int_ret_from_sys_call:
        DISABLE_INTERRUPTS(CLBR_NONE)
        TRACE_IRQS_OFF
@@ -483,7 +532,7 @@ int_very_careful:
        ENABLE_INTERRUPTS(CLBR_NONE)
        SAVE_REST
        /* Check for syscall exit trace */      
-       testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP),%edx
+       testl $_TIF_WORK_SYSCALL_EXIT,%edx
        jz int_signal
        pushq %rdi
        CFI_ADJUST_CFA_OFFSET 8
@@ -491,7 +540,7 @@ int_very_careful:
        call syscall_trace_leave
        popq %rdi
        CFI_ADJUST_CFA_OFFSET -8
-       andl $~(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP),%edi
+       andl $~(_TIF_WORK_SYSCALL_EXIT|_TIF_SYSCALL_EMU),%edi
        jmp int_restore_rest
        
 int_signal:
@@ -1189,6 +1238,7 @@ END(device_not_available)
        /* runs on exception stack */
 KPROBE_ENTRY(debug)
        INTR_FRAME
+       PARAVIRT_ADJUST_EXCEPTION_FRAME
        pushq $0
        CFI_ADJUST_CFA_OFFSET 8         
        paranoidentry do_debug, DEBUG_STACK
@@ -1198,6 +1248,7 @@ KPROBE_END(debug)
        /* runs on exception stack */   
 KPROBE_ENTRY(nmi)
        INTR_FRAME
+       PARAVIRT_ADJUST_EXCEPTION_FRAME
        pushq $-1
        CFI_ADJUST_CFA_OFFSET 8
        paranoidentry do_nmi, 0, 0
@@ -1211,6 +1262,7 @@ KPROBE_END(nmi)
 
 KPROBE_ENTRY(int3)
        INTR_FRAME
+       PARAVIRT_ADJUST_EXCEPTION_FRAME
        pushq $0
        CFI_ADJUST_CFA_OFFSET 8
        paranoidentry do_int3, DEBUG_STACK
@@ -1237,6 +1289,7 @@ END(coprocessor_segment_overrun)
        /* runs on exception stack */
 ENTRY(double_fault)
        XCPT_FRAME
+       PARAVIRT_ADJUST_EXCEPTION_FRAME
        paranoidentry do_double_fault
        jmp paranoid_exit1
        CFI_ENDPROC
@@ -1253,6 +1306,7 @@ END(segment_not_present)
        /* runs on exception stack */
 ENTRY(stack_segment)
        XCPT_FRAME
+       PARAVIRT_ADJUST_EXCEPTION_FRAME
        paranoidentry do_stack_segment
        jmp paranoid_exit1
        CFI_ENDPROC
@@ -1278,6 +1332,7 @@ END(spurious_interrupt_bug)
        /* runs on exception stack */
 ENTRY(machine_check)
        INTR_FRAME
+       PARAVIRT_ADJUST_EXCEPTION_FRAME
        pushq $0
        CFI_ADJUST_CFA_OFFSET 8 
        paranoidentry do_machine_check