Merge tag 'r8169-20060920-00' of git://electric-eye.fr.zoreil.com/home/romieu/linux...
[pandora-kernel.git] / arch / i386 / kernel / entry.S
index 8713e02..87f9f60 100644 (file)
@@ -40,9 +40,9 @@
  * "current" is in register %ebx during any slow entries.
  */
 
-#include <linux/config.h>
 #include <linux/linkage.h>
 #include <asm/thread_info.h>
+#include <asm/irqflags.h>
 #include <asm/errno.h>
 #include <asm/segment.h>
 #include <asm/smp.h>
@@ -77,12 +77,27 @@ NT_MASK             = 0x00004000
 VM_MASK                = 0x00020000
 
 #ifdef CONFIG_PREEMPT
-#define preempt_stop           cli
+#define preempt_stop           cli; TRACE_IRQS_OFF
 #else
 #define preempt_stop
 #define resume_kernel          restore_nocheck
 #endif
 
+.macro TRACE_IRQS_IRET
+#ifdef CONFIG_TRACE_IRQFLAGS
+       testl $IF_MASK,EFLAGS(%esp)     # interrupts off?
+       jz 1f
+       TRACE_IRQS_ON
+1:
+#endif
+.endm
+
+#ifdef CONFIG_VM86
+#define resume_userspace_sig   check_userspace
+#else
+#define resume_userspace_sig   resume_userspace
+#endif
+
 #define SAVE_ALL \
        cld; \
        pushl %es; \
@@ -189,11 +204,15 @@ VM_MASK           = 0x00020000
 ENTRY(ret_from_fork)
        CFI_STARTPROC
        pushl %eax
-       CFI_ADJUST_CFA_OFFSET -4
+       CFI_ADJUST_CFA_OFFSET 4
        call schedule_tail
        GET_THREAD_INFO(%ebp)
        popl %eax
        CFI_ADJUST_CFA_OFFSET -4
+       pushl $0x0202                   # Reset kernel eflags
+       CFI_ADJUST_CFA_OFFSET 4
+       popfl
+       CFI_ADJUST_CFA_OFFSET -4
        jmp syscall_exit
        CFI_ENDPROC
 
@@ -211,6 +230,7 @@ ret_from_exception:
        preempt_stop
 ret_from_intr:
        GET_THREAD_INFO(%ebp)
+check_userspace:
        movl EFLAGS(%esp), %eax         # mix EFLAGS and CS
        movb CS(%esp), %al
        testl $(VM_MASK | 3), %eax
@@ -251,6 +271,10 @@ ENTRY(sysenter_entry)
        CFI_REGISTER esp, ebp
        movl TSS_sysenter_esp0(%esp),%esp
 sysenter_past_esp:
+       /*
+        * No need to follow this irqs on/off section: the syscall
+        * disabled irqs and here we enable it straight after entry:
+        */
        sti
        pushl $(__USER_DS)
        CFI_ADJUST_CFA_OFFSET 4
@@ -263,7 +287,12 @@ sysenter_past_esp:
        pushl $(__USER_CS)
        CFI_ADJUST_CFA_OFFSET 4
        /*CFI_REL_OFFSET cs, 0*/
-       pushl $SYSENTER_RETURN
+       /*
+        * Push current_thread_info()->sysenter_return to the stack.
+        * A tiny bit of offset fixup is necessary - 4*4 means the 4 words
+        * pushed above; +8 corresponds to copy_thread's esp0 setting.
+        */
+       pushl (TI_sysenter_return-THREAD_SIZE+8+4*4)(%esp)
        CFI_ADJUST_CFA_OFFSET 4
        CFI_REL_OFFSET eip, 0
 
@@ -292,6 +321,7 @@ sysenter_past_esp:
        call *sys_call_table(,%eax,4)
        movl %eax,EAX(%esp)
        cli
+       TRACE_IRQS_OFF
        movl TI_flags(%ebp), %ecx
        testw $_TIF_ALLWORK_MASK, %cx
        jne syscall_exit_work
@@ -299,6 +329,7 @@ sysenter_past_esp:
        movl EIP(%esp), %edx
        movl OLDESP(%esp), %ecx
        xorl %ebp,%ebp
+       TRACE_IRQS_ON
        sti
        sysexit
        CFI_ENDPROC
@@ -328,6 +359,7 @@ syscall_exit:
        cli                             # make sure we don't miss an interrupt
                                        # setting need_resched or sigpending
                                        # between sampling and the iret
+       TRACE_IRQS_OFF
        movl TI_flags(%ebp), %ecx
        testw $_TIF_ALLWORK_MASK, %cx   # current->work
        jne syscall_exit_work
@@ -344,12 +376,15 @@ restore_all:
        CFI_REMEMBER_STATE
        je ldt_ss                       # returning to user-space with LDT SS
 restore_nocheck:
+       TRACE_IRQS_IRET
+restore_nocheck_notrace:
        RESTORE_REGS
        addl $4, %esp
        CFI_ADJUST_CFA_OFFSET -4
 1:     iret
 .section .fixup,"ax"
 iret_exc:
+       TRACE_IRQS_ON
        sti
        pushl $0                        # no error code
        pushl $do_iret_error
@@ -375,11 +410,13 @@ ldt_ss:
        subl $8, %esp           # reserve space for switch16 pointer
        CFI_ADJUST_CFA_OFFSET 8
        cli
+       TRACE_IRQS_OFF
        movl %esp, %eax
        /* Set up the 16bit stack frame with switch32 pointer on top,
         * and a switch16 pointer on top of the current frame. */
        call setup_x86_bogus_stack
        CFI_ADJUST_CFA_OFFSET -8        # frame has moved
+       TRACE_IRQS_IRET
        RESTORE_REGS
        lss 20+4(%esp), %esp    # switch to 16bit stack
 1:     iret
@@ -400,6 +437,7 @@ work_resched:
        cli                             # make sure we don't miss an interrupt
                                        # setting need_resched or sigpending
                                        # between sampling and the iret
+       TRACE_IRQS_OFF
        movl TI_flags(%ebp), %ecx
        andl $_TIF_WORK_MASK, %ecx      # is there any work to be done other
                                        # than syscall tracing?
@@ -415,7 +453,7 @@ work_notifysig:                             # deal with pending signals and
                                        # vm86-space
        xorl %edx, %edx
        call do_notify_resume
-       jmp resume_userspace
+       jmp resume_userspace_sig
 
        ALIGN
 work_notifysig_v86:
@@ -428,7 +466,7 @@ work_notifysig_v86:
        movl %eax, %esp
        xorl %edx, %edx
        call do_notify_resume
-       jmp resume_userspace
+       jmp resume_userspace_sig
 #endif
 
        # perform syscall exit tracing
@@ -451,6 +489,7 @@ syscall_trace_entry:
 syscall_exit_work:
        testb $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP), %cl
        jz work_pending
+       TRACE_IRQS_ON
        sti                             # could let do_syscall_trace() call
                                        # schedule() instead
        movl %esp, %eax
@@ -524,9 +563,14 @@ ENTRY(irq_entries_start)
 vector=vector+1
 .endr
 
+/*
+ * the CPU automatically disables interrupts when executing an IRQ vector,
+ * so IRQ-flags tracing has to follow that:
+ */
        ALIGN
 common_interrupt:
        SAVE_ALL
+       TRACE_IRQS_OFF
        movl %esp,%eax
        call do_IRQ
        jmp ret_from_intr
@@ -538,9 +582,10 @@ ENTRY(name)                                \
        pushl $~(nr);                   \
        CFI_ADJUST_CFA_OFFSET 4;        \
        SAVE_ALL;                       \
+       TRACE_IRQS_OFF                  \
        movl %esp,%eax;                 \
        call smp_/**/name;              \
-       jmp ret_from_intr;      \
+       jmp ret_from_intr;              \
        CFI_ENDPROC
 
 /* The include is where all of the SMP etc. interrupts come from */
@@ -715,7 +760,7 @@ nmi_stack_correct:
        xorl %edx,%edx          # zero error code
        movl %esp,%eax          # pt_regs pointer
        call do_nmi
-       jmp restore_all
+       jmp restore_nocheck_notrace
        CFI_ENDPROC
 
 nmi_stack_fixup: