summaryrefslogtreecommitdiffstats
path: root/sys/arm/arm/exception.S
diff options
context:
space:
mode:
authorcognet <cognet@FreeBSD.org>2004-05-14 11:46:45 +0000
committercognet <cognet@FreeBSD.org>2004-05-14 11:46:45 +0000
commit295dcdd68788bc2248ebf4ab1df93d68da49b711 (patch)
tree3eb2afc6dea26c92444202ed2d06bac484ff40ae /sys/arm/arm/exception.S
parentdd167f263352cec86bd3c4298031380259b2fb17 (diff)
downloadFreeBSD-src-295dcdd68788bc2248ebf4ab1df93d68da49b711.zip
FreeBSD-src-295dcdd68788bc2248ebf4ab1df93d68da49b711.tar.gz
Import FreeBSD/arm kernel bits.
It only supports sa1110 (on simics) right now, but xscale support should come soon. Some of the initial work has been provided by : Stephane Potvin <sepotvin at videotron.ca> Most of this comes from NetBSD.
Diffstat (limited to 'sys/arm/arm/exception.S')
-rw-r--r--sys/arm/arm/exception.S392
1 files changed, 392 insertions, 0 deletions
diff --git a/sys/arm/arm/exception.S b/sys/arm/arm/exception.S
new file mode 100644
index 0000000..fb6bded
--- /dev/null
+++ b/sys/arm/arm/exception.S
@@ -0,0 +1,392 @@
+/* $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 <machine/asm.h>
+#include <machine/armreg.h>
+#include <machine/asmacros.h>
+__FBSDID("$FreeBSD$");
+
+ .text
+ .align 0
+
+AST_ALIGNMENT_FAULT_LOCALS
+
+/*
+ * reset_entry:
+ *
+ * Handler for Reset exception.
+ */
+ASENTRY_NP(reset_entry)
+ adr r0, Lreset_panicmsg
+ adr r1, Lfile
+ mov r2, #__LINE__
+ bl _C_LABEL(__panic)
+ /* NOTREACHED */
+Lreset_panicmsg:
+ .asciz "Reset vector called, LR = 0x%08x"
+Lfile:
+ .asciz __FILE__
+ .balign 4
+
+/*
+ * swi_entry
+ *
+ * Handler for the Software Interrupt exception.
+ */
+ASENTRY_NP(swi_entry)
+ PUSHFRAME
+ ENABLE_ALIGNMENT_FAULTS
+
+ mov r0, sp /* Pass the frame to any function */
+ bl _C_LABEL(swi_handler) /* It's a SWI ! */
+
+ DO_AST_AND_RESTORE_ALIGNMENT_FAULTS
+ PULLFRAME
+ movs pc, lr /* Exit */
+
+/*
+ * prefetch_abort_entry:
+ *
+ * Handler for the Prefetch Abort exception.
+ */
+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
+ ENABLE_ALIGNMENT_FAULTS
+ ldr r1, Lprefetch_abort_handler_address
+ adr lr, exception_exit
+ mov r0, sp /* pass the stack pointer as r0 */
+ ldr pc, [r1]
+
+Lprefetch_abort_handler_address:
+ .word _C_LABEL(prefetch_abort_handler_address)
+
+ .data
+ .global _C_LABEL(prefetch_abort_handler_address)
+
+_C_LABEL(prefetch_abort_handler_address):
+ .word abortprefetch
+
+ .text
+abortprefetch:
+ adr r0, abortprefetchmsg
+ adr r1, filee
+ mov r2, #__LINE__
+ b _C_LABEL(__panic)
+
+filee:
+ .asciz __FILE__
+
+abortprefetchmsg:
+ .asciz "abortprefetch"
+ .align 0
+
+/*
+ * data_abort_entry:
+ *
+ * Handler for the Data Abort exception.
+ */
+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 */
+ ENABLE_ALIGNMENT_FAULTS
+
+ ldr r1, Ldata_abort_handler_address
+ adr lr, exception_exit
+ mov r0, sp /* pass the stack pointer as r0 */
+ ldr pc, [r1]
+Ldata_abort_handler_address:
+ .word _C_LABEL(data_abort_handler_address)
+
+ .data
+ .global _C_LABEL(data_abort_handler_address)
+_C_LABEL(data_abort_handler_address):
+ .word abortdata
+
+ .text
+abortdata:
+ adr r0, abortdatamsg
+ adr r1, file
+ mov r2, #__LINE__
+ b _C_LABEL(__panic)
+
+abortdatamsg:
+ .asciz "abortdata"
+file:
+ .asciz __FILE__
+ .align 0
+
+/*
+ * address_exception_entry:
+ *
+ * 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.
+ */
+ASENTRY_NP(address_exception_entry)
+ mrs r1, cpsr_all
+ mrs r2, spsr_all
+ mov r3, lr
+ adr r0, Laddress_exception_msg
+ bl _C_LABEL(printf) /* XXX CLOBBERS LR!! */
+ b data_abort_entry
+Laddress_exception_msg:
+ .asciz "Address Exception CPSR=0x%08x SPSR=0x%08x LR=0x%08x\n"
+ .balign 4
+
+/*
+ * General exception exit handler
+ * (Placed here to be within range of all the references to it)
+ *
+ * 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_RESTORE_ALIGNMENT_FAULTS thus should
+ * only be called if the exception handler used PUSHFRAMEINSVC
+ * followed by ENABLE_ALIGNMENT_FAULTS.
+ */
+
+exception_exit:
+ DO_AST_AND_RESTORE_ALIGNMENT_FAULTS
+ PULLFRAMEFROMSVCANDEXIT
+
+/*
+ * undefined_entry:
+ *
+ * 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)
+#ifdef IPKDB
+/*
+ * IPKDB must be hooked in at the earliest possible entry point.
+ *
+ */
+/*
+ * Make room for all registers saving real r0-r7 and r15.
+ * The remaining registers are updated later.
+ */
+ stmfd sp!, {r0,r1} /* psr & spsr */
+ stmfd sp!, {lr} /* pc */
+ stmfd sp!, {r0-r14} /* r0-r7, r8-r14 */
+/*
+ * Get previous psr.
+ */
+ mrs r7, cpsr_all
+ mrs r0, spsr_all
+ str r0, [sp, #(16*4)]
+/*
+ * Test for user mode.
+ */
+ tst r0, #0xf
+ bne .Lprenotuser_push
+ add r1, sp, #(8*4)
+ stmia r1,{r8-r14}^ /* store user mode r8-r14*/
+ b .Lgoipkdb
+/*
+ * Switch to previous mode to get r8-r13.
+ */
+.Lprenotuser_push:
+ orr r0, r0, #(I32_bit) /* disable interrupts */
+ msr cpsr_all, r0
+ mov r1, r8
+ mov r2, r9
+ mov r3, r10
+ mov r4, r11
+ mov r5, r12
+ mov r6, r13
+ msr cpsr_all, r7 /* back to undefined mode */
+ add r8, sp, #(8*4)
+ stmia r8, {r1-r6} /* r8-r13 */
+/*
+ * Now back to previous mode to get r14 and spsr.
+ */
+ msr cpsr_all, r0
+ mov r1, r14
+ mrs r2, spsr
+ msr cpsr_all, r7 /* back to undefined mode */
+ str r1, [sp, #(14*4)] /* r14 */
+ str r2, [sp, #(17*4)] /* spsr */
+/*
+ * Now to IPKDB.
+ */
+.Lgoipkdb:
+ mov r0, sp
+ bl _C_LABEL(ipkdb_trap_glue)
+ ldr r1, .Lipkdb_trap_return
+ str r0,[r1]
+
+/*
+ * Have to load all registers from the stack.
+ *
+ * Start with spsr and pc.
+ */
+ ldr r0, [sp, #(16*4)] /* spsr */
+ ldr r1, [sp, #(15*4)] /* r15 */
+ msr spsr_all, r0
+ mov r14, r1
+/*
+ * Test for user mode.
+ */
+ tst r0, #0xf
+ bne .Lprenotuser_pull
+ add r1, sp, #(8*4)
+ ldmia r1, {r8-r14}^ /* load user mode r8-r14 */
+ b .Lpull_r0r7
+.Lprenotuser_pull:
+/*
+ * Now previous mode spsr and r14.
+ */
+ ldr r1, [sp, #(17*4)] /* spsr */
+ ldr r2, [sp, #(14*4)] /* r14 */
+ orr r0, r0, #(I32_bit)
+ msr cpsr_all, r0 /* switch to previous mode */
+ msr spsr_all, r1
+ mov r14, r2
+ msr cpsr_all, r7 /* back to undefined mode */
+/*
+ * Now r8-r13.
+ */
+ add r8, sp, #(8*4)
+ ldmia r8, {r1-r6} /* r8-r13 */
+ msr cpsr_all, r0
+ mov r8, r1
+ mov r9, r2
+ mov r10, r3
+ mov r11, r4
+ mov r12, r5
+ mov r13, r6
+ msr cpsr_all, r7
+.Lpull_r0r7:
+/*
+ * Now the rest of the registers.
+ */
+ ldr r1,Lipkdb_trap_return
+ ldr r0,[r1]
+ tst r0,r0
+ ldmfd sp!, {r0-r7} /* r0-r7 */
+ add sp, sp, #(10*4) /* adjust sp */
+
+/*
+ * Did IPKDB handle it?
+ */
+ movnes pc, lr /* return */
+
+#endif
+ stmfd sp!, {r0, r1}
+ ldr r0, Lundefined_handler_indirection
+ ldr r1, [sp], #0x0004
+ str r1, [r0, #0x0000]
+ ldr r1, [sp], #0x0004
+ str r1, [r0, #0x0004]
+ ldmia r0, {r0, r1, pc}
+
+#ifdef IPKDB
+Lipkdb_trap_return:
+ .word Lipkdb_trap_return_data
+#endif
+
+Lundefined_handler_indirection:
+ .word Lundefined_handler_indirection_data
+
+/*
+ * assembly bounce code for calling the kernel
+ * undefined instruction handler. This uses
+ * a standard trap frame and is called in SVC mode.
+ */
+
+ENTRY_NP(undefinedinstruction_bounce)
+ PUSHFRAMEINSVC
+ ENABLE_ALIGNMENT_FAULTS
+
+ mov r0, sp
+ adr lr, exception_exit
+ b _C_LABEL(undefinedinstruction)
+
+ .data
+ .align 0
+
+#ifdef IPKDB
+Lipkdb_trap_return_data:
+ .word 0
+#endif
+
+/*
+ * Indirection data
+ * 2 words use for preserving r0 and r1
+ * 3rd word contains the undefined handler address.
+ */
+
+Lundefined_handler_indirection_data:
+ .word 0
+ .word 0
+
+ .global _C_LABEL(undefined_handler_address)
+_C_LABEL(undefined_handler_address):
+ .word _C_LABEL(undefinedinstruction_bounce)
OpenPOWER on IntegriCloud