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

Annotation of sys/arch/arm/arm/exception.S, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: exception.S,v 1.2 2004/02/01 06:10:33 drahn Exp $     */
                      2: /*     $NetBSD: exception.S,v 1.13 2003/10/31 16:30:15 scw Exp $       */
                      3:
                      4: /*
                      5:  * Copyright (c) 1994-1997 Mark Brinicombe.
                      6:  * Copyright (c) 1994 Brini.
                      7:  * All rights reserved.
                      8:  *
                      9:  * This code is derived from software written for Brini by Mark Brinicombe
                     10:  *
                     11:  * Redistribution and use in source and binary forms, with or without
                     12:  * modification, are permitted provided that the following conditions
                     13:  * are met:
                     14:  * 1. Redistributions of source code must retain the above copyright
                     15:  *    notice, this list of conditions and the following disclaimer.
                     16:  * 2. Redistributions in binary form must reproduce the above copyright
                     17:  *    notice, this list of conditions and the following disclaimer in the
                     18:  *    documentation and/or other materials provided with the distribution.
                     19:  * 3. All advertising materials mentioning features or use of this software
                     20:  *    must display the following acknowledgement:
                     21:  *     This product includes software developed by Brini.
                     22:  * 4. The name of the company nor the name of the author may be used to
                     23:  *    endorse or promote products derived from this software without specific
                     24:  *    prior written permission.
                     25:  *
                     26:  * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
                     27:  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
                     28:  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
                     29:  * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
                     30:  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
                     31:  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
                     32:  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     33:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     34:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     35:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     36:  * SUCH DAMAGE.
                     37:  *
                     38:  * RiscBSD kernel project
                     39:  *
                     40:  * exception.S
                     41:  *
                     42:  * Low level handlers for exception vectors
                     43:  *
                     44:  * Created      : 24/09/94
                     45:  *
                     46:  * Based on kate/display/abort.s
                     47:  */
                     48:
                     49: #include <machine/asm.h>
                     50: #include <machine/cpu.h>
                     51: #include <machine/frame.h>
                     52: #include "assym.h"
                     53:
                     54:        .text
                     55:        .align  0
                     56:
                     57: AST_ALIGNMENT_FAULT_LOCALS
                     58:
                     59: /*
                     60:  * reset_entry:
                     61:  *
                     62:  *     Handler for Reset exception.
                     63:  */
                     64: ASENTRY_NP(reset_entry)
                     65:        adr     r0, Lreset_panicmsg
                     66:        mov     r1, lr
                     67:        bl      _C_LABEL(panic)
                     68:        /* NOTREACHED */
                     69: Lreset_panicmsg:
                     70:        .asciz  "Reset vector called, LR = 0x%08x"
                     71:        .balign 4
                     72:
                     73: /*
                     74:  * swi_entry
                     75:  *
                     76:  *     Handler for the Software Interrupt exception.
                     77:  */
                     78: ASENTRY_NP(swi_entry)
                     79:        PUSHFRAME
                     80:        ENABLE_ALIGNMENT_FAULTS
                     81:
                     82:        mov     r0, sp                  /* Pass the frame to any function */
                     83:        bl      _C_LABEL(swi_handler)   /* It's a SWI ! */
                     84:
                     85:        DO_AST_AND_RESTORE_ALIGNMENT_FAULTS
                     86:        PULLFRAME
                     87:        movs    pc, lr                  /* Exit */
                     88:
                     89: /*
                     90:  * prefetch_abort_entry:
                     91:  *
                     92:  *     Handler for the Prefetch Abort exception.
                     93:  */
                     94: ASENTRY_NP(prefetch_abort_entry)
                     95: #ifdef __XSCALE__
                     96:        nop                             /* Make absolutely sure any pending */
                     97:        nop                             /* imprecise aborts have occurred. */
                     98: #endif
                     99:         sub     lr, lr, #0x00000004     /* Adjust the lr */
                    100:
                    101:        PUSHFRAMEINSVC
                    102:        ENABLE_ALIGNMENT_FAULTS
                    103:
                    104:        ldr     r1, Lprefetch_abort_handler_address
                    105:        adr     lr, exception_exit
                    106:        mov     r0, sp                  /* pass the stack pointer as r0 */
                    107:        ldr     pc, [r1]
                    108:
                    109: Lprefetch_abort_handler_address:
                    110:        .word   _C_LABEL(prefetch_abort_handler_address)
                    111:
                    112:        .data
                    113:        .global _C_LABEL(prefetch_abort_handler_address)
                    114:
                    115: _C_LABEL(prefetch_abort_handler_address):
                    116:        .word   abortprefetch
                    117:
                    118:        .text
                    119: abortprefetch:
                    120:         adr     r0, abortprefetchmsg
                    121:        b       _C_LABEL(panic)
                    122:
                    123: abortprefetchmsg:
                    124:         .asciz  "abortprefetch"
                    125:         .align  0
                    126:
                    127: /*
                    128:  * data_abort_entry:
                    129:  *
                    130:  *     Handler for the Data Abort exception.
                    131:  */
                    132: ASENTRY_NP(data_abort_entry)
                    133: #ifdef __XSCALE__
                    134:        nop                             /* Make absolutely sure any pending */
                    135:        nop                             /* imprecise aborts have occurred. */
                    136: #endif
                    137:         sub     lr, lr, #0x00000008     /* Adjust the lr */
                    138:
                    139:        PUSHFRAMEINSVC                  /* Push trap frame and switch */
                    140:                                        /* to SVC32 mode */
                    141:        ENABLE_ALIGNMENT_FAULTS
                    142:
                    143:        ldr     r1, Ldata_abort_handler_address
                    144:        adr     lr, exception_exit
                    145:        mov     r0, sp                  /* pass the stack pointer as r0 */
                    146:        ldr     pc, [r1]
                    147:
                    148: Ldata_abort_handler_address:
                    149:        .word   _C_LABEL(data_abort_handler_address)
                    150:
                    151:        .data
                    152:        .global _C_LABEL(data_abort_handler_address)
                    153: _C_LABEL(data_abort_handler_address):
                    154:        .word   abortdata
                    155:
                    156:        .text
                    157: abortdata:
                    158:         adr     r0, abortdatamsg
                    159:        b       _C_LABEL(panic)
                    160:
                    161: abortdatamsg:
                    162:         .asciz  "abortdata"
                    163:         .align  0
                    164:
                    165: /*
                    166:  * address_exception_entry:
                    167:  *
                    168:  *     Handler for the Address Exception exception.
                    169:  *
                    170:  *     NOTE: This exception isn't really used on arm32.  We
                    171:  *     print a warning message to the console and then treat
                    172:  *     it like a Data Abort.
                    173:  */
                    174: ASENTRY_NP(address_exception_entry)
                    175:        mrs     r1, cpsr_all
                    176:        mrs     r2, spsr_all
                    177:        mov     r3, lr
                    178:        adr     r0, Laddress_exception_msg
                    179:        bl      _C_LABEL(printf)        /* XXX CLOBBERS LR!! */
                    180:        b       data_abort_entry
                    181: Laddress_exception_msg:
                    182:        .asciz  "Address Exception CPSR=0x%08x SPSR=0x%08x LR=0x%08x\n"
                    183:        .balign 4
                    184:
                    185: /*
                    186:  * General exception exit handler
                    187:  * (Placed here to be within range of all the references to it)
                    188:  *
                    189:  * It exits straight away if not returning to USR mode.
                    190:  * This loops around delivering any pending ASTs.
                    191:  * Interrupts are disabled at suitable points to avoid ASTs
                    192:  * being posted between testing and exit to user mode.
                    193:  *
                    194:  * This function uses PULLFRAMEFROMSVCANDEXIT and
                    195:  * DO_AST_AND_RESTORE_ALIGNMENT_FAULTS thus should
                    196:  * only be called if the exception handler used PUSHFRAMEINSVC
                    197:  * followed by ENABLE_ALIGNMENT_FAULTS.
                    198:  */
                    199:
                    200: exception_exit:
                    201:        DO_AST_AND_RESTORE_ALIGNMENT_FAULTS
                    202:        PULLFRAMEFROMSVCANDEXIT
                    203:
                    204: /*
                    205:  * undefined_entry:
                    206:  *
                    207:  *     Handler for the Undefined Instruction exception.
                    208:  *
                    209:  *     We indirect the undefined vector via the handler address
                    210:  *     in the data area.  Entry to the undefined handler must
                    211:  *     look like direct entry from the vector.
                    212:  */
                    213: ASENTRY_NP(undefined_entry)
                    214: #ifdef IPKDB
                    215: /*
                    216:  * IPKDB must be hooked in at the earliest possible entry point.
                    217:  *
                    218:  */
                    219: /*
                    220:  * Make room for all registers saving real r0-r7 and r15.
                    221:  * The remaining registers are updated later.
                    222:  */
                    223:        stmfd   sp!, {r0,r1}            /* psr & spsr */
                    224:        stmfd   sp!, {lr}               /* pc */
                    225:        stmfd   sp!, {r0-r14}           /* r0-r7, r8-r14 */
                    226: /*
                    227:  * Get previous psr.
                    228:  */
                    229:        mrs     r7, cpsr_all
                    230:        mrs     r0, spsr_all
                    231:        str     r0, [sp, #(16*4)]
                    232: /*
                    233:  * Test for user mode.
                    234:  */
                    235:        tst     r0, #0xf
                    236:        bne     .Lprenotuser_push
                    237:        add     r1, sp, #(8*4)
                    238:        stmia   r1,{r8-r14}^            /* store user mode r8-r14*/
                    239:        b       .Lgoipkdb
                    240: /*
                    241:  * Switch to previous mode to get r8-r13.
                    242:  */
                    243: .Lprenotuser_push:
                    244:        orr     r0, r0, #(I32_bit) /* disable interrupts */
                    245:        msr     cpsr_all, r0
                    246:        mov     r1, r8
                    247:        mov     r2, r9
                    248:        mov     r3, r10
                    249:        mov     r4, r11
                    250:        mov     r5, r12
                    251:        mov     r6, r13
                    252:        msr     cpsr_all, r7            /* back to undefined mode */
                    253:        add     r8, sp, #(8*4)
                    254:        stmia   r8, {r1-r6}             /* r8-r13 */
                    255: /*
                    256:  * Now back to previous mode to get r14 and spsr.
                    257:  */
                    258:        msr     cpsr_all, r0
                    259:        mov     r1, r14
                    260:        mrs     r2, spsr
                    261:        msr     cpsr_all, r7            /* back to undefined mode */
                    262:        str     r1, [sp, #(14*4)]       /* r14 */
                    263:        str     r2, [sp, #(17*4)]       /* spsr */
                    264: /*
                    265:  * Now to IPKDB.
                    266:  */
                    267: .Lgoipkdb:
                    268:        mov     r0, sp
                    269:        bl      _C_LABEL(ipkdb_trap_glue)
                    270:        ldr     r1, .Lipkdb_trap_return
                    271:        str     r0,[r1]
                    272:
                    273: /*
                    274:  * Have to load all registers from the stack.
                    275:  *
                    276:  * Start with spsr and pc.
                    277:  */
                    278:        ldr     r0, [sp, #(16*4)]       /* spsr */
                    279:        ldr     r1, [sp, #(15*4)]       /* r15 */
                    280:        msr     spsr_all, r0
                    281:        mov     r14, r1
                    282: /*
                    283:  * Test for user mode.
                    284:  */
                    285:        tst     r0, #0xf
                    286:        bne     .Lprenotuser_pull
                    287:        add     r1, sp, #(8*4)
                    288:        ldmia   r1, {r8-r14}^           /* load user mode r8-r14 */
                    289:        b       .Lpull_r0r7
                    290: .Lprenotuser_pull:
                    291: /*
                    292:  * Now previous mode spsr and r14.
                    293:  */
                    294:        ldr     r1, [sp, #(17*4)]               /* spsr */
                    295:        ldr     r2, [sp, #(14*4)]               /* r14 */
                    296:        orr     r0, r0, #(I32_bit)
                    297:        msr     cpsr_all, r0                    /* switch to previous mode */
                    298:        msr     spsr_all, r1
                    299:        mov     r14, r2
                    300:        msr     cpsr_all, r7                    /* back to undefined mode */
                    301: /*
                    302:  * Now r8-r13.
                    303:  */
                    304:        add     r8, sp, #(8*4)
                    305:        ldmia   r8, {r1-r6}             /* r8-r13 */
                    306:        msr     cpsr_all, r0
                    307:        mov     r8, r1
                    308:        mov     r9, r2
                    309:        mov     r10, r3
                    310:        mov     r11, r4
                    311:        mov     r12, r5
                    312:        mov     r13, r6
                    313:        msr     cpsr_all, r7
                    314: .Lpull_r0r7:
                    315: /*
                    316:  * Now the rest of the registers.
                    317:  */
                    318:        ldr     r1,Lipkdb_trap_return
                    319:        ldr     r0,[r1]
                    320:        tst     r0,r0
                    321:        ldmfd   sp!, {r0-r7}            /* r0-r7 */
                    322:        add     sp, sp, #(10*4)         /* adjust sp */
                    323:
                    324: /*
                    325:  * Did IPKDB handle it?
                    326:  */
                    327:        movnes  pc, lr                  /* return */
                    328:
                    329: #endif
                    330:        stmfd   sp!, {r0, r1}
                    331:        ldr     r0, Lundefined_handler_indirection
                    332:        ldr     r1, [sp], #0x0004
                    333:        str     r1, [r0, #0x0000]
                    334:        ldr     r1, [sp], #0x0004
                    335:        str     r1, [r0, #0x0004]
                    336:        ldmia   r0, {r0, r1, pc}
                    337:
                    338: #ifdef IPKDB
                    339: Lipkdb_trap_return:
                    340:        .word   Lipkdb_trap_return_data
                    341: #endif
                    342:
                    343: Lundefined_handler_indirection:
                    344:        .word   Lundefined_handler_indirection_data
                    345:
                    346: /*
                    347:  * assembly bounce code for calling the kernel
                    348:  * undefined instruction handler. This uses
                    349:  * a standard trap frame and is called in SVC mode.
                    350:  */
                    351:
                    352: ENTRY_NP(undefinedinstruction_bounce)
                    353:        PUSHFRAMEINSVC
                    354:        ENABLE_ALIGNMENT_FAULTS
                    355:
                    356:        mov     r0, sp
                    357:        adr     lr, exception_exit
                    358:        b       _C_LABEL(undefinedinstruction)
                    359:
                    360:        .data
                    361:        .align  0
                    362:
                    363: #ifdef IPKDB
                    364: Lipkdb_trap_return_data:
                    365:        .word   0
                    366: #endif
                    367:
                    368: /*
                    369:  * Indirection data
                    370:  * 2 words use for preserving r0 and r1
                    371:  * 3rd word contains the undefined handler address.
                    372:  */
                    373:
                    374: Lundefined_handler_indirection_data:
                    375:        .word   0
                    376:        .word   0
                    377:
                    378:        .global _C_LABEL(undefined_handler_address)
                    379: _C_LABEL(undefined_handler_address):
                    380:        .word   _C_LABEL(undefinedinstruction_bounce)

CVSweb