Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0 */
0002 #ifndef __HEAD_BOOKE_H__
0003 #define __HEAD_BOOKE_H__
0004 
0005 #include <asm/ptrace.h> /* for STACK_FRAME_REGS_MARKER */
0006 #include <asm/kvm_asm.h>
0007 #include <asm/kvm_booke_hv_asm.h>
0008 
0009 #ifdef __ASSEMBLY__
0010 
0011 /*
0012  * Macros used for common Book-e exception handling
0013  */
0014 
0015 #define SET_IVOR(vector_number, vector_label)       \
0016         li  r26,vector_label@l;         \
0017         mtspr   SPRN_IVOR##vector_number,r26;   \
0018         sync
0019 
0020 #if (THREAD_SHIFT < 15)
0021 #define ALLOC_STACK_FRAME(reg, val)         \
0022     addi reg,reg,val
0023 #else
0024 #define ALLOC_STACK_FRAME(reg, val)         \
0025     addis   reg,reg,val@ha;             \
0026     addi    reg,reg,val@l
0027 #endif
0028 
0029 /*
0030  * Macro used to get to thread save registers.
0031  * Note that entries 0-3 are used for the prolog code, and the remaining
0032  * entries are available for specific exception use in the event a handler
0033  * requires more than 4 scratch registers.
0034  */
0035 #define THREAD_NORMSAVE(offset) (THREAD_NORMSAVES + (offset * 4))
0036 
0037 #ifdef CONFIG_PPC_FSL_BOOK3E
0038 #define BOOKE_CLEAR_BTB(reg)                                    \
0039 START_BTB_FLUSH_SECTION                             \
0040     BTB_FLUSH(reg)                                  \
0041 END_BTB_FLUSH_SECTION
0042 #else
0043 #define BOOKE_CLEAR_BTB(reg)
0044 #endif
0045 
0046 
0047 #define NORMAL_EXCEPTION_PROLOG(trapno, intno)                           \
0048     mtspr   SPRN_SPRG_WSCRATCH0, r10;   /* save one register */      \
0049     mfspr   r10, SPRN_SPRG_THREAD;                       \
0050     stw r11, THREAD_NORMSAVE(0)(r10);                    \
0051     stw r13, THREAD_NORMSAVE(2)(r10);                    \
0052     mfcr    r13;            /* save CR in r13 for now      */\
0053     mfspr   r11, SPRN_SRR1;                                          \
0054     DO_KVM  BOOKE_INTERRUPT_##intno SPRN_SRR1;               \
0055     andi.   r11, r11, MSR_PR;   /* check whether user or kernel    */\
0056     LOAD_REG_IMMEDIATE(r11, MSR_KERNEL);                \
0057     mtmsr   r11;                            \
0058     mr  r11, r1;                             \
0059     beq 1f;                              \
0060     BOOKE_CLEAR_BTB(r11)                        \
0061     /* if from user, start at top of this thread's kernel stack */       \
0062     lwz r11, TASK_STACK - THREAD(r10);                   \
0063     ALLOC_STACK_FRAME(r11, THREAD_SIZE);                     \
0064 1 : subi    r11, r11, INT_FRAME_SIZE; /* Allocate exception frame */     \
0065     stw r13, _CCR(r11);     /* save various registers */         \
0066     stw r12,GPR12(r11);                          \
0067     stw r9,GPR9(r11);                            \
0068     mfspr   r13, SPRN_SPRG_RSCRATCH0;                    \
0069     stw r13, GPR10(r11);                         \
0070     lwz r12, THREAD_NORMSAVE(0)(r10);                    \
0071     stw r12,GPR11(r11);                          \
0072     lwz r13, THREAD_NORMSAVE(2)(r10); /* restore r13 */          \
0073     mflr    r10;                                 \
0074     stw r10,_LINK(r11);                          \
0075     mfspr   r12,SPRN_SRR0;                           \
0076     stw r1, GPR1(r11);                           \
0077     mfspr   r9,SPRN_SRR1;                            \
0078     stw r1, 0(r11);                          \
0079     mr  r1, r11;                             \
0080     rlwinm  r9,r9,0,14,12;      /* clear MSR_WE (necessary?)       */\
0081     COMMON_EXCEPTION_PROLOG_END trapno
0082 
0083 .macro COMMON_EXCEPTION_PROLOG_END trapno
0084     stw r0,GPR0(r1)
0085     lis r10, STACK_FRAME_REGS_MARKER@ha /* exception frame marker */
0086     addi    r10, r10, STACK_FRAME_REGS_MARKER@l
0087     stw r10, 8(r1)
0088     li  r10, \trapno
0089     stw r10,_TRAP(r1)
0090     SAVE_GPRS(3, 8, r1)
0091     SAVE_NVGPRS(r1)
0092     stw r2,GPR2(r1)
0093     stw r12,_NIP(r1)
0094     stw r9,_MSR(r1)
0095     mfctr   r10
0096     mfspr   r2,SPRN_SPRG_THREAD
0097     stw r10,_CTR(r1)
0098     tovirt(r2, r2)
0099     mfspr   r10,SPRN_XER
0100     addi    r2, r2, -THREAD
0101     stw r10,_XER(r1)
0102     addi    r3,r1,STACK_FRAME_OVERHEAD
0103 .endm
0104 
0105 .macro prepare_transfer_to_handler
0106 #ifdef CONFIG_E500
0107     andi.   r12,r9,MSR_PR
0108     bne 777f
0109     bl  prepare_transfer_to_handler
0110 777:
0111 #endif
0112 .endm
0113 
0114 .macro SYSCALL_ENTRY trapno intno srr1
0115     mfspr   r10, SPRN_SPRG_THREAD
0116 #ifdef CONFIG_KVM_BOOKE_HV
0117 BEGIN_FTR_SECTION
0118     mtspr   SPRN_SPRG_WSCRATCH0, r10
0119     stw r11, THREAD_NORMSAVE(0)(r10)
0120     stw r13, THREAD_NORMSAVE(2)(r10)
0121     mfcr    r13         /* save CR in r13 for now      */
0122     mfspr   r11, SPRN_SRR1
0123     mtocrf  0x80, r11   /* check MSR[GS] without clobbering reg */
0124     bf  3, 1975f
0125     b   kvmppc_handler_\intno\()_\srr1
0126 1975:
0127     mr  r12, r13
0128     lwz r13, THREAD_NORMSAVE(2)(r10)
0129 FTR_SECTION_ELSE
0130     mfcr    r12
0131 ALT_FTR_SECTION_END_IFSET(CPU_FTR_EMB_HV)
0132 #else
0133     mfcr    r12
0134 #endif
0135     mfspr   r9, SPRN_SRR1
0136     BOOKE_CLEAR_BTB(r11)
0137     mr  r11, r1
0138     lwz r1, TASK_STACK - THREAD(r10)
0139     rlwinm  r12,r12,0,4,2   /* Clear SO bit in CR */
0140     ALLOC_STACK_FRAME(r1, THREAD_SIZE - INT_FRAME_SIZE)
0141     stw r12, _CCR(r1)
0142     mfspr   r12,SPRN_SRR0
0143     stw r12,_NIP(r1)
0144     b   transfer_to_syscall /* jump to handler */
0145 .endm
0146 
0147 /* To handle the additional exception priority levels on 40x and Book-E
0148  * processors we allocate a stack per additional priority level.
0149  *
0150  * On 40x critical is the only additional level
0151  * On 44x/e500 we have critical and machine check
0152  *
0153  * Additionally we reserve a SPRG for each priority level so we can free up a
0154  * GPR to use as the base for indirect access to the exception stacks.  This
0155  * is necessary since the MMU is always on, for Book-E parts, and the stacks
0156  * are offset from KERNELBASE.
0157  *
0158  * There is some space optimization to be had here if desired.  However
0159  * to allow for a common kernel with support for debug exceptions either
0160  * going to critical or their own debug level we aren't currently
0161  * providing configurations that micro-optimize space usage.
0162  */
0163 
0164 #define MC_STACK_BASE       mcheckirq_ctx
0165 #define CRIT_STACK_BASE     critirq_ctx
0166 
0167 /* only on e500mc */
0168 #define DBG_STACK_BASE      dbgirq_ctx
0169 
0170 #ifdef CONFIG_SMP
0171 #define BOOKE_LOAD_EXC_LEVEL_STACK(level)       \
0172     mfspr   r8,SPRN_PIR;                \
0173     slwi    r8,r8,2;                \
0174     addis   r8,r8,level##_STACK_BASE@ha;        \
0175     lwz r8,level##_STACK_BASE@l(r8);        \
0176     addi    r8,r8,THREAD_SIZE - INT_FRAME_SIZE;
0177 #else
0178 #define BOOKE_LOAD_EXC_LEVEL_STACK(level)       \
0179     lis r8,level##_STACK_BASE@ha;       \
0180     lwz r8,level##_STACK_BASE@l(r8);        \
0181     addi    r8,r8,THREAD_SIZE - INT_FRAME_SIZE;
0182 #endif
0183 
0184 /*
0185  * Exception prolog for critical/machine check exceptions.  This is a
0186  * little different from the normal exception prolog above since a
0187  * critical/machine check exception can potentially occur at any point
0188  * during normal exception processing. Thus we cannot use the same SPRG
0189  * registers as the normal prolog above. Instead we use a portion of the
0190  * critical/machine check exception stack at low physical addresses.
0191  */
0192 #define EXC_LEVEL_EXCEPTION_PROLOG(exc_level, trapno, intno, exc_level_srr0, exc_level_srr1) \
0193     mtspr   SPRN_SPRG_WSCRATCH_##exc_level,r8;               \
0194     BOOKE_LOAD_EXC_LEVEL_STACK(exc_level);/* r8 points to the exc_level stack*/ \
0195     stw r9,GPR9(r8);        /* save various registers      */\
0196     mfcr    r9;         /* save CR in r9 for now       */\
0197     stw r10,GPR10(r8);                           \
0198     stw r11,GPR11(r8);                           \
0199     stw r9,_CCR(r8);        /* save CR on stack        */\
0200     mfspr   r11,exc_level_srr1; /* check whether user or kernel    */\
0201     DO_KVM  BOOKE_INTERRUPT_##intno exc_level_srr1;                  \
0202     BOOKE_CLEAR_BTB(r10)                        \
0203     andi.   r11,r11,MSR_PR;                          \
0204     LOAD_REG_IMMEDIATE(r11, MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE));  \
0205     mtmsr   r11;                            \
0206     mfspr   r11,SPRN_SPRG_THREAD;   /* if from user, start at top of   */\
0207     lwz r11, TASK_STACK - THREAD(r11); /* this thread's kernel stack */\
0208     addi    r11,r11,THREAD_SIZE - INT_FRAME_SIZE;   /* allocate stack frame    */\
0209     beq 1f;                              \
0210     /* COMING FROM USER MODE */                      \
0211     stw r9,_CCR(r11);       /* save CR             */\
0212     lwz r10,GPR10(r8);      /* copy regs from exception stack  */\
0213     lwz r9,GPR9(r8);                             \
0214     stw r10,GPR10(r11);                          \
0215     lwz r10,GPR11(r8);                           \
0216     stw r9,GPR9(r11);                            \
0217     stw r10,GPR11(r11);                          \
0218     b   2f;                              \
0219     /* COMING FROM PRIV MODE */                      \
0220 1:  mr  r11, r8;                                 \
0221 2:  mfspr   r8,SPRN_SPRG_RSCRATCH_##exc_level;               \
0222     stw r12,GPR12(r11);     /* save various registers      */\
0223     mflr    r10;                                 \
0224     stw r10,_LINK(r11);                          \
0225     mfspr   r12,SPRN_DEAR;      /* save DEAR and ESR in the frame  */\
0226     stw r12,_DEAR(r11);     /* since they may have had stuff   */\
0227     mfspr   r9,SPRN_ESR;        /* in them at the point where the  */\
0228     stw r9,_ESR(r11);       /* exception was taken         */\
0229     mfspr   r12,exc_level_srr0;                      \
0230     stw r1,GPR1(r11);                            \
0231     mfspr   r9,exc_level_srr1;                       \
0232     stw r1,0(r11);                           \
0233     mr  r1,r11;                              \
0234     rlwinm  r9,r9,0,14,12;      /* clear MSR_WE (necessary?)       */\
0235     COMMON_EXCEPTION_PROLOG_END trapno
0236 
0237 #define SAVE_xSRR(xSRR)         \
0238     mfspr   r0,SPRN_##xSRR##0;  \
0239     stw r0,_##xSRR##0(r1);  \
0240     mfspr   r0,SPRN_##xSRR##1;  \
0241     stw r0,_##xSRR##1(r1)
0242 
0243 
0244 .macro SAVE_MMU_REGS
0245 #ifdef CONFIG_PPC_BOOK3E_MMU
0246     mfspr   r0,SPRN_MAS0
0247     stw r0,MAS0(r1)
0248     mfspr   r0,SPRN_MAS1
0249     stw r0,MAS1(r1)
0250     mfspr   r0,SPRN_MAS2
0251     stw r0,MAS2(r1)
0252     mfspr   r0,SPRN_MAS3
0253     stw r0,MAS3(r1)
0254     mfspr   r0,SPRN_MAS6
0255     stw r0,MAS6(r1)
0256 #ifdef CONFIG_PHYS_64BIT
0257     mfspr   r0,SPRN_MAS7
0258     stw r0,MAS7(r1)
0259 #endif /* CONFIG_PHYS_64BIT */
0260 #endif /* CONFIG_PPC_BOOK3E_MMU */
0261 #ifdef CONFIG_44x
0262     mfspr   r0,SPRN_MMUCR
0263     stw r0,MMUCR(r1)
0264 #endif
0265 .endm
0266 
0267 #define CRITICAL_EXCEPTION_PROLOG(trapno, intno) \
0268         EXC_LEVEL_EXCEPTION_PROLOG(CRIT, trapno+2, intno, SPRN_CSRR0, SPRN_CSRR1)
0269 #define DEBUG_EXCEPTION_PROLOG(trapno) \
0270         EXC_LEVEL_EXCEPTION_PROLOG(DBG, trapno+8, DEBUG, SPRN_DSRR0, SPRN_DSRR1)
0271 #define MCHECK_EXCEPTION_PROLOG(trapno) \
0272         EXC_LEVEL_EXCEPTION_PROLOG(MC, trapno+4, MACHINE_CHECK, \
0273             SPRN_MCSRR0, SPRN_MCSRR1)
0274 
0275 /*
0276  * Guest Doorbell -- this is a bit odd in that uses GSRR0/1 despite
0277  * being delivered to the host.  This exception can only happen
0278  * inside a KVM guest -- so we just handle up to the DO_KVM rather
0279  * than try to fit this into one of the existing prolog macros.
0280  */
0281 #define GUEST_DOORBELL_EXCEPTION \
0282     START_EXCEPTION(GuestDoorbell);                      \
0283     mtspr   SPRN_SPRG_WSCRATCH0, r10;   /* save one register */      \
0284     mfspr   r10, SPRN_SPRG_THREAD;                       \
0285     stw r11, THREAD_NORMSAVE(0)(r10);                    \
0286     mfspr   r11, SPRN_SRR1;                                          \
0287     stw r13, THREAD_NORMSAVE(2)(r10);                    \
0288     mfcr    r13;            /* save CR in r13 for now      */\
0289     DO_KVM  BOOKE_INTERRUPT_GUEST_DBELL SPRN_GSRR1;              \
0290     trap
0291 
0292 /*
0293  * Exception vectors.
0294  */
0295 #define START_EXCEPTION(label)                           \
0296         .align 5;                                        \
0297 label:
0298 
0299 #define EXCEPTION(n, intno, label, hdlr)            \
0300     START_EXCEPTION(label);                 \
0301     NORMAL_EXCEPTION_PROLOG(n, intno);          \
0302     prepare_transfer_to_handler;                \
0303     bl  hdlr;                       \
0304     b   interrupt_return
0305 
0306 #define CRITICAL_EXCEPTION(n, intno, label, hdlr)           \
0307     START_EXCEPTION(label);                     \
0308     CRITICAL_EXCEPTION_PROLOG(n, intno);                \
0309     SAVE_MMU_REGS;                          \
0310     SAVE_xSRR(SRR);                         \
0311     prepare_transfer_to_handler;                    \
0312     bl  hdlr;                           \
0313     b   ret_from_crit_exc
0314 
0315 #define MCHECK_EXCEPTION(n, label, hdlr)            \
0316     START_EXCEPTION(label);                 \
0317     MCHECK_EXCEPTION_PROLOG(n);             \
0318     mfspr   r5,SPRN_ESR;                    \
0319     stw r5,_ESR(r11);                   \
0320     SAVE_xSRR(DSRR);                    \
0321     SAVE_xSRR(CSRR);                    \
0322     SAVE_MMU_REGS;                      \
0323     SAVE_xSRR(SRR);                     \
0324     prepare_transfer_to_handler;                \
0325     bl  hdlr;                       \
0326     b   ret_from_mcheck_exc
0327 
0328 /* Check for a single step debug exception while in an exception
0329  * handler before state has been saved.  This is to catch the case
0330  * where an instruction that we are trying to single step causes
0331  * an exception (eg ITLB/DTLB miss) and thus the first instruction of
0332  * the exception handler generates a single step debug exception.
0333  *
0334  * If we get a debug trap on the first instruction of an exception handler,
0335  * we reset the MSR_DE in the _exception handler's_ MSR (the debug trap is
0336  * a critical exception, so we are using SPRN_CSRR1 to manipulate the MSR).
0337  * The exception handler was handling a non-critical interrupt, so it will
0338  * save (and later restore) the MSR via SPRN_CSRR1, which will still have
0339  * the MSR_DE bit set.
0340  */
0341 #define DEBUG_DEBUG_EXCEPTION                             \
0342     START_EXCEPTION(DebugDebug);                          \
0343     DEBUG_EXCEPTION_PROLOG(2000);                             \
0344                                           \
0345     /*                                    \
0346      * If there is a single step or branch-taken exception in an          \
0347      * exception entry sequence, it was probably meant to apply to        \
0348      * the code where the exception occurred (since exception entry       \
0349      * doesn't turn off DE automatically).  We simulate the effect        \
0350      * of turning off DE on entry to an exception handler by turning      \
0351      * off DE in the DSRR1 value and clearing the debug status.       \
0352      */                                   \
0353     mfspr   r10,SPRN_DBSR;      /* check single-step/branch taken */  \
0354     andis.  r10,r10,(DBSR_IC|DBSR_BT)@h;                      \
0355     beq+    2f;                               \
0356                                           \
0357     lis r10,interrupt_base@h;   /* check if exception in vectors */   \
0358     ori r10,r10,interrupt_base@l;                     \
0359     cmplw   r12,r10;                              \
0360     blt+    2f;         /* addr below exception vectors */    \
0361                                           \
0362     lis r10,interrupt_end@h;                          \
0363     ori r10,r10,interrupt_end@l;                      \
0364     cmplw   r12,r10;                              \
0365     bgt+    2f;         /* addr above exception vectors */    \
0366                                           \
0367     /* here it looks like we got an inappropriate debug exception. */     \
0368 1:  rlwinm  r9,r9,0,~MSR_DE;    /* clear DE in the CDRR1 value */     \
0369     lis r10,(DBSR_IC|DBSR_BT)@h;    /* clear the IC event */      \
0370     mtspr   SPRN_DBSR,r10;                            \
0371     /* restore state and get out */                       \
0372     lwz r10,_CCR(r11);                            \
0373     lwz r0,GPR0(r11);                             \
0374     lwz r1,GPR1(r11);                             \
0375     mtcrf   0x80,r10;                             \
0376     mtspr   SPRN_DSRR0,r12;                           \
0377     mtspr   SPRN_DSRR1,r9;                            \
0378     lwz r9,GPR9(r11);                             \
0379     lwz r12,GPR12(r11);                           \
0380     mtspr   SPRN_SPRG_WSCRATCH_DBG,r8;                    \
0381     BOOKE_LOAD_EXC_LEVEL_STACK(DBG); /* r8 points to the debug stack */ \
0382     lwz r10,GPR10(r8);                            \
0383     lwz r11,GPR11(r8);                            \
0384     mfspr   r8,SPRN_SPRG_RSCRATCH_DBG;                    \
0385                                           \
0386     PPC_RFDI;                                 \
0387     b   .;                                \
0388                                           \
0389     /* continue normal handling for a debug exception... */           \
0390 2:  mfspr   r4,SPRN_DBSR;                             \
0391     stw r4,_ESR(r11);       /* DebugException takes DBSR in _ESR */\
0392     SAVE_xSRR(CSRR);                              \
0393     SAVE_MMU_REGS;                                \
0394     SAVE_xSRR(SRR);                               \
0395     prepare_transfer_to_handler;                      \
0396     bl  DebugException;                           \
0397     b   ret_from_debug_exc
0398 
0399 #define DEBUG_CRIT_EXCEPTION                              \
0400     START_EXCEPTION(DebugCrit);                       \
0401     CRITICAL_EXCEPTION_PROLOG(2000,DEBUG);                    \
0402                                           \
0403     /*                                    \
0404      * If there is a single step or branch-taken exception in an          \
0405      * exception entry sequence, it was probably meant to apply to        \
0406      * the code where the exception occurred (since exception entry       \
0407      * doesn't turn off DE automatically).  We simulate the effect        \
0408      * of turning off DE on entry to an exception handler by turning      \
0409      * off DE in the CSRR1 value and clearing the debug status.       \
0410      */                                   \
0411     mfspr   r10,SPRN_DBSR;      /* check single-step/branch taken */  \
0412     andis.  r10,r10,(DBSR_IC|DBSR_BT)@h;                      \
0413     beq+    2f;                               \
0414                                           \
0415     lis r10,interrupt_base@h;   /* check if exception in vectors */   \
0416     ori r10,r10,interrupt_base@l;                     \
0417     cmplw   r12,r10;                              \
0418     blt+    2f;         /* addr below exception vectors */    \
0419                                           \
0420     lis r10,interrupt_end@h;                          \
0421     ori r10,r10,interrupt_end@l;                      \
0422     cmplw   r12,r10;                              \
0423     bgt+    2f;         /* addr above exception vectors */    \
0424                                           \
0425     /* here it looks like we got an inappropriate debug exception. */     \
0426 1:  rlwinm  r9,r9,0,~MSR_DE;    /* clear DE in the CSRR1 value */     \
0427     lis r10,(DBSR_IC|DBSR_BT)@h;    /* clear the IC event */      \
0428     mtspr   SPRN_DBSR,r10;                            \
0429     /* restore state and get out */                       \
0430     lwz r10,_CCR(r11);                            \
0431     lwz r0,GPR0(r11);                             \
0432     lwz r1,GPR1(r11);                             \
0433     mtcrf   0x80,r10;                             \
0434     mtspr   SPRN_CSRR0,r12;                           \
0435     mtspr   SPRN_CSRR1,r9;                            \
0436     lwz r9,GPR9(r11);                             \
0437     lwz r12,GPR12(r11);                           \
0438     mtspr   SPRN_SPRG_WSCRATCH_CRIT,r8;                   \
0439     BOOKE_LOAD_EXC_LEVEL_STACK(CRIT); /* r8 points to the debug stack */  \
0440     lwz r10,GPR10(r8);                            \
0441     lwz r11,GPR11(r8);                            \
0442     mfspr   r8,SPRN_SPRG_RSCRATCH_CRIT;                   \
0443                                           \
0444     rfci;                                     \
0445     b   .;                                \
0446                                           \
0447     /* continue normal handling for a critical exception... */        \
0448 2:  mfspr   r4,SPRN_DBSR;                             \
0449     stw r4,_ESR(r11);       /* DebugException takes DBSR in _ESR */\
0450     SAVE_MMU_REGS;                                \
0451     SAVE_xSRR(SRR);                               \
0452     prepare_transfer_to_handler;                          \
0453     bl  DebugException;                           \
0454     b   ret_from_crit_exc
0455 
0456 #define DATA_STORAGE_EXCEPTION                            \
0457     START_EXCEPTION(DataStorage)                          \
0458     NORMAL_EXCEPTION_PROLOG(0x300, DATA_STORAGE);             \
0459     mfspr   r5,SPRN_ESR;        /* Grab the ESR and save it */        \
0460     stw r5,_ESR(r11);                             \
0461     mfspr   r4,SPRN_DEAR;       /* Grab the DEAR */           \
0462     stw r4, _DEAR(r11);                           \
0463     prepare_transfer_to_handler;                          \
0464     bl  do_page_fault;                            \
0465     b   interrupt_return
0466 
0467 /*
0468  * Instruction TLB Error interrupt handlers may call InstructionStorage
0469  * directly without clearing ESR, so the ESR at this point may be left over
0470  * from a prior interrupt.
0471  *
0472  * In any case, do_page_fault for BOOK3E does not use ESR and always expects
0473  * dsisr to be 0. ESR_DST from a prior store in particular would confuse fault
0474  * handling.
0475  */
0476 #define INSTRUCTION_STORAGE_EXCEPTION                         \
0477     START_EXCEPTION(InstructionStorage)                   \
0478     NORMAL_EXCEPTION_PROLOG(0x400, INST_STORAGE);                 \
0479     li  r5,0;           /* Store 0 in regs->esr (dsisr) */    \
0480     stw r5,_ESR(r11);                             \
0481     stw r12, _DEAR(r11);    /* Set regs->dear (dar) to SRR0 */    \
0482     prepare_transfer_to_handler;                          \
0483     bl  do_page_fault;                            \
0484     b   interrupt_return
0485 
0486 #define ALIGNMENT_EXCEPTION                           \
0487     START_EXCEPTION(Alignment)                        \
0488     NORMAL_EXCEPTION_PROLOG(0x600, ALIGNMENT);            \
0489     mfspr   r4,SPRN_DEAR;           /* Grab the DEAR and save it */       \
0490     stw     r4,_DEAR(r11);                            \
0491     prepare_transfer_to_handler;                          \
0492     bl  alignment_exception;                          \
0493     REST_NVGPRS(r1);                              \
0494     b   interrupt_return
0495 
0496 #define PROGRAM_EXCEPTION                             \
0497     START_EXCEPTION(Program)                          \
0498     NORMAL_EXCEPTION_PROLOG(0x700, PROGRAM);              \
0499     mfspr   r4,SPRN_ESR;        /* Grab the ESR and save it */        \
0500     stw r4,_ESR(r11);                             \
0501     prepare_transfer_to_handler;                          \
0502     bl  program_check_exception;                      \
0503     REST_NVGPRS(r1);                              \
0504     b   interrupt_return
0505 
0506 #define DECREMENTER_EXCEPTION                             \
0507     START_EXCEPTION(Decrementer)                          \
0508     NORMAL_EXCEPTION_PROLOG(0x900, DECREMENTER);              \
0509     lis     r0,TSR_DIS@h;           /* Setup the DEC interrupt mask */    \
0510     mtspr   SPRN_TSR,r0;        /* Clear the DEC interrupt */         \
0511     prepare_transfer_to_handler;                          \
0512     bl  timer_interrupt;                          \
0513     b   interrupt_return
0514 
0515 #define FP_UNAVAILABLE_EXCEPTION                          \
0516     START_EXCEPTION(FloatingPointUnavailable)                 \
0517     NORMAL_EXCEPTION_PROLOG(0x800, FP_UNAVAIL);           \
0518     beq 1f;                               \
0519     bl  load_up_fpu;        /* if from user, just load it up */   \
0520     b   fast_exception_return;                        \
0521 1:  prepare_transfer_to_handler;                          \
0522     bl  kernel_fp_unavailable_exception;                  \
0523     b   interrupt_return
0524 
0525 #endif /* __ASSEMBLY__ */
0526 #endif /* __HEAD_BOOKE_H__ */