[POWERPC] Clear RI bit in MSR before restoring r13 when returning to userspace
authorPaul Mackerras <paulus@samba.org>
Wed, 7 Feb 2007 02:13:26 +0000 (13:13 +1100)
committerPaul Mackerras <paulus@samba.org>
Wed, 7 Feb 2007 03:03:23 +0000 (14:03 +1100)
Some instruction tracing tools use the RI (recoverable interrupt) bit
in the MSR to indicate when it's safe to single-step.  Currently we
clear RI after restoring r13 when returning to userspace.  However,
if we single-step past the point where r13 is restored, we'll corrupt
r13 in the exception entry code and not restore it.  This moves the
clearing of RI to just before r13 is restored so this doesn't happen.

Signed-off-by: Paul Mackerras <paulus@samba.org>
arch/powerpc/kernel/entry_64.S

index 2551c0884afcd178d957ce02304ccef119e5870d..2b66d53dcc55fbf5f7d4d52d7ba0d3c1bbc8bc8d 100644 (file)
@@ -172,13 +172,18 @@ syscall_error_cont:
        stdcx.  r0,0,r1                 /* to clear the reservation */
        andi.   r6,r8,MSR_PR
        ld      r4,_LINK(r1)
+       /*
+        * Clear RI before restoring r13.  If we are returning to
+        * userspace and we take an exception after restoring r13,
+        * we end up corrupting the userspace r13 value.
+        */
+       li      r12,MSR_RI
+       andc    r11,r10,r12
+       mtmsrd  r11,1                   /* clear MSR.RI */
        beq-    1f
        ACCOUNT_CPU_USER_EXIT(r11, r12)
        ld      r13,GPR13(r1)   /* only restore r13 if returning to usermode */
 1:     ld      r2,GPR2(r1)
-       li      r12,MSR_RI
-       andc    r11,r10,r12
-       mtmsrd  r11,1                   /* clear MSR.RI */
        ld      r1,GPR1(r1)
        mtlr    r4
        mtcr    r5
@@ -488,42 +493,44 @@ END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
 #endif
        stb     r5,PACASOFTIRQEN(r13)
 
+       /* extract EE bit and use it to restore paca->hard_enabled */
        ld      r3,_MSR(r1)
+       rldicl  r4,r3,49,63             /* r0 = (r3 >> 15) & 1 */
+       stb     r4,PACAHARDIRQEN(r13)
+
+       ld      r4,_CTR(r1)
+       ld      r0,_LINK(r1)
+       mtctr   r4
+       mtlr    r0
+       ld      r4,_XER(r1)
+       mtspr   SPRN_XER,r4
+
+       REST_8GPRS(5, r1)
+
        andi.   r0,r3,MSR_RI
        beq-    unrecov_restore
 
-       /* extract EE bit and use it to restore paca->hard_enabled */
-       rldicl  r4,r3,49,63             /* r0 = (r3 >> 15) & 1 */
-       stb     r4,PACAHARDIRQEN(r13)
+       stdcx.  r0,0,r1         /* to clear the reservation */
 
-       andi.   r0,r3,MSR_PR
+       /*
+        * Clear RI before restoring r13.  If we are returning to
+        * userspace and we take an exception after restoring r13,
+        * we end up corrupting the userspace r13 value.
+        */
+       mfmsr   r4
+       andc    r4,r4,r0        /* r0 contains MSR_RI here */
+       mtmsrd  r4,1
 
        /*
         * r13 is our per cpu area, only restore it if we are returning to
         * userspace
         */
+       andi.   r0,r3,MSR_PR
        beq     1f
-       ACCOUNT_CPU_USER_EXIT(r3, r4)
+       ACCOUNT_CPU_USER_EXIT(r2, r4)
        REST_GPR(13, r1)
 1:
-       ld      r3,_CTR(r1)
-       ld      r0,_LINK(r1)
-       mtctr   r3
-       mtlr    r0
-       ld      r3,_XER(r1)
-       mtspr   SPRN_XER,r3
-
-       REST_8GPRS(5, r1)
-
-       stdcx.  r0,0,r1         /* to clear the reservation */
-
-       mfmsr   r0
-       li      r2, MSR_RI
-       andc    r0,r0,r2
-       mtmsrd  r0,1
-
-       ld      r0,_MSR(r1)
-       mtspr   SPRN_SRR1,r0
+       mtspr   SPRN_SRR1,r3
 
        ld      r2,_CCR(r1)
        mtcrf   0xFF,r2