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