1 /* SPDX-License-Identifier: GPL-2.0 */ 2 #ifndef __HEAD_32_H__ 3 #define __HEAD_32_H__ 4 5 #include <asm/ptrace.h> /* for STACK_FRAME_REGS_MARKER */ 6 7 /* 8 * Exception entry code. This code runs with address translation 9 * turned off, i.e. using physical addresses. 10 * We assume sprg3 has the physical address of the current 11 * task's thread_struct. 12 */ 13 14 .macro EXCEPTION_PROLOG 15 mtspr SPRN_SPRG_SCRATCH0,r10 16 mtspr SPRN_SPRG_SCRATCH1,r11 17 mfcr r10 18 EXCEPTION_PROLOG_1 19 EXCEPTION_PROLOG_2 20 .endm 21 22 .macro EXCEPTION_PROLOG_1 23 mfspr r11,SPRN_SRR1 /* check whether user or kernel */ 24 andi. r11,r11,MSR_PR 25 tophys(r11,r1) /* use tophys(r1) if kernel */ 26 beq 1f 27 mfspr r11,SPRN_SPRG_THREAD 28 lwz r11,TASK_STACK-THREAD(r11) 29 addi r11,r11,THREAD_SIZE 30 tophys(r11,r11) 31 1: subi r11,r11,INT_FRAME_SIZE /* alloc exc. frame */ 32 .endm 33 34 .macro EXCEPTION_PROLOG_2 35 stw r10,_CCR(r11) /* save registers */ 36 stw r12,GPR12(r11) 37 stw r9,GPR9(r11) 38 mfspr r10,SPRN_SPRG_SCRATCH0 39 stw r10,GPR10(r11) 40 mfspr r12,SPRN_SPRG_SCRATCH1 41 stw r12,GPR11(r11) 42 mflr r10 43 stw r10,_LINK(r11) 44 mfspr r12,SPRN_SRR0 45 mfspr r9,SPRN_SRR1 46 stw r1,GPR1(r11) 47 stw r1,0(r11) 48 tovirt(r1,r11) /* set new kernel sp */ 49 #ifdef CONFIG_40x 50 rlwinm r9,r9,0,14,12 /* clear MSR_WE (necessary?) */ 51 #else 52 li r10,MSR_KERNEL & ~(MSR_IR|MSR_DR) /* can take exceptions */ 53 MTMSRD(r10) /* (except for mach check in rtas) */ 54 #endif 55 stw r0,GPR0(r11) 56 lis r10,STACK_FRAME_REGS_MARKER@ha /* exception frame marker */ 57 addi r10,r10,STACK_FRAME_REGS_MARKER@l 58 stw r10,8(r11) 59 SAVE_4GPRS(3, r11) 60 SAVE_2GPRS(7, r11) 61 .endm 62 63 .macro SYSCALL_ENTRY trapno 64 mfspr r12,SPRN_SPRG_THREAD 65 mfcr r10 66 lwz r11,TASK_STACK-THREAD(r12) 67 mflr r9 68 addi r11,r11,THREAD_SIZE - INT_FRAME_SIZE 69 rlwinm r10,r10,0,4,2 /* Clear SO bit in CR */ 70 tophys(r11,r11) 71 stw r10,_CCR(r11) /* save registers */ 72 mfspr r10,SPRN_SRR0 73 stw r9,_LINK(r11) 74 mfspr r9,SPRN_SRR1 75 stw r1,GPR1(r11) 76 stw r1,0(r11) 77 tovirt(r1,r11) /* set new kernel sp */ 78 stw r10,_NIP(r11) 79 #ifdef CONFIG_40x 80 rlwinm r9,r9,0,14,12 /* clear MSR_WE (necessary?) */ 81 #else 82 LOAD_REG_IMMEDIATE(r10, MSR_KERNEL & ~(MSR_IR|MSR_DR)) /* can take exceptions */ 83 MTMSRD(r10) /* (except for mach check in rtas) */ 84 #endif 85 lis r10,STACK_FRAME_REGS_MARKER@ha /* exception frame marker */ 86 stw r2,GPR2(r11) 87 addi r10,r10,STACK_FRAME_REGS_MARKER@l 88 stw r9,_MSR(r11) 89 li r2, \trapno + 1 90 stw r10,8(r11) 91 stw r2,_TRAP(r11) 92 SAVE_GPR(0, r11) 93 SAVE_4GPRS(3, r11) 94 SAVE_2GPRS(7, r11) 95 addi r11,r1,STACK_FRAME_OVERHEAD 96 addi r2,r12,-THREAD 97 stw r11,PT_REGS(r12) 98 #if defined(CONFIG_40x) 99 /* Check to see if the dbcr0 register is set up to debug. Use the 100 internal debug mode bit to do this. */ 101 lwz r12,THREAD_DBCR0(r12) 102 andis. r12,r12,DBCR0_IDM@h 103 #endif 104 ACCOUNT_CPU_USER_ENTRY(r2, r11, r12) 105 #if defined(CONFIG_40x) 106 beq+ 3f 107 /* From user and task is ptraced - load up global dbcr0 */ 108 li r12,-1 /* clear all pending debug events */ 109 mtspr SPRN_DBSR,r12 110 lis r11,global_dbcr0@ha 111 tophys(r11,r11) 112 addi r11,r11,global_dbcr0@l 113 lwz r12,0(r11) 114 mtspr SPRN_DBCR0,r12 115 lwz r12,4(r11) 116 addi r12,r12,-1 117 stw r12,4(r11) 118 #endif 119 120 3: 121 tovirt(r2, r2) /* set r2 to current */ 122 lis r11, transfer_to_syscall@h 123 ori r11, r11, transfer_to_syscall@l 124 #ifdef CONFIG_TRACE_IRQFLAGS 125 /* 126 * If MSR is changing we need to keep interrupts disabled at this point 127 * otherwise we might risk taking an interrupt before we tell lockdep 128 * they are enabled. 129 */ 130 LOAD_REG_IMMEDIATE(r10, MSR_KERNEL) 131 rlwimi r10, r9, 0, MSR_EE 132 #else 133 LOAD_REG_IMMEDIATE(r10, MSR_KERNEL | MSR_EE) 134 #endif 135 #if defined(CONFIG_PPC_8xx) && defined(CONFIG_PERF_EVENTS) 136 mtspr SPRN_NRI, r0 137 #endif 138 mtspr SPRN_SRR1,r10 139 mtspr SPRN_SRR0,r11 140 SYNC 141 RFI /* jump to handler, enable MMU */ 142 .endm 143 144 /* 145 * Note: code which follows this uses cr0.eq (set if from kernel), 146 * r11, r12 (SRR0), and r9 (SRR1). 147 * 148 * Note2: once we have set r1 we are in a position to take exceptions 149 * again, and we could thus set MSR:RI at that point. 150 */ 151 152 /* 153 * Exception vectors. 154 */ 155 #ifdef CONFIG_PPC_BOOK3S 156 #define START_EXCEPTION(n, label) \ 157 . = n; \ 158 DO_KVM n; \ 159 label: 160 161 #else 162 #define START_EXCEPTION(n, label) \ 163 . = n; \ 164 label: 165 166 #endif 167 168 #define EXCEPTION(n, label, hdlr, xfer) \ 169 START_EXCEPTION(n, label) \ 170 EXCEPTION_PROLOG; \ 171 addi r3,r1,STACK_FRAME_OVERHEAD; \ 172 xfer(n, hdlr) 173 174 #define EXC_XFER_TEMPLATE(hdlr, trap, msr, tfer, ret) \ 175 li r10,trap; \ 176 stw r10,_TRAP(r11); \ 177 LOAD_REG_IMMEDIATE(r10, msr); \ 178 bl tfer; \ 179 .long hdlr; \ 180 .long ret 181 182 #define EXC_XFER_STD(n, hdlr) \ 183 EXC_XFER_TEMPLATE(hdlr, n, MSR_KERNEL, transfer_to_handler_full, \ 184 ret_from_except_full) 185 186 #define EXC_XFER_LITE(n, hdlr) \ 187 EXC_XFER_TEMPLATE(hdlr, n+1, MSR_KERNEL, transfer_to_handler, \ 188 ret_from_except) 189 190 #endif /* __HEAD_32_H__ */ 191