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 <[EMAIL PROTECTED]>
---

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,[EMAIL PROTECTED];                                      
       \
+       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,[EMAIL PROTECTED];                                         \
+       tophys(r11,r11);                                                       \
+       addi    r11,r11,[EMAIL PROTECTED];                                      
       \
+       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,[EMAIL PROTECTED]
-       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,[EMAIL PROTECTED]
-       tophys(r11,r11)
-       addi    r11,r11,[EMAIL PROTECTED]
-#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

_______________________________________________
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev

Reply via email to