trap_subr64.S revision 96253
1/* $FreeBSD: head/sys/powerpc/aim/trap_subr.S 96253 2002-05-09 14:15:51Z benno $ */ 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/powerpc/trap_subr.S> 40 */ 41 42/* 43 * XXX Fake AST trap vector. This is here until we work out how to safely 44 * remove the AST code. 45 */ 46#define EXC_AST 0x3000 47 .data 48 .align 4 49astpending: 50 .long 0 51cpassert: 52 .asciz "attempting to return from kernel with no current pmap" 53 54/* 55 * Data used during primary/secondary traps/interrupts 56 */ 57#define tempsave EXC_MCHK+0xe0 /* primary save area for trap handling */ 58#define disisave EXC_DSI+0xe0 /* primary save area for dsi/isi traps */ 59 60/* 61 * XXX Interrupt and spill stacks need to be per-CPU. 62 */ 63 .data 64 .align 4 65intstk: 66 .space INTSTK /* interrupt stack */ 67 68GLOBAL(intr_depth) 69 .long -1 /* in-use marker */ 70 71 .comm spillstk,SPILLSTK,8 72 73/* 74 * This code gets copied to all the trap vectors 75 * (except ISI/DSI, ALI, the interrupts, and possibly the debugging 76 * traps when using IPKDB). 77 */ 78 .text 79 .globl _C_LABEL(trapcode),_C_LABEL(trapsize) 80_C_LABEL(trapcode): 81 mtsprg 1,1 /* save SP */ 82 stmw 28,tempsave(0) /* free r28-r31 */ 83 mflr 28 /* save LR */ 84 mfcr 29 /* save CR */ 85/* Test whether we already had PR set */ 86 mfsrr1 31 87 mtcr 31 88 bc 4,17,1f /* branch if PSL_PR is clear */ 89 mfsprg 31,0 90 lwz 1,PC_CURPCB(31) 91 addi 1,1,USPACE /* stack is top of user struct */ 921: 93 bla s_trap 94_C_LABEL(trapsize) = .-_C_LABEL(trapcode) 95 96/* 97 * For ALI: has to save DSISR and DAR 98 */ 99 .globl _C_LABEL(alitrap),_C_LABEL(alisize) 100_C_LABEL(alitrap): 101 mtsprg 1,1 /* save SP */ 102 stmw 28,tempsave(0) /* free r28-r31 */ 103 mfdar 30 104 mfdsisr 31 105 stmw 30,tempsave+16(0) 106 mflr 28 /* save LR */ 107 mfcr 29 /* save CR */ 108/* Test whether we already had PR set */ 109 mfsrr1 31 110 mtcr 31 111 bc 4,17,1f /* branch if PSL_PR is clear */ 112 mfsprg 31,0 113 lwz 1,PC_CURPCB(31) 114 addi 1,1,USPACE /* stack is top of user struct */ 1151: 116 bla s_trap 117_C_LABEL(alisize) = .-_C_LABEL(alitrap) 118 119/* 120 * Similar to the above for DSI 121 * Has to handle BAT spills 122 * and standard pagetable spills 123 */ 124 .globl _C_LABEL(dsitrap),_C_LABEL(dsisize) 125_C_LABEL(dsitrap): 126 stmw 28,disisave(0) /* free r28-r31 */ 127 mfcr 29 /* save CR */ 128 mfxer 30 /* save XER */ 129 mtsprg 2,30 /* in SPRG2 */ 130 mfsrr1 31 /* test kernel mode */ 131 mtcr 31 132 bc 12,17,1f /* branch if PSL_PR is set */ 133 mfdar 31 /* get fault address */ 134 rlwinm 31,31,7,25,28 /* get segment * 8 */ 135 136 /* get batu */ 137 addis 31,31,_C_LABEL(battable)@ha 138 lwz 30,_C_LABEL(battable)@l(31) 139 mtcr 30 140 bc 4,30,1f /* branch if supervisor valid is 141 false */ 142 /* get batl */ 143 lwz 31,_C_LABEL(battable)+4@l(31) 144/* We randomly use the highest two bat registers here */ 145 mftb 28 146 andi. 28,28,1 147 bne 2f 148 mtdbatu 2,30 149 mtdbatl 2,31 150 b 3f 1512: 152 mtdbatu 3,30 153 mtdbatl 3,31 1543: 155 mfsprg 30,2 /* restore XER */ 156 mtxer 30 157 mtcr 29 /* restore CR */ 158 lmw 28,disisave(0) /* restore r28-r31 */ 159 rfi /* return to trapped code */ 1601: 161 mflr 28 /* save LR */ 162 bla s_dsitrap 163_C_LABEL(dsisize) = .-_C_LABEL(dsitrap) 164 165/* 166 * Dedicated MPC601 version of the above. 167 * Considers different BAT format and combined implementation 168 * (being addressed as I-BAT). 169 */ 170 .globl _C_LABEL(dsitrap601),_C_LABEL(dsi601size) 171_C_LABEL(dsitrap601): 172 stmw 28,disisave(0) /* free r28-r31 */ 173 mfcr 29 /* save CR */ 174 mfxer 30 /* save XER */ 175 mtsprg 2,30 /* in SPRG2 */ 176 mfsrr1 31 /* test kernel mode */ 177 mtcr 31 178 bc 12,17,1f /* branch if PSL_PR is set */ 179 mfdar 31 /* get fault address */ 180 rlwinm 31,31,12,20,28 /* get "segment" battable offset */ 181 182 /* get batl */ 183 addis 31,31,_C_LABEL(battable)@ha 184 lwz 30,_C_LABEL(battable)+4@l(31) 185 mtcr 30 186 bc 4,25,1f /* branch if Valid is is false, 187 presently assumes supervisor only */ 188 189 /* get batu */ 190 lwz 31,_C_LABEL(battable)@l(31) 191/* We randomly use the highest two bat registers here */ 192 mfspr 28,SPR_RTCL_R 193 andi. 28,28,128 194 bne 2f 195 mtibatu 2,31 196 mtibatl 2,30 197 b 3f 1982: 199 mtibatu 3,31 200 mtibatl 3,30 2013: 202 mfsprg 30,2 /* restore XER */ 203 mtxer 30 204 mtcr 29 /* restore CR */ 205 lmw 28,disisave(0) /* restore r28-r31 */ 206 rfi /* return to trapped code */ 2071: 208 mflr 28 /* save LR */ 209 bla s_dsitrap 210_C_LABEL(dsi601size) = .-_C_LABEL(dsitrap601) 211 212/* 213 * Similar to the above for ISI 214 */ 215 .globl _C_LABEL(isitrap),_C_LABEL(isisize) 216_C_LABEL(isitrap): 217 stmw 28,disisave(0) /* free r28-r31 */ 218 mflr 28 /* save LR */ 219 mfcr 29 /* save CR */ 220 mfsrr1 31 /* test kernel mode */ 221 mtcr 31 222 bc 12,17,1f /* branch if PSL_PR is set */ 223 mfsrr0 31 /* get fault address */ 224 rlwinm 31,31,7,25,28 /* get segment * 8 */ 225 226 /* get batu */ 227 addis 31,31,_C_LABEL(battable)@ha 228 lwz 30,_C_LABEL(battable)@l(31) 229 mtcr 30 230 bc 4,30,1f /* branch if supervisor valid is 231 false */ 232 mtibatu 3,30 233 234 /* get batl */ 235 lwz 30,_C_LABEL(battable)+4@l(31) 236 mtibatl 3,30 237 238 mtcr 29 /* restore CR */ 239 lmw 28,disisave(0) /* restore r28-r31 */ 240 rfi /* return to trapped code */ 2411: 242 bla s_isitrap 243_C_LABEL(isisize)= .-_C_LABEL(isitrap) 244 245/* 246 * Dedicated MPC601 version of the above. 247 * Considers different BAT format. 248 */ 249 .globl _C_LABEL(isitrap601),_C_LABEL(isi601size) 250_C_LABEL(isitrap601): 251 stmw 28,disisave(0) /* free r28-r31 */ 252 mflr 28 /* save LR */ 253 mfcr 29 /* save CR */ 254 mfsrr1 31 /* test kernel mode */ 255 mtcr 31 256 bc 12,17,1f /* branch if PSL_PR is set */ 257 mfsrr0 31 /* get fault address */ 258 rlwinm 31,31,12,20,28 /* get "segment" battable offset */ 259 260 /* get batl */ 261 addis 31,31,_C_LABEL(battable)@ha 262 lwz 30,_C_LABEL(battable)+4@l(31) 263 mtcr 30 264 bc 4,25,1f /* branch if Valid is is false, 265 presently assumes supervisor only */ 266 /* get batu */ 267 lwz 31,_C_LABEL(battable)@l(31) 268 269 mtibatu 3,31 270 mtibatl 3,30 271 272 mtcr 29 /* restore CR */ 273 lmw 28,disisave(0) /* restore r28-r31 */ 274 rfi /* return to trapped code */ 2751: 276 bla s_isitrap 277_C_LABEL(isi601size)= .-_C_LABEL(isitrap601) 278 279/* 280 * This one for the external interrupt handler. 281 */ 282 .globl _C_LABEL(extint),_C_LABEL(extsize) 283_C_LABEL(extint): 284 mtsprg 1,1 /* save SP */ 285 stmw 28,tempsave(0) /* free r28-r31 */ 286 mflr 28 /* save LR */ 287 mfcr 29 /* save CR */ 288 mfxer 30 /* save XER */ 289 lis 1,intstk+INTSTK@ha /* get interrupt stack */ 290 addi 1,1,intstk+INTSTK@l /* this is really intr_depth! */ 291 lwz 31,0(1) /* were we already running on intstk? */ 292 addic. 31,31,1 293 stw 31,0(1) 294 beq 1f 295 mfsprg 1,1 /* yes, get old SP */ 2961: 297 ba extintr 298_C_LABEL(extsize) = .-_C_LABEL(extint) 299 300/* 301 * And this one for the decrementer interrupt handler. 302 */ 303 .globl _C_LABEL(decrint),_C_LABEL(decrsize) 304_C_LABEL(decrint): 305 mtsprg 1,1 /* save SP */ 306 stmw 28,tempsave(0) /* free r28-r31 */ 307 mflr 28 /* save LR */ 308 mfcr 29 /* save CR */ 309 mfxer 30 /* save XER */ 310 lis 1,intstk+INTSTK@ha /* get interrupt stack */ 311 addi 1,1,intstk+INTSTK@l 312 lwz 31,0(1) /* were we already running on intstk? */ 313 addic. 31,31,1 314 stw 31,0(1) 315 beq 1f 316 mfsprg 1,1 /* yes, get old SP */ 3171: 318 ba decrintr 319_C_LABEL(decrsize) = .-_C_LABEL(decrint) 320 321/* 322 * Now the tlb software load for 603 processors: 323 * (Code essentially from the 603e User Manual, Chapter 5, but 324 * corrected a lot.) 325 */ 326 327 .globl _C_LABEL(tlbimiss),_C_LABEL(tlbimsize) 328_C_LABEL(tlbimiss): 329#ifdef PMAPDEBUG 330 mfspr 2,SPR_IMISS /* exception address */ 331 li 1,24 /* get rid of the lower */ 332 srw 2,2,1 /* 24 bits */ 333 li 1,1 /* Load 1 */ 334 cmpl 2,1,1 /* is it > 16MB */ 335 blt 99f /* nope, skip saving these SPRs */ 336 li 1,0xc0 /* arbitrary */ 337 mfspr 2,SPR_HASH1 338 stw 2,0(1) 339 mfspr 2,SPR_HASH2 340 stw 2,4(1) 341 mfspr 2,SPR_IMISS 342 stw 2,8(1) 343 mfspr 2,SPR_ICMP 344 stw 2,12(1) 34599: 346#endif /* PMAPDEBUG */ 347 mfspr 2,SPR_HASH1 /* get first pointer */ 348 li 1,8 349 mfctr 0 /* save counter */ 350 mfspr 3,SPR_ICMP /* get first compare value */ 351 addi 2,2,-8 /* predec pointer */ 3521: 353 mtctr 1 /* load counter */ 3542: 355 lwzu 1,8(2) /* get next pte */ 356 cmpl 0,1,3 /* see if found pte */ 357 bdneq 2b /* loop if not eq */ 358 bne 3f /* not found */ 359 lwz 1,4(2) /* load tlb entry lower word */ 360 andi. 3,1,8 /* check G-bit */ 361 bne 4f /* if guarded, take ISI */ 362 mtctr 0 /* restore counter */ 363 mfspr 0,SPR_IMISS /* get the miss address for the tlbli */ 364 mfsrr1 3 /* get the saved cr0 bits */ 365 mtcrf 0x80,3 /* and restore */ 366 ori 1,1,0x100 /* set the reference bit */ 367 mtspr SPR_RPA,1 /* set the pte */ 368 srwi 1,1,8 /* get byte 7 of pte */ 369 tlbli 0 /* load the itlb */ 370 stb 1,6(2) /* update page table */ 371 rfi 372 3733: /* not found in pteg */ 374 andi. 1,3,0x40 /* have we already done second hash? */ 375 bne 5f 376 mfspr 2,SPR_HASH2 /* get the second pointer */ 377 ori 3,3,0x40 /* change the compare value */ 378 li 1,8 379 addi 2,2,-8 /* predec pointer */ 380 b 1b 3814: /* guarded */ 382 mfsrr1 3 383 andi. 2,3,0xffff /* clean upper srr1 */ 384 oris 2,2,0x8000000@h /* set srr<4> to flag prot violation */ 385 b 6f 3865: /* not found anywhere */ 387 mfsrr1 3 388 andi. 2,3,0xffff /* clean upper srr1 */ 389 oris 2,2,0x40000000@h /* set srr1<1> to flag pte not found */ 3906: 391 mtctr 0 /* restore counter */ 392 mtsrr1 2 393 mfmsr 0 394 xoris 0,0,0x20000@h /* flip the msr<tgpr> bit */ 395 mtcrf 0x80,3 /* restore cr0 */ 396 mtmsr 0 /* now with native gprs */ 397 isync 398 ba EXC_ISI 399_C_LABEL(tlbimsize) = .-_C_LABEL(tlbimiss) 400 401 .globl _C_LABEL(tlbdlmiss),_C_LABEL(tlbdlmsize) 402_C_LABEL(tlbdlmiss): 403 mfspr 2,SPR_HASH1 /* get first pointer */ 404 li 1,8 405 mfctr 0 /* save counter */ 406 mfspr 3,SPR_DCMP /* get first compare value */ 407 addi 2,2,-8 /* predec pointer */ 4081: 409 mtctr 1 /* load counter */ 4102: 411 lwzu 1,8(2) /* get next pte */ 412 cmpl 0,1,3 /* see if found pte */ 413 bdneq 2b /* loop if not eq */ 414 bne 3f /* not found */ 415 lwz 1,4(2) /* load tlb entry lower word */ 416 mtctr 0 /* restore counter */ 417 mfspr 0,SPR_DMISS /* get the miss address for the tlbld */ 418 mfsrr1 3 /* get the saved cr0 bits */ 419 mtcrf 0x80,3 /* and restore */ 420 ori 1,1,0x100 /* set the reference bit */ 421 mtspr SPR_RPA,1 /* set the pte */ 422 srwi 1,1,8 /* get byte 7 of pte */ 423 tlbld 0 /* load the dtlb */ 424 stb 1,6(2) /* update page table */ 425 rfi 426 4273: /* not found in pteg */ 428 andi. 1,3,0x40 /* have we already done second hash? */ 429 bne 5f 430 mfspr 2,SPR_HASH2 /* get the second pointer */ 431 ori 3,3,0x40 /* change the compare value */ 432 li 1,8 433 addi 2,2,-8 /* predec pointer */ 434 b 1b 4355: /* not found anywhere */ 436 mfsrr1 3 437 lis 1,0x40000000@h /* set dsisr<1> to flag pte not found */ 438 mtctr 0 /* restore counter */ 439 andi. 2,3,0xffff /* clean upper srr1 */ 440 mtsrr1 2 441 mtdsisr 1 /* load the dsisr */ 442 mfspr 1,SPR_DMISS /* get the miss address */ 443 mtdar 1 /* put in dar */ 444 mfmsr 0 445 xoris 0,0,0x20000@h /* flip the msr<tgpr> bit */ 446 mtcrf 0x80,3 /* restore cr0 */ 447 mtmsr 0 /* now with native gprs */ 448 isync 449 ba EXC_DSI 450_C_LABEL(tlbdlmsize) = .-_C_LABEL(tlbdlmiss) 451 452 .globl _C_LABEL(tlbdsmiss),_C_LABEL(tlbdsmsize) 453_C_LABEL(tlbdsmiss): 454 mfspr 2,SPR_HASH1 /* get first pointer */ 455 li 1,8 456 mfctr 0 /* save counter */ 457 mfspr 3,SPR_DCMP /* get first compare value */ 458 addi 2,2,-8 /* predec pointer */ 4591: 460 mtctr 1 /* load counter */ 4612: 462 lwzu 1,8(2) /* get next pte */ 463 cmpl 0,1,3 /* see if found pte */ 464 bdneq 2b /* loop if not eq */ 465 bne 3f /* not found */ 466 lwz 1,4(2) /* load tlb entry lower word */ 467 andi. 3,1,0x80 /* check the C-bit */ 468 beq 4f 4695: 470 mtctr 0 /* restore counter */ 471 mfspr 0,SPR_DMISS /* get the miss address for the tlbld */ 472 mfsrr1 3 /* get the saved cr0 bits */ 473 mtcrf 0x80,3 /* and restore */ 474 mtspr SPR_RPA,1 /* set the pte */ 475 tlbld 0 /* load the dtlb */ 476 rfi 477 4783: /* not found in pteg */ 479 andi. 1,3,0x40 /* have we already done second hash? */ 480 bne 5f 481 mfspr 2,SPR_HASH2 /* get the second pointer */ 482 ori 3,3,0x40 /* change the compare value */ 483 li 1,8 484 addi 2,2,-8 /* predec pointer */ 485 b 1b 4864: /* found, but C-bit = 0 */ 487 rlwinm. 3,1,30,0,1 /* test PP */ 488 bge- 7f 489 andi. 3,1,1 490 beq+ 8f 4919: /* found, but protection violation (PP==00)*/ 492 mfsrr1 3 493 lis 1,0xa000000@h /* indicate protection violation 494 on store */ 495 b 1f 4967: /* found, PP=1x */ 497 mfspr 3,SPR_DMISS /* get the miss address */ 498 mfsrin 1,3 /* get the segment register */ 499 mfsrr1 3 500 rlwinm 3,3,18,31,31 /* get PR-bit */ 501 rlwnm. 2,2,3,1,1 /* get the key */ 502 bne- 9b /* protection violation */ 5038: /* found, set reference/change bits */ 504 lwz 1,4(2) /* reload tlb entry */ 505 ori 1,1,0x180 506 sth 1,6(2) 507 b 5b 5085: /* not found anywhere */ 509 mfsrr1 3 510 lis 1,0x42000000@h /* set dsisr<1> to flag pte not found */ 511 /* dsisr<6> to flag store */ 5121: 513 mtctr 0 /* restore counter */ 514 andi. 2,3,0xffff /* clean upper srr1 */ 515 mtsrr1 2 516 mtdsisr 1 /* load the dsisr */ 517 mfspr 1,SPR_DMISS /* get the miss address */ 518 mtdar 1 /* put in dar */ 519 mfmsr 0 520 xoris 0,0,0x20000@h /* flip the msr<tgpr> bit */ 521 mtcrf 0x80,3 /* restore cr0 */ 522 mtmsr 0 /* now with native gprs */ 523 isync 524 ba EXC_DSI 525_C_LABEL(tlbdsmsize) = .-_C_LABEL(tlbdsmiss) 526 527#if defined(DDB) || defined(KGDB) 528#define ddbsave 0xde0 /* primary save area for DDB */ 529/* 530 * In case of DDB we want a separate trap catcher for it 531 */ 532 .local ddbstk 533 .comm ddbstk,INTSTK,8 /* ddb stack */ 534 535 .globl _C_LABEL(ddblow),_C_LABEL(ddbsize) 536_C_LABEL(ddblow): 537 mtsprg 1,1 /* save SP */ 538 stmw 28,ddbsave(0) /* free r28-r31 */ 539 mflr 28 /* save LR */ 540 mfcr 29 /* save CR */ 541 lis 1,ddbstk+INTSTK@ha /* get new SP */ 542 addi 1,1,ddbstk+INTSTK@l 543 bla ddbtrap 544_C_LABEL(ddbsize) = .-_C_LABEL(ddblow) 545#endif /* DDB | KGDB */ 546 547#ifdef IPKDB 548#define ipkdbsave 0xde0 /* primary save area for IPKDB */ 549/* 550 * In case of IPKDB we want a separate trap catcher for it 551 */ 552 553 .local ipkdbstk 554 .comm ipkdbstk,INTSTK,8 /* ipkdb stack */ 555 556 .globl _C_LABEL(ipkdblow),_C_LABEL(ipkdbsize) 557_C_LABEL(ipkdblow): 558 mtsprg 1,1 /* save SP */ 559 stmw 28,ipkdbsave(0) /* free r28-r31 */ 560 mflr 28 /* save LR */ 561 mfcr 29 /* save CR */ 562 lis 1,ipkdbstk+INTSTK@ha /* get new SP */ 563 addi 1,1,ipkdbstk+INTSTK@l 564 bla ipkdbtrap 565_C_LABEL(ipkdbsize) = .-_C_LABEL(ipkdblow) 566#endif /* IPKDB */ 567 568/* 569 * FRAME_SETUP assumes: 570 * SPRG1 SP (1) 571 * savearea r28-r31,DAR,DSISR (DAR & DSISR only for DSI traps) 572 * 28 LR 573 * 29 CR 574 * 1 kernel stack 575 * LR trap type 576 * SRR0/1 as at start of trap 577 */ 578#define FRAME_SETUP(savearea) \ 579/* Have to enable translation to allow access of kernel stack: */ \ 580 mfsrr0 30; \ 581 mfsrr1 31; \ 582 stmw 30,savearea+24(0); \ 583 mfmsr 30; \ 584 ori 30,30,(PSL_DR|PSL_IR); \ 585 mtmsr 30; \ 586 isync; \ 587 mfsprg 31,1; \ 588 stwu 31,-FRAMELEN(1); \ 589 stw 0,FRAME_0+8(1); \ 590 stw 31,FRAME_1+8(1); \ 591 stw 28,FRAME_LR+8(1); \ 592 stw 29,FRAME_CR+8(1); \ 593 lmw 28,savearea(0); \ 594 stmw 2,FRAME_2+8(1); \ 595 lmw 28,savearea+16(0); \ 596 mfxer 3; \ 597 mfctr 4; \ 598 mflr 5; \ 599 andi. 5,5,0xff00; \ 600 stw 3,FRAME_XER+8(1); \ 601 stw 4,FRAME_CTR+8(1); \ 602 stw 5,FRAME_EXC+8(1); \ 603 stw 28,FRAME_DAR+8(1); \ 604 stw 29,FRAME_DSISR+8(1); \ 605 stw 30,FRAME_SRR0+8(1); \ 606 stw 31,FRAME_SRR1+8(1) 607 608#define FRAME_LEAVE(savearea) \ 609/* Now restore regs: */ \ 610 lwz 2,FRAME_SRR0+8(1); \ 611 lwz 3,FRAME_SRR1+8(1); \ 612 lwz 4,FRAME_CTR+8(1); \ 613 lwz 5,FRAME_XER+8(1); \ 614 lwz 6,FRAME_LR+8(1); \ 615 lwz 7,FRAME_CR+8(1); \ 616 stw 2,savearea(0); \ 617 stw 3,savearea+4(0); \ 618 mtctr 4; \ 619 mtxer 5; \ 620 mtlr 6; \ 621 mtsprg 1,7; /* save cr */ \ 622 lmw 2,FRAME_2+8(1); \ 623 lwz 0,FRAME_0+8(1); \ 624 lwz 1,FRAME_1+8(1); \ 625 mtsprg 2,2; /* save r2 & r3 */ \ 626 mtsprg 3,3; \ 627/* Disable translation, machine check and recoverability: */ \ 628 mfmsr 2; \ 629 andi. 2,2,~(PSL_DR|PSL_IR|PSL_ME|PSL_RI)@l; \ 630 mtmsr 2; \ 631 isync; \ 632/* Decide whether we return to user mode: */ \ 633 lwz 3,savearea+4(0); \ 634 mtcr 3; \ 635 bc 4,17,1f; /* branch if PSL_PR is false */ \ 636/* Restore user & kernel access SR: */ \ 637 mfsprg 2,0; \ 638 lwz 2,PC_CURPMAP(2); \ 639 cmpwi cr4,2,0; /* is curpmap NULL? */ \ 640 bne cr4,2f; \ 641 lis 3,cpassert@ha; /* if it is, panic */ \ 642 addi 3,3,cpassert@l; \ 643 b panic; \ 6442: lwz 3,PM_SR+0(2); \ 645 mtsr 0,3; /* restore SR0 */ \ 646 lwz 3,PM_SR+4(2); \ 647 mtsr 1,3; /* restore SR1 */ \ 648 lwz 3,PM_SR+8(2); \ 649 mtsr 2,3; /* restore SR2 */ \ 650 lwz 3,PM_SR+12(2); \ 651 mtsr 3,3; /* restore SR3 */ \ 652 lwz 3,PM_SR+16(2); \ 653 mtsr 4,3; /* restore SR4 */ \ 654 lwz 3,PM_SR+20(2); \ 655 mtsr 5,3; /* restore SR5 */ \ 656 lwz 3,PM_SR+24(2); \ 657 mtsr 6,3; /* restore SR6 */ \ 658 lwz 3,PM_SR+28(2); \ 659 mtsr 7,3; /* restore SR7 */ \ 660 lwz 3,PM_USRSR(2); \ 661 mtsr USER_SR,3; \ 662 lwz 3,PM_KERNELSR(2); \ 663 mtsr KERNEL_SR,3; \ 6641: mfsprg 2,1; /* restore cr */ \ 665 mtcr 2; \ 666 lwz 2,savearea(0); \ 667 lwz 3,savearea+4(0); \ 668 mtsrr0 2; \ 669 mtsrr1 3; \ 670 mfsprg 2,2; /* restore r2 & r3 */ \ 671 mfsprg 3,3 672 673/* 674 * Preamble code for DSI/ISI traps 675 */ 676disitrap: 677 lmw 30,disisave(0) 678 stmw 30,tempsave(0) 679 lmw 30,disisave+8(0) 680 stmw 30,tempsave+8(0) 681 mfdar 30 682 mfdsisr 31 683 stmw 30,tempsave+16(0) 684realtrap: 685/* Test whether we already had PR set */ 686 mfsrr1 1 687 mtcr 1 688 mfsprg 1,1 /* restore SP (might have been 689 overwritten) */ 690 bc 4,17,s_trap /* branch if PSL_PR is false */ 691 mfsprg 31,0 692 lwz 1,PC_CURPCB(31) 693 addi 1,1,USPACE /* stack is top of user struct */ 694 695/* 696 * Now the common trap catching code. 697 */ 698s_trap: 699/* First have to enable KERNEL mapping */ 700 lis 31,KERNEL_SEGMENT@h 701 ori 31,31,KERNEL_SEGMENT@l 702 mtsr KERNEL_SR,31 703/* Obliterate SRs so BAT spills work correctly */ 704 lis 31,EMPTY_SEGMENT@h 705 ori 31,31,EMPTY_SEGMENT@l 706 mtsr 0,31 707 mtsr 1,31 708 mtsr 2,31 709 mtsr 3,31 710 mtsr 4,31 711 mtsr 5,31 712 mtsr 6,31 713 mtsr 7,31 714 FRAME_SETUP(tempsave) 715/* Now we can recover interrupts again: */ 716 mfmsr 7 717 ori 7,7,(PSL_EE|PSL_ME|PSL_RI)@l 718 mtmsr 7 719 isync 720/* Call C trap code: */ 721trapagain: 722 addi 3,1,8 723 bl _C_LABEL(trap) 724 .globl _C_LABEL(trapexit) 725_C_LABEL(trapexit): 726/* Disable interrupts: */ 727 mfmsr 3 728 andi. 3,3,~PSL_EE@l 729 mtmsr 3 730/* Test AST pending: */ 731 lwz 5,FRAME_SRR1+8(1) 732 mtcr 5 733 bc 4,17,1f /* branch if PSL_PR is false */ 734 lis 3,_C_LABEL(astpending)@ha 735 lwz 4,_C_LABEL(astpending)@l(3) 736 andi. 4,4,1 737 beq 1f 738 li 6,EXC_AST 739 stw 6,FRAME_EXC+8(1) 740 b trapagain 7411: 742 FRAME_LEAVE(tempsave) 743 rfi 744 745/* 746 * DSI second stage fault handler 747 */ 748s_dsitrap: 749 mfdsisr 31 /* test whether this may be a 750 spill fault */ 751 mtcr 31 752 mtsprg 1,1 /* save SP */ 753 bc 4,1,disitrap /* branch if table miss is false */ 754 lis 1,spillstk+SPILLSTK@ha 755 addi 1,1,spillstk+SPILLSTK@l /* get spill stack */ 756 stwu 1,-SPFRAMELEN(1) 757 stw 0,SPFRAME_R0(1) /* save non-volatile registers */ 758 stw 3,SPFRAME_R3(1) 759 stw 4,SPFRAME_R4(1) 760 stw 5,SPFRAME_R5(1) 761 stw 6,SPFRAME_R6(1) 762 stw 7,SPFRAME_R7(1) 763 stw 8,SPFRAME_R8(1) 764 stw 9,SPFRAME_R9(1) 765 stw 10,SPFRAME_R10(1) 766 stw 11,SPFRAME_R11(1) 767 stw 12,SPFRAME_R12(1) 768 mflr 30 /* save trap type */ 769 mfctr 31 /* & CTR */ 770 mfdar 3 771s_pte_spill: 772 bl _C_LABEL(pmap_pte_spill) /* try a spill */ 773 or. 3,3,3 774 mtctr 31 /* restore CTR */ 775 mtlr 30 /* and trap type */ 776 mfsprg 31,2 /* get saved XER */ 777 mtxer 31 /* restore XER */ 778 lwz 12,SPFRAME_R12(1) /* restore non-volatile registers */ 779 lwz 11,SPFRAME_R11(1) 780 lwz 10,SPFRAME_R10(1) 781 lwz 9,SPFRAME_R9(1) 782 lwz 8,SPFRAME_R8(1) 783 lwz 7,SPFRAME_R7(1) 784 lwz 6,SPFRAME_R6(1) 785 lwz 5,SPFRAME_R5(1) 786 lwz 4,SPFRAME_R4(1) 787 lwz 3,SPFRAME_R3(1) 788 lwz 0,SPFRAME_R0(1) 789 beq disitrap 790 mfsprg 1,1 /* restore SP */ 791 mtcr 29 /* restore CR */ 792 mtlr 28 /* restore LR */ 793 lmw 28,disisave(0) /* restore r28-r31 */ 794 rfi /* return to trapped code */ 795 796/* 797 * ISI second stage fault handler 798 */ 799s_isitrap: 800 mfsrr1 31 /* test whether this may be a 801 spill fault */ 802 mtcr 31 803 mtsprg 1,1 /* save SP */ 804 bc 4,1,disitrap /* branch if table miss is false */ 805 lis 1,spillstk+SPILLSTK@ha 806 addi 1,1,spillstk+SPILLSTK@l /* get spill stack */ 807 stwu 1,-SPFRAMELEN(1) 808 stw 0,SPFRAME_R0(1) /* save non-volatile registers */ 809 stw 3,SPFRAME_R3(1) 810 stw 4,SPFRAME_R4(1) 811 stw 5,SPFRAME_R5(1) 812 stw 6,SPFRAME_R6(1) 813 stw 7,SPFRAME_R7(1) 814 stw 8,SPFRAME_R8(1) 815 stw 9,SPFRAME_R9(1) 816 stw 10,SPFRAME_R10(1) 817 stw 11,SPFRAME_R11(1) 818 stw 12,SPFRAME_R12(1) 819 mfxer 30 /* save XER */ 820 mtsprg 2,30 821 mflr 30 /* save trap type */ 822 mfctr 31 /* & ctr */ 823 mfsrr0 3 824 b s_pte_spill /* above */ 825 826/* 827 * External interrupt second level handler 828 */ 829#define INTRENTER \ 830/* Save non-volatile registers: */ \ 831 stwu 1,-IFRAMELEN(1); /* temporarily */ \ 832 stw 0,IFRAME_R0(1); \ 833 mfsprg 0,1; /* get original SP */ \ 834 stw 0,IFRAME_R1(1); /* and store it */ \ 835 stw 3,IFRAME_R3(1); \ 836 stw 4,IFRAME_R4(1); \ 837 stw 5,IFRAME_R5(1); \ 838 stw 6,IFRAME_R6(1); \ 839 stw 7,IFRAME_R7(1); \ 840 stw 8,IFRAME_R8(1); \ 841 stw 9,IFRAME_R9(1); \ 842 stw 10,IFRAME_R10(1); \ 843 stw 11,IFRAME_R11(1); \ 844 stw 12,IFRAME_R12(1); \ 845 stw 28,IFRAME_LR(1); /* saved LR */ \ 846 stw 29,IFRAME_CR(1); /* saved CR */ \ 847 stw 30,IFRAME_XER(1); /* saved XER */ \ 848 lmw 28,tempsave(0); /* restore r28-r31 */ \ 849 mfctr 6; \ 850 lis 5,_C_LABEL(intr_depth)@ha; \ 851 lwz 5,_C_LABEL(intr_depth)@l(5); \ 852 mfsrr0 4; \ 853 mfsrr1 3; \ 854 stw 6,IFRAME_CTR(1); \ 855 stw 5,IFRAME_INTR_DEPTH(1); \ 856 stw 4,IFRAME_SRR0(1); \ 857 stw 3,IFRAME_SRR1(1); \ 858 mtcr 3; \ 859 bc 4,17,99f; /* branch if PSL_PR is false */ \ 860 lis 3,EMPTY_SEGMENT@h; \ 861 ori 3,3,EMPTY_SEGMENT@l; \ 862 mtsr 0,3; /* reset SRs so BAT spills work */ \ 863 mtsr 1,3; \ 864 mtsr 2,3; \ 865 mtsr 3,3; \ 866 mtsr 4,3; \ 867 mtsr 5,3; \ 868 mtsr 6,3; \ 869 mtsr 7,3; \ 870/* interrupts are recoverable here, and enable translation */ \ 871 lis 3,(KERNEL_SEGMENT|SR_KS|SR_KP)@h; \ 872 ori 3,3,(KERNEL_SEGMENT|SR_KS|SR_KP)@l; \ 873 mtsr KERNEL_SR,3; \ 87499: mfmsr 5; \ 875 ori 5,5,(PSL_IR|PSL_DR|PSL_RI); \ 876 mtmsr 5; \ 877 isync 878 879 .globl _C_LABEL(extint_call) 880extintr: 881 INTRENTER 882_C_LABEL(extint_call): 883 bl _C_LABEL(extint_call) /* to be filled in later */ 884 885intr_exit: 886/* Disable interrupts (should already be disabled) and MMU here: */ 887 mfmsr 3 888 andi. 3,3,~(PSL_EE|PSL_ME|PSL_RI|PSL_DR|PSL_IR)@l 889 mtmsr 3 890 isync 891/* restore possibly overwritten registers: */ 892 lwz 12,IFRAME_R12(1) 893 lwz 11,IFRAME_R11(1) 894 lwz 10,IFRAME_R10(1) 895 lwz 9,IFRAME_R9(1) 896 lwz 8,IFRAME_R8(1) 897 lwz 7,IFRAME_R7(1) 898 lwz 6,IFRAME_SRR1(1) 899 lwz 5,IFRAME_SRR0(1) 900 lwz 4,IFRAME_CTR(1) 901 lwz 3,IFRAME_XER(1) 902 mtsrr1 6 903 mtsrr0 5 904 mtctr 4 905 mtxer 3 906/* Returning to user mode? */ 907 mtcr 6 /* saved SRR1 */ 908 bc 4,17,1f /* branch if PSL_PR is false */ 909 mfsprg 31,0 910 lwz 3,PC_CURPMAP(31) 911 lwz 4,PM_SR+0(3) 912 mtsr 0,4 /* Restore SR0 */ 913 lwz 4,PM_SR+4(3) 914 mtsr 1,4 /* Restore SR1 */ 915 lwz 4,PM_SR+8(3) 916 mtsr 2,4 /* Restore SR2 */ 917 lwz 4,PM_SR+12(3) 918 mtsr 3,4 /* Restore SR3 */ 919 lwz 4,PM_SR+16(3) 920 mtsr 4,4 /* Restore SR4 */ 921 lwz 4,PM_SR+20(3) 922 mtsr 5,4 /* Restore SR5 */ 923 lwz 4,PM_SR+24(3) 924 mtsr 6,4 /* Restore SR6 */ 925 lwz 4,PM_SR+28(3) 926 mtsr 7,4 /* Restore SR7 */ 927 lwz 3,PM_KERNELSR(3) 928 mtsr KERNEL_SR,3 /* Restore kernel SR */ 929 lis 3,_C_LABEL(astpending)@ha /* Test AST pending */ 930 lwz 4,_C_LABEL(astpending)@l(3) 931 andi. 4,4,1 932 beq 1f 933/* Setup for entry to realtrap: */ 934 lwz 3,IFRAME_R1(1) /* get saved SP */ 935 mtsprg 1,3 936 li 6,EXC_AST 937 stmw 28,tempsave(0) /* establish tempsave again */ 938 mtlr 6 939 lwz 28,IFRAME_LR(1) /* saved LR */ 940 lwz 29,IFRAME_CR(1) /* saved CR */ 941 lwz 6,IFRAME_R6(1) 942 lwz 5,IFRAME_R5(1) 943 lwz 4,IFRAME_R4(1) 944 lwz 3,IFRAME_R3(1) 945 lwz 0,IFRAME_R0(1) 946 lis 30,_C_LABEL(intr_depth)@ha /* adjust reentrancy count */ 947 lwz 31,_C_LABEL(intr_depth)@l(30) 948 addi 31,31,-1 949 stw 31,_C_LABEL(intr_depth)@l(30) 950 b realtrap 9511: 952/* Here is the normal exit of extintr: */ 953 lwz 5,IFRAME_CR(1) 954 lwz 6,IFRAME_LR(1) 955 mtcr 5 956 mtlr 6 957 lwz 6,IFRAME_R6(1) 958 lwz 5,IFRAME_R5(1) 959 lis 3,_C_LABEL(intr_depth)@ha /* adjust reentrancy count */ 960 lwz 4,_C_LABEL(intr_depth)@l(3) 961 addi 4,4,-1 962 stw 4,_C_LABEL(intr_depth)@l(3) 963 lwz 4,IFRAME_R4(1) 964 lwz 3,IFRAME_R3(1) 965 lwz 0,IFRAME_R0(1) 966 lwz 1,IFRAME_R1(1) 967 rfi 968 969/* 970 * Decrementer interrupt second level handler 971 */ 972decrintr: 973 INTRENTER 974 addi 3,1,8 /* intr frame -> clock frame */ 975 bl _C_LABEL(decr_intr) 976 b intr_exit 977 978#if defined(DDB) 979/* 980 * Deliberate entry to ddbtrap 981 */ 982 .globl _C_LABEL(ddb_trap) 983_C_LABEL(ddb_trap): 984 mtsprg 1,1 985 mfmsr 3 986 mtsrr1 3 987 andi. 3,3,~(PSL_EE|PSL_ME)@l 988 mtmsr 3 /* disable interrupts */ 989 isync 990 stmw 28,ddbsave(0) 991 mflr 28 992 li 29,EXC_BPT 993 mtlr 29 994 mfcr 29 995 mtsrr0 28 996#endif /* DDB */ 997 998#if defined(DDB) || defined(KGDB) 999/* 1000 * Now the ddb trap catching code. 1001 */ 1002ddbtrap: 1003 FRAME_SETUP(ddbsave) 1004/* Call C trap code: */ 1005 addi 3,1,8 1006 bl _C_LABEL(ddb_trap_glue) 1007 or. 3,3,3 1008 bne ddbleave 1009/* This wasn't for DDB, so switch to real trap: */ 1010 lwz 3,FRAME_EXC+8(1) /* save exception */ 1011 stw 3,ddbsave+8(0) 1012 FRAME_LEAVE(ddbsave) 1013 mtsprg 1,1 /* prepare for entrance to realtrap */ 1014 stmw 28,tempsave(0) 1015 mflr 28 1016 mfcr 29 1017 lwz 31,ddbsave+8(0) 1018 mtlr 31 1019 b realtrap 1020ddbleave: 1021 FRAME_LEAVE(ddbsave) 1022 rfi 1023#endif /* DDB || KGDB */ 1024 1025#ifdef IPKDB 1026/* 1027 * Deliberate entry to ipkdbtrap 1028 */ 1029 .globl _C_LABEL(ipkdb_trap) 1030_C_LABEL(ipkdb_trap): 1031 mtsprg 1,1 1032 mfmsr 3 1033 mtsrr1 3 1034 andi. 3,3,~(PSL_EE|PSL_ME)@l 1035 mtmsr 3 /* disable interrupts */ 1036 isync 1037 stmw 28,ipkdbsave(0) 1038 mflr 28 1039 li 29,EXC_BPT 1040 mtlr 29 1041 mfcr 29 1042 mtsrr0 28 1043 1044/* 1045 * Now the ipkdb trap catching code. 1046 */ 1047ipkdbtrap: 1048 FRAME_SETUP(ipkdbsave) 1049/* Call C trap code: */ 1050 addi 3,1,8 1051 bl _C_LABEL(ipkdb_trap_glue) 1052 or. 3,3,3 1053 bne ipkdbleave 1054/* This wasn't for IPKDB, so switch to real trap: */ 1055 lwz 3,FRAME_EXC+8(1) /* save exception */ 1056 stw 3,ipkdbsave+8(0) 1057 FRAME_LEAVE(ipkdbsave) 1058 mtsprg 1,1 /* prepare for entrance to realtrap */ 1059 stmw 28,tempsave(0) 1060 mflr 28 1061 mfcr 29 1062 lwz 31,ipkdbsave+8(0) 1063 mtlr 31 1064 b realtrap 1065ipkdbleave: 1066 FRAME_LEAVE(ipkdbsave) 1067 rfi 1068 1069ipkdbfault: 1070 ba _ipkdbfault 1071_ipkdbfault: 1072 mfsrr0 3 1073 addi 3,3,4 1074 mtsrr0 3 1075 li 3,-1 1076 rfi 1077 1078/* 1079 * int ipkdbfbyte(unsigned char *p) 1080 */ 1081 .globl _C_LABEL(ipkdbfbyte) 1082_C_LABEL(ipkdbfbyte): 1083 li 9,EXC_DSI /* establish new fault routine */ 1084 lwz 5,0(9) 1085 lis 6,ipkdbfault@ha 1086 lwz 6,ipkdbfault@l(6) 1087 stw 6,0(9) 1088#ifdef IPKDBUSERHACK 1089 lis 8,_C_LABEL(ipkdbsr)@ha 1090 lwz 8,_C_LABEL(ipkdbsr)@l(8) 1091 mtsr USER_SR,8 1092 isync 1093#endif 1094 dcbst 0,9 /* flush data... */ 1095 sync 1096 icbi 0,9 /* and instruction caches */ 1097 lbz 3,0(3) /* fetch data */ 1098 stw 5,0(9) /* restore previous fault handler */ 1099 dcbst 0,9 /* and flush data... */ 1100 sync 1101 icbi 0,9 /* and instruction caches */ 1102 blr 1103 1104/* 1105 * int ipkdbsbyte(unsigned char *p, int c) 1106 */ 1107 .globl _C_LABEL(ipkdbsbyte) 1108_C_LABEL(ipkdbsbyte): 1109 li 9,EXC_DSI /* establish new fault routine */ 1110 lwz 5,0(9) 1111 lis 6,ipkdbfault@ha 1112 lwz 6,ipkdbfault@l(6) 1113 stw 6,0(9) 1114#ifdef IPKDBUSERHACK 1115 lis 8,_C_LABEL(ipkdbsr)@ha 1116 lwz 8,_C_LABEL(ipkdbsr)@l(8) 1117 mtsr USER_SR,8 1118 isync 1119#endif 1120 dcbst 0,9 /* flush data... */ 1121 sync 1122 icbi 0,9 /* and instruction caches */ 1123 mr 6,3 1124 xor 3,3,3 1125 stb 4,0(6) 1126 dcbst 0,6 /* Now do appropriate flushes 1127 to data... */ 1128 sync 1129 icbi 0,6 /* and instruction caches */ 1130 stw 5,0(9) /* restore previous fault handler */ 1131 dcbst 0,9 /* and flush data... */ 1132 sync 1133 icbi 0,9 /* and instruction caches */ 1134 blr 1135#endif /* IPKDB */ 1136