[BACK]Return to locore.S CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / arch / macppc / macppc

Annotation of src/sys/arch/macppc/macppc/locore.S, Revision 1.22

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

CVSweb <webmaster@jp.NetBSD.org>