Merge branch 'for-linus' of git://neil.brown.name/md
[pandora-kernel.git] / arch / powerpc / kernel / head_booke.h
index aefafc6..fce2df9 100644 (file)
@@ -43,9 +43,7 @@
        SAVE_2GPRS(7, r11)
 
 /* To handle the additional exception priority levels on 40x and Book-E
- * processors we allocate a 4k stack per additional priority level. The various
- * head_xxx.S files allocate space (exception_stack_top) for each priority's
- * stack times the number of CPUs
+ * processors we allocate a stack per additional priority level.
  *
  * On 40x critical is the only additional level
  * On 44x/e500 we have critical and machine check
  * going to critical or their own debug level we aren't currently
  * providing configurations that micro-optimize space usage.
  */
-#ifdef CONFIG_44x
-#define NUM_EXCEPTION_LVLS     2
-#else
-#define NUM_EXCEPTION_LVLS     3
-#endif
-#define BOOKE_EXCEPTION_STACK_SIZE     (4096 * NUM_EXCEPTION_LVLS)
 
 /* CRIT_SPRG only used in critical exception handling */
 #define CRIT_SPRG      SPRN_SPRG2
 /* MCHECK_SPRG only used in machine check exception handling */
 #define MCHECK_SPRG    SPRN_SPRG6W
 
-#define MCHECK_STACK_TOP       (exception_stack_top - 4096)
-#define CRIT_STACK_TOP         (exception_stack_top)
+#define MCHECK_STACK_BASE      mcheckirq_ctx
+#define CRIT_STACK_BASE                critirq_ctx
 
-/* only on e200 for now */
-#define DEBUG_STACK_TOP                (exception_stack_top - 8192)
+/* only on e500mc/e200 */
+#define DEBUG_STACK_BASE       dbgirq_ctx
+#ifdef CONFIG_PPC_E500MC
+#define DEBUG_SPRG             SPRN_SPRG9
+#else
 #define DEBUG_SPRG             SPRN_SPRG6W
+#endif
+
+#define EXC_LVL_FRAME_OVERHEAD (THREAD_SIZE - INT_FRAME_SIZE - EXC_LVL_SIZE)
 
 #ifdef CONFIG_SMP
 #define BOOKE_LOAD_EXC_LEVEL_STACK(level)              \
        mfspr   r8,SPRN_PIR;                            \
-       mulli   r8,r8,BOOKE_EXCEPTION_STACK_SIZE;       \
-       neg     r8,r8;                                  \
-       addis   r8,r8,level##_STACK_TOP@ha;             \
-       addi    r8,r8,level##_STACK_TOP@l
+       slwi    r8,r8,2;                                \
+       addis   r8,r8,level##_STACK_BASE@ha;            \
+       lwz     r8,level##_STACK_BASE@l(r8);            \
+       addi    r8,r8,EXC_LVL_FRAME_OVERHEAD;
 #else
 #define BOOKE_LOAD_EXC_LEVEL_STACK(level)              \
-       lis     r8,level##_STACK_TOP@h;                 \
-       ori     r8,r8,level##_STACK_TOP@l
+       lis     r8,level##_STACK_BASE@ha;               \
+       lwz     r8,level##_STACK_BASE@l(r8);            \
+       addi    r8,r8,EXC_LVL_FRAME_OVERHEAD;
 #endif
 
 /*
 #define EXC_LEVEL_EXCEPTION_PROLOG(exc_level, exc_level_srr0, exc_level_srr1) \
        mtspr   exc_level##_SPRG,r8;                                         \
        BOOKE_LOAD_EXC_LEVEL_STACK(exc_level);/* r8 points to the exc_level stack*/ \
-       stw     r10,GPR10-INT_FRAME_SIZE(r8);                                \
-       stw     r11,GPR11-INT_FRAME_SIZE(r8);                                \
-       mfcr    r10;                    /* save CR in r10 for now          */\
-       mfspr   r11,exc_level_srr1;     /* check whether user or kernel    */\
-       andi.   r11,r11,MSR_PR;                                              \
-       mr      r11,r8;                                                      \
-       mfspr   r8,exc_level##_SPRG;                                         \
-       beq     1f;                                                          \
-       /* COMING FROM USER MODE */                                          \
+       stw     r9,GPR9(r8);            /* save various registers          */\
+       mfcr    r9;                     /* save CR in r9 for now           */\
+       stw     r10,GPR10(r8);                                               \
+       stw     r11,GPR11(r8);                                               \
+       stw     r9,_CCR(r8);            /* save CR on stack                */\
+       mfspr   r10,exc_level_srr1;     /* check whether user or kernel    */\
+       andi.   r10,r10,MSR_PR;                                              \
        mfspr   r11,SPRN_SPRG3;         /* if from user, start at top of   */\
        lwz     r11,THREAD_INFO-THREAD(r11); /* this thread's kernel stack */\
-       addi    r11,r11,THREAD_SIZE;                                         \
-1:     subi    r11,r11,INT_FRAME_SIZE; /* Allocate an exception frame     */\
-       stw     r10,_CCR(r11);          /* save various registers          */\
-       stw     r12,GPR12(r11);                                              \
+       addi    r11,r11,EXC_LVL_FRAME_OVERHEAD; /* allocate stack frame    */\
+       beq     1f;                                                          \
+       /* COMING FROM USER MODE */                                          \
+       stw     r9,_CCR(r11);           /* save CR                         */\
+       lwz     r10,GPR10(r8);          /* copy regs from exception stack  */\
+       lwz     r9,GPR9(r8);                                                 \
+       stw     r10,GPR10(r11);                                              \
+       lwz     r10,GPR11(r8);                                               \
        stw     r9,GPR9(r11);                                                \
+       stw     r10,GPR11(r11);                                              \
+       b       2f;                                                          \
+       /* COMING FROM PRIV MODE */                                          \
+1:     lwz     r9,TI_FLAGS-EXC_LVL_FRAME_OVERHEAD(r11);                     \
+       lwz     r10,TI_PREEMPT-EXC_LVL_FRAME_OVERHEAD(r11);                  \
+       stw     r9,TI_FLAGS-EXC_LVL_FRAME_OVERHEAD(r8);                      \
+       stw     r10,TI_PREEMPT-EXC_LVL_FRAME_OVERHEAD(r8);                   \
+       lwz     r9,TI_TASK-EXC_LVL_FRAME_OVERHEAD(r11);                      \
+       stw     r9,TI_TASK-EXC_LVL_FRAME_OVERHEAD(r8);                       \
+       mr      r11,r8;                                                      \
+2:     mfspr   r8,exc_level##_SPRG;                                         \
+       stw     r12,GPR12(r11);         /* save various registers          */\
        mflr    r10;                                                         \
        stw     r10,_LINK(r11);                                              \
        mfspr   r12,SPRN_DEAR;          /* save DEAR and ESR in the frame  */\
@@ -231,7 +244,7 @@ label:
         * the code where the exception occurred (since exception entry       \
         * doesn't turn off DE automatically).  We simulate the effect        \
         * of turning off DE on entry to an exception handler by turning      \
-        * off DE in the CSRR1 value and clearing the debug status.           \
+        * off DE in the DSRR1 value and clearing the debug status.           \
         */                                                                   \
        mfspr   r10,SPRN_DBSR;          /* check single-step/branch taken */  \
        andis.  r10,r10,DBSR_IC@h;                                            \
@@ -262,17 +275,17 @@ label:
        lwz     r12,GPR12(r11);                                               \
        mtspr   DEBUG_SPRG,r8;                                                \
        BOOKE_LOAD_EXC_LEVEL_STACK(DEBUG); /* r8 points to the debug stack */ \
-       lwz     r10,GPR10-INT_FRAME_SIZE(r8);                                 \
-       lwz     r11,GPR11-INT_FRAME_SIZE(r8);                                 \
+       lwz     r10,GPR10(r8);                                                \
+       lwz     r11,GPR11(r8);                                                \
        mfspr   r8,DEBUG_SPRG;                                                \
                                                                              \
        RFDI;                                                                 \
        b       .;                                                            \
                                                                              \
-       /* continue normal handling for a critical exception... */            \
+       /* continue normal handling for a debug exception... */               \
 2:     mfspr   r4,SPRN_DBSR;                                                 \
        addi    r3,r1,STACK_FRAME_OVERHEAD;                                   \
-       EXC_XFER_TEMPLATE(DebugException, 0x2002, (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), NOCOPY, debug_transfer_to_handler, ret_from_debug_exc)
+       EXC_XFER_TEMPLATE(DebugException, 0x2008, (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), NOCOPY, debug_transfer_to_handler, ret_from_debug_exc)
 
 #define DEBUG_CRIT_EXCEPTION                                                 \
        START_EXCEPTION(DebugCrit);                                           \
@@ -315,8 +328,8 @@ label:
        lwz     r12,GPR12(r11);                                               \
        mtspr   CRIT_SPRG,r8;                                                 \
        BOOKE_LOAD_EXC_LEVEL_STACK(CRIT); /* r8 points to the debug stack */  \
-       lwz     r10,GPR10-INT_FRAME_SIZE(r8);                                 \
-       lwz     r11,GPR11-INT_FRAME_SIZE(r8);                                 \
+       lwz     r10,GPR10(r8);                                                \
+       lwz     r11,GPR11(r8);                                                \
        mfspr   r8,CRIT_SPRG;                                                 \
                                                                              \
        rfci;                                                                 \
@@ -327,6 +340,14 @@ label:
        addi    r3,r1,STACK_FRAME_OVERHEAD;                                   \
        EXC_XFER_TEMPLATE(DebugException, 0x2002, (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), NOCOPY, crit_transfer_to_handler, ret_from_crit_exc)
 
+#define DATA_STORAGE_EXCEPTION                                               \
+       START_EXCEPTION(DataStorage)                                          \
+       NORMAL_EXCEPTION_PROLOG;                                              \
+       mfspr   r5,SPRN_ESR;            /* Grab the ESR and save it */        \
+       stw     r5,_ESR(r11);                                                 \
+       mfspr   r4,SPRN_DEAR;           /* Grab the DEAR */                   \
+       EXC_XFER_EE_LITE(0x0300, handle_page_fault)
+
 #define INSTRUCTION_STORAGE_EXCEPTION                                        \
        START_EXCEPTION(InstructionStorage)                                   \
        NORMAL_EXCEPTION_PROLOG;                                              \
@@ -363,8 +384,31 @@ label:
 #define FP_UNAVAILABLE_EXCEPTION                                             \
        START_EXCEPTION(FloatingPointUnavailable)                             \
        NORMAL_EXCEPTION_PROLOG;                                              \
-       bne     load_up_fpu;            /* if from user, just load it up */   \
-       addi    r3,r1,STACK_FRAME_OVERHEAD;                                   \
+       beq     1f;                                                           \
+       bl      load_up_fpu;            /* if from user, just load it up */   \
+       b       fast_exception_return;                                        \
+1:     addi    r3,r1,STACK_FRAME_OVERHEAD;                                   \
        EXC_XFER_EE_LITE(0x800, kernel_fp_unavailable_exception)
 
+#ifndef __ASSEMBLY__
+struct exception_regs {
+       unsigned long mas0;
+       unsigned long mas1;
+       unsigned long mas2;
+       unsigned long mas3;
+       unsigned long mas6;
+       unsigned long mas7;
+       unsigned long srr0;
+       unsigned long srr1;
+       unsigned long csrr0;
+       unsigned long csrr1;
+       unsigned long dsrr0;
+       unsigned long dsrr1;
+       unsigned long saved_ksp_limit;
+};
+
+/* ensure this structure is always sized to a multiple of the stack alignment */
+#define STACK_EXC_LVL_FRAME_SIZE       _ALIGN_UP(sizeof (struct exception_regs), 16)
+
+#endif /* __ASSEMBLY__ */
 #endif /* __HEAD_BOOKE_H__ */