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