ofw_irq.S revision 1.11
11.11Smatt/* $NetBSD: ofw_irq.S,v 1.11 2008/04/27 18:58:45 matt Exp $ */ 21.1Sthorpej 31.1Sthorpej/* 41.1Sthorpej * Copyright (c) 1994-1998 Mark Brinicombe. 51.1Sthorpej * Copyright (c) 1994 Brini. 61.1Sthorpej * All rights reserved. 71.1Sthorpej * 81.1Sthorpej * This code is derived from software written for Brini by Mark Brinicombe 91.1Sthorpej * 101.1Sthorpej * Redistribution and use in source and binary forms, with or without 111.1Sthorpej * modification, are permitted provided that the following conditions 121.1Sthorpej * are met: 131.1Sthorpej * 1. Redistributions of source code must retain the above copyright 141.1Sthorpej * notice, this list of conditions and the following disclaimer. 151.1Sthorpej * 2. Redistributions in binary form must reproduce the above copyright 161.1Sthorpej * notice, this list of conditions and the following disclaimer in the 171.1Sthorpej * documentation and/or other materials provided with the distribution. 181.1Sthorpej * 3. All advertising materials mentioning features or use of this software 191.1Sthorpej * must display the following acknowledgement: 201.1Sthorpej * This product includes software developed by Mark Brinicombe 211.1Sthorpej * for the NetBSD Project. 221.1Sthorpej * 4. The name of the company nor the name of the author may be used to 231.1Sthorpej * endorse or promote products derived from this software without specific 241.1Sthorpej * prior written permission. 251.1Sthorpej * 261.1Sthorpej * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 271.1Sthorpej * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 281.1Sthorpej * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 291.1Sthorpej * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 301.1Sthorpej * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 311.1Sthorpej * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 321.1Sthorpej * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 331.1Sthorpej * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 341.1Sthorpej * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 351.1Sthorpej * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 361.1Sthorpej * 371.1Sthorpej * Low level irq and fiq handlers 381.1Sthorpej * 391.1Sthorpej * Created : 27/09/94 401.1Sthorpej */ 411.1Sthorpej 421.1Sthorpej#include "assym.h" 431.1Sthorpej#include <machine/asm.h> 441.1Sthorpej#include <machine/cpu.h> 451.1Sthorpej#include <machine/frame.h> 461.1Sthorpej#include <machine/irqhandler.h> 471.1Sthorpej 481.1Sthorpej .text 491.1Sthorpej .align 0 501.1Sthorpej 511.1Sthorpej/* 521.1Sthorpej * 531.1Sthorpej * irq_entry 541.1Sthorpej * 551.1Sthorpej * Main entry point for the IRQ vector 561.1Sthorpej * 571.1Sthorpej * This function is called only on timer ticks, passed on to the 581.1Sthorpej * kernel from the OFW tick handler. 591.1Sthorpej * 601.1Sthorpej * For now, I am trying to re-use as much of the code from the 611.1Sthorpej * IOMD interrupt-handler as possible. In time, I will strip this 621.1Sthorpej * down to something OFW-specific. 631.1Sthorpej * 641.1Sthorpej * Here's the original, IOMD-specific description: 651.1Sthorpej * This function reads the irq request bits in the IOMD registers 661.1Sthorpej * IRQRQA, IRQRQB and DMARQ 671.1Sthorpej * It then calls an installed handler for each bit that is set. 681.1Sthorpej * The function stray_irqhandler is called if a handler is not defined 691.1Sthorpej * for a particular interrupt. 701.1Sthorpej * If a interrupt handler is found then it is called with r0 containing 711.1Sthorpej * the argument defined in the handler structure. If the field ih_arg 721.1Sthorpej * is zero then a pointer to the IRQ frame on the stack is passed instead. 731.1Sthorpej */ 741.1Sthorpej 751.1SthorpejLdisabled_mask: 761.1Sthorpej .word _C_LABEL(disabled_mask) 771.1Sthorpej 781.1SthorpejLspl_masks: 791.1Sthorpej .word _C_LABEL(spl_masks) 801.1Sthorpej 811.1SthorpejLofw_ticktmp: 821.1Sthorpej .word _C_LABEL(ofw_ticktmp) 831.1Sthorpej 841.1SthorpejLirq_entry: 851.1Sthorpej .word irq_entry 861.1Sthorpej 871.1SthorpejLofwirqstk: /* hack */ 881.1Sthorpej .word ofwirqstk + 4096 891.1Sthorpej 901.7SthorpejLOCK_CAS_CHECK_LOCALS 911.7Sthorpej 921.3SscwAST_ALIGNMENT_FAULT_LOCALS 931.3Sscw 941.1Sthorpej/* 951.1Sthorpej * Regsister usage 961.1Sthorpej * 971.11Smatt * r4 - Address of cpu_info 981.1Sthorpej * r6 - Address of current handler 991.1Sthorpej * r7 - Pointer to handler pointer list 1001.1Sthorpej * r8 - Current IRQ requests. 1011.1Sthorpej * r9 - Used to count through possible IRQ bits. 1021.1Sthorpej * r10 - Base address of IOMD 1031.1Sthorpej */ 1041.1Sthorpej 1051.1SthorpejASENTRY_NP(irq_entry) 1061.1Sthorpej /* 1071.1Sthorpej * We come here following an OFW-handled timer tick. 1081.1Sthorpej * 1091.1Sthorpej * We are in the SVC frame, and interrupts are disabled. 1101.1Sthorpej * The state of the interrupted context is partially in 1111.1Sthorpej * the registers and partially in the global storage area 1121.1Sthorpej * labeled ofw_ticktmp. ofw_ticktmp is filled-in by the 1131.1Sthorpej * tick callback that is invoked by OFW on the way out of 1141.1Sthorpej * its interrupt handler. ofw_ticktmp contains the following: 1151.1Sthorpej * 1161.1Sthorpej * pc // interrupted instruction 1171.1Sthorpej * lr_usr 1181.1Sthorpej * sp_usr 1191.1Sthorpej * r1 // makes r1 available for scratch 1201.1Sthorpej * r0 // makes r0 available for scratch 1211.1Sthorpej * spsr_svc // cpsr of interrupted context 1221.1Sthorpej * 1231.1Sthorpej * The prologue of this routine must re-construct the 1241.1Sthorpej * machine state that existed at the time OFW's interrupt- 1251.1Sthorpej * handler fielded the interrupt. That allows us to use 1261.1Sthorpej * the rest of the code in this routine, and have it all 1271.1Sthorpej * "just work." 1281.1Sthorpej */ 1291.1Sthorpej 1301.1Sthorpej /* 1311.1Sthorpej * Switch to IRQ mode. 1321.1Sthorpej * First check the spsr in ofw_ticktmp to see what the FIQ bit should be. 1331.1Sthorpej * 1341.1Sthorpej * I need 2 scratch registers to do this. 1351.1Sthorpej * Fortunately, r0 and r1 are already saved in ofw_ticktmp. 1361.1Sthorpej * How convenient. 1371.1Sthorpej */ 1381.1Sthorpej ldr r0, Lofw_ticktmp 1391.1Sthorpej ldr r0, [r0] 1401.1Sthorpej and r0, r0, #F32_bit 1411.1Sthorpej mov r1, #(I32_bit | PSR_IRQ32_MODE) 1421.1Sthorpej orr r1, r1, r0 1431.1Sthorpej msr cpsr_all, r1 1441.1Sthorpej 1451.1Sthorpej /* Now we're in IRQ mode. */ 1461.1Sthorpej /* Restore contents of ofw_ticktmp. */ 1471.2Sbjh21 adr r0, Lofwirqstk /* Bummer! Mitch hasn't left me a stack. */ 1481.2Sbjh21 ldr sp, [r0] /* I'll use my own for now... */ 1491.1Sthorpej ldr r0, Lofw_ticktmp /* r0 now points to ofw_ticktmp[0] */ 1501.1Sthorpej ldr r1, [r0], #(4*3) /* skip over saved {r0, r1} */ 1511.1Sthorpej msr spsr_all, r1 /* restore spsr */ 1521.1Sthorpej ldmia r0, {sp, lr}^ /* restore user sp and lr */ 1531.1Sthorpej add r0, r0, #(4*2) /* previous instruction can't writeback */ 1541.1Sthorpej /* this one can't use banked registers */ 1551.1Sthorpej ldr lr, [r0], #(-4*4) /* restore pc; point r0 at ofw_ticktmp[1] */ 1561.1Sthorpej add lr, lr, #4 /* pc += 4; will be decremented below */ 1571.1Sthorpej ldmia r0, {r0, r1} /* restore r0 and r1 */ 1581.1Sthorpej 1591.1Sthorpej /* OK, the machine state should be identical now to that when */ 1601.1Sthorpej /* OFW fielded the interrupt. So just fall through... */ 1611.1Sthorpej 1621.1Sthorpej sub lr, lr, #0x00000004 /* Adjust the lr */ 1631.1Sthorpej 1641.1Sthorpej PUSHFRAMEINSVC /* Push an interrupt frame */ 1651.1Sthorpej 1661.1Sthorpej /* 1671.11Smatt * Can't field this interrupt now if priority is IPL_CLOCK 1681.1Sthorpej * or higher. For now, we'll just ignore the interrupt. 1691.1Sthorpej * Soon, we will have to schedule it for later action. 1701.1Sthorpej */ 1711.1Sthorpej ldr r0, Lcurrent_spl_level 1721.11Smatt ldr r0, [r4, #CI_CPL] 1731.11Smatt cmp r0, #IPL_CLOCK 1741.1Sthorpej blt ofwtakeint 1751.1Sthorpej 1761.1Sthorpej PULLFRAMEFROMSVCANDEXIT 1771.1Sthorpej movs pc, lr /* Exit */ 1781.1Sthorpej 1791.1Sthorpej /* 1801.1Sthorpej * Stuff a bit-mask into r8 indicating which interrupts 1811.1Sthorpej * are pending. In our case, that is just the timer0 1821.1Sthorpej * interrupt: (1 << TIMER0). The existing code will take 1831.1Sthorpej * care of invoking that handler and the softint/ast stuff 1841.1Sthorpej * which follows it. 1851.1Sthorpej */ 1861.1Sthorpejofwtakeint: 1871.5Smanu#ifdef EXEC_AOUT 1881.3Sscw ldr r0, [sp] /* Fetch SPSR */ 1891.3Sscw#endif 1901.3Sscw ENABLE_ALIGNMENT_FAULTS 1911.3Sscw 1921.1Sthorpej mov r8, #0x00000001 /* timer interrupt pending! */ 1931.1Sthorpej mov r8, r8, lsl #IRQ_TIMER0 1941.1Sthorpej 1951.1Sthorpej /* 1961.1Sthorpej * Note that we have entered the IRQ handler. 1971.1Sthorpej * We are in SVC mode so we cannot use the processor mode 1981.1Sthorpej * to determine if we are in an IRQ. Instead we will count the 1991.1Sthorpej * each time the interrupt handler is nested. 2001.1Sthorpej */ 2011.1Sthorpej 2021.11Smatt ldr r1, [r4, #CI_INTR_DEPTH] 2031.1Sthorpej add r1, r1, #1 2041.11Smatt str r1, [r4, #CI_INTR_DEPTH] 2051.1Sthorpej 2061.1Sthorpej /* Block the current requested interrupts */ 2071.1Sthorpej ldr r1, Ldisabled_mask 2081.1Sthorpej ldr r0, [r1] 2091.1Sthorpej stmfd sp!, {r0} 2101.1Sthorpej orr r0, r0, r8 2111.1Sthorpej 2121.1Sthorpej /* 2131.1Sthorpej * Need to block all interrupts at the IPL or lower for 2141.1Sthorpej * all asserted interrupts. 2151.1Sthorpej * This basically emulates hardware interrupt priority levels. 2161.1Sthorpej * Means we need to go through the interrupt mask and for 2171.1Sthorpej * every asserted interrupt we need to mask out all other 2181.1Sthorpej * interrupts at the same or lower IPL. 2191.1Sthorpej * If only we could wait until the main loop but we need to sort 2201.1Sthorpej * this out first so interrupts can be re-enabled. 2211.1Sthorpej * 2221.1Sthorpej * This would benefit from a special ffs type routine 2231.1Sthorpej */ 2241.1Sthorpej 2251.11Smatt mov r9, #(NIPL - 1) 2261.1Sthorpej ldr r7, Lspl_masks 2271.1Sthorpej 2281.1SthorpejLfind_highest_ipl: 2291.1Sthorpej ldr r2, [r7, r9, lsl #2] 2301.1Sthorpej tst r8, r2 2311.1Sthorpej subeq r9, r9, #1 2321.1Sthorpej beq Lfind_highest_ipl 2331.1Sthorpej 2341.1Sthorpej /* r9 = SPL level of highest priority interrupt */ 2351.1Sthorpej add r9, r9, #1 2361.1Sthorpej ldr r2, [r7, r9, lsl #2] 2371.1Sthorpej mvn r2, r2 2381.1Sthorpej orr r0, r0, r2 2391.1Sthorpej 2401.1Sthorpej str r0, [r1] 2411.1Sthorpej 2421.1Sthorpej ldr r0, Lcurrent_spl_level 2431.11Smatt ldr r1, [r4, #CI_CPL] 2441.11Smatt str r9, [r4, #CI_CPL] 2451.1Sthorpej stmfd sp!, {r1} 2461.1Sthorpej 2471.1Sthorpej /* Update the irq masks */ 2481.1Sthorpej bl _C_LABEL(irq_setmasks) 2491.1Sthorpej 2501.6Smatt mrs r0, cpsr_all /* Enable IRQ's */ 2511.1Sthorpej bic r0, r0, #I32_bit 2521.1Sthorpej msr cpsr_all, r0 2531.1Sthorpej 2541.2Sbjh21 ldr r7, Lirqhandlers 2551.6Smatt mov r9, #0x00000001 2561.1Sthorpej 2571.1Sthorpejirqloop: 2581.1Sthorpej /* This would benefit from a special ffs type routine */ 2591.1Sthorpej tst r8, r9 /* Is a bit set ? */ 2601.1Sthorpej beq nextirq /* No ? try next bit */ 2611.1Sthorpej 2621.1Sthorpej ldr r6, [r7] /* Get address of first handler structure */ 2631.1Sthorpej 2641.1Sthorpej teq r6, #0x00000000 /* Do we have a handler */ 2651.1Sthorpej moveq r0, r8 /* IRQ requests as arg 0 */ 2661.1Sthorpej beq _C_LABEL(stray_irqhandler) /* call special handler */ 2671.1Sthorpej 2681.6Smatt ldr r0, Lcnt 2691.1Sthorpej ldr r1, [r0, #(V_INTR)] 2701.1Sthorpej add r1, r1, #0x00000001 2711.1Sthorpej str r1, [r0, #(V_INTR)] 2721.1Sthorpej 2731.1Sthorpejirqchainloop: 2741.1Sthorpej ldr r0, [r6, #(IH_ARG)] /* Get argument pointer */ 2751.1Sthorpej teq r0, #0x00000000 /* If arg is zero pass stack frame */ 2761.1Sthorpej addeq r0, sp, #8 /* ... stack frame */ 2771.2Sbjh21 mov lr, pc /* return address */ 2781.1Sthorpej ldr pc, [r6, #(IH_FUNC)] /* Call handler */ 2791.1Sthorpej 2801.1Sthorpej teq r0, #0x00000001 /* Was the irq serviced ? */ 2811.1Sthorpej beq irqdone 2821.1Sthorpej 2831.1Sthorpej ldr r6, [r6, #(IH_NEXT)] 2841.1Sthorpej teq r6, #0x00000000 2851.1Sthorpej bne irqchainloop 2861.6Smatt b nextirq 2871.1Sthorpej 2881.1Sthorpejirqdone: 2891.6Smatt add r3, r6, #IH_EV_COUNT /* get address of ih's ev_count */ 2901.6Smatt ldmia r3, {r1-r2} /* load ev_count */ 2911.6Smatt adds r1, r1, #0x00000001 /* 64bit incr (lo) */ 2921.6Smatt adc r2, r2, #0x00000000 /* 64bit incr (hi) */ 2931.6Smatt stmia r3, {r1-r2} /* store ev_count */ 2941.6Smatt 2951.1Sthorpejnextirq: 2961.1Sthorpej add r7, r7, #0x00000004 /* update pointer to handlers */ 2971.1Sthorpej mov r9, r9, lsl #1 /* move on to next bit */ 2981.1Sthorpej teq r9, #(1 << 24) /* done the last bit ? */ 2991.1Sthorpej bne irqloop /* no - loop back. */ 3001.1Sthorpej 3011.1Sthorpej ldmfd sp!, {r2} 3021.11Smatt str r2, [r4, #CI_CPL] 3031.1Sthorpej 3041.1Sthorpej /* Restore previous disabled mask */ 3051.1Sthorpej ldmfd sp!, {r2} 3061.1Sthorpej ldr r1, Ldisabled_mask 3071.1Sthorpej str r2, [r1] 3081.1Sthorpej bl _C_LABEL(irq_setmasks) 3091.1Sthorpej 3101.1Sthorpej bl _C_LABEL(dosoftints) /* Handle the soft interrupts */ 3111.1Sthorpej 3121.1Sthorpej /* Kill IRQ's in preparation for exit */ 3131.6Smatt mrs r0, cpsr_all 3141.6Smatt orr r0, r0, #(I32_bit) 3151.6Smatt msr cpsr_all, r0 3161.1Sthorpej 3171.1Sthorpej /* Decrement the nest count */ 3181.11Smatt ldr r1, [r4, #CI_INTR_DEPTH] 3191.1Sthorpej sub r1, r1, #1 3201.11Smatt str r1, [r4, #CI_INTR_DEPTH] 3211.1Sthorpej 3221.7Sthorpej LOCK_CAS_CHECK 3231.7Sthorpej 3241.3Sscw DO_AST_AND_RESTORE_ALIGNMENT_FAULTS 3251.1Sthorpej PULLFRAMEFROMSVCANDEXIT 3261.1Sthorpej movs pc, lr /* Exit */ 3271.1Sthorpej 3281.1SthorpejLcurrent_mask: 3291.1Sthorpej .word _C_LABEL(current_mask) /* irq's that are usable */ 3301.1Sthorpej 3311.1Sthorpej 3321.1SthorpejENTRY(irq_setmasks) 3331.1Sthorpej /* Do nothing */ 3341.1Sthorpej mov pc, lr 3351.1Sthorpej 3361.1Sthorpej 3371.1SthorpejLcnt: 3381.1Sthorpej .word _C_LABEL(uvmexp) 3391.1Sthorpej 3401.1SthorpejLirqhandlers: 3411.1Sthorpej .word _C_LABEL(irqhandlers) /* Pointer to array of irqhandlers */ 3421.1Sthorpej 3431.1Sthorpej .text 3441.1Sthorpej .global _C_LABEL(dotickgrovelling) 3451.1Sthorpej 3461.1Sthorpej/* 3471.1Sthorpej * Do magic to cause OFW to call our irq_entry 3481.1Sthorpej * routine when it returns from its tick-handling. 3491.1Sthorpej * 3501.1Sthorpej * This consists of two sub-tasks: 3511.1Sthorpej * - save some machine state in ofw_ticktmp 3521.1Sthorpej * - punch some new machine state into the 3531.1Sthorpej * OFW-supplied frame 3541.1Sthorpej * 3551.1Sthorpej * We are running in the IRQ frame, with 3561.1Sthorpej * interrupts disabled. 3571.1Sthorpej * 3581.1Sthorpej * r0 - base of saved OFW interrupt frame, which 3591.1Sthorpej * has the following format: 3601.1Sthorpej * 3611.1Sthorpej * pc // interrupted instruction 3621.1Sthorpej * lr // lr of interrupted context 3631.1Sthorpej * sp // sp of interrupted context 3641.1Sthorpej * r12 3651.1Sthorpej * ... // non-banked register values 3661.1Sthorpej * ... // of interrupted context 3671.1Sthorpej * r0 3681.1Sthorpej * spsr // psr of interrupted context 3691.1Sthorpej * 3701.1Sthorpej */ 3711.1Sthorpej 3721.1Sthorpej_C_LABEL(dotickgrovelling): 3731.1Sthorpej /*assert((cpsr & PSR_MODE) == PSR_IRQ32_MODE);*/ 3741.1Sthorpej 3751.1Sthorpej stmfd sp!, {r1-r5} /* scratch registers r1-r5 */ 3761.1Sthorpej 3771.1Sthorpej /* 3781.1Sthorpej * Sub-task 1: 3791.1Sthorpej * 3801.1Sthorpej * Our irq_entry routine needs to re-construct 3811.1Sthorpej * the state of the machine at the time OFW 3821.1Sthorpej * fielded the interrupt, so that we can use 3831.1Sthorpej * the rest of the standard interrupt-handling 3841.1Sthorpej * code. Specifically, irq_entry needs to get 3851.1Sthorpej * at the following machine state: 3861.1Sthorpej * 3871.1Sthorpej * pc // interrupted instruction 3881.1Sthorpej * lr_usr 3891.1Sthorpej * sp_usr 3901.1Sthorpej * r0-r12 // the non-banked registers 3911.1Sthorpej * // at the time of interruption 3921.1Sthorpej * spsr // cpsr of interrupted context 3931.1Sthorpej * 3941.1Sthorpej * The non-banked registers will be valid at the 3951.1Sthorpej * time irq_entry is called, but the other values 3961.1Sthorpej * will not be. We must save them here, in the 3971.1Sthorpej * ofw_ticktmp storage block. We also save r0 3981.1Sthorpej * and r1 so that we have some free registers 3991.1Sthorpej * when it's time to do the re-construction. 4001.1Sthorpej * 4011.1Sthorpej * Note that interrupts are not enabled before 4021.1Sthorpej * irq_entry is entered, so we don't have to 4031.1Sthorpej * worry about ofw_ticktmp getting clobbered. 4041.1Sthorpej */ 4051.1Sthorpej ldr r1, Lofw_ticktmp /* r1 points to ofw_ticktmp[0] */ 4061.1Sthorpej 4071.1Sthorpej ldr r2, [r0, #0] /* ofwframe[0] is spsr */ 4081.1Sthorpej stmia r1!, {r2} /* put it in ofw_ticktmp[0] */ 4091.1Sthorpej 4101.1Sthorpej ldr r2, [r0, #(4*1)] /* ofwframe[1] is saved r0 */ 4111.1Sthorpej stmia r1!, {r2} /* put it in ofw_ticktmp[1] */ 4121.1Sthorpej 4131.1Sthorpej ldr r2, [r0, #(4*2)] /* ofwframe[2] is saved r1 */ 4141.1Sthorpej stmia r1!, {r2} /* put it in ofw_ticktmp[2] */ 4151.1Sthorpej 4161.1Sthorpej stmia r1, {sp, lr}^ /* put {sp,lr}_usr in ofw_ticktmp[3,4]; */ 4171.1Sthorpej /* the user registers are still valid */ 4181.1Sthorpej /* because we haven't left IRQ mode */ 4191.1Sthorpej add r1, r1, #(4*2) /* previous instruction can't writeback */ 4201.1Sthorpej /* this one can't use banked registers */ 4211.1Sthorpej 4221.1Sthorpej ldr r2, [r0, #(4*16)] /* ofwframe[16] is pc */ 4231.1Sthorpej stmia r1!, {r2} /* put it in ofw_ticktmp[5] */ 4241.1Sthorpej 4251.1Sthorpej 4261.1Sthorpej /* 4271.1Sthorpej * Sub-task 2: 4281.1Sthorpej * 4291.1Sthorpej * Diddle the OFW-supplied frame such that 4301.1Sthorpej * control passes to irq_entry when OFW does 4311.1Sthorpej * its return from interrupt. There are 4 4321.1Sthorpej * fields in that frame that we need to plug: 4331.1Sthorpej * 4341.1Sthorpej * pc // gets irq_entry 4351.1Sthorpej * lr // gets lr_svc 4361.1Sthorpej * sp // gets sp_svc 4371.1Sthorpej * spsr // gets (I32_bit | PSR_SVC32_MODE) 4381.1Sthorpej * 4391.1Sthorpej */ 4401.1Sthorpej mov r1, #(I32_bit | PSR_SVC32_MODE) 4411.1Sthorpej str r1, [r0, #0] /* plug spsr */ 4421.1Sthorpej 4431.1Sthorpej /* Sneak into SVC mode to get sp and lr */ 4441.1Sthorpej mrs r3, cpsr_all 4451.1Sthorpej bic r3, r3, #(PSR_MODE) 4461.1Sthorpej orr r3, r3, #(PSR_SVC32_MODE) 4471.1Sthorpej msr cpsr_all, r3 4481.1Sthorpej mov r4, lr /* snarf lr_svc */ 4491.1Sthorpej mov r5, sp /* snarf sp_svc */ 4501.1Sthorpej bic r3, r3, #(PSR_MODE) 4511.1Sthorpej orr r3, r3, #(PSR_IRQ32_MODE) 4521.1Sthorpej msr cpsr_all, r3 4531.1Sthorpej str r5, [r0, #(4*14)] /* plug sp */ 4541.1Sthorpej str r4, [r0, #(4*15)] /* plug lr */ 4551.1Sthorpej 4561.2Sbjh21 ldr r1, Lirq_entry 4571.1Sthorpej str r1, [r0, #(4*16)] /* plug pc */ 4581.1Sthorpej 4591.1Sthorpej ldmfd sp!, {r1-r5} 4601.1Sthorpej mov pc, lr 4611.1Sthorpej 4621.1Sthorpej 4631.1Sthorpej .bss 4641.1Sthorpej .align 0 4651.1Sthorpej 4661.1Sthorpej_C_LABEL(ofw_ticktmp): 4671.1Sthorpej .space 4 * 6 /* temporary storage for 6 words of machine state */ 4681.1Sthorpej 4691.1Sthorpejofwirqstk: /* hack */ 4701.1Sthorpej .space 4096 471