From e56a6e20f3029ed5c178dd0328bd688dbbc8272a Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Wed, 7 Feb 2007 13:13:26 +1100 Subject: [PATCH] [POWERPC] Clear RI bit in MSR before restoring r13 when returning to userspace 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 --- arch/powerpc/kernel/entry_64.S | 59 +++++++++++++++++++--------------- 1 file changed, 33 insertions(+), 26 deletions(-) diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S index 2551c0884afc..2b66d53dcc55 100644 --- a/arch/powerpc/kernel/entry_64.S +++ b/arch/powerpc/kernel/entry_64.S @@ -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 -- GitLab