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

Annotation of sys/arch/arm/arm/cpuswitch.S, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: cpuswitch.S,v 1.7 2007/05/14 07:07:09 art Exp $       */
        !             2: /*     $NetBSD: cpuswitch.S,v 1.41 2003/11/15 08:44:18 scw Exp $       */
        !             3:
        !             4: /*
        !             5:  * Copyright 2003 Wasabi Systems, Inc.
        !             6:  * All rights reserved.
        !             7:  *
        !             8:  * Written by Steve C. Woodford for Wasabi Systems, Inc.
        !             9:  *
        !            10:  * Redistribution and use in source and binary forms, with or without
        !            11:  * modification, are permitted provided that the following conditions
        !            12:  * are met:
        !            13:  * 1. Redistributions of source code must retain the above copyright
        !            14:  *    notice, this list of conditions and the following disclaimer.
        !            15:  * 2. Redistributions in binary form must reproduce the above copyright
        !            16:  *    notice, this list of conditions and the following disclaimer in the
        !            17:  *    documentation and/or other materials provided with the distribution.
        !            18:  * 3. All advertising materials mentioning features or use of this software
        !            19:  *    must display the following acknowledgement:
        !            20:  *      This product includes software developed for the NetBSD Project by
        !            21:  *      Wasabi Systems, Inc.
        !            22:  * 4. The name of Wasabi Systems, Inc. may not be used to endorse
        !            23:  *    or promote products derived from this software without specific prior
        !            24:  *    written permission.
        !            25:  *
        !            26:  * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
        !            27:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
        !            28:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
        !            29:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL WASABI SYSTEMS, INC
        !            30:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
        !            31:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
        !            32:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
        !            33:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
        !            34:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
        !            35:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
        !            36:  * POSSIBILITY OF SUCH DAMAGE.
        !            37:  */
        !            38: /*
        !            39:  * Copyright (c) 1994-1998 Mark Brinicombe.
        !            40:  * Copyright (c) 1994 Brini.
        !            41:  * All rights reserved.
        !            42:  *
        !            43:  * This code is derived from software written for Brini by Mark Brinicombe
        !            44:  *
        !            45:  * Redistribution and use in source and binary forms, with or without
        !            46:  * modification, are permitted provided that the following conditions
        !            47:  * are met:
        !            48:  * 1. Redistributions of source code must retain the above copyright
        !            49:  *    notice, this list of conditions and the following disclaimer.
        !            50:  * 2. Redistributions in binary form must reproduce the above copyright
        !            51:  *    notice, this list of conditions and the following disclaimer in the
        !            52:  *    documentation and/or other materials provided with the distribution.
        !            53:  * 3. All advertising materials mentioning features or use of this software
        !            54:  *    must display the following acknowledgement:
        !            55:  *     This product includes software developed by Brini.
        !            56:  * 4. The name of the company nor the name of the author may be used to
        !            57:  *    endorse or promote products derived from this software without specific
        !            58:  *    prior written permission.
        !            59:  *
        !            60:  * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
        !            61:  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
        !            62:  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
        !            63:  * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
        !            64:  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
        !            65:  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
        !            66:  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            67:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            68:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            69:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            70:  * SUCH DAMAGE.
        !            71:  *
        !            72:  * RiscBSD kernel project
        !            73:  *
        !            74:  * cpuswitch.S
        !            75:  *
        !            76:  * cpu switching functions
        !            77:  *
        !            78:  * Created      : 15/10/94
        !            79:  */
        !            80:
        !            81: #include "assym.h"
        !            82: #include <machine/cpu.h>
        !            83: #include <machine/frame.h>
        !            84: #include <machine/intr.h>
        !            85: #include <machine/asm.h>
        !            86:
        !            87: /* LINTSTUB: include <sys/param.h> */
        !            88:
        !            89: #undef IRQdisable
        !            90: #undef IRQenable
        !            91:
        !            92: /*
        !            93:  * New experimental definitions of IRQdisable and IRQenable
        !            94:  * These keep FIQ's enabled since FIQ's are special.
        !            95:  */
        !            96:
        !            97: #define IRQdisable \
        !            98:        mrs     r14, cpsr ; \
        !            99:        orr     r14, r14, #(I32_bit) ; \
        !           100:        msr     cpsr_c, r14 ; \
        !           101:
        !           102: #define IRQenable \
        !           103:        mrs     r14, cpsr ; \
        !           104:        bic     r14, r14, #(I32_bit) ; \
        !           105:        msr     cpsr_c, r14 ; \
        !           106:
        !           107: /*
        !           108:  * These are used for switching the translation table/DACR.
        !           109:  * Since the vector page can be invalid for a short time, we must
        !           110:  * disable both regular IRQs *and* FIQs.
        !           111:  *
        !           112:  * XXX: This is not necessary if the vector table is relocated.
        !           113:  */
        !           114: #define IRQdisableALL \
        !           115:        mrs     r14, cpsr ; \
        !           116:        orr     r14, r14, #(I32_bit | F32_bit) ; \
        !           117:        msr     cpsr_c, r14
        !           118:
        !           119: #define IRQenableALL \
        !           120:        mrs     r14, cpsr ; \
        !           121:        bic     r14, r14, #(I32_bit | F32_bit) ; \
        !           122:        msr     cpsr_c, r14
        !           123:
        !           124:        .text
        !           125:
        !           126: .Lwhichqs:
        !           127:        .word   _C_LABEL(whichqs)
        !           128:
        !           129: .Lqs:
        !           130:        .word   _C_LABEL(qs)
        !           131:
        !           132: /*
        !           133:  * On entry
        !           134:  *     r0 = process
        !           135:  */
        !           136:
        !           137: ENTRY(setrunqueue)
        !           138:        /*
        !           139:         * Local register usage
        !           140:         *      r0 = process
        !           141:         *      r1 = queue
        !           142:         *      r2 = &qs[queue] and temp
        !           143:         *      r3 = temp
        !           144:         *      r12 = whichqs
        !           145:         */
        !           146: #ifdef DIAGNOSTIC
        !           147:        ldr     r1, [r0, #(P_BACK)]
        !           148:        teq     r1, #0x00000000
        !           149:        bne     Lsetrunqueue_erg
        !           150:
        !           151:        ldr     r1, [r0, #(P_WCHAN)]
        !           152:        teq     r1, #0x00000000
        !           153:        bne     Lsetrunqueue_erg
        !           154: #endif
        !           155:
        !           156:        /* Get the priority of the queue */
        !           157:        ldrb    r1, [r0, #(P_PRIORITY)]
        !           158:        mov     r1, r1, lsr #2
        !           159:
        !           160:        /* Indicate that there is a process on this queue */
        !           161:        ldr     r12, .Lwhichqs
        !           162:        ldr     r2, [r12]
        !           163:        mov     r3, #0x00000001
        !           164:        mov     r3, r3, lsl r1
        !           165:        orr     r2, r2, r3
        !           166:        str     r2, [r12]
        !           167:
        !           168:        /* Get the address of the queue */
        !           169:        ldr     r2, .Lqs
        !           170:        add     r1, r2, r1, lsl # 3
        !           171:
        !           172:        /* Hook the process in */
        !           173:        str     r1, [r0, #(P_FORW)]
        !           174:        ldr     r2, [r1, #(P_BACK)]
        !           175:
        !           176:        str     r0, [r1, #(P_BACK)]
        !           177: #ifdef DIAGNOSTIC
        !           178:        teq     r2, #0x00000000
        !           179:        beq     Lsetrunqueue_erg
        !           180: #endif
        !           181:        str     r0, [r2, #(P_FORW)]
        !           182:        str     r2, [r0, #(P_BACK)]
        !           183:
        !           184:        mov     pc, lr
        !           185:
        !           186: #ifdef DIAGNOSTIC
        !           187: Lsetrunqueue_erg:
        !           188:        mov     r2, r1
        !           189:        mov     r1, r0
        !           190:        add     r0, pc, #Ltext1 - . - 8
        !           191:        bl      _C_LABEL(printf)
        !           192:
        !           193:        ldr     r2, .Lqs
        !           194:        ldr     r1, [r2]
        !           195:        add     r0, pc, #Ltext2 - . - 8
        !           196:        b       _C_LABEL(panic)
        !           197:
        !           198: Ltext1:
        !           199:        .asciz  "setrunqueue : %08x %08x\n"
        !           200: Ltext2:
        !           201:        .asciz  "setrunqueue : [qs]=%08x qs=%08x\n"
        !           202:        .align  0
        !           203: #endif
        !           204:
        !           205: /*
        !           206:  * On entry
        !           207:  *     r0 = process
        !           208:  */
        !           209:
        !           210: ENTRY(remrunqueue)
        !           211:        /*
        !           212:         * Local register usage
        !           213:         *      r0 = oldproc
        !           214:         *      r1 = queue
        !           215:         *      r2 = &qs[queue] and scratch
        !           216:         *      r3 = scratch
        !           217:         *      r12 = whichqs
        !           218:         */
        !           219:
        !           220:        /* Get the priority of the queue */
        !           221:        ldrb    r1, [r0, #(P_PRIORITY)]
        !           222:        mov     r1, r1, lsr #2
        !           223:
        !           224:        /* Unhook the process */
        !           225:        ldr     r2, [r0, #(P_FORW)]
        !           226:        ldr     r3, [r0, #(P_BACK)]
        !           227:
        !           228:        str     r3, [r2, #(P_BACK)]
        !           229:        str     r2, [r3, #(P_FORW)]
        !           230:
        !           231:        /* If the queue is now empty clear the queue not empty flag */
        !           232:        teq     r2, r3
        !           233:
        !           234:        /* This could be reworked to avoid the use of r4 */
        !           235:        ldreq   r12, .Lwhichqs
        !           236:        ldreq   r2, [r12]
        !           237:        moveq   r3, #0x00000001
        !           238:        moveq   r3, r3, lsl r1
        !           239:        biceq   r2, r2, r3
        !           240:        streq   r2, [r12]
        !           241:
        !           242:        /* Remove the back pointer for the process */
        !           243:        mov     r1, #0x00000000
        !           244:        str     r1, [r0, #(P_BACK)]
        !           245:
        !           246:        mov     pc, lr
        !           247:
        !           248:
        !           249: /*
        !           250:  * cpuswitch()
        !           251:  *
        !           252:  * preforms a process context switch.
        !           253:  * This function has several entry points
        !           254:  */
        !           255:
        !           256: .Lcpu_info_store:
        !           257:        .word   _C_LABEL(cpu_info_store)
        !           258: .Lcurproc:
        !           259:        .word   _C_LABEL(cpu_info_store) + CI_CURPROC
        !           260:
        !           261:
        !           262: .Lwant_resched:
        !           263:        .word   _C_LABEL(want_resched)
        !           264:
        !           265: .Lcpufuncs:
        !           266:        .word   _C_LABEL(cpufuncs)
        !           267:
        !           268: #ifndef MULTIPROCESSOR
        !           269: .Lcurpcb:
        !           270:        .word   _C_LABEL(curpcb)
        !           271:        .data
        !           272:        .global _C_LABEL(curpcb)
        !           273: _C_LABEL(curpcb):
        !           274:        .word   0x00000000
        !           275:        .text
        !           276: #else
        !           277: .Lcurpcb:
        !           278:        .word   _C_LABEL(cpu_info_store) + CI_CURPCB
        !           279: #endif
        !           280:
        !           281: .Lcpu_do_powersave:
        !           282:        .word   _C_LABEL(cpu_do_powersave)
        !           283:
        !           284: .Lpmap_kernel_cstate:
        !           285:        .word   (kernel_pmap_store + PMAP_CSTATE)
        !           286:
        !           287: .Llast_cache_state_ptr:
        !           288:        .word   _C_LABEL(pmap_cache_state)
        !           289:
        !           290: /*
        !           291:  * Idle loop, exercised while waiting for a process to wake up.
        !           292:  *
        !           293:  * NOTE: When we jump back to .Lswitch_search, we must have a
        !           294:  * pointer to whichqs in r7, which is what it is when we arrive
        !           295:  * here.
        !           296:  */
        !           297: /* LINTSTUB: Ignore */
        !           298: ASENTRY_NP(idle)
        !           299:        ldr     r6, .Lcpu_do_powersave
        !           300:        IRQenable                       /* Enable interrupts */
        !           301:        ldr     r6, [r6]                /* r6 = cpu_do_powersave */
        !           302:
        !           303: #if defined(MULTIPROCESSOR) || defined(LOCKDEBUG)
        !           304:        bl      _C_LABEL(sched_unlock_idle)
        !           305: #endif
        !           306:
        !           307:        /* Drop to spl0 (returns the current spl level in r0). */
        !           308:        mov     r0, #(IPL_NONE)
        !           309:        bl      _C_LABEL(_spllower)
        !           310:
        !           311:        teq     r6, #0                  /* cpu_do_powersave non zero? */
        !           312:        ldrne   r6, .Lcpufuncs
        !           313:        mov     r4, r0                  /* Old interrupt level to r4 */
        !           314:        ldrne   r6, [r6, #(CF_SLEEP)]
        !           315:
        !           316:        /*
        !           317:         * Main idle loop.
        !           318:         * r6 points to power-save idle function if required, else NULL.
        !           319:         */
        !           320: 1:     ldr     r3, [r7]                /* r3 = sched_whichqs */
        !           321:        teq     r3, #0
        !           322:        bne     2f                      /* We have work to do */
        !           323:        teq     r6, #0                  /* Powersave idle? */
        !           324:        beq     1b                      /* Nope. Just sit-n-spin. */
        !           325:
        !           326:        /*
        !           327:         * Before going into powersave idle mode, disable interrupts
        !           328:         * and check sched_whichqs one more time.
        !           329:         */
        !           330:        IRQdisableALL
        !           331:        ldr     r3, [r7]
        !           332:        mov     r0, #0
        !           333:        teq     r3, #0                  /* sched_whichqs still zero? */
        !           334:        moveq   lr, pc
        !           335:        moveq   pc, r6                  /* If so, do powersave idle */
        !           336:        IRQenableALL
        !           337:        b       1b                      /* Back around */
        !           338:
        !           339:        /*
        !           340:         * sched_whichqs indicates that at least one proc is ready to run.
        !           341:         * Restore the original interrupt priority level, grab the
        !           342:         * scheduler lock if necessary, and jump back into cpu_switch.
        !           343:         */
        !           344: 2:     mov     r0, r4
        !           345: #if defined(MULTIPROCESSOR) || defined(LOCKDEBUG)
        !           346:        bl      _C_LABEL(splx)
        !           347:        adr     lr, .Lswitch_search
        !           348:        b       _C_LABEL(sched_lock_idle)
        !           349: #else
        !           350:        adr     lr, .Lswitch_search
        !           351:        b       _C_LABEL(splx)
        !           352: #endif
        !           353:
        !           354:
        !           355: /*
        !           356:  * Find a new lwp to run, save the current context and
        !           357:  * load the new context
        !           358:  *
        !           359:  * Arguments:
        !           360:  *     r0      'struct proc *' of the current LWP
        !           361:  */
        !           362:
        !           363: ENTRY(cpu_switch)
        !           364: /*
        !           365:  * Local register usage. Some of these registers are out of date.
        !           366:  * r1 = oldproc
        !           367:  * r2 = spl level
        !           368:  * r3 = whichqs
        !           369:  * r4 = queue
        !           370:  * r5 = &qs[queue]
        !           371:  * r6 = newlwp
        !           372:  * r7 = scratch
        !           373:  */
        !           374:        stmfd   sp!, {r4-r7, lr}
        !           375:
        !           376:        /*
        !           377:         * Indicate that there is no longer a valid process (curlwp = 0).
        !           378:         * Zero the current PCB pointer while we're at it.
        !           379:         */
        !           380:        ldr     r7, .Lcurproc
        !           381:        ldr     r6, .Lcurpcb
        !           382:        mov     r2, #0x00000000
        !           383:        str     r2, [r7]                /* curproc = NULL */
        !           384:        str     r2, [r6]                /* curpcb = NULL */
        !           385:
        !           386:        /* stash the old proc while we call functions */
        !           387:        mov     r5, r0
        !           388:
        !           389:        /* First phase : find a new proc */
        !           390:        ldr     r7, .Lwhichqs
        !           391:
        !           392:        /* rem: r5 = old proc */
        !           393:        /* rem: r7 = &whichqs */
        !           394:
        !           395: .Lswitch_search:
        !           396:        IRQdisable
        !           397:
        !           398:        /* Do we have any active queues  */
        !           399:        ldr     r3, [r7]
        !           400:
        !           401:        /* If not we must idle until we do. */
        !           402:        teq     r3, #0x00000000
        !           403:        beq     _ASM_LABEL(idle)
        !           404:
        !           405:        /* put old proc back in r1 */
        !           406:        mov     r1, r5
        !           407:
        !           408:        /* rem: r1 = old proc */
        !           409:        /* rem: r3 = whichqs */
        !           410:        /* rem: interrupts are disabled */
        !           411:
        !           412:        /* used further down, saves SA stall */
        !           413:        ldr     r6, .Lqs
        !           414:
        !           415:        /*
        !           416:         * We have found an active queue. Currently we do not know which queue
        !           417:         * is active just that one of them is.
        !           418:         */
        !           419:        /* Non-Xscale version of the ffs algorithm devised by d.seal and
        !           420:         * posted to comp.sys.arm on 16 Feb 1994.
        !           421:         */
        !           422:        rsb     r5, r3, #0
        !           423:        ands    r0, r3, r5
        !           424:
        !           425: #ifndef __XSCALE__
        !           426:        adr     r5, .Lcpu_switch_ffs_table
        !           427:
        !           428:                                    /* X = R0 */
        !           429:        orr     r4, r0, r0, lsl #4  /* r4 = X * 0x11 */
        !           430:        orr     r4, r4, r4, lsl #6  /* r4 = X * 0x451 */
        !           431:        rsb     r4, r4, r4, lsl #16 /* r4 = X * 0x0450fbaf */
        !           432:
        !           433:        /* now lookup in table indexed on top 6 bits of a4 */
        !           434:        ldrb    r4, [ r5, r4, lsr #26 ]
        !           435:
        !           436: #else  /* __XSCALE__ */
        !           437:        clz     r4, r0
        !           438:        rsb     r4, r4, #31
        !           439: #endif /* __XSCALE__ */
        !           440:
        !           441:        /* rem: r0 = bit mask of chosen queue (1 << r4) */
        !           442:        /* rem: r1 = old proc */
        !           443:        /* rem: r3 = whichqs */
        !           444:        /* rem: r4 = queue number */
        !           445:        /* rem: interrupts are disabled */
        !           446:
        !           447:        /* Get the address of the queue (&qs[queue]) */
        !           448:        add     r5, r6, r4, lsl #3
        !           449:
        !           450:        /*
        !           451:         * Get the proc from the queue and place the next process in
        !           452:         * the queue at the head. This basically unlinks the lwp at
        !           453:         * the head of the queue.
        !           454:         */
        !           455:        ldr     r6, [r5, #(P_FORW)]
        !           456:
        !           457: #ifdef DIAGNOSTIC
        !           458:        cmp     r6, r5
        !           459:        beq     .Lswitch_bogons
        !           460: #endif
        !           461:
        !           462:        /* rem: r6 = new proc */
        !           463:        ldr     r7, [r6, #(P_FORW)]
        !           464:        str     r7, [r5, #(P_FORW)]
        !           465:
        !           466:        /*
        !           467:         * Test to see if the queue is now empty. If the head of the queue
        !           468:         * points to the queue itself then there are no more procs in
        !           469:         * the queue. We can therefore clear the queue not empty flag held
        !           470:         * in r3.
        !           471:         */
        !           472:
        !           473:        teq     r5, r7
        !           474:        biceq   r3, r3, r0
        !           475:
        !           476:        /* rem: r0 = bit mask of chosen queue (1 << r4) - NOT NEEDED AN MORE */
        !           477:
        !           478:        /* Fix the back pointer for the lwp now at the head of the queue. */
        !           479:        ldr     r0, [r6, #(P_BACK)]
        !           480:        str     r0, [r7, #(P_BACK)]
        !           481:
        !           482:        /* Update the RAM copy of the queue not empty flags word. */
        !           483:        ldreq   r7, .Lwhichqs
        !           484:        streq   r3, [r7]
        !           485:
        !           486:        /* rem: r1 = old proc */
        !           487:        /* rem: r3 = whichqs - NOT NEEDED ANY MORE */
        !           488:        /* rem: r4 = queue number - NOT NEEDED ANY MORE */
        !           489:        /* rem: r6 = new proc */
        !           490:        /* rem: interrupts are disabled */
        !           491:
        !           492:        /* Clear the want_resched flag */
        !           493:        ldr     r7, .Lwant_resched
        !           494:        mov     r0, #0x00000000
        !           495:        str     r0, [r7]
        !           496:
        !           497:        /*
        !           498:         * Clear the back pointer of the proc we have removed from
        !           499:         * the head of the queue. The new proc is isolated now.
        !           500:         */
        !           501:        str     r0, [r6, #(P_BACK)]
        !           502:
        !           503: #if defined(MULTIPROCESSOR) || defined(LOCKDEBUG)
        !           504:        /*
        !           505:         * unlock the sched_lock, but leave interrupts off, for now.
        !           506:         */
        !           507:        mov     r7, r1
        !           508:        bl      _C_LABEL(sched_unlock_idle)
        !           509:        mov     r1, r7
        !           510: #endif
        !           511:
        !           512:
        !           513: .Lswitch_resume:
        !           514:        /* rem: r1 = old proc */
        !           515:        /* rem: r4 = return value [not used if came from cpu_switchto()] */
        !           516:        /* rem: r6 = new process */
        !           517:        /* rem: interrupts are disabled */
        !           518:
        !           519: #ifdef MULTIPROCESSOR
        !           520:        /* XXX use curcpu() */
        !           521:        ldr     r0, .Lcpu_info_store
        !           522:        str     r0, [r6, #(P_CPU)]
        !           523: #else
        !           524:        /* l->l_cpu initialized in fork1() for single-processor */
        !           525: #endif
        !           526:
        !           527:        /* Process is now on a processor. */
        !           528:        mov     r0, #SONPROC                    /* p->p_stat = SONPROC */
        !           529:        strb    r0, [r6, #(P_STAT)]
        !           530:
        !           531:        /* We have a new curproc now so make a note it */
        !           532:        ldr     r7, .Lcurproc
        !           533:        str     r6, [r7]
        !           534:
        !           535:        /* Hook in a new pcb */
        !           536:        ldr     r7, .Lcurpcb
        !           537:        ldr     r0, [r6, #(P_ADDR)]
        !           538:        str     r0, [r7]
        !           539:
        !           540:        /* At this point we can allow IRQ's again. */
        !           541:        IRQenable
        !           542:
        !           543:        /* rem: r1 = old proc */
        !           544:        /* rem: r4 = return value */
        !           545:        /* rem: r6 = new process */
        !           546:        /* rem: interrupts are enabled */
        !           547:
        !           548:        /*
        !           549:         * If the new process is the same as the process that called
        !           550:         * cpu_switch() then we do not need to save and restore any
        !           551:         * contexts. This means we can make a quick exit.
        !           552:         * The test is simple if curproc on entry (now in r1) is the
        !           553:         * same as the proc removed from the queue we can jump to the exit.
        !           554:         */
        !           555:        teq     r1, r6
        !           556:        moveq   r4, #0x00000000         /* default to "didn't switch" */
        !           557:        beq     .Lswitch_return
        !           558:
        !           559:        /*
        !           560:         * At this point, we are guaranteed to be switching to
        !           561:         * a new proc.
        !           562:         */
        !           563:        mov     r4, #0x00000001
        !           564:
        !           565:        /* Remember the old proc in r0 */
        !           566:        mov     r0, r1
        !           567:
        !           568:        /*
        !           569:         * If the old proc on entry to cpu_switch was zero then the
        !           570:         * process that called it was exiting. This means that we do
        !           571:         * not need to save the current context. Instead we can jump
        !           572:         * straight to restoring the context for the new process.
        !           573:         */
        !           574:        teq     r0, #0x00000000
        !           575:        beq     .Lswitch_exited
        !           576:
        !           577:        /* rem: r0 = old proc */
        !           578:        /* rem: r4 = return value */
        !           579:        /* rem: r6 = new process */
        !           580:        /* rem: interrupts are enabled */
        !           581:
        !           582:        /* Stage two : Save old context */
        !           583:
        !           584:        /* Get the user structure for the old proc. */
        !           585:        ldr     r1, [r0, #(P_ADDR)]
        !           586:
        !           587:        /* Save all the registers in the old proc's pcb */
        !           588: #ifndef __XSCALE__
        !           589:        add     r7, r1, #(PCB_R8)
        !           590:        stmia   r7, {r8-r13}
        !           591: #else
        !           592:        strd    r8, [r1, #(PCB_R8)]
        !           593:        strd    r10, [r1, #(PCB_R10)]
        !           594:        strd    r12, [r1, #(PCB_R12)]
        !           595: #endif
        !           596:
        !           597:        /*
        !           598:         * NOTE: We can now use r8-r13 until it is time to restore
        !           599:         * them for the new process.
        !           600:         */
        !           601:
        !           602:        /* Remember the old PCB. */
        !           603:        mov     r8, r1
        !           604:
        !           605:        /* r1 now free! */
        !           606:
        !           607:        /* Get the user structure for the new process in r9 */
        !           608:        ldr     r9, [r6, #(P_ADDR)]
        !           609:
        !           610:        /*
        !           611:         * This can be optimised... We know we want to go from SVC32
        !           612:         * mode to UND32 mode
        !           613:         */
        !           614:         mrs    r3, cpsr
        !           615:        bic     r2, r3, #(PSR_MODE)
        !           616:        orr     r2, r2, #(PSR_UND32_MODE | I32_bit)
        !           617:         msr    cpsr_c, r2
        !           618:
        !           619:        str     sp, [r8, #(PCB_UND_SP)]
        !           620:
        !           621:         msr    cpsr_c, r3              /* Restore the old mode */
        !           622:
        !           623:        /* rem: r0 = old proc */
        !           624:        /* rem: r4 = return value */
        !           625:        /* rem: r6 = new process */
        !           626:        /* rem: r8 = old PCB */
        !           627:        /* rem: r9 = new PCB */
        !           628:        /* rem: interrupts are enabled */
        !           629:
        !           630:        /* What else needs to be saved  Only FPA stuff when that is supported */
        !           631:
        !           632:        /* Third phase : restore saved context */
        !           633:
        !           634:        /* rem: r0 = old proc */
        !           635:        /* rem: r4 = return value */
        !           636:        /* rem: r6 = new proc */
        !           637:        /* rem: r8 = old PCB */
        !           638:        /* rem: r9 = new PCB */
        !           639:        /* rem: interrupts are enabled */
        !           640:
        !           641:        /*
        !           642:         * Get the new L1 table pointer into r11.  If we're switching to
        !           643:         * an LWP with the same address space as the outgoing one, we can
        !           644:         * skip the cache purge and the TTB load.
        !           645:         *
        !           646:         * To avoid data dep stalls that would happen anyway, we try
        !           647:         * and get some useful work done in the mean time.
        !           648:         */
        !           649:        ldr     r10, [r8, #(PCB_PAGEDIR)]       /* r10 = old L1 */
        !           650:        ldr     r11, [r9, #(PCB_PAGEDIR)]       /* r11 = new L1 */
        !           651:
        !           652:        ldr     r0, [r8, #(PCB_DACR)]           /* r0 = old DACR */
        !           653:        ldr     r1, [r9, #(PCB_DACR)]           /* r1 = new DACR */
        !           654:        ldr     r8, [r9, #(PCB_CSTATE)]         /* r8 = &new_pmap->pm_cstate */
        !           655:        ldr     r5, .Llast_cache_state_ptr      /* Previous thread's cstate */
        !           656:
        !           657:        teq     r10, r11                        /* Same L1? */
        !           658:        ldr     r5, [r5]
        !           659:        cmpeq   r0, r1                          /* Same DACR? */
        !           660:        beq     .Lcs_context_switched           /* yes! */
        !           661:
        !           662:        mov     r12, #0
        !           663:        cmp     r5, #0                          /* No last vm? (switch_exit) */
        !           664:        beq     .Lcs_cache_purge_skipped        /* No, we can skip cache flsh */
        !           665:
        !           666:        mov     r2, #DOMAIN_CLIENT
        !           667:        cmp     r1, r2, lsl #(PMAP_DOMAIN_KERNEL * 2) /* Sw to kernel thread? */
        !           668:        beq     .Lcs_cache_purge_skipped        /* Yup. Don't flush cache */
        !           669:
        !           670:        cmp     r5, r8                          /* Same userland VM space? */
        !           671:        ldrneb  r12, [r5, #(CS_CACHE_ID)]       /* Last VM space cache state */
        !           672:
        !           673:        /*
        !           674:         * We're definately switching to a new userland VM space,
        !           675:         * and the previous userland VM space has yet to be flushed
        !           676:         * from the cache/tlb.
        !           677:         *
        !           678:         * r12 holds the previous VM space's cs_cache_id state
        !           679:         */
        !           680:        tst     r12, #0xff                      /* Test cs_cache_id */
        !           681:        beq     .Lcs_cache_purge_skipped        /* VM space is not in cache */
        !           682:
        !           683:        /*
        !           684:         * Definately need to flush the cache.
        !           685:         * Mark the old VM space as NOT being resident in the cache.
        !           686:         */
        !           687:        mov     r2, #0x00000000
        !           688:        strb    r2, [r5, #(CS_CACHE_ID)]
        !           689:        strb    r2, [r5, #(CS_CACHE_D)]
        !           690:
        !           691:        stmfd   sp!, {r0-r3}
        !           692:        ldr     r1, .Lcpufuncs
        !           693:        mov     lr, pc
        !           694:        ldr     pc, [r1, #CF_IDCACHE_WBINV_ALL]
        !           695:        ldmfd   sp!, {r0-r3}
        !           696:
        !           697: .Lcs_cache_purge_skipped:
        !           698:        /* rem: r1 = new DACR */
        !           699:        /* rem: r4 = return value */
        !           700:        /* rem: r5 = &old_pmap->pm_cstate (or NULL) */
        !           701:        /* rem: r6 = new proc */
        !           702:        /* rem: r8 = &new_pmap->pm_cstate */
        !           703:        /* rem: r9 = new PCB */
        !           704:        /* rem: r10 = old L1 */
        !           705:        /* rem: r11 = new L1 */
        !           706:
        !           707:        ldr     r7, [r9, #(PCB_PL1VEC)]
        !           708:
        !           709:        /*
        !           710:         * At this point we need to kill IRQ's again.
        !           711:         *
        !           712:         * XXXSCW: Don't need to block FIQs if vectors have been relocated
        !           713:         */
        !           714:        IRQdisableALL
        !           715:
        !           716:        /*
        !           717:         * Ensure the vector table is accessible by fixing up the L1
        !           718:         */
        !           719:        cmp     r7, #0                  /* No need to fixup vector table? */
        !           720:        ldrne   r2, [r7]                /* But if yes, fetch current value */
        !           721:        ldrne   r0, [r9, #(PCB_L1VEC)]  /* Fetch new vector_page value */
        !           722:        mcr     p15, 0, r1, c3, c0, 0   /* Update DACR for new context */
        !           723:        cmpne   r2, r0                  /* Stuffing the same value? */
        !           724: #ifndef PMAP_INCLUDE_PTE_SYNC
        !           725:        strne   r0, [r7]                /* Nope, update it */
        !           726: #else
        !           727:        beq     .Lcs_same_vector
        !           728:        str     r0, [r7]                /* Otherwise, update it */
        !           729:
        !           730:        /*
        !           731:         * Need to sync the cache to make sure that last store is
        !           732:         * visible to the MMU.
        !           733:         */
        !           734:        ldr     r2, .Lcpufuncs
        !           735:        mov     r0, r7
        !           736:        mov     r1, #4
        !           737:        mov     lr, pc
        !           738:        ldr     pc, [r2, #CF_DCACHE_WB_RANGE]
        !           739:
        !           740: .Lcs_same_vector:
        !           741: #endif /* PMAP_INCLUDE_PTE_SYNC */
        !           742:
        !           743:        cmp     r10, r11                /* Switching to the same L1? */
        !           744:        ldr     r10, .Lcpufuncs
        !           745:        beq     .Lcs_same_l1            /* Yup. */
        !           746:
        !           747:        /*
        !           748:         * Do a full context switch, including full TLB flush.
        !           749:         */
        !           750:        mov     r0, r11
        !           751:        mov     lr, pc
        !           752:        ldr     pc, [r10, #CF_CONTEXT_SWITCH]
        !           753:
        !           754:        /*
        !           755:         * Mark the old VM space as NOT being resident in the TLB
        !           756:         */
        !           757:        mov     r2, #0x00000000
        !           758:        cmp     r5, #0
        !           759:        strneh  r2, [r5, #(CS_TLB_ID)]
        !           760:        b       .Lcs_context_switched
        !           761:
        !           762:        /*
        !           763:         * We're switching to a different process in the same L1.
        !           764:         * In this situation, we only need to flush the TLB for the
        !           765:         * vector_page mapping, and even then only if r7 is non-NULL.
        !           766:         */
        !           767: .Lcs_same_l1:
        !           768:        cmp     r7, #0
        !           769:        movne   r0, #0                  /* We *know* vector_page's VA is 0x0 */
        !           770:        movne   lr, pc
        !           771:        ldrne   pc, [r10, #CF_TLB_FLUSHID_SE]
        !           772:
        !           773: .Lcs_context_switched:
        !           774:        /* rem: r8 = &new_pmap->pm_cstate */
        !           775:
        !           776:        /* XXXSCW: Safe to re-enable FIQs here */
        !           777:
        !           778:        /*
        !           779:         * The new VM space is live in the cache and TLB.
        !           780:         * Update its cache/tlb state, and if it's not the kernel
        !           781:         * pmap, update the 'last cache state' pointer.
        !           782:         */
        !           783:        mov     r2, #-1
        !           784:        ldr     r5, .Lpmap_kernel_cstate
        !           785:        ldr     r0, .Llast_cache_state_ptr
        !           786:        str     r2, [r8, #(CS_ALL)]
        !           787:        cmp     r5, r8
        !           788:        strne   r8, [r0]
        !           789:
        !           790:        /* rem: r4 = return value */
        !           791:        /* rem: r6 = new proc */
        !           792:        /* rem: r9 = new PCB */
        !           793:
        !           794:        /*
        !           795:         * This can be optimised... We know we want to go from SVC32
        !           796:         * mode to UND32 mode
        !           797:         */
        !           798:         mrs    r3, cpsr
        !           799:        bic     r2, r3, #(PSR_MODE)
        !           800:        orr     r2, r2, #(PSR_UND32_MODE)
        !           801:         msr    cpsr_c, r2
        !           802:
        !           803:        ldr     sp, [r9, #(PCB_UND_SP)]
        !           804:
        !           805:         msr    cpsr_c, r3              /* Restore the old mode */
        !           806:
        !           807:        /* Restore all the save registers */
        !           808: #ifndef __XSCALE__
        !           809:        add     r7, r9, #PCB_R8
        !           810:        ldmia   r7, {r8-r13}
        !           811:
        !           812:        sub     r7, r7, #PCB_R8         /* restore PCB pointer */
        !           813: #else
        !           814:        mov     r7, r9
        !           815:        ldr     r8, [r7, #(PCB_R8)]
        !           816:        ldr     r9, [r7, #(PCB_R9)]
        !           817:        ldr     r10, [r7, #(PCB_R10)]
        !           818:        ldr     r11, [r7, #(PCB_R11)]
        !           819:        ldr     r12, [r7, #(PCB_R12)]
        !           820:        ldr     r13, [r7, #(PCB_SP)]
        !           821: #endif
        !           822:
        !           823: #if 0
        !           824:        ldr     r5, [r6, #(L_PROC)]     /* fetch the proc for below */
        !           825: #else
        !           826:        mov     r5, r6
        !           827: #endif
        !           828:
        !           829:        /* rem: r4 = return value */
        !           830:        /* rem: r5 = new proc's proc */
        !           831:        /* rem: r6 = new proc */
        !           832:        /* rem: r7 = new pcb */
        !           833:
        !           834: #ifdef ARMFPE
        !           835:        add     r0, r7, #(USER_SIZE) & 0x00ff
        !           836:        add     r0, r0, #(USER_SIZE) & 0xff00
        !           837:        bl      _C_LABEL(arm_fpe_core_changecontext)
        !           838: #endif
        !           839:
        !           840:        /* We can enable interrupts again */
        !           841:        IRQenableALL
        !           842:
        !           843:        /* rem: r4 = return value */
        !           844:        /* rem: r5 = new proc's proc */
        !           845:        /* rem: r6 = new proc */
        !           846:        /* rem: r7 = new PCB */
        !           847:
        !           848: #if 0
        !           849:        /*
        !           850:         * Check for restartable atomic sequences (RAS).
        !           851:         */
        !           852:
        !           853:        ldr     r2, [r5, #(P_RASLIST)]
        !           854:        ldr     r1, [r7, #(PCB_TF)]     /* r1 = trapframe (used below) */
        !           855:        teq     r2, #0                  /* p->p_nras == 0? */
        !           856:        bne     .Lswitch_do_ras         /* no, check for one */
        !           857: #endif
        !           858:
        !           859: .Lswitch_return:
        !           860:        /* cpu_switch returns 1 == switched, 0 == didn't switch */
        !           861:        mov     r0, r4
        !           862:
        !           863:        /*
        !           864:         * Pull the registers that got pushed when either savectx() or
        !           865:         * cpu_switch() was called and return.
        !           866:         */
        !           867:        ldmfd   sp!, {r4-r7, pc}
        !           868:
        !           869: #if 0
        !           870: .Lswitch_do_ras:
        !           871:        ldr     r1, [r1, #(TF_PC)]      /* second ras_lookup() arg */
        !           872:        mov     r0, r5                  /* first ras_lookup() arg */
        !           873:        bl      _C_LABEL(ras_lookup)
        !           874:        cmn     r0, #1                  /* -1 means "not in a RAS" */
        !           875:        ldrne   r1, [r7, #(PCB_TF)]
        !           876:        strne   r0, [r1, #(TF_PC)]
        !           877:        b       .Lswitch_return
        !           878: #endif
        !           879:
        !           880: .Lswitch_exited:
        !           881:        /*
        !           882:         * We skip the cache purge because switch_exit() already did it.
        !           883:         * Load up registers the way .Lcs_cache_purge_skipped expects.
        !           884:         * Userpsace access already blocked by switch_exit().
        !           885:         */
        !           886:        ldr     r9, [r6, #(P_ADDR)]             /* r9 = new PCB */
        !           887:        mrc     p15, 0, r10, c2, c0, 0          /* r10 = old L1 */
        !           888:        mov     r5, #0                          /* No previous cache state */
        !           889:        ldr     r1, [r9, #(PCB_DACR)]           /* r1 = new DACR */
        !           890:        ldr     r8, [r9, #(PCB_CSTATE)]         /* r8 = new cache state */
        !           891:        ldr     r11, [r9, #(PCB_PAGEDIR)]       /* r11 = new L1 */
        !           892:        b       .Lcs_cache_purge_skipped
        !           893:
        !           894:
        !           895: #ifdef DIAGNOSTIC
        !           896: .Lswitch_bogons:
        !           897:        adr     r0, .Lswitch_panic_str
        !           898:        bl      _C_LABEL(panic)
        !           899: 1:     nop
        !           900:        b       1b
        !           901:
        !           902: .Lswitch_panic_str:
        !           903:        .asciz  "cpu_switch: sched_qs empty with non-zero sched_whichqs!\n"
        !           904: #endif
        !           905:
        !           906: /*
        !           907:  * cpu_switchto(struct proc *current, struct proc *next)
        !           908:  * Switch to the specified next LWP
        !           909:  * Arguments:
        !           910:  *
        !           911:  *     r0      'struct proc *' of the current LWP
        !           912:  *     r1      'struct proc *' of the LWP to switch to
        !           913:  */
        !           914: ENTRY(cpu_switchto)
        !           915:        stmfd   sp!, {r4-r7, lr}
        !           916:
        !           917:        mov     r6, r1          /* save new proc */
        !           918:
        !           919: #if defined(LOCKDEBUG)
        !           920:        mov     r5, r0          /* save old proc */
        !           921:        bl      _C_LABEL(sched_unlock_idle)
        !           922:        mov     r1, r5
        !           923: #else
        !           924:        mov     r1, r0
        !           925: #endif
        !           926:
        !           927:        IRQdisable
        !           928:
        !           929:        /*
        !           930:         * Okay, set up registers the way cpu_switch() wants them,
        !           931:         * and jump into the middle of it (where we bring up the
        !           932:         * new process).
        !           933:         *
        !           934:         * r1 = old proc (r6 = new proc)
        !           935:         */
        !           936:        b       .Lswitch_resume
        !           937:
        !           938: /*
        !           939:  * void switch_exit(struct proc *l, struct proc *l0,
        !           940:  *    void (*exit)(struct proc *));
        !           941:  * Switch to proc0's saved context and deallocate the address space and kernel
        !           942:  * stack for l.  Then jump into cpu_switch(), as if we were in proc0 all along.
        !           943:  */
        !           944:
        !           945: /* LINTSTUB: Func: void switch_exit(struct proc *l, struct proc *l0,
        !           946:     void (*func)(struct proc *)) */
        !           947: ENTRY(switch_exit)
        !           948:        /*
        !           949:         * The process is going away, so we can use callee-saved
        !           950:         * registers here without having to save them.
        !           951:         */
        !           952:
        !           953:        mov     r4, r0
        !           954:        ldr     r0, .Lcurproc
        !           955:
        !           956:        mov     r5, r1
        !           957:        mov     r6, r2
        !           958:
        !           959:        /*
        !           960:         * r4 = proc
        !           961:         * r5 = proc0
        !           962:         * r6 = exit func
        !           963:         */
        !           964:
        !           965:        mov     r2, #0x00000000         /* curproc = NULL */
        !           966:        str     r2, [r0]
        !           967:
        !           968:        /*
        !           969:         * We're about to clear both the cache and the TLB.
        !           970:         * Make sure to zap the 'last cache state' pointer since the
        !           971:         * pmap might be about to go away. Also ensure the outgoing
        !           972:         * VM space's cache state is marked as NOT resident in the
        !           973:         * cache, and that proc0's cache state IS resident.
        !           974:         */
        !           975:        ldr     r7, [r4, #(P_ADDR)]             /* r7 = old proc's PCB */
        !           976:        ldr     r0, .Llast_cache_state_ptr      /* Last userland cache state */
        !           977:        ldr     r9, [r7, #(PCB_CSTATE)]         /* Fetch cache state pointer */
        !           978:        ldr     r3, [r5, #(P_ADDR)]             /* r3 = proc0's PCB */
        !           979:        str     r2, [r0]                        /* No previous cache state */
        !           980:        str     r2, [r9, #(CS_ALL)]             /* Zap old proc's cache state */
        !           981:        ldr     r3, [r3, #(PCB_CSTATE)]         /* proc0's cache state */
        !           982:        mov     r2, #-1
        !           983:        str     r2, [r3, #(CS_ALL)]             /* proc0 is in da cache! */
        !           984:
        !           985:        /* Switch to proc0 context */
        !           986:
        !           987:        ldr     r9, .Lcpufuncs
        !           988:        mov     lr, pc
        !           989:        ldr     pc, [r9, #CF_IDCACHE_WBINV_ALL]
        !           990:
        !           991:        ldr     r0, [r7, #(PCB_PL1VEC)]
        !           992:        ldr     r1, [r7, #(PCB_DACR)]
        !           993:
        !           994:        /*
        !           995:         * r0 = Pointer to L1 slot for vector_page (or NULL)
        !           996:         * r1 = proc0's DACR
        !           997:         * r4 = proc we're switching from
        !           998:         * r5 = proc0
        !           999:         * r6 = exit func
        !          1000:         * r7 = proc0's PCB
        !          1001:         * r9 = cpufuncs
        !          1002:         */
        !          1003:
        !          1004:        IRQdisableALL
        !          1005:
        !          1006:        /*
        !          1007:         * Ensure the vector table is accessible by fixing up proc0's L1
        !          1008:         */
        !          1009:        cmp     r0, #0                  /* No need to fixup vector table? */
        !          1010:        ldrne   r3, [r0]                /* But if yes, fetch current value */
        !          1011:        ldrne   r2, [r7, #(PCB_L1VEC)]  /* Fetch new vector_page value */
        !          1012:        mcr     p15, 0, r1, c3, c0, 0   /* Update DACR for proc0's context */
        !          1013:        cmpne   r3, r2                  /* Stuffing the same value? */
        !          1014:        strne   r2, [r0]                /* Store if not. */
        !          1015:
        !          1016: #ifdef PMAP_INCLUDE_PTE_SYNC
        !          1017:        /*
        !          1018:         * Need to sync the cache to make sure that last store is
        !          1019:         * visible to the MMU.
        !          1020:         */
        !          1021:        movne   r1, #4
        !          1022:        movne   lr, pc
        !          1023:        ldrne   pc, [r9, #CF_DCACHE_WB_RANGE]
        !          1024: #endif /* PMAP_INCLUDE_PTE_SYNC */
        !          1025:
        !          1026:        /*
        !          1027:         * Note: We don't do the same optimisation as cpu_switch() with
        !          1028:         * respect to avoiding flushing the TLB if we're switching to
        !          1029:         * the same L1 since this process' VM space may be about to go
        !          1030:         * away, so we don't want *any* turds left in the TLB.
        !          1031:         */
        !          1032:
        !          1033:        /* Switch the memory to the new process */
        !          1034:        ldr     r0, [r7, #(PCB_PAGEDIR)]
        !          1035:        mov     lr, pc
        !          1036:        ldr     pc, [r9, #CF_CONTEXT_SWITCH]
        !          1037:
        !          1038:        ldr     r0, .Lcurpcb
        !          1039:
        !          1040:        /* Restore all the save registers */
        !          1041: #ifndef __XSCALE__
        !          1042:        add     r1, r7, #PCB_R8
        !          1043:        ldmia   r1, {r8-r13}
        !          1044: #else
        !          1045:        ldr     r8, [r7, #(PCB_R8)]
        !          1046:        ldr     r9, [r7, #(PCB_R9)]
        !          1047:        ldr     r10, [r7, #(PCB_R10)]
        !          1048:        ldr     r11, [r7, #(PCB_R11)]
        !          1049:        ldr     r12, [r7, #(PCB_R12)]
        !          1050:        ldr     r13, [r7, #(PCB_SP)]
        !          1051: #endif
        !          1052:        str     r7, [r0]        /* curpcb = proc0's PCB */
        !          1053:
        !          1054:        IRQenableALL
        !          1055:
        !          1056:        /*
        !          1057:         * Schedule the vmspace and stack to be freed.
        !          1058:         */
        !          1059:        mov     r0, r4                  /* {proc_}exit2(l) */
        !          1060:        mov     lr, pc
        !          1061:        mov     pc, r6
        !          1062:
        !          1063: #if defined(MULTIPROCESSOR) || defined(LOCKDEBUG)
        !          1064:        bl      _C_LABEL(sched_lock_idle)
        !          1065: #endif
        !          1066:
        !          1067:        ldr     r7, .Lwhichqs           /* r7 = &whichqs */
        !          1068:        mov     r5, #0x00000000         /* r5 = old proc = NULL */
        !          1069:        b       .Lswitch_search
        !          1070:
        !          1071: /* LINTSTUB: Func: void savectx(struct pcb *pcb) */
        !          1072: ENTRY(savectx)
        !          1073:        /*
        !          1074:         * r0 = pcb
        !          1075:         */
        !          1076:
        !          1077:        /* Push registers.*/
        !          1078:        stmfd   sp!, {r4-r7, lr}
        !          1079:
        !          1080:        /* Store all the registers in the process's pcb */
        !          1081: #ifndef __XSCALE__
        !          1082:        add     r2, r0, #(PCB_R8)
        !          1083:        stmia   r2, {r8-r13}
        !          1084: #else
        !          1085:        strd    r8, [r0, #(PCB_R8)]
        !          1086:        strd    r10, [r0, #(PCB_R10)]
        !          1087:        strd    r12, [r0, #(PCB_R12)]
        !          1088: #endif
        !          1089:
        !          1090:        /* Pull the regs of the stack */
        !          1091:        ldmfd   sp!, {r4-r7, pc}
        !          1092:
        !          1093: ENTRY(proc_trampoline)
        !          1094:        mov     r0, #(IPL_NONE)
        !          1095:        bl      _C_LABEL(_spllower)
        !          1096:
        !          1097: #ifdef MULTIPROCESSOR
        !          1098:        bl      _C_LABEL(proc_trampoline_mp)
        !          1099: #endif
        !          1100:        mov     r0, r5
        !          1101:        mov     r1, sp
        !          1102:        mov     lr, pc
        !          1103:        mov     pc, r4
        !          1104:
        !          1105:        /* Kill irq's */
        !          1106:         mrs     r0, cpsr
        !          1107:         orr     r0, r0, #(I32_bit)
        !          1108:         msr     cpsr_c, r0
        !          1109:
        !          1110:        PULLFRAME
        !          1111:
        !          1112:        movs    pc, lr                  /* Exit */
        !          1113:
        !          1114: #ifndef __XSCALE__
        !          1115:        .type .Lcpu_switch_ffs_table, _ASM_TYPE_OBJECT;
        !          1116: .Lcpu_switch_ffs_table:
        !          1117: /* same as ffs table but all nums are -1 from that */
        !          1118: /*               0   1   2   3   4   5   6   7           */
        !          1119:        .byte    0,  0,  1, 12,  2,  6,  0, 13  /*  0- 7 */
        !          1120:        .byte    3,  0,  7,  0,  0,  0,  0, 14  /*  8-15 */
        !          1121:        .byte   10,  4,  0,  0,  8,  0,  0, 25  /* 16-23 */
        !          1122:        .byte    0,  0,  0,  0,  0, 21, 27, 15  /* 24-31 */
        !          1123:        .byte   31, 11,  5,  0,  0,  0,  0,  0  /* 32-39 */
        !          1124:        .byte    9,  0,  0, 24,  0,  0, 20, 26  /* 40-47 */
        !          1125:        .byte   30,  0,  0,  0,  0, 23,  0, 19  /* 48-55 */
        !          1126:        .byte   29,  0, 22, 18, 28, 17, 16,  0  /* 56-63 */
        !          1127: #endif /* !__XSCALE_ */

CVSweb