[PATCH] [POWERPC] convert transfer_to_handler into a macro
Kumar Gala
galak at kernel.crashing.org
Tue Apr 29 23:56:56 EST 2008
We need to have unique transfer_to_handler paths for each exception level
that is supported. We need to use the proper xSRR0/1 depending on which
exception level the interrupt was from. The macro conversion lets up
templatize this code path.
Signed-off-by: Kumar Gala <galak at kernel.crashing.org>
---
Paul,
I request you apply this for v2.6.26. I know its a bit late in the game
but I'd prefer to get this in so reduce churn later. Also, I've built this
version on pmac_defconfig, ppc40x_defconfig, and ppc44x_config and compared
the objdump output to ensure that the code is identical before and after
this patch.
- k
arch/powerpc/kernel/entry_32.S | 191 ++++++++++++++++++++++------------------
1 files changed, 106 insertions(+), 85 deletions(-)
diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S
index 0c8614d..7710a02 100644
--- a/arch/powerpc/kernel/entry_32.S
+++ b/arch/powerpc/kernel/entry_32.S
@@ -43,6 +43,111 @@
#define LOAD_MSR_KERNEL(r, x) li r,(x)
#endif
+#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
+#ifdef CONFIG_SMP
+#define SMP_ADJUST_GLOBAL_DBCR0 \
+ rlwinm r9,r1,0,0,(31-THREAD_SHIFT); \
+ lwz r9,TI_CPU(r9); \
+ slwi r9,r9,3; \
+ add r11,r11,r9;
+#else
+#define SMP_ADJUST_GLOBAL_DBCR0
+#endif
+#define HANDLE_DBCR \
+ /* Check to see if the dbcr0 register is set up to debug. Use the \
+ internal debug mode bit to do this. */ \
+ lwz r12,THREAD_DBCR0(r12); \
+ andis. r12,r12,DBCR0_IDM at h; \
+ beq+ 3f; \
+ /* From user and task is ptraced - load up global dbcr0 */ \
+ li r12,-1; /* clear all pending debug events */ \
+ mtspr SPRN_DBSR,r12; \
+ lis r11,global_dbcr0 at ha; \
+ tophys(r11,r11); \
+ addi r11,r11,global_dbcr0 at l; \
+ SMP_ADJUST_GLOBAL_DBCR0; \
+ lwz r12,0(r11); \
+ mtspr SPRN_DBCR0,r12; \
+ lwz r12,4(r11); \
+ addi r12,r12,-1; \
+ stw r12,4(r11);
+#else
+#define HANDLE_DBCR
+#endif
+
+#ifdef CONFIG_6xx
+#define CHECK_DOZE_NAP \
+ rlwinm r9,r1,0,0,31-THREAD_SHIFT; \
+ tophys(r9,r9); /* check local flags */ \
+ lwz r12,TI_LOCAL_FLAGS(r9); \
+ mtcrf 0x01,r12; \
+ bt- 31-TLF_NAPPING,4f;
+#define RESTORE_DOZE_NAP \
+4: rlwinm r12,r12,0,~_TLF_NAPPING; \
+ stw r12,TI_LOCAL_FLAGS(r9); \
+ b power_save_6xx_restore;
+#else
+#define RESTORE_DOZE_NAP
+#define CHECK_DOZE_NAP
+#endif /* CONFIG_6xx */
+
+/*
+ * This code finishes saving the registers to the exception frame
+ * and jumps to the appropriate handler for the exception, turning
+ * on address translation.
+ * Note that we rely on the caller having set cr0.eq iff the exception
+ * occurred in kernel mode (i.e. MSR:PR = 0).
+ */
+
+#define TRANSFER_TO_HANDLER(prefix, exc_lvl_srr0, exc_lvl_srr1, exc_lvl_rfi) \
+ .globl prefix##transfer_to_handler_full; \
+prefix##transfer_to_handler_full: \
+ SAVE_NVGPRS(r11); \
+ /* fall through */ \
+ \
+ .globl prefix##transfer_to_handler; \
+prefix##transfer_to_handler: \
+ stw r2,GPR2(r11); \
+ stw r12,_NIP(r11); \
+ stw r9,_MSR(r11); \
+ andi. r2,r9,MSR_PR; \
+ mfctr r12; \
+ mfspr r2,SPRN_XER; \
+ stw r12,_CTR(r11); \
+ stw r2,_XER(r11); \
+ mfspr r12,SPRN_SPRG3; \
+ addi r2,r12,-THREAD; \
+ tovirt(r2,r2); /* set r2 to current */ \
+ beq 2f; /* if from user, fix up THREAD.regs */ \
+ \
+ addi r11,r1,STACK_FRAME_OVERHEAD; \
+ stw r11,PT_REGS(r12); \
+ HANDLE_DBCR; \
+ b 3f; \
+ \
+2: /* if from kernel, check interrupted DOZE/NAP mode and \
+ * check for stack overflow \
+ */ \
+ lwz r9,KSP_LIMIT(r12); \
+ cmplw r1,r9; /* if r1 <= ksp_limit */ \
+ ble- stack_ovf; /* then the kernel stack overflowed */ \
+5: \
+ CHECK_DOZE_NAP; \
+ \
+ .globl prefix##transfer_to_handler_cont; \
+prefix##transfer_to_handler_cont: \
+3: \
+ mflr r9; \
+ lwz r11,0(r9); /* virtual address of handler */ \
+ lwz r9,4(r9); /* where to go when done */ \
+ mtspr exc_lvl_srr0,r11; \
+ mtspr exc_lvl_srr1,r10; \
+ mtlr r9; \
+ SYNC; \
+ exc_lvl_rfi; /* jump to handler, enable MMU */ \
+ \
+ RESTORE_DOZE_NAP;
+
#ifdef CONFIG_BOOKE
#include "head_booke.h"
#define TRANSFER_TO_HANDLER_EXC_LEVEL(exc_level) \
@@ -80,91 +185,7 @@ crit_transfer_to_handler:
/* fall through */
#endif
-/*
- * This code finishes saving the registers to the exception frame
- * and jumps to the appropriate handler for the exception, turning
- * on address translation.
- * Note that we rely on the caller having set cr0.eq iff the exception
- * occurred in kernel mode (i.e. MSR:PR = 0).
- */
- .globl transfer_to_handler_full
-transfer_to_handler_full:
- SAVE_NVGPRS(r11)
- /* fall through */
-
- .globl transfer_to_handler
-transfer_to_handler:
- stw r2,GPR2(r11)
- stw r12,_NIP(r11)
- stw r9,_MSR(r11)
- andi. r2,r9,MSR_PR
- mfctr r12
- mfspr r2,SPRN_XER
- stw r12,_CTR(r11)
- stw r2,_XER(r11)
- mfspr r12,SPRN_SPRG3
- addi r2,r12,-THREAD
- tovirt(r2,r2) /* set r2 to current */
- beq 2f /* if from user, fix up THREAD.regs */
- addi r11,r1,STACK_FRAME_OVERHEAD
- stw r11,PT_REGS(r12)
-#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
- /* Check to see if the dbcr0 register is set up to debug. Use the
- internal debug mode bit to do this. */
- lwz r12,THREAD_DBCR0(r12)
- andis. r12,r12,DBCR0_IDM at h
- beq+ 3f
- /* From user and task is ptraced - load up global dbcr0 */
- li r12,-1 /* clear all pending debug events */
- mtspr SPRN_DBSR,r12
- lis r11,global_dbcr0 at ha
- tophys(r11,r11)
- addi r11,r11,global_dbcr0 at l
-#ifdef CONFIG_SMP
- rlwinm r9,r1,0,0,(31-THREAD_SHIFT)
- lwz r9,TI_CPU(r9)
- slwi r9,r9,3
- add r11,r11,r9
-#endif
- lwz r12,0(r11)
- mtspr SPRN_DBCR0,r12
- lwz r12,4(r11)
- addi r12,r12,-1
- stw r12,4(r11)
-#endif
- b 3f
-
-2: /* if from kernel, check interrupted DOZE/NAP mode and
- * check for stack overflow
- */
- lwz r9,KSP_LIMIT(r12)
- cmplw r1,r9 /* if r1 <= ksp_limit */
- ble- stack_ovf /* then the kernel stack overflowed */
-5:
-#ifdef CONFIG_6xx
- rlwinm r9,r1,0,0,31-THREAD_SHIFT
- tophys(r9,r9) /* check local flags */
- lwz r12,TI_LOCAL_FLAGS(r9)
- mtcrf 0x01,r12
- bt- 31-TLF_NAPPING,4f
-#endif /* CONFIG_6xx */
- .globl transfer_to_handler_cont
-transfer_to_handler_cont:
-3:
- mflr r9
- lwz r11,0(r9) /* virtual address of handler */
- lwz r9,4(r9) /* where to go when done */
- mtspr SPRN_SRR0,r11
- mtspr SPRN_SRR1,r10
- mtlr r9
- SYNC
- RFI /* jump to handler, enable MMU */
-
-#ifdef CONFIG_6xx
-4: rlwinm r12,r12,0,~_TLF_NAPPING
- stw r12,TI_LOCAL_FLAGS(r9)
- b power_save_6xx_restore
-#endif
+ TRANSFER_TO_HANDLER(, SPRN_SRR0, SPRN_SRR1, RFI);
/*
* On kernel stack overflow, load up an initial stack pointer
--
1.5.4.1
More information about the Linuxppc-dev
mailing list