Annotation of sys/arch/mvmeppc/mvmeppc/locore.S, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: locore.S,v 1.12 2005/11/24 12:08:16 pedro Exp $ */
! 2: /* $NetBSD: locore.S,v 1.2 1996/10/16 19:33:09 ws Exp $ */
! 3:
! 4: /*
! 5: * Copyright (C) 1995, 1996 Wolfgang Solfrank.
! 6: * Copyright (C) 1995, 1996 TooLs GmbH.
! 7: * All rights reserved.
! 8: *
! 9: * Redistribution and use in source and binary forms, with or without
! 10: * modification, are permitted provided that the following conditions
! 11: * are met:
! 12: * 1. Redistributions of source code must retain the above copyright
! 13: * notice, this list of conditions and the following disclaimer.
! 14: * 2. Redistributions in binary form must reproduce the above copyright
! 15: * notice, this list of conditions and the following disclaimer in the
! 16: * documentation and/or other materials provided with the distribution.
! 17: * 3. All advertising materials mentioning features or use of this software
! 18: * must display the following acknowledgement:
! 19: * This product includes software developed by TooLs GmbH.
! 20: * 4. The name of TooLs GmbH may not be used to endorse or promote products
! 21: * derived from this software without specific prior written permission.
! 22: *
! 23: * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
! 24: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
! 25: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
! 26: * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
! 27: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
! 28: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
! 29: * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
! 30: * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
! 31: * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
! 32: * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
! 33: */
! 34:
! 35: #include "assym.h"
! 36:
! 37: #include <sys/syscall.h>
! 38:
! 39: #include <machine/asm.h>
! 40: #include <machine/param.h>
! 41: #include <machine/pmap.h>
! 42: #include <machine/psl.h>
! 43: #include <machine/trap.h>
! 44:
! 45: /*
! 46: * Globals
! 47: */
! 48: .globl _C_LABEL(esym),_C_LABEL(proc0paddr)
! 49: .type _C_LABEL(esym),@object
! 50: .type _C_LABEL(proc0paddr),@object
! 51: .data
! 52: _C_LABEL(esym): .long 0 /* end of symbol table */
! 53: _C_LABEL(proc0paddr): .long 0 /* proc0 p_addr */
! 54: idle_u: .long 0 /* fake uarea during idle after exit */
! 55:
! 56: /*
! 57: * Startup entry
! 58: */
! 59: _ENTRY(_C_LABEL(kernel_text))
! 60: _ENTRY(_ASM_LABEL(start))
! 61: /*
! 62: * Arguments to start for mvmeppc
! 63: * r1 - stack provided by firmware/bootloader
! 64: * r3 - boot flags
! 65: * r4 - boot device
! 66: * r5 - firmware pointer (NULL for PPC1bug)
! 67: * r6 - arg list (NULL)
! 68: * r7 - length (0)
! 69: * r8 - end of symbol table
! 70: */
! 71: .globl start
! 72: .type start,@function
! 73: start:
! 74: li %r0,0
! 75: mtmsr %r0 /* Disable FPU/MMU/exceptions */
! 76: isync
! 77:
! 78: /* save boot device and flags */
! 79: lis %r9, _C_LABEL(boothowto)@ha
! 80: stw %r3, _C_LABEL(boothowto)@l(%r9)
! 81: lis %r9, _C_LABEL(bootdev)@ha
! 82: stw %r4, _C_LABEL(bootdev)@l(%r9)
! 83:
! 84: /* compute end of kernel memory */
! 85: #if defined(DDB)
! 86: lis %r9,_C_LABEL(esym)@ha
! 87: stw %r8,_C_LABEL(esym)@l(%r9) /* save for symbol handling */
! 88: #else
! 89: lis %r8,_end@ha
! 90: addi %r8,%r8,_end@l
! 91: #endif
! 92: li %r9,PGOFSET
! 93: add %r8,%r8,%r9
! 94: andc %r8,%r8,%r9
! 95: lis %r9,idle_u@ha
! 96: stw %r8,idle_u@l(%r9)
! 97: addi %r8,%r8,USPACE /* space for idle_u */
! 98: lis %r9,_C_LABEL(proc0paddr)@ha
! 99: stw %r8,_C_LABEL(proc0paddr)@l(%r9)
! 100: addi %r1,%r8,USPACE-FRAMELEN /* stackpointer for proc0 */
! 101: mr %r4,%r1 /* end of mem reserved for kernel */
! 102: li %r0,0
! 103: stwu %r0,-16(%r1) /* end of stack chain */
! 104:
! 105: lis %r3,start@ha
! 106: addi %r3,%r3,start@l
! 107: mr %r5,%r6 /* args string */
! 108: bl _C_LABEL(initppc)
! 109: bl _C_LABEL(main)
! 110: b _C_LABEL(PPC1_exit)
! 111:
! 112: /*
! 113: * No processes are runnable, so loop waiting for one.
! 114: * Separate label here for accounting purposes.
! 115: */
! 116: _C_LABEL(idle):
! 117: mfmsr %r3
! 118: /* disable interrupts while manipulating runque */
! 119: andi. %r3,%r3,~PSL_EE@l
! 120: mtmsr %r3
! 121:
! 122: lis %r8,_C_LABEL(whichqs)@ha
! 123: lwz %r9,_C_LABEL(whichqs)@l(%r8)
! 124:
! 125: or. %r9,%r9,%r9
! 126: bne- _C_LABEL(sw1) /* at least one queue non-empty */
! 127:
! 128: ori %r3,%r3,PSL_EE /* reenable ints again */
! 129: mtmsr %r3
! 130: isync
! 131: sync
! 132: /* low power mode */
! 133: mfmsr %r3
! 134: oris %r3, %r3, PSL_POW@h
! 135: mtmsr %r3
! 136: isync
! 137:
! 138: /* May do some power saving here? */
! 139:
! 140: b _C_LABEL(idle)
! 141:
! 142: /*
! 143: * switchexit gets called from cpu_exit to free the user structure
! 144: * and kernel stack of the current process.
! 145: */
! 146: _ENTRY(_C_LABEL(switchexit))
! 147: /* First switch to the idle pcb/kernel stack */
! 148: lis %r6,idle_u@ha
! 149: lwz %r6,idle_u@l(%r6)
! 150: lis %r7,_C_LABEL(curpcb)@ha
! 151: stw %r6,_C_LABEL(curpcb)@l(%r7)
! 152: addi %r1,%r6,USPACE-16 /* 16 bytes are reserved at stack top */
! 153: /*
! 154: * Schedule the vmspace and stack to be freed (the proc arg is
! 155: * already in r3).
! 156: */
! 157: bl _C_LABEL(exit2)
! 158:
! 159: /* Fall through to cpu_switch to actually select another proc */
! 160: li %r3,0 /* indicate exited process */
! 161:
! 162: /* Fall through to cpu_switch to actually select another proc */
! 163:
! 164: /*
! 165: * void cpu_switch(struct proc *p)
! 166: * Find a runnable process and switch to it.
! 167: */
! 168: _ENTRY(_C_LABEL(cpu_switch))
! 169: mflr %r0 /* save lr */
! 170: stw %r0,4(%r1)
! 171: stwu %r1,-16(%r1)
! 172: stw %r31,12(%r1)
! 173: stw %r30,8(%r1)
! 174:
! 175: mr %r30,%r3
! 176: lis %r3,_C_LABEL(curproc)@ha
! 177: li %r31,0
! 178: /* Zero to not accumulate cpu time */
! 179: stw %r31,_C_LABEL(curproc)@l(%r3)
! 180: lis %r3,_C_LABEL(curpcb)@ha
! 181: lwz %r31,_C_LABEL(curpcb)@l(%r3)
! 182:
! 183: li %r3,0
! 184: bl _C_LABEL(lcsplx)
! 185: stw %r3,PCB_SPL(%r31) /* save spl */
! 186:
! 187: /* Find a new process */
! 188: mfmsr %r3
! 189: andi. %r3,%r3,~PSL_EE@l /* disable interrupts while
! 190: manipulating runque */
! 191: mtmsr %r3
! 192: isync
! 193:
! 194: lis %r8,_C_LABEL(whichqs)@ha
! 195: lwz %r9,_C_LABEL(whichqs)@l(%r8)
! 196:
! 197: or. %r9,%r9,%r9
! 198: beq- _C_LABEL(idle) /* all queues empty */
! 199: _C_LABEL(sw1):
! 200: cntlzw %r10,%r9
! 201: lis %r4,_C_LABEL(qs)@ha
! 202: addi %r4,%r4,_C_LABEL(qs)@l
! 203: slwi %r3,%r10,3
! 204: add %r3,%r3,%r4 /* select queue */
! 205:
! 206: lwz %r31,P_FORW(%r3) /* unlink first proc from queue */
! 207: lwz %r4,P_FORW(%r31)
! 208: stw %r4,P_FORW(%r3)
! 209: stw %r3,P_BACK(%r4)
! 210:
! 211: cmpl 0,%r3,%r4 /* queue empty? */
! 212: bne 1f
! 213:
! 214: lis %r3,0x80000000@ha
! 215: srw %r3,%r3,%r10
! 216: andc %r9,%r9,%r3
! 217: stw %r9,_C_LABEL(whichqs)@l(%r8) /* mark it empty */
! 218:
! 219: 1:
! 220: /* just did this resched thing, clear resched */
! 221: li %r3,0
! 222: lis %r4,_C_LABEL(want_resched)@ha
! 223: stw %r3,_C_LABEL(want_resched)@l(%r4)
! 224:
! 225: stw %r3,P_BACK(%r31) /* probably superfluous */
! 226:
! 227: lis %r4,_C_LABEL(curproc)@ha
! 228: stw %r31,_C_LABEL(curproc)@l(%r4) /* record new process */
! 229:
! 230: li %r3,SONPROC
! 231: stb %r3,P_STAT(%r31)
! 232:
! 233: mfmsr %r3
! 234: ori %r3,%r3,PSL_EE /* Now we can interrupt again */
! 235: mtmsr %r3
! 236:
! 237: cmpl 0,%r31,%r30 /* is it the same process? */
! 238: beq switch_return
! 239:
! 240: or. %r30,%r30,%r30 /* old process was exiting? */
! 241: beq switch_exited
! 242:
! 243: mfsr %r10,PPC_USER_SR /* save PPC_USER_SR for copyin/copyout*/
! 244: mfcr %r11 /* save cr */
! 245: mr %r12,%r2 /* save r2 */
! 246: stwu %r1,-SFRAMELEN(%r1) /* still running on old stack */
! 247: stmw %r10,8(%r1)
! 248: lwz %r3,P_ADDR(%r30)
! 249: stw %r1,PCB_SP(%r3) /* save SP */
! 250:
! 251: switch_exited:
! 252: /* disable interrupts while actually switching */
! 253: mfmsr %r3
! 254: andi. %r3,%r3,~PSL_EE@l
! 255: mtmsr %r3
! 256:
! 257: lwz %r4,P_ADDR(%r31)
! 258: lis %r5,_C_LABEL(curpcb)@ha
! 259: stw %r4,_C_LABEL(curpcb)@l(%r5) /* indicate new pcb */
! 260:
! 261: lwz %r5,PCB_PMR(%r4)
! 262:
! 263: /* save real pmap pointer for spill fill */
! 264: lis %r6,_C_LABEL(curpm)@ha
! 265: stwu %r5,_C_LABEL(curpm)@l(%r6)
! 266: stwcx. %r5,%r0,%r6 /* clear possible reservation */
! 267:
! 268: addic. %r5,%r5,64
! 269: li %r6,0
! 270: mfsr %r8,PPC_KERNEL_SR /* save kernel SR */
! 271: 1:
! 272: addis %r6,%r6,-0x10000000@ha /* set new procs segment registers */
! 273: or. %r6,%r6,%r6 /* This is done from the real address pmap */
! 274: lwzu %r7,-4(%r5) /* so we don't have to worry */
! 275: mtsrin %r7,%r6 /* about accessibility */
! 276: bne 1b
! 277: mtsr PPC_KERNEL_SR,%r8 /* restore kernel SR */
! 278: isync
! 279:
! 280: lwz %r1,PCB_SP(%r4) /* get new procs SP */
! 281:
! 282: ori %r3,%r3,PSL_EE /* interrupts are okay again */
! 283: mtmsr %r3
! 284:
! 285: lmw %r10,8(%r1) /* get other regs */
! 286: lwz %r1,0(%r1) /* get saved SP */
! 287: mr %r2,%r12 /* get saved r2 */
! 288: mtcr %r11 /* get saved cr */
! 289: isync
! 290: mtsr PPC_USER_SR,%r10 /* get saved PPC_USER_SR */
! 291: isync
! 292:
! 293: switch_return:
! 294: mr %r30,%r7 /* save proc pointer */
! 295: lwz %r3,PCB_SPL(%r4)
! 296: bl _C_LABEL(lcsplx)
! 297:
! 298: mr %r3,%r30 /* curproc for special fork returns */
! 299:
! 300: lwz %r31,12(%r1)
! 301: lwz %r30,8(%r1)
! 302: addi %r1,%r1,16
! 303: lwz %r0,4(%r1)
! 304: mtlr %r0
! 305: blr
! 306:
! 307:
! 308: /*
! 309: * Data used during primary/secondary traps/interrupts
! 310: */
! 311: #define tempsave 0x2e0 /* primary save area for trap handling */
! 312: #define disisave 0x3e0 /* primary save area for dsi/isi traps */
! 313: #define INTSTK (8*1024) /* 8K interrupt stack */
! 314: .data
! 315: intstk: .space INTSTK /* interrupt stack */
! 316: .global _C_LABEL(intr_depth)
! 317: .type _C_LABEL(intr_depth),@object
! 318: _C_LABEL(intr_depth):
! 319: .long -1 /* in-use marker */
! 320: #define SPILLSTK 1024 /* 1K spill stack */
! 321: .lcomm spillstk,SPILLSTK,8
! 322:
! 323: /*
! 324: * This code gets copied to all the trap vectors
! 325: * except ISI/DSI, ALI, and the interrupts
! 326: */
! 327: .text
! 328: .globl _C_LABEL(trapcode),_C_LABEL(trapsize)
! 329: .type _C_LABEL(trapcode),@function
! 330: .type _C_LABEL(trapsize),@object
! 331: _C_LABEL(trapcode):
! 332: mtsprg 1,%r1 /* save SP */
! 333: stmw %r28,tempsave(%r0) /* free r28-r31 */
! 334: mflr %r28 /* save LR */
! 335: mfcr %r29 /* save CR */
! 336:
! 337: /* Test whether we already had PR set */
! 338: mfsrr1 %r31
! 339: mtcr %r31
! 340: bc 4,17,1f /* branch if PSL_PR is clear */
! 341: lis %r1,_C_LABEL(curpcb)@ha
! 342: lwz %r1,_C_LABEL(curpcb)@l(%r1)
! 343: addi %r1,%r1,USPACE /* stack is top of user struct */
! 344: 1:
! 345: bla s_trap
! 346: _C_LABEL(trapsize) = .-_C_LABEL(trapcode)
! 347:
! 348: /*
! 349: * For ALI: has to save DSISR and DAR
! 350: */
! 351: .globl _C_LABEL(alitrap),_C_LABEL(alisize)
! 352: _C_LABEL(alitrap):
! 353: mtsprg 1,%r1 /* save SP */
! 354: stmw %r28,tempsave(0) /* free r28-r31 */
! 355: mfdar %r30
! 356: mfdsisr %r31
! 357: stmw %r30,tempsave+16(0)
! 358: mflr %r28 /* save LR */
! 359: mfcr %r29 /* save CR */
! 360:
! 361: /* Test whether we already had PR set */
! 362: mfsrr1 %r31
! 363: mtcr %r31
! 364: bc 4,17,1f /* branch if PSL_PR is clear */
! 365: lis %r1,_C_LABEL(curpcb)@ha
! 366: lwz %r1,_C_LABEL(curpcb)@l(%r1)
! 367: addi %r1,%r1,USPACE /* stack is top of user struct */
! 368: 1:
! 369: bla s_trap
! 370: _C_LABEL(alisize) = .-_C_LABEL(alitrap)
! 371:
! 372: /*
! 373: * Similar to the above for DSI
! 374: * Has to handle BAT spills
! 375: * and standard pagetable spills
! 376: */
! 377: .globl _C_LABEL(dsitrap),_C_LABEL(dsisize)
! 378: .type _C_LABEL(dsitrap),@function
! 379: .type _C_LABEL(dsisize),@object
! 380: _C_LABEL(dsitrap):
! 381: stmw %r28,disisave(0) /* free r28-r31 */
! 382: mfcr %r29 /* save CR */
! 383: mfxer %r30 /* save XER */
! 384: mtsprg 2,%r30 /* in SPRG2 */
! 385: mfsrr1 %r31 /* test kernel mode */
! 386: #if 0
! 387: mtcr %r31
! 388: bc 12,17,1f /* branch if PSL_PR is set */
! 389: mfdar %r31 /* get fault address */
! 390: rlwinm %r31,%r31,7,25,28 /* get segment * 8 */
! 391: addis %r31,%r31,_C_LABEL(battable)@ha
! 392: lwz %r30,_C_LABEL(battable)@l(%r31) /* get batu */
! 393: mtcr %r30
! 394: bc 4,30,1f /* branch if supervisor valid is false */
! 395: lwz %r31,_C_LABEL(battable)+4@l(%r31) /* get batl */
! 396: /* We randomly use the highest two bat registers here */
! 397: mftb %r28
! 398: andi. %r28,%r28,1
! 399: bne 2f
! 400: mtdbatu 2,%r30
! 401: mtdbatl 2,%r31
! 402: b 3f
! 403: 2:
! 404: mtdbatu 3,%r30
! 405: mtdbatl 3,%r31
! 406: 3:
! 407: mfsprg %r30,2 /* restore XER */
! 408: mtxer %r30
! 409: mtcr %r29 /* restore CR */
! 410: lmw %r28,disisave(0) /* restore r28-r31 */
! 411: rfi /* return to trapped code */
! 412: 1:
! 413: #endif
! 414: mflr %r28 /* save LR */
! 415: bla s_dsitrap
! 416: _C_LABEL(dsisize) = .-_C_LABEL(dsitrap)
! 417:
! 418: /*
! 419: * Similar to the above for ISI
! 420: */
! 421: .globl _C_LABEL(isitrap),_C_LABEL(isisize)
! 422: .type _C_LABEL(isitrap),@function
! 423: .type _C_LABEL(isisize),@object
! 424: _C_LABEL(isitrap):
! 425: stmw %r28,disisave(0) /* free r28-r31 */
! 426: mflr %r28 /* save LR */
! 427: mfcr %r29 /* save CR */
! 428: mfsrr1 %r31 /* test kernel mode */
! 429: #if 0
! 430: mtcr %r31
! 431: bc 12,17,1f /* branch if PSL_PR is set */
! 432: mfsrr0 %r31 /* get fault address */
! 433: rlwinm %r31,%r31,7,25,28 /* get segment * 8 */
! 434: addis %r31,%r31,_C_LABEL(battable)@ha
! 435: lwz %r30,_C_LABEL(battable)@l(%r31) /* get batu */
! 436: mtcr %r30
! 437: bc 4,30,1f /* branch if supervisor valid is false */
! 438: mtibatu 3,%r30
! 439: lwz %r30,_C_LABEL(battable)+4@l(%r31) /* get batl */
! 440: mtibatl 3,%r30
! 441: mtcr %r29 /* restore CR */
! 442: lmw %r28,disisave(0) /* restore r28-r31 */
! 443: rfi /* return to trapped code */
! 444: 1:
! 445: #endif
! 446: bla s_isitrap
! 447: _C_LABEL(isisize) = .-_C_LABEL(isitrap)
! 448:
! 449: /*
! 450: * This one for the external interrupt handler.
! 451: */
! 452: .globl _C_LABEL(extint),_C_LABEL(extsize)
! 453: .type _C_LABEL(extint),@function
! 454: .type _C_LABEL(extsize),@object
! 455: _C_LABEL(extint):
! 456: mtsprg 1,%r1 /* save SP */
! 457: stmw %r28,tempsave(0) /* free r28-r31 */
! 458: mflr %r28 /* save LR */
! 459: mfcr %r29 /* save CR */
! 460: mfxer %r30 /* save XER */
! 461: lis %r1,intstk+INTSTK@ha /* get interrupt stack */
! 462: addi %r1,%r1,intstk+INTSTK@l
! 463: lwz %r31,0(%r1) /* were we already running on intstk? */
! 464: addic. %r31,%r31,%r1
! 465: stw %r31,0(%r1)
! 466: beq 1f
! 467: mfsprg %r1,1 /* yes, get old SP */
! 468: 1:
! 469: ba extintr
! 470: _C_LABEL(extsize) = .-_C_LABEL(extint)
! 471:
! 472: /*
! 473: * And this one for the decrementer interrupt handler.
! 474: */
! 475: .globl _C_LABEL(decrint),_C_LABEL(decrsize)
! 476: .type _C_LABEL(decrint),@function
! 477: .type _C_LABEL(decrsize),@object
! 478: _C_LABEL(decrint):
! 479: mtsprg 1,%r1 /* save SP */
! 480: stmw %r28,tempsave(0) /* free r28-r31 */
! 481: mflr %r28 /* save LR */
! 482: mfcr %r29 /* save CR */
! 483: mfxer %r30 /* save XER */
! 484: lis %r1,intstk+INTSTK@ha /* get interrupt stack */
! 485: addi %r1,%r1,intstk+INTSTK@l
! 486: lwz %r31,0(%r1) /* were we already running on intstk? */
! 487: addic. %r31,%r31,%r1
! 488: stw %r31,0(%r1)
! 489: beq 1f
! 490: mfsprg %r1,1 /* yes, get old SP */
! 491: 1:
! 492: ba decrintr
! 493: _C_LABEL(decrsize) = .-_C_LABEL(decrint)
! 494:
! 495: /*
! 496: * Now the tlb software load for 603 processors:
! 497: * (Code essentially from the 603e User Manual, Chapter 5)
! 498: */
! 499: #define DMISS 976
! 500: #define DCMP 977
! 501: #define HASH1 978
! 502: #define HASH2 979
! 503: #define IMISS 980
! 504: #define ICMP 981
! 505: #define RPA 982
! 506:
! 507: #define bdneq bdnzf 2,
! 508: #define tlbli .long 0x7c0007e4+0x800*
! 509: #define tlbld .long 0x7c0007a4+0x800*
! 510:
! 511: .globl _C_LABEL(tlbimiss),_C_LABEL(tlbimsize)
! 512: .type _C_LABEL(tlbimiss),@function
! 513: .type _C_LABEL(tlbimsize),@object
! 514: _C_LABEL(tlbimiss):
! 515: mfspr %r2,HASH1 /* get first pointer */
! 516: li %r1,8
! 517: mfctr %r0 /* save counter */
! 518: mfspr %r3,ICMP /* get first compare value */
! 519: addi %r2,%r2,-8 /* predec pointer */
! 520: 1:
! 521: mtctr %r1 /* load counter */
! 522: 2:
! 523: lwzu %r1,8(%r2) /* get next pte */
! 524: cmpl 0,%r1,%r3 /* see if found pte */
! 525: bdneq 2b /* loop if not eq */
! 526: bne 3f /* not found */
! 527: lwz %r1,4(%r2) /* load tlb entry lower word */
! 528: andi. %r3,%r1,8 /* check G-bit */
! 529: bne 4f /* if guarded, take ISI */
! 530: mtctr %r0 /* restore counter */
! 531: mfspr %r0,IMISS /* get the miss address for the tlbli */
! 532: mfsrr1 %r3 /* get the saved cr0 bits */
! 533: mtcrf 0x80,%r3 /* and restore */
! 534: ori %r1,%r1,0x100 /* set the reference bit */
! 535: mtspr RPA,%r1 /* set the pte */
! 536: srwi %r1,%r1,8 /* get byte 7 of pte */
! 537: tlbli 0 /* load the itlb */
! 538: stb %r1,6(%r2) /* update page table */
! 539: rfi
! 540:
! 541: 3: /* not found in pteg */
! 542: andi. %r1,%r3,0x40 /* have we already done second hash? */
! 543: bne 5f
! 544: mfspr %r2,HASH2 /* get the second pointer */
! 545: ori %r3,%r3,0x40 /* change the compare value */
! 546: li %r1,8
! 547: addi %r2,%r2,-8 /* predec pointer */
! 548: b 1b
! 549: 4: /* guarded */
! 550: mfsrr1 %r3
! 551: andi. %r2,%r3,0xffff /* clean upper srr1 */
! 552: addis %r2,%r2,0x800 /* set srr<4> to flag prot violation */
! 553: b 6f
! 554: 5: /* not found anywhere */
! 555: mfsrr1 %r3
! 556: andi. %r2,%r3,0xffff /* clean upper srr1 */
! 557: addis %r2,%r2,0x4000 /* set srr1<1> to flag pte not found */
! 558: 6:
! 559: mtctr %r0 /* restore counter */
! 560: mtsrr1 %r2
! 561: mfmsr %r0
! 562: xoris %r0,%r0,2 /* flip the msr<tgpr> bit */
! 563: mtcrf 0x80,%r3 /* restore cr0 */
! 564: mtmsr %r0 /* now with native gprs */
! 565: isync
! 566: ba EXC_ISI
! 567: _C_LABEL(tlbimsize) = .-_C_LABEL(tlbimiss)
! 568:
! 569: .globl _C_LABEL(tlbdlmiss),_C_LABEL(tlbdlmsize)
! 570: .type _C_LABEL(tlbdlmiss),@function
! 571: .type _C_LABEL(tlbdlmsize),@object
! 572: _C_LABEL(tlbdlmiss):
! 573: mfspr %r2,HASH1 /* get first pointer */
! 574: li %r1,8
! 575: mfctr %r0 /* save counter */
! 576: mfspr %r3,DCMP /* get first compare value */
! 577: addi %r2,%r2,-8 /* predec pointer */
! 578: 1:
! 579: mtctr %r1 /* load counter */
! 580: 2:
! 581: lwzu %r1,8(%r2) /* get next pte */
! 582: cmpl 0,%r1,%r3 /* see if found pte */
! 583: bdneq 2b /* loop if not eq */
! 584: bne 3f /* not found */
! 585: lwz %r1,4(%r2) /* load tlb entry lower word */
! 586: mtctr %r0 /* restore counter */
! 587: mfspr %r0,DMISS /* get the miss address for the tlbld */
! 588: mfsrr1 %r3 /* get the saved cr0 bits */
! 589: mtcrf 0x80,%r3 /* and restore */
! 590: ori %r1,%r1,0x100 /* set the reference bit */
! 591: mtspr RPA,%r1 /* set the pte */
! 592: srwi %r1,%r1,8 /* get byte 7 of pte */
! 593: tlbld 0 /* load the dtlb */
! 594: stb %r1,6(%r2) /* update page table */
! 595: rfi
! 596:
! 597: 3: /* not found in pteg */
! 598: andi. %r1,%r3,0x40 /* have we already done second hash? */
! 599: bne 5f
! 600: mfspr %r2,HASH2 /* get the second pointer */
! 601: ori %r3,%r3,0x40 /* change the compare value */
! 602: li %r1,8
! 603: addi %r2,%r2,-8 /* predec pointer */
! 604: b 1b
! 605: 5: /* not found anywhere */
! 606: mfsrr1 %r3
! 607: lis %r1,0x4000 /* set dsisr<1> to flag pte not found */
! 608: mtctr %r0 /* restore counter */
! 609: andi. %r2,%r3,0xffff /* clean upper srr1 */
! 610: mtsrr1 %r2
! 611: mtdsisr %r1 /* load the dsisr */
! 612: mfspr %r1,DMISS /* get the miss address */
! 613: mtdar %r1 /* put in dar */
! 614: mfmsr %r0
! 615: xoris %r0,%r0,2 /* flip the msr<tgpr> bit */
! 616: mtcrf 0x80,%r3 /* restore cr0 */
! 617: mtmsr %r0 /* now with native gprs */
! 618: isync
! 619: ba EXC_DSI
! 620: _C_LABEL(tlbdlmsize) = .-_C_LABEL(tlbdlmiss)
! 621:
! 622: .globl _C_LABEL(tlbdsmiss),_C_LABEL(tlbdsmsize)
! 623: .type _C_LABEL(tlbdsmiss),@function
! 624: .type _C_LABEL(tlbdsmsize),@object
! 625: _C_LABEL(tlbdsmiss):
! 626: mfspr %r2,HASH1 /* get first pointer */
! 627: li %r1,8
! 628: mfctr %r0 /* save counter */
! 629: mfspr %r3,DCMP /* get first compare value */
! 630: addi %r2,%r2,-8 /* predec pointer */
! 631: 1:
! 632: mtctr %r1 /* load counter */
! 633: 2:
! 634: lwzu %r1,8(%r2) /* get next pte */
! 635: cmpl 0,%r1,%r3 /* see if found pte */
! 636: bdneq 2b /* loop if not eq */
! 637: bne 3f /* not found */
! 638: lwz %r1,4(%r2) /* load tlb entry lower word */
! 639: andi. %r3,%r1,0x80 /* check the C-bit */
! 640: beq 4f
! 641: 5:
! 642: mtctr %r0 /* restore counter */
! 643: mfspr %r0,DMISS /* get the miss address for the tlbld */
! 644: mfsrr1 %r3 /* get the saved cr0 bits */
! 645: mtcrf 0x80,%r3 /* and restore */
! 646: mtspr RPA,%r1 /* set the pte */
! 647: tlbld 0 /* load the dtlb */
! 648: rfi
! 649:
! 650: 3: /* not found in pteg */
! 651: andi. %r1,%r3,0x40 /* have we already done second hash? */
! 652: bne 5f
! 653: mfspr %r2,HASH2 /* get the second pointer */
! 654: ori %r3,%r3,0x40 /* change the compare value */
! 655: li %r1,8
! 656: addi %r2,%r2,-8 /* predec pointer */
! 657: b 1b
! 658: 4: /* found, but C-bit = 0 */
! 659: rlwinm. %r3,%r1,30,0,1 /* test PP */
! 660: bge- 7f
! 661: andi. %r3,%r1,1
! 662: beq+ 8f
! 663: 9: /* found, but protection violation (PP==00)*/
! 664: mfsrr1 %r3
! 665: lis %r1,0xa00 /* indicate protection violation on store */
! 666: b 1f
! 667: 7: /* found, PP=1x */
! 668: mfspr %r3,DMISS /* get the miss address */
! 669: mfsrin %r1,%r3 /* get the segment register */
! 670: mfsrr1 %r3
! 671: rlwinm %r3,%r3,18,31,31 /* get PR-bit */
! 672: rlwnm. %r2,%r2,3,1,1 /* get the key */
! 673: bne- 9b /* protection violation */
! 674: 8: /* found, set reference/change bits */
! 675: lwz %r1,4(%r2) /* reload tlb entry */
! 676: ori %r1,%r1,0x180
! 677: sth %r1,6(%r2)
! 678: b 5b
! 679: 5: /* not found anywhere */
! 680: mfsrr1 %r3
! 681: lis %r1,0x4200 /* set dsisr<1> to flag pte not found */
! 682: /* dsisr<6> to flag store */
! 683: 1:
! 684: mtctr %r0 /* restore counter */
! 685: andi. %r2,%r3,0xffff /* clean upper srr1 */
! 686: mtsrr1 %r2
! 687: mtdsisr %r1 /* load the dsisr */
! 688: mfspr %r1,DMISS /* get the miss address */
! 689: mtdar %r1 /* put in dar */
! 690: mfmsr %r0
! 691: xoris %r0,%r0,2 /* flip the msr<tgpr> bit */
! 692: mtcrf 0x80,%r3 /* restore cr0 */
! 693: mtmsr %r0 /* now with native gprs */
! 694: isync
! 695: ba EXC_DSI
! 696: _C_LABEL(tlbdsmsize) = .-_C_LABEL(tlbdsmiss)
! 697:
! 698: #ifdef DDB
! 699: #define ddbsave 0xde0 /* primary save area for DDB */
! 700: /*
! 701: * In case of DDB we want a separate trap catcher for it
! 702: */
! 703: .local ddbstk
! 704: .comm ddbstk,INTSTK,8 /* ddb stack */
! 705:
! 706: .globl _C_LABEL(ddblow),_C_LABEL(ddbsize)
! 707: _C_LABEL(ddblow):
! 708: mtsprg 1,%r1 /* save SP */
! 709: stmw %r28,ddbsave(0) /* free r28-r31 */
! 710: mflr %r28 /* save LR */
! 711: mfcr %r29 /* save CR */
! 712: lis %r1,ddbstk+INTSTK@ha /* get new SP */
! 713: addi %r1,%r1,ddbstk+INTSTK@l
! 714: bla ddbtrap
! 715: _C_LABEL(ddbsize) = .-_C_LABEL(ddblow)
! 716: #endif /* DDB */
! 717:
! 718:
! 719: /*
! 720: * FRAME_SETUP assumes:
! 721: * SPRG1 SP (1)
! 722: * savearea r28-r31,DAR,DSISR (DAR & DSISR only for DSI traps)
! 723: * 28 LR
! 724: * 29 CR
! 725: * 1 kernel stack
! 726: * LR trap type
! 727: * SRR0/1 as at start of trap
! 728: */
! 729: #define FRAME_SETUP(savearea) \
! 730: /* Have to enable translation to allow access of kernel stack: */ \
! 731: mfsrr0 %r30; \
! 732: mfsrr1 %r31; \
! 733: stmw %r30,savearea+24(0); \
! 734: mfmsr %r30; \
! 735: ori %r30,%r30,(PSL_DR|PSL_IR); \
! 736: mtmsr %r30; \
! 737: isync; \
! 738: mfsprg %r31,1; \
! 739: stwu %r31,-FRAMELEN(%r1); \
! 740: stw %r0,FRAME_0+8(%r1); \
! 741: stw %r31,FRAME_1+8(%r1); \
! 742: stw %r28,FRAME_LR+8(%r1); \
! 743: stw %r29,FRAME_CR+8(%r1); \
! 744: lmw %r28,savearea(0); \
! 745: stmw %r2,FRAME_2+8(%r1); \
! 746: lmw %r28,savearea+16(0); \
! 747: mfxer %r3; \
! 748: mfctr %r4; \
! 749: mflr %r5; \
! 750: andi. %r5,%r5,0xff00; \
! 751: stw %r3,FRAME_XER+8(%r1); \
! 752: stw %r4,FRAME_CTR+8(%r1); \
! 753: stw %r5,FRAME_EXC+8(%r1); \
! 754: stw %r28,FRAME_DAR+8(%r1); \
! 755: stw %r29,FRAME_DSISR+8(%r1); \
! 756: stw %r30,FRAME_SRR0+8(%r1); \
! 757: stw %r31,FRAME_SRR1+8(%r1)
! 758:
! 759: #define FRAME_LEAVE(savearea) \
! 760: /* Now restore regs: */ \
! 761: lwz %r2,FRAME_SRR0+8(%r1); \
! 762: lwz %r3,FRAME_SRR1+8(%r1); \
! 763: lwz %r4,FRAME_CTR+8(%r1); \
! 764: lwz %r5,FRAME_XER+8(%r1); \
! 765: lwz %r6,FRAME_LR+8(%r1); \
! 766: lwz %r7,FRAME_CR+8(%r1); \
! 767: stw %r2,savearea(0); \
! 768: stw %r3,savearea+4(0); \
! 769: mtctr %r4; \
! 770: mtxer %r5; \
! 771: mtlr %r6; \
! 772: mtsprg 1,%r7; /* save cr */ \
! 773: lmw %r2,FRAME_2+8(%r1); \
! 774: lwz %r0,FRAME_0+8(%r1); \
! 775: lwz %r1,FRAME_1+8(%r1); \
! 776: mtsprg 2,%r2; /* save r2 & r3 */ \
! 777: mtsprg 3,%r3; \
! 778: /* Disable translation, machine check and recoverability: */ \
! 779: mfmsr %r2; \
! 780: lis %r3,(PSL_DR|PSL_IR|PSL_ME|PSL_RI)@ha; \
! 781: addi %r3,%r3,(PSL_DR|PSL_IR|PSL_ME|PSL_RI)@l; \
! 782: andc %r2,%r2,%r3; \
! 783: mtmsr %r2; \
! 784: isync; \
! 785: /* Decide whether we return to user mode: */ \
! 786: lwz %r3,savearea+4(0); \
! 787: mtcr %r3; \
! 788: bc 4,17,1f; /* branch if PSL_PR is false */ \
! 789: /* Restore user & kernel access SR: */ \
! 790: lis %r2,_C_LABEL(curpm)@ha; /* get real address of pmap */ \
! 791: lwz %r2,_C_LABEL(curpm)@l(%r2); \
! 792: lwz %r3,PM_USRSR(%r2); \
! 793: mtsr PPC_USER_SR,%r3; \
! 794: lwz %r3,PM_KERNELSR(%r2); \
! 795: mtsr PPC_KERNEL_SR,%r3; \
! 796: 1: mfsprg %r2,1; /* restore cr */ \
! 797: mtcr %r2; \
! 798: lwz %r2,savearea(0); \
! 799: lwz %r3,savearea+4(0); \
! 800: mtsrr0 %r2; \
! 801: mtsrr1 %r3; \
! 802: mfsprg %r2,2; /* restore r2 & r3 */ \
! 803: mfsprg %r3,3
! 804:
! 805: /*
! 806: * Preamble code for DSI/ISI traps
! 807: */
! 808: disitrap:
! 809: lmw %r30,disisave(0)
! 810: stmw %r30,tempsave(0)
! 811: lmw %r30,disisave+8(0)
! 812: stmw %r30,tempsave+8(0)
! 813: mfdar %r30
! 814: mfdsisr %r31
! 815: stmw %r30,tempsave+16(0)
! 816: realtrap:
! 817: /* Test whether we already had PR set */
! 818: mfsrr1 %r1
! 819: mtcr %r1
! 820: /* restore SP (might have been overwritten) */
! 821: mfsprg %r1,1
! 822: bc 4,17,s_trap /* branch if PSL_PR is false */
! 823: lis %r1,_C_LABEL(curpcb)@ha
! 824: lwz %r1,_C_LABEL(curpcb)@l(%r1)
! 825: addi %r1,%r1,USPACE /* stack is top of user struct */
! 826: /*
! 827: * Now the common trap catching code.
! 828: */
! 829: s_trap:
! 830: /* First have to enable KERNEL mapping */
! 831: lis %r31,PPC_KERNEL_SEGMENT@ha
! 832: addi %r31,%r31,PPC_KERNEL_SEGMENT@l
! 833: mtsr PPC_KERNEL_SR,%r31
! 834: FRAME_SETUP(tempsave)
! 835: /* Now we can recover interrupts again: */
! 836: mfmsr %r7
! 837: mfsrr1 %r31
! 838: andi. %r31,%r31,PSL_EE /* restore EE from previous context */
! 839: or %r7,%r7,%r31
! 840: ori %r7,%r7,(PSL_ME|PSL_RI)
! 841: mtmsr %r7
! 842: isync
! 843: /* Call C trap code: */
! 844: trapagain:
! 845: addi %r3,%r1,8
! 846: bl _C_LABEL(trap)
! 847: trapexit:
! 848: /* Disable interrupts: */
! 849: mfmsr %r3
! 850: andi. %r3,%r3,~PSL_EE@l
! 851: mtmsr %r3
! 852: /* Test AST pending: */
! 853: lwz %r5,FRAME_SRR1+8(%r1)
! 854: mtcr %r5
! 855: bc 4,17,1f /* branch if PSL_PR is false */
! 856: lis %r3,_C_LABEL(astpending)@ha
! 857: lwz %r4,_C_LABEL(astpending)@l(%r3)
! 858: andi. %r4,%r4,1
! 859: beq 1f
! 860: li %r6,EXC_AST
! 861: stw %r6,FRAME_EXC+8(%r1)
! 862: b trapagain
! 863: 1:
! 864: FRAME_LEAVE(tempsave)
! 865: rfi
! 866:
! 867: /*
! 868: * Child comes here at the end of a fork.
! 869: * Mostly similar to the above.
! 870: */
! 871: .globl _C_LABEL(fork_trampoline)
! 872: .type _C_LABEL(fork_trampoline),@function
! 873: _C_LABEL(fork_trampoline):
! 874: li %r3,0
! 875: bl _C_LABEL(lcsplx)
! 876: mtlr %r31
! 877: mr %r3,%r30
! 878: blrl /* jump indirect to r31 */
! 879: b trapexit
! 880:
! 881: /*
! 882: * DSI second stage fault handler
! 883: */
! 884: s_dsitrap:
! 885: mfdsisr %r31 /* test if this is spill fault */
! 886: mtcr %r31
! 887: mtsprg 1,%r1 /* save SP */
! 888: bc 4,1,disitrap /* branch if table miss is false */
! 889: lis %r1,spillstk+SPILLSTK@ha
! 890: addi %r1,%r1,spillstk+SPILLSTK@l /* get spill stack */
! 891: stwu %r1,-52(%r1)
! 892: stw %r0,48(%r1) /* save non-volatile registers */
! 893: stw %r3,44(%r1)
! 894: stw %r4,40(%r1)
! 895: stw %r5,36(%r1)
! 896: stw %r6,32(%r1)
! 897: stw %r7,28(%r1)
! 898: stw %r8,24(%r1)
! 899: stw %r9,20(%r1)
! 900: stw %r10,16(%r1)
! 901: stw %r11,12(%r1)
! 902: stw %r12,8(%r1)
! 903: mfxer %r30 /* save XER */
! 904: mtsprg 2,%r30
! 905: mflr %r30 /* save trap type */
! 906: mfctr %r31 /* & CTR */
! 907: mfdar %r3
! 908: mfsrr1 %r4
! 909: mfdsisr %r5
! 910: li %r6, 0
! 911: s_pte_spill:
! 912: bl _C_LABEL(pte_spill_r) /* try a spill */
! 913: cmpwi 0,%r3,0
! 914: mtctr %r31 /* restore CTR */
! 915: mtlr %r30 /* and trap type */
! 916: mfsprg %r31,2 /* get saved XER */
! 917: mtxer %r31 /* restore XER */
! 918: lwz %r12,8(%r1) /* restore non-volatile registers */
! 919: lwz %r11,12(%r1)
! 920: lwz %r10,16(%r1)
! 921: lwz %r9,20(%r1)
! 922: lwz %r8,24(%r1)
! 923: lwz %r7,28(%r1)
! 924: lwz %r6,32(%r1)
! 925: lwz %r5,36(%r1)
! 926: lwz %r4,40(%r1)
! 927: lwz %r3,44(%r1)
! 928: lwz %r0,48(%r1)
! 929: beq disitrap
! 930: mfsprg %r1,1 /* restore SP */
! 931: mtcr %r29 /* restore CR */
! 932: mtlr %r28 /* restore LR */
! 933: lmw %r28,disisave(0) /* restore r28-r31 */
! 934: rfi /* return to trapped code */
! 935:
! 936: /*
! 937: * ISI second stage fault handler
! 938: */
! 939: s_isitrap:
! 940: mfsrr1 %r31 /* test if this may be a spill fault */
! 941: mtcr %r31
! 942: mtsprg 1,%r1 /* save SP */
! 943: bc 4,%r1,disitrap /* branch if table miss is false */
! 944: lis %r1,spillstk+SPILLSTK@ha
! 945: addi %r1,%r1,spillstk+SPILLSTK@l /* get spill stack */
! 946: stwu %r1,-52(%r1)
! 947: stw %r0,48(%r1) /* save non-volatile registers */
! 948: stw %r3,44(%r1)
! 949: stw %r4,40(%r1)
! 950: stw %r5,36(%r1)
! 951: stw %r6,32(%r1)
! 952: stw %r7,28(%r1)
! 953: stw %r8,24(%r1)
! 954: stw %r9,20(%r1)
! 955: stw %r10,16(%r1)
! 956: stw %r11,12(%r1)
! 957: stw %r12,8(%r1)
! 958: mfxer %r30 /* save XER */
! 959: mtsprg 2,%r30
! 960: mflr %r30 /* save trap type */
! 961: mfctr %r31 /* & ctr */
! 962: mfsrr0 %r3
! 963: mfsrr1 %r4
! 964: li %r5, 0
! 965: li %r6, 1
! 966: b s_pte_spill /* above */
! 967:
! 968: /*
! 969: * External interrupt second level handler
! 970: */
! 971: #define INTRENTER \
! 972: /* Save non-volatile registers: */ \
! 973: stwu %r1,-88(%r1); /* temporarily */ \
! 974: stw %r0,84(%r1); \
! 975: mfsprg %r0,1; /* get original SP */ \
! 976: stw %r0,0(%r1); /* and store it */ \
! 977: stw %r3,80(%r1); \
! 978: stw %r4,76(%r1); \
! 979: stw %r5,72(%r1); \
! 980: stw %r6,68(%r1); \
! 981: stw %r7,64(%r1); \
! 982: stw %r8,60(%r1); \
! 983: stw %r9,56(%r1); \
! 984: stw %r10,52(%r1); \
! 985: stw %r11,48(%r1); \
! 986: stw %r12,44(%r1); \
! 987: stw %r28,40(%r1); /* saved LR */ \
! 988: stw %r29,36(%r1); /* saved CR */ \
! 989: stw %r30,32(%r1); /* saved XER */ \
! 990: lmw %r28,tempsave(0); /* restore r28-r31 */ \
! 991: mfctr %r6; \
! 992: lis %r5,_C_LABEL(intr_depth)@ha; \
! 993: lwz %r5,_C_LABEL(intr_depth)@l(%r5); \
! 994: mfsrr0 %r4; \
! 995: mfsrr1 %r3; \
! 996: stw %r6,28(%r1); \
! 997: stw %r5,20(%r1); \
! 998: stw %r4,12(%r1); \
! 999: stw %r3,8(%r1); \
! 1000: /* interrupts are recoverable here, and enable translation */ \
! 1001: lis %r3,(PPC_KERNEL_SEGMENT|SR_SUKEY|SR_PRKEY)@ha; \
! 1002: addi %r3,%r3,(PPC_KERNEL_SEGMENT|SR_SUKEY|SR_PRKEY)@l; \
! 1003: mtsr PPC_KERNEL_SR,%r3; \
! 1004: mfmsr %r5; \
! 1005: ori %r5,%r5,(PSL_IR|PSL_DR|PSL_RI); \
! 1006: mtmsr %r5; \
! 1007: isync
! 1008:
! 1009: .globl _C_LABEL(extint_call)
! 1010: .type _C_LABEL(extint_call),@function
! 1011: extintr:
! 1012: INTRENTER
! 1013: _C_LABEL(extint_call):
! 1014: bl _C_LABEL(extint_call) /* to be filled in later */
! 1015: intr_exit:
! 1016: /* Disable interrupts (should already be disabled) and MMU here: */
! 1017: mfmsr %r3
! 1018: andi. %r3,%r3,~(PSL_EE|PSL_ME|PSL_RI|PSL_DR|PSL_IR)@l
! 1019: mtmsr %r3
! 1020: isync
! 1021: /* restore possibly overwritten registers: */
! 1022: lwz %r12,44(%r1)
! 1023: lwz %r11,48(%r1)
! 1024: lwz %r10,52(%r1)
! 1025: lwz %r9,56(%r1)
! 1026: lwz %r8,60(%r1)
! 1027: lwz %r7,64(%r1)
! 1028: lwz %r6,8(%r1)
! 1029: lwz %r5,12(%r1)
! 1030: lwz %r4,28(%r1)
! 1031: lwz %r3,32(%r1)
! 1032: mtsrr1 %r6
! 1033: mtsrr0 %r5
! 1034: mtctr %r4
! 1035: mtxer %r3
! 1036: /* Returning to user mode? */
! 1037: mtcr %r6 /* saved SRR1 */
! 1038: bc 4,17,1f /* branch if PSL_PR is false */
! 1039: lis %r3,_C_LABEL(curpm)@ha /* get current pmap real address */
! 1040: lwz %r3,_C_LABEL(curpm)@l(%r3)
! 1041: lwz %r3,PM_KERNELSR(%r3)
! 1042: mtsr PPC_KERNEL_SR,%r3 /* Restore kernel SR */
! 1043: lis %r3,_C_LABEL(astpending)@ha /* Test AST pending */
! 1044: lwz %r4,_C_LABEL(astpending)@l(%r3)
! 1045: andi. %r4,%r4,1
! 1046: beq 1f
! 1047: /* Setup for entry to realtrap: */
! 1048: lwz %r3,0(%r1) /* get saved SP */
! 1049: mtsprg %r1,3
! 1050: li %r6,EXC_AST
! 1051: stmw %r28,tempsave(0) /* establish tempsave again */
! 1052: mtlr %r6
! 1053: lwz %r28,40(%r1) /* saved LR */
! 1054: lwz %r29,36(%r1) /* saved CR */
! 1055: lwz %r6,68(%r1)
! 1056: lwz %r5,72(%r1)
! 1057: lwz %r4,76(%r1)
! 1058: lwz %r3,80(%r1)
! 1059: lwz %r0,84(%r1)
! 1060: lis %r30,_C_LABEL(intr_depth)@ha /* adjust reentrancy count */
! 1061: lwz %r31,_C_LABEL(intr_depth)@l(%r30)
! 1062: addi %r31,%r31,-1
! 1063: stw %r31,_C_LABEL(intr_depth)@l(%r30)
! 1064: b realtrap
! 1065: 1:
! 1066: /* Here is the normal exit of extintr: */
! 1067: lwz %r5,36(%r1)
! 1068: lwz %r6,40(%r1)
! 1069: mtcr %r5
! 1070: mtlr %r6
! 1071: lwz %r6,68(%r1)
! 1072: lwz %r5,72(%r1)
! 1073: lis %r3,_C_LABEL(intr_depth)@ha /* adjust reentrancy count */
! 1074: lwz %r4,_C_LABEL(intr_depth)@l(%r3)
! 1075: addi %r4,%r4,-1
! 1076: stw %r4,_C_LABEL(intr_depth)@l(%r3)
! 1077: lwz %r4,76(%r1)
! 1078: lwz %r3,80(%r1)
! 1079: lwz %r0,84(%r1)
! 1080: lwz %r1,0(%r1)
! 1081: rfi
! 1082:
! 1083: /*
! 1084: * Decrementer interrupt second level handler
! 1085: */
! 1086: decrintr:
! 1087: INTRENTER
! 1088: addi %r3,%r1,8 /* intr frame */
! 1089: bl _C_LABEL(decr_intr)
! 1090: b intr_exit
! 1091:
! 1092:
! 1093: /*
! 1094: * int setfault()
! 1095: *
! 1096: * Similar to setjmp to setup for handling faults on accesses to user memory.
! 1097: * Any routine using this may only call bcopy, either the form below,
! 1098: * or the (currently used) C code optimized, so it doesn't use any non-volatile
! 1099: * registers.
! 1100: */
! 1101: .globl _C_LABEL(setfault)
! 1102: .type _C_LABEL(setfault),@function
! 1103: _C_LABEL(setfault):
! 1104: mflr %r0
! 1105: mfcr %r12
! 1106: mfmsr %r2
! 1107: lis %r4,_C_LABEL(curpcb)@ha
! 1108: lwz %r4,_C_LABEL(curpcb)@l(%r4)
! 1109: stw %r3,PCB_FAULT(%r4)
! 1110: stw %r0,0(%r3)
! 1111: stw %r2,4(%r3)
! 1112: stw %r1,8(%r3)
! 1113: stmw %r12,12(%r3)
! 1114: li %r3,0
! 1115: blr
! 1116:
! 1117: /*
! 1118: * The following code gets copied to the top of the user stack on process
! 1119: * execution. It does signal trampolining on signal delivery.
! 1120: *
! 1121: * On entry r1 points to a struct sigframe at bottom of current stack.
! 1122: * All other registers are unchanged.
! 1123: */
! 1124: .globl _C_LABEL(sigcode),_C_LABEL(esigcode)
! 1125: .type _C_LABEL(sigcode),@function
! 1126: .type _C_LABEL(esigcode),@function
! 1127: _C_LABEL(sigcode):
! 1128: addi %r1,%r1,-((16+FPSIG_SIZEOF+15)& ~0xf) /* reserved space for callee */
! 1129: addi %r6,%r1,8
! 1130: stfd %f0,0(%r6)
! 1131: stfd %f1,8(%r6)
! 1132: stfd %f2,16(%r6)
! 1133: stfd %f3,24(%r6)
! 1134: stfd %f4,32(%r6)
! 1135: stfd %f5,40(%r6)
! 1136: stfd %f6,48(%r6)
! 1137: stfd %f7,56(%r6)
! 1138: stfd %f8,64(%r6)
! 1139: stfd %f9,72(%r6)
! 1140: stfd %f10,80(%r6)
! 1141: stfd %f11,88(%r6)
! 1142: stfd %f12,96(%r6)
! 1143: stfd %f13,104(%r6)
! 1144: mffs %f0
! 1145: stfd %f0,112(%r6)
! 1146: lfd %f0,0(%r6) /* restore the clobbered register */
! 1147:
! 1148: blrl
! 1149: addi %r6,%r1,8
! 1150: lfd %f0,112(%r6)
! 1151: mtfsf 0xff,%f0
! 1152: lfd %f0,0(%r6)
! 1153: lfd %f1,8(%r6)
! 1154: lfd %f2,16(%r6)
! 1155: lfd %f3,24(%r6)
! 1156: lfd %f4,32(%r6)
! 1157: lfd %f5,40(%r6)
! 1158: lfd %f6,48(%r6)
! 1159: lfd %f7,56(%r6)
! 1160: lfd %f8,64(%r6)
! 1161: lfd %f9,72(%r6)
! 1162: lfd %f10,80(%r6)
! 1163: lfd %f11,88(%r6)
! 1164: lfd %f12,96(%r6)
! 1165: lfd %f13,104(%r6)
! 1166: addi %r3,%r1,((16+FPSIG_SIZEOF+15)&~0xf)+SF_SC /* compute &sf_sc */
! 1167: li %r0,SYS_sigreturn
! 1168: sc /* sigreturn(scp) */
! 1169: li %r0,SYS_exit
! 1170: sc /* exit(errno) */
! 1171: _C_LABEL(esigcode):
! 1172:
! 1173:
! 1174: #ifdef DDB
! 1175: /*
! 1176: * Deliberate entry to ddbtrap
! 1177: */
! 1178: .globl _C_LABEL(ddb_trap)
! 1179: _C_LABEL(ddb_trap):
! 1180: mtsprg %r1,1
! 1181: mfmsr %r3
! 1182: mtsrr1 %r3
! 1183: andi. %r3,%r3,~(PSL_EE|PSL_ME)@l
! 1184: mtmsr %r3 /* disable interrupts */
! 1185: isync
! 1186: stmw %r28,ddbsave(0)
! 1187: mflr %r28
! 1188: li %r29,EXC_BPT
! 1189: mtlr %r29
! 1190: mfcr %r29
! 1191: mtsrr0 %r28
! 1192:
! 1193: /*
! 1194: * Now the ddb trap catching code.
! 1195: */
! 1196: ddbtrap:
! 1197: FRAME_SETUP(ddbsave)
! 1198: /* Call C trap code: */
! 1199: addi %r3,%r1,8
! 1200: bl _C_LABEL(ddb_trap_glue)
! 1201: or. %r3,%r3,%r3
! 1202: bne ddbleave
! 1203: /* This wasn't for DDB, so switch to real trap: */
! 1204: lwz %r3,FRAME_EXC+8(%r1) /* save exception */
! 1205: stw %r3,ddbsave+8(0)
! 1206: FRAME_LEAVE(ddbsave)
! 1207: mtsprg %r1,1 /* prepare for entrance to realtrap */
! 1208: stmw %r28,tempsave(0)
! 1209: mflr %r28
! 1210: mfcr %r29
! 1211: lwz %r31,ddbsave+8(0)
! 1212: mtlr %r31
! 1213: b realtrap
! 1214: ddbleave:
! 1215: FRAME_LEAVE(ddbsave)
! 1216: rfi
! 1217: #endif /* DDB */
! 1218:
CVSweb