exception.S revision 262980
1/* $NetBSD: exception.S,v 1.13 2003/10/31 16:30:15 scw Exp $ */ 2 3/*- 4 * Copyright (c) 1994-1997 Mark Brinicombe. 5 * Copyright (c) 1994 Brini. 6 * All rights reserved. 7 * 8 * This code is derived from software written for Brini by Mark Brinicombe 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 by Brini. 21 * 4. The name of the company nor the name of the author may be used to 22 * endorse or promote products derived from this software without specific 23 * prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED 26 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 27 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 28 * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 29 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 30 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 31 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35 * SUCH DAMAGE. 36 * 37 * RiscBSD kernel project 38 * 39 * exception.S 40 * 41 * Low level handlers for exception vectors 42 * 43 * Created : 24/09/94 44 * 45 * Based on kate/display/abort.s 46 * 47 */ 48 49#include "assym.s" 50 51#include <machine/asm.h> 52#include <machine/armreg.h> 53#include <machine/asmacros.h> 54__FBSDID("$FreeBSD: head/sys/arm/arm/exception.S 262980 2014-03-10 19:36:26Z ian $"); 55 56 .text 57 .align 0 58 59AST_LOCALS 60 61/* 62 * reset_entry: 63 * 64 * Handler for Reset exception. 65 */ 66ASENTRY_NP(reset_entry) 67 adr r0, Lreset_panicmsg 68 bl _C_LABEL(panic) 69 /* NOTREACHED */ 70Lreset_panicmsg: 71 .asciz "Reset vector called, LR = 0x%08x" 72 .balign 4 73END(reset_entry) 74 75/* 76 * swi_entry 77 * 78 * Handler for the Software Interrupt exception. 79 */ 80ASENTRY_NP(swi_entry) 81 STOP_UNWINDING /* Don't unwind past here */ 82 83 PUSHFRAME 84 85 mov r0, sp /* Pass the frame to any function */ 86 bl _C_LABEL(swi_handler) /* It's a SWI ! */ 87 88 DO_AST 89 PULLFRAME 90 movs pc, lr /* Exit */ 91END(swi_entry) 92 93/* 94 * prefetch_abort_entry: 95 * 96 * Handler for the Prefetch Abort exception. 97 */ 98ASENTRY_NP(prefetch_abort_entry) 99#ifdef __XSCALE__ 100 nop /* Make absolutely sure any pending */ 101 nop /* imprecise aborts have occurred. */ 102#endif 103 sub lr, lr, #0x00000004 /* Adjust the lr */ 104 105 PUSHFRAMEINSVC 106 ldr r1, Lprefetch_abort_handler_address 107 adr lr, exception_exit 108 mov r0, sp /* pass the stack pointer as r0 */ 109 ldr pc, [r1] 110 111Lprefetch_abort_handler_address: 112 .word _C_LABEL(prefetch_abort_handler_address) 113 114 .data 115 .global _C_LABEL(prefetch_abort_handler_address) 116 117_C_LABEL(prefetch_abort_handler_address): 118 .word prefetch_abort_handler 119 120END(prefetch_abort_entry) 121 122/* 123 * data_abort_entry: 124 * 125 * Handler for the Data Abort exception. 126 */ 127ASENTRY_NP(data_abort_entry) 128#ifdef __XSCALE__ 129 nop /* Make absolutely sure any pending */ 130 nop /* imprecise aborts have occurred. */ 131#endif 132 133 sub lr, lr, #0x00000008 /* Adjust the lr */ 134 PUSHFRAMEINSVC /* Push trap frame and switch */ 135 /* to SVC32 mode */ 136 ldr r1, Ldata_abort_handler_address 137 adr lr, exception_exit 138 mov r0, sp /* pass the stack pointer as r0 */ 139 ldr pc, [r1] 140Ldata_abort_handler_address: 141 .word _C_LABEL(data_abort_handler_address) 142 143 .data 144 .global _C_LABEL(data_abort_handler_address) 145_C_LABEL(data_abort_handler_address): 146 .word data_abort_handler 147 148END(data_abort_entry) 149 150/* 151 * addr_exception_entry: 152 * 153 * Handler for the Address Exception exception. 154 * 155 * NOTE: This exception isn't really used on arm32. We 156 * print a warning message to the console and then treat 157 * it like a Data Abort. 158 */ 159ASENTRY_NP(addr_exception_entry) 160 mrs r1, cpsr 161 mrs r2, spsr 162 mov r3, lr 163 adr r0, Laddr_exception_msg 164 bl _C_LABEL(printf) /* XXX CLOBBERS LR!! */ 165 b data_abort_entry 166Laddr_exception_msg: 167 .asciz "Address Exception CPSR=0x%08x SPSR=0x%08x LR=0x%08x\n" 168 .balign 4 169END(addr_exception_entry) 170 171/* 172 * General exception exit handler 173 * (Placed here to be within range of all the references to it) 174 * 175 * It exits straight away if not returning to USR mode. 176 * This loops around delivering any pending ASTs. 177 * Interrupts are disabled at suitable points to avoid ASTs 178 * being posted between testing and exit to user mode. 179 * 180 * This function uses PULLFRAMEFROMSVCANDEXIT and DO_AST and can 181 * only be called if the exception handler used PUSHFRAMEINSVC. 182 * 183 * For EABI, don't try to unwind any further than this. This is a 184 * stopgap measure to avoid getting stuck in a loop in the unwinder, 185 * which happens because we don't yet provide the proper unwind info 186 * here that describes which registers are being restored. 187 */ 188 189ASENTRY_NP(exception_exit) 190 UNWINDSVCFRAME 191 DO_AST 192 PULLFRAMEFROMSVCANDEXIT 193END(exception_exit) 194 195ASENTRY_NP(irq_entry) 196 sub lr, lr, #0x00000004 /* Adjust the lr */ 197 PUSHFRAMEINSVC /* Push an interrupt frame */ 198 mov r0, sp /* arg for dispatcher */ 199 200 adr lr, exception_exit 201 mov r1, #0 202 b _C_LABEL(arm_irq_handler) 203END(irq_entry) 204 205/* 206 * undefined_entry: 207 * 208 * Handler for the Undefined Instruction exception. 209 * 210 * We indirect the undefined vector via the handler address 211 * in the data area. Entry to the undefined handler must 212 * look like direct entry from the vector. 213 */ 214ASENTRY_NP(undefined_entry) 215 216 sub lr, lr, #0x00000004 /* Adjust the lr */ 217 PUSHFRAMEINSVC /* Push trap frame and switch */ 218 /* to SVC32 mode */ 219 ldr r1, Lundefined_handler_address 220 adr lr, exception_exit 221 mov r0, sp /* pass the stack pointer as r0 */ 222 ldr pc, [r1] 223END(undefined_entry) 224 225ASENTRY_NP(undefinedinstruction_bounce) 226 b undefinedinstruction 227END(undefinedinstruction_bounce) 228 229Lundefined_handler_address: 230 .word _C_LABEL(undefined_handler_address) 231 232 .data 233 .global _C_LABEL(undefined_handler_address) 234_C_LABEL(undefined_handler_address): 235 .word undefinedinstruction_bounce 236 237/* 238 * Entry point for FIQ interrupts. 239 * 240 * We don't currently support FIQ handlers very much. Something can 241 * install itself in the FIQ vector using code (that may or may not work 242 * these days) in fiq.c. If nobody does that and an FIQ happens, this 243 * default handler just disables FIQs and otherwise ignores it. 244 */ 245ASENTRY_NP(fiq_entry) 246 mrs r8, cpsr /* FIQ handling isn't supported, */ 247 bic r8, #(F32_bit) /* just disable FIQ and return. */ 248 msr cpsr_c, r8 /* The r8 we trash here is the */ 249 subs pc, lr, #4 /* banked FIQ-mode r8. */ 250END(fiq_entry) 251 252/* 253 * page0 and page0_data -- An image of the ARM vectors which is copied to 254 * the ARM vectors page (high or low) as part of CPU initialization. The 255 * code that does the copy assumes that page0_data holds one 32-bit word 256 * of data for each of the predefined ARM vectors. It also assumes that 257 * page0_data follows the vectors in page0, but other stuff can appear 258 * between the two. We currently leave room between the two for some fiq 259 * handler code to be copied in. 260 */ 261 .global _C_LABEL(page0), _C_LABEL(page0_data) 262 263_C_LABEL(page0): 264 ldr pc, .Lreset_entry 265 ldr pc, .Lundefined_entry 266 ldr pc, .Lswi_entry 267 ldr pc, .Lprefetch_abort_entry 268 ldr pc, .Ldata_abort_entry 269 ldr pc, .Laddr_exception_entry 270 ldr pc, .Lirq_entry 271.fiqv: ldr pc, .Lfiq_entry 272 .space 256 /* room for some fiq handler code */ 273 274_C_LABEL(page0_data): 275.Lreset_entry: .word reset_entry 276.Lundefined_entry: .word undefined_entry 277.Lswi_entry: .word swi_entry 278.Lprefetch_abort_entry: .word prefetch_abort_entry 279.Ldata_abort_entry: .word data_abort_entry 280.Laddr_exception_entry: .word addr_exception_entry 281.Lirq_entry: .word irq_entry 282.Lfiq_entry: .word fiq_entry 283 284/* 285 * These items are used by the code in fiq.c to install what it calls the 286 * "null" handler. It's actually our default vector entry that just jumps 287 * to the default handler which just disables FIQs and returns. 288 */ 289 .global _C_LABEL(fiq_nullhandler_code), _C_LABEL(fiq_nullhandler_size) 290 291_C_LABEL(fiq_nullhandler_code): 292 .word .fiqv 293_C_LABEL(fiq_nullhandler_size): 294 .word 4 295 296 297