浏览代码

powerpc: Fix fatal SLB miss when restoring PPR

When restoring the PPR value, we incorrectly access the thread structure
at a time where MSR:RI is clear, which means we cannot recover from nested
faults. However the thread structure isn't covered by the "bolted" SLB
entries and thus accessing can fault.

This fixes it by splitting the code so that the PPR value is loaded into
a GPR before MSR:RI is cleared.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Benjamin Herrenschmidt 11 年之前
父节点
当前提交
0c4888ef1d
共有 2 个文件被更改,包括 9 次插入8 次删除
  1. 0 7
      arch/powerpc/include/asm/ppc_asm.h
  2. 9 1
      arch/powerpc/kernel/entry_64.S

+ 0 - 7
arch/powerpc/include/asm/ppc_asm.h

@@ -406,13 +406,6 @@ BEGIN_FTR_SECTION_NESTED(945)						\
 	std	ra,TASKTHREADPPR(rb);					\
 	std	ra,TASKTHREADPPR(rb);					\
 END_FTR_SECTION_NESTED(CPU_FTR_HAS_PPR,CPU_FTR_HAS_PPR,945)
 END_FTR_SECTION_NESTED(CPU_FTR_HAS_PPR,CPU_FTR_HAS_PPR,945)
 
 
-#define RESTORE_PPR(ra, rb)						\
-BEGIN_FTR_SECTION_NESTED(946)						\
-	ld	ra,PACACURRENT(r13);					\
-	ld	rb,TASKTHREADPPR(ra);					\
-	mtspr	SPRN_PPR,rb;	/* Restore PPR */			\
-END_FTR_SECTION_NESTED(CPU_FTR_HAS_PPR,CPU_FTR_HAS_PPR,946)
-
 #endif
 #endif
 
 
 /*
 /*

+ 9 - 1
arch/powerpc/kernel/entry_64.S

@@ -818,6 +818,12 @@ fast_exception_return:
 	andi.	r0,r3,MSR_RI
 	andi.	r0,r3,MSR_RI
 	beq-	unrecov_restore
 	beq-	unrecov_restore
 
 
+	/* Load PPR from thread struct before we clear MSR:RI */
+BEGIN_FTR_SECTION
+	ld	r2,PACACURRENT(r13)
+	ld	r2,TASKTHREADPPR(r2)
+END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR)
+
 	/*
 	/*
 	 * Clear RI before restoring r13.  If we are returning to
 	 * Clear RI before restoring r13.  If we are returning to
 	 * userspace and we take an exception after restoring r13,
 	 * userspace and we take an exception after restoring r13,
@@ -838,8 +844,10 @@ fast_exception_return:
 	 */
 	 */
 	andi.	r0,r3,MSR_PR
 	andi.	r0,r3,MSR_PR
 	beq	1f
 	beq	1f
+BEGIN_FTR_SECTION
+	mtspr	SPRN_PPR,r2	/* Restore PPR */
+END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR)
 	ACCOUNT_CPU_USER_EXIT(r2, r4)
 	ACCOUNT_CPU_USER_EXIT(r2, r4)
-	RESTORE_PPR(r2, r4)
 	REST_GPR(13, r1)
 	REST_GPR(13, r1)
 1:
 1:
 	mtspr	SPRN_SRR1,r3
 	mtspr	SPRN_SRR1,r3