Index: head/sys/arm/arm/exception.S =================================================================== --- head/sys/arm/arm/exception.S (revision 263032) +++ head/sys/arm/arm/exception.S (revision 263033) @@ -1,482 +1,464 @@ /* $NetBSD: exception.S,v 1.13 2003/10/31 16:30:15 scw Exp $ */ /*- * Copyright (c) 1994-1997 Mark Brinicombe. * Copyright (c) 1994 Brini. * All rights reserved. * * This code is derived from software written for Brini by Mark Brinicombe * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Brini. * 4. The name of the company nor the name of the author may be used to * endorse or promote products derived from this software without specific * prior written permission. * * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * RiscBSD kernel project * * exception.S * * Low level handlers for exception vectors * * Created : 24/09/94 * * Based on kate/display/abort.s * */ #include "assym.s" #include #include #include __FBSDID("$FreeBSD$"); .text .align 0 /* * ASM macros for pushing and pulling trapframes from the stack * * These macros are used to handle the irqframe and trapframe structures * defined above. */ /* * PUSHFRAME - macro to push a trap frame on the stack in the current mode * Since the current mode is used, the SVC lr field is not defined. * * NOTE: r13 and r14 are stored separately as a work around for the * SA110 rev 2 STM^ bug */ #ifdef ARM_TP_ADDRESS #define PUSHFRAME \ sub sp, sp, #4; /* Align the stack */ \ str lr, [sp, #-4]!; /* Push the return address */ \ sub sp, sp, #(4*17); /* Adjust the stack pointer */ \ stmia sp, {r0-r12}; /* Push the user mode registers */ \ add r0, sp, #(4*13); /* Adjust the stack pointer */ \ stmia r0, {r13-r14}^; /* Push the user mode registers */ \ - mov r0, r0; /* NOP for previous instruction */ \ + mov r0, r0; /* NOP for previous instruction */ \ mrs r0, spsr; /* Put the SPSR on the stack */ \ str r0, [sp, #-4]!; \ ldr r0, =ARM_RAS_START; \ mov r1, #0; \ str r1, [r0]; \ mov r1, #0xffffffff; \ str r1, [r0, #4]; #else #define PUSHFRAME \ sub sp, sp, #4; /* Align the stack */ \ str lr, [sp, #-4]!; /* Push the return address */ \ sub sp, sp, #(4*17); /* Adjust the stack pointer */ \ stmia sp, {r0-r12}; /* Push the user mode registers */ \ add r0, sp, #(4*13); /* Adjust the stack pointer */ \ stmia r0, {r13-r14}^; /* Push the user mode registers */ \ - mov r0, r0; /* NOP for previous instruction */ \ + mov r0, r0; /* NOP for previous instruction */ \ mrs r0, spsr; /* Put the SPSR on the stack */ \ str r0, [sp, #-4]!; #endif /* * PULLFRAME - macro to pull a trap frame from the stack in the current mode * Since the current mode is used, the SVC lr field is ignored. */ #ifdef ARM_TP_ADDRESS #define PULLFRAME \ - ldr r0, [sp], #0x0004; /* Get the SPSR from stack */ \ - msr spsr_fsxc, r0; \ - ldmia sp, {r0-r14}^; /* Restore registers (usr mode) */ \ - mov r0, r0; /* NOP for previous instruction */ \ + ldr r0, [sp], #4; /* Get the SPSR from stack */ \ + msr spsr_fsxc, r0; \ + ldmia sp, {r0-r14}^; /* Restore registers (usr mode) */ \ + mov r0, r0; /* NOP for previous instruction */ \ add sp, sp, #(4*17); /* Adjust the stack pointer */ \ - ldr lr, [sp], #0x0004; /* Pull the return address */ \ + ldr lr, [sp], #4; /* Pull the return address */ \ add sp, sp, #4 /* Align the stack */ #else #define PULLFRAME \ - ldr r0, [sp], #0x0004; /* Get the SPSR from stack */ \ - msr spsr_fsxc, r0; \ + ldr r0, [sp], #4 ; /* Get the SPSR from stack */ \ + msr spsr_fsxc, r0; \ clrex; \ - ldmia sp, {r0-r14}^; /* Restore registers (usr mode) */ \ - mov r0, r0; /* NOP for previous instruction */ \ + ldmia sp, {r0-r14}^; /* Restore registers (usr mode) */ \ + mov r0, r0; /* NOP for previous instruction */ \ add sp, sp, #(4*17); /* Adjust the stack pointer */ \ - ldr lr, [sp], #0x0004; /* Pull the return address */ \ + ldr lr, [sp], #4; /* Pull the return address */ \ add sp, sp, #4 /* Align the stack */ #endif /* * PUSHFRAMEINSVC - macro to push a trap frame on the stack in SVC32 mode * This should only be used if the processor is not currently in SVC32 * mode. The processor mode is switched to SVC mode and the trap frame is * stored. The SVC lr field is used to store the previous value of * lr in SVC mode. * * NOTE: r13 and r14 are stored separately as a work around for the * SA110 rev 2 STM^ bug */ #ifdef ARM_TP_ADDRESS #define PUSHFRAMEINSVC \ stmdb sp, {r0-r3}; /* Save 4 registers */ \ mov r0, lr; /* Save xxx32 r14 */ \ mov r1, sp; /* Save xxx32 sp */ \ mrs r3, spsr; /* Save xxx32 spsr */ \ - mrs r2, cpsr; /* Get the CPSR */ \ - bic r2, r2, #(PSR_MODE); /* Fix for SVC mode */ \ - orr r2, r2, #(PSR_SVC32_MODE); \ - msr cpsr_c, r2; /* Punch into SVC mode */ \ + mrs r2, cpsr; /* Get the CPSR */ \ + bic r2, r2, #(PSR_MODE); /* Fix for SVC mode */ \ + orr r2, r2, #(PSR_SVC32_MODE); \ + msr cpsr_c, r2; /* Punch into SVC mode */ \ mov r2, sp; /* Save SVC sp */ \ bic sp, sp, #7; /* Align sp to an 8-byte addrress */ \ sub sp, sp, #4; /* Pad trapframe to keep alignment */ \ str r0, [sp, #-4]!; /* Push return address */ \ str lr, [sp, #-4]!; /* Push SVC lr */ \ str r2, [sp, #-4]!; /* Push SVC sp */ \ - msr spsr_fsxc, r3; /* Restore correct spsr */ \ + msr spsr_fsxc, r3; /* Restore correct spsr */ \ ldmdb r1, {r0-r3}; /* Restore 4 regs from xxx mode */ \ sub sp, sp, #(4*15); /* Adjust the stack pointer */ \ stmia sp, {r0-r12}; /* Push the user mode registers */ \ add r0, sp, #(4*13); /* Adjust the stack pointer */ \ stmia r0, {r13-r14}^; /* Push the user mode registers */ \ - mov r0, r0; /* NOP for previous instruction */ \ + mov r0, r0; /* NOP for previous instruction */ \ ldr r5, =ARM_RAS_START; /* Check if there's any RAS */ \ - ldr r4, [r5, #4]; /* reset it to point at the */ \ - cmp r4, #0xffffffff; /* end of memory if necessary; */ \ - movne r1, #0xffffffff; /* leave value in r4 for later */ \ - strne r1, [r5, #4]; /* comparision against PC. */ \ - ldr r3, [r5]; /* Retrieve global RAS_START */ \ - cmp r3, #0; /* and reset it if non-zero. */ \ - movne r1, #0; /* If non-zero RAS_START and */ \ - strne r1, [r5]; /* PC was lower than RAS_END, */ \ - ldrne r1, [r0, #16]; /* adjust the saved PC so that */ \ - cmpne r4, r1; /* execution later resumes at */ \ - strhi r3, [r0, #16]; /* the RAS_START location. */ \ - mrs r0, spsr; \ - str r0, [sp, #-4]! + ldr r4, [r5, #4]; /* reset it to point at the */ \ + cmp r4, #0xffffffff; /* end of memory if necessary; */ \ + movne r1, #0xffffffff; /* leave value in r4 for later */ \ + strne r1, [r5, #4]; /* comparision against PC. */ \ + ldr r3, [r5]; /* Retrieve global RAS_START */ \ + cmp r3, #0; /* and reset it if non-zero. */ \ + movne r1, #0; /* If non-zero RAS_START and */ \ + strne r1, [r5]; /* PC was lower than RAS_END, */ \ + ldrne r1, [r0, #16]; /* adjust the saved PC so that */ \ + cmpne r4, r1; /* execution later resumes at */ \ + strhi r3, [r0, #16]; /* the RAS_START location. */ \ + mrs r0, spsr; \ + str r0, [sp, #-4]! #else #define PUSHFRAMEINSVC \ stmdb sp, {r0-r3}; /* Save 4 registers */ \ mov r0, lr; /* Save xxx32 r14 */ \ mov r1, sp; /* Save xxx32 sp */ \ mrs r3, spsr; /* Save xxx32 spsr */ \ - mrs r2, cpsr; /* Get the CPSR */ \ - bic r2, r2, #(PSR_MODE); /* Fix for SVC mode */ \ - orr r2, r2, #(PSR_SVC32_MODE); \ - msr cpsr_c, r2; /* Punch into SVC mode */ \ + mrs r2, cpsr; /* Get the CPSR */ \ + bic r2, r2, #(PSR_MODE); /* Fix for SVC mode */ \ + orr r2, r2, #(PSR_SVC32_MODE); \ + msr cpsr_c, r2; /* Punch into SVC mode */ \ mov r2, sp; /* Save SVC sp */ \ bic sp, sp, #7; /* Align sp to an 8-byte addrress */ \ sub sp, sp, #4; /* Pad trapframe to keep alignment */ \ str r0, [sp, #-4]!; /* Push return address */ \ str lr, [sp, #-4]!; /* Push SVC lr */ \ str r2, [sp, #-4]!; /* Push SVC sp */ \ - msr spsr_fsxc, r3; /* Restore correct spsr */ \ + msr spsr_fsxc, r3; /* Restore correct spsr */ \ ldmdb r1, {r0-r3}; /* Restore 4 regs from xxx mode */ \ sub sp, sp, #(4*15); /* Adjust the stack pointer */ \ stmia sp, {r0-r12}; /* Push the user mode registers */ \ add r0, sp, #(4*13); /* Adjust the stack pointer */ \ stmia r0, {r13-r14}^; /* Push the user mode registers */ \ - mov r0, r0; /* NOP for previous instruction */ \ + mov r0, r0; /* NOP for previous instruction */ \ mrs r0, spsr; /* Put the SPSR on the stack */ \ str r0, [sp, #-4]! #endif /* * PULLFRAMEFROMSVCANDEXIT - macro to pull a trap frame from the stack * in SVC32 mode and restore the saved processor mode and PC. * This should be used when the SVC lr register needs to be restored on * exit. */ #ifdef ARM_TP_ADDRESS #define PULLFRAMEFROMSVCANDEXIT \ - ldr r0, [sp], #0x0004; /* Get the SPSR from stack */ \ - msr spsr_fsxc, r0; /* restore SPSR */ \ - ldmia sp, {r0-r14}^; /* Restore registers (usr mode) */ \ - mov r0, r0; /* NOP for previous instruction */ \ + ldr r0, [sp], #4; /* Get the SPSR from stack */ \ + msr spsr_fsxc, r0; /* restore SPSR */ \ + ldmia sp, {r0-r14}^; /* Restore registers (usr mode) */ \ + mov r0, r0; /* NOP for previous instruction */ \ add sp, sp, #(4*15); /* Adjust the stack pointer */ \ ldmia sp, {sp, lr, pc}^ /* Restore lr and exit */ #else #define PULLFRAMEFROMSVCANDEXIT \ - ldr r0, [sp], #0x0004; /* Get the SPSR from stack */ \ - msr spsr_fsxc, r0; /* restore SPSR */ \ + ldr r0, [sp], #4; /* Get the SPSR from stack */ \ + msr spsr_fsxc, r0; /* restore SPSR */ \ clrex; \ - ldmia sp, {r0-r14}^; /* Restore registers (usr mode) */ \ - mov r0, r0; /* NOP for previous instruction */ \ + ldmia sp, {r0-r14}^; /* Restore registers (usr mode) */ \ + mov r0, r0; /* NOP for previous instruction */ \ add sp, sp, #(4*15); /* Adjust the stack pointer */ \ ldmia sp, {sp, lr, pc}^ /* Restore lr and exit */ #endif #if defined(__ARM_EABI__) /* * Unwind hints so we can unwind past functions that use * PULLFRAMEFROMSVCANDEXIT. They are run in reverse order. * As the last thing we do is restore the stack pointer * we can ignore the padding at the end of struct trapframe. */ #define UNWINDSVCFRAME \ .save {r13-r15}; /* Restore sp, lr, pc */ \ .pad #(2*4); /* Skip user sp and lr */ \ .save {r0-r12}; /* Restore r0-r12 */ \ .pad #(4) /* Skip spsr */ #else #define UNWINDSVCFRAME #endif #define DO_AST \ ldr r0, [sp] /* Get the SPSR from stack */ ;\ mrs r4, cpsr /* save CPSR */ ;\ orr r1, r4, #(I32_bit|F32_bit) ;\ msr cpsr_c, r1 /* Disable interrupts */ ;\ and r0, r0, #(PSR_MODE) /* Returning to USR mode? */ ;\ teq r0, #(PSR_USR32_MODE) ;\ bne 2f /* Nope, get out now */ ;\ bic r4, r4, #(I32_bit|F32_bit) ;\ 1: GET_CURTHREAD_PTR(r5) ;\ ldr r1, [r5, #(TD_FLAGS)] ;\ and r1, r1, #(TDF_ASTPENDING|TDF_NEEDRESCHED) ;\ teq r1, #0x00000000 ;\ beq 2f /* Nope. Just bail */ ;\ msr cpsr_c, r4 /* Restore interrupts */ ;\ mov r0, sp ;\ bl _C_LABEL(ast) /* ast(frame) */ ;\ orr r0, r4, #(I32_bit|F32_bit) ;\ msr cpsr_c, r0 ;\ b 1b ;\ 2: - - /* - * reset_entry: + * Entry point for a Software Interrupt (SWI). * - * Handler for Reset exception. + * The hardware switches to svc32 mode on a swi, so we're already on the + * right stack; just build a trapframe and call the handler. */ -ASENTRY_NP(reset_entry) - adr r0, Lreset_panicmsg - bl _C_LABEL(panic) - /* NOTREACHED */ -Lreset_panicmsg: - .asciz "Reset vector called, LR = 0x%08x" - .balign 4 -END(reset_entry) - -/* - * swi_entry - * - * Handler for the Software Interrupt exception. - */ ASENTRY_NP(swi_entry) - STOP_UNWINDING /* Don't unwind into user mode. */ - - PUSHFRAME - - mov r0, sp /* Pass the frame to any function */ - bl _C_LABEL(swi_handler) /* It's a SWI ! */ - + PUSHFRAME /* Build the trapframe on the */ + mov r0, sp /* scv32 stack, pass it to the */ + bl _C_LABEL(swi_handler) /* swi handler. */ /* * The fork_trampoline() code in swtch.S aranges for the MI fork_exit() * to return to swi_exit here, to return to userland. The net effect is * that a newly created thread appears to return from a SWI just like * the parent thread that created it. */ ASENTRY_NP(swi_exit) - - DO_AST /* Deliver signals. */ - - PULLFRAME - movs pc, lr /* Exit */ - + DO_AST /* Handle pending signals. */ + PULLFRAME /* Deallocate trapframe. */ + movs pc, lr /* Return to userland. */ + STOP_UNWINDING /* Don't unwind into user mode. */ END(swi_exit) END(swi_entry) /* - * prefetch_abort_entry: + * Standard exception exit handler. * - * Handler for the Prefetch Abort exception. + * This is used to return from all exceptions except SWI. It uses DO_AST and + * PULLFRAMEFROMSVCANDEXIT and can only be called if the exception entry code + * used PUSHFRAMEINSVC. + * + * If the return is to user mode, this uses DO_AST to deliver any pending + * signals and/or handle TDF_NEEDRESCHED first. */ +ASENTRY_NP(exception_exit) + DO_AST /* Handle pending signals. */ + PULLFRAMEFROMSVCANDEXIT /* Return. */ + UNWINDSVCFRAME /* Special unwinding for exceptions. */ +END(exception_exit) + +/* + * Entry point for a Prefetch Abort exception. + * + * The hardware switches to the abort mode stack; we switch to svc32 before + * calling the handler, then return directly to the original mode/stack + * on exit (without transitioning back through the abort mode stack). + */ ASENTRY_NP(prefetch_abort_entry) #ifdef __XSCALE__ nop /* Make absolutely sure any pending */ nop /* imprecise aborts have occurred. */ #endif - sub lr, lr, #0x00000004 /* Adjust the lr */ - - PUSHFRAMEINSVC - adr lr, exception_exit - mov r0, sp /* pass the stack pointer as r0 */ - b prefetch_abort_handler + sub lr, lr, #4 /* Adjust the lr. Transition to scv32 */ + PUSHFRAMEINSVC /* mode stack, build trapframe there. */ + adr lr, exception_exit /* Return from handler via standard */ + mov r0, sp /* exception exit routine. Pass the */ + b prefetch_abort_handler /* trapframe to the handler. */ END(prefetch_abort_entry) /* - * data_abort_entry: + * Entry point for a Data Abort exception. * - * Handler for the Data Abort exception. + * The hardware switches to the abort mode stack; we switch to svc32 before + * calling the handler, then return directly to the original mode/stack + * on exit (without transitioning back through the abort mode stack). */ ASENTRY_NP(data_abort_entry) #ifdef __XSCALE__ nop /* Make absolutely sure any pending */ nop /* imprecise aborts have occurred. */ #endif - - sub lr, lr, #0x00000008 /* Adjust the lr */ - PUSHFRAMEINSVC /* Push trap frame and switch */ - /* to SVC32 mode */ - adr lr, exception_exit - mov r0, sp /* pass the stack pointer as r0 */ - b data_abort_handler + sub lr, lr, #8 /* Adjust the lr. Transition to scv32 */ + PUSHFRAMEINSVC /* mode stack, build trapframe there. */ + adr lr, exception_exit /* Return from handler via standard */ + mov r0, sp /* exception exit routine. Pass the */ + b data_abort_handler /* trapframe to the handler. */ END(data_abort_entry) /* - * addr_exception_entry: + * Entry point for an Undefined Instruction exception. * - * Handler for the Address Exception exception. - * - * NOTE: This exception isn't really used on arm32. We - * print a warning message to the console and then treat - * it like a Data Abort. + * The hardware switches to the undefined mode stack; we switch to svc32 before + * calling the handler, then return directly to the original mode/stack + * on exit (without transitioning back through the undefined mode stack). */ -ASENTRY_NP(addr_exception_entry) - mrs r1, cpsr - mrs r2, spsr - mov r3, lr - adr r0, Laddr_exception_msg - bl _C_LABEL(printf) /* XXX CLOBBERS LR!! */ - b data_abort_entry -Laddr_exception_msg: - .asciz "Address Exception CPSR=0x%08x SPSR=0x%08x LR=0x%08x\n" - .balign 4 -END(addr_exception_entry) +ASENTRY_NP(undefined_entry) + sub lr, lr, #4 /* Adjust the lr. Transition to scv32 */ + PUSHFRAMEINSVC /* mode stack, build trapframe there. */ + adr lr, exception_exit /* Return from handler via standard */ + mov r0, sp /* exception exit routine. Pass the */ + b undefinedinstruction /* trapframe to the handler. */ +END(undefined_entry) /* - * General exception exit handler - * (Placed here to be within range of all the references to it) + * Entry point for a normal IRQ. * - * It exits straight away if not returning to USR mode. - * This loops around delivering any pending ASTs. - * Interrupts are disabled at suitable points to avoid ASTs - * being posted between testing and exit to user mode. - * - * This function uses PULLFRAMEFROMSVCANDEXIT and DO_AST and can - * only be called if the exception handler used PUSHFRAMEINSVC. - * - * For EABI, don't try to unwind any further than this. This is a - * stopgap measure to avoid getting stuck in a loop in the unwinder, - * which happens because we don't yet provide the proper unwind info - * here that describes which registers are being restored. + * The hardware switches to the IRQ mode stack; we switch to svc32 before + * calling the handler, then return directly to the original mode/stack + * on exit (without transitioning back through the IRQ mode stack). */ - -ASENTRY_NP(exception_exit) - UNWINDSVCFRAME - DO_AST - PULLFRAMEFROMSVCANDEXIT -END(exception_exit) - ASENTRY_NP(irq_entry) - sub lr, lr, #0x00000004 /* Adjust the lr */ - PUSHFRAMEINSVC /* Push an interrupt frame */ - mov r0, sp /* arg for dispatcher */ + sub lr, lr, #4 /* Adjust the lr. Transition to scv32 */ + PUSHFRAMEINSVC /* mode stack, build trapframe there. */ + adr lr, exception_exit /* Return from handler via standard */ + mov r0, sp /* exception exit routine. Pass the */ + b _C_LABEL(arm_irq_handler)/* trapframe to the handler. */ +END(irq_entry) - adr lr, exception_exit - mov r1, #0 - b _C_LABEL(arm_irq_handler) -END(irq_entry) - /* - * undefined_entry: + * Entry point for an FIQ interrupt. * - * Handler for the Undefined Instruction exception. - * - * We indirect the undefined vector via the handler address - * in the data area. Entry to the undefined handler must - * look like direct entry from the vector. - */ -ASENTRY_NP(undefined_entry) - - sub lr, lr, #0x00000004 /* Adjust the lr */ - PUSHFRAMEINSVC /* Push trap frame and switch */ - /* to SVC32 mode */ - adr lr, exception_exit - mov r0, sp /* pass the stack pointer as r0 */ - b undefinedinstruction -END(undefined_entry) - -/* - * Entry point for FIQ interrupts. - * * We don't currently support FIQ handlers very much. Something can * install itself in the FIQ vector using code (that may or may not work * these days) in fiq.c. If nobody does that and an FIQ happens, this * default handler just disables FIQs and otherwise ignores it. + */ ASENTRY_NP(fiq_entry) mrs r8, cpsr /* FIQ handling isn't supported, */ bic r8, #(F32_bit) /* just disable FIQ and return. */ msr cpsr_c, r8 /* The r8 we trash here is the */ subs pc, lr, #4 /* banked FIQ-mode r8. */ END(fiq_entry) + +/* + * Entry point for an Address Exception exception. + * This is an arm26 exception that should never happen. + */ +ASENTRY_NP(addr_exception_entry) + mrs r1, cpsr + mrs r2, spsr + mov r3, lr + adr r0, Laddr_exception_msg + bl _C_LABEL(printf) /* XXX CLOBBERS LR!! */ + b data_abort_entry +Laddr_exception_msg: + .asciz "Address Exception CPSR=0x%08x SPSR=0x%08x LR=0x%08x\n" + .balign 4 +END(addr_exception_entry) + +/* + * Entry point for the system Reset vector. + * This should never happen, so panic. + */ +ASENTRY_NP(reset_entry) + adr r0, Lreset_panicmsg + bl _C_LABEL(panic) + /* NOTREACHED */ +Lreset_panicmsg: + .asciz "Reset vector called, LR = 0x%08x" + .balign 4 +END(reset_entry) /* * page0 and page0_data -- An image of the ARM vectors which is copied to * the ARM vectors page (high or low) as part of CPU initialization. The * code that does the copy assumes that page0_data holds one 32-bit word * of data for each of the predefined ARM vectors. It also assumes that * page0_data follows the vectors in page0, but other stuff can appear * between the two. We currently leave room between the two for some fiq * handler code to be copied in. */ .global _C_LABEL(page0), _C_LABEL(page0_data) _C_LABEL(page0): ldr pc, .Lreset_entry ldr pc, .Lundefined_entry ldr pc, .Lswi_entry ldr pc, .Lprefetch_abort_entry ldr pc, .Ldata_abort_entry ldr pc, .Laddr_exception_entry ldr pc, .Lirq_entry .fiqv: ldr pc, .Lfiq_entry .space 256 /* room for some fiq handler code */ _C_LABEL(page0_data): .Lreset_entry: .word reset_entry .Lundefined_entry: .word undefined_entry .Lswi_entry: .word swi_entry .Lprefetch_abort_entry: .word prefetch_abort_entry .Ldata_abort_entry: .word data_abort_entry .Laddr_exception_entry: .word addr_exception_entry .Lirq_entry: .word irq_entry .Lfiq_entry: .word fiq_entry /* * These items are used by the code in fiq.c to install what it calls the * "null" handler. It's actually our default vector entry that just jumps * to the default handler which just disables FIQs and returns. */ .global _C_LABEL(fiq_nullhandler_code), _C_LABEL(fiq_nullhandler_size) _C_LABEL(fiq_nullhandler_code): .word .fiqv _C_LABEL(fiq_nullhandler_size): .word 4