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_FP|PSL_ME|PSL_RI)@l 931 mtmsr 7 932 isync 933/* Call C trap code: */ 934 addi 3,1,8 935 mr 30,3 936 bl trap 937 mr 3,30 938 bl ast 939 FRAME_LEAVE(tempsave) 940 rfi 941 942/* 943 * Child comes here at the end of a fork. 944 * Mostly similar to the above. 945 */ 946 .globl fork_trampoline 947fork_trampoline: 948 xor 3,3,3 949#if 0 /* XXX */ 950 bl lcsplx 951#endif 952 mtlr 31 953 mr 3,30 954 blrl /* jump indirect to r31 */ 955 mr 3,30 956 bl ast 957 FRAME_LEAVE(tempsave) 958 rfi 959 960/* 961 * DSI second stage fault handler 962 */ 963s_dsitrap: 964 mfdsisr 31 /* test whether this may be a 965 spill fault */ 966 mtcr 31 967 mtsprg 1,1 /* save SP */ 968 bc 4,1,disitrap /* branch if table miss is false */ 969 lis 1,spillstk+SPILLSTK@ha 970 addi 1,1,spillstk+SPILLSTK@l /* get spill stack */ 971 stwu 1,-52(1) 972 stw 0,48(1) /* save non-volatile registers */ 973 stw 3,44(1) 974 stw 4,40(1) 975 stw 5,36(1) 976 stw 6,32(1) 977 stw 7,28(1) 978 stw 8,24(1) 979 stw 9,20(1) 980 stw 10,16(1) 981 stw 11,12(1) 982 stw 12,8(1) 983 mflr 30 /* save trap type */ 984 mfctr 31 /* & CTR */ 985 mfdar 3 986s_pte_spill: 987 bl pte_spill /* try a spill */ 988 or. 3,3,3 989 mtctr 31 /* restore CTR */ 990 mtlr 30 /* and trap type */ 991 mfsprg 31,2 /* get saved XER */ 992 mtxer 31 /* restore XER */ 993 lwz 12,8(1) /* restore non-volatile registers */ 994 lwz 11,12(1) 995 lwz 10,16(1) 996 lwz 9,20(1) 997 lwz 8,24(1) 998 lwz 7,28(1) 999 lwz 6,32(1) 1000 lwz 5,36(1) 1001 lwz 4,40(1) 1002 lwz 3,44(1) 1003 lwz 0,48(1) 1004 beq disitrap 1005 mfsprg 1,1 /* restore SP */ 1006 mtcr 29 /* restore CR */ 1007 mtlr 28 /* restore LR */ 1008 lmw 28,disisave(0) /* restore r28-r31 */ 1009 rfi /* return to trapped code */ 1010 1011/* 1012 * ISI second stage fault handler 1013 */ 1014s_isitrap: 1015 mfsrr1 31 /* test whether this may be a 1016 spill fault */ 1017 mtcr 31 1018 mtsprg 1,1 /* save SP */ 1019 bc 4,1,disitrap /* branch if table miss is false */ 1020 lis 1,spillstk+SPILLSTK@ha 1021 addi 1,1,spillstk+SPILLSTK@l /* get spill stack */ 1022 stwu 1,-52(1) 1023 stw 0,48(1) /* save non-volatile registers */ 1024 stw 3,44(1) 1025 stw 4,40(1) 1026 stw 5,36(1) 1027 stw 6,32(1) 1028 stw 7,28(1) 1029 stw 8,24(1) 1030 stw 9,20(1) 1031 stw 10,16(1) 1032 stw 11,12(1) 1033 stw 12,8(1) 1034 mfxer 30 /* save XER */ 1035 mtsprg 2,30 1036 mflr 30 /* save trap type */ 1037 mfctr 31 /* & ctr */ 1038 mfsrr0 3 1039 b s_pte_spill /* above */ 1040 1041/* 1042 * External interrupt second level handler 1043 */ 1044#define INTRENTER \ 1045/* Save non-volatile registers: */ \ 1046 stwu 1,-88(1); /* temporarily */ \ 1047 stw 0,84(1); \ 1048 mfsprg 0,1; /* get original SP */ \ 1049 stw 0,0(1); /* and store it */ \ 1050 stw 3,80(1); \ 1051 stw 4,76(1); \ 1052 stw 5,72(1); \ 1053 stw 6,68(1); \ 1054 stw 7,64(1); \ 1055 stw 8,60(1); \ 1056 stw 9,56(1); \ 1057 stw 10,52(1); \ 1058 stw 11,48(1); \ 1059 stw 12,44(1); \ 1060 stw 28,40(1); /* saved LR */ \ 1061 stw 29,36(1); /* saved CR */ \ 1062 stw 30,32(1); /* saved XER */ \ 1063 lmw 28,tempsave(0); /* restore r28-r31 */ \ 1064 mfctr 6; \ 1065 lis 5,intr_depth@ha; \ 1066 lwz 5,intr_depth@l(5); \ 1067 mfsrr0 4; \ 1068 mfsrr1 3; \ 1069 stw 6,28(1); \ 1070 stw 5,20(1); \ 1071 stw 4,12(1); \ 1072 stw 3,8(1); \ 1073/* interrupts are recoverable here, and enable translation */ \ 1074 lis 3,(KERNEL_SEGMENT|SR_SUKEY|SR_PRKEY)@h; \ 1075 ori 3,3,(KERNEL_SEGMENT|SR_SUKEY|SR_PRKEY)@l; \ 1076 mtsr KERNEL_SR,3; \ 1077 mfmsr 5; \ 1078 ori 5,5,(PSL_IR|PSL_DR|PSL_RI); \ 1079 mtmsr 5; \ 1080 isync 1081 1082 .globl extint_call 1083extintr: 1084 INTRENTER 1085extint_call: 1086 bl extint_call /* to be filled in later */ 1087 1088intr_exit: 1089/* Disable interrupts (should already be disabled) and MMU here: */ 1090 mfmsr 3 1091 andi. 3,3,~(PSL_EE|PSL_ME|PSL_RI|PSL_DR|PSL_IR)@l 1092 mtmsr 3 1093 isync 1094/* restore possibly overwritten registers: */ 1095 lwz 12,44(1) 1096 lwz 11,48(1) 1097 lwz 10,52(1) 1098 lwz 9,56(1) 1099 lwz 8,60(1) 1100 lwz 7,64(1) 1101 lwz 6,8(1) 1102 lwz 5,12(1) 1103 lwz 4,28(1) 1104 lwz 3,32(1) 1105 mtsrr1 6 1106 mtsrr0 5 1107 mtctr 4 1108 mtxer 3 1109/* Returning to user mode? */ 1110 mtcr 6 /* saved SRR1 */ 1111 bc 4,17,1f /* branch if PSL_PR is false */ 1112 mfsprg 3,0 /* get globaldata */ 1113 lwz 3,GD_CURPCB(3) /* get curpcb from globaldata */ 1114 lwz 3,PCB_PMR(3) /* get pmap real address from curpcb */ 1115 mtsr KERNEL_SR,3 1116/* Setup for entry to realtrap: */ 1117 lwz 3,0(1) /* get saved SP */ 1118 mtsprg 1,3 1119#if 0 /* XXX */ 1120 li 6,EXC_AST 1121#endif 1122 stmw 28,tempsave(0) /* establish tempsave again */ 1123 mtlr 6 1124 lwz 28,40(1) /* saved LR */ 1125 lwz 29,36(1) /* saved CR */ 1126 lwz 6,68(1) 1127 lwz 5,72(1) 1128 lwz 4,76(1) 1129 lwz 3,80(1) 1130 lwz 0,84(1) 1131 lis 30,intr_depth@ha /* adjust reentrancy count */ 1132 lwz 31,intr_depth@l(30) 1133 addi 31,31,-1 1134 stw 31,intr_depth@l(30) 1135 b realtrap /* XXX: should call ast(frame ptr) */ 11361: 1137/* Here is the normal exit of extintr: */ 1138 lwz 5,36(1) 1139 lwz 6,40(1) 1140 mtcr 5 1141 mtlr 6 1142 lwz 6,68(1) 1143 lwz 5,72(1) 1144 lis 3,intr_depth@ha /* adjust reentrancy count */ 1145 lwz 4,intr_depth@l(3) 1146 addi 4,4,-1 1147 stw 4,intr_depth@l(3) 1148 lwz 4,76(1) 1149 lwz 3,80(1) 1150 lwz 0,84(1) 1151 lwz 1,0(1) 1152 rfi 1153 1154/* 1155 * Decrementer interrupt second level handler 1156 */ 1157decrintr: 1158 INTRENTER 1159 addi 3,1,8 /* intr frame */ 1160 bl decr_intr 1161 b intr_exit 1162 1163#ifdef DDB 1164/* 1165 * Deliberate entry to ddbtrap 1166 */ 1167 .globl ddb_trap 1168ddb_trap: 1169 mtsprg 1,1 1170 mfmsr 3 1171 mtsrr1 3 1172 andi. 3,3,~(PSL_EE|PSL_ME)@l 1173 mtmsr 3 /* disable interrupts */ 1174 isync 1175 stmw 28,ddbsave(0) 1176 mflr 28 1177 li 29,EXC_BPT 1178 mtlr 29 1179 mfcr 29 1180 mtsrr0 28 1181 1182/* 1183 * Now the ddb trap catching code. 1184 */ 1185ddbtrap: 1186 FRAME_SETUP(ddbsave) 1187/* Call C trap code: */ 1188 addi 3,1,8 1189 bl ddb_trap_glue 1190 or. 3,3,3 1191 bne ddbleave 1192/* This wasn't for DDB, so switch to real trap: */ 1193 lwz 3,FRAME_EXC+8(1) /* save exception */ 1194 stw 3,ddbsave+8(0) 1195 FRAME_LEAVE(ddbsave) 1196 mtsprg 1,1 /* prepare for entrance to realtrap */ 1197 stmw 28,tempsave(0) 1198 mflr 28 1199 mfcr 29 1200 lwz 31,ddbsave+8(0) 1201 mtlr 31 1202 b realtrap 1203ddbleave: 1204 FRAME_LEAVE(ddbsave) 1205 rfi 1206#endif /* DDB */ 1207 1208#ifdef IPKDB 1209/* 1210 * Deliberate entry to ipkdbtrap 1211 */ 1212 .globl ipkdb_trap 1213ipkdb_trap: 1214 mtsprg 1,1 1215 mfmsr 3 1216 mtsrr1 3 1217 andi. 3,3,~(PSL_EE|PSL_ME)@l 1218 mtmsr 3 /* disable interrupts */ 1219 isync 1220 stmw 28,ipkdbsave(0) 1221 mflr 28 1222 li 29,EXC_BPT 1223 mtlr 29 1224 mfcr 29 1225 mtsrr0 28 1226 1227/* 1228 * Now the ipkdb trap catching code. 1229 */ 1230ipkdbtrap: 1231 FRAME_SETUP(ipkdbsave) 1232/* Call C trap code: */ 1233 addi 3,1,8 1234 bl ipkdb_trap_glue 1235 or. 3,3,3 1236 bne ipkdbleave 1237/* This wasn't for IPKDB, so switch to real trap: */ 1238 lwz 3,FRAME_EXC+8(1) /* save exception */ 1239 stw 3,ipkdbsave+8(0) 1240 FRAME_LEAVE(ipkdbsave) 1241 mtsprg 1,1 /* prepare for entrance to realtrap */ 1242 stmw 28,tempsave(0) 1243 mflr 28 1244 mfcr 29 1245 lwz 31,ipkdbsave+8(0) 1246 mtlr 31 1247 b realtrap 1248ipkdbleave: 1249 FRAME_LEAVE(ipkdbsave) 1250 rfi 1251 1252ipkdbfault: 1253 ba _ipkdbfault 1254_ipkdbfault: 1255 mfsrr0 3 1256 addi 3,3,4 1257 mtsrr0 3 1258 li 3,-1 1259 rfi 1260 1261/* 1262 * int ipkdbfbyte(unsigned char *p) 1263 */ 1264 .globl ipkdbfbyte 1265ipkdbfbyte: 1266 li 9,EXC_DSI /* establish new fault routine */ 1267 lwz 5,0(9) 1268 lis 6,ipkdbfault@ha 1269 lwz 6,ipkdbfault@l(6) 1270 stw 6,0(9) 1271#ifdef IPKDBUSERHACK 1272 lis 8,ipkdbsr@ha 1273 lwz 8,ipkdbsr@l(8) 1274 mtsr USER_SR,8 1275 isync 1276#endif 1277 dcbst 0,9 /* flush data... */ 1278 sync 1279 icbi 0,9 /* and instruction caches */ 1280 lbz 3,0(3) /* fetch data */ 1281 stw 5,0(9) /* restore previous fault handler */ 1282 dcbst 0,9 /* and flush data... */ 1283 sync 1284 icbi 0,9 /* and instruction caches */ 1285 blr 1286 1287/* 1288 * int ipkdbsbyte(unsigned char *p, int c) 1289 */ 1290 .globl ipkdbsbyte 1291ipkdbsbyte: 1292 li 9,EXC_DSI /* establish new fault routine */ 1293 lwz 5,0(9) 1294 lis 6,ipkdbfault@ha 1295 lwz 6,ipkdbfault@l(6) 1296 stw 6,0(9) 1297#ifdef IPKDBUSERHACK 1298 lis 8,ipkdbsr@ha 1299 lwz 8,ipkdbsr@l(8) 1300 mtsr USER_SR,8 1301 isync 1302#endif 1303 dcbst 0,9 /* flush data... */ 1304 sync 1305 icbi 0,9 /* and instruction caches */ 1306 mr 6,3 1307 xor 3,3,3 1308 stb 4,0(6) 1309 dcbst 0,6 /* Now do appropriate flushes 1310 to data... */ 1311 sync 1312 icbi 0,6 /* and instruction caches */ 1313 stw 5,0(9) /* restore previous fault handler */ 1314 dcbst 0,9 /* and flush data... */ 1315 sync 1316 icbi 0,9 /* and instruction caches */ 1317 blr 1318#endif /* IPKDB */ 1319 1320/* 1321 * int setfault() 1322 * 1323 * Similar to setjmp to setup for handling faults on accesses to user memory. 1324 * Any routine using this may only call bcopy, either the form below, 1325 * or the (currently used) C code optimized, so it doesn't use any non-volatile 1326 * registers. 1327 */ 1328 .globl setfault 1329setfault: 1330 mflr 0 1331 mfcr 12 1332 mfsprg 4,0 1333 lwz 4,GD_CURPCB(4) 1334 stw 3,PCB_ONFAULT(4) 1335 stw 0,0(3) 1336 stw 1,4(3) 1337 stw 2,8(3) 1338 stmw 12,12(3) 1339 xor 3,3,3 1340 blr 1341 1342/* 1343 * Signal "trampoline" code. 1344 */ 1345 .globl sigcode 1346sigcode: 1347 b sys_exit 1348esigcode: 1349 .data 1350GLOBAL(szsigcode) 1351 .long esigcode-sigcode 1352 .text 1353 1354