1/* $NetBSD: locore.S,v 1.8 2001/12/03 21:10:48 aymeric 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/* Amiga part written by Adam Ciarcinski adam@albedo.art.pl */ 35 36/* 37 * Some instructions gas doesn't understand (yet?) 38 */ 39#define bdneq bdnzf 2, 40 41#include "opt_ddb.h" 42#include "opt_ipkdb.h" 43#include "opt_lockdebug.h" 44#include "assym.h" 45 46#include <sys/syscall.h> 47 48#include <machine/param.h> 49#include <machine/pmap.h> 50#include <machine/psl.h> 51#include <machine/trap.h> 52#include <machine/asm.h> 53#include <machine/p5reg.h> 54 55#include <machine/hid.h> 56#include <amiga/amiga/custom.h> 57 58 .data 59GLOBAL(proc0paddr) 60 .long 0 61GLOBAL(ssir) 62 .word 0 63GLOBAL(delaydivisor) 64 .long 0 65GLOBAL(lowram) 66 .long 0 67 68GLOBAL(eintrnames) 69 .align 4 70GLOBAL(intrcnt) 71 .long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 72 .long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 73 .long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 74 .long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 75 .long 0,0,0,0 76GLOBAL(eintrcnt) 77 78GLOBAL(powersave) 79 .long 0 80 81idle_u: 82 .long 0 /* fake uarea during idle after exit */ 83openfirmware_entry: 84 .long 0 /* openfirmware entry point */ 85srsave: 86 .long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 87 88 89/* 90 * This symbol is here for the benefit of kvm_mkdb, and is supposed to 91 * mark the start of kernel text. 92 */ 93 .text 94 .globl _C_LABEL(kernel_text) 95_C_LABEL(kernel_text): 96 97/* 98 * Startup entry 99 * This is where bootloader jumps after successful kernel loading. 100 * Must be the first address in text segment 101 */ 102 .text 103 .globl __start 104__start: 105/* 106 * Disable M68k 107 * First of all we must disable M68k, since it cannot be done by 108 * the loader (which is run under M68k). 109 */ 110 lis 5,P5BASE@h 111 /* ori 5,5,P5BASE@l - we assume that the lsb is 0x0000 */ 112 li 3,P5_M68K_RESET 113 stb 3,P5_REG_RESET(5) 114 115/* 116 * Disable Amiga interrupts 117 */ 118 lis 4,0xbfd000@h 119 ori 4,4,0xbfd000@l 120 li 3,0x7f 121 stb 3,0xd00(4) /* CIAB icr */ 122 stb 3,0x1d01(4) /* CIAA icr */ 123 124/* 125 * Change interrupt master 126 * Only one CPU can get Amiga interrupts, either M68k or PowerPC. 127 */ 128 li 3,P5_SET_CLEAR|P5_DISABLE_INT 129 stb 3,P5_IPL_EMU(5) /* disable interrupts */ 130 li 3,P5_INT_MASTER 131 stb 3,P5_REG_INT(5) /* let the PowerPC get interrupts */ 132 li 3,P5_DISABLE_INT 133 stb 3,P5_IPL_EMU(5) /* enable interrupts */ 134 li 3,P5_LVL7 135 stb 3,P5_INT_LVL(5) 136 137/* 138 * Remove ROM mapping 139 * This will give us extra 512K RAM 140 */ 141 li 3,0x60 142 stb 3,P5_REG_LOCK(5) 143 li 3,0x50 144 stb 3,P5_REG_LOCK(5) 145 li 3,0x30 146 stb 3,P5_REG_LOCK(5) 147 li 3,P5_SET_CLEAR|P5_SHADOW 148 stb 3,P5_REG_SHADOW(5) 149 li 3,0x00 150 stb 3,P5_REG_LOCK(5) 151 152 153/* 154 * Clear BAT registers 155 * Clearing segment register 156 */ 157 xor 0,0,0 158 mtibatu 0,0 159 mtibatu 1,0 160 mtibatu 2,0 161 mtibatu 3,0 162 mtdbatu 0,0 163 mtdbatu 1,0 164 mtdbatu 2,0 165 mtdbatu 3,0 166 mtsr 0,0 167 mtsr 1,0 168 mtsr 2,0 169 mtsr 3,0 170 mtsr 4,0 171 mtsr 5,0 172 mtsr 6,0 173 mtsr 7,0 174 mtsr 8,0 175 mtsr 9,0 176 mtsr 10,0 177 mtsr 11,0 178 mtsr 12,0 179 mtsr 13,0 180 mtsr 14,0 181 mtsr 15,0 182 sync 183 184/* 185 * Enable caches on 603e/604e 186 */ 187 mfspr 3,1008 188 ori 3,3,HID0_ICE|HID0_DCE|HID0_SGE|HID0_BHT 189 ori 4,3,HID0_ICFI|HID0_DCFI 190 sync 191 mtspr 1008,4 192 sync 193 mtspr 1008,3 194 sync 195 isync 196 197/* 198 * Compute end-of-kernel memory 199 */ 200 lis 8,_C_LABEL(end)@h 201 ori 8,8,_C_LABEL(end)@l 202 li 9,PGOFSET 203 add 8,8,9 204 andc 8,8,9 /* page alignment */ 205 206 addi 8,8,USPACE /* space for idle_u */ 207 lis 9,_C_LABEL(proc0paddr)@ha 208 stw 8,_C_LABEL(proc0paddr)@l(9) 209 addi 1,8,USPACE-FRAMELEN /* stack pointer for proc0 */ 210 mr 4,1 211 xor 0,0,0 212 stwu 0,-16(1) 213 214 lis 3,__start@h 215 ori 3,3,__start@l 216 bl _C_LABEL(initppc) 217 218 219/* 220 * Jump to main() (from kern/init_main.c) 221 * main() should call consinit(), uvm_init() and cpu_startup() 222 */ 223 b _C_LABEL(main) 224 225/* 226 * Colours on the screen 227 * For visual test purposes. 228 */ 229 .globl _C_LABEL(cpu_fail) 230_C_LABEL(cpu_fail): 231 li 3,0xb8b 232 li 4,0xa0a 233 li 5,0x000 234 lis 2,0xdff000@h 235 ori 2,2,0xdff000@l 236loop: sth 3,0x180(2) 237 sth 4,0x180(2) 238 sth 5,0x180(2) 239 b loop 240 241 242/* 243 * ADAM: fake interrupt handler 244 */ 245 .globl _C_LABEL(adamint),_C_LABEL(adamintsize) 246_C_LABEL(adamint): 247 mtsprg 2,2 248 mtsprg 3,3 249 lis 3,0xdff000@h 250 ori 3,3,0xdff000@l 2511: li 2,0x00a 252 sth 2,0x180(3) 253 li 2,0xaaa 254 sth 2,0x180(3) 255 b 1b 256 mfsprg 3,3 257 mfsprg 2,2 258 rfi 259_C_LABEL(adamintsize) = .-_C_LABEL(adamint) 260 261/* 262 * No processes are runnable, so loop waiting for one. 263 * Separate label here for accounting purposes. 264 * When we get here, interrupts are off (MSR[EE]=0) and sched_lock is held. 265 */ 266 .text 267ASENTRY(Idle) 268 lis 8,_C_LABEL(sched_whichqs)@ha 269 lwz 9,_C_LABEL(sched_whichqs)@l(8) 270 271 or. 9,9,9 272 bne- .Lsw1 /* at least one queue non-empty */ 273 274#if defined(MULTIPROCESSOR) || defined(LOCKDEBUG) 275 bl _C_LABEL(sched_unlock_idle) 276#endif 277 278 mfmsr 3 279 ori 3,3,PSL_EE@l /* reenable ints again */ 280 mtmsr 3 281 isync 282 283/* Check if we can use power saving mode */ 284 lis 8,_C_LABEL(powersave)@ha 285 lwz 9,_C_LABEL(powersave)@l(8) 286 287 or. 9,9,9 288 beq 1f 289 290 sync 291 oris 3,3,PSL_POW@h /* enter power saving mode */ 292 mtmsr 3 293 isync 2941: 295 andi. 3,3,~PSL_EE@l /* disable interrupts while 296 manipulating runque */ 297 mtmsr 3 298 299#if defined(MULTIPROCESSOR) || defined(LOCKDEBUG) 300 bl _C_LABEL(sched_lock_idle) 301#endif 302 b _ASM_LABEL(Idle) 303 304/* 305 * switchexit gets called from cpu_exit to complete the exit procedure. 306 */ 307ENTRY(switchexit) 308/* First switch to the idle pcb/kernel stack */ 309 lis 6,idle_u@ha 310 lwz 6,idle_u@l(6) 311 lis 7,_C_LABEL(curpcb)@ha 312 stw 6,_C_LABEL(curpcb)@l(7) 313 addi 1,6,USPACE-16 /* 16 bytes are reserved at stack top */ 314 /* 315 * Schedule the vmspace and stack to be freed (the proc arg is 316 * already in r3). 317 */ 318 bl _C_LABEL(exit2) 319 320#if defined(MULTIPROCESSOR) || defined(LOCKDEBUG) 321 bl _C_LABEL(sched_lock_idle) 322#endif 323 324/* Fall through to cpu_switch to actually select another proc */ 325 li 3,0 /* indicate exited process */ 326 327/* 328 * void cpu_switch(struct proc *p) 329 * Find a runnable process and switch to it. 330 */ 331/* XXX noprofile? --thorpej@netbsd.org */ 332ENTRY(cpu_switch) 333 mflr 0 /* save lr */ 334 stw 0,4(1) 335 stwu 1,-16(1) 336 stw 31,12(1) 337 stw 30,8(1) 338 339 mr 30,3 340 lis 3,_C_LABEL(curproc)@ha 341 xor 31,31,31 342 stw 31,_C_LABEL(curproc)@l(3) /* Zero to not accumulate cpu time */ 343 lis 3,_C_LABEL(curpcb)@ha 344 lwz 31,_C_LABEL(curpcb)@l(3) 345 346#if defined(MULTIPROCESSOR) || defined(LOCKDEBUG) 347/* Release the sched_lock before processing interrupts. */ 348 bl _C_LABEL(sched_unlock_idle) 349#endif 350 351 xor 3,3,3 352 bl _C_LABEL(lcsplx) 353 stw 3,PCB_SPL(31) /* save spl */ 354 355/* Lock the scheduler. */ 356 mfmsr 3 357 andi. 3,3,~PSL_EE@l /* disable interrupts while 358 manipulating runque */ 359 mtmsr 3 360 isync 361#if defined(MULTIPROCESSOR) || defined(LOCKDEBUG) 362 bl _C_LABEL(sched_lock_idle) 363#endif 364 365/* Find a new process */ 366 lis 8,_C_LABEL(sched_whichqs)@ha 367 lwz 9,_C_LABEL(sched_whichqs)@l(8) 368 369 or. 9,9,9 370 beq- _ASM_LABEL(Idle) /* all queues empty */ 371.Lsw1: 372 cntlzw 10,9 373 lis 4,_C_LABEL(sched_qs)@ha 374 addi 4,4,_C_LABEL(sched_qs)@l 375 slwi 3,10,3 376 add 3,3,4 /* select queue */ 377 378 lwz 31,P_FORW(3) /* unlink first proc from queue */ 379 lwz 4,P_FORW(31) 380 stw 4,P_FORW(3) 381 stw 3,P_BACK(4) 382 383 cmpl 0,3,4 /* queue empty? */ 384 bne 1f 385 386 lis 3,0x80000000@h 387 srw 3,3,10 388 andc 9,9,3 389 stw 9,_C_LABEL(sched_whichqs)@l(8) /* mark it empty */ 390 3911: 392 /* just did this resched thing */ 393 xor 3,3,3 394 lis 4,_C_LABEL(want_resched)@ha 395 stw 3,_C_LABEL(want_resched)@l(4) 396 397 stw 3,P_BACK(31) /* probably superfluous */ 398 399#if defined(MULTIPROCESSOR) || defined(LOCKDEBUG) 400 /* Unlock the sched_lock, but leave interrupts off, for now. */ 401 bl _C_LABEL(sched_unlock_idle) 402#endif 403 404 /* p->p_cpu initialized in fork1() for single-processor */ 405 406 li 3,SONPROC /* p->p_stat = SONPROC */ 407 stb 3,P_STAT(31) 408 409 /* record new process */ 410 lis 4,_C_LABEL(curproc)@ha 411 stw 31,_C_LABEL(curproc)@l(4) 412 413 mfmsr 3 414 ori 3,3,PSL_EE@l /* Now we can interrupt again */ 415 mtmsr 3 416 417 cmpl 0,31,30 /* is it the same process? */ 418 beq switch_return 419 420 or. 30,30,30 /* old process was exiting? */ 421 beq switch_exited 422 423 mfsr 10,USER_SR /* save USER_SR for copyin/copyout */ 424 mfcr 11 /* save cr */ 425 mr 12,2 /* save r2 */ 426 stwu 1,-SFRAMELEN(1) /* still running on old stack */ 427 stmw 10,8(1) 428 lwz 3,P_ADDR(30) 429 stw 1,PCB_SP(3) /* save SP */ 430 431switch_exited: 432 mfmsr 3 433 andi. 3,3,~PSL_EE@l /* disable interrupts while 434 actually switching */ 435 mtmsr 3 436 437 /* indicate new pcb */ 438 lwz 4,P_ADDR(31) 439 lis 5,_C_LABEL(curpcb)@ha 440 stw 4,_C_LABEL(curpcb)@l(5) 441 442 /* save real pmap pointer for spill fill */ 443 lwz 5,PCB_PMR(4) 444 lis 6,_C_LABEL(curpm)@ha 445 stwu 5,_C_LABEL(curpm)@l(6) 446 stwcx. 5,0,6 /* clear possible reservation */ 447 448 addic. 5,5,64 449 li 6,0 450 mfsr 8,KERNEL_SR /* save kernel SR */ 4511: 452 addis 6,6,-0x10000000@ha /* set new procs segment registers */ 453 or. 6,6,6 /* This is done from the real 454 address pmap */ 455 lwzu 7,-4(5) /* so we don't have to worry */ 456 mtsrin 7,6 /* about accessibility */ 457 bne 1b 458 mtsr KERNEL_SR,8 /* restore kernel SR */ 459 isync 460 461 lwz 1,PCB_SP(4) /* get new procs SP */ 462 463 ori 3,3,PSL_EE@l /* interrupts are okay again */ 464 mtmsr 3 465 466 lmw 10,8(1) /* get other regs */ 467 lwz 1,0(1) /* get saved SP */ 468 mr 2,12 /* get saved r2 */ 469 mtcr 11 /* get saved cr */ 470 isync 471 mtsr USER_SR,10 /* get saved USER_SR */ 472 isync 473 474switch_return: 475 mr 30,7 /* save proc pointer */ 476 lwz 3,PCB_SPL(4) 477 bl _C_LABEL(lcsplx) 478 479 mr 3,30 /* get curproc for special fork 480 returns */ 481 482 lwz 31,12(1) 483 lwz 30,8(1) 484 addi 1,1,16 485 lwz 0,4(1) 486 mtlr 0 487 blr 488 489/* 490 * Data used during primary/secondary traps/interrupts 491 */ 492#define tempsave 0x2e0 /* primary save area for trap handling */ 493#define disisave 0x3e0 /* primary save area for dsi/isi traps */ 494 495#define INTSTK (8*1024) /* 8K interrupt stack */ 496 .data 497 .align 4 498intstk: 499 .space INTSTK /* interrupt stack */ 500 501GLOBAL(intr_depth) 502 .long -1 /* in-use marker */ 503 504#define SPILLSTK 1024 /* 1K spill stack */ 505 506 .comm spillstk,SPILLSTK,8 507 508/* 509 * This code gets copied to all the trap vectors 510 * (except ISI/DSI, ALI, the interrupts, and possibly the debugging 511 * traps when using IPKDB). 512 */ 513 .text 514 .globl _C_LABEL(trapcode),_C_LABEL(trapsize) 515_C_LABEL(trapcode): 516 mtsprg 1,1 /* save SP */ 517 stmw 28,tempsave(0) /* free r28-r31 */ 518 mflr 28 /* save LR */ 519 mfcr 29 /* save CR */ 520/* Test whether we already had PR set */ 521 mfsrr1 31 522 mtcr 31 523 bc 4,17,1f /* branch if PSL_PR is clear */ 524 lis 1,_C_LABEL(curpcb)@ha 525 lwz 1,_C_LABEL(curpcb)@l(1) 526 addi 1,1,USPACE /* stack is top of user struct */ 5271: 528 bl s_trap 529_C_LABEL(trapsize) = .-_C_LABEL(trapcode) 530 531/* 532 * For ALI: has to save DSISR and DAR 533 */ 534 .globl _C_LABEL(alitrap),_C_LABEL(alisize) 535_C_LABEL(alitrap): 536 mtsprg 1,1 /* save SP */ 537 stmw 28,tempsave(0) /* free r28-r31 */ 538 mfdar 30 539 mfdsisr 31 540 stmw 30,tempsave+16(0) 541 mflr 28 /* save LR */ 542 mfcr 29 /* save CR */ 543/* Test whether we already had PR set */ 544 mfsrr1 31 545 mtcr 31 546 bc 4,17,1f /* branch if PSL_PR is clear */ 547 lis 1,_C_LABEL(curpcb)@ha 548 lwz 1,_C_LABEL(curpcb)@l(1) 549 addi 1,1,USPACE /* stack is top of user struct */ 5501: 551 bl s_trap 552_C_LABEL(alisize) = .-_C_LABEL(alitrap) 553 554/* 555 * Similar to the above for DSI 556 * Has to handle BAT spills 557 * and standard pagetable spills 558 */ 559 .globl _C_LABEL(dsitrap),_C_LABEL(dsisize) 560_C_LABEL(dsitrap): 561 stmw 28,disisave(0) /* free r28-r31 */ 562 mfcr 29 /* save CR */ 563 mfxer 30 /* save XER */ 564 mtsprg 2,30 /* in SPRG2 */ 565 mfsrr1 31 /* test kernel mode */ 566 mtcr 31 567 bc 12,17,1f /* branch if PSL_PR is set */ 568 mfdar 31 /* get fault address */ 569 rlwinm 31,31,7,25,28 /* get segment * 8 */ 570 571 /* get batu */ 572 addis 31,31,_C_LABEL(battable)@ha 573 lwz 30,_C_LABEL(battable)@l(31) 574 mtcr 30 575 bc 4,30,1f /* branch if supervisor valid is 576 false */ 577 /* get batl */ 578 lwz 31,_C_LABEL(battable)+4@l(31) 579/* We randomly use the highest two bat registers here */ 580 mftb 28 581 andi. 28,28,1 582 bne 2f 583 mtdbatu 2,30 584 mtdbatl 2,31 585 b 3f 5862: 587 mtdbatu 3,30 588 mtdbatl 3,31 5893: 590 mfsprg 30,2 /* restore XER */ 591 mtxer 30 592 mtcr 29 /* restore CR */ 593 lmw 28,disisave(0) /* restore r28-r31 */ 594 rfi /* return to trapped code */ 5951: 596 mflr 28 /* save LR */ 597 b s_dsitrap 598_C_LABEL(dsisize) = .-_C_LABEL(dsitrap) 599 600/* 601 * Similar to the above for ISI 602 */ 603 .globl _C_LABEL(isitrap),_C_LABEL(isisize) 604_C_LABEL(isitrap): 605 stmw 28,disisave(0) /* free r28-r31 */ 606 mflr 28 /* save LR */ 607 mfcr 29 /* save CR */ 608 mfsrr1 31 /* test kernel mode */ 609 mtcr 31 610 bc 12,17,1f /* branch if PSL_PR is set */ 611 mfsrr0 31 /* get fault address */ 612 rlwinm 31,31,7,25,28 /* get segment * 8 */ 613 614 /* get batu */ 615 addis 31,31,_C_LABEL(battable)@ha 616 lwz 30,_C_LABEL(battable)@l(31) 617 mtcr 30 618 bc 4,30,1f /* branch if supervisor valid is 619 false */ 620 mtibatu 3,30 621 622 /* get batl */ 623 lwz 30,_C_LABEL(battable)+4@l(31) 624 mtibatl 3,30 625 626 mtcr 29 /* restore CR */ 627 lmw 28,disisave(0) /* restore r28-r31 */ 628 rfi /* return to trapped code */ 6291: 630 b s_isitrap 631_C_LABEL(isisize)= .-_C_LABEL(isitrap) 632 633/* 634 * This one for the external interrupt handler. 635 */ 636 .globl _C_LABEL(extint),_C_LABEL(extsize) 637_C_LABEL(extint): 638 mtsprg 1,1 /* save SP */ 639 stmw 28,tempsave(0) /* free r28-r31 */ 640 mflr 28 /* save LR */ 641 mfcr 29 /* save CR */ 642 mfxer 30 /* save XER */ 643 lis 1,intstk+INTSTK@ha /* get interrupt stack */ 644 addi 1,1,intstk+INTSTK@l 645 lwz 31,0(1) /* were we already running on intstk? */ 646 addic. 31,31,1 647 stw 31,0(1) 648 beq 1f 649 mfsprg 1,1 /* yes, get old SP */ 6501: 651 lis 0,extintr@h 652 ori 0,0,extintr@l 653 mtlr 0 654 blr 655/* ba extintr*/ 656_C_LABEL(extsize) = .-_C_LABEL(extint) 657 658/* 659 * And this one for the decrementer interrupt handler. 660 */ 661 .globl _C_LABEL(decrint),_C_LABEL(decrsize) 662_C_LABEL(decrint): 663 mtsprg 1,1 /* save SP */ 664 stmw 28,tempsave(0) /* free r28-r31 */ 665 mflr 28 /* save LR */ 666 mfcr 29 /* save CR */ 667 mfxer 30 /* save XER */ 668 lis 1,intstk+INTSTK@ha /* get interrupt stack */ 669 addi 1,1,intstk+INTSTK@l 670 lwz 31,0(1) /* were we already running on intstk? */ 671 addic. 31,31,1 672 stw 31,0(1) 673 beq 1f 674 mfsprg 1,1 /* yes, get old SP */ 6751: 676 lis 0,decrintr@h 677 ori 0,0,decrintr@l 678 mtlr 0 679 blr 680/* ba decrintr*/ 681_C_LABEL(decrsize) = .-_C_LABEL(decrint) 682 683/* 684 * Now the tlb software load for 603 processors: 685 * (Code essentially from the 603e User Manual, Chapter 5, but 686 * corrected a lot.) 687 */ 688#define DMISS 976 689#define DCMP 977 690#define HASH1 978 691#define HASH2 979 692#define IMISS 980 693#define ICMP 981 694#define RPA 982 695 696 .globl _C_LABEL(tlbimiss),_C_LABEL(tlbimsize) 697_C_LABEL(tlbimiss): 698 mfspr 2,HASH1 /* get first pointer */ 699 li 1,8 700 mfctr 0 /* save counter */ 701 mfspr 3,ICMP /* get first compare value */ 702 addi 2,2,-8 /* predec pointer */ 7031: 704 mtctr 1 /* load counter */ 7052: 706 lwzu 1,8(2) /* get next pte */ 707 cmpl 0,1,3 /* see if found pte */ 708 bdneq 2b /* loop if not eq */ 709 bne 3f /* not found */ 710 lwz 1,4(2) /* load tlb entry lower word */ 711 andi. 3,1,8 /* check G-bit */ 712 bne 4f /* if guarded, take ISI */ 713 mtctr 0 /* restore counter */ 714 mfspr 0,IMISS /* get the miss address for the tlbli */ 715 mfsrr1 3 /* get the saved cr0 bits */ 716 mtcrf 0x80,3 /* and restore */ 717 ori 1,1,0x100 /* set the reference bit */ 718 mtspr RPA,1 /* set the pte */ 719 srwi 1,1,8 /* get byte 7 of pte */ 720 tlbli 0 /* load the itlb */ 721 stb 1,6(2) /* update page table */ 722 rfi 723 7243: /* not found in pteg */ 725 andi. 1,3,0x40 /* have we already done second hash? */ 726 bne 5f 727 mfspr 2,HASH2 /* get the second pointer */ 728 ori 3,3,0x40 /* change the compare value */ 729 li 1,8 730 addi 2,2,-8 /* predec pointer */ 731 b 1b 7324: /* guarded */ 733 mfsrr1 3 734 andi. 2,3,0xffff /* clean upper srr1 */ 735 oris 2,2,0x8000000@h /* set srr<4> to flag prot violation */ 736 b 6f 7375: /* not found anywhere */ 738 mfsrr1 3 739 andi. 2,3,0xffff /* clean upper srr1 */ 740 oris 2,2,0x40000000@h /* set srr1<1> to flag pte not found */ 7416: 742 mtctr 0 /* restore counter */ 743 mtsrr1 2 744 mfmsr 0 745 xoris 0,0,0x20000@h /* flip the msr<tgpr> bit */ 746 mtcrf 0x80,3 /* restore cr0 */ 747 mtmsr 0 /* now with native gprs */ 748 isync 749 ba EXC_ISI 750_C_LABEL(tlbimsize) = .-_C_LABEL(tlbimiss) 751 752 .globl _C_LABEL(tlbdlmiss),_C_LABEL(tlbdlmsize) 753_C_LABEL(tlbdlmiss): 754 mfspr 2,HASH1 /* get first pointer */ 755 li 1,8 756 mfctr 0 /* save counter */ 757 mfspr 3,DCMP /* get first compare value */ 758 addi 2,2,-8 /* predec pointer */ 7591: 760 mtctr 1 /* load counter */ 7612: 762 lwzu 1,8(2) /* get next pte */ 763 cmpl 0,1,3 /* see if found pte */ 764 bdneq 2b /* loop if not eq */ 765 bne 3f /* not found */ 766 lwz 1,4(2) /* load tlb entry lower word */ 767 mtctr 0 /* restore counter */ 768 mfspr 0,DMISS /* get the miss address for the tlbld */ 769 mfsrr1 3 /* get the saved cr0 bits */ 770 mtcrf 0x80,3 /* and restore */ 771 ori 1,1,0x100 /* set the reference bit */ 772 mtspr RPA,1 /* set the pte */ 773 srwi 1,1,8 /* get byte 7 of pte */ 774 tlbld 0 /* load the dtlb */ 775 stb 1,6(2) /* update page table */ 776 rfi 777 7783: /* not found in pteg */ 779 andi. 1,3,0x40 /* have we already done second hash? */ 780 bne 5f 781 mfspr 2,HASH2 /* get the second pointer */ 782 ori 3,3,0x40 /* change the compare value */ 783 li 1,8 784 addi 2,2,-8 /* predec pointer */ 785 b 1b 7865: /* not found anywhere */ 787 mfsrr1 3 788 lis 1,0x40000000@h /* set dsisr<1> to flag pte not found */ 789 mtctr 0 /* restore counter */ 790 andi. 2,3,0xffff /* clean upper srr1 */ 791 mtsrr1 2 792 mtdsisr 1 /* load the dsisr */ 793 mfspr 1,DMISS /* get the miss address */ 794 mtdar 1 /* put in dar */ 795 mfmsr 0 796 xoris 0,0,0x20000@h /* flip the msr<tgpr> bit */ 797 mtcrf 0x80,3 /* restore cr0 */ 798 mtmsr 0 /* now with native gprs */ 799 isync 800 ba EXC_DSI 801_C_LABEL(tlbdlmsize) = .-_C_LABEL(tlbdlmiss) 802 803 .globl _C_LABEL(tlbdsmiss),_C_LABEL(tlbdsmsize) 804_C_LABEL(tlbdsmiss): 805 mfspr 2,HASH1 /* get first pointer */ 806 li 1,8 807 mfctr 0 /* save counter */ 808 mfspr 3,DCMP /* get first compare value */ 809 addi 2,2,-8 /* predec pointer */ 8101: 811 mtctr 1 /* load counter */ 8122: 813 lwzu 1,8(2) /* get next pte */ 814 cmpl 0,1,3 /* see if found pte */ 815 bdneq 2b /* loop if not eq */ 816 bne 3f /* not found */ 817 lwz 1,4(2) /* load tlb entry lower word */ 818 andi. 3,1,0x80 /* check the C-bit */ 819 beq 4f 8205: 821 mtctr 0 /* restore counter */ 822 mfspr 0,DMISS /* get the miss address for the tlbld */ 823 mfsrr1 3 /* get the saved cr0 bits */ 824 mtcrf 0x80,3 /* and restore */ 825 mtspr RPA,1 /* set the pte */ 826 tlbld 0 /* load the dtlb */ 827 rfi 828 8293: /* not found in pteg */ 830 andi. 1,3,0x40 /* have we already done second hash? */ 831 bne 5f 832 mfspr 2,HASH2 /* get the second pointer */ 833 ori 3,3,0x40 /* change the compare value */ 834 li 1,8 835 addi 2,2,-8 /* predec pointer */ 836 b 1b 8374: /* found, but C-bit = 0 */ 838 rlwinm. 3,1,30,0,1 /* test PP */ 839 bge- 7f 840 andi. 3,1,1 841 beq+ 8f 8429: /* found, but protection violation (PP==00)*/ 843 mfsrr1 3 844 lis 1,0xa000000@h /* indicate protection violation 845 on store */ 846 b 1f 8477: /* found, PP=1x */ 848 mfspr 3,DMISS /* get the miss address */ 849 mfsrin 1,3 /* get the segment register */ 850 mfsrr1 3 851 rlwinm 3,3,18,31,31 /* get PR-bit */ 852 rlwnm. 2,2,3,1,1 /* get the key */ 853 bne- 9b /* protection violation */ 8548: /* found, set reference/change bits */ 855 lwz 1,4(2) /* reload tlb entry */ 856 ori 1,1,0x180 857 sth 1,6(2) 858 b 5b 8595: /* not found anywhere */ 860 mfsrr1 3 861 lis 1,0x42000000@h /* set dsisr<1> to flag pte not found */ 862 /* dsisr<6> to flag store */ 8631: 864 mtctr 0 /* restore counter */ 865 andi. 2,3,0xffff /* clean upper srr1 */ 866 mtsrr1 2 867 mtdsisr 1 /* load the dsisr */ 868 mfspr 1,DMISS /* get the miss address */ 869 mtdar 1 /* put in dar */ 870 mfmsr 0 871 xoris 0,0,0x20000@h /* flip the msr<tgpr> bit */ 872 mtcrf 0x80,3 /* restore cr0 */ 873 mtmsr 0 /* now with native gprs */ 874 isync 875 ba EXC_DSI 876_C_LABEL(tlbdsmsize) = .-_C_LABEL(tlbdsmiss) 877 878#ifdef DDB 879#define ddbsave 0xde0 /* primary save area for DDB */ 880/* 881 * In case of DDB we want a separate trap catcher for it 882 */ 883 .local ddbstk 884 .comm ddbstk,INTSTK,8 /* ddb stack */ 885 886 .globl _C_LABEL(ddblow),_C_LABEL(ddbsize) 887_C_LABEL(ddblow): 888 mtsprg 1,1 /* save SP */ 889 stmw 28,ddbsave(0) /* free r28-r31 */ 890 mflr 28 /* save LR */ 891 mfcr 29 /* save CR */ 892 lis 1,ddbstk+INTSTK@ha /* get new SP */ 893 addi 1,1,ddbstk+INTSTK@l 894 b ddbtrap 895_C_LABEL(ddbsize) = .-_C_LABEL(ddblow) 896#endif /* DDB */ 897 898#ifdef IPKDB 899#define ipkdbsave 0xde0 /* primary save area for IPKDB */ 900/* 901 * In case of IPKDB we want a separate trap catcher for it 902 */ 903 904 .local ipkdbstk 905 .comm ipkdbstk,INTSTK,8 /* ipkdb stack */ 906 907 .globl _C_LABEL(ipkdblow),_C_LABEL(ipkdbsize) 908_C_LABEL(ipkdblow): 909 mtsprg 1,1 /* save SP */ 910 stmw 28,ipkdbsave(0) /* free r28-r31 */ 911 mflr 28 /* save LR */ 912 mfcr 29 /* save CR */ 913 lis 1,ipkdbstk+INTSTK@ha /* get new SP */ 914 addi 1,1,ipkdbstk+INTSTK@l 915 bipkdbtrap 916_C_LABEL(ipkdbsize) = .-_C_LABEL(ipkdblow) 917#endif /* IPKDB */ 918 919/* 920 * FRAME_SETUP assumes: 921 * SPRG1 SP (1) 922 * savearea r28-r31,DAR,DSISR (DAR & DSISR only for DSI traps) 923 * 28 LR 924 * 29 CR 925 * 1 kernel stack 926 * LR trap type 927 * SRR0/1 as at start of trap 928 */ 929#define FRAME_SETUP(savearea) \ 930/* Have to enable translation to allow access of kernel stack: */ \ 931 mfsrr0 30; \ 932 mfsrr1 31; \ 933 stmw 30,savearea+24(0); \ 934 mfmsr 30; \ 935 ori 30,30,(PSL_DR|PSL_IR); \ 936 mtmsr 30; \ 937 isync; \ 938 mfsprg 31,1; \ 939 stwu 31,-FRAMELEN(1); \ 940 stw 0,FRAME_0+8(1); \ 941 stw 31,FRAME_1+8(1); \ 942 stw 28,FRAME_LR+8(1); \ 943 stw 29,FRAME_CR+8(1); \ 944 lmw 28,savearea(0); \ 945 stmw 2,FRAME_2+8(1); \ 946 lmw 28,savearea+16(0); \ 947 mfxer 3; \ 948 mfctr 4; \ 949 mflr 5; \ 950 andi. 5,5,0xff00; \ 951 stw 3,FRAME_XER+8(1); \ 952 stw 4,FRAME_CTR+8(1); \ 953 stw 5,FRAME_EXC+8(1); \ 954 stw 28,FRAME_DAR+8(1); \ 955 stw 29,FRAME_DSISR+8(1); \ 956 stw 30,FRAME_SRR0+8(1); \ 957 stw 31,FRAME_SRR1+8(1) 958 959#define FRAME_LEAVE(savearea) \ 960/* Now restore regs: */ \ 961 lwz 2,FRAME_SRR0+8(1); \ 962 lwz 3,FRAME_SRR1+8(1); \ 963 lwz 4,FRAME_CTR+8(1); \ 964 lwz 5,FRAME_XER+8(1); \ 965 lwz 6,FRAME_LR+8(1); \ 966 lwz 7,FRAME_CR+8(1); \ 967 stw 2,savearea(0); \ 968 stw 3,savearea+4(0); \ 969 mtctr 4; \ 970 mtxer 5; \ 971 mtlr 6; \ 972 mtsprg 1,7; /* save cr */ \ 973 lmw 2,FRAME_2+8(1); \ 974 lwz 0,FRAME_0+8(1); \ 975 lwz 1,FRAME_1+8(1); \ 976 mtsprg 2,2; /* save r2 & r3 */ \ 977 mtsprg 3,3; \ 978/* Disable translation, machine check and recoverability: */ \ 979 mfmsr 2; \ 980 andi. 2,2,~(PSL_DR|PSL_IR|PSL_ME|PSL_RI)@l; \ 981 mtmsr 2; \ 982 isync; \ 983/* Decide whether we return to user mode: */ \ 984 lwz 3,savearea+4(0); \ 985 mtcr 3; \ 986 bc 4,17,1f; /* branch if PSL_PR is false */ \ 987/* Restore user & kernel access SR: */ \ 988 lis 2,_C_LABEL(curpm)@ha; /* get real address of pmap */ \ 989 lwz 2,_C_LABEL(curpm)@l(2); \ 990 lwz 3,PM_USRSR(2); \ 991 mtsr USER_SR,3; \ 992 lwz 3,PM_KERNELSR(2); \ 993 mtsr KERNEL_SR,3; \ 9941: mfsprg 2,1; /* restore cr */ \ 995 mtcr 2; \ 996 lwz 2,savearea(0); \ 997 lwz 3,savearea+4(0); \ 998 mtsrr0 2; \ 999 mtsrr1 3; \ 1000 mfsprg 2,2; /* restore r2 & r3 */ \ 1001 mfsprg 3,3 1002 1003/* 1004 * Preamble code for DSI/ISI traps 1005 */ 1006disitrap: 1007 lmw 30,disisave(0) 1008 stmw 30,tempsave(0) 1009 lmw 30,disisave+8(0) 1010 stmw 30,tempsave+8(0) 1011 mfdar 30 1012 mfdsisr 31 1013 stmw 30,tempsave+16(0) 1014realtrap: 1015/* Test whether we already had PR set */ 1016 mfsrr1 1 1017 mtcr 1 1018 mfsprg 1,1 /* restore SP (might have been 1019 overwritten) */ 1020 bc 4,17,s_trap /* branch if PSL_PR is false */ 1021 lis 1,_C_LABEL(curpcb)@ha 1022 lwz 1,_C_LABEL(curpcb)@l(1) 1023 addi 1,1,USPACE /* stack is top of user struct */ 1024 1025/* 1026 * Now the common trap catching code. 1027 */ 1028s_trap: 1029/* First have to enable KERNEL mapping */ 1030 lis 31,KERNEL_SEGMENT@h 1031 ori 31,31,KERNEL_SEGMENT@l 1032 mtsr KERNEL_SR,31 1033 FRAME_SETUP(tempsave) 1034/* Now we can recover interrupts again: */ 1035 mfmsr 7 1036 ori 7,7,(PSL_EE|PSL_ME|PSL_RI)@l 1037 mtmsr 7 1038 isync 1039/* Call C trap code: */ 1040trapagain: 1041 addi 3,1,8 1042 bl _C_LABEL(trap) 1043trapexit: 1044/* Disable interrupts: */ 1045 mfmsr 3 1046 andi. 3,3,~PSL_EE@l 1047 mtmsr 3 1048/* Test AST pending: */ 1049 lwz 5,FRAME_SRR1+8(1) 1050 mtcr 5 1051 bc 4,17,1f /* branch if PSL_PR is false */ 1052 lis 3,_C_LABEL(astpending)@ha 1053 lwz 4,_C_LABEL(astpending)@l(3) 1054 andi. 4,4,1 1055 beq 1f 1056 li 6,EXC_AST 1057 stw 6,FRAME_EXC+8(1) 1058 b trapagain 10591: 1060 FRAME_LEAVE(tempsave) 1061 rfi 1062 1063/* 1064 * Child comes here at the end of a fork. 1065 * Mostly similar to the above. 1066 */ 1067 .globl _C_LABEL(fork_trampoline) 1068_C_LABEL(fork_trampoline): 1069 xor 3,3,3 1070 bl _C_LABEL(lcsplx) 1071 mtlr 31 1072 mr 3,30 1073 blrl /* jump indirect to r31 */ 1074 b trapexit 1075 1076/* 1077 * DSI second stage fault handler 1078 */ 1079s_dsitrap: 1080 mfdsisr 31 /* test whether this may be a 1081 spill fault */ 1082 mtcr 31 1083 mtsprg 1,1 /* save SP */ 1084 bc 4,1,disitrap /* branch if table miss is false */ 1085 lis 1,spillstk+SPILLSTK@ha 1086 addi 1,1,spillstk+SPILLSTK@l /* get spill stack */ 1087 stwu 1,-52(1) 1088 stw 0,48(1) /* save non-volatile registers */ 1089 stw 3,44(1) 1090 stw 4,40(1) 1091 stw 5,36(1) 1092 stw 6,32(1) 1093 stw 7,28(1) 1094 stw 8,24(1) 1095 stw 9,20(1) 1096 stw 10,16(1) 1097 stw 11,12(1) 1098 stw 12,8(1) 1099 mflr 30 /* save trap type */ 1100 mfctr 31 /* & CTR */ 1101 mfdar 3 1102s_pte_spill: 1103 bl _C_LABEL(pmap_pte_spill) /* try a spill */ 1104 or. 3,3,3 1105 mtctr 31 /* restore CTR */ 1106 mtlr 30 /* and trap type */ 1107 mfsprg 31,2 /* get saved XER */ 1108 mtxer 31 /* restore XER */ 1109 lwz 12,8(1) /* restore non-volatile registers */ 1110 lwz 11,12(1) 1111 lwz 10,16(1) 1112 lwz 9,20(1) 1113 lwz 8,24(1) 1114 lwz 7,28(1) 1115 lwz 6,32(1) 1116 lwz 5,36(1) 1117 lwz 4,40(1) 1118 lwz 3,44(1) 1119 lwz 0,48(1) 1120 beq disitrap 1121 mfsprg 1,1 /* restore SP */ 1122 mtcr 29 /* restore CR */ 1123 mtlr 28 /* restore LR */ 1124 lmw 28,disisave(0) /* restore r28-r31 */ 1125 rfi /* return to trapped code */ 1126 1127/* 1128 * ISI second stage fault handler 1129 */ 1130s_isitrap: 1131 mfsrr1 31 /* test whether this may be a 1132 spill fault */ 1133 mtcr 31 1134 mtsprg 1,1 /* save SP */ 1135 bc 4,1,disitrap /* branch if table miss is false */ 1136 lis 1,spillstk+SPILLSTK@ha 1137 addi 1,1,spillstk+SPILLSTK@l /* get spill stack */ 1138 stwu 1,-52(1) 1139 stw 0,48(1) /* save non-volatile registers */ 1140 stw 3,44(1) 1141 stw 4,40(1) 1142 stw 5,36(1) 1143 stw 6,32(1) 1144 stw 7,28(1) 1145 stw 8,24(1) 1146 stw 9,20(1) 1147 stw 10,16(1) 1148 stw 11,12(1) 1149 stw 12,8(1) 1150 mfxer 30 /* save XER */ 1151 mtsprg 2,30 1152 mflr 30 /* save trap type */ 1153 mfctr 31 /* & ctr */ 1154 mfsrr0 3 1155 b s_pte_spill /* above */ 1156 1157/* 1158 * External interrupt second level handler 1159 */ 1160#define INTRENTER \ 1161/* Save non-volatile registers: */ \ 1162 stwu 1,-88(1); /* temporarily */ \ 1163 stw 0,84(1); \ 1164 mfsprg 0,1; /* get original SP */ \ 1165 stw 0,0(1); /* and store it */ \ 1166 stw 3,80(1); \ 1167 stw 4,76(1); \ 1168 stw 5,72(1); \ 1169 stw 6,68(1); \ 1170 stw 7,64(1); \ 1171 stw 8,60(1); \ 1172 stw 9,56(1); \ 1173 stw 10,52(1); \ 1174 stw 11,48(1); \ 1175 stw 12,44(1); \ 1176 stw 28,40(1); /* saved LR */ \ 1177 stw 29,36(1); /* saved CR */ \ 1178 stw 30,32(1); /* saved XER */ \ 1179 lmw 28,tempsave(0); /* restore r28-r31 */ \ 1180 mfctr 6; \ 1181 lis 5,_C_LABEL(intr_depth)@ha; \ 1182 lwz 5,_C_LABEL(intr_depth)@l(5); \ 1183 mfsrr0 4; \ 1184 mfsrr1 3; \ 1185 stw 6,28(1); \ 1186 stw 5,20(1); \ 1187 stw 4,12(1); \ 1188 stw 3,8(1); \ 1189/* interrupts are recoverable here, and enable translation */ \ 1190 lis 3,(KERNEL_SEGMENT|SR_SUKEY|SR_PRKEY)@h; \ 1191 ori 3,3,(KERNEL_SEGMENT|SR_SUKEY|SR_PRKEY)@l; \ 1192 mtsr KERNEL_SR,3; \ 1193 mfmsr 5; \ 1194 ori 5,5,(PSL_IR|PSL_DR|PSL_RI); \ 1195 mtmsr 5; \ 1196 isync 1197 1198 .globl _C_LABEL(extint_call) 1199extintr: 1200 INTRENTER 1201_C_LABEL(extint_call): 1202/* 1203 lis 0,intrhand@h 1204 ori 0,0,intrhand@l 1205 mtlr 0 1206 blr*/ 1207 bl _C_LABEL(intrhand) 1208/* bl _C_LABEL(extint_call)*/ /* to be filled in later */ 1209 1210intr_exit: 1211/* Disable interrupts (should already be disabled) and MMU here: */ 1212 mfmsr 3 1213 andi. 3,3,~(PSL_EE|PSL_ME|PSL_RI|PSL_DR|PSL_IR)@l 1214 mtmsr 3 1215 isync 1216/* restore possibly overwritten registers: */ 1217 lwz 12,44(1) 1218 lwz 11,48(1) 1219 lwz 10,52(1) 1220 lwz 9,56(1) 1221 lwz 8,60(1) 1222 lwz 7,64(1) 1223 lwz 6,8(1) 1224 lwz 5,12(1) 1225 lwz 4,28(1) 1226 lwz 3,32(1) 1227 mtsrr1 6 1228 mtsrr0 5 1229 mtctr 4 1230 mtxer 3 1231/* Returning to user mode? */ 1232 mtcr 6 /* saved SRR1 */ 1233 bc 4,17,1f /* branch if PSL_PR is false */ 1234 lis 3,_C_LABEL(curpm)@ha /* get current pmap real address */ 1235 lwz 3,_C_LABEL(curpm)@l(3) 1236 lwz 3,PM_KERNELSR(3) 1237 mtsr KERNEL_SR,3 /* Restore kernel SR */ 1238 lis 3,_C_LABEL(astpending)@ha /* Test AST pending */ 1239 lwz 4,_C_LABEL(astpending)@l(3) 1240 andi. 4,4,1 1241 beq 1f 1242/* Setup for entry to realtrap: */ 1243 lwz 3,0(1) /* get saved SP */ 1244 mtsprg 1,3 1245 li 6,EXC_AST 1246 stmw 28,tempsave(0) /* establish tempsave again */ 1247 mtlr 6 1248 lwz 28,40(1) /* saved LR */ 1249 lwz 29,36(1) /* saved CR */ 1250 lwz 6,68(1) 1251 lwz 5,72(1) 1252 lwz 4,76(1) 1253 lwz 3,80(1) 1254 lwz 0,84(1) 1255 lis 30,_C_LABEL(intr_depth)@ha /* adjust reentrancy count */ 1256 lwz 31,_C_LABEL(intr_depth)@l(30) 1257 addi 31,31,-1 1258 stw 31,_C_LABEL(intr_depth)@l(30) 1259 b realtrap 12601: 1261/* Here is the normal exit of extintr: */ 1262 lwz 5,36(1) 1263 lwz 6,40(1) 1264 mtcr 5 1265 mtlr 6 1266 lwz 6,68(1) 1267 lwz 5,72(1) 1268 lis 3,_C_LABEL(intr_depth)@ha /* adjust reentrancy count */ 1269 lwz 4,_C_LABEL(intr_depth)@l(3) 1270 addi 4,4,-1 1271 stw 4,_C_LABEL(intr_depth)@l(3) 1272 lwz 4,76(1) 1273 lwz 3,80(1) 1274 lwz 0,84(1) 1275 lwz 1,0(1) 1276 rfi 1277 1278/* 1279 * Decrementer interrupt second level handler 1280 */ 1281decrintr: 1282 INTRENTER 1283 addi 3,1,8 /* intr frame */ 1284 /*bl _C_LABEL(decr_intr)*/ 1285 b intr_exit 1286 1287#ifdef DDB 1288/* 1289 * Deliberate entry to ddbtrap 1290 */ 1291 .globl _C_LABEL(ddb_trap) 1292_C_LABEL(ddb_trap): 1293 mtsprg 1,1 1294 mfmsr 3 1295 mtsrr1 3 1296 andi. 3,3,~(PSL_EE|PSL_ME)@l 1297 mtmsr 3 /* disable interrupts */ 1298 isync 1299 stmw 28,ddbsave(0) 1300 mflr 28 1301 li 29,EXC_BPT 1302 mtlr 29 1303 mfcr 29 1304 mtsrr0 28 1305 1306/* 1307 * Now the ddb trap catching code. 1308 */ 1309ddbtrap: 1310 FRAME_SETUP(ddbsave) 1311/* Call C trap code: */ 1312 addi 3,1,8 1313 bl _C_LABEL(ddb_trap_glue) 1314 or. 3,3,3 1315 bne ddbleave 1316/* This wasn't for DDB, so switch to real trap: */ 1317 lwz 3,FRAME_EXC+8(1) /* save exception */ 1318 stw 3,ddbsave+8(0) 1319 FRAME_LEAVE(ddbsave) 1320 mtsprg 1,1 /* prepare for entrance to realtrap */ 1321 stmw 28,tempsave(0) 1322 mflr 28 1323 mfcr 29 1324 lwz 31,ddbsave+8(0) 1325 mtlr 31 1326 b realtrap 1327ddbleave: 1328 FRAME_LEAVE(ddbsave) 1329 rfi 1330#endif /* DDB */ 1331 1332#ifdef IPKDB 1333/* 1334 * Deliberate entry to ipkdbtrap 1335 */ 1336 .globl _C_LABEL(ipkdb_trap) 1337_C_LABEL(ipkdb_trap): 1338 mtsprg 1,1 1339 mfmsr 3 1340 mtsrr1 3 1341 andi. 3,3,~(PSL_EE|PSL_ME)@l 1342 mtmsr 3 /* disable interrupts */ 1343 isync 1344 stmw 28,ipkdbsave(0) 1345 mflr 28 1346 li 29,EXC_BPT 1347 mtlr 29 1348 mfcr 29 1349 mtsrr0 28 1350 1351/* 1352 * Now the ipkdb trap catching code. 1353 */ 1354ipkdbtrap: 1355 FRAME_SETUP(ipkdbsave) 1356/* Call C trap code: */ 1357 addi 3,1,8 1358 bl _C_LABEL(ipkdb_trap_glue) 1359 or. 3,3,3 1360 bne ipkdbleave 1361/* This wasn't for IPKDB, so switch to real trap: */ 1362 lwz 3,FRAME_EXC+8(1) /* save exception */ 1363 stw 3,ipkdbsave+8(0) 1364 FRAME_LEAVE(ipkdbsave) 1365 mtsprg 1,1 /* prepare for entrance to realtrap */ 1366 stmw 28,tempsave(0) 1367 mflr 28 1368 mfcr 29 1369 lwz 31,ipkdbsave+8(0) 1370 mtlr 31 1371 b realtrap 1372ipkdbleave: 1373 FRAME_LEAVE(ipkdbsave) 1374 rfi 1375 1376ipkdbfault: 1377 ba _ipkdbfault 1378_ipkdbfault: 1379 mfsrr0 3 1380 addi 3,3,4 1381 mtsrr0 3 1382 li 3,-1 1383 rfi 1384 1385/* 1386 * int ipkdbfbyte(unsigned char *p) 1387 */ 1388 .globl _C_LABEL(ipkdbfbyte) 1389_C_LABEL(ipkdbfbyte): 1390 li 9,EXC_DSI /* establish new fault routine */ 1391 lwz 5,0(9) 1392 lis 6,ipkdbfault@ha 1393 lwz 6,ipkdbfault@l(6) 1394 stw 6,0(9) 1395#ifdef IPKDBUSERHACK 1396 lis 8,_C_LABEL(ipkdbsr)@ha 1397 lwz 8,_C_LABEL(ipkdbsr)@l(8) 1398 mtsr USER_SR,8 1399 isync 1400#endif 1401 dcbst 0,9 /* flush data... */ 1402 sync 1403 icbi 0,9 /* and instruction caches */ 1404 lbz 3,0(3) /* fetch data */ 1405 stw 5,0(9) /* restore previous fault handler */ 1406 dcbst 0,9 /* and flush data... */ 1407 sync 1408 icbi 0,9 /* and instruction caches */ 1409 blr 1410 1411/* 1412 * int ipkdbsbyte(unsigned char *p, int c) 1413 */ 1414 .globl _C_LABEL(ipkdbsbyte) 1415_C_LABEL(ipkdbsbyte): 1416 li 9,EXC_DSI /* establish new fault routine */ 1417 lwz 5,0(9) 1418 lis 6,ipkdbfault@ha 1419 lwz 6,ipkdbfault@l(6) 1420 stw 6,0(9) 1421#ifdef IPKDBUSERHACK 1422 lis 8,_C_LABEL(ipkdbsr)@ha 1423 lwz 8,_C_LABEL(ipkdbsr)@l(8) 1424 mtsr USER_SR,8 1425 isync 1426#endif 1427 dcbst 0,9 /* flush data... */ 1428 sync 1429 icbi 0,9 /* and instruction caches */ 1430 mr 6,3 1431 xor 3,3,3 1432 stb 4,0(6) 1433 dcbst 0,6 /* Now do appropriate flushes 1434 to data... */ 1435 sync 1436 icbi 0,6 /* and instruction caches */ 1437 stw 5,0(9) /* restore previous fault handler */ 1438 dcbst 0,9 /* and flush data... */ 1439 sync 1440 icbi 0,9 /* and instruction caches */ 1441 blr 1442#endif /* IPKDB */ 1443 1444/* 1445 * int setfault() 1446 * 1447 * Similar to setjmp to setup for handling faults on accesses to user memory. 1448 * Any routine using this may only call bcopy, either the form below, 1449 * or the (currently used) C code optimized, so it doesn't use any non-volatile 1450 * registers. 1451 */ 1452 .globl _C_LABEL(setfault) 1453_C_LABEL(setfault): 1454 mflr 0 1455 mfcr 12 1456 lis 4,_C_LABEL(curpcb)@ha 1457 lwz 4,_C_LABEL(curpcb)@l(4) 1458 stw 3,PCB_FAULT(4) 1459 stw 0,0(3) 1460 stw 1,4(3) 1461 stw 2,8(3) 1462 stmw 12,12(3) 1463 xor 3,3,3 1464 blr 1465 1466