Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 | /* SPDX-License-Identifier: GPL-2.0 */ #ifndef __HEAD_32_H__ #define __HEAD_32_H__ #include <asm/ptrace.h> /* for STACK_FRAME_REGS_MARKER */ /* * Exception entry code. This code runs with address translation * turned off, i.e. using physical addresses. * We assume sprg3 has the physical address of the current * task's thread_struct. */ .macro EXCEPTION_PROLOG trapno name handle_dar_dsisr=0 EXCEPTION_PROLOG_0 handle_dar_dsisr=\handle_dar_dsisr EXCEPTION_PROLOG_1 EXCEPTION_PROLOG_2 \trapno \name handle_dar_dsisr=\handle_dar_dsisr .endm .macro EXCEPTION_PROLOG_0 handle_dar_dsisr=0 mtspr SPRN_SPRG_SCRATCH0,r10 mtspr SPRN_SPRG_SCRATCH1,r11 mfspr r10, SPRN_SPRG_THREAD .if \handle_dar_dsisr #ifdef CONFIG_40x mfspr r11, SPRN_DEAR #else mfspr r11, SPRN_DAR #endif stw r11, DAR(r10) #ifdef CONFIG_40x mfspr r11, SPRN_ESR #else mfspr r11, SPRN_DSISR #endif stw r11, DSISR(r10) .endif mfspr r11, SPRN_SRR0 stw r11, SRR0(r10) mfspr r11, SPRN_SRR1 /* check whether user or kernel */ stw r11, SRR1(r10) mfcr r10 andi. r11, r11, MSR_PR .endm .macro EXCEPTION_PROLOG_1 mtspr SPRN_SPRG_SCRATCH2,r1 subi r1, r1, INT_FRAME_SIZE /* use r1 if kernel */ beq 1f mfspr r1,SPRN_SPRG_THREAD lwz r1,TASK_STACK-THREAD(r1) addi r1, r1, THREAD_SIZE - INT_FRAME_SIZE 1: #ifdef CONFIG_VMAP_STACK mtcrf 0x3f, r1 bt 32 - THREAD_ALIGN_SHIFT, vmap_stack_overflow #endif .endm .macro EXCEPTION_PROLOG_2 trapno name handle_dar_dsisr=0 #ifdef CONFIG_PPC_8xx .if \handle_dar_dsisr li r11, RPN_PATTERN mtspr SPRN_DAR, r11 /* Tag DAR, to be used in DTLB Error */ .endif #endif LOAD_REG_IMMEDIATE(r11, MSR_KERNEL & ~MSR_RI) /* re-enable MMU */ mtspr SPRN_SRR1, r11 lis r11, 1f@h ori r11, r11, 1f@l mtspr SPRN_SRR0, r11 mfspr r11, SPRN_SPRG_SCRATCH2 rfi .text \name\()_virt: 1: stw r11,GPR1(r1) stw r11,0(r1) mr r11, r1 stw r10,_CCR(r11) /* save registers */ stw r12,GPR12(r11) stw r9,GPR9(r11) mfspr r10,SPRN_SPRG_SCRATCH0 mfspr r12,SPRN_SPRG_SCRATCH1 stw r10,GPR10(r11) stw r12,GPR11(r11) mflr r10 stw r10,_LINK(r11) mfspr r12, SPRN_SPRG_THREAD tovirt(r12, r12) .if \handle_dar_dsisr lwz r10, DAR(r12) stw r10, _DAR(r11) lwz r10, DSISR(r12) stw r10, _DSISR(r11) .endif lwz r9, SRR1(r12) lwz r12, SRR0(r12) #ifdef CONFIG_40x rlwinm r9,r9,0,14,12 /* clear MSR_WE (necessary?) */ #elif defined(CONFIG_PPC_8xx) mtspr SPRN_EID, r2 /* Set MSR_RI */ #else li r10, MSR_KERNEL /* can take exceptions */ mtmsr r10 /* (except for mach check in rtas) */ #endif COMMON_EXCEPTION_PROLOG_END \trapno _ASM_NOKPROBE_SYMBOL(\name\()_virt) .endm .macro COMMON_EXCEPTION_PROLOG_END trapno stw r0,GPR0(r1) lis r10,STACK_FRAME_REGS_MARKER@ha /* exception frame marker */ addi r10,r10,STACK_FRAME_REGS_MARKER@l stw r10,STACK_INT_FRAME_MARKER(r1) li r10, \trapno stw r10,_TRAP(r1) SAVE_GPRS(3, 8, r1) SAVE_NVGPRS(r1) stw r2,GPR2(r1) stw r12,_NIP(r1) stw r9,_MSR(r1) mfctr r10 mfspr r2,SPRN_SPRG_THREAD stw r10,_CTR(r1) tovirt(r2, r2) mfspr r10,SPRN_XER addi r2, r2, -THREAD stw r10,_XER(r1) addi r3,r1,STACK_INT_FRAME_REGS .endm .macro prepare_transfer_to_handler #ifdef CONFIG_PPC_BOOK3S_32 andi. r12,r9,MSR_PR bne 777f bl prepare_transfer_to_handler #ifdef CONFIG_PPC_KUEP b 778f 777: bl __kuep_lock 778: #endif 777: #endif .endm .macro SYSCALL_ENTRY trapno mfspr r9, SPRN_SRR1 mfspr r12, SPRN_SRR0 LOAD_REG_IMMEDIATE(r11, MSR_KERNEL) /* can take exceptions */ lis r10, 1f@h ori r10, r10, 1f@l mtspr SPRN_SRR1, r11 mtspr SPRN_SRR0, r10 mfspr r10,SPRN_SPRG_THREAD mr r11, r1 lwz r1,TASK_STACK-THREAD(r10) tovirt(r10, r10) addi r1, r1, THREAD_SIZE - INT_FRAME_SIZE rfi 1: stw r12,_NIP(r1) mfcr r12 rlwinm r12,r12,0,4,2 /* Clear SO bit in CR */ stw r12,_CCR(r1) b transfer_to_syscall /* jump to handler */ .endm /* * Note: code which follows this uses cr0.eq (set if from kernel), * r11, r12 (SRR0), and r9 (SRR1). * * Note2: once we have set r1 we are in a position to take exceptions * again, and we could thus set MSR:RI at that point. */ /* * Exception vectors. */ #ifdef CONFIG_PPC_BOOK3S #define START_EXCEPTION(n, label) \ __HEAD; \ . = n; \ DO_KVM n; \ label: #else #define START_EXCEPTION(n, label) \ __HEAD; \ . = n; \ label: #endif #define EXCEPTION(n, label, hdlr) \ START_EXCEPTION(n, label) \ EXCEPTION_PROLOG n label; \ prepare_transfer_to_handler; \ bl hdlr; \ b interrupt_return .macro vmap_stack_overflow_exception __HEAD vmap_stack_overflow: #ifdef CONFIG_SMP mfspr r1, SPRN_SPRG_THREAD lwz r1, TASK_CPU - THREAD(r1) slwi r1, r1, 3 addis r1, r1, emergency_ctx-PAGE_OFFSET@ha #else lis r1, emergency_ctx-PAGE_OFFSET@ha #endif lwz r1, emergency_ctx-PAGE_OFFSET@l(r1) addi r1, r1, THREAD_SIZE - INT_FRAME_SIZE EXCEPTION_PROLOG_2 0 vmap_stack_overflow prepare_transfer_to_handler bl stack_overflow_exception b interrupt_return .endm #endif /* __HEAD_32_H__ */ |