Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris...
[sfrench/cifs-2.6.git] / arch / powerpc / kernel / entry_32.S
index ead5016b02d020c32741e5f6d122736eb907d083..af37528da49fff06ef7b47fb2e9add01dd6b1caa 100644 (file)
@@ -831,19 +831,56 @@ restore_user:
        bnel-   load_dbcr0
 #endif
 
-#ifdef CONFIG_PREEMPT
        b       restore
 
 /* N.B. the only way to get here is from the beq following ret_from_except. */
 resume_kernel:
-       /* check current_thread_info->preempt_count */
+       /* check current_thread_info, _TIF_EMULATE_STACK_STORE */
        CURRENT_THREAD_INFO(r9, r1)
+       lwz     r8,TI_FLAGS(r9)
+       andis.  r8,r8,_TIF_EMULATE_STACK_STORE@h
+       beq+    1f
+
+       addi    r8,r1,INT_FRAME_SIZE    /* Get the kprobed function entry */
+
+       lwz     r3,GPR1(r1)
+       subi    r3,r3,INT_FRAME_SIZE    /* dst: Allocate a trampoline exception frame */
+       mr      r4,r1                   /* src:  current exception frame */
+       mr      r1,r3                   /* Reroute the trampoline frame to r1 */
+
+       /* Copy from the original to the trampoline. */
+       li      r5,INT_FRAME_SIZE/4     /* size: INT_FRAME_SIZE */
+       li      r6,0                    /* start offset: 0 */
+       mtctr   r5
+2:     lwzx    r0,r6,r4
+       stwx    r0,r6,r3
+       addi    r6,r6,4
+       bdnz    2b
+
+       /* Do real store operation to complete stwu */
+       lwz     r5,GPR1(r1)
+       stw     r8,0(r5)
+
+       /* Clear _TIF_EMULATE_STACK_STORE flag */
+       lis     r11,_TIF_EMULATE_STACK_STORE@h
+       addi    r5,r9,TI_FLAGS
+0:     lwarx   r8,0,r5
+       andc    r8,r8,r11
+#ifdef CONFIG_IBM405_ERR77
+       dcbt    0,r5
+#endif
+       stwcx.  r8,0,r5
+       bne-    0b
+1:
+
+#ifdef CONFIG_PREEMPT
+       /* check current_thread_info->preempt_count */
        lwz     r0,TI_PREEMPT(r9)
        cmpwi   0,r0,0          /* if non-zero, just restore regs and return */
        bne     restore
-       lwz     r0,TI_FLAGS(r9)
-       andi.   r0,r0,_TIF_NEED_RESCHED
+       andi.   r8,r8,_TIF_NEED_RESCHED
        beq+    restore
+       lwz     r3,_MSR(r1)
        andi.   r0,r3,MSR_EE    /* interrupts off? */
        beq     restore         /* don't schedule if so */
 #ifdef CONFIG_TRACE_IRQFLAGS
@@ -864,8 +901,6 @@ resume_kernel:
         */
        bl      trace_hardirqs_on
 #endif
-#else
-resume_kernel:
 #endif /* CONFIG_PREEMPT */
 
        /* interrupts are hard-disabled at this point */