1 #ifndef _ASM_POWERPC_EXCEPTION_H 2 #define _ASM_POWERPC_EXCEPTION_H 3 /* 4 * Extracted from head_64.S 5 * 6 * PowerPC version 7 * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) 8 * 9 * Rewritten by Cort Dougan (cort@cs.nmt.edu) for PReP 10 * Copyright (C) 1996 Cort Dougan <cort@cs.nmt.edu> 11 * Adapted for Power Macintosh by Paul Mackerras. 12 * Low-level exception handlers and MMU support 13 * rewritten by Paul Mackerras. 14 * Copyright (C) 1996 Paul Mackerras. 15 * 16 * Adapted for 64bit PowerPC by Dave Engebretsen, Peter Bergner, and 17 * Mike Corrigan {engebret|bergner|mikejc}@us.ibm.com 18 * 19 * This file contains the low-level support and setup for the 20 * PowerPC-64 platform, including trap and interrupt dispatch. 21 * 22 * This program is free software; you can redistribute it and/or 23 * modify it under the terms of the GNU General Public License 24 * as published by the Free Software Foundation; either version 25 * 2 of the License, or (at your option) any later version. 26 */ 27 /* 28 * The following macros define the code that appears as 29 * the prologue to each of the exception handlers. They 30 * are split into two parts to allow a single kernel binary 31 * to be used for pSeries and iSeries. 32 * 33 * We make as much of the exception code common between native 34 * exception handlers (including pSeries LPAR) and iSeries LPAR 35 * implementations as possible. 36 */ 37 38 #define EX_R9 0 39 #define EX_R10 8 40 #define EX_R11 16 41 #define EX_R12 24 42 #define EX_R13 32 43 #define EX_SRR0 40 44 #define EX_DAR 48 45 #define EX_DSISR 56 46 #define EX_CCR 60 47 #define EX_R3 64 48 #define EX_LR 72 49 50 /* 51 * We're short on space and time in the exception prolog, so we can't 52 * use the normal SET_REG_IMMEDIATE macro. Normally we just need the 53 * low halfword of the address, but for Kdump we need the whole low 54 * word. 55 */ 56 #define LOAD_HANDLER(reg, label) \ 57 addi reg,reg,(label)-_stext; /* virt addr of handler ... */ 58 59 #define EXCEPTION_PROLOG_1(area) \ 60 mfspr r13,SPRN_SPRG3; /* get paca address into r13 */ \ 61 std r9,area+EX_R9(r13); /* save r9 - r12 */ \ 62 std r10,area+EX_R10(r13); \ 63 std r11,area+EX_R11(r13); \ 64 std r12,area+EX_R12(r13); \ 65 mfspr r9,SPRN_SPRG1; \ 66 std r9,area+EX_R13(r13); \ 67 mfcr r9 68 69 #define EXCEPTION_PROLOG_PSERIES(area, label) \ 70 EXCEPTION_PROLOG_1(area); \ 71 ld r12,PACAKBASE(r13); /* get high part of &label */ \ 72 ld r10,PACAKMSR(r13); /* get MSR value for kernel */ \ 73 mfspr r11,SPRN_SRR0; /* save SRR0 */ \ 74 LOAD_HANDLER(r12,label) \ 75 mtspr SPRN_SRR0,r12; \ 76 mfspr r12,SPRN_SRR1; /* and SRR1 */ \ 77 mtspr SPRN_SRR1,r10; \ 78 rfid; \ 79 b . /* prevent speculative execution */ 80 81 /* 82 * The common exception prolog is used for all except a few exceptions 83 * such as a segment miss on a kernel address. We have to be prepared 84 * to take another exception from the point where we first touch the 85 * kernel stack onwards. 86 * 87 * On entry r13 points to the paca, r9-r13 are saved in the paca, 88 * r9 contains the saved CR, r11 and r12 contain the saved SRR0 and 89 * SRR1, and relocation is on. 90 */ 91 #define EXCEPTION_PROLOG_COMMON(n, area) \ 92 andi. r10,r12,MSR_PR; /* See if coming from user */ \ 93 mr r10,r1; /* Save r1 */ \ 94 subi r1,r1,INT_FRAME_SIZE; /* alloc frame on kernel stack */ \ 95 beq- 1f; \ 96 ld r1,PACAKSAVE(r13); /* kernel stack to use */ \ 97 1: cmpdi cr1,r1,0; /* check if r1 is in userspace */ \ 98 bge- cr1,2f; /* abort if it is */ \ 99 b 3f; \ 100 2: li r1,(n); /* will be reloaded later */ \ 101 sth r1,PACA_TRAP_SAVE(r13); \ 102 b bad_stack; \ 103 3: std r9,_CCR(r1); /* save CR in stackframe */ \ 104 std r11,_NIP(r1); /* save SRR0 in stackframe */ \ 105 std r12,_MSR(r1); /* save SRR1 in stackframe */ \ 106 std r10,0(r1); /* make stack chain pointer */ \ 107 std r0,GPR0(r1); /* save r0 in stackframe */ \ 108 std r10,GPR1(r1); /* save r1 in stackframe */ \ 109 ACCOUNT_CPU_USER_ENTRY(r9, r10); \ 110 std r2,GPR2(r1); /* save r2 in stackframe */ \ 111 SAVE_4GPRS(3, r1); /* save r3 - r6 in stackframe */ \ 112 SAVE_2GPRS(7, r1); /* save r7, r8 in stackframe */ \ 113 ld r9,area+EX_R9(r13); /* move r9, r10 to stackframe */ \ 114 ld r10,area+EX_R10(r13); \ 115 std r9,GPR9(r1); \ 116 std r10,GPR10(r1); \ 117 ld r9,area+EX_R11(r13); /* move r11 - r13 to stackframe */ \ 118 ld r10,area+EX_R12(r13); \ 119 ld r11,area+EX_R13(r13); \ 120 std r9,GPR11(r1); \ 121 std r10,GPR12(r1); \ 122 std r11,GPR13(r1); \ 123 ld r2,PACATOC(r13); /* get kernel TOC into r2 */ \ 124 mflr r9; /* save LR in stackframe */ \ 125 std r9,_LINK(r1); \ 126 mfctr r10; /* save CTR in stackframe */ \ 127 std r10,_CTR(r1); \ 128 lbz r10,PACASOFTIRQEN(r13); \ 129 mfspr r11,SPRN_XER; /* save XER in stackframe */ \ 130 std r10,SOFTE(r1); \ 131 std r11,_XER(r1); \ 132 li r9,(n)+1; \ 133 std r9,_TRAP(r1); /* set trap number */ \ 134 li r10,0; \ 135 ld r11,exception_marker@toc(r2); \ 136 std r10,RESULT(r1); /* clear regs->result */ \ 137 std r11,STACK_FRAME_OVERHEAD-16(r1); /* mark the frame */ 138 139 /* 140 * Exception vectors. 141 */ 142 #define STD_EXCEPTION_PSERIES(n, label) \ 143 . = n; \ 144 .globl label##_pSeries; \ 145 label##_pSeries: \ 146 HMT_MEDIUM; \ 147 mtspr SPRN_SPRG1,r13; /* save r13 */ \ 148 EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common) 149 150 #define HSTD_EXCEPTION_PSERIES(n, label) \ 151 . = n; \ 152 .globl label##_pSeries; \ 153 label##_pSeries: \ 154 HMT_MEDIUM; \ 155 mtspr SPRN_SPRG1,r20; /* save r20 */ \ 156 mfspr r20,SPRN_HSRR0; /* copy HSRR0 to SRR0 */ \ 157 mtspr SPRN_SRR0,r20; \ 158 mfspr r20,SPRN_HSRR1; /* copy HSRR0 to SRR0 */ \ 159 mtspr SPRN_SRR1,r20; \ 160 mfspr r20,SPRN_SPRG1; /* restore r20 */ \ 161 mtspr SPRN_SPRG1,r13; /* save r13 */ \ 162 EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common) 163 164 165 #define MASKABLE_EXCEPTION_PSERIES(n, label) \ 166 . = n; \ 167 .globl label##_pSeries; \ 168 label##_pSeries: \ 169 HMT_MEDIUM; \ 170 mtspr SPRN_SPRG1,r13; /* save r13 */ \ 171 mfspr r13,SPRN_SPRG3; /* get paca address into r13 */ \ 172 std r9,PACA_EXGEN+EX_R9(r13); /* save r9, r10 */ \ 173 std r10,PACA_EXGEN+EX_R10(r13); \ 174 lbz r10,PACASOFTIRQEN(r13); \ 175 mfcr r9; \ 176 cmpwi r10,0; \ 177 beq masked_interrupt; \ 178 mfspr r10,SPRN_SPRG1; \ 179 std r10,PACA_EXGEN+EX_R13(r13); \ 180 std r11,PACA_EXGEN+EX_R11(r13); \ 181 std r12,PACA_EXGEN+EX_R12(r13); \ 182 ld r12,PACAKBASE(r13); /* get high part of &label */ \ 183 ld r10,PACAKMSR(r13); /* get MSR value for kernel */ \ 184 mfspr r11,SPRN_SRR0; /* save SRR0 */ \ 185 LOAD_HANDLER(r12,label##_common) \ 186 mtspr SPRN_SRR0,r12; \ 187 mfspr r12,SPRN_SRR1; /* and SRR1 */ \ 188 mtspr SPRN_SRR1,r10; \ 189 rfid; \ 190 b . /* prevent speculative execution */ 191 192 #ifdef CONFIG_PPC_ISERIES 193 #define DISABLE_INTS \ 194 li r11,0; \ 195 stb r11,PACASOFTIRQEN(r13); \ 196 BEGIN_FW_FTR_SECTION; \ 197 stb r11,PACAHARDIRQEN(r13); \ 198 END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES); \ 199 TRACE_DISABLE_INTS; \ 200 BEGIN_FW_FTR_SECTION; \ 201 mfmsr r10; \ 202 ori r10,r10,MSR_EE; \ 203 mtmsrd r10,1; \ 204 END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES) 205 #else 206 #define DISABLE_INTS \ 207 li r11,0; \ 208 stb r11,PACASOFTIRQEN(r13); \ 209 stb r11,PACAHARDIRQEN(r13); \ 210 TRACE_DISABLE_INTS 211 #endif /* CONFIG_PPC_ISERIES */ 212 213 #define ENABLE_INTS \ 214 ld r12,_MSR(r1); \ 215 mfmsr r11; \ 216 rlwimi r11,r12,0,MSR_EE; \ 217 mtmsrd r11,1 218 219 #define STD_EXCEPTION_COMMON(trap, label, hdlr) \ 220 .align 7; \ 221 .globl label##_common; \ 222 label##_common: \ 223 EXCEPTION_PROLOG_COMMON(trap, PACA_EXGEN); \ 224 DISABLE_INTS; \ 225 bl .save_nvgprs; \ 226 addi r3,r1,STACK_FRAME_OVERHEAD; \ 227 bl hdlr; \ 228 b .ret_from_except 229 230 /* 231 * Like STD_EXCEPTION_COMMON, but for exceptions that can occur 232 * in the idle task and therefore need the special idle handling. 233 */ 234 #define STD_EXCEPTION_COMMON_IDLE(trap, label, hdlr) \ 235 .align 7; \ 236 .globl label##_common; \ 237 label##_common: \ 238 EXCEPTION_PROLOG_COMMON(trap, PACA_EXGEN); \ 239 FINISH_NAP; \ 240 DISABLE_INTS; \ 241 bl .save_nvgprs; \ 242 addi r3,r1,STACK_FRAME_OVERHEAD; \ 243 bl hdlr; \ 244 b .ret_from_except 245 246 #define STD_EXCEPTION_COMMON_LITE(trap, label, hdlr) \ 247 .align 7; \ 248 .globl label##_common; \ 249 label##_common: \ 250 EXCEPTION_PROLOG_COMMON(trap, PACA_EXGEN); \ 251 FINISH_NAP; \ 252 DISABLE_INTS; \ 253 BEGIN_FTR_SECTION \ 254 bl .ppc64_runlatch_on; \ 255 END_FTR_SECTION_IFSET(CPU_FTR_CTRL) \ 256 addi r3,r1,STACK_FRAME_OVERHEAD; \ 257 bl hdlr; \ 258 b .ret_from_except_lite 259 260 /* 261 * When the idle code in power4_idle puts the CPU into NAP mode, 262 * it has to do so in a loop, and relies on the external interrupt 263 * and decrementer interrupt entry code to get it out of the loop. 264 * It sets the _TLF_NAPPING bit in current_thread_info()->local_flags 265 * to signal that it is in the loop and needs help to get out. 266 */ 267 #ifdef CONFIG_PPC_970_NAP 268 #define FINISH_NAP \ 269 BEGIN_FTR_SECTION \ 270 clrrdi r11,r1,THREAD_SHIFT; \ 271 ld r9,TI_LOCAL_FLAGS(r11); \ 272 andi. r10,r9,_TLF_NAPPING; \ 273 bnel power4_fixup_nap; \ 274 END_FTR_SECTION_IFSET(CPU_FTR_CAN_NAP) 275 #else 276 #define FINISH_NAP 277 #endif 278 279 #endif /* _ASM_POWERPC_EXCEPTION_H */ 280