trap_subr64.S revision 209975
1/* $FreeBSD: head/sys/powerpc/aim/trap_subr64.S 209975 2010-07-13 05:32:19Z nwhitehorn $ */ 2/* $NetBSD: trap_subr.S,v 1.20 2002/04/22 23:20:08 kleink Exp $ */ 3 4/*- 5 * Copyright (C) 1995, 1996 Wolfgang Solfrank. 6 * Copyright (C) 1995, 1996 TooLs GmbH. 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. All advertising materials mentioning features or use of this software 18 * must display the following acknowledgement: 19 * This product includes software developed by TooLs GmbH. 20 * 4. The name of TooLs GmbH may not be used to endorse or promote products 21 * derived from this software without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR 24 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 25 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 26 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 28 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 29 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 30 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 31 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 32 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 */ 34 35/* 36 * NOTICE: This is not a standalone file. to use it, #include it in 37 * your port's locore.S, like so: 38 * 39 * #include <powerpc/aim/trap_subr.S> 40 */ 41 42/* 43 * Save/restore segment registers 44 */ 45 46/* 47 * Restore SRs for a pmap 48 * 49 * Requires that r28-r31 be scratch, with r28 initialized to the SLB cache 50 */ 51 52restoresrs: 53 li %r29, 0 /* Set the counter to zero */ 54 55 slbia 56 slbmfee %r31,%r29 57 clrrdi %r31,%r31,28 58 slbie %r31 59instslb: 60 ld %r31, 8(%r28); /* Load SLBE */ 61 62 cmpli 0, %r31, 0; /* If SLBE is not valid, get the next */ 63 beq nslb; 64 65 ld %r30, 0(%r28) /* Load SLBV */ 66 slbmte %r30, %r31; /* Install SLB entry */ 67 68nslb: 69 addi %r28, %r28, 16; /* Advance */ 70 addi %r29, %r29, 1; 71 cmpli 0, %r29, 64; /* Repeat if we are not at the end */ 72 blt instslb; 73 74 blr; 75 76/* 77 * User SRs are loaded through a pointer to the current pmap. 78 */ 79#define RESTORE_USER_SRS() \ 80 GET_CPUINFO(%r28); \ 81 ld %r28,PC_USERSLB(%r28); \ 82 bl restoresrs; 83 84/* 85 * Kernel SRs are loaded directly from kernel_pmap_ 86 */ 87#define RESTORE_KERN_SRS() \ 88 GET_CPUINFO(%r28); \ 89 addi %r28,%r28,PC_KERNSLB; \ 90 bl restoresrs; 91 92/* 93 * FRAME_SETUP assumes: 94 * SPRG1 SP (1) 95 * SPRG3 trap type 96 * savearea r27-r31,DAR,DSISR (DAR & DSISR only for DSI traps) 97 * r28 LR 98 * r29 CR 99 * r30 scratch 100 * r31 scratch 101 * r1 kernel stack 102 * SRR0/1 as at start of trap 103 */ 104#define FRAME_SETUP(savearea) \ 105/* Have to enable translation to allow access of kernel stack: */ \ 106 GET_CPUINFO(%r31); \ 107 mfsrr0 %r30; \ 108 std %r30,(savearea+CPUSAVE_SRR0)(%r31); /* save SRR0 */ \ 109 mfsrr1 %r30; \ 110 std %r30,(savearea+CPUSAVE_SRR1)(%r31); /* save SRR1 */ \ 111 mfmsr %r30; \ 112 ori %r30,%r30,(PSL_DR|PSL_IR|PSL_RI)@l; /* relocation on */ \ 113 mtmsr %r30; /* stack can now be accessed */ \ 114 isync; \ 115 mfsprg1 %r31; /* get saved SP */ \ 116 stdu %r31,-(FRAMELEN+288)(%r1); /* save it in the callframe */ \ 117 std %r0, FRAME_0+48(%r1); /* save r0 in the trapframe */ \ 118 std %r31,FRAME_1+48(%r1); /* save SP " " */ \ 119 std %r2, FRAME_2+48(%r1); /* save r2 " " */ \ 120 std %r28,FRAME_LR+48(%r1); /* save LR " " */ \ 121 std %r29,FRAME_CR+48(%r1); /* save CR " " */ \ 122 GET_CPUINFO(%r2); \ 123 ld %r27,(savearea+CPUSAVE_R27)(%r2); /* get saved r27 */ \ 124 ld %r28,(savearea+CPUSAVE_R28)(%r2); /* get saved r28 */ \ 125 ld %r29,(savearea+CPUSAVE_R29)(%r2); /* get saved r29 */ \ 126 ld %r30,(savearea+CPUSAVE_R30)(%r2); /* get saved r30 */ \ 127 ld %r31,(savearea+CPUSAVE_R31)(%r2); /* get saved r31 */ \ 128 std %r3, FRAME_3+48(%r1); /* save r3-r31 */ \ 129 std %r4, FRAME_4+48(%r1); \ 130 std %r5, FRAME_5+48(%r1); \ 131 std %r6, FRAME_6+48(%r1); \ 132 std %r7, FRAME_7+48(%r1); \ 133 std %r8, FRAME_8+48(%r1); \ 134 std %r9, FRAME_9+48(%r1); \ 135 std %r10, FRAME_10+48(%r1); \ 136 std %r11, FRAME_11+48(%r1); \ 137 std %r12, FRAME_12+48(%r1); \ 138 std %r13, FRAME_13+48(%r1); \ 139 std %r14, FRAME_14+48(%r1); \ 140 std %r15, FRAME_15+48(%r1); \ 141 std %r16, FRAME_16+48(%r1); \ 142 std %r17, FRAME_17+48(%r1); \ 143 std %r18, FRAME_18+48(%r1); \ 144 std %r19, FRAME_19+48(%r1); \ 145 std %r20, FRAME_20+48(%r1); \ 146 std %r21, FRAME_21+48(%r1); \ 147 std %r22, FRAME_22+48(%r1); \ 148 std %r23, FRAME_23+48(%r1); \ 149 std %r24, FRAME_24+48(%r1); \ 150 std %r25, FRAME_25+48(%r1); \ 151 std %r26, FRAME_26+48(%r1); \ 152 std %r27, FRAME_27+48(%r1); \ 153 std %r28, FRAME_28+48(%r1); \ 154 std %r29, FRAME_29+48(%r1); \ 155 std %r30, FRAME_30+48(%r1); \ 156 std %r31, FRAME_31+48(%r1); \ 157 ld %r28,(savearea+CPUSAVE_AIM_DAR)(%r2); /* saved DAR */ \ 158 ld %r29,(savearea+CPUSAVE_AIM_DSISR)(%r2);/* saved DSISR */\ 159 ld %r30,(savearea+CPUSAVE_SRR0)(%r2); /* saved SRR0 */ \ 160 ld %r31,(savearea+CPUSAVE_SRR1)(%r2); /* saved SRR1 */ \ 161 mfxer %r3; \ 162 mfctr %r4; \ 163 mfsprg3 %r5; \ 164 std %r3, FRAME_XER+48(1); /* save xer/ctr/exc */ \ 165 std %r4, FRAME_CTR+48(1); \ 166 std %r5, FRAME_EXC+48(1); \ 167 std %r28,FRAME_AIM_DAR+48(1); \ 168 std %r29,FRAME_AIM_DSISR+48(1); /* save dsisr/srr0/srr1 */ \ 169 std %r30,FRAME_SRR0+48(1); \ 170 std %r31,FRAME_SRR1+48(1) 171 172#define FRAME_LEAVE(savearea) \ 173/* Now restore regs: */ \ 174 ld %r2,FRAME_SRR0+48(%r1); \ 175 ld %r3,FRAME_SRR1+48(%r1); \ 176 ld %r4,FRAME_CTR+48(%r1); \ 177 ld %r5,FRAME_XER+48(%r1); \ 178 ld %r6,FRAME_LR+48(%r1); \ 179 GET_CPUINFO(%r7); \ 180 std %r2,(savearea+CPUSAVE_SRR0)(%r7); /* save SRR0 */ \ 181 std %r3,(savearea+CPUSAVE_SRR1)(%r7); /* save SRR1 */ \ 182 ld %r7,FRAME_CR+48(%r1); \ 183 mtctr %r4; \ 184 mtxer %r5; \ 185 mtlr %r6; \ 186 mtsprg1 %r7; /* save cr */ \ 187 ld %r31,FRAME_31+48(%r1); /* restore r0-31 */ \ 188 ld %r30,FRAME_30+48(%r1); \ 189 ld %r29,FRAME_29+48(%r1); \ 190 ld %r28,FRAME_28+48(%r1); \ 191 ld %r27,FRAME_27+48(%r1); \ 192 ld %r26,FRAME_26+48(%r1); \ 193 ld %r25,FRAME_25+48(%r1); \ 194 ld %r24,FRAME_24+48(%r1); \ 195 ld %r23,FRAME_23+48(%r1); \ 196 ld %r22,FRAME_22+48(%r1); \ 197 ld %r21,FRAME_21+48(%r1); \ 198 ld %r20,FRAME_20+48(%r1); \ 199 ld %r19,FRAME_19+48(%r1); \ 200 ld %r18,FRAME_18+48(%r1); \ 201 ld %r17,FRAME_17+48(%r1); \ 202 ld %r16,FRAME_16+48(%r1); \ 203 ld %r15,FRAME_15+48(%r1); \ 204 ld %r14,FRAME_14+48(%r1); \ 205 ld %r13,FRAME_13+48(%r1); \ 206 ld %r12,FRAME_12+48(%r1); \ 207 ld %r11,FRAME_11+48(%r1); \ 208 ld %r10,FRAME_10+48(%r1); \ 209 ld %r9, FRAME_9+48(%r1); \ 210 ld %r8, FRAME_8+48(%r1); \ 211 ld %r7, FRAME_7+48(%r1); \ 212 ld %r6, FRAME_6+48(%r1); \ 213 ld %r5, FRAME_5+48(%r1); \ 214 ld %r4, FRAME_4+48(%r1); \ 215 ld %r3, FRAME_3+48(%r1); \ 216 ld %r2, FRAME_2+48(%r1); \ 217 ld %r0, FRAME_0+48(%r1); \ 218 ld %r1, FRAME_1+48(%r1); \ 219/* Can't touch %r1 from here on */ \ 220 mtsprg2 %r2; /* save r2 & r3 */ \ 221 mtsprg3 %r3; \ 222/* Disable translation, machine check and recoverability: */ \ 223 mfmsr %r2; \ 224 andi. %r2,%r2,~(PSL_DR|PSL_IR|PSL_EE|PSL_ME|PSL_RI)@l; \ 225 mtmsr %r2; \ 226 isync; \ 227/* Decide whether we return to user mode: */ \ 228 GET_CPUINFO(%r2); \ 229 ld %r3,(savearea+CPUSAVE_SRR1)(%r2); \ 230 mtcr %r3; \ 231 bf 17,1f; /* branch if PSL_PR is false */ \ 232/* Restore user SRs */ \ 233 GET_CPUINFO(%r3); \ 234 std %r27,(savearea+CPUSAVE_R27)(%r3); \ 235 std %r28,(savearea+CPUSAVE_R28)(%r3); \ 236 std %r29,(savearea+CPUSAVE_R29)(%r3); \ 237 std %r30,(savearea+CPUSAVE_R30)(%r3); \ 238 std %r31,(savearea+CPUSAVE_R31)(%r3); \ 239 mflr %r27; /* preserve LR */ \ 240 RESTORE_USER_SRS(); /* uses r28-r31 */ \ 241 mtlr %r27; \ 242 ld %r31,(savearea+CPUSAVE_R31)(%r3); \ 243 ld %r30,(savearea+CPUSAVE_R30)(%r3); \ 244 ld %r29,(savearea+CPUSAVE_R29)(%r3); \ 245 ld %r28,(savearea+CPUSAVE_R28)(%r3); \ 246 ld %r27,(savearea+CPUSAVE_R27)(%r3); \ 2471: mfsprg1 %r2; /* restore cr */ \ 248 mtcr %r2; \ 249 GET_CPUINFO(%r2); \ 250 ld %r3,(savearea+CPUSAVE_SRR0)(%r2); /* restore srr0 */ \ 251 mtsrr0 %r3; \ 252 ld %r3,(savearea+CPUSAVE_SRR1)(%r2); /* restore srr1 */ \ 253 mtsrr1 %r3; \ 254 mfsprg2 %r2; /* restore r2 & r3 */ \ 255 mfsprg3 %r3 256 257#ifdef SMP 258/* 259 * Processor reset exception handler. These are typically 260 * the first instructions the processor executes after a 261 * software reset. We do this in two bits so that we are 262 * not still hanging around in the trap handling region 263 * once the MMU is turned on. 264 */ 265 .globl CNAME(rstcode), CNAME(rstsize) 266CNAME(rstcode): 267 /* Explicitly set MSR[SF] */ 268 mfmsr %r9 269 li %r8,1 270 insrdi %r9,%r8,1,0 271 mtmsrd %r9 272 isync 273 274 ba cpu_reset 275CNAME(rstsize) = . - CNAME(rstcode) 276 277cpu_reset: 278 lis %r1,(tmpstk+TMPSTKSZ-48)@ha /* get new SP */ 279 addi %r1,%r1,(tmpstk+TMPSTKSZ-48)@l 280 281 lis %r3,tocbase@ha 282 ld %r2,tocbase@l(%r3) 283 lis %r3,1@l 284 bl CNAME(.cpudep_ap_early_bootstrap) /* Set PCPU */ 285 nop 286 bl CNAME(.pmap_cpu_bootstrap) /* Turn on virtual memory */ 287 nop 288 bl CNAME(.cpudep_ap_bootstrap) /* Set up PCPU and stack */ 289 nop 290 mr %r1,%r3 /* Use new stack */ 291 bl CNAME(.machdep_ap_bootstrap) /* And away! */ 292 nop 293 294 /* Should not be reached */ 2959: 296 b 9b 297#endif 298 299/* 300 * This code gets copied to all the trap vectors 301 * (except ISI/DSI, ALI, and the interrupts) 302 */ 303 304 .globl CNAME(trapcode),CNAME(trapsize) 305CNAME(trapcode): 306 mtsprg1 %r1 /* save SP */ 307 mflr %r1 /* Save the old LR in r1 */ 308 mtsprg2 %r1 /* And then in SPRG2 */ 309 li %r1, 0xA0 /* How to get the vector from LR */ 310 bla generictrap /* LR & SPRG3 is exception # */ 311CNAME(trapsize) = .-CNAME(trapcode) 312 313/* 314 * For ALI: has to save DSISR and DAR 315 */ 316 .globl CNAME(alitrap),CNAME(alisize) 317CNAME(alitrap): 318 mtsprg1 %r1 /* save SP */ 319 GET_CPUINFO(%r1) 320 std %r27,(PC_TEMPSAVE+CPUSAVE_R27)(%r1) /* free r27-r31 */ 321 std %r28,(PC_TEMPSAVE+CPUSAVE_R28)(%r1) 322 std %r29,(PC_TEMPSAVE+CPUSAVE_R29)(%r1) 323 std %r30,(PC_TEMPSAVE+CPUSAVE_R30)(%r1) 324 std %r31,(PC_TEMPSAVE+CPUSAVE_R31)(%r1) 325 mfdar %r30 326 mfdsisr %r31 327 std %r30,(PC_TEMPSAVE+CPUSAVE_AIM_DAR)(%r1) 328 std %r31,(PC_TEMPSAVE+CPUSAVE_AIM_DSISR)(%r1) 329 mfsprg1 %r1 /* restore SP, in case of branch */ 330 mflr %r28 /* save LR */ 331 mfcr %r29 /* save CR */ 332 333 /* Put our exception vector in SPRG3 */ 334 li %r31, EXC_ALI 335 mtsprg3 %r31 336 337 /* Test whether we already had PR set */ 338 mfsrr1 %r31 339 mtcr %r31 340 bla s_trap 341CNAME(alisize) = .-CNAME(alitrap) 342 343/* 344 * Similar to the above for DSI 345 * Has to handle BAT spills 346 * and standard pagetable spills 347 */ 348 .globl CNAME(dsitrap),CNAME(dsisize) 349CNAME(dsitrap): 350 mtsprg1 %r1 /* save SP */ 351 GET_CPUINFO(%r1) 352 std %r27,(PC_DISISAVE+CPUSAVE_R27)(%r1) /* free r27-r31 */ 353 std %r28,(PC_DISISAVE+CPUSAVE_R28)(%r1) 354 std %r29,(PC_DISISAVE+CPUSAVE_R29)(%r1) 355 std %r30,(PC_DISISAVE+CPUSAVE_R30)(%r1) 356 std %r31,(PC_DISISAVE+CPUSAVE_R31)(%r1) 357 mfsprg1 %r1 /* restore SP */ 358 mfcr %r29 /* save CR */ 359 mfxer %r30 /* save XER */ 360 mtsprg2 %r30 /* in SPRG2 */ 361 mfsrr1 %r31 /* test kernel mode */ 362 mtcr %r31 363 mflr %r28 /* save LR (SP already saved) */ 364 bla disitrap 365CNAME(dsisize) = .-CNAME(dsitrap) 366 367/* 368 * Preamble code for DSI/ISI traps 369 */ 370disitrap: 371 /* Write the trap vector to SPRG3 by computing LR & 0xff00 */ 372 mflr %r1 373 andi. %r1,%r1,0xff00 374 mtsprg3 %r1 375 376 GET_CPUINFO(%r1) 377 ld %r31,(PC_DISISAVE+CPUSAVE_R27)(%r1) 378 std %r31,(PC_TEMPSAVE+CPUSAVE_R27)(%r1) 379 ld %r30,(PC_DISISAVE+CPUSAVE_R28)(%r1) 380 std %r30,(PC_TEMPSAVE+CPUSAVE_R28)(%r1) 381 ld %r31,(PC_DISISAVE+CPUSAVE_R29)(%r1) 382 std %r31,(PC_TEMPSAVE+CPUSAVE_R29)(%r1) 383 ld %r30,(PC_DISISAVE+CPUSAVE_R30)(%r1) 384 std %r30,(PC_TEMPSAVE+CPUSAVE_R30)(%r1) 385 ld %r31,(PC_DISISAVE+CPUSAVE_R31)(%r1) 386 std %r31,(PC_TEMPSAVE+CPUSAVE_R31)(%r1) 387 mfdar %r30 388 mfdsisr %r31 389 std %r30,(PC_TEMPSAVE+CPUSAVE_AIM_DAR)(%r1) 390 std %r31,(PC_TEMPSAVE+CPUSAVE_AIM_DSISR)(%r1) 391 392#ifdef KDB 393 /* Try and detect a kernel stack overflow */ 394 mfsrr1 %r31 395 mtcr %r31 396 bt 17,realtrap /* branch is user mode */ 397 mfsprg1 %r31 /* get old SP */ 398 sub. %r30,%r31,%r30 /* SP - DAR */ 399 bge 1f 400 neg %r30,%r30 /* modulo value */ 4011: cmpldi %cr0,%r30,4096 /* is DAR within a page of SP? */ 402 bge %cr0,realtrap /* no, too far away. */ 403 404 /* Now convert this DSI into a DDB trap. */ 405 GET_CPUINFO(%r1) 406 ld %r30,(PC_TEMPSAVE+CPUSAVE_AIM_DAR)(%r1) /* get DAR */ 407 std %r30,(PC_DBSAVE +CPUSAVE_AIM_DAR)(%r1) /* save DAR */ 408 ld %r30,(PC_TEMPSAVE+CPUSAVE_AIM_DSISR)(%r1) /* get DSISR */ 409 std %r30,(PC_DBSAVE +CPUSAVE_AIM_DSISR)(%r1) /* save DSISR */ 410 ld %r31,(PC_DISISAVE+CPUSAVE_R27)(%r1) /* get r27 */ 411 std %r31,(PC_DBSAVE +CPUSAVE_R27)(%r1) /* save r27 */ 412 ld %r30,(PC_DISISAVE+CPUSAVE_R28)(%r1) /* get r28 */ 413 std %r30,(PC_DBSAVE +CPUSAVE_R28)(%r1) /* save r28 */ 414 ld %r31,(PC_DISISAVE+CPUSAVE_R29)(%r1) /* get r29 */ 415 std %r31,(PC_DBSAVE +CPUSAVE_R29)(%r1) /* save r29 */ 416 ld %r30,(PC_DISISAVE+CPUSAVE_R30)(%r1) /* get r30 */ 417 std %r30,(PC_DBSAVE +CPUSAVE_R30)(%r1) /* save r30 */ 418 ld %r31,(PC_DISISAVE+CPUSAVE_R31)(%r1) /* get r31 */ 419 std %r31,(PC_DBSAVE +CPUSAVE_R31)(%r1) /* save r31 */ 420 b dbtrap 421#endif 422 423 /* XXX need stack probe here */ 424realtrap: 425/* Test whether we already had PR set */ 426 mfsrr1 %r1 427 mtcr %r1 428 mfsprg1 %r1 /* restore SP (might have been 429 overwritten) */ 430 bf 17,k_trap /* branch if PSL_PR is false */ 431 GET_CPUINFO(%r1) 432 ld %r1,PC_CURPCB(%r1) 433 mr %r27,%r28 /* Save LR, r29 */ 434 mtsprg2 %r29 435 RESTORE_KERN_SRS() /* enable kernel mapping */ 436 mfsprg2 %r29 437 mr %r28,%r27 438 ba s_trap 439 440/* 441 * generictrap does some standard setup for trap handling to minimize 442 * the code that need be installed in the actual vectors. It expects 443 * the following conditions. 444 * 445 * R1 - Trap vector = LR & (0xff00 | R1) 446 * SPRG1 - Original R1 contents 447 * SPRG2 - Original LR 448 */ 449 450generictrap: 451 /* Save R1 for computing the exception vector */ 452 mtsprg3 %r1 453 454 /* Save interesting registers */ 455 GET_CPUINFO(%r1) 456 std %r27,(PC_TEMPSAVE+CPUSAVE_R27)(%r1) /* free r27-r31 */ 457 std %r28,(PC_TEMPSAVE+CPUSAVE_R28)(%r1) 458 std %r29,(PC_TEMPSAVE+CPUSAVE_R29)(%r1) 459 std %r30,(PC_TEMPSAVE+CPUSAVE_R30)(%r1) 460 std %r31,(PC_TEMPSAVE+CPUSAVE_R31)(%r1) 461 mfdar %r30 462 std %r30,(PC_TEMPSAVE+CPUSAVE_AIM_DAR)(%r1) 463 mfsprg1 %r1 /* restore SP, in case of branch */ 464 mfsprg2 %r28 /* save LR */ 465 mfcr %r29 /* save CR */ 466 467 /* Compute the exception vector from the link register */ 468 mfsprg3 %r31 469 ori %r31,%r31,0xff00 470 mflr %r30 471 and %r30,%r30,%r31 472 mtsprg3 %r30 473 474 /* Test whether we already had PR set */ 475 mfsrr1 %r31 476 mtcr %r31 477 478s_trap: 479 bf 17,k_trap /* branch if PSL_PR is false */ 480 GET_CPUINFO(%r1) 481u_trap: 482 ld %r1,PC_CURPCB(%r1) 483 mr %r27,%r28 /* Save LR, r29 */ 484 mtsprg2 %r29 485 RESTORE_KERN_SRS() /* enable kernel mapping */ 486 mfsprg2 %r29 487 mr %r28,%r27 488 489/* 490 * Now the common trap catching code. 491 */ 492k_trap: 493 FRAME_SETUP(PC_TEMPSAVE) 494/* Call C interrupt dispatcher: */ 495trapagain: 496 lis %r3,tocbase@ha 497 ld %r2,tocbase@l(%r3) 498 addi %r3,%r1,48 499 bl CNAME(.powerpc_interrupt) 500 nop 501 502 .globl CNAME(trapexit) /* backtrace code sentinel */ 503CNAME(trapexit): 504/* Disable interrupts: */ 505 mfmsr %r3 506 andi. %r3,%r3,~PSL_EE@l 507 mtmsr %r3 508/* Test AST pending: */ 509 ld %r5,FRAME_SRR1+48(%r1) 510 mtcr %r5 511 bf 17,1f /* branch if PSL_PR is false */ 512 513 GET_CPUINFO(%r3) /* get per-CPU pointer */ 514 ld %r4, PC_CURTHREAD(%r3) /* deref to get curthread */ 515 lwz %r4, TD_FLAGS(%r4) /* get thread flags value */ 516 lis %r5, (TDF_ASTPENDING|TDF_NEEDRESCHED)@h 517 ori %r5,%r5, (TDF_ASTPENDING|TDF_NEEDRESCHED)@l 518 and. %r4,%r4,%r5 519 beq 1f 520 mfmsr %r3 /* re-enable interrupts */ 521 ori %r3,%r3,PSL_EE@l 522 mtmsr %r3 523 isync 524 lis %r3,tocbase@ha 525 ld %r2,tocbase@l(%r3) 526 addi %r3,%r1,48 527 bl CNAME(.ast) 528 nop 529 .globl CNAME(asttrapexit) /* backtrace code sentinel #2 */ 530CNAME(asttrapexit): 531 b trapexit /* test ast ret value ? */ 5321: 533 FRAME_LEAVE(PC_TEMPSAVE) 534 rfid 535 536#if defined(KDB) 537/* 538 * Deliberate entry to dbtrap 539 */ 540ASENTRY(breakpoint) 541 mtsprg1 %r1 542 mfmsr %r3 543 mtsrr1 %r3 544 andi. %r3,%r3,~(PSL_EE|PSL_ME)@l 545 mtmsr %r3 /* disable interrupts */ 546 isync 547 GET_CPUINFO(%r3) 548 std %r27,(PC_DBSAVE+CPUSAVE_R27)(%r3) 549 std %r28,(PC_DBSAVE+CPUSAVE_R28)(%r3) 550 std %r29,(PC_DBSAVE+CPUSAVE_R29)(%r3) 551 std %r30,(PC_DBSAVE+CPUSAVE_R30)(%r3) 552 std %r31,(PC_DBSAVE+CPUSAVE_R31)(%r3) 553 mflr %r28 554 li %r29,EXC_BPT 555 mtlr %r29 556 mfcr %r29 557 mtsrr0 %r28 558 559/* 560 * Now the kdb trap catching code. 561 */ 562dbtrap: 563 /* Write the trap vector to SPRG3 by computing LR & 0xff00 */ 564 mflr %r1 565 andi. %r1,%r1,0xff00 566 mtsprg3 %r1 567 568 lis %r1,(tmpstk+TMPSTKSZ-48)@ha /* get new SP */ 569 addi %r1,%r1,(tmpstk+TMPSTKSZ-48)@l 570 571 FRAME_SETUP(PC_DBSAVE) 572/* Call C trap code: */ 573 lis %r3,tocbase@ha 574 ld %r2,tocbase@l(%r3) 575 addi %r3,%r1,48 576 bl CNAME(.db_trap_glue) 577 nop 578 or. %r3,%r3,%r3 579 bne dbleave 580/* This wasn't for KDB, so switch to real trap: */ 581 ld %r3,FRAME_EXC+48(%r1) /* save exception */ 582 GET_CPUINFO(%r4) 583 std %r3,(PC_DBSAVE+CPUSAVE_R31)(%r4) 584 FRAME_LEAVE(PC_DBSAVE) 585 mtsprg1 %r1 /* prepare for entrance to realtrap */ 586 GET_CPUINFO(%r1) 587 std %r27,(PC_TEMPSAVE+CPUSAVE_R27)(%r1) 588 std %r28,(PC_TEMPSAVE+CPUSAVE_R28)(%r1) 589 std %r29,(PC_TEMPSAVE+CPUSAVE_R29)(%r1) 590 std %r30,(PC_TEMPSAVE+CPUSAVE_R30)(%r1) 591 std %r31,(PC_TEMPSAVE+CPUSAVE_R31)(%r1) 592 mflr %r28 593 mfcr %r29 594 ld %r31,(PC_DBSAVE+CPUSAVE_R31)(%r1) 595 mtsprg3 %r31 /* SPRG3 was clobbered by FRAME_LEAVE */ 596 mfsprg1 %r1 597 b realtrap 598dbleave: 599 FRAME_LEAVE(PC_DBSAVE) 600 rfid 601 602/* 603 * In case of KDB we want a separate trap catcher for it 604 */ 605 .globl CNAME(dblow),CNAME(dbsize) 606CNAME(dblow): 607 mtsprg1 %r1 /* save SP */ 608 mtsprg2 %r29 /* save r29 */ 609 mfcr %r29 /* save CR in r29 */ 610 mfsrr1 %r1 611 mtcr %r1 612 bf 17,1f /* branch if privileged */ 613 614 /* Unprivileged case */ 615 mtcr %r29 /* put the condition register back */ 616 mfsprg2 %r29 /* ... and r29 */ 617 mflr %r1 /* save LR */ 618 mtsprg2 %r1 /* And then in SPRG2 */ 619 li %r1, 0 /* How to get the vector from LR */ 620 621 bla generictrap /* and we look like a generic trap */ 6221: 623 /* Privileged, so drop to KDB */ 624 GET_CPUINFO(%r1) 625 std %r27,(PC_DBSAVE+CPUSAVE_R27)(%r1) /* free r27 */ 626 std %r28,(PC_DBSAVE+CPUSAVE_R28)(%r1) /* free r28 */ 627 mfsprg2 %r28 /* r29 holds cr... */ 628 std %r28,(PC_DBSAVE+CPUSAVE_R29)(%r1) /* free r29 */ 629 std %r30,(PC_DBSAVE+CPUSAVE_R30)(%r1) /* free r30 */ 630 std %r31,(PC_DBSAVE+CPUSAVE_R31)(%r1) /* free r31 */ 631 mflr %r28 /* save LR */ 632 bla dbtrap 633CNAME(dbsize) = .-CNAME(dblow) 634#endif /* KDB */ 635