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