exception.S revision 279667
1129198Scognet/* $NetBSD: exception.S,v 1.13 2003/10/31 16:30:15 scw Exp $ */ 2129198Scognet 3139735Simp/*- 4129198Scognet * Copyright (c) 1994-1997 Mark Brinicombe. 5129198Scognet * Copyright (c) 1994 Brini. 6129198Scognet * All rights reserved. 7129198Scognet * 8129198Scognet * This code is derived from software written for Brini by Mark Brinicombe 9129198Scognet * 10129198Scognet * Redistribution and use in source and binary forms, with or without 11129198Scognet * modification, are permitted provided that the following conditions 12129198Scognet * are met: 13129198Scognet * 1. Redistributions of source code must retain the above copyright 14129198Scognet * notice, this list of conditions and the following disclaimer. 15129198Scognet * 2. Redistributions in binary form must reproduce the above copyright 16129198Scognet * notice, this list of conditions and the following disclaimer in the 17129198Scognet * documentation and/or other materials provided with the distribution. 18129198Scognet * 3. All advertising materials mentioning features or use of this software 19129198Scognet * must display the following acknowledgement: 20129198Scognet * This product includes software developed by Brini. 21129198Scognet * 4. The name of the company nor the name of the author may be used to 22129198Scognet * endorse or promote products derived from this software without specific 23129198Scognet * prior written permission. 24129198Scognet * 25129198Scognet * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED 26129198Scognet * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 27129198Scognet * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 28129198Scognet * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 29129198Scognet * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 30129198Scognet * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 31129198Scognet * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32129198Scognet * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33129198Scognet * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34129198Scognet * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35129198Scognet * SUCH DAMAGE. 36129198Scognet * 37129198Scognet * RiscBSD kernel project 38129198Scognet * 39129198Scognet * exception.S 40129198Scognet * 41129198Scognet * Low level handlers for exception vectors 42129198Scognet * 43129198Scognet * Created : 24/09/94 44129198Scognet * 45129198Scognet * Based on kate/display/abort.s 46129198Scognet * 47129198Scognet */ 48129198Scognet 49129198Scognet#include "assym.s" 50129198Scognet 51278529Sgnn#include "opt_kdtrace.h" 52129198Scognet#include <machine/asm.h> 53129198Scognet#include <machine/armreg.h> 54129198Scognet#include <machine/asmacros.h> 55129198Scognet__FBSDID("$FreeBSD: head/sys/arm/arm/exception.S 279667 2015-03-05 17:55:31Z andrew $"); 56129198Scognet 57278529Sgnn#ifdef KDTRACE_HOOKS 58278529Sgnn .bss 59278529Sgnn .align 4 60278529Sgnn .global _C_LABEL(dtrace_invop_calltrap_addr) 61278529Sgnn_C_LABEL(dtrace_invop_calltrap_addr): 62278529Sgnn .word 0 63278529Sgnn .word 0 64278529Sgnn#endif 65278529Sgnn 66129198Scognet .text 67276596Sian .align 2 68129198Scognet 69129198Scognet/* 70262997Sian * ASM macros for pushing and pulling trapframes from the stack 71262997Sian * 72262997Sian * These macros are used to handle the irqframe and trapframe structures 73262997Sian * defined above. 74262997Sian */ 75262997Sian 76262997Sian/* 77262997Sian * PUSHFRAME - macro to push a trap frame on the stack in the current mode 78262997Sian * Since the current mode is used, the SVC lr field is not defined. 79262997Sian * 80262997Sian * NOTE: r13 and r14 are stored separately as a work around for the 81262997Sian * SA110 rev 2 STM^ bug 82262997Sian */ 83262997Sian#ifdef ARM_TP_ADDRESS 84262997Sian#define PUSHFRAME \ 85262997Sian sub sp, sp, #4; /* Align the stack */ \ 86262997Sian str lr, [sp, #-4]!; /* Push the return address */ \ 87262997Sian sub sp, sp, #(4*17); /* Adjust the stack pointer */ \ 88262997Sian stmia sp, {r0-r12}; /* Push the user mode registers */ \ 89262997Sian add r0, sp, #(4*13); /* Adjust the stack pointer */ \ 90262997Sian stmia r0, {r13-r14}^; /* Push the user mode registers */ \ 91263033Sian mov r0, r0; /* NOP for previous instruction */ \ 92262997Sian mrs r0, spsr; /* Put the SPSR on the stack */ \ 93262997Sian str r0, [sp, #-4]!; \ 94262997Sian ldr r0, =ARM_RAS_START; \ 95262997Sian mov r1, #0; \ 96262997Sian str r1, [r0]; \ 97262997Sian mov r1, #0xffffffff; \ 98262997Sian str r1, [r0, #4]; 99262997Sian#else 100262997Sian#define PUSHFRAME \ 101262997Sian sub sp, sp, #4; /* Align the stack */ \ 102262997Sian str lr, [sp, #-4]!; /* Push the return address */ \ 103262997Sian sub sp, sp, #(4*17); /* Adjust the stack pointer */ \ 104262997Sian stmia sp, {r0-r12}; /* Push the user mode registers */ \ 105262997Sian add r0, sp, #(4*13); /* Adjust the stack pointer */ \ 106262997Sian stmia r0, {r13-r14}^; /* Push the user mode registers */ \ 107263033Sian mov r0, r0; /* NOP for previous instruction */ \ 108262997Sian mrs r0, spsr; /* Put the SPSR on the stack */ \ 109262997Sian str r0, [sp, #-4]!; 110262997Sian#endif 111262997Sian 112262997Sian/* 113262997Sian * PULLFRAME - macro to pull a trap frame from the stack in the current mode 114262997Sian * Since the current mode is used, the SVC lr field is ignored. 115262997Sian */ 116262997Sian 117262997Sian#ifdef ARM_TP_ADDRESS 118262997Sian#define PULLFRAME \ 119263033Sian ldr r0, [sp], #4; /* Get the SPSR from stack */ \ 120263033Sian msr spsr_fsxc, r0; \ 121263033Sian ldmia sp, {r0-r14}^; /* Restore registers (usr mode) */ \ 122263033Sian mov r0, r0; /* NOP for previous instruction */ \ 123262997Sian add sp, sp, #(4*17); /* Adjust the stack pointer */ \ 124263033Sian ldr lr, [sp], #4; /* Pull the return address */ \ 125262997Sian add sp, sp, #4 /* Align the stack */ 126262997Sian#else 127262997Sian#define PULLFRAME \ 128263033Sian ldr r0, [sp], #4 ; /* Get the SPSR from stack */ \ 129263033Sian msr spsr_fsxc, r0; \ 130262997Sian clrex; \ 131263033Sian ldmia sp, {r0-r14}^; /* Restore registers (usr mode) */ \ 132263033Sian mov r0, r0; /* NOP for previous instruction */ \ 133262997Sian add sp, sp, #(4*17); /* Adjust the stack pointer */ \ 134263033Sian ldr lr, [sp], #4; /* Pull the return address */ \ 135262997Sian add sp, sp, #4 /* Align the stack */ 136262997Sian#endif 137262997Sian 138262997Sian/* 139262987Sian * PUSHFRAMEINSVC - macro to push a trap frame on the stack in SVC32 mode 140262987Sian * This should only be used if the processor is not currently in SVC32 141262987Sian * mode. The processor mode is switched to SVC mode and the trap frame is 142262987Sian * stored. The SVC lr field is used to store the previous value of 143262987Sian * lr in SVC mode. 144262987Sian * 145262987Sian * NOTE: r13 and r14 are stored separately as a work around for the 146262987Sian * SA110 rev 2 STM^ bug 147262987Sian */ 148262987Sian#ifdef ARM_TP_ADDRESS 149262987Sian#define PUSHFRAMEINSVC \ 150262987Sian stmdb sp, {r0-r3}; /* Save 4 registers */ \ 151262987Sian mov r0, lr; /* Save xxx32 r14 */ \ 152262987Sian mov r1, sp; /* Save xxx32 sp */ \ 153262987Sian mrs r3, spsr; /* Save xxx32 spsr */ \ 154263033Sian mrs r2, cpsr; /* Get the CPSR */ \ 155263033Sian bic r2, r2, #(PSR_MODE); /* Fix for SVC mode */ \ 156263033Sian orr r2, r2, #(PSR_SVC32_MODE); \ 157263033Sian msr cpsr_c, r2; /* Punch into SVC mode */ \ 158262987Sian mov r2, sp; /* Save SVC sp */ \ 159262987Sian bic sp, sp, #7; /* Align sp to an 8-byte addrress */ \ 160279667Sandrew sub sp, sp, #(4 * 17); /* Pad trapframe to keep alignment */ \ 161279667Sandrew /* and for dtrace to emulate push/pop */ \ 162262987Sian str r0, [sp, #-4]!; /* Push return address */ \ 163262987Sian str lr, [sp, #-4]!; /* Push SVC lr */ \ 164262987Sian str r2, [sp, #-4]!; /* Push SVC sp */ \ 165263033Sian msr spsr_fsxc, r3; /* Restore correct spsr */ \ 166262987Sian ldmdb r1, {r0-r3}; /* Restore 4 regs from xxx mode */ \ 167262987Sian sub sp, sp, #(4*15); /* Adjust the stack pointer */ \ 168262987Sian stmia sp, {r0-r12}; /* Push the user mode registers */ \ 169262987Sian add r0, sp, #(4*13); /* Adjust the stack pointer */ \ 170262987Sian stmia r0, {r13-r14}^; /* Push the user mode registers */ \ 171263033Sian mov r0, r0; /* NOP for previous instruction */ \ 172262987Sian ldr r5, =ARM_RAS_START; /* Check if there's any RAS */ \ 173263033Sian ldr r4, [r5, #4]; /* reset it to point at the */ \ 174263033Sian cmp r4, #0xffffffff; /* end of memory if necessary; */ \ 175263033Sian movne r1, #0xffffffff; /* leave value in r4 for later */ \ 176263033Sian strne r1, [r5, #4]; /* comparision against PC. */ \ 177263033Sian ldr r3, [r5]; /* Retrieve global RAS_START */ \ 178263033Sian cmp r3, #0; /* and reset it if non-zero. */ \ 179263033Sian movne r1, #0; /* If non-zero RAS_START and */ \ 180263033Sian strne r1, [r5]; /* PC was lower than RAS_END, */ \ 181263033Sian ldrne r1, [r0, #16]; /* adjust the saved PC so that */ \ 182263033Sian cmpne r4, r1; /* execution later resumes at */ \ 183263033Sian strhi r3, [r0, #16]; /* the RAS_START location. */ \ 184263033Sian mrs r0, spsr; \ 185263033Sian str r0, [sp, #-4]! 186262987Sian#else 187262987Sian#define PUSHFRAMEINSVC \ 188262987Sian stmdb sp, {r0-r3}; /* Save 4 registers */ \ 189262987Sian mov r0, lr; /* Save xxx32 r14 */ \ 190262987Sian mov r1, sp; /* Save xxx32 sp */ \ 191262987Sian mrs r3, spsr; /* Save xxx32 spsr */ \ 192263033Sian mrs r2, cpsr; /* Get the CPSR */ \ 193263033Sian bic r2, r2, #(PSR_MODE); /* Fix for SVC mode */ \ 194263033Sian orr r2, r2, #(PSR_SVC32_MODE); \ 195263033Sian msr cpsr_c, r2; /* Punch into SVC mode */ \ 196262987Sian mov r2, sp; /* Save SVC sp */ \ 197262987Sian bic sp, sp, #7; /* Align sp to an 8-byte addrress */ \ 198279667Sandrew sub sp, sp, #(4 * 17); /* Pad trapframe to keep alignment */ \ 199279667Sandrew /* and for dtrace to emulate push/pop */ \ 200262987Sian str r0, [sp, #-4]!; /* Push return address */ \ 201262987Sian str lr, [sp, #-4]!; /* Push SVC lr */ \ 202262987Sian str r2, [sp, #-4]!; /* Push SVC sp */ \ 203263033Sian msr spsr_fsxc, r3; /* Restore correct spsr */ \ 204262987Sian ldmdb r1, {r0-r3}; /* Restore 4 regs from xxx mode */ \ 205262987Sian sub sp, sp, #(4*15); /* Adjust the stack pointer */ \ 206262987Sian stmia sp, {r0-r12}; /* Push the user mode registers */ \ 207262987Sian add r0, sp, #(4*13); /* Adjust the stack pointer */ \ 208262987Sian stmia r0, {r13-r14}^; /* Push the user mode registers */ \ 209263033Sian mov r0, r0; /* NOP for previous instruction */ \ 210262987Sian mrs r0, spsr; /* Put the SPSR on the stack */ \ 211262987Sian str r0, [sp, #-4]! 212262987Sian#endif 213262987Sian 214262987Sian/* 215262987Sian * PULLFRAMEFROMSVCANDEXIT - macro to pull a trap frame from the stack 216262987Sian * in SVC32 mode and restore the saved processor mode and PC. 217262987Sian * This should be used when the SVC lr register needs to be restored on 218262987Sian * exit. 219262987Sian */ 220262987Sian 221262987Sian#ifdef ARM_TP_ADDRESS 222262987Sian#define PULLFRAMEFROMSVCANDEXIT \ 223263033Sian ldr r0, [sp], #4; /* Get the SPSR from stack */ \ 224263033Sian msr spsr_fsxc, r0; /* restore SPSR */ \ 225263033Sian ldmia sp, {r0-r14}^; /* Restore registers (usr mode) */ \ 226263033Sian mov r0, r0; /* NOP for previous instruction */ \ 227262987Sian add sp, sp, #(4*15); /* Adjust the stack pointer */ \ 228262987Sian ldmia sp, {sp, lr, pc}^ /* Restore lr and exit */ 229262987Sian#else 230262987Sian#define PULLFRAMEFROMSVCANDEXIT \ 231263033Sian ldr r0, [sp], #4; /* Get the SPSR from stack */ \ 232263033Sian msr spsr_fsxc, r0; /* restore SPSR */ \ 233262987Sian clrex; \ 234263033Sian ldmia sp, {r0-r14}^; /* Restore registers (usr mode) */ \ 235263033Sian mov r0, r0; /* NOP for previous instruction */ \ 236262987Sian add sp, sp, #(4*15); /* Adjust the stack pointer */ \ 237262987Sian ldmia sp, {sp, lr, pc}^ /* Restore lr and exit */ 238262987Sian#endif 239262987Sian 240262987Sian#if defined(__ARM_EABI__) 241262987Sian/* 242262987Sian * Unwind hints so we can unwind past functions that use 243262987Sian * PULLFRAMEFROMSVCANDEXIT. They are run in reverse order. 244262987Sian * As the last thing we do is restore the stack pointer 245262987Sian * we can ignore the padding at the end of struct trapframe. 246262987Sian */ 247262987Sian#define UNWINDSVCFRAME \ 248262987Sian .save {r13-r15}; /* Restore sp, lr, pc */ \ 249262987Sian .pad #(2*4); /* Skip user sp and lr */ \ 250262987Sian .save {r0-r12}; /* Restore r0-r12 */ \ 251262987Sian .pad #(4) /* Skip spsr */ 252262987Sian#else 253262987Sian#define UNWINDSVCFRAME 254262987Sian#endif 255262987Sian 256276196Sian#define DO_AST \ 257276196Sian ldr r0, [sp]; /* Get the SPSR from stack */ \ 258276196Sian mrs r4, cpsr; /* save CPSR */ \ 259276196Sian orr r1, r4, #(PSR_I|PSR_F); \ 260276196Sian msr cpsr_c, r1; /* Disable interrupts */ \ 261276196Sian and r0, r0, #(PSR_MODE); /* Returning to USR mode? */ \ 262276196Sian teq r0, #(PSR_USR32_MODE); \ 263276196Sian bne 2f; /* Nope, get out now */ \ 264276196Sian bic r4, r4, #(PSR_I|PSR_F); \ 265276196Sian1: GET_CURTHREAD_PTR(r5); \ 266276196Sian ldr r1, [r5, #(TD_FLAGS)]; \ 267276196Sian and r1, r1, #(TDF_ASTPENDING|TDF_NEEDRESCHED); \ 268276196Sian teq r1, #0; \ 269276196Sian beq 2f; /* Nope. Just bail */ \ 270276196Sian msr cpsr_c, r4; /* Restore interrupts */ \ 271276196Sian mov r0, sp; \ 272276196Sian bl _C_LABEL(ast); /* ast(frame) */ \ 273276196Sian orr r0, r4, #(PSR_I|PSR_F); \ 274276196Sian msr cpsr_c, r0; \ 275276197Sian b 1b; \ 276262987Sian2: 277262987Sian 278262987Sian 279262987Sian/* 280263033Sian * Entry point for a Software Interrupt (SWI). 281129198Scognet * 282263033Sian * The hardware switches to svc32 mode on a swi, so we're already on the 283263033Sian * right stack; just build a trapframe and call the handler. 284129198Scognet */ 285129198ScognetASENTRY_NP(swi_entry) 286263033Sian PUSHFRAME /* Build the trapframe on the */ 287263033Sian mov r0, sp /* scv32 stack, pass it to the */ 288263033Sian bl _C_LABEL(swi_handler) /* swi handler. */ 289262987Sian /* 290262987Sian * The fork_trampoline() code in swtch.S aranges for the MI fork_exit() 291262987Sian * to return to swi_exit here, to return to userland. The net effect is 292262987Sian * that a newly created thread appears to return from a SWI just like 293262987Sian * the parent thread that created it. 294262987Sian */ 295269390SianASEENTRY_NP(swi_exit) 296263033Sian DO_AST /* Handle pending signals. */ 297263033Sian PULLFRAME /* Deallocate trapframe. */ 298263033Sian movs pc, lr /* Return to userland. */ 299263033Sian STOP_UNWINDING /* Don't unwind into user mode. */ 300269390SianEEND(swi_exit) 301248361SandrewEND(swi_entry) 302129198Scognet 303129198Scognet/* 304263033Sian * Standard exception exit handler. 305129198Scognet * 306263033Sian * This is used to return from all exceptions except SWI. It uses DO_AST and 307263033Sian * PULLFRAMEFROMSVCANDEXIT and can only be called if the exception entry code 308263033Sian * used PUSHFRAMEINSVC. 309263033Sian * 310263033Sian * If the return is to user mode, this uses DO_AST to deliver any pending 311263033Sian * signals and/or handle TDF_NEEDRESCHED first. 312129198Scognet */ 313263033SianASENTRY_NP(exception_exit) 314263033Sian DO_AST /* Handle pending signals. */ 315263033Sian PULLFRAMEFROMSVCANDEXIT /* Return. */ 316263033Sian UNWINDSVCFRAME /* Special unwinding for exceptions. */ 317263033SianEND(exception_exit) 318263033Sian 319263033Sian/* 320263033Sian * Entry point for a Prefetch Abort exception. 321263033Sian * 322263033Sian * The hardware switches to the abort mode stack; we switch to svc32 before 323263033Sian * calling the handler, then return directly to the original mode/stack 324263033Sian * on exit (without transitioning back through the abort mode stack). 325263033Sian */ 326129198ScognetASENTRY_NP(prefetch_abort_entry) 327129198Scognet#ifdef __XSCALE__ 328129198Scognet nop /* Make absolutely sure any pending */ 329129198Scognet nop /* imprecise aborts have occurred. */ 330129198Scognet#endif 331263033Sian sub lr, lr, #4 /* Adjust the lr. Transition to scv32 */ 332263033Sian PUSHFRAMEINSVC /* mode stack, build trapframe there. */ 333263033Sian adr lr, exception_exit /* Return from handler via standard */ 334263033Sian mov r0, sp /* exception exit routine. Pass the */ 335276206Sian mov r1, #1 /* Type flag */ 336276206Sian b _C_LABEL(abort_handler) 337248361SandrewEND(prefetch_abort_entry) 338129198Scognet 339129198Scognet/* 340263033Sian * Entry point for a Data Abort exception. 341129198Scognet * 342263033Sian * The hardware switches to the abort mode stack; we switch to svc32 before 343263033Sian * calling the handler, then return directly to the original mode/stack 344263033Sian * on exit (without transitioning back through the abort mode stack). 345129198Scognet */ 346129198ScognetASENTRY_NP(data_abort_entry) 347129198Scognet#ifdef __XSCALE__ 348129198Scognet nop /* Make absolutely sure any pending */ 349129198Scognet nop /* imprecise aborts have occurred. */ 350129198Scognet#endif 351263033Sian sub lr, lr, #8 /* Adjust the lr. Transition to scv32 */ 352263033Sian PUSHFRAMEINSVC /* mode stack, build trapframe there. */ 353276206Sian adr lr, exception_exit /* Exception exit routine */ 354276206Sian mov r0, sp /* Trapframe to the handler */ 355276206Sian mov r1, #0 /* Type flag */ 356276206Sian b _C_LABEL(abort_handler) 357248361SandrewEND(data_abort_entry) 358129198Scognet 359129198Scognet/* 360263033Sian * Entry point for an Undefined Instruction exception. 361129198Scognet * 362263033Sian * The hardware switches to the undefined mode stack; we switch to svc32 before 363263033Sian * calling the handler, then return directly to the original mode/stack 364263033Sian * on exit (without transitioning back through the undefined mode stack). 365129198Scognet */ 366263033SianASENTRY_NP(undefined_entry) 367263033Sian sub lr, lr, #4 /* Adjust the lr. Transition to scv32 */ 368263033Sian PUSHFRAMEINSVC /* mode stack, build trapframe there. */ 369263033Sian adr lr, exception_exit /* Return from handler via standard */ 370263033Sian mov r0, sp /* exception exit routine. Pass the */ 371263033Sian b undefinedinstruction /* trapframe to the handler. */ 372263033SianEND(undefined_entry) 373129198Scognet 374129198Scognet/* 375263033Sian * Entry point for a normal IRQ. 376129198Scognet * 377263033Sian * The hardware switches to the IRQ mode stack; we switch to svc32 before 378263033Sian * calling the handler, then return directly to the original mode/stack 379263033Sian * on exit (without transitioning back through the IRQ mode stack). 380129198Scognet */ 381262979SianASENTRY_NP(irq_entry) 382263033Sian sub lr, lr, #4 /* Adjust the lr. Transition to scv32 */ 383263033Sian PUSHFRAMEINSVC /* mode stack, build trapframe there. */ 384263033Sian adr lr, exception_exit /* Return from handler via standard */ 385263033Sian mov r0, sp /* exception exit routine. Pass the */ 386263033Sian b _C_LABEL(arm_irq_handler)/* trapframe to the handler. */ 387263033SianEND(irq_entry) 388262979Sian 389129198Scognet/* 390263033Sian * Entry point for an FIQ interrupt. 391129198Scognet * 392262980Sian * We don't currently support FIQ handlers very much. Something can 393262980Sian * install itself in the FIQ vector using code (that may or may not work 394262980Sian * these days) in fiq.c. If nobody does that and an FIQ happens, this 395262980Sian * default handler just disables FIQs and otherwise ignores it. 396262980Sian */ 397262980SianASENTRY_NP(fiq_entry) 398262980Sian mrs r8, cpsr /* FIQ handling isn't supported, */ 399271398Sandrew bic r8, #(PSR_F) /* just disable FIQ and return. */ 400262980Sian msr cpsr_c, r8 /* The r8 we trash here is the */ 401262980Sian subs pc, lr, #4 /* banked FIQ-mode r8. */ 402262980SianEND(fiq_entry) 403262980Sian 404262980Sian/* 405263033Sian * Entry point for an Address Exception exception. 406263033Sian * This is an arm26 exception that should never happen. 407263033Sian */ 408263033SianASENTRY_NP(addr_exception_entry) 409263034Sian mov r3, lr 410263034Sian mrs r2, spsr 411263033Sian mrs r1, cpsr 412263033Sian adr r0, Laddr_exception_msg 413263034Sian b _C_LABEL(panic) 414263033SianLaddr_exception_msg: 415263033Sian .asciz "Address Exception CPSR=0x%08x SPSR=0x%08x LR=0x%08x\n" 416263033Sian .balign 4 417263033SianEND(addr_exception_entry) 418263033Sian 419263033Sian/* 420263033Sian * Entry point for the system Reset vector. 421263033Sian * This should never happen, so panic. 422263033Sian */ 423263033SianASENTRY_NP(reset_entry) 424263034Sian mov r1, lr 425263033Sian adr r0, Lreset_panicmsg 426263034Sian b _C_LABEL(panic) 427263033Sian /* NOTREACHED */ 428263033SianLreset_panicmsg: 429263033Sian .asciz "Reset vector called, LR = 0x%08x" 430263033Sian .balign 4 431263033SianEND(reset_entry) 432263033Sian 433263033Sian/* 434262980Sian * page0 and page0_data -- An image of the ARM vectors which is copied to 435262980Sian * the ARM vectors page (high or low) as part of CPU initialization. The 436262980Sian * code that does the copy assumes that page0_data holds one 32-bit word 437262980Sian * of data for each of the predefined ARM vectors. It also assumes that 438262980Sian * page0_data follows the vectors in page0, but other stuff can appear 439262980Sian * between the two. We currently leave room between the two for some fiq 440262980Sian * handler code to be copied in. 441262980Sian */ 442262980Sian .global _C_LABEL(page0), _C_LABEL(page0_data) 443262980Sian 444262980Sian_C_LABEL(page0): 445262980Sian ldr pc, .Lreset_entry 446262980Sian ldr pc, .Lundefined_entry 447262980Sian ldr pc, .Lswi_entry 448262980Sian ldr pc, .Lprefetch_abort_entry 449262980Sian ldr pc, .Ldata_abort_entry 450262980Sian ldr pc, .Laddr_exception_entry 451262980Sian ldr pc, .Lirq_entry 452262980Sian.fiqv: ldr pc, .Lfiq_entry 453262980Sian .space 256 /* room for some fiq handler code */ 454262980Sian 455262980Sian_C_LABEL(page0_data): 456262980Sian.Lreset_entry: .word reset_entry 457262980Sian.Lundefined_entry: .word undefined_entry 458262980Sian.Lswi_entry: .word swi_entry 459262980Sian.Lprefetch_abort_entry: .word prefetch_abort_entry 460262980Sian.Ldata_abort_entry: .word data_abort_entry 461262980Sian.Laddr_exception_entry: .word addr_exception_entry 462262980Sian.Lirq_entry: .word irq_entry 463262980Sian.Lfiq_entry: .word fiq_entry 464262980Sian 465262980Sian/* 466262980Sian * These items are used by the code in fiq.c to install what it calls the 467262980Sian * "null" handler. It's actually our default vector entry that just jumps 468262980Sian * to the default handler which just disables FIQs and returns. 469262980Sian */ 470262980Sian .global _C_LABEL(fiq_nullhandler_code), _C_LABEL(fiq_nullhandler_size) 471262980Sian 472262980Sian_C_LABEL(fiq_nullhandler_code): 473262980Sian .word .fiqv 474262980Sian_C_LABEL(fiq_nullhandler_size): 475262980Sian .word 4 476262980Sian 477262980Sian 478