[BACK]Return to context.S CVS log [TXT][DIR] Up to [local] / sys / arch / mips64 / mips64

Annotation of sys/arch/mips64/mips64/context.S, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: context.S,v 1.13 2007/07/16 20:22:18 miod Exp $ */
                      2:
                      3: /*
                      4:  * Copyright (c) 2002-2003 Opsycon AB  (www.opsycon.se / www.opsycon.com)
                      5:  *
                      6:  * Redistribution and use in source and binary forms, with or without
                      7:  * modification, are permitted provided that the following conditions
                      8:  * are met:
                      9:  * 1. Redistributions of source code must retain the above copyright
                     10:  *    notice, this list of conditions and the following disclaimer.
                     11:  * 2. Redistributions in binary form must reproduce the above copyright
                     12:  *    notice, this list of conditions and the following disclaimer in the
                     13:  *    documentation and/or other materials provided with the distribution.
                     14:  *
                     15:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
                     16:  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
                     17:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     18:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
                     19:  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     20:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     21:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     22:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     23:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     24:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     25:  * SUCH DAMAGE.
                     26:  *
                     27:  */
                     28: #include <sys/errno.h>
                     29: #include <sys/syscall.h>
                     30:
                     31: #include <machine/param.h>
                     32: #include <machine/psl.h>
                     33: #include <machine/asm.h>
                     34: #include <machine/cpu.h>
                     35: #include <machine/regnum.h>
                     36: #include <machine/cpustate.h>
                     37: #include <machine/pte.h>
                     38:
                     39: #include "assym.h"
                     40:
                     41: #define curproc        (cpu_info_primary + CI_CURPROC)
                     42:
                     43:        .set    mips3
                     44:
                     45:        .set    noreorder               # Noreorder is default style!
                     46:
                     47: /*
                     48:  * Save registers and state used by reboot to take snapshot.
                     49:  */
                     50: LEAF(savectx, 0)
                     51:        REG_S   s0, PCB_CONTEXT+0*REGSZ(a0)
                     52:        REG_S   s1, PCB_CONTEXT+1*REGSZ(a0)
                     53:        REG_S   s2, PCB_CONTEXT+2*REGSZ(a0)
                     54:        REG_S   s3, PCB_CONTEXT+3*REGSZ(a0)
                     55:        mfc0    v0, COP_0_STATUS_REG
                     56:        REG_S   s4, PCB_CONTEXT+4*REGSZ(a0)
                     57:        REG_S   s5, PCB_CONTEXT+5*REGSZ(a0)
                     58:        REG_S   s6, PCB_CONTEXT+6*REGSZ(a0)
                     59:        REG_S   s7, PCB_CONTEXT+7*REGSZ(a0)
                     60:        REG_S   sp, PCB_CONTEXT+8*REGSZ(a0)
                     61:        REG_S   s8, PCB_CONTEXT+9*REGSZ(a0)
                     62:        REG_S   ra, PCB_CONTEXT+10*REGSZ(a0)
                     63:        REG_S   v0, PCB_CONTEXT+11*REGSZ(a0)
                     64:        cfc0    t1, COP_0_ICR
                     65:        lw      t0, cpl
                     66:        REG_S   t1, PCB_CONTEXT+12*REGSZ(a0)    # save status register
                     67:        REG_S   t0, PCB_CONTEXT+13*REGSZ(a0)
                     68:        j       ra
                     69:        move    v0, zero
                     70: END(savectx)
                     71:
                     72: /*
                     73:  * The following primitives manipulate the run queues.  _whichqs tells which
                     74:  * of the 32 queues _qs have processes in them.  Setrunqueue puts processes
                     75:  * into queues, Remrq removes them from queues.  The running process is on
                     76:  * no queue, other processes are on a queue related to p->p_priority, divided
                     77:  * by 4 actually to shrink the 0-127 range of priorities into the 32 available
                     78:  * queues.
                     79:  */
                     80: /*
                     81:  * setrunqueue(p)
                     82:  *     proc *p;
                     83:  *
                     84:  * Call should be made at splclock(), and p->p_stat should be SRUN.
                     85:  */
                     86: NON_LEAF(setrunqueue, FRAMESZ(CF_SZ), ra)
                     87:        .mask   0x80000000, (CF_RA_OFFS - FRAMESZ(CF_SZ))
                     88:        PTR_L   t0, P_BACK(a0)          ## firewall: p->p_back must be 0
                     89:        bne     t0, zero, 1f            ##
                     90:        lbu     t0, P_PRIORITY(a0)      # put on p->p_priority / 4 queue
                     91:        li      t1, 1                   # compute corresponding bit
                     92:        srl     t0, t0, 2               # compute index into 'whichqs'
                     93:        sll     t1, t1, t0
                     94:        lw      t2, whichqs             # set corresponding bit
                     95:        sll     t0, t0, LOGREGSZ+1      # compute index into 'qs'
                     96:        or      t2, t2, t1
                     97:        sw      t2, whichqs
                     98:        LA      t1, qs
                     99:        PTR_ADDU t0, t0, t1             # t0 = qp = &qs[pri >> 2]
                    100:        PTR_L   t1, P_BACK(t0)          # t1 = qp->ph_rlink
                    101:        PTR_S   t0, P_FORW(a0)          # p->p_forw = qp
                    102:        PTR_S   t1, P_BACK(a0)          # p->p_back = qp->ph_rlink
                    103:        PTR_S   a0, P_FORW(t1)          # p->p_back->p_forw = p;
                    104:        j       ra
                    105:        PTR_S   a0, P_BACK(t0)          # qp->ph_rlink = p
                    106:
                    107: 1:
                    108:        PTR_SUBU sp, sp, FRAMESZ(CF_SZ)
                    109:        PTR_S   ra, CF_RA_OFFS(sp)
                    110:        PANIC("setrunqueue")
                    111:        jr      ra
                    112:        nop
                    113: END(setrunqueue)
                    114:
                    115: /*
                    116:  * Remrq(p)
                    117:  *
                    118:  * Call should be made at splclock().
                    119:  */
                    120: NON_LEAF(remrunqueue, FRAMESZ(CF_SZ), ra)
                    121:        .mask   0x80000000, (CF_RA_OFFS - FRAMESZ(CF_SZ))
                    122:        lbu     t0, P_PRIORITY(a0)      # get from p->p_priority / 4 queue
                    123:        li      t1, 1                   # compute corresponding bit
                    124:        srl     t0, t0, 2               # compute index into 'whichqs'
                    125:        lw      t2, whichqs             # check corresponding bit
                    126:        sll     t1, t1, t0
                    127:        and     v0, t2, t1
                    128:        beqz    v0, 2f                  # oops! queue is empty!
                    129:        PTR_L   v0, P_BACK(a0)          # v0 = p->p_back
                    130:
                    131:        PTR_L   v1, P_FORW(a0)          # v1 = p->p_forw
                    132:        PTR_SLL t0, t0, LOGREGSZ+1      # compute index into 'qs'
                    133:        PTR_S   v1, P_FORW(v0)          # p->p_back->p_forw = p->p_forw;
                    134:        PTR_S   v0, P_BACK(v1)          # p->p_forw->p_back = p->r_rlink
                    135:        LA      v0, qs
                    136:        PTR_ADDU t0, t0, v0             # t0 = qp = &qs[pri >> 2]
                    137:        PTR_L   v0, P_FORW(t0)          # check if queue empty
                    138:        bne     v0, t0, 1f              # No. qp->ph_link != qp
                    139:        xor     t2, t2, t1              # clear corresponding bit in 'whichqs'
                    140:        sw      t2, whichqs
                    141: 1:
                    142:        j       ra
                    143:        PTR_S   zero, P_BACK(a0)        # for firewall checking
                    144:
                    145: 2:
                    146:        PTR_SUBU sp, sp, FRAMESZ(CF_SZ)
                    147:        PTR_S   ra, CF_RA_OFFS(sp)
                    148:        PANIC("remrunqueue empty")
                    149:        jr      ra
                    150:        nop
                    151: END(remrunqueue)
                    152:
                    153: /*
                    154:  *   Idle, this is where we spend time when nothing to do.
                    155:  */
                    156: LEAF(idle, 0)
                    157: _idle:
                    158:        sw      zero, cpl               # lower to spl0
                    159:        lw      t0, ipending
                    160:        beqz    t0, 1f
                    161:        nop
                    162:        jal     setsoftintr0
                    163:        nop
                    164: 1:
                    165:        mfc0    a0, COP_0_STATUS_REG    # ... and enable interrupts
                    166:        li      a1, SR_INT_ENAB
                    167:        or      a0, a0, a1
                    168:        mtc0    a0, COP_0_STATUS_REG
                    169:        ITLBNOPFIX
                    170:
                    171: #ifdef IMASK_EXTERNAL
                    172:        jal     hw_setintrmask
                    173:        xor     a0, a0
                    174: #endif
                    175:        jal     updateimask             # Make sure SR imask is updated
                    176:        xor     a0, a0
                    177:
                    178:        li      t1,1
                    179: #if defined(TGT_CP7000) || defined(TGT_CP7000G)
                    180:        PTR_L   t2, misc_h              # if non zero, do Ocelot LEDs.
                    181:        beqz    t2, 1f
                    182:        li      t0, 0x40
                    183:        sb      t0, 0x0d(t2)
                    184: #endif
                    185: 1:
                    186:        lw      t0, whichqs             # look for non-empty queue
                    187:        beq     t0, zero, 1b
                    188:        nop
                    189: #if defined(TGT_CP7000) || defined(TGT_CP7000G)
                    190:        beqz    t2, sw1
                    191:        li      t0, 0x40
                    192:        sb      t0, 0x0c(t2)
                    193: #endif
                    194:        b       sw1                     # Hey, time to do some work!
                    195:        nop
                    196:        jr      ra                      # DDB trace
                    197:        nop
                    198:        .globl e_idle
                    199: e_idle:
                    200: END(idle)
                    201:
                    202: /*
                    203:  * switch_exit(p)
                    204:  *
                    205:  * At exit of a process, do a cpu_switch for the last time.
                    206:  * All interrupts should be blocked at this point.
                    207:  */
                    208: LEAF(switch_exit, 0)
                    209:        mfc0    v0, COP_0_STATUS_REG
                    210:        li      v1, ~SR_INT_ENAB
                    211:        and     v0, v0, v1
                    212:        mtc0    v0, COP_0_STATUS_REG
                    213:        ITLBNOPFIX
                    214:        LA      sp, idle_stack - FRAMESZ(CF_SZ)
                    215:        jal     exit2
                    216:        nop
                    217:
                    218:        PTR_S   zero, curproc
                    219:        b       sw0
                    220:        nop
                    221:        jr      ra                      # DDB trace
                    222:        nop
                    223: END(switch_exit)
                    224:
                    225: /*
                    226:  * cpu_switch()
                    227:  * Find the highest priority process and resume it.
                    228:  */
                    229: NON_LEAF(cpu_switch, FRAMESZ(CF_SZ), ra)
                    230:        PTR_L   t3, curprocpaddr
                    231:        REG_S   sp, PCB_CONTEXT+8*REGSZ(t3)     # save old sp
                    232:        PTR_SUBU sp, sp, FRAMESZ(CF_SZ)
                    233:        REG_S   ra, CF_RA_OFFS(sp)
                    234:        .mask   0x80000000, (CF_RA_OFFS - FRAMESZ(CF_SZ))
                    235:        lw      t0, cpl
                    236:        REG_S   t0, PCB_CONTEXT+13*REGSZ(t3)
                    237:        REG_S   s0, PCB_CONTEXT+0*REGSZ(t3)     # do a 'savectx()'
                    238:        REG_S   s1, PCB_CONTEXT+1*REGSZ(t3)
                    239:        REG_S   s2, PCB_CONTEXT+2*REGSZ(t3)
                    240:        REG_S   s3, PCB_CONTEXT+3*REGSZ(t3)
                    241:        REG_S   s4, PCB_CONTEXT+4*REGSZ(t3)
                    242:        REG_S   s5, PCB_CONTEXT+5*REGSZ(t3)
                    243:        REG_S   s6, PCB_CONTEXT+6*REGSZ(t3)
                    244:        REG_S   s7, PCB_CONTEXT+7*REGSZ(t3)
                    245:        REG_S   s8, PCB_CONTEXT+9*REGSZ(t3)
                    246:        REG_S   ra, PCB_CONTEXT+10*REGSZ(t3)
                    247:        mfc0    t0, COP_0_STATUS_REG
                    248:        cfc0    t1, COP_0_ICR
                    249:        REG_S   t0, PCB_CONTEXT+11*REGSZ(t3)
                    250:        REG_S   t1, PCB_CONTEXT+12*REGSZ(t3)
                    251:
                    252: sw0:
                    253: #      lw      t2, cnt+V_SWTCH                 # for statistics
                    254:        lw      t1, whichqs                     # look for non-empty queue
                    255: #      addu    t2, t2, 1
                    256: #      sw      t2, cnt+V_SWTCH
                    257:        beq     t1, zero, _idle                 # if none, idle
                    258:        nop
                    259: sw1:
                    260:        mfc0    v0, COP_0_STATUS_REG
                    261:        li      v1, ~SR_INT_ENAB
                    262:        and     v0, v0, v1
                    263:        mtc0    v0, COP_0_STATUS_REG
                    264:        ITLBNOPFIX
                    265:        lw      t0, whichqs                     # look for non-empty queue
                    266:        li      t2, -1                          # t2 = lowest bit set
                    267:        beq     t0, zero, _idle                 # if none, idle
                    268:        move    t3, t0                          # t3 = saved whichqs
                    269: 1:
                    270:        addu    t2, t2, 1
                    271:        and     t1, t0, 1                       # bit set?
                    272:        beq     t1, zero, 1b
                    273:        srl     t0, t0, 1                       # try next bit
                    274: /*
                    275:  * Remove process from queue.
                    276:  */
                    277:        PTR_SLL t0, t2, LOGREGSZ+1
                    278:        LA      t1, qs
                    279:        PTR_ADDU t0, t0, t1                     # t0 = qp = &qs[highbit]
                    280:        PTR_L   a0, P_FORW(t0)                  # a0 = p = highest pri process
                    281:        PTR_L   v0, P_FORW(a0)                  # v0 = p->p_forw
                    282:        beq     t0, a0, 4f                      # make sure something in queue
                    283:        PTR_S   v0, P_FORW(t0)                  # qp->ph_link = p->p_forw;
                    284:        PTR_S   t0, P_BACK(v0)                  # p->p_forw->p_back = qp
                    285:        bne     v0, t0, 2f                      # queue still not empty
                    286:        PTR_S   zero, P_BACK(a0)                ## for firewall checking
                    287:        li      v1, 1                           # compute bit in 'whichqs'
                    288:        sll     v1, v1, t2
                    289:        xor     t3, t3, v1                      # clear bit in 'whichqs'
                    290:        sw      t3, whichqs
                    291: 2:
                    292: /*
                    293:  * Switch to new context.
                    294:  */
                    295:        sw      zero, want_resched
                    296:        jal     pmap_activate                   # v0 = TLB PID
                    297:        move    s0, a0                          # BDSLOT: save p
                    298:
                    299: /*
                    300:  * We need to wire the process kernel stack mapping so there
                    301:  * will be no tlb misses in exception handlers. This is done
                    302:  * by invalidating any tlb entries mapping the U-area and
                    303:  * put valid mappings in tlb entries 0 and 1.
                    304:  */
                    305:
                    306:        PTR_L   t3, P_ADDR(s0)                  # get uarea pointer.
                    307:        PTR_S   s0, curproc                     # set curproc
                    308:        PTR_S   t3, curprocpaddr
                    309:
                    310:        li      t1, SONPROC
                    311:        sb      t1, P_STAT(s0)                  # set to onproc.
                    312:
                    313:        or      v0, t3
                    314:        dmtc0   v0, COP_0_TLB_HI                # init high entry (tlbid)
                    315:        LA      t1, (VM_MIN_KERNEL_ADDRESS)
                    316:        PTR_SUBU t2, t3, t1
                    317:        bltz    t2, ctx3                        # not mapped.
                    318:        PTR_SRL t2, PGSHIFT+1
                    319:        PTR_L   t1, Sysmap
                    320:        tlbp
                    321:        PTR_SLL t2, 3
                    322:        PTR_ADDU t1, t2                         # t1 now points at ptes.
                    323:        mfc0    t0, COP_0_TLB_INDEX
                    324:        nop
                    325:        bltz    t0, ctx1                        # not in tlb
                    326:        LA      t2, KSEG0_BASE          # NOTE: if > 1 ins, does not matter
                    327:
                    328:        dmtc0   t2, COP_0_TLB_HI                # invalidate it.
                    329:        dmtc0   zero, COP_0_TLB_LO0
                    330:        dmtc0   zero, COP_0_TLB_LO1
                    331:        nop
                    332:        nop
                    333:        nop
                    334:        nop
                    335:        tlbwi
                    336:        nop
                    337:        nop
                    338:        nop
                    339:
                    340: ctx1:
                    341:        mtc0    zero, COP_0_TLB_INDEX
                    342:        dmtc0   v0, COP_0_TLB_HI
                    343:        lw      ta0, 0(t1)
                    344:        lw      ta1, 4(t1)
                    345:        dsll    ta0, ta0, 34
                    346:        dsrl    ta0, ta0, 34
                    347:        dsll    ta1, ta1, 34
                    348:        dsrl    ta1, ta1, 34
                    349:        dmtc0   ta0, COP_0_TLB_LO0
                    350:        dmtc0   ta1, COP_0_TLB_LO1
                    351:        nop
                    352:        PTR_ADDU v0, 2*NBPG
                    353:        nop
                    354:        nop
                    355:        tlbwi
                    356:
                    357: #if (UPAGES != 2)
                    358:        dmtc0   v0, COP_0_TLB_HI                # init high entry (tlbid)
                    359:        lw      ta0, 8(t1)
                    360:        lw      ta1, 12(t1)
                    361:        dsll    ta0, ta0, 34
                    362:        dsrl    ta0, ta0, 34
                    363:        tlbp
                    364:        nop
                    365:        dsll    ta1, ta1, 34
                    366:        dsrl    ta1, ta1, 34
                    367:        mfc0    t0, COP_0_TLB_INDEX
                    368:        nop
                    369:        bltz    t0, ctx2                        # not in tlb
                    370:        li      t2, 1
                    371:
                    372:        dmtc0   t2, COP_0_TLB_HI                # invalidate it.
                    373:        dmtc0   zero, COP_0_TLB_LO0
                    374:        dmtc0   zero, COP_0_TLB_LO1
                    375:        nop
                    376:        nop
                    377:        nop
                    378:        nop
                    379:        tlbwi
                    380:        nop
                    381:        nop
                    382:        nop
                    383:
                    384: ctx2:
                    385:        mtc0    t2, COP_0_TLB_INDEX
                    386:        dmtc0   v0, COP_0_TLB_HI
                    387:        dmtc0   ta0, COP_0_TLB_LO0
                    388:        dmtc0   ta1, COP_0_TLB_LO1
                    389:        nop
                    390:        nop
                    391:        nop
                    392:        nop
                    393:        tlbwi
                    394: #endif
                    395:        nop
                    396:        nop
                    397:        nop
                    398:        nop
                    399:
                    400: ctx3:
                    401:
                    402: /*
                    403:  * Restore registers and return.
                    404:  */
                    405:        REG_L   a0, PCB_CONTEXT+13*REGSZ(t3)
                    406:        REG_L   s0, PCB_CONTEXT+0*REGSZ(t3)
                    407:        REG_L   s1, PCB_CONTEXT+1*REGSZ(t3)
                    408:        REG_L   s2, PCB_CONTEXT+2*REGSZ(t3)
                    409:        REG_L   s3, PCB_CONTEXT+3*REGSZ(t3)
                    410:        REG_L   s4, PCB_CONTEXT+4*REGSZ(t3)
                    411:        REG_L   s5, PCB_CONTEXT+5*REGSZ(t3)
                    412:        REG_L   s6, PCB_CONTEXT+6*REGSZ(t3)
                    413:        REG_L   s7, PCB_CONTEXT+7*REGSZ(t3)
                    414:        REG_L   sp, PCB_CONTEXT+8*REGSZ(t3)
                    415:        REG_L   s8, PCB_CONTEXT+9*REGSZ(t3)
                    416:        sw      a0, cpl
                    417: #ifdef IMASK_EXTERNAL
                    418:        jal     hw_setintrmask
                    419:        nop
                    420: #endif
                    421:        REG_L   ra, PCB_CONTEXT+10*REGSZ(t3)
                    422:        REG_L   v0, PCB_CONTEXT+11*REGSZ(t3)
                    423:        REG_L   v1, PCB_CONTEXT+12*REGSZ(t3)
                    424: #ifndef IMASK_EXTERNAL
                    425:        ctc0    v1, COP_0_ICR           # XXX RM7000
                    426: #endif
                    427:        mtc0    v0, COP_0_STATUS_REG
                    428:        ITLBNOPFIX
                    429:        j       ra
                    430:        nop
                    431: 4:
                    432:        PANIC("cpu_switch")                     # nothing in queue
                    433: END(cpu_switch)

CVSweb