1/* $FreeBSD$ */ 2/* $NetBSD: locore.S,v 1.24 2000/05/31 05:09:17 thorpej Exp $ */ 3 4/* 5 * Copyright (C) 2001 Benno Rice 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY Benno Rice ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 23 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 25 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 26 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28/* 29 * Copyright (C) 1995, 1996 Wolfgang Solfrank. 30 * Copyright (C) 1995, 1996 TooLs GmbH. 31 * All rights reserved. 32 * 33 * Redistribution and use in source and binary forms, with or without 34 * modification, are permitted provided that the following conditions 35 * are met: 36 * 1. Redistributions of source code must retain the above copyright 37 * notice, this list of conditions and the following disclaimer. 38 * 2. Redistributions in binary form must reproduce the above copyright 39 * notice, this list of conditions and the following disclaimer in the 40 * documentation and/or other materials provided with the distribution. 41 * 3. All advertising materials mentioning features or use of this software 42 * must display the following acknowledgement: 43 * This product includes software developed by TooLs GmbH. 44 * 4. The name of TooLs GmbH may not be used to endorse or promote products 45 * derived from this software without specific prior written permission. 46 * 47 * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR 48 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 49 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 50 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 51 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 52 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 53 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 54 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 55 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 56 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 57 */ 58 59#include "opt_ddb.h" 60#include "opt_ipkdb.h" 61#include "assym.s" 62 63#include <sys/syscall.h> 64 65#include <machine/trap.h> 66#include <machine/param.h> 67#include <machine/pmap.h> 68#include <machine/psl.h> 69#include <machine/asm.h> 70 71/* 72 * Some instructions gas doesn't understand (yet?) 73 */ 74#define bdneq bdnzf 2, 75 76/* 77 * Globals 78 */ 79 .data 80GLOBAL(tmpstk) 81 .space 8208 82GLOBAL(esym) 83 .long 0 /* end of symbol table */ 84GLOBAL(proc0paddr) 85 .long 0 /* proc0 p_addr */ 86GLOBAL(PTmap) 87 .long 0 /* PTmap */ 88 89GLOBAL(intrnames) 90 .asciz "irq0", "irq1", "irq2", "irq3" 91 .asciz "irq4", "irq5", "irq6", "irq7" 92 .asciz "irq8", "irq9", "irq10", "irq11" 93 .asciz "irq12", "irq13", "irq14", "irq15" 94 .asciz "irq16", "irq17", "irq18", "irq19" 95 .asciz "irq20", "irq21", "irq22", "irq23" 96 .asciz "irq24", "irq25", "irq26", "irq27" 97 .asciz "irq28", "irq29", "irq30", "irq31" 98 .asciz "irq32", "irq33", "irq34", "irq35" 99 .asciz "irq36", "irq37", "irq38", "irq39" 100 .asciz "irq40", "irq41", "irq42", "irq43" 101 .asciz "irq44", "irq45", "irq46", "irq47" 102 .asciz "irq48", "irq49", "irq50", "irq51" 103 .asciz "irq52", "irq53", "irq54", "irq55" 104 .asciz "irq56", "irq57", "irq58", "irq59" 105 .asciz "irq60", "irq61", "irq62", "irq63" 106 .asciz "clock", "softclock", "softnet", "softserial" 107GLOBAL(eintrnames) 108 .align 4 109GLOBAL(intrcnt) 110 .long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 111 .long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 112 .long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 113 .long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 114 .long 0,0,0,0 115GLOBAL(eintrcnt) 116 117GLOBAL(ofmsr) 118 .long 0 /* msr used in Open Firmware */ 119 120GLOBAL(powersave) 121 .long 0 122 123/* 124 * File-scope for locore.S 125 */ 126idle_u: 127 .long 0 /* fake uarea during idle after exit */ 128openfirmware_entry: 129 .long 0 /* openfirmware entry point */ 130srsave: 131 .long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 132 133/* 134 * This symbol is here for the benefit of kvm_mkdb, and is supposed to 135 * mark the start of kernel text. 136 */ 137 .text 138 .globl kernel_text 139kernel_text: 140 141/* 142 * Startup entry. Note, this must be the first thing in the text 143 * segment! 144 */ 145 .text 146 .globl __start 147__start: 148#ifdef FIRMWORKSBUGS 149 mfmsr 0 150 andi. 0,0,PSL_IR|PSL_DR 151 beq 1f 152 153 bl ofwr_init 1541: 155#endif 156 li 8,0 157 li 9,0x100 158 mtctr 9 1591: 160 dcbf 0,8 161 icbi 0,8 162 addi 8,8,0x20 163 bdnz 1b 164 sync 165 isync 166 167 mtibatu 0,0 168 mtibatu 1,0 169 mtibatu 2,0 170 mtibatu 3,0 171 mtdbatu 0,0 172 mtdbatu 1,0 173 mtdbatu 2,0 174 mtdbatu 3,0 175 176 li 9,0x12 177 mtibatl 0,9 178 mtdbatl 0,9 179 li 9,0x1ffe 180 mtibatu 0,9 181 mtdbatu 0,9 182 isync 183 184 lis 8,openfirmware_entry@ha 185 stw 5,openfirmware_entry@l(8) /* save client interface handler */ 186 mr 3,5 187 188 lis 1,tmpstk@ha 189 addi 1,1,tmpstk@l 190 addi 1,1,8192 191 192 mfmsr 0 193 lis 9,ofmsr@ha 194 stw 0,ofmsr@l(9) 195 196 bl OF_init 197 198 lis 4,end@ha 199 addi 4,4,end@l 200 mr 5,4 201 li 9,PAGE_MASK 202 add 4,4,9 203 andc 4,4,9 204 lis 9,OF_buf@ha 205 stw 4,OF_buf@l(9) 206 addi 4,4,PAGE_SIZE 207 lis 9,proc0paddr@ha 208 stw 4,proc0paddr@l(9) 209 addi 4,4,USPACE-FRAMELEN 210 mr 1,4 211 xor 0,0,0 212 stwu 0,-16(1) 213 214 lis 3,kernel_text@ha 215 addi 3,3,kernel_text@l 216#if 0 217 mr 5,6 218#endif 219 220 bl powerpc_init 221 bl mi_startup 222 b OF_exit 223 224#if 0 /* XXX: We may switch back to this in the future. */ 225/* 226 * OpenFirmware entry point 227 */ 228ENTRY(openfirmware) 229 mflr 0 /* save return address */ 230 stw 0,4(1) 231 stwu 1,-16(1) /* setup stack frame */ 232 233 mfmsr 4 /* save msr */ 234 stw 4,8(1) 235 236 lis 4,openfirmware_entry@ha /* get firmware entry point */ 237 lwz 4,openfirmware_entry@l(4) 238 mtlr 4 239 240 li 0,0 /* clear battable translations */ 241 mtdbatu 2,0 242 mtdbatu 3,0 243 mtibatu 2,0 244 mtibatu 3,0 245 246 lis 4,ofmsr@ha /* Open Firmware msr */ 247 lwz 4,ofmsr@l(4) 248 mtmsr 4 249 isync 250 251 lis 4,srsave@ha /* save old SR */ 252 addi 4,4,srsave@l 253 li 5,0 2541: mfsrin 0,5 255 stw 0,0(4) 256 addi 4,4,4 257 addis 5,5,0x10000000@h 258 cmpwi 5,0 259 bne 1b 260 261 lis 4,ofw_pmap@ha /* load OFW SR */ 262 addi 4,4,ofw_pmap@l 263 lwz 0,PM_KERNELSR(4) 264 cmpwi 0,0 /* pm_sr[KERNEL_SR] == 0? */ 265 beq 2f /* then skip (not initialized yet) */ 266 li 5,0 2671: lwz 0,0(4) 268 mtsrin 0,5 269 addi 4,4,4 270 addis 5,5,0x10000000@h 271 cmpwi 5,0 272 bne 1b 2732: 274 blrl /* call Open Firmware */ 275 276 mfmsr 4 277 li 5,PSL_IR|PSL_DR 278 andc 4,4,5 279 mtmsr 4 280 isync 281 282 lis 4,srsave@ha /* restore saved SR */ 283 addi 4,4,srsave@l 284 li 5,0 2851: lwz 0,0(4) 286 mtsrin 0,5 287 addi 4,4,4 288 addis 5,5,0x10000000@h 289 cmpwi 5,0 290 bne 1b 291 292 lwz 4,8(1) /* restore msr */ 293 mtmsr 4 294 isync 295 296 lwz 1,0(1) /* and return */ 297 lwz 0,4(1) 298 mtlr 0 299 blr 300#endif 301 302/* 303 * Switch to/from OpenFirmware real mode stack 304 * 305 * Note: has to be called as the very first thing in OpenFirmware interface 306 * routines. 307 * E.g.: 308 * int 309 * OF_xxx(arg1, arg2) 310 * type arg1, arg2; 311 * { 312 * static struct { 313 * char *name; 314 * int nargs; 315 * int nreturns; 316 * char *method; 317 * int arg1; 318 * int arg2; 319 * int ret; 320 * } args = { 321 * "xxx", 322 * 2, 323 * 1, 324 * }; 325 * 326 * ofw_stack(); 327 * args.arg1 = arg1; 328 * args.arg2 = arg2; 329 * if (openfirmware(&args) < 0) 330 * return -1; 331 * return args.ret; 332 * } 333 */ 334 335 .local firmstk 336 .comm firmstk,PAGE_SIZE,8 337 338ENTRY(ofw_stack) 339 mfmsr 8 /* turn off interrupts */ 340 andi. 0,8,~(PSL_EE|PSL_RI)@l 341 mtmsr 0 342 stw 8,4(1) /* abuse return address slot */ 343 344 lwz 5,0(1) /* get length of stack frame */ 345 subf 5,1,5 346 347 lis 7,firmstk+PAGE_SIZE-8@ha 348 addi 7,7,firmstk+PAGE_SIZE-8@l 349 lis 6,ofw_back@ha 350 addi 6,6,ofw_back@l 351 subf 4,5,7 /* make room for stack frame on 352 new stack */ 353 stw 6,-4(7) /* setup return pointer */ 354 stwu 1,-8(7) 355 356 stw 7,-8(4) 357 358 addi 3,1,8 359 addi 1,4,-8 360 subi 5,5,8 361 362 cmpw 3,4 363 beqlr 364 365 mr 0,5 366 addi 5,5,-1 367 cmpwi 0,0 368 beqlr 369 3701: lwz 0,0(3) 371 stw 0,0(4) 372 addi 3,3,1 373 addi 4,4,1 374 mr 0,5 375 addi 5,5,-1 376 cmpwi 0,0 377 bne 1b 378 blr 379 380ofw_back: 381 lwz 1,0(1) /* get callers original stack pointer */ 382 383 lwz 0,4(1) /* get saved msr from abused slot */ 384 mtmsr 0 385 386 lwz 1,0(1) /* return */ 387 lwz 0,4(1) 388 mtlr 0 389 blr 390 391/* 392 * Data used during primary/secondary traps/interrupts 393 */ 394#define tempsave 0x2e0 /* primary save area for trap handling */ 395#define disisave 0x3e0 /* primary save area for dsi/isi traps */ 396 397#define INTSTK (8*1024) /* 8K interrupt stack */ 398 .data 399 .align 4 400intstk: 401 .space INTSTK /* interrupt stack */ 402 403GLOBAL(intr_depth) 404 .long -1 /* in-use marker */ 405 406#define SPILLSTK 1024 /* 1K spill stack */ 407 408 .comm spillstk,SPILLSTK,8 409 410/* 411 * This code gets copied to all the trap vectors 412 * (except ISI/DSI, ALI, the interrupts, and possibly the debugging 413 * traps when using IPKDB). 414 */ 415 .text 416 .globl trapcode,trapsize 417trapcode: 418 mtsprg 1,1 /* save SP */ 419 stmw 28,tempsave(0) /* free r28-r31 */ 420 mflr 28 /* save LR */ 421 mfcr 29 /* save CR */ 422/* Test whether we already had PR set */ 423 mfsrr1 31 424 mtcr 31 425 bc 4,17,1f /* branch if PSL_PR is clear */ 426 mfsprg 1,0 427 lwz 1,GD_CURPCB(1) 428 addi 1,1,USPACE /* stack is top of user struct */ 4291: 430 bla s_trap 431trapsize = .-trapcode 432 433/* 434 * For ALI: has to save DSISR and DAR 435 */ 436 .globl alitrap,alisize 437alitrap: 438 mtsprg 1,1 /* save SP */ 439 stmw 28,tempsave(0) /* free r28-r31 */ 440 mfdar 30 441 mfdsisr 31 442 stmw 30,tempsave+16(0) 443 mflr 28 /* save LR */ 444 mfcr 29 /* save CR */ 445/* Test whether we already had PR set */ 446 mfsrr1 31 447 mtcr 31 448 bc 4,17,1f /* branch if PSL_PR is clear */ 449 mfsprg 1,0 450 lwz 1,GD_CURPCB(1) 451 addi 1,1,USPACE /* stack is top of user struct */ 4521: 453 bla s_trap 454alisize = .-alitrap 455 456/* 457 * Similar to the above for DSI 458 * Has to handle BAT spills 459 * and standard pagetable spills 460 */ 461 .globl dsitrap,dsisize 462dsitrap: 463 stmw 28,disisave(0) /* free r28-r31 */ 464 mfcr 29 /* save CR */ 465 mfxer 30 /* save XER */ 466 mtsprg 2,30 /* in SPRG2 */ 467 mfsrr1 31 /* test kernel mode */ 468 mtcr 31 469 bc 12,17,1f /* branch if PSL_PR is set */ 470 mfdar 31 /* get fault address */ 471 rlwinm 31,31,7,25,28 /* get segment * 8 */ 472 473 /* get batu */ 474 addis 31,31,battable@ha 475 lwz 30,battable@l(31) 476 mtcr 30 477 bc 4,30,1f /* branch if supervisor valid is 478 false */ 479 /* get batl */ 480 lwz 31,battable+4@l(31) 481/* We randomly use the highest two bat registers here */ 482 mftb 28 483 andi. 28,28,1 484 bne 2f 485 mtdbatu 2,30 486 mtdbatl 2,31 487 b 3f 4882: 489 mtdbatu 3,30 490 mtdbatl 3,31 4913: 492 mfsprg 30,2 /* restore XER */ 493 mtxer 30 494 mtcr 29 /* restore CR */ 495 lmw 28,disisave(0) /* restore r28-r31 */ 496 rfi /* return to trapped code */ 4971: 498 mflr 28 /* save LR */ 499 bla s_dsitrap 500dsisize = .-dsitrap 501 502/* 503 * Similar to the above for ISI 504 */ 505 .globl isitrap,isisize 506isitrap: 507 stmw 28,disisave(0) /* free r28-r31 */ 508 mflr 28 /* save LR */ 509 mfcr 29 /* save CR */ 510 mfsrr1 31 /* test kernel mode */ 511 mtcr 31 512 bc 12,17,1f /* branch if PSL_PR is set */ 513 mfsrr0 31 /* get fault address */ 514 rlwinm 31,31,7,25,28 /* get segment * 8 */ 515 516 /* get batu */ 517 addis 31,31,battable@ha 518 lwz 30,battable@l(31) 519 mtcr 30 520 bc 4,30,1f /* branch if supervisor valid is 521 false */ 522 mtibatu 3,30 523 524 /* get batl */ 525 lwz 30,battable+4@l(31) 526 mtibatl 3,30 527 528 mtcr 29 /* restore CR */ 529 lmw 28,disisave(0) /* restore r28-r31 */ 530 rfi /* return to trapped code */ 5311: 532 bla s_isitrap 533isisize = .-isitrap 534 535/* 536 * This one for the external interrupt handler. 537 */ 538 .globl extint,extsize 539extint: 540 mtsprg 1,1 /* save SP */ 541 stmw 28,tempsave(0) /* free r28-r31 */ 542 mflr 28 /* save LR */ 543 mfcr 29 /* save CR */ 544 mfxer 30 /* save XER */ 545 lis 1,intstk+INTSTK@ha /* get interrupt stack */ 546 addi 1,1,intstk+INTSTK@l 547 lwz 31,0(1) /* were we already running on intstk? */ 548 addic. 31,31,1 549 stw 31,0(1) 550 beq 1f 551 mfsprg 1,1 /* yes, get old SP */ 5521: 553 ba extintr 554extsize = .-extint 555 556/* 557 * And this one for the decrementer interrupt handler. 558 */ 559 .globl decrint,decrsize 560decrint: 561 mtsprg 1,1 /* save SP */ 562 stmw 28,tempsave(0) /* free r28-r31 */ 563 mflr 28 /* save LR */ 564 mfcr 29 /* save CR */ 565 mfxer 30 /* save XER */ 566 lis 1,intstk+INTSTK@ha /* get interrupt stack */ 567 addi 1,1,intstk+INTSTK@l 568 lwz 31,0(1) /* were we already running on intstk? */ 569 addic. 31,31,1 570 stw 31,0(1) 571 beq 1f 572 mfsprg 1,1 /* yes, get old SP */ 5731: 574 ba decrintr 575decrsize = .-decrint 576 577/* 578 * Now the tlb software load for 603 processors: 579 * (Code essentially from the 603e User Manual, Chapter 5, but 580 * corrected a lot.) 581 */ 582#define DMISS 976 583#define DCMP 977 584#define HASH1 978 585#define HASH2 979 586#define IMISS 980 587#define ICMP 981 588#define RPA 982 589 590 .globl tlbimiss,tlbimsize 591tlbimiss: 592 mfspr 2,HASH1 /* get first pointer */ 593 li 1,8 594 mfctr 0 /* save counter */ 595 mfspr 3,ICMP /* get first compare value */ 596 addi 2,2,-8 /* predec pointer */ 5971: 598 mtctr 1 /* load counter */ 5992: 600 lwzu 1,8(2) /* get next pte */ 601 cmpl 0,1,3 /* see if found pte */ 602 bdneq 2b /* loop if not eq */ 603 bne 3f /* not found */ 604 lwz 1,4(2) /* load tlb entry lower word */ 605 andi. 3,1,8 /* check G-bit */ 606 bne 4f /* if guarded, take ISI */ 607 mtctr 0 /* restore counter */ 608 mfspr 0,IMISS /* get the miss address for the tlbli */ 609 mfsrr1 3 /* get the saved cr0 bits */ 610 mtcrf 0x80,3 /* and restore */ 611 ori 1,1,0x100 /* set the reference bit */ 612 mtspr RPA,1 /* set the pte */ 613 srwi 1,1,8 /* get byte 7 of pte */ 614 tlbli 0 /* load the itlb */ 615 stb 1,6(2) /* update page table */ 616 rfi 617 6183: /* not found in pteg */ 619 andi. 1,3,0x40 /* have we already done second hash? */ 620 bne 5f 621 mfspr 2,HASH2 /* get the second pointer */ 622 ori 3,3,0x40 /* change the compare value */ 623 li 1,8 624 addi 2,2,-8 /* predec pointer */ 625 b 1b 6264: /* guarded */ 627 mfsrr1 3 628 andi. 2,3,0xffff /* clean upper srr1 */ 629 oris 2,2,0x8000000@h /* set srr<4> to flag prot violation */ 630 b 6f 6315: /* not found anywhere */ 632 mfsrr1 3 633 andi. 2,3,0xffff /* clean upper srr1 */ 634 oris 2,2,0x40000000@h /* set srr1<1> to flag pte not found */ 6356: 636 mtctr 0 /* restore counter */ 637 mtsrr1 2 638 mfmsr 0 639 xoris 0,0,0x20000@h /* flip the msr<tgpr> bit */ 640 mtcrf 0x80,3 /* restore cr0 */ 641 mtmsr 0 /* now with native gprs */ 642 isync 643 ba EXC_ISI 644tlbimsize = .-tlbimiss 645 646 .globl tlbdlmiss,tlbdlmsize 647tlbdlmiss: 648 mfspr 2,HASH1 /* get first pointer */ 649 li 1,8 650 mfctr 0 /* save counter */ 651 mfspr 3,DCMP /* get first compare value */ 652 addi 2,2,-8 /* predec pointer */ 6531: 654 mtctr 1 /* load counter */ 6552: 656 lwzu 1,8(2) /* get next pte */ 657 cmpl 0,1,3 /* see if found pte */ 658 bdneq 2b /* loop if not eq */ 659 bne 3f /* not found */ 660 lwz 1,4(2) /* load tlb entry lower word */ 661 mtctr 0 /* restore counter */ 662 mfspr 0,DMISS /* get the miss address for the tlbld */ 663 mfsrr1 3 /* get the saved cr0 bits */ 664 mtcrf 0x80,3 /* and restore */ 665 ori 1,1,0x100 /* set the reference bit */ 666 mtspr RPA,1 /* set the pte */ 667 srwi 1,1,8 /* get byte 7 of pte */ 668 tlbld 0 /* load the dtlb */ 669 stb 1,6(2) /* update page table */ 670 rfi 671 6723: /* not found in pteg */ 673 andi. 1,3,0x40 /* have we already done second hash? */ 674 bne 5f 675 mfspr 2,HASH2 /* get the second pointer */ 676 ori 3,3,0x40 /* change the compare value */ 677 li 1,8 678 addi 2,2,-8 /* predec pointer */ 679 b 1b 6805: /* not found anywhere */ 681 mfsrr1 3 682 lis 1,0x40000000@h /* set dsisr<1> to flag pte not found */ 683 mtctr 0 /* restore counter */ 684 andi. 2,3,0xffff /* clean upper srr1 */ 685 mtsrr1 2 686 mtdsisr 1 /* load the dsisr */ 687 mfspr 1,DMISS /* get the miss address */ 688 mtdar 1 /* put in dar */ 689 mfmsr 0 690 xoris 0,0,0x20000@h /* flip the msr<tgpr> bit */ 691 mtcrf 0x80,3 /* restore cr0 */ 692 mtmsr 0 /* now with native gprs */ 693 isync 694 ba EXC_DSI 695tlbdlmsize = .-tlbdlmiss 696 697 .globl tlbdsmiss,tlbdsmsize 698tlbdsmiss: 699 mfspr 2,HASH1 /* get first pointer */ 700 li 1,8 701 mfctr 0 /* save counter */ 702 mfspr 3,DCMP /* get first compare value */ 703 addi 2,2,-8 /* predec pointer */ 7041: 705 mtctr 1 /* load counter */ 7062: 707 lwzu 1,8(2) /* get next pte */ 708 cmpl 0,1,3 /* see if found pte */ 709 bdneq 2b /* loop if not eq */ 710 bne 3f /* not found */ 711 lwz 1,4(2) /* load tlb entry lower word */ 712 andi. 3,1,0x80 /* check the C-bit */ 713 beq 4f 7145: 715 mtctr 0 /* restore counter */ 716 mfspr 0,DMISS /* get the miss address for the tlbld */ 717 mfsrr1 3 /* get the saved cr0 bits */ 718 mtcrf 0x80,3 /* and restore */ 719 mtspr RPA,1 /* set the pte */ 720 tlbld 0 /* load the dtlb */ 721 rfi 722 7233: /* not found in pteg */ 724 andi. 1,3,0x40 /* have we already done second hash? */ 725 bne 5f 726 mfspr 2,HASH2 /* get the second pointer */ 727 ori 3,3,0x40 /* change the compare value */ 728 li 1,8 729 addi 2,2,-8 /* predec pointer */ 730 b 1b 7314: /* found, but C-bit = 0 */ 732 rlwinm. 3,1,30,0,1 /* test PP */ 733 bge- 7f 734 andi. 3,1,1 735 beq+ 8f 7369: /* found, but protection violation (PP==00)*/ 737 mfsrr1 3 738 lis 1,0xa000000@h /* indicate protection violation 739 on store */ 740 b 1f 7417: /* found, PP=1x */ 742 mfspr 3,DMISS /* get the miss address */ 743 mfsrin 1,3 /* get the segment register */ 744 mfsrr1 3 745 rlwinm 3,3,18,31,31 /* get PR-bit */ 746 rlwnm. 2,2,3,1,1 /* get the key */ 747 bne- 9b /* protection violation */ 7488: /* found, set reference/change bits */ 749 lwz 1,4(2) /* reload tlb entry */ 750 ori 1,1,0x180 751 sth 1,6(2) 752 b 5b 7535: /* not found anywhere */ 754 mfsrr1 3 755 lis 1,0x42000000@h /* set dsisr<1> to flag pte not found */ 756 /* dsisr<6> to flag store */ 7571: 758 mtctr 0 /* restore counter */ 759 andi. 2,3,0xffff /* clean upper srr1 */ 760 mtsrr1 2 761 mtdsisr 1 /* load the dsisr */ 762 mfspr 1,DMISS /* get the miss address */ 763 mtdar 1 /* put in dar */ 764 mfmsr 0 765 xoris 0,0,0x20000@h /* flip the msr<tgpr> bit */ 766 mtcrf 0x80,3 /* restore cr0 */ 767 mtmsr 0 /* now with native gprs */ 768 isync 769 ba EXC_DSI 770tlbdsmsize = .-tlbdsmiss 771 772#ifdef DDB 773#define ddbsave 0xde0 /* primary save area for DDB */ 774/* 775 * In case of DDB we want a separate trap catcher for it 776 */ 777 .local ddbstk 778 .comm ddbstk,INTSTK,8 /* ddb stack */ 779 780 .globl ddblow,ddbsize 781ddblow: 782 mtsprg 1,1 /* save SP */ 783 stmw 28,ddbsave(0) /* free r28-r31 */ 784 mflr 28 /* save LR */ 785 mfcr 29 /* save CR */ 786 lis 1,ddbstk+INTSTK@ha /* get new SP */ 787 addi 1,1,ddbstk+INTSTK@l 788 bla ddbtrap 789ddbsize = .-ddblow 790#endif /* DDB */ 791 792#ifdef IPKDB 793#define ipkdbsave 0xde0 /* primary save area for IPKDB */ 794/* 795 * In case of IPKDB we want a separate trap catcher for it 796 */ 797 798 .local ipkdbstk 799 .comm ipkdbstk,INTSTK,8 /* ipkdb stack */ 800 801 .globl ipkdblow,ipkdbsize 802ipkdblow: 803 mtsprg 1,1 /* save SP */ 804 stmw 28,ipkdbsave(0) /* free r28-r31 */ 805 mflr 28 /* save LR */ 806 mfcr 29 /* save CR */ 807 lis 1,ipkdbstk+INTSTK@ha /* get new SP */ 808 addi 1,1,ipkdbstk+INTSTK@l 809 bla ipkdbtrap 810ipkdbsize = .-ipkdblow 811#endif /* IPKDB */ 812 813/* 814 * FRAME_SETUP assumes: 815 * SPRG1 SP (1) 816 * savearea r28-r31,DAR,DSISR (DAR & DSISR only for DSI traps) 817 * 28 LR 818 * 29 CR 819 * 1 kernel stack 820 * LR trap type 821 * SRR0/1 as at start of trap 822 */ 823#define FRAME_SETUP(savearea) \ 824/* Have to enable translation to allow access of kernel stack: */ \ 825 mfsrr0 30; \ 826 mfsrr1 31; \ 827 stmw 30,savearea+24(0); \ 828 mfmsr 30; \ 829 ori 30,30,(PSL_DR|PSL_IR); \ 830 mtmsr 30; \ 831 isync; \ 832 mfsprg 31,1; \ 833 stwu 31,-FRAMELEN(1); \ 834 stw 0,FRAME_0+8(1); \ 835 stw 31,FRAME_1+8(1); \ 836 stw 28,FRAME_LR+8(1); \ 837 stw 29,FRAME_CR+8(1); \ 838 lmw 28,savearea(0); \ 839 stmw 2,FRAME_2+8(1); \ 840 lmw 28,savearea+16(0); \ 841 mfxer 3; \ 842 mfctr 4; \ 843 mflr 5; \ 844 andi. 5,5,0xff00; \ 845 stw 3,FRAME_XER+8(1); \ 846 stw 4,FRAME_CTR+8(1); \ 847 stw 5,FRAME_EXC+8(1); \ 848 stw 28,FRAME_DAR+8(1); \ 849 stw 29,FRAME_DSISR+8(1); \ 850 stw 30,FRAME_SRR0+8(1); \ 851 stw 31,FRAME_SRR1+8(1) 852 853#define FRAME_LEAVE(savearea) \ 854/* Now restore regs: */ \ 855 lwz 2,FRAME_SRR0+8(1); \ 856 lwz 3,FRAME_SRR1+8(1); \ 857 lwz 4,FRAME_CTR+8(1); \ 858 lwz 5,FRAME_XER+8(1); \ 859 lwz 6,FRAME_LR+8(1); \ 860 lwz 7,FRAME_CR+8(1); \ 861 stw 2,savearea(0); \ 862 stw 3,savearea+4(0); \ 863 mtctr 4; \ 864 mtxer 5; \ 865 mtlr 6; \ 866 mtsprg 1,7; /* save cr */ \ 867 lmw 2,FRAME_2+8(1); \ 868 lwz 0,FRAME_0+8(1); \ 869 lwz 1,FRAME_1+8(1); \ 870 mtsprg 2,2; /* save r2 & r3 */ \ 871 mtsprg 3,3; \ 872/* Disable translation, machine check and recoverability: */ \ 873 mfmsr 2; \ 874 andi. 2,2,~(PSL_DR|PSL_IR|PSL_ME|PSL_RI)@l; \ 875 mtmsr 2; \ 876 isync; \ 877/* Decide whether we return to user mode: */ \ 878 lwz 3,savearea+4(0); \ 879 mtcr 3; \ 880 bc 4,17,1f; /* branch if PSL_PR is false */ \ 881/* Restore user & kernel access SR: */ \ 882/* lis 2,curpm@ha; get real address of pmap */ \ 883/* lwz 2,curpm@l(2); */ \ 884/* lwz 3,PM_USRSR(2); */ \ 885/* mtsr USER_SR,3; */ \ 886/* lwz 3,PM_KERNELSR(2); */ \ 887/* mtsr KERNEL_SR,3; */ \ 8881: mfsprg 2,1; /* restore cr */ \ 889 mtcr 2; \ 890 lwz 2,savearea(0); \ 891 lwz 3,savearea+4(0); \ 892 mtsrr0 2; \ 893 mtsrr1 3; \ 894 mfsprg 2,2; /* restore r2 & r3 */ \ 895 mfsprg 3,3 896 897/* 898 * Preamble code for DSI/ISI traps 899 */ 900disitrap: 901 lmw 30,disisave(0) 902 stmw 30,tempsave(0) 903 lmw 30,disisave+8(0) 904 stmw 30,tempsave+8(0) 905 mfdar 30 906 mfdsisr 31 907 stmw 30,tempsave+16(0) 908realtrap: 909/* Test whether we already had PR set */ 910 mfsrr1 1 911 mtcr 1 912 mfsprg 1,1 /* restore SP (might have been 913 overwritten) */ 914 bc 4,17,s_trap /* branch if PSL_PR is false */ 915 mfsprg 1,0 916 lwz 1,GD_CURPCB(1) 917 addi 1,1,USPACE /* stack is top of user struct */ 918 919/* 920 * Now the common trap catching code. 921 */ 922s_trap: 923/* First have to enable KERNEL mapping */ 924 lis 31,KERNEL_SEGMENT@h 925 ori 31,31,KERNEL_SEGMENT@l 926 mtsr KERNEL_SR,31 927 FRAME_SETUP(tempsave) 928/* Now we can recover interrupts again: */ 929 mfmsr 7 930 ori 7,7,(PSL_EE|PSL_ME|PSL_RI)@l 931 mtmsr 7 932 isync 933/* Call C trap code: */ 934trapagain: 935 addi 3,1,8 936 bl trap 937trapexit: 938/* Disable interrupts: */ 939 mfmsr 3 940 andi. 3,3,~PSL_EE@l 941 mtmsr 3 942/* Test AST pending: */ 943 lwz 5,FRAME_SRR1+8(1) 944 mtcr 5 945 bc 4,17,1f /* branch if PSL_PR is false */ 946 lis 3,astpending@ha 947 lwz 4,astpending@l(3) 948 andi. 4,4,1 949 beq 1f 950#if 0 /* XXX */ 951 li 6,EXC_AST 952#endif 953 stw 6,FRAME_EXC+8(1) 954 b trapagain 9551: 956#if 0 957 FRAME_LEAVE(tempsave) 958#endif 959 rfi 960 961/* 962 * Child comes here at the end of a fork. 963 * Mostly similar to the above. 964 */ 965 .globl fork_trampoline 966fork_trampoline: 967 xor 3,3,3 968#if 0 /* XXX */ 969 bl lcsplx 970#endif 971 mtlr 31 972 mr 3,30 973 blrl /* jump indirect to r31 */ 974 b trapexit 975 976/* 977 * DSI second stage fault handler 978 */ 979s_dsitrap: 980 mfdsisr 31 /* test whether this may be a 981 spill fault */ 982 mtcr 31 983 mtsprg 1,1 /* save SP */ 984 bc 4,1,disitrap /* branch if table miss is false */ 985 lis 1,spillstk+SPILLSTK@ha 986 addi 1,1,spillstk+SPILLSTK@l /* get spill stack */ 987 stwu 1,-52(1) 988 stw 0,48(1) /* save non-volatile registers */ 989 stw 3,44(1) 990 stw 4,40(1) 991 stw 5,36(1) 992 stw 6,32(1) 993 stw 7,28(1) 994 stw 8,24(1) 995 stw 9,20(1) 996 stw 10,16(1) 997 stw 11,12(1) 998 stw 12,8(1) 999 mflr 30 /* save trap type */ 1000 mfctr 31 /* & CTR */ 1001 mfdar 3 1002s_pte_spill: 1003 bl pte_spill /* try a spill */ 1004 or. 3,3,3 1005 mtctr 31 /* restore CTR */ 1006 mtlr 30 /* and trap type */ 1007 mfsprg 31,2 /* get saved XER */ 1008 mtxer 31 /* restore XER */ 1009 lwz 12,8(1) /* restore non-volatile registers */ 1010 lwz 11,12(1) 1011 lwz 10,16(1) 1012 lwz 9,20(1) 1013 lwz 8,24(1) 1014 lwz 7,28(1) 1015 lwz 6,32(1) 1016 lwz 5,36(1) 1017 lwz 4,40(1) 1018 lwz 3,44(1) 1019 lwz 0,48(1) 1020 beq disitrap 1021 mfsprg 1,1 /* restore SP */ 1022 mtcr 29 /* restore CR */ 1023 mtlr 28 /* restore LR */ 1024 lmw 28,disisave(0) /* restore r28-r31 */ 1025 rfi /* return to trapped code */ 1026 1027/* 1028 * ISI second stage fault handler 1029 */ 1030s_isitrap: 1031 mfsrr1 31 /* test whether this may be a 1032 spill fault */ 1033 mtcr 31 1034 mtsprg 1,1 /* save SP */ 1035 bc 4,1,disitrap /* branch if table miss is false */ 1036 lis 1,spillstk+SPILLSTK@ha 1037 addi 1,1,spillstk+SPILLSTK@l /* get spill stack */ 1038 stwu 1,-52(1) 1039 stw 0,48(1) /* save non-volatile registers */ 1040 stw 3,44(1) 1041 stw 4,40(1) 1042 stw 5,36(1) 1043 stw 6,32(1) 1044 stw 7,28(1) 1045 stw 8,24(1) 1046 stw 9,20(1) 1047 stw 10,16(1) 1048 stw 11,12(1) 1049 stw 12,8(1) 1050 mfxer 30 /* save XER */ 1051 mtsprg 2,30 1052 mflr 30 /* save trap type */ 1053 mfctr 31 /* & ctr */ 1054 mfsrr0 3 1055 b s_pte_spill /* above */ 1056 1057/* 1058 * External interrupt second level handler 1059 */ 1060#define INTRENTER \ 1061/* Save non-volatile registers: */ \ 1062 stwu 1,-88(1); /* temporarily */ \ 1063 stw 0,84(1); \ 1064 mfsprg 0,1; /* get original SP */ \ 1065 stw 0,0(1); /* and store it */ \ 1066 stw 3,80(1); \ 1067 stw 4,76(1); \ 1068 stw 5,72(1); \ 1069 stw 6,68(1); \ 1070 stw 7,64(1); \ 1071 stw 8,60(1); \ 1072 stw 9,56(1); \ 1073 stw 10,52(1); \ 1074 stw 11,48(1); \ 1075 stw 12,44(1); \ 1076 stw 28,40(1); /* saved LR */ \ 1077 stw 29,36(1); /* saved CR */ \ 1078 stw 30,32(1); /* saved XER */ \ 1079 lmw 28,tempsave(0); /* restore r28-r31 */ \ 1080 mfctr 6; \ 1081 lis 5,intr_depth@ha; \ 1082 lwz 5,intr_depth@l(5); \ 1083 mfsrr0 4; \ 1084 mfsrr1 3; \ 1085 stw 6,28(1); \ 1086 stw 5,20(1); \ 1087 stw 4,12(1); \ 1088 stw 3,8(1); \ 1089/* interrupts are recoverable here, and enable translation */ \ 1090 lis 3,(KERNEL_SEGMENT|SR_SUKEY|SR_PRKEY)@h; \ 1091 ori 3,3,(KERNEL_SEGMENT|SR_SUKEY|SR_PRKEY)@l; \ 1092 mtsr KERNEL_SR,3; \ 1093 mfmsr 5; \ 1094 ori 5,5,(PSL_IR|PSL_DR|PSL_RI); \ 1095 mtmsr 5; \ 1096 isync 1097 1098 .globl extint_call 1099extintr: 1100 INTRENTER 1101extint_call: 1102 bl extint_call /* to be filled in later */ 1103 1104intr_exit: 1105/* Disable interrupts (should already be disabled) and MMU here: */ 1106 mfmsr 3 1107 andi. 3,3,~(PSL_EE|PSL_ME|PSL_RI|PSL_DR|PSL_IR)@l 1108 mtmsr 3 1109 isync 1110/* restore possibly overwritten registers: */ 1111 lwz 12,44(1) 1112 lwz 11,48(1) 1113 lwz 10,52(1) 1114 lwz 9,56(1) 1115 lwz 8,60(1) 1116 lwz 7,64(1) 1117 lwz 6,8(1) 1118 lwz 5,12(1) 1119 lwz 4,28(1) 1120 lwz 3,32(1) 1121 mtsrr1 6 1122 mtsrr0 5 1123 mtctr 4 1124 mtxer 3 1125/* Returning to user mode? */ 1126 mtcr 6 /* saved SRR1 */ 1127 bc 4,17,1f /* branch if PSL_PR is false */ 1128 mfsprg 3,0 /* get globaldata */ 1129 lwz 3,GD_CURPCB(3) /* get curpcb from globaldata */ 1130 lwz 3,PCB_PMR(3) /* get pmap real address from curpcb */ 1131 mtsr KERNEL_SR,3 1132 lis 3,astpending@ha /* Test AST pending */ 1133 lwz 4,astpending@l(3) 1134 andi. 4,4,1 1135 beq 1f 1136/* Setup for entry to realtrap: */ 1137 lwz 3,0(1) /* get saved SP */ 1138 mtsprg 1,3 1139#if 0 /* XXX */ 1140 li 6,EXC_AST 1141#endif 1142 stmw 28,tempsave(0) /* establish tempsave again */ 1143 mtlr 6 1144 lwz 28,40(1) /* saved LR */ 1145 lwz 29,36(1) /* saved CR */ 1146 lwz 6,68(1) 1147 lwz 5,72(1) 1148 lwz 4,76(1) 1149 lwz 3,80(1) 1150 lwz 0,84(1) 1151 lis 30,intr_depth@ha /* adjust reentrancy count */ 1152 lwz 31,intr_depth@l(30) 1153 addi 31,31,-1 1154 stw 31,intr_depth@l(30) 1155 b realtrap 11561: 1157/* Here is the normal exit of extintr: */ 1158 lwz 5,36(1) 1159 lwz 6,40(1) 1160 mtcr 5 1161 mtlr 6 1162 lwz 6,68(1) 1163 lwz 5,72(1) 1164 lis 3,intr_depth@ha /* adjust reentrancy count */ 1165 lwz 4,intr_depth@l(3) 1166 addi 4,4,-1 1167 stw 4,intr_depth@l(3) 1168 lwz 4,76(1) 1169 lwz 3,80(1) 1170 lwz 0,84(1) 1171 lwz 1,0(1) 1172 rfi 1173 1174/* 1175 * Decrementer interrupt second level handler 1176 */ 1177decrintr: 1178 INTRENTER 1179 addi 3,1,8 /* intr frame */ 1180 bl decr_intr 1181 b intr_exit 1182 1183#ifdef DDB 1184/* 1185 * Deliberate entry to ddbtrap 1186 */ 1187 .globl ddb_trap 1188ddb_trap: 1189 mtsprg 1,1 1190 mfmsr 3 1191 mtsrr1 3 1192 andi. 3,3,~(PSL_EE|PSL_ME)@l 1193 mtmsr 3 /* disable interrupts */ 1194 isync 1195 stmw 28,ddbsave(0) 1196 mflr 28 1197 li 29,EXC_BPT 1198 mtlr 29 1199 mfcr 29 1200 mtsrr0 28 1201 1202/* 1203 * Now the ddb trap catching code. 1204 */ 1205ddbtrap: 1206 FRAME_SETUP(ddbsave) 1207/* Call C trap code: */ 1208 addi 3,1,8 1209 bl ddb_trap_glue 1210 or. 3,3,3 1211 bne ddbleave 1212/* This wasn't for DDB, so switch to real trap: */ 1213 lwz 3,FRAME_EXC+8(1) /* save exception */ 1214 stw 3,ddbsave+8(0) 1215 FRAME_LEAVE(ddbsave) 1216 mtsprg 1,1 /* prepare for entrance to realtrap */ 1217 stmw 28,tempsave(0) 1218 mflr 28 1219 mfcr 29 1220 lwz 31,ddbsave+8(0) 1221 mtlr 31 1222 b realtrap 1223ddbleave: 1224 FRAME_LEAVE(ddbsave) 1225 rfi 1226#endif /* DDB */ 1227 1228#ifdef IPKDB 1229/* 1230 * Deliberate entry to ipkdbtrap 1231 */ 1232 .globl ipkdb_trap 1233ipkdb_trap: 1234 mtsprg 1,1 1235 mfmsr 3 1236 mtsrr1 3 1237 andi. 3,3,~(PSL_EE|PSL_ME)@l 1238 mtmsr 3 /* disable interrupts */ 1239 isync 1240 stmw 28,ipkdbsave(0) 1241 mflr 28 1242 li 29,EXC_BPT 1243 mtlr 29 1244 mfcr 29 1245 mtsrr0 28 1246 1247/* 1248 * Now the ipkdb trap catching code. 1249 */ 1250ipkdbtrap: 1251 FRAME_SETUP(ipkdbsave) 1252/* Call C trap code: */ 1253 addi 3,1,8 1254 bl ipkdb_trap_glue 1255 or. 3,3,3 1256 bne ipkdbleave 1257/* This wasn't for IPKDB, so switch to real trap: */ 1258 lwz 3,FRAME_EXC+8(1) /* save exception */ 1259 stw 3,ipkdbsave+8(0) 1260 FRAME_LEAVE(ipkdbsave) 1261 mtsprg 1,1 /* prepare for entrance to realtrap */ 1262 stmw 28,tempsave(0) 1263 mflr 28 1264 mfcr 29 1265 lwz 31,ipkdbsave+8(0) 1266 mtlr 31 1267 b realtrap 1268ipkdbleave: 1269 FRAME_LEAVE(ipkdbsave) 1270 rfi 1271 1272ipkdbfault: 1273 ba _ipkdbfault 1274_ipkdbfault: 1275 mfsrr0 3 1276 addi 3,3,4 1277 mtsrr0 3 1278 li 3,-1 1279 rfi 1280 1281/* 1282 * int ipkdbfbyte(unsigned char *p) 1283 */ 1284 .globl ipkdbfbyte 1285ipkdbfbyte: 1286 li 9,EXC_DSI /* establish new fault routine */ 1287 lwz 5,0(9) 1288 lis 6,ipkdbfault@ha 1289 lwz 6,ipkdbfault@l(6) 1290 stw 6,0(9) 1291#ifdef IPKDBUSERHACK 1292 lis 8,ipkdbsr@ha 1293 lwz 8,ipkdbsr@l(8) 1294 mtsr USER_SR,8 1295 isync 1296#endif 1297 dcbst 0,9 /* flush data... */ 1298 sync 1299 icbi 0,9 /* and instruction caches */ 1300 lbz 3,0(3) /* fetch data */ 1301 stw 5,0(9) /* restore previous fault handler */ 1302 dcbst 0,9 /* and flush data... */ 1303 sync 1304 icbi 0,9 /* and instruction caches */ 1305 blr 1306 1307/* 1308 * int ipkdbsbyte(unsigned char *p, int c) 1309 */ 1310 .globl ipkdbsbyte 1311ipkdbsbyte: 1312 li 9,EXC_DSI /* establish new fault routine */ 1313 lwz 5,0(9) 1314 lis 6,ipkdbfault@ha 1315 lwz 6,ipkdbfault@l(6) 1316 stw 6,0(9) 1317#ifdef IPKDBUSERHACK 1318 lis 8,ipkdbsr@ha 1319 lwz 8,ipkdbsr@l(8) 1320 mtsr USER_SR,8 1321 isync 1322#endif 1323 dcbst 0,9 /* flush data... */ 1324 sync 1325 icbi 0,9 /* and instruction caches */ 1326 mr 6,3 1327 xor 3,3,3 1328 stb 4,0(6) 1329 dcbst 0,6 /* Now do appropriate flushes 1330 to data... */ 1331 sync 1332 icbi 0,6 /* and instruction caches */ 1333 stw 5,0(9) /* restore previous fault handler */ 1334 dcbst 0,9 /* and flush data... */ 1335 sync 1336 icbi 0,9 /* and instruction caches */ 1337 blr 1338#endif /* IPKDB */ 1339 1340/* 1341 * int setfault() 1342 * 1343 * Similar to setjmp to setup for handling faults on accesses to user memory. 1344 * Any routine using this may only call bcopy, either the form below, 1345 * or the (currently used) C code optimized, so it doesn't use any non-volatile 1346 * registers. 1347 */ 1348 .globl setfault 1349setfault: 1350 mflr 0 1351 mfcr 12 1352 mfsprg 4,0 1353 lwz 4,GD_CURPCB(4) 1354 stw 3,PCB_FAULT(4) 1355 stw 0,0(3) 1356 stw 1,4(3) 1357 stw 2,8(3) 1358 stmw 12,12(3) 1359 xor 3,3,3 1360 blr 1361 1362/* 1363 * Signal "trampoline" code. 1364 */ 1365 .globl sigcode 1366sigcode: 1367 b sys_exit 1368esigcode: 1369 .data 1370GLOBAL(szsigcode) 1371 .long esigcode-sigcode 1372 .text 1373 1374