xref: /haiku/src/system/kernel/arch/arm/arch_exceptions.S (revision 6f80a9801fedbe7355c4360bd204ba746ec3ec2d)
1/*
2 * Copyright 2012-2022, Haiku Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 *		Ithamar R. Adema <ithamar@upgrade-android.com>
7 *
8 */
9
10#include <asm_defs.h>
11
12#define CPSR_MODE_MASK	0x1f
13#define CPSR_MODE_USR	0x10
14#define CPSR_MODE_FIQ	0x11
15#define CPSR_MODE_IRQ	0x12
16#define CPSR_MODE_SVC	0x13
17#define CPSR_MODE_ABT	0x17
18#define CPSR_MODE_UND	0x1b
19
20/* The following two macros are taken from FreeBSD... */
21
22.macro PUSHFRAMEINSVC
23	stmdb	sp, {r0-r3}					/* Save 4 registers */
24	mov		r0, lr						/* Save xxx32 r14 */
25	mov		r1, sp						/* Save xxx32 sp */
26	mrs		r3, spsr					/* Save xxx32 spsr */
27	mrs		r2, cpsr					/* Get the CPSR */
28	bic		r2, r2, #(CPSR_MODE_MASK)	/* Fix for SVC mode */
29	orr		r2, r2, #(CPSR_MODE_SVC)
30	msr		cpsr_c, r2					/* Punch into SVC mode */
31	mov		r2, sp						/* Save SVC sp */
32	str		r0, [sp, #-4]!				/* Push return address */
33	str		lr, [sp, #-4]!				/* Push SVC lr */
34	str		r2, [sp, #-4]!				/* Push SVC sp */
35	msr		spsr, r3					/* Restore correct spsr */
36	ldmdb	r1, {r0-r3}					/* Restore 4 regs from xxx mode */
37	sub		sp, sp, #(4*15)				/* Adjust the stack pointer */
38	stmia	sp, {r0-r12}				/* Push the user mode registers */
39	add		r0, sp, #(4*13)				/* Adjust the stack pointer */
40	stmia	r0, {r13-r14}^				/* Push the user mode registers */
41	mov		r0, r0						/* NOP for previous instruction */
42	mrs		r0, spsr
43	str		r0, [sp, #-4]!				/* Save spsr */
44.endm
45
46.macro PULLFRAMEFROMSVCANDEXIT
47	ldr		r0, [sp], #0x0004			/* Get the SPSR from stack */
48	msr		spsr, r0					/* restore SPSR */
49	ldmia	sp, {r0-r14}^				/* Restore registers (usr mode) */
50	mov		r0, r0						/* NOP for previous instruction */
51	add		sp, sp, #(4*15)				/* Adjust the stack pointer */
52	ldmia	sp, {sp, lr, pc}^			/* Restore lr and exit */
53.endm
54
55/* The following two macros are adapted from the two macros above, taken from FreeBSD. */
56
57.macro	PUSHFRAMEINSWI
58	str		lr, [sp, #-4]!				/* Push the return address */
59	sub		sp, sp, #(4*17)				/* Adjust the stack pointer */
60	stmia	sp, {r0-r12}				/* Store the general purpose registers */
61	add		r0, sp, #(4*13)				/* Adjust the stack pointer */
62	stmia	r0, {r13-r14}^				/* Store the user mode sp and lr registers */
63	mrs		r0, spsr					/* Store the SPSR */
64	str		r0, [sp, #-4]!
65	mov		r0, #0						/* Fill in svc mode sp and lr with zeroes */
66	str		r0, [sp, #(4*16)]
67	str		r0, [sp, #(4*17)]
68.endm
69
70.macro	PULLFRAMEINSWIANDEXIT
71	ldr		r0, [sp], #4				/* Get SPSR from stack */
72	msr		spsr, r0
73	ldmia	sp, {r0-r14}^				/* Restore user mode registers */
74	add		sp, sp, #(4*17)				/* Adjust the stack pointer */
75	ldr		lr, [sp], #4				/* Pull the return address */
76	movs	pc, lr						/* Return to user mode */
77.endm
78
79.text
80
81.globl _vectors_start
82_vectors_start:
83	ldr		pc, _arm_reset
84	ldr		pc, _arm_undefined
85	ldr		pc, _arm_syscall
86	ldr		pc, _arm_prefetch_abort
87	ldr		pc, _arm_data_abort
88	ldr		pc, _arm_reserved
89	ldr		pc, _arm_irq
90	ldr		pc, _arm_fiq
91
92
93_arm_reset:
94	.word	arm_reserved // actually reset, but not used when mapped
95
96_arm_undefined:
97	.word	arm_undefined
98
99_arm_syscall:
100	.word	arm_syscall
101
102_arm_prefetch_abort:
103	.word	arm_prefetch_abort
104
105_arm_data_abort:
106	.word	arm_data_abort
107
108_arm_reserved:
109	.word	arm_reserved
110
111_arm_irq:
112	.word	arm_irq
113
114_arm_fiq:
115	.word	arm_fiq
116
117
118.globl _vectors_end
119_vectors_end:
120
121.data
122
123	.rept	64
124	.word	0xdeadbeef
125	.endr
126
127abort_stack:
128	.word	. - 4
129	.word	0xdeadbeef
130
131	.rept	64
132	.word	0xcafebabe
133	.endr
134
135irq_stack:
136	.word	. - 4
137	.word	0xcafebabe
138
139	.rept	64
140	.word	0xaaaabbbb
141	.endr
142
143fiq_stack:
144	.word	. - 4
145	.word	0xaaaabbbb
146
147	.rept	64
148	.word	0xccccdddd
149	.endr
150
151und_stack:
152	.word	. - 4
153	.word	0xccccdddd
154
155.text
156
157FUNCTION(arm_undefined):
158	PUSHFRAMEINSVC
159
160	mov	r0, sp
161	bl	arch_arm_undefined
162
163	PULLFRAMEFROMSVCANDEXIT
164FUNCTION_END(arm_undefined)
165
166
167FUNCTION(arm_syscall):
168	PUSHFRAMEINSWI
169
170	mov	r0, sp
171	bl	arch_arm_syscall
172
173	PULLFRAMEINSWIANDEXIT
174FUNCTION_END(arm_syscall)
175
176
177FUNCTION(arm_prefetch_abort):
178#ifdef __XSCALE__
179	nop					/* Make absolutely sure any pending */
180	nop					/* imprecise aborts have occurred. */
181#endif
182	sub	lr, lr, #4
183	PUSHFRAMEINSVC
184
185	mov	r0, sp
186	bl	arch_arm_prefetch_abort
187
188	PULLFRAMEFROMSVCANDEXIT
189FUNCTION_END(arm_prefetch_abort)
190
191
192FUNCTION(arm_data_abort):
193#ifdef __XSCALE__
194	nop					/* Make absolutely sure any pending */
195	nop					/* imprecise aborts have occurred. */
196#endif
197	sub	lr, lr, #8		/* Adjust the lr */
198	PUSHFRAMEINSVC
199
200	mov	r0, sp
201	bl	arch_arm_data_abort
202
203	PULLFRAMEFROMSVCANDEXIT
204FUNCTION_END(arm_data_abort)
205
206
207FUNCTION(arm_reserved):
208	b	.
209FUNCTION_END(arm_reserved)
210
211
212FUNCTION(arm_irq):
213	sub	lr, lr, #4
214	PUSHFRAMEINSVC
215
216	mov	r0, sp			/* iframe */
217	bl	arch_arm_irq
218
219	PULLFRAMEFROMSVCANDEXIT
220FUNCTION_END(arm_irq)
221
222
223FUNCTION(arm_fiq):
224	sub	lr, lr, #4
225	PUSHFRAMEINSVC
226
227	mov	r0, sp			/* iframe */
228	bl	arch_arm_fiq
229
230	PULLFRAMEFROMSVCANDEXIT
231FUNCTION_END(arm_fiq)
232
233
234
235FUNCTION(arm_vector_init):
236	mrs	r1, cpsr
237	bic	r1, r1, #CPSR_MODE_MASK
238
239	/* move into modes and set initial sp */
240	mov	r0, r1
241	orr	r0, r0, #CPSR_MODE_FIQ
242	msr	cpsr_c, r0
243	ldr r2, =fiq_stack
244	ldr sp, [r2]
245
246	mov	r0, r1
247	orr	r0, r0, #CPSR_MODE_IRQ
248	msr	cpsr_c, r0
249	ldr r2, =irq_stack
250	ldr sp, [r2]
251
252	mov	r0, r1
253	orr	r0, r0, #CPSR_MODE_ABT
254	msr	cpsr_c, r0
255	ldr r2, =abort_stack
256	ldr sp, [r2]
257
258	mov	r0, r1
259	orr	r0, r0, #CPSR_MODE_UND
260	msr	cpsr_c, r0
261	ldr r2, =und_stack
262	ldr sp, [r2]
263
264	/* ... and return back to supervisor mode */
265	mov	r0, r1
266	orr	r0, r0, #CPSR_MODE_SVC
267	msr	cpsr_c, r0
268
269	bx	lr
270FUNCTION_END(arm_vector_init)
271