1/*- 2 * Copyright (C) 2006-2009 Semihalf, Rafal Jaworowski <raj@semihalf.com> 3 * Copyright (C) 2006 Semihalf, Marian Balakowicz <m8@semihalf.com> 4 * Copyright (C) 2006 Juniper Networks, Inc. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. The name of the author may not be used to endorse or promote products 16 * derived from this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN 21 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 23 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 24 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 25 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 26 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 * 29 * $FreeBSD$ 30 */ 31/*- 32 * Copyright (C) 1995, 1996 Wolfgang Solfrank. 33 * Copyright (C) 1995, 1996 TooLs GmbH. 34 * All rights reserved. 35 * 36 * Redistribution and use in source and binary forms, with or without 37 * modification, are permitted provided that the following conditions 38 * are met: 39 * 1. Redistributions of source code must retain the above copyright 40 * notice, this list of conditions and the following disclaimer. 41 * 2. Redistributions in binary form must reproduce the above copyright 42 * notice, this list of conditions and the following disclaimer in the 43 * documentation and/or other materials provided with the distribution. 44 * 3. All advertising materials mentioning features or use of this software 45 * must display the following acknowledgement: 46 * This product includes software developed by TooLs GmbH. 47 * 4. The name of TooLs GmbH may not be used to endorse or promote products 48 * derived from this software without specific prior written permission. 49 * 50 * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR 51 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 52 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 53 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 54 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 55 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 56 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 57 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 58 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 59 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 60 * 61 * from: $NetBSD: trap_subr.S,v 1.20 2002/04/22 23:20:08 kleink Exp $ 62 */ 63 64/* 65 * NOTICE: This is not a standalone file. to use it, #include it in 66 * your port's locore.S, like so: 67 * 68 * #include <powerpc/booke/trap_subr.S> 69 */ 70 71/* 72 * SPRG usage notes 73 * 74 * SPRG0 - pcpu pointer 75 * SPRG1 - all interrupts except TLB miss, critical, machine check 76 * SPRG2 - critical 77 * SPRG3 - machine check 78 * SPRG4-6 - scratch 79 * 80 */ 81 82/* Get the per-CPU data structure */ 83#define GET_CPUINFO(r) mfsprg0 r 84 85#define RES_GRANULE 64 86#define RES_LOCK 0 /* offset to the 'lock' word */ 87#ifdef __powerpc64__ 88#define RES_RECURSE 8 /* offset to the 'recurse' word */ 89#else 90#define RES_RECURSE 4 /* offset to the 'recurse' word */ 91#endif 92 93/* 94 * Standard interrupt prolog 95 * 96 * sprg_sp - SPRG{1-3} reg used to temporarily store the SP 97 * savearea - temp save area (pc_{tempsave, disisave, critsave, mchksave}) 98 * isrr0-1 - save restore registers with CPU state at interrupt time (may be 99 * SRR0-1, CSRR0-1, MCSRR0-1 100 * 101 * 1. saves in the given savearea: 102 * - R30-31 103 * - DEAR, ESR 104 * - xSRR0-1 105 * 106 * 2. saves CR -> R30 107 * 108 * 3. switches to kstack if needed 109 * 110 * 4. notes: 111 * - R31 can be used as scratch register until a new frame is laid on 112 * the stack with FRAME_SETUP 113 * 114 * - potential TLB miss: NO. Saveareas are always acessible via TLB1 115 * permanent entries, and within this prolog we do not dereference any 116 * locations potentially not in the TLB 117 */ 118#define STANDARD_PROLOG(sprg_sp, savearea, isrr0, isrr1) \ 119 mtspr sprg_sp, %r1; /* Save SP */ \ 120 GET_CPUINFO(%r1); /* Per-cpu structure */ \ 121 STORE %r30, (savearea+CPUSAVE_R30)(%r1); \ 122 STORE %r31, (savearea+CPUSAVE_R31)(%r1); \ 123 mfspr %r30, SPR_DEAR; \ 124 mfspr %r31, SPR_ESR; \ 125 STORE %r30, (savearea+CPUSAVE_BOOKE_DEAR)(%r1); \ 126 STORE %r31, (savearea+CPUSAVE_BOOKE_ESR)(%r1); \ 127 mfspr %r30, isrr0; \ 128 mfspr %r31, isrr1; /* MSR at interrupt time */ \ 129 STORE %r30, (savearea+CPUSAVE_SRR0)(%r1); \ 130 STORE %r31, (savearea+CPUSAVE_SRR1)(%r1); \ 131 isync; \ 132 mfspr %r1, sprg_sp; /* Restore SP */ \ 133 mfcr %r30; /* Save CR */ \ 134 /* switch to per-thread kstack if intr taken in user mode */ \ 135 mtcr %r31; /* MSR at interrupt time */ \ 136 bf 17, 1f; \ 137 GET_CPUINFO(%r1); /* Per-cpu structure */ \ 138 LOAD %r1, PC_CURPCB(%r1); /* Per-thread kernel stack */ \ 1391: 140 141#define STANDARD_CRIT_PROLOG(sprg_sp, savearea, isrr0, isrr1) \ 142 mtspr sprg_sp, %r1; /* Save SP */ \ 143 GET_CPUINFO(%r1); /* Per-cpu structure */ \ 144 STORE %r30, (savearea+CPUSAVE_R30)(%r1); \ 145 STORE %r31, (savearea+CPUSAVE_R31)(%r1); \ 146 mfspr %r30, SPR_DEAR; \ 147 mfspr %r31, SPR_ESR; \ 148 STORE %r30, (savearea+CPUSAVE_BOOKE_DEAR)(%r1); \ 149 STORE %r31, (savearea+CPUSAVE_BOOKE_ESR)(%r1); \ 150 mfspr %r30, isrr0; \ 151 mfspr %r31, isrr1; /* MSR at interrupt time */ \ 152 STORE %r30, (savearea+CPUSAVE_SRR0)(%r1); \ 153 STORE %r31, (savearea+CPUSAVE_SRR1)(%r1); \ 154 mfspr %r30, SPR_SRR0; \ 155 mfspr %r31, SPR_SRR1; /* MSR at interrupt time */ \ 156 STORE %r30, (savearea+BOOKE_CRITSAVE_SRR0)(%r1); \ 157 STORE %r31, (savearea+BOOKE_CRITSAVE_SRR1)(%r1); \ 158 isync; \ 159 mfspr %r1, sprg_sp; /* Restore SP */ \ 160 mfcr %r30; /* Save CR */ \ 161 /* switch to per-thread kstack if intr taken in user mode */ \ 162 mtcr %r31; /* MSR at interrupt time */ \ 163 bf 17, 1f; \ 164 GET_CPUINFO(%r1); /* Per-cpu structure */ \ 165 LOAD %r1, PC_CURPCB(%r1); /* Per-thread kernel stack */ \ 1661: 167 168/* 169 * FRAME_SETUP assumes: 170 * SPRG{1-3} SP at the time interrupt occurred 171 * savearea r30-r31, DEAR, ESR, xSRR0-1 172 * r30 CR 173 * r31 scratch 174 * r1 kernel stack 175 * 176 * sprg_sp - SPRG reg containing SP at the time interrupt occurred 177 * savearea - temp save 178 * exc - exception number (EXC_xxx) 179 * 180 * 1. sets a new frame 181 * 2. saves in the frame: 182 * - R0, R1 (SP at the time of interrupt), R2, LR, CR 183 * - R3-31 (R30-31 first restored from savearea) 184 * - XER, CTR, DEAR, ESR (from savearea), xSRR0-1 185 * 186 * Notes: 187 * - potential TLB miss: YES, since we make dereferences to kstack, which 188 * can happen not covered (we can have up to two DTLB misses if fortunate 189 * enough i.e. when kstack crosses page boundary and both pages are 190 * untranslated) 191 */ 192#ifdef __powerpc64__ 193#define SAVE_REGS(r) \ 194 std %r3, FRAME_3+CALLSIZE(r); \ 195 std %r4, FRAME_4+CALLSIZE(r); \ 196 std %r5, FRAME_5+CALLSIZE(r); \ 197 std %r6, FRAME_6+CALLSIZE(r); \ 198 std %r7, FRAME_7+CALLSIZE(r); \ 199 std %r8, FRAME_8+CALLSIZE(r); \ 200 std %r9, FRAME_9+CALLSIZE(r); \ 201 std %r10, FRAME_10+CALLSIZE(r); \ 202 std %r11, FRAME_11+CALLSIZE(r); \ 203 std %r12, FRAME_12+CALLSIZE(r); \ 204 std %r13, FRAME_13+CALLSIZE(r); \ 205 std %r14, FRAME_14+CALLSIZE(r); \ 206 std %r15, FRAME_15+CALLSIZE(r); \ 207 std %r16, FRAME_16+CALLSIZE(r); \ 208 std %r17, FRAME_17+CALLSIZE(r); \ 209 std %r18, FRAME_18+CALLSIZE(r); \ 210 std %r19, FRAME_19+CALLSIZE(r); \ 211 std %r20, FRAME_20+CALLSIZE(r); \ 212 std %r21, FRAME_21+CALLSIZE(r); \ 213 std %r22, FRAME_22+CALLSIZE(r); \ 214 std %r23, FRAME_23+CALLSIZE(r); \ 215 std %r24, FRAME_24+CALLSIZE(r); \ 216 std %r25, FRAME_25+CALLSIZE(r); \ 217 std %r26, FRAME_26+CALLSIZE(r); \ 218 std %r27, FRAME_27+CALLSIZE(r); \ 219 std %r28, FRAME_28+CALLSIZE(r); \ 220 std %r29, FRAME_29+CALLSIZE(r); \ 221 std %r30, FRAME_30+CALLSIZE(r); \ 222 std %r31, FRAME_31+CALLSIZE(r) 223#define LD_REGS(r) \ 224 ld %r3, FRAME_3+CALLSIZE(r); \ 225 ld %r4, FRAME_4+CALLSIZE(r); \ 226 ld %r5, FRAME_5+CALLSIZE(r); \ 227 ld %r6, FRAME_6+CALLSIZE(r); \ 228 ld %r7, FRAME_7+CALLSIZE(r); \ 229 ld %r8, FRAME_8+CALLSIZE(r); \ 230 ld %r9, FRAME_9+CALLSIZE(r); \ 231 ld %r10, FRAME_10+CALLSIZE(r); \ 232 ld %r11, FRAME_11+CALLSIZE(r); \ 233 ld %r12, FRAME_12+CALLSIZE(r); \ 234 ld %r13, FRAME_13+CALLSIZE(r); \ 235 ld %r14, FRAME_14+CALLSIZE(r); \ 236 ld %r15, FRAME_15+CALLSIZE(r); \ 237 ld %r16, FRAME_16+CALLSIZE(r); \ 238 ld %r17, FRAME_17+CALLSIZE(r); \ 239 ld %r18, FRAME_18+CALLSIZE(r); \ 240 ld %r19, FRAME_19+CALLSIZE(r); \ 241 ld %r20, FRAME_20+CALLSIZE(r); \ 242 ld %r21, FRAME_21+CALLSIZE(r); \ 243 ld %r22, FRAME_22+CALLSIZE(r); \ 244 ld %r23, FRAME_23+CALLSIZE(r); \ 245 ld %r24, FRAME_24+CALLSIZE(r); \ 246 ld %r25, FRAME_25+CALLSIZE(r); \ 247 ld %r26, FRAME_26+CALLSIZE(r); \ 248 ld %r27, FRAME_27+CALLSIZE(r); \ 249 ld %r28, FRAME_28+CALLSIZE(r); \ 250 ld %r29, FRAME_29+CALLSIZE(r); \ 251 ld %r30, FRAME_30+CALLSIZE(r); \ 252 ld %r31, FRAME_31+CALLSIZE(r) 253#else 254#define SAVE_REGS(r) \ 255 stmw %r3, FRAME_3+CALLSIZE(r) 256#define LD_REGS(r) \ 257 lmw %r3, FRAME_3+CALLSIZE(r) 258#endif 259#define FRAME_SETUP(sprg_sp, savearea, exc) \ 260 mfspr %r31, sprg_sp; /* get saved SP */ \ 261 /* establish a new stack frame and put everything on it */ \ 262 STU %r31, -(FRAMELEN+REDZONE)(%r1); \ 263 STORE %r0, FRAME_0+CALLSIZE(%r1); /* save r0 in the trapframe */ \ 264 STORE %r31, FRAME_1+CALLSIZE(%r1); /* save SP " " */ \ 265 STORE %r2, FRAME_2+CALLSIZE(%r1); /* save r2 " " */ \ 266 mflr %r31; \ 267 STORE %r31, FRAME_LR+CALLSIZE(%r1); /* save LR " " */ \ 268 STORE %r30, FRAME_CR+CALLSIZE(%r1); /* save CR " " */ \ 269 GET_CPUINFO(%r2); \ 270 LOAD %r30, (savearea+CPUSAVE_R30)(%r2); /* get saved r30 */ \ 271 LOAD %r31, (savearea+CPUSAVE_R31)(%r2); /* get saved r31 */ \ 272 /* save R3-31 */ \ 273 SAVE_REGS(%r1); \ 274 /* save DEAR, ESR */ \ 275 LOAD %r28, (savearea+CPUSAVE_BOOKE_DEAR)(%r2); \ 276 LOAD %r29, (savearea+CPUSAVE_BOOKE_ESR)(%r2); \ 277 STORE %r28, FRAME_BOOKE_DEAR+CALLSIZE(%r1); \ 278 STORE %r29, FRAME_BOOKE_ESR+CALLSIZE(%r1); \ 279 /* save XER, CTR, exc number */ \ 280 mfxer %r3; \ 281 mfctr %r4; \ 282 STORE %r3, FRAME_XER+CALLSIZE(%r1); \ 283 STORE %r4, FRAME_CTR+CALLSIZE(%r1); \ 284 li %r5, exc; \ 285 STORE %r5, FRAME_EXC+CALLSIZE(%r1); \ 286 /* save DBCR0 */ \ 287 mfspr %r3, SPR_DBCR0; \ 288 STORE %r3, FRAME_BOOKE_DBCR0+CALLSIZE(%r1); \ 289 /* save xSSR0-1 */ \ 290 LOAD %r30, (savearea+CPUSAVE_SRR0)(%r2); \ 291 LOAD %r31, (savearea+CPUSAVE_SRR1)(%r2); \ 292 STORE %r30, FRAME_SRR0+CALLSIZE(%r1); \ 293 STORE %r31, FRAME_SRR1+CALLSIZE(%r1); \ 294 LOAD THREAD_REG, PC_CURTHREAD(%r2); \ 295 296/* 297 * 298 * isrr0-1 - save restore registers to restore CPU state to (may be 299 * SRR0-1, CSRR0-1, MCSRR0-1 300 * 301 * Notes: 302 * - potential TLB miss: YES. The deref'd kstack may be not covered 303 */ 304#define FRAME_LEAVE(isrr0, isrr1) \ 305 wrteei 0; \ 306 /* restore CTR, XER, LR, CR */ \ 307 LOAD %r4, FRAME_CTR+CALLSIZE(%r1); \ 308 LOAD %r5, FRAME_XER+CALLSIZE(%r1); \ 309 LOAD %r6, FRAME_LR+CALLSIZE(%r1); \ 310 LOAD %r7, FRAME_CR+CALLSIZE(%r1); \ 311 mtctr %r4; \ 312 mtxer %r5; \ 313 mtlr %r6; \ 314 mtcr %r7; \ 315 /* restore DBCR0 */ \ 316 LOAD %r4, FRAME_BOOKE_DBCR0+CALLSIZE(%r1); \ 317 mtspr SPR_DBCR0, %r4; \ 318 /* restore xSRR0-1 */ \ 319 LOAD %r30, FRAME_SRR0+CALLSIZE(%r1); \ 320 LOAD %r31, FRAME_SRR1+CALLSIZE(%r1); \ 321 mtspr isrr0, %r30; \ 322 mtspr isrr1, %r31; \ 323 /* restore R2-31, SP */ \ 324 LD_REGS(%r1); \ 325 LOAD %r2, FRAME_2+CALLSIZE(%r1); \ 326 LOAD %r0, FRAME_0+CALLSIZE(%r1); \ 327 LOAD %r1, FRAME_1+CALLSIZE(%r1); \ 328 isync 329 330/* 331 * TLB miss prolog 332 * 333 * saves LR, CR, SRR0-1, R20-31 in the TLBSAVE area 334 * 335 * Notes: 336 * - potential TLB miss: NO. It is crucial that we do not generate a TLB 337 * miss within the TLB prolog itself! 338 * - TLBSAVE is always translated 339 */ 340#ifdef __powerpc64__ 341#define TLB_SAVE_REGS(br) \ 342 std %r20, (TLBSAVE_BOOKE_R20)(br); \ 343 std %r21, (TLBSAVE_BOOKE_R21)(br); \ 344 std %r22, (TLBSAVE_BOOKE_R22)(br); \ 345 std %r23, (TLBSAVE_BOOKE_R23)(br); \ 346 std %r24, (TLBSAVE_BOOKE_R24)(br); \ 347 std %r25, (TLBSAVE_BOOKE_R25)(br); \ 348 std %r26, (TLBSAVE_BOOKE_R26)(br); \ 349 std %r27, (TLBSAVE_BOOKE_R27)(br); \ 350 std %r28, (TLBSAVE_BOOKE_R28)(br); \ 351 std %r29, (TLBSAVE_BOOKE_R29)(br); \ 352 std %r30, (TLBSAVE_BOOKE_R30)(br); \ 353 std %r31, (TLBSAVE_BOOKE_R31)(br); 354#define TLB_RESTORE_REGS(br) \ 355 ld %r20, (TLBSAVE_BOOKE_R20)(br); \ 356 ld %r21, (TLBSAVE_BOOKE_R21)(br); \ 357 ld %r22, (TLBSAVE_BOOKE_R22)(br); \ 358 ld %r23, (TLBSAVE_BOOKE_R23)(br); \ 359 ld %r24, (TLBSAVE_BOOKE_R24)(br); \ 360 ld %r25, (TLBSAVE_BOOKE_R25)(br); \ 361 ld %r26, (TLBSAVE_BOOKE_R26)(br); \ 362 ld %r27, (TLBSAVE_BOOKE_R27)(br); \ 363 ld %r28, (TLBSAVE_BOOKE_R28)(br); \ 364 ld %r29, (TLBSAVE_BOOKE_R29)(br); \ 365 ld %r30, (TLBSAVE_BOOKE_R30)(br); \ 366 ld %r31, (TLBSAVE_BOOKE_R31)(br); 367#define TLB_NEST(outr,inr) \ 368 rlwinm outr, inr, 7, 23, 24; /* 8 x TLBSAVE_LEN */ 369#else 370#define TLB_SAVE_REGS(br) \ 371 stmw %r20, TLBSAVE_BOOKE_R20(br) 372#define TLB_RESTORE_REGS(br) \ 373 lmw %r20, TLBSAVE_BOOKE_R20(br) 374#define TLB_NEST(outr,inr) \ 375 rlwinm outr, inr, 6, 24, 25; /* 4 x TLBSAVE_LEN */ 376#endif 377#define TLB_PROLOG \ 378 mtspr SPR_SPRG4, %r1; /* Save SP */ \ 379 mtspr SPR_SPRG5, %r28; \ 380 mtspr SPR_SPRG6, %r29; \ 381 /* calculate TLB nesting level and TLBSAVE instance address */ \ 382 GET_CPUINFO(%r1); /* Per-cpu structure */ \ 383 LOAD %r28, PC_BOOKE_TLB_LEVEL(%r1); \ 384 TLB_NEST(%r29,%r28); \ 385 addi %r28, %r28, 1; \ 386 STORE %r28, PC_BOOKE_TLB_LEVEL(%r1); \ 387 addi %r29, %r29, PC_BOOKE_TLBSAVE@l; \ 388 add %r1, %r1, %r29; /* current TLBSAVE ptr */ \ 389 \ 390 /* save R20-31 */ \ 391 mfspr %r28, SPR_SPRG5; \ 392 mfspr %r29, SPR_SPRG6; \ 393 TLB_SAVE_REGS(%r1); \ 394 /* save LR, CR */ \ 395 mflr %r30; \ 396 mfcr %r31; \ 397 STORE %r30, (TLBSAVE_BOOKE_LR)(%r1); \ 398 STORE %r31, (TLBSAVE_BOOKE_CR)(%r1); \ 399 /* save SRR0-1 */ \ 400 mfsrr0 %r30; /* execution addr at interrupt time */ \ 401 mfsrr1 %r31; /* MSR at interrupt time*/ \ 402 STORE %r30, (TLBSAVE_BOOKE_SRR0)(%r1); /* save SRR0 */ \ 403 STORE %r31, (TLBSAVE_BOOKE_SRR1)(%r1); /* save SRR1 */ \ 404 isync; \ 405 mfspr %r1, SPR_SPRG4 406 407/* 408 * restores LR, CR, SRR0-1, R20-31 from the TLBSAVE area 409 * 410 * same notes as for the TLB_PROLOG 411 */ 412#define TLB_RESTORE \ 413 mtspr SPR_SPRG4, %r1; /* Save SP */ \ 414 GET_CPUINFO(%r1); /* Per-cpu structure */ \ 415 /* calculate TLB nesting level and TLBSAVE instance addr */ \ 416 LOAD %r28, PC_BOOKE_TLB_LEVEL(%r1); \ 417 subi %r28, %r28, 1; \ 418 STORE %r28, PC_BOOKE_TLB_LEVEL(%r1); \ 419 TLB_NEST(%r29,%r28); \ 420 addi %r29, %r29, PC_BOOKE_TLBSAVE@l; \ 421 add %r1, %r1, %r29; \ 422 \ 423 /* restore LR, CR */ \ 424 LOAD %r30, (TLBSAVE_BOOKE_LR)(%r1); \ 425 LOAD %r31, (TLBSAVE_BOOKE_CR)(%r1); \ 426 mtlr %r30; \ 427 mtcr %r31; \ 428 /* restore SRR0-1 */ \ 429 LOAD %r30, (TLBSAVE_BOOKE_SRR0)(%r1); \ 430 LOAD %r31, (TLBSAVE_BOOKE_SRR1)(%r1); \ 431 mtsrr0 %r30; \ 432 mtsrr1 %r31; \ 433 /* restore R20-31 */ \ 434 TLB_RESTORE_REGS(%r1); \ 435 mfspr %r1, SPR_SPRG4 436 437#ifdef SMP 438#define TLB_LOCK \ 439 GET_CPUINFO(%r20); \ 440 LOAD %r21, PC_CURTHREAD(%r20); \ 441 LOAD %r22, PC_BOOKE_TLB_LOCK(%r20); \ 442 \ 4431: LOADX %r23, 0, %r22; \ 444 CMPI %r23, TLB_UNLOCKED; \ 445 beq 2f; \ 446 \ 447 /* check if this is recursion */ \ 448 CMPL cr0, %r21, %r23; \ 449 bne- 1b; \ 450 \ 4512: /* try to acquire lock */ \ 452 STOREX %r21, 0, %r22; \ 453 bne- 1b; \ 454 \ 455 /* got it, update recursion counter */ \ 456 lwz %r21, RES_RECURSE(%r22); \ 457 addi %r21, %r21, 1; \ 458 stw %r21, RES_RECURSE(%r22); \ 459 isync; \ 460 msync 461 462#define TLB_UNLOCK \ 463 GET_CPUINFO(%r20); \ 464 LOAD %r21, PC_CURTHREAD(%r20); \ 465 LOAD %r22, PC_BOOKE_TLB_LOCK(%r20); \ 466 \ 467 /* update recursion counter */ \ 468 lwz %r23, RES_RECURSE(%r22); \ 469 subi %r23, %r23, 1; \ 470 stw %r23, RES_RECURSE(%r22); \ 471 \ 472 cmplwi %r23, 0; \ 473 bne 1f; \ 474 isync; \ 475 msync; \ 476 \ 477 /* release the lock */ \ 478 li %r23, TLB_UNLOCKED; \ 479 STORE %r23, 0(%r22); \ 4801: isync; \ 481 msync 482#else 483#define TLB_LOCK 484#define TLB_UNLOCK 485#endif /* SMP */ 486 487#define INTERRUPT(label) \ 488 .globl label; \ 489 .align 5; \ 490 CNAME(label): 491 492/* 493 * Interrupt handling routines in BookE can be flexibly placed and do not have 494 * to live in pre-defined vectors location. Note they need to be TLB-mapped at 495 * all times in order to be able to handle exceptions. We thus arrange for 496 * them to be part of kernel text which is always TLB-accessible. 497 * 498 * The interrupt handling routines have to be 16 bytes aligned: we align them 499 * to 32 bytes (cache line length) which supposedly performs better. 500 * 501 */ 502 .text 503 .globl CNAME(interrupt_vector_base) 504 .align 5 505interrupt_vector_base: 506/***************************************************************************** 507 * Catch-all handler to handle uninstalled IVORs 508 ****************************************************************************/ 509INTERRUPT(int_unknown) 510 STANDARD_PROLOG(SPR_SPRG1, PC_TEMPSAVE, SPR_SRR0, SPR_SRR1) 511 FRAME_SETUP(SPR_SPRG1, PC_TEMPSAVE, EXC_RSVD) 512 b trap_common 513 514/***************************************************************************** 515 * Critical input interrupt 516 ****************************************************************************/ 517INTERRUPT(int_critical_input) 518 STANDARD_CRIT_PROLOG(SPR_SPRG2, PC_BOOKE_CRITSAVE, SPR_CSRR0, SPR_CSRR1) 519 FRAME_SETUP(SPR_SPRG2, PC_BOOKE_CRITSAVE, EXC_CRIT) 520 GET_TOCBASE(%r2) 521 addi %r3, %r1, CALLSIZE 522 bl CNAME(powerpc_interrupt) 523 TOC_RESTORE 524 FRAME_LEAVE(SPR_CSRR0, SPR_CSRR1) 525 rfci 526 527 528/***************************************************************************** 529 * Machine check interrupt 530 ****************************************************************************/ 531INTERRUPT(int_machine_check) 532 STANDARD_PROLOG(SPR_SPRG3, PC_BOOKE_MCHKSAVE, SPR_MCSRR0, SPR_MCSRR1) 533 FRAME_SETUP(SPR_SPRG3, PC_BOOKE_MCHKSAVE, EXC_MCHK) 534 GET_TOCBASE(%r2) 535 addi %r3, %r1, CALLSIZE 536 bl CNAME(powerpc_interrupt) 537 TOC_RESTORE 538 FRAME_LEAVE(SPR_MCSRR0, SPR_MCSRR1) 539 rfmci 540 541 542/***************************************************************************** 543 * Data storage interrupt 544 ****************************************************************************/ 545INTERRUPT(int_data_storage) 546 STANDARD_PROLOG(SPR_SPRG1, PC_DISISAVE, SPR_SRR0, SPR_SRR1) 547 FRAME_SETUP(SPR_SPRG1, PC_DISISAVE, EXC_DSI) 548 b trap_common 549 550 551/***************************************************************************** 552 * Instruction storage interrupt 553 ****************************************************************************/ 554INTERRUPT(int_instr_storage) 555 STANDARD_PROLOG(SPR_SPRG1, PC_TEMPSAVE, SPR_SRR0, SPR_SRR1) 556 FRAME_SETUP(SPR_SPRG1, PC_TEMPSAVE, EXC_ISI) 557 b trap_common 558 559 560/***************************************************************************** 561 * External input interrupt 562 ****************************************************************************/ 563INTERRUPT(int_external_input) 564 STANDARD_PROLOG(SPR_SPRG1, PC_TEMPSAVE, SPR_SRR0, SPR_SRR1) 565 FRAME_SETUP(SPR_SPRG1, PC_TEMPSAVE, EXC_EXI) 566 b trap_common 567 568 569INTERRUPT(int_alignment) 570 STANDARD_PROLOG(SPR_SPRG1, PC_TEMPSAVE, SPR_SRR0, SPR_SRR1) 571 FRAME_SETUP(SPR_SPRG1, PC_TEMPSAVE, EXC_ALI) 572 b trap_common 573 574 575INTERRUPT(int_program) 576 STANDARD_PROLOG(SPR_SPRG1, PC_TEMPSAVE, SPR_SRR0, SPR_SRR1) 577 FRAME_SETUP(SPR_SPRG1, PC_TEMPSAVE, EXC_PGM) 578 b trap_common 579 580 581INTERRUPT(int_fpu) 582 STANDARD_PROLOG(SPR_SPRG1, PC_TEMPSAVE, SPR_SRR0, SPR_SRR1) 583 FRAME_SETUP(SPR_SPRG1, PC_TEMPSAVE, EXC_FPU) 584 b trap_common 585 586 587/***************************************************************************** 588 * System call 589 ****************************************************************************/ 590INTERRUPT(int_syscall) 591 STANDARD_PROLOG(SPR_SPRG1, PC_TEMPSAVE, SPR_SRR0, SPR_SRR1) 592 FRAME_SETUP(SPR_SPRG1, PC_TEMPSAVE, EXC_SC) 593 b trap_common 594 595 596/***************************************************************************** 597 * Decrementer interrupt 598 ****************************************************************************/ 599INTERRUPT(int_decrementer) 600 STANDARD_PROLOG(SPR_SPRG1, PC_TEMPSAVE, SPR_SRR0, SPR_SRR1) 601 FRAME_SETUP(SPR_SPRG1, PC_TEMPSAVE, EXC_DECR) 602 b trap_common 603 604 605/***************************************************************************** 606 * Fixed interval timer 607 ****************************************************************************/ 608INTERRUPT(int_fixed_interval_timer) 609 STANDARD_PROLOG(SPR_SPRG1, PC_TEMPSAVE, SPR_SRR0, SPR_SRR1) 610 FRAME_SETUP(SPR_SPRG1, PC_TEMPSAVE, EXC_FIT) 611 b trap_common 612 613 614/***************************************************************************** 615 * Watchdog interrupt 616 ****************************************************************************/ 617INTERRUPT(int_watchdog) 618 STANDARD_PROLOG(SPR_SPRG1, PC_TEMPSAVE, SPR_SRR0, SPR_SRR1) 619 FRAME_SETUP(SPR_SPRG1, PC_TEMPSAVE, EXC_WDOG) 620 b trap_common 621 622 623/***************************************************************************** 624 * Altivec Unavailable interrupt 625 ****************************************************************************/ 626INTERRUPT(int_vec) 627 STANDARD_PROLOG(SPR_SPRG1, PC_TEMPSAVE, SPR_SRR0, SPR_SRR1) 628 FRAME_SETUP(SPR_SPRG1, PC_TEMPSAVE, EXC_VEC) 629 b trap_common 630 631 632/***************************************************************************** 633 * Altivec Assist interrupt 634 ****************************************************************************/ 635INTERRUPT(int_vecast) 636 STANDARD_PROLOG(SPR_SPRG1, PC_TEMPSAVE, SPR_SRR0, SPR_SRR1) 637 FRAME_SETUP(SPR_SPRG1, PC_TEMPSAVE, EXC_VECAST_E) 638 b trap_common 639 640 641#ifdef __SPE__ 642/***************************************************************************** 643 * Floating point Assist interrupt 644 ****************************************************************************/ 645INTERRUPT(int_spe_fpdata) 646 STANDARD_PROLOG(SPR_SPRG1, PC_TEMPSAVE, SPR_SRR0, SPR_SRR1) 647 FRAME_SETUP(SPR_SPRG1, PC_TEMPSAVE, EXC_SPFPD) 648 addi %r3, %r1, CALLSIZE 649 bl spe_handle_fpdata 650 FRAME_LEAVE(SPR_SRR0, SPR_SRR1) 651 rfi 652 653INTERRUPT(int_spe_fpround) 654 STANDARD_PROLOG(SPR_SPRG1, PC_TEMPSAVE, SPR_SRR0, SPR_SRR1) 655 FRAME_SETUP(SPR_SPRG1, PC_TEMPSAVE, EXC_SPFPR) 656 addi %r3, %r1, CALLSIZE 657 bl spe_handle_fpround 658 FRAME_LEAVE(SPR_SRR0, SPR_SRR1) 659 rfi 660#endif 661 662 663#ifdef HWPMC_HOOKS 664/***************************************************************************** 665 * PMC Interrupt 666 ****************************************************************************/ 667INTERRUPT(int_performance_counter) 668 STANDARD_PROLOG(SPR_SPRG3, PC_TEMPSAVE, SPR_SRR0, SPR_SRR1) 669 FRAME_SETUP(SPR_SPRG3, PC_TEMPSAVE, EXC_PERF) 670 b trap_common 671#endif 672 673 674/***************************************************************************** 675 * Data TLB miss interrupt 676 * 677 * There can be nested TLB misses - while handling a TLB miss we reference 678 * data structures that may be not covered by translations. We support up to 679 * TLB_NESTED_MAX-1 nested misses. 680 * 681 * Registers use: 682 * r31 - dear 683 * r30 - unused 684 * r29 - saved mas0 685 * r28 - saved mas1 686 * r27 - saved mas2 687 * r26 - pmap address 688 * r25 - pte address 689 * 690 * r20:r23 - scratch registers 691 ****************************************************************************/ 692INTERRUPT(int_data_tlb_error) 693 TLB_PROLOG 694 TLB_LOCK 695 696 mfspr %r31, SPR_DEAR 697 698 /* 699 * Save MAS0-MAS2 registers. There might be another tlb miss during 700 * pte lookup overwriting current contents (which was hw filled). 701 */ 702 mfspr %r29, SPR_MAS0 703 mfspr %r28, SPR_MAS1 704 mfspr %r27, SPR_MAS2 705 706 /* Check faulting address. */ 707 LOAD_ADDR(%r21, VM_MAXUSER_ADDRESS) 708 CMPL cr0, %r31, %r21 709 blt search_user_pmap 710 711 /* If it's kernel address, allow only supervisor mode misses. */ 712 mfsrr1 %r21 713 mtcr %r21 714 bt 17, search_failed /* check MSR[PR] */ 715 716#ifdef __powerpc64__ 717 srdi %r21, %r31, 48 718 cmpldi cr0, %r21, VM_MIN_KERNEL_ADDRESS@highest 719#else 720 lis %r21, VM_MIN_KERNEL_ADDRESS@h 721 cmplw cr0, %r31, %r21 722#endif 723 blt search_failed 724 725search_kernel_pmap: 726 /* Load r26 with kernel_pmap address */ 727 bl 1f 728#ifdef __powerpc64__ 729 .llong kernel_pmap_store-. 730#else 731 .long kernel_pmap_store-. 732#endif 7331: mflr %r21 734 LOAD %r26, 0(%r21) 735 add %r26, %r21, %r26 /* kernel_pmap_store in r26 */ 736 737 /* Force kernel tid, set TID to 0 in MAS1. */ 738 li %r21, 0 739 rlwimi %r28, %r21, 0, 8, 15 /* clear TID bits */ 740 741tlb_miss_handle: 742 /* This may result in nested tlb miss. */ 743 bl pte_lookup /* returns PTE address in R25 */ 744 745 CMPI %r25, 0 /* pte found? */ 746 beq search_failed 747 748 /* Finish up, write TLB entry. */ 749 bl tlb_fill_entry 750 751tlb_miss_return: 752 TLB_UNLOCK 753 TLB_RESTORE 754 rfi 755 756search_user_pmap: 757 /* Load r26 with current user space process pmap */ 758 GET_CPUINFO(%r26) 759 LOAD %r26, PC_CURPMAP(%r26) 760 761 b tlb_miss_handle 762 763search_failed: 764 /* 765 * Whenever we don't find a TLB mapping in PT, set a TLB0 entry with 766 * the faulting virtual address anyway, but put a fake RPN and no 767 * access rights. This should cause a following {D,I}SI exception. 768 */ 769 lis %r23, 0xffff0000@h /* revoke all permissions */ 770 771 /* Load MAS registers. */ 772 mtspr SPR_MAS0, %r29 773 mtspr SPR_MAS1, %r28 774 mtspr SPR_MAS2, %r27 775 mtspr SPR_MAS3, %r23 776 777 li %r23, 0 778 mtspr SPR_MAS7, %r23 779 780 isync 781 tlbwe 782 msync 783 isync 784 b tlb_miss_return 785 786/***************************************************************************** 787 * 788 * Return pte address that corresponds to given pmap/va. If there is no valid 789 * entry return 0. 790 * 791 * input: r26 - pmap 792 * input: r31 - dear 793 * output: r25 - pte address 794 * 795 * scratch regs used: r21 796 * 797 ****************************************************************************/ 798pte_lookup: 799 CMPI %r26, 0 800 beq 1f /* fail quickly if pmap is invalid */ 801 802#ifdef __powerpc64__ 803 rldicl %r21, %r31, (64 - PG_ROOT_L), (64 - PG_ROOT_NUM) /* pp2d offset */ 804 slwi %r21, %r21, PG_ROOT_ENTRY_SHIFT /* multiply by pp2d entry size */ 805 ld %r25, PM_ROOT(%r26) /* pmap pm_pp2d[] address */ 806 ldx %r25, %r25, %r21 /* get pdir address, i.e. pmap->pm_pp2d[pp2d_idx] * */ 807 808 cmpdi %r25, 0 809 beq 2f 810 811 rldicl %r21, %r31, (64 - PDIR_L1_L), (64 - PDIR_L1_NUM) /* pp2d offset */ 812 slwi %r21, %r21, PDIR_L1_ENTRY_SHIFT /* multiply by pp2d entry size */ 813 ldx %r25, %r25, %r21 /* get pdir address, i.e. pmap->pm_pp2d[pp2d_idx] * */ 814 815 cmpdi %r25, 0 816 beq 2f 817 818 rldicl %r21, %r31, (64 - PDIR_L), (64 - PDIR_NUM) /* pdir offset */ 819 slwi %r21, %r21, PDIR_ENTRY_SHIFT /* multiply by pdir entry size */ 820 ldx %r25, %r25, %r21 /* get ptbl address, i.e. pmap->pm_pp2d[pp2d_idx][pdir_idx] */ 821 822 cmpdi %r25, 0 823 beq 2f 824 825 rldicl %r21, %r31, (64 - PTBL_L), (64 - PTBL_NUM) /* ptbl offset */ 826 slwi %r21, %r21, PTBL_ENTRY_SHIFT /* multiply by pte entry size */ 827 828#else 829 srwi %r21, %r31, PDIR_SHIFT /* pdir offset */ 830 slwi %r21, %r21, PDIR_ENTRY_SHIFT /* multiply by pdir entry size */ 831 832 lwz %r25, PM_PDIR(%r26) /* pmap pm_dir[] address */ 833 /* 834 * Get ptbl address, i.e. pmap->pm_pdir[pdir_idx] 835 * This load may cause a Data TLB miss for non-kernel pmap! 836 */ 837 lwzx %r25, %r25, %r21 /* offset within pm_pdir[] table */ 838 cmpwi %r25, 0 839 beq 2f 840 841 lis %r21, PTBL_MASK@h 842 ori %r21, %r21, PTBL_MASK@l 843 and %r21, %r21, %r31 844 845 /* ptbl offset, multiply by ptbl entry size */ 846 srwi %r21, %r21, (PTBL_SHIFT - PTBL_ENTRY_SHIFT) 847#endif 848 849 add %r25, %r25, %r21 /* address of pte entry */ 850 /* 851 * Get pte->flags 852 * This load may cause a Data TLB miss for non-kernel pmap! 853 */ 854 lwz %r21, PTE_FLAGS(%r25) 855 andi. %r21, %r21, PTE_VALID@l 856 bne 2f 8571: 858 li %r25, 0 8592: 860 blr 861 862/***************************************************************************** 863 * 864 * Load MAS1-MAS3 registers with data, write TLB entry 865 * 866 * input: 867 * r29 - mas0 868 * r28 - mas1 869 * r27 - mas2 870 * r25 - pte 871 * 872 * output: none 873 * 874 * scratch regs: r21-r23 875 * 876 ****************************************************************************/ 877tlb_fill_entry: 878 /* 879 * Update PTE flags: we have to do it atomically, as pmap_protect() 880 * running on other CPUs could attempt to update the flags at the same 881 * time. 882 */ 883 li %r23, PTE_FLAGS 8841: 885 lwarx %r21, %r23, %r25 /* get pte->flags */ 886 oris %r21, %r21, PTE_REFERENCED@h /* set referenced bit */ 887 888 andi. %r22, %r21, (PTE_SW | PTE_UW)@l /* check if writable */ 889 beq 2f 890 ori %r21, %r21, PTE_MODIFIED@l /* set modified bit */ 8912: 892 stwcx. %r21, %r23, %r25 /* write it back */ 893 bne- 1b 894 895 /* Update MAS2. */ 896 rlwimi %r27, %r21, 13, 27, 30 /* insert WIMG bits from pte */ 897 898 /* Setup MAS3 value in r23. */ 899 LOAD %r23, PTE_RPN(%r25) /* get pte->rpn */ 900#ifdef __powerpc64__ 901 rldicr %r22, %r23, 52, 51 /* extract MAS3 portion of RPN */ 902 rldicl %r23, %r23, 20, 54 /* extract MAS7 portion of RPN */ 903 904 rlwimi %r22, %r21, 30, 26, 31 /* insert protection bits from pte */ 905#else 906 rlwinm %r22, %r23, 20, 0, 11 /* extract MAS3 portion of RPN */ 907 908 rlwimi %r22, %r21, 30, 26, 31 /* insert protection bits from pte */ 909 rlwimi %r22, %r21, 20, 12, 19 /* insert lower 8 RPN bits to MAS3 */ 910 rlwinm %r23, %r23, 20, 24, 31 /* MAS7 portion of RPN */ 911#endif 912 913 /* Load MAS registers. */ 914 mtspr SPR_MAS0, %r29 915 mtspr SPR_MAS1, %r28 916 mtspr SPR_MAS2, %r27 917 mtspr SPR_MAS3, %r22 918 mtspr SPR_MAS7, %r23 919 920 isync 921 tlbwe 922 isync 923 msync 924 blr 925 926/***************************************************************************** 927 * Instruction TLB miss interrupt 928 * 929 * Same notes as for the Data TLB miss 930 ****************************************************************************/ 931INTERRUPT(int_inst_tlb_error) 932 TLB_PROLOG 933 TLB_LOCK 934 935 mfsrr0 %r31 /* faulting address */ 936 937 /* 938 * Save MAS0-MAS2 registers. There might be another tlb miss during pte 939 * lookup overwriting current contents (which was hw filled). 940 */ 941 mfspr %r29, SPR_MAS0 942 mfspr %r28, SPR_MAS1 943 mfspr %r27, SPR_MAS2 944 945 mfsrr1 %r21 946 mtcr %r21 947 948 /* check MSR[PR] */ 949 bt 17, search_user_pmap 950 b search_kernel_pmap 951 952 953 .globl interrupt_vector_top 954interrupt_vector_top: 955 956/***************************************************************************** 957 * Debug interrupt 958 ****************************************************************************/ 959INTERRUPT(int_debug) 960 STANDARD_CRIT_PROLOG(SPR_SPRG2, PC_BOOKE_CRITSAVE, SPR_CSRR0, SPR_CSRR1) 961 FRAME_SETUP(SPR_SPRG2, PC_BOOKE_CRITSAVE, EXC_DEBUG) 962 bl int_debug_int 963 FRAME_LEAVE(SPR_CSRR0, SPR_CSRR1) 964 rfci 965 966INTERRUPT(int_debug_ed) 967 STANDARD_CRIT_PROLOG(SPR_SPRG2, PC_BOOKE_CRITSAVE, SPR_DSRR0, SPR_DSRR1) 968 FRAME_SETUP(SPR_SPRG2, PC_BOOKE_CRITSAVE, EXC_DEBUG) 969 bl int_debug_int 970 FRAME_LEAVE(SPR_DSRR0, SPR_DSRR1) 971 rfdi 972 /* .long 0x4c00004e */ 973 974/* Internal helper for debug interrupt handling. */ 975/* Common code between e500v1/v2 and e500mc-based cores. */ 976int_debug_int: 977 mflr %r14 978 GET_CPUINFO(%r3) 979 LOAD %r3, (PC_BOOKE_CRITSAVE+CPUSAVE_SRR0)(%r3) 980 bl 0f 981 ADDR(interrupt_vector_base-.) 982 ADDR(interrupt_vector_top-.) 9830: mflr %r5 984 LOAD %r4,0(%r5) /* interrupt_vector_base in r4 */ 985 add %r4,%r4,%r5 986 CMPL cr0, %r3, %r4 987 blt trap_common 988 LOAD %r4,WORD_SIZE(%r5) /* interrupt_vector_top in r4 */ 989 add %r4,%r4,%r5 990 addi %r4,%r4,4 991 CMPL cr0, %r3, %r4 992 bge trap_common 993 /* Disable single-stepping for the interrupt handlers. */ 994 LOAD %r3, FRAME_SRR1+CALLSIZE(%r1); 995 rlwinm %r3, %r3, 0, 23, 21 996 STORE %r3, FRAME_SRR1+CALLSIZE(%r1); 997 /* Restore srr0 and srr1 as they could have been clobbered. */ 998 GET_CPUINFO(%r4) 999 LOAD %r3, (PC_BOOKE_CRITSAVE+BOOKE_CRITSAVE_SRR0)(%r4); 1000 mtspr SPR_SRR0, %r3 1001 LOAD %r4, (PC_BOOKE_CRITSAVE+BOOKE_CRITSAVE_SRR1)(%r4); 1002 mtspr SPR_SRR1, %r4 1003 mtlr %r14 1004 blr 1005 1006/***************************************************************************** 1007 * Common trap code 1008 ****************************************************************************/ 1009trap_common: 1010 /* Call C trap dispatcher */ 1011 GET_TOCBASE(%r2) 1012 addi %r3, %r1, CALLSIZE 1013 bl CNAME(powerpc_interrupt) 1014 TOC_RESTORE 1015 1016 .globl CNAME(trapexit) /* exported for db_backtrace use */ 1017CNAME(trapexit): 1018 /* disable interrupts */ 1019 wrteei 0 1020 1021 /* Test AST pending - makes sense for user process only */ 1022 LOAD %r5, FRAME_SRR1+CALLSIZE(%r1) 1023 mtcr %r5 1024 bf 17, 1f 1025 1026 GET_CPUINFO(%r3) 1027 LOAD %r4, PC_CURTHREAD(%r3) 1028 lwz %r4, TD_AST(%r4) 1029 cmpwi %r4, 0 1030 beq 1f 1031 1032 /* re-enable interrupts before calling ast() */ 1033 wrteei 1 1034 1035 addi %r3, %r1, CALLSIZE 1036 bl CNAME(ast) 1037 TOC_RESTORE 1038 .globl CNAME(asttrapexit) /* db_backtrace code sentinel #2 */ 1039CNAME(asttrapexit): 1040 b trapexit /* test ast ret value ? */ 10411: 1042 FRAME_LEAVE(SPR_SRR0, SPR_SRR1) 1043 rfi 1044 1045 1046#if defined(KDB) 1047/* 1048 * Deliberate entry to dbtrap 1049 */ 1050 /* .globl CNAME(breakpoint)*/ 1051ASENTRY_NOPROF(breakpoint) 1052 mtsprg1 %r1 1053 mfmsr %r3 1054 mtsrr1 %r3 1055 li %r4, ~(PSL_EE | PSL_ME)@l 1056 oris %r4, %r4, ~(PSL_EE | PSL_ME)@h 1057 and %r3, %r3, %r4 1058 mtmsr %r3 /* disable interrupts */ 1059 isync 1060 GET_CPUINFO(%r3) 1061 STORE %r30, (PC_DBSAVE+CPUSAVE_R30)(%r3) 1062 STORE %r31, (PC_DBSAVE+CPUSAVE_R31)(%r3) 1063 1064 mflr %r31 1065 mtsrr0 %r31 1066 1067 mfspr %r30, SPR_DEAR 1068 mfspr %r31, SPR_ESR 1069 STORE %r30, (PC_DBSAVE+CPUSAVE_BOOKE_DEAR)(%r3) 1070 STORE %r31, (PC_DBSAVE+CPUSAVE_BOOKE_ESR)(%r3) 1071 1072 mfsrr0 %r30 1073 mfsrr1 %r31 1074 STORE %r30, (PC_DBSAVE+CPUSAVE_SRR0)(%r3) 1075 STORE %r31, (PC_DBSAVE+CPUSAVE_SRR1)(%r3) 1076 isync 1077 1078 mfcr %r30 1079 1080/* 1081 * Now the kdb trap catching code. 1082 */ 1083dbtrap: 1084 FRAME_SETUP(SPR_SPRG1, PC_DBSAVE, EXC_DEBUG) 1085/* Call C trap code: */ 1086 GET_TOCBASE(%r2) 1087 addi %r3, %r1, CALLSIZE 1088 bl CNAME(db_trap_glue) 1089 TOC_RESTORE 1090 or. %r3, %r3, %r3 1091 bne dbleave 1092/* This wasn't for KDB, so switch to real trap: */ 1093 b trap_common 1094 1095dbleave: 1096 FRAME_LEAVE(SPR_SRR0, SPR_SRR1) 1097 rfi 1098ASEND(breakpoint) 1099#endif /* KDB */ 1100 1101#ifdef SMP 1102ENTRY(tlb_lock) 1103 GET_CPUINFO(%r5) 1104 LOAD %r5, PC_CURTHREAD(%r5) 11051: LOADX %r4, 0, %r3 1106 CMPI %r4, TLB_UNLOCKED 1107 bne 1b 1108 STOREX %r5, 0, %r3 1109 bne- 1b 1110 isync 1111 msync 1112 blr 1113END(tlb_lock) 1114 1115ENTRY(tlb_unlock) 1116 isync 1117 msync 1118 li %r4, TLB_UNLOCKED 1119 STORE %r4, 0(%r3) 1120 isync 1121 msync 1122 blr 1123END(tlb_unlock) 1124 1125/* 1126 * TLB miss spin locks. For each CPU we have a reservation granule (32 bytes); 1127 * only a single word from this granule will actually be used as a spin lock 1128 * for mutual exclusion between TLB miss handler and pmap layer that 1129 * manipulates page table contents. 1130 */ 1131 .data 1132 .align 5 1133GLOBAL(tlb0_miss_locks) 1134 .space RES_GRANULE * MAXCPU 1135#endif 1136