1b2441318SGreg Kroah-Hartman /* SPDX-License-Identifier: GPL-2.0 */ 263dafe57SBecky Bruce #ifndef __HEAD_BOOKE_H__ 363dafe57SBecky Bruce #define __HEAD_BOOKE_H__ 463dafe57SBecky Bruce 5471c70ffSTorez Smith #include <asm/ptrace.h> /* for STACK_FRAME_REGS_MARKER */ 6cfac5784SScott Wood #include <asm/kvm_asm.h> 7d30f6e48SScott Wood #include <asm/kvm_booke_hv_asm.h> 8*8002725bSNathan Chancellor #include <asm/thread_info.h> /* for THREAD_SHIFT */ 9cfac5784SScott Wood 101a4b739bSChristophe Leroy #ifdef __ASSEMBLY__ 111a4b739bSChristophe Leroy 1263dafe57SBecky Bruce /* 1363dafe57SBecky Bruce * Macros used for common Book-e exception handling 1463dafe57SBecky Bruce */ 1563dafe57SBecky Bruce 1663dafe57SBecky Bruce #define SET_IVOR(vector_number, vector_label) \ 1763dafe57SBecky Bruce li r26,vector_label@l; \ 1863dafe57SBecky Bruce mtspr SPRN_IVOR##vector_number,r26; \ 1963dafe57SBecky Bruce sync 2063dafe57SBecky Bruce 21e1240122SYuri Tikhonov #if (THREAD_SHIFT < 15) 22e1240122SYuri Tikhonov #define ALLOC_STACK_FRAME(reg, val) \ 23e1240122SYuri Tikhonov addi reg,reg,val 24e1240122SYuri Tikhonov #else 25e1240122SYuri Tikhonov #define ALLOC_STACK_FRAME(reg, val) \ 26e1240122SYuri Tikhonov addis reg,reg,val@ha; \ 27e1240122SYuri Tikhonov addi reg,reg,val@l 28e1240122SYuri Tikhonov #endif 29e1240122SYuri Tikhonov 301325a684SAshish Kalra /* 311325a684SAshish Kalra * Macro used to get to thread save registers. 321325a684SAshish Kalra * Note that entries 0-3 are used for the prolog code, and the remaining 331325a684SAshish Kalra * entries are available for specific exception use in the event a handler 341325a684SAshish Kalra * requires more than 4 scratch registers. 351325a684SAshish Kalra */ 361325a684SAshish Kalra #define THREAD_NORMSAVE(offset) (THREAD_NORMSAVES + (offset * 4)) 371325a684SAshish Kalra 383e731858SChristophe Leroy #ifdef CONFIG_PPC_E500 39039daac5SDiana Craciun #define BOOKE_CLEAR_BTB(reg) \ 40039daac5SDiana Craciun START_BTB_FLUSH_SECTION \ 41039daac5SDiana Craciun BTB_FLUSH(reg) \ 42039daac5SDiana Craciun END_BTB_FLUSH_SECTION 43039daac5SDiana Craciun #else 44039daac5SDiana Craciun #define BOOKE_CLEAR_BTB(reg) 45039daac5SDiana Craciun #endif 46039daac5SDiana Craciun 47039daac5SDiana Craciun 48719e7e21SChristophe Leroy #define NORMAL_EXCEPTION_PROLOG(trapno, intno) \ 491325a684SAshish Kalra mtspr SPRN_SPRG_WSCRATCH0, r10; /* save one register */ \ 501325a684SAshish Kalra mfspr r10, SPRN_SPRG_THREAD; \ 511325a684SAshish Kalra stw r11, THREAD_NORMSAVE(0)(r10); \ 521325a684SAshish Kalra stw r13, THREAD_NORMSAVE(2)(r10); \ 531325a684SAshish Kalra mfcr r13; /* save CR in r13 for now */\ 54d30f6e48SScott Wood mfspr r11, SPRN_SRR1; \ 55d30f6e48SScott Wood DO_KVM BOOKE_INTERRUPT_##intno SPRN_SRR1; \ 56d30f6e48SScott Wood andi. r11, r11, MSR_PR; /* check whether user or kernel */\ 579b6150fbSChristophe Leroy LOAD_REG_IMMEDIATE(r11, MSR_KERNEL); \ 589b6150fbSChristophe Leroy mtmsr r11; \ 5963dafe57SBecky Bruce mr r11, r1; \ 601325a684SAshish Kalra beq 1f; \ 61039daac5SDiana Craciun BOOKE_CLEAR_BTB(r11) \ 621325a684SAshish Kalra /* if from user, start at top of this thread's kernel stack */ \ 638c1fc5abSChristophe Leroy lwz r11, TASK_STACK - THREAD(r10); \ 641325a684SAshish Kalra ALLOC_STACK_FRAME(r11, THREAD_SIZE); \ 651325a684SAshish Kalra 1 : subi r11, r11, INT_FRAME_SIZE; /* Allocate exception frame */ \ 661325a684SAshish Kalra stw r13, _CCR(r11); /* save various registers */ \ 6763dafe57SBecky Bruce stw r12,GPR12(r11); \ 6863dafe57SBecky Bruce stw r9,GPR9(r11); \ 691325a684SAshish Kalra mfspr r13, SPRN_SPRG_RSCRATCH0; \ 701325a684SAshish Kalra stw r13, GPR10(r11); \ 711325a684SAshish Kalra lwz r12, THREAD_NORMSAVE(0)(r10); \ 7263dafe57SBecky Bruce stw r12,GPR11(r11); \ 731325a684SAshish Kalra lwz r13, THREAD_NORMSAVE(2)(r10); /* restore r13 */ \ 7463dafe57SBecky Bruce mflr r10; \ 7563dafe57SBecky Bruce stw r10,_LINK(r11); \ 7663dafe57SBecky Bruce mfspr r12,SPRN_SRR0; \ 771325a684SAshish Kalra stw r1, GPR1(r11); \ 7863dafe57SBecky Bruce mfspr r9,SPRN_SRR1; \ 791325a684SAshish Kalra stw r1, 0(r11); \ 801325a684SAshish Kalra mr r1, r11; \ 8163dafe57SBecky Bruce rlwinm r9,r9,0,14,12; /* clear MSR_WE (necessary?) */\ 82a3055978SChristophe Leroy COMMON_EXCEPTION_PROLOG_END trapno 83a3055978SChristophe Leroy 84a3055978SChristophe Leroy .macro COMMON_EXCEPTION_PROLOG_END trapno 85a3055978SChristophe Leroy stw r0,GPR0(r1) 86a3055978SChristophe Leroy lis r10, STACK_FRAME_REGS_MARKER@ha /* exception frame marker */ 87a3055978SChristophe Leroy addi r10, r10, STACK_FRAME_REGS_MARKER@l 88d2e8ff9fSNicholas Piggin stw r10, STACK_INT_FRAME_MARKER(r1) 89a3055978SChristophe Leroy li r10, \trapno 90a3055978SChristophe Leroy stw r10,_TRAP(r1) 91aebd1fb4SNicholas Piggin SAVE_GPRS(3, 8, r1) 9216db5436SChristophe Leroy SAVE_NVGPRS(r1) 9316db5436SChristophe Leroy stw r2,GPR2(r1) 9416db5436SChristophe Leroy stw r12,_NIP(r1) 9516db5436SChristophe Leroy stw r9,_MSR(r1) 9616db5436SChristophe Leroy mfctr r10 9716db5436SChristophe Leroy mfspr r2,SPRN_SPRG_THREAD 9816db5436SChristophe Leroy stw r10,_CTR(r1) 9916db5436SChristophe Leroy tovirt(r2, r2) 10016db5436SChristophe Leroy mfspr r10,SPRN_XER 10116db5436SChristophe Leroy addi r2, r2, -THREAD 10216db5436SChristophe Leroy stw r10,_XER(r1) 103c03be0a3SNicholas Piggin addi r3,r1,STACK_INT_FRAME_REGS 104a3055978SChristophe Leroy .endm 10563dafe57SBecky Bruce 106bce4c26aSChristophe Leroy .macro prepare_transfer_to_handler 107688de017SChristophe Leroy #ifdef CONFIG_PPC_E500 108b5efec00SChristophe Leroy andi. r12,r9,MSR_PR 109b5efec00SChristophe Leroy bne 777f 110bce4c26aSChristophe Leroy bl prepare_transfer_to_handler 111b5efec00SChristophe Leroy 777: 112a2b3e09aSChristophe Leroy #endif 113bce4c26aSChristophe Leroy .endm 114bce4c26aSChristophe Leroy 11582f6e266SChristophe Leroy .macro SYSCALL_ENTRY trapno intno srr1 1161a4b739bSChristophe Leroy mfspr r10, SPRN_SPRG_THREAD 1171a4b739bSChristophe Leroy #ifdef CONFIG_KVM_BOOKE_HV 1181a4b739bSChristophe Leroy BEGIN_FTR_SECTION 1191a4b739bSChristophe Leroy mtspr SPRN_SPRG_WSCRATCH0, r10 1201a4b739bSChristophe Leroy stw r11, THREAD_NORMSAVE(0)(r10) 1211a4b739bSChristophe Leroy stw r13, THREAD_NORMSAVE(2)(r10) 1221a4b739bSChristophe Leroy mfcr r13 /* save CR in r13 for now */ 1231a4b739bSChristophe Leroy mfspr r11, SPRN_SRR1 1241a4b739bSChristophe Leroy mtocrf 0x80, r11 /* check MSR[GS] without clobbering reg */ 1251a4b739bSChristophe Leroy bf 3, 1975f 12682f6e266SChristophe Leroy b kvmppc_handler_\intno\()_\srr1 1271a4b739bSChristophe Leroy 1975: 1281a4b739bSChristophe Leroy mr r12, r13 1291a4b739bSChristophe Leroy lwz r13, THREAD_NORMSAVE(2)(r10) 1301a4b739bSChristophe Leroy FTR_SECTION_ELSE 1311a4b739bSChristophe Leroy mfcr r12 1321a4b739bSChristophe Leroy ALT_FTR_SECTION_END_IFSET(CPU_FTR_EMB_HV) 133a27755d5SChristophe Leroy #else 134a27755d5SChristophe Leroy mfcr r12 1351a4b739bSChristophe Leroy #endif 1369e270862SChristophe Leroy mfspr r9, SPRN_SRR1 1371a4b739bSChristophe Leroy BOOKE_CLEAR_BTB(r11) 138275dcf24SChristophe Leroy mr r11, r1 139275dcf24SChristophe Leroy lwz r1, TASK_STACK - THREAD(r10) 1401a4b739bSChristophe Leroy rlwinm r12,r12,0,4,2 /* Clear SO bit in CR */ 141275dcf24SChristophe Leroy ALLOC_STACK_FRAME(r1, THREAD_SIZE - INT_FRAME_SIZE) 142275dcf24SChristophe Leroy stw r12, _CCR(r1) 1431a4b739bSChristophe Leroy mfspr r12,SPRN_SRR0 144275dcf24SChristophe Leroy stw r12,_NIP(r1) 14576249ddcSChristophe Leroy b transfer_to_syscall /* jump to handler */ 1461a4b739bSChristophe Leroy .endm 1471a4b739bSChristophe Leroy 14863dafe57SBecky Bruce /* To handle the additional exception priority levels on 40x and Book-E 149bcf0b088SKumar Gala * processors we allocate a stack per additional priority level. 15063dafe57SBecky Bruce * 15163dafe57SBecky Bruce * On 40x critical is the only additional level 15263dafe57SBecky Bruce * On 44x/e500 we have critical and machine check 15363dafe57SBecky Bruce * 15463dafe57SBecky Bruce * Additionally we reserve a SPRG for each priority level so we can free up a 15563dafe57SBecky Bruce * GPR to use as the base for indirect access to the exception stacks. This 15663dafe57SBecky Bruce * is necessary since the MMU is always on, for Book-E parts, and the stacks 15763dafe57SBecky Bruce * are offset from KERNELBASE. 15863dafe57SBecky Bruce * 159eb0cd5fdSKumar Gala * There is some space optimization to be had here if desired. However 160eb0cd5fdSKumar Gala * to allow for a common kernel with support for debug exceptions either 161eb0cd5fdSKumar Gala * going to critical or their own debug level we aren't currently 162eb0cd5fdSKumar Gala * providing configurations that micro-optimize space usage. 16363dafe57SBecky Bruce */ 16463dafe57SBecky Bruce 165ee43eb78SBenjamin Herrenschmidt #define MC_STACK_BASE mcheckirq_ctx 166bcf0b088SKumar Gala #define CRIT_STACK_BASE critirq_ctx 16763dafe57SBecky Bruce 16839c8bf2bSChristophe Leroy /* only on e500mc */ 169ee43eb78SBenjamin Herrenschmidt #define DBG_STACK_BASE dbgirq_ctx 17063dafe57SBecky Bruce 17163dafe57SBecky Bruce #ifdef CONFIG_SMP 17263dafe57SBecky Bruce #define BOOKE_LOAD_EXC_LEVEL_STACK(level) \ 17363dafe57SBecky Bruce mfspr r8,SPRN_PIR; \ 174bcf0b088SKumar Gala slwi r8,r8,2; \ 175bcf0b088SKumar Gala addis r8,r8,level##_STACK_BASE@ha; \ 176bcf0b088SKumar Gala lwz r8,level##_STACK_BASE@l(r8); \ 177b5cfc9cdSChristophe Leroy addi r8,r8,THREAD_SIZE - INT_FRAME_SIZE; 17863dafe57SBecky Bruce #else 17963dafe57SBecky Bruce #define BOOKE_LOAD_EXC_LEVEL_STACK(level) \ 180bcf0b088SKumar Gala lis r8,level##_STACK_BASE@ha; \ 181bcf0b088SKumar Gala lwz r8,level##_STACK_BASE@l(r8); \ 182b5cfc9cdSChristophe Leroy addi r8,r8,THREAD_SIZE - INT_FRAME_SIZE; 18363dafe57SBecky Bruce #endif 18463dafe57SBecky Bruce 18563dafe57SBecky Bruce /* 18663dafe57SBecky Bruce * Exception prolog for critical/machine check exceptions. This is a 18763dafe57SBecky Bruce * little different from the normal exception prolog above since a 18863dafe57SBecky Bruce * critical/machine check exception can potentially occur at any point 18963dafe57SBecky Bruce * during normal exception processing. Thus we cannot use the same SPRG 19063dafe57SBecky Bruce * registers as the normal prolog above. Instead we use a portion of the 19163dafe57SBecky Bruce * critical/machine check exception stack at low physical addresses. 19263dafe57SBecky Bruce */ 193719e7e21SChristophe Leroy #define EXC_LEVEL_EXCEPTION_PROLOG(exc_level, trapno, intno, exc_level_srr0, exc_level_srr1) \ 194ee43eb78SBenjamin Herrenschmidt mtspr SPRN_SPRG_WSCRATCH_##exc_level,r8; \ 19563dafe57SBecky Bruce BOOKE_LOAD_EXC_LEVEL_STACK(exc_level);/* r8 points to the exc_level stack*/ \ 196369e757bSKumar Gala stw r9,GPR9(r8); /* save various registers */\ 197369e757bSKumar Gala mfcr r9; /* save CR in r9 for now */\ 198369e757bSKumar Gala stw r10,GPR10(r8); \ 199369e757bSKumar Gala stw r11,GPR11(r8); \ 200369e757bSKumar Gala stw r9,_CCR(r8); /* save CR on stack */\ 201d30f6e48SScott Wood mfspr r11,exc_level_srr1; /* check whether user or kernel */\ 202d30f6e48SScott Wood DO_KVM BOOKE_INTERRUPT_##intno exc_level_srr1; \ 203039daac5SDiana Craciun BOOKE_CLEAR_BTB(r10) \ 204d30f6e48SScott Wood andi. r11,r11,MSR_PR; \ 2059b6150fbSChristophe Leroy LOAD_REG_IMMEDIATE(r11, MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)); \ 2069b6150fbSChristophe Leroy mtmsr r11; \ 207ee43eb78SBenjamin Herrenschmidt mfspr r11,SPRN_SPRG_THREAD; /* if from user, start at top of */\ 2088c1fc5abSChristophe Leroy lwz r11, TASK_STACK - THREAD(r11); /* this thread's kernel stack */\ 209b5cfc9cdSChristophe Leroy addi r11,r11,THREAD_SIZE - INT_FRAME_SIZE; /* allocate stack frame */\ 210369e757bSKumar Gala beq 1f; \ 211369e757bSKumar Gala /* COMING FROM USER MODE */ \ 212369e757bSKumar Gala stw r9,_CCR(r11); /* save CR */\ 213369e757bSKumar Gala lwz r10,GPR10(r8); /* copy regs from exception stack */\ 214369e757bSKumar Gala lwz r9,GPR9(r8); \ 215369e757bSKumar Gala stw r10,GPR10(r11); \ 216369e757bSKumar Gala lwz r10,GPR11(r8); \ 21763dafe57SBecky Bruce stw r9,GPR9(r11); \ 218369e757bSKumar Gala stw r10,GPR11(r11); \ 219369e757bSKumar Gala b 2f; \ 220369e757bSKumar Gala /* COMING FROM PRIV MODE */ \ 221ed1cd6deSChristophe Leroy 1: mr r11, r8; \ 222ee43eb78SBenjamin Herrenschmidt 2: mfspr r8,SPRN_SPRG_RSCRATCH_##exc_level; \ 223369e757bSKumar Gala stw r12,GPR12(r11); /* save various registers */\ 22463dafe57SBecky Bruce mflr r10; \ 22563dafe57SBecky Bruce stw r10,_LINK(r11); \ 22663dafe57SBecky Bruce mfspr r12,SPRN_DEAR; /* save DEAR and ESR in the frame */\ 22763dafe57SBecky Bruce stw r12,_DEAR(r11); /* since they may have had stuff */\ 22863dafe57SBecky Bruce mfspr r9,SPRN_ESR; /* in them at the point where the */\ 22963dafe57SBecky Bruce stw r9,_ESR(r11); /* exception was taken */\ 23063dafe57SBecky Bruce mfspr r12,exc_level_srr0; \ 23163dafe57SBecky Bruce stw r1,GPR1(r11); \ 23263dafe57SBecky Bruce mfspr r9,exc_level_srr1; \ 23363dafe57SBecky Bruce stw r1,0(r11); \ 23463dafe57SBecky Bruce mr r1,r11; \ 23563dafe57SBecky Bruce rlwinm r9,r9,0,14,12; /* clear MSR_WE (necessary?) */\ 236a3055978SChristophe Leroy COMMON_EXCEPTION_PROLOG_END trapno 23763dafe57SBecky Bruce 23832d2ca0eSChristophe Leroy #define SAVE_xSRR(xSRR) \ 23932d2ca0eSChristophe Leroy mfspr r0,SPRN_##xSRR##0; \ 24032d2ca0eSChristophe Leroy stw r0,_##xSRR##0(r1); \ 24132d2ca0eSChristophe Leroy mfspr r0,SPRN_##xSRR##1; \ 24232d2ca0eSChristophe Leroy stw r0,_##xSRR##1(r1) 24332d2ca0eSChristophe Leroy 24432d2ca0eSChristophe Leroy 24532d2ca0eSChristophe Leroy .macro SAVE_MMU_REGS 246aa5f59dfSChristophe Leroy #ifdef CONFIG_PPC_E500 24732d2ca0eSChristophe Leroy mfspr r0,SPRN_MAS0 24832d2ca0eSChristophe Leroy stw r0,MAS0(r1) 24932d2ca0eSChristophe Leroy mfspr r0,SPRN_MAS1 25032d2ca0eSChristophe Leroy stw r0,MAS1(r1) 25132d2ca0eSChristophe Leroy mfspr r0,SPRN_MAS2 25232d2ca0eSChristophe Leroy stw r0,MAS2(r1) 25332d2ca0eSChristophe Leroy mfspr r0,SPRN_MAS3 25432d2ca0eSChristophe Leroy stw r0,MAS3(r1) 25532d2ca0eSChristophe Leroy mfspr r0,SPRN_MAS6 25632d2ca0eSChristophe Leroy stw r0,MAS6(r1) 25732d2ca0eSChristophe Leroy #ifdef CONFIG_PHYS_64BIT 25832d2ca0eSChristophe Leroy mfspr r0,SPRN_MAS7 25932d2ca0eSChristophe Leroy stw r0,MAS7(r1) 26032d2ca0eSChristophe Leroy #endif /* CONFIG_PHYS_64BIT */ 261aa5f59dfSChristophe Leroy #endif /* CONFIG_PPC_E500 */ 26232d2ca0eSChristophe Leroy #ifdef CONFIG_44x 26332d2ca0eSChristophe Leroy mfspr r0,SPRN_MMUCR 26432d2ca0eSChristophe Leroy stw r0,MMUCR(r1) 26532d2ca0eSChristophe Leroy #endif 26632d2ca0eSChristophe Leroy .endm 26732d2ca0eSChristophe Leroy 268719e7e21SChristophe Leroy #define CRITICAL_EXCEPTION_PROLOG(trapno, intno) \ 269719e7e21SChristophe Leroy EXC_LEVEL_EXCEPTION_PROLOG(CRIT, trapno+2, intno, SPRN_CSRR0, SPRN_CSRR1) 270719e7e21SChristophe Leroy #define DEBUG_EXCEPTION_PROLOG(trapno) \ 271719e7e21SChristophe Leroy EXC_LEVEL_EXCEPTION_PROLOG(DBG, trapno+8, DEBUG, SPRN_DSRR0, SPRN_DSRR1) 272719e7e21SChristophe Leroy #define MCHECK_EXCEPTION_PROLOG(trapno) \ 273719e7e21SChristophe Leroy EXC_LEVEL_EXCEPTION_PROLOG(MC, trapno+4, MACHINE_CHECK, \ 274cfac5784SScott Wood SPRN_MCSRR0, SPRN_MCSRR1) 27563dafe57SBecky Bruce 27663dafe57SBecky Bruce /* 277d30f6e48SScott Wood * Guest Doorbell -- this is a bit odd in that uses GSRR0/1 despite 278d30f6e48SScott Wood * being delivered to the host. This exception can only happen 279d30f6e48SScott Wood * inside a KVM guest -- so we just handle up to the DO_KVM rather 280d30f6e48SScott Wood * than try to fit this into one of the existing prolog macros. 281d30f6e48SScott Wood */ 282d30f6e48SScott Wood #define GUEST_DOORBELL_EXCEPTION \ 283d30f6e48SScott Wood START_EXCEPTION(GuestDoorbell); \ 284d30f6e48SScott Wood mtspr SPRN_SPRG_WSCRATCH0, r10; /* save one register */ \ 285d30f6e48SScott Wood mfspr r10, SPRN_SPRG_THREAD; \ 286d30f6e48SScott Wood stw r11, THREAD_NORMSAVE(0)(r10); \ 287d30f6e48SScott Wood mfspr r11, SPRN_SRR1; \ 288d30f6e48SScott Wood stw r13, THREAD_NORMSAVE(2)(r10); \ 289d30f6e48SScott Wood mfcr r13; /* save CR in r13 for now */\ 290d30f6e48SScott Wood DO_KVM BOOKE_INTERRUPT_GUEST_DBELL SPRN_GSRR1; \ 291d30f6e48SScott Wood trap 292d30f6e48SScott Wood 293d30f6e48SScott Wood /* 29463dafe57SBecky Bruce * Exception vectors. 29563dafe57SBecky Bruce */ 29663dafe57SBecky Bruce #define START_EXCEPTION(label) \ 29763dafe57SBecky Bruce .align 5; \ 29863dafe57SBecky Bruce label: 29963dafe57SBecky Bruce 300acc142b6SChristophe Leroy #define EXCEPTION(n, intno, label, hdlr) \ 30163dafe57SBecky Bruce START_EXCEPTION(label); \ 302719e7e21SChristophe Leroy NORMAL_EXCEPTION_PROLOG(n, intno); \ 3034c0104a8SChristophe Leroy prepare_transfer_to_handler; \ 3044c0104a8SChristophe Leroy bl hdlr; \ 3054c0104a8SChristophe Leroy b interrupt_return 30663dafe57SBecky Bruce 307cfac5784SScott Wood #define CRITICAL_EXCEPTION(n, intno, label, hdlr) \ 30863dafe57SBecky Bruce START_EXCEPTION(label); \ 309719e7e21SChristophe Leroy CRITICAL_EXCEPTION_PROLOG(n, intno); \ 31032d2ca0eSChristophe Leroy SAVE_MMU_REGS; \ 31132d2ca0eSChristophe Leroy SAVE_xSRR(SRR); \ 3124c0104a8SChristophe Leroy prepare_transfer_to_handler; \ 3134c0104a8SChristophe Leroy bl hdlr; \ 3144c0104a8SChristophe Leroy b ret_from_crit_exc 31563dafe57SBecky Bruce 31663dafe57SBecky Bruce #define MCHECK_EXCEPTION(n, label, hdlr) \ 31763dafe57SBecky Bruce START_EXCEPTION(label); \ 318719e7e21SChristophe Leroy MCHECK_EXCEPTION_PROLOG(n); \ 31963dafe57SBecky Bruce mfspr r5,SPRN_ESR; \ 32063dafe57SBecky Bruce stw r5,_ESR(r11); \ 32132d2ca0eSChristophe Leroy SAVE_xSRR(DSRR); \ 32232d2ca0eSChristophe Leroy SAVE_xSRR(CSRR); \ 32332d2ca0eSChristophe Leroy SAVE_MMU_REGS; \ 32432d2ca0eSChristophe Leroy SAVE_xSRR(SRR); \ 3254c0104a8SChristophe Leroy prepare_transfer_to_handler; \ 3260f2793e3SChristophe Leroy bl hdlr; \ 3274c0104a8SChristophe Leroy b ret_from_mcheck_exc 32863dafe57SBecky Bruce 32963dafe57SBecky Bruce /* Check for a single step debug exception while in an exception 33063dafe57SBecky Bruce * handler before state has been saved. This is to catch the case 33163dafe57SBecky Bruce * where an instruction that we are trying to single step causes 33263dafe57SBecky Bruce * an exception (eg ITLB/DTLB miss) and thus the first instruction of 33363dafe57SBecky Bruce * the exception handler generates a single step debug exception. 33463dafe57SBecky Bruce * 33563dafe57SBecky Bruce * If we get a debug trap on the first instruction of an exception handler, 33663dafe57SBecky Bruce * we reset the MSR_DE in the _exception handler's_ MSR (the debug trap is 33763dafe57SBecky Bruce * a critical exception, so we are using SPRN_CSRR1 to manipulate the MSR). 33863dafe57SBecky Bruce * The exception handler was handling a non-critical interrupt, so it will 33963dafe57SBecky Bruce * save (and later restore) the MSR via SPRN_CSRR1, which will still have 34063dafe57SBecky Bruce * the MSR_DE bit set. 34163dafe57SBecky Bruce */ 342eb0cd5fdSKumar Gala #define DEBUG_DEBUG_EXCEPTION \ 343eb0cd5fdSKumar Gala START_EXCEPTION(DebugDebug); \ 344719e7e21SChristophe Leroy DEBUG_EXCEPTION_PROLOG(2000); \ 34563dafe57SBecky Bruce \ 34663dafe57SBecky Bruce /* \ 34763dafe57SBecky Bruce * If there is a single step or branch-taken exception in an \ 34863dafe57SBecky Bruce * exception entry sequence, it was probably meant to apply to \ 34963dafe57SBecky Bruce * the code where the exception occurred (since exception entry \ 35063dafe57SBecky Bruce * doesn't turn off DE automatically). We simulate the effect \ 35163dafe57SBecky Bruce * of turning off DE on entry to an exception handler by turning \ 352fec6a822SKumar Gala * off DE in the DSRR1 value and clearing the debug status. \ 35363dafe57SBecky Bruce */ \ 35463dafe57SBecky Bruce mfspr r10,SPRN_DBSR; /* check single-step/branch taken */ \ 355ec097c84SRoland McGrath andis. r10,r10,(DBSR_IC|DBSR_BT)@h; \ 35663dafe57SBecky Bruce beq+ 2f; \ 35763dafe57SBecky Bruce \ 358fc2a6cfeSBharat Bhushan lis r10,interrupt_base@h; /* check if exception in vectors */ \ 359fc2a6cfeSBharat Bhushan ori r10,r10,interrupt_base@l; \ 36063dafe57SBecky Bruce cmplw r12,r10; \ 36163dafe57SBecky Bruce blt+ 2f; /* addr below exception vectors */ \ 36263dafe57SBecky Bruce \ 363fc2a6cfeSBharat Bhushan lis r10,interrupt_end@h; \ 364fc2a6cfeSBharat Bhushan ori r10,r10,interrupt_end@l; \ 36563dafe57SBecky Bruce cmplw r12,r10; \ 36663dafe57SBecky Bruce bgt+ 2f; /* addr above exception vectors */ \ 36763dafe57SBecky Bruce \ 36863dafe57SBecky Bruce /* here it looks like we got an inappropriate debug exception. */ \ 36963dafe57SBecky Bruce 1: rlwinm r9,r9,0,~MSR_DE; /* clear DE in the CDRR1 value */ \ 370ec097c84SRoland McGrath lis r10,(DBSR_IC|DBSR_BT)@h; /* clear the IC event */ \ 37163dafe57SBecky Bruce mtspr SPRN_DBSR,r10; \ 37263dafe57SBecky Bruce /* restore state and get out */ \ 37363dafe57SBecky Bruce lwz r10,_CCR(r11); \ 37463dafe57SBecky Bruce lwz r0,GPR0(r11); \ 37563dafe57SBecky Bruce lwz r1,GPR1(r11); \ 37663dafe57SBecky Bruce mtcrf 0x80,r10; \ 37763dafe57SBecky Bruce mtspr SPRN_DSRR0,r12; \ 37863dafe57SBecky Bruce mtspr SPRN_DSRR1,r9; \ 37963dafe57SBecky Bruce lwz r9,GPR9(r11); \ 38063dafe57SBecky Bruce lwz r12,GPR12(r11); \ 381ee43eb78SBenjamin Herrenschmidt mtspr SPRN_SPRG_WSCRATCH_DBG,r8; \ 382ee43eb78SBenjamin Herrenschmidt BOOKE_LOAD_EXC_LEVEL_STACK(DBG); /* r8 points to the debug stack */ \ 383369e757bSKumar Gala lwz r10,GPR10(r8); \ 384369e757bSKumar Gala lwz r11,GPR11(r8); \ 385ee43eb78SBenjamin Herrenschmidt mfspr r8,SPRN_SPRG_RSCRATCH_DBG; \ 38663dafe57SBecky Bruce \ 38716c57b36SKumar Gala PPC_RFDI; \ 38863dafe57SBecky Bruce b .; \ 38963dafe57SBecky Bruce \ 390fec6a822SKumar Gala /* continue normal handling for a debug exception... */ \ 39163dafe57SBecky Bruce 2: mfspr r4,SPRN_DBSR; \ 392755d6641SNicholas Piggin stw r4,_ESR(r11); /* DebugException takes DBSR in _ESR */\ 39332d2ca0eSChristophe Leroy SAVE_xSRR(CSRR); \ 39432d2ca0eSChristophe Leroy SAVE_MMU_REGS; \ 39532d2ca0eSChristophe Leroy SAVE_xSRR(SRR); \ 3964c0104a8SChristophe Leroy prepare_transfer_to_handler; \ 3974c0104a8SChristophe Leroy bl DebugException; \ 3984c0104a8SChristophe Leroy b ret_from_debug_exc 399eb0cd5fdSKumar Gala 400eb0cd5fdSKumar Gala #define DEBUG_CRIT_EXCEPTION \ 401eb0cd5fdSKumar Gala START_EXCEPTION(DebugCrit); \ 402719e7e21SChristophe Leroy CRITICAL_EXCEPTION_PROLOG(2000,DEBUG); \ 40363dafe57SBecky Bruce \ 40463dafe57SBecky Bruce /* \ 40563dafe57SBecky Bruce * If there is a single step or branch-taken exception in an \ 40663dafe57SBecky Bruce * exception entry sequence, it was probably meant to apply to \ 40763dafe57SBecky Bruce * the code where the exception occurred (since exception entry \ 40863dafe57SBecky Bruce * doesn't turn off DE automatically). We simulate the effect \ 40963dafe57SBecky Bruce * of turning off DE on entry to an exception handler by turning \ 41063dafe57SBecky Bruce * off DE in the CSRR1 value and clearing the debug status. \ 41163dafe57SBecky Bruce */ \ 41263dafe57SBecky Bruce mfspr r10,SPRN_DBSR; /* check single-step/branch taken */ \ 413ec097c84SRoland McGrath andis. r10,r10,(DBSR_IC|DBSR_BT)@h; \ 41463dafe57SBecky Bruce beq+ 2f; \ 41563dafe57SBecky Bruce \ 416fc2a6cfeSBharat Bhushan lis r10,interrupt_base@h; /* check if exception in vectors */ \ 417fc2a6cfeSBharat Bhushan ori r10,r10,interrupt_base@l; \ 41863dafe57SBecky Bruce cmplw r12,r10; \ 41963dafe57SBecky Bruce blt+ 2f; /* addr below exception vectors */ \ 42063dafe57SBecky Bruce \ 421fc2a6cfeSBharat Bhushan lis r10,interrupt_end@h; \ 422fc2a6cfeSBharat Bhushan ori r10,r10,interrupt_end@l; \ 42363dafe57SBecky Bruce cmplw r12,r10; \ 42463dafe57SBecky Bruce bgt+ 2f; /* addr above exception vectors */ \ 42563dafe57SBecky Bruce \ 42663dafe57SBecky Bruce /* here it looks like we got an inappropriate debug exception. */ \ 42763dafe57SBecky Bruce 1: rlwinm r9,r9,0,~MSR_DE; /* clear DE in the CSRR1 value */ \ 428ec097c84SRoland McGrath lis r10,(DBSR_IC|DBSR_BT)@h; /* clear the IC event */ \ 42963dafe57SBecky Bruce mtspr SPRN_DBSR,r10; \ 43063dafe57SBecky Bruce /* restore state and get out */ \ 43163dafe57SBecky Bruce lwz r10,_CCR(r11); \ 43263dafe57SBecky Bruce lwz r0,GPR0(r11); \ 43363dafe57SBecky Bruce lwz r1,GPR1(r11); \ 43463dafe57SBecky Bruce mtcrf 0x80,r10; \ 43563dafe57SBecky Bruce mtspr SPRN_CSRR0,r12; \ 43663dafe57SBecky Bruce mtspr SPRN_CSRR1,r9; \ 43763dafe57SBecky Bruce lwz r9,GPR9(r11); \ 43863dafe57SBecky Bruce lwz r12,GPR12(r11); \ 439ee43eb78SBenjamin Herrenschmidt mtspr SPRN_SPRG_WSCRATCH_CRIT,r8; \ 44063dafe57SBecky Bruce BOOKE_LOAD_EXC_LEVEL_STACK(CRIT); /* r8 points to the debug stack */ \ 441369e757bSKumar Gala lwz r10,GPR10(r8); \ 442369e757bSKumar Gala lwz r11,GPR11(r8); \ 443ee43eb78SBenjamin Herrenschmidt mfspr r8,SPRN_SPRG_RSCRATCH_CRIT; \ 44463dafe57SBecky Bruce \ 44563dafe57SBecky Bruce rfci; \ 44663dafe57SBecky Bruce b .; \ 44763dafe57SBecky Bruce \ 44863dafe57SBecky Bruce /* continue normal handling for a critical exception... */ \ 44963dafe57SBecky Bruce 2: mfspr r4,SPRN_DBSR; \ 450755d6641SNicholas Piggin stw r4,_ESR(r11); /* DebugException takes DBSR in _ESR */\ 45132d2ca0eSChristophe Leroy SAVE_MMU_REGS; \ 45232d2ca0eSChristophe Leroy SAVE_xSRR(SRR); \ 4534c0104a8SChristophe Leroy prepare_transfer_to_handler; \ 4544c0104a8SChristophe Leroy bl DebugException; \ 4554c0104a8SChristophe Leroy b ret_from_crit_exc 45663dafe57SBecky Bruce 4571bc54c03SBenjamin Herrenschmidt #define DATA_STORAGE_EXCEPTION \ 4581bc54c03SBenjamin Herrenschmidt START_EXCEPTION(DataStorage) \ 459719e7e21SChristophe Leroy NORMAL_EXCEPTION_PROLOG(0x300, DATA_STORAGE); \ 4601bc54c03SBenjamin Herrenschmidt mfspr r5,SPRN_ESR; /* Grab the ESR and save it */ \ 4611bc54c03SBenjamin Herrenschmidt stw r5,_ESR(r11); \ 4621bc54c03SBenjamin Herrenschmidt mfspr r4,SPRN_DEAR; /* Grab the DEAR */ \ 4631ca9db5bSChristophe Leroy stw r4, _DEAR(r11); \ 4644c0104a8SChristophe Leroy prepare_transfer_to_handler; \ 4654c0104a8SChristophe Leroy bl do_page_fault; \ 4664c0104a8SChristophe Leroy b interrupt_return 4671bc54c03SBenjamin Herrenschmidt 46881291383SNicholas Piggin /* 46981291383SNicholas Piggin * Instruction TLB Error interrupt handlers may call InstructionStorage 47081291383SNicholas Piggin * directly without clearing ESR, so the ESR at this point may be left over 47181291383SNicholas Piggin * from a prior interrupt. 47281291383SNicholas Piggin * 47381291383SNicholas Piggin * In any case, do_page_fault for BOOK3E does not use ESR and always expects 47481291383SNicholas Piggin * dsisr to be 0. ESR_DST from a prior store in particular would confuse fault 47581291383SNicholas Piggin * handling. 47681291383SNicholas Piggin */ 47763dafe57SBecky Bruce #define INSTRUCTION_STORAGE_EXCEPTION \ 47863dafe57SBecky Bruce START_EXCEPTION(InstructionStorage) \ 479719e7e21SChristophe Leroy NORMAL_EXCEPTION_PROLOG(0x400, INST_STORAGE); \ 48081291383SNicholas Piggin li r5,0; /* Store 0 in regs->esr (dsisr) */ \ 48163dafe57SBecky Bruce stw r5,_ESR(r11); \ 48281291383SNicholas Piggin stw r12, _DEAR(r11); /* Set regs->dear (dar) to SRR0 */ \ 4834c0104a8SChristophe Leroy prepare_transfer_to_handler; \ 4844c0104a8SChristophe Leroy bl do_page_fault; \ 4854c0104a8SChristophe Leroy b interrupt_return 48663dafe57SBecky Bruce 48763dafe57SBecky Bruce #define ALIGNMENT_EXCEPTION \ 48863dafe57SBecky Bruce START_EXCEPTION(Alignment) \ 489719e7e21SChristophe Leroy NORMAL_EXCEPTION_PROLOG(0x600, ALIGNMENT); \ 49063dafe57SBecky Bruce mfspr r4,SPRN_DEAR; /* Grab the DEAR and save it */ \ 49163dafe57SBecky Bruce stw r4,_DEAR(r11); \ 4928f6ff5bdSChristophe Leroy prepare_transfer_to_handler; \ 4938f6ff5bdSChristophe Leroy bl alignment_exception; \ 4948f6ff5bdSChristophe Leroy REST_NVGPRS(r1); \ 4958f6ff5bdSChristophe Leroy b interrupt_return 49663dafe57SBecky Bruce 49763dafe57SBecky Bruce #define PROGRAM_EXCEPTION \ 49863dafe57SBecky Bruce START_EXCEPTION(Program) \ 499719e7e21SChristophe Leroy NORMAL_EXCEPTION_PROLOG(0x700, PROGRAM); \ 50063dafe57SBecky Bruce mfspr r4,SPRN_ESR; /* Grab the ESR and save it */ \ 50163dafe57SBecky Bruce stw r4,_ESR(r11); \ 5028f6ff5bdSChristophe Leroy prepare_transfer_to_handler; \ 5038f6ff5bdSChristophe Leroy bl program_check_exception; \ 5048f6ff5bdSChristophe Leroy REST_NVGPRS(r1); \ 5058f6ff5bdSChristophe Leroy b interrupt_return 50663dafe57SBecky Bruce 50763dafe57SBecky Bruce #define DECREMENTER_EXCEPTION \ 50863dafe57SBecky Bruce START_EXCEPTION(Decrementer) \ 509719e7e21SChristophe Leroy NORMAL_EXCEPTION_PROLOG(0x900, DECREMENTER); \ 51063dafe57SBecky Bruce lis r0,TSR_DIS@h; /* Setup the DEC interrupt mask */ \ 51163dafe57SBecky Bruce mtspr SPRN_TSR,r0; /* Clear the DEC interrupt */ \ 5124c0104a8SChristophe Leroy prepare_transfer_to_handler; \ 5134c0104a8SChristophe Leroy bl timer_interrupt; \ 5144c0104a8SChristophe Leroy b interrupt_return 51563dafe57SBecky Bruce 51663dafe57SBecky Bruce #define FP_UNAVAILABLE_EXCEPTION \ 51763dafe57SBecky Bruce START_EXCEPTION(FloatingPointUnavailable) \ 518719e7e21SChristophe Leroy NORMAL_EXCEPTION_PROLOG(0x800, FP_UNAVAIL); \ 5196f3d8e69SMichael Neuling beq 1f; \ 5206f3d8e69SMichael Neuling bl load_up_fpu; /* if from user, just load it up */ \ 5216f3d8e69SMichael Neuling b fast_exception_return; \ 5224c0104a8SChristophe Leroy 1: prepare_transfer_to_handler; \ 5234c0104a8SChristophe Leroy bl kernel_fp_unavailable_exception; \ 5244c0104a8SChristophe Leroy b interrupt_return 52563dafe57SBecky Bruce 526fca622c5SKumar Gala #endif /* __ASSEMBLY__ */ 52763dafe57SBecky Bruce #endif /* __HEAD_BOOKE_H__ */ 528