[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     ! 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