xref: /kvm-unit-tests/arm/cstart.S (revision 4363f1d9a646a5c7ea673bee8fc33ca6f2cddbd8)
1/*
2 * Boot entry point and assembler functions for armv7 tests.
3 *
4 * Copyright (C) 2014, Red Hat Inc, Andrew Jones <drjones@redhat.com>
5 *
6 * This work is licensed under the terms of the GNU LGPL, version 2.
7 */
8#define __ASSEMBLY__
9#include <asm/thread_info.h>
10#include <asm/asm-offsets.h>
11#include <asm/ptrace.h>
12#include <asm/sysreg.h>
13
14#define THREAD_START_SP ((THREAD_SIZE - S_FRAME_SIZE * 8) & ~7)
15
16.arm
17
18.section .init
19
20.globl start
21start:
22	/*
23	 * set stack, making room at top of stack for cpu0's
24	 * exception stacks. Must start wtih stackptr, not
25	 * stacktop, so the thread size masking (shifts) work.
26	 */
27	ldr	sp, =stackptr
28	lsr	sp, #THREAD_SHIFT
29	lsl	sp, #THREAD_SHIFT
30	add	sp, #THREAD_START_SP
31
32	/*
33	 * save sp before pushing anything on the stack
34	 * lr makes a good temp register right now
35	 */
36	mov	lr, sp
37
38	/*
39	 * bootloader params are in r0-r2
40	 * See the kernel doc Documentation/arm/Booting
41	 *   r0 = 0
42	 *   r1 = machine type number
43	 *   r2 = physical address of the dtb
44	 *
45	 * As we have no need for r0's nor r1's value, then
46	 * put the dtb in r0. This allows setup to be consistent
47	 * with arm64.
48	 */
49	mov	r0, r2
50	push	{r0-r1}
51
52	/* set up vector table and mode stacks */
53	mov	r0, lr			@ lr is stack top (see above),
54					@ which is the exception stacks base
55	bl	exceptions_init
56
57	/* complete setup */
58	pop	{r0-r1}
59	bl	setup
60
61	/* run the test */
62	ldr	r0, =__argc
63	ldr	r0, [r0]
64	ldr	r1, =__argv
65	ldr	r2, =__environ
66	bl	main
67	bl	exit
68	b	halt
69
70
71.macro set_mode_stack mode, stack
72	add	\stack, #S_FRAME_SIZE
73	msr	cpsr_c, #(\mode | PSR_I_BIT | PSR_F_BIT)
74	isb
75	mov	sp, \stack
76.endm
77
78exceptions_init:
79	mrc	p15, 0, r2, c1, c0, 0	@ read SCTLR
80	bic	r2, #CR_V		@ SCTLR.V := 0
81	mcr	p15, 0, r2, c1, c0, 0	@ write SCTLR
82	ldr	r2, =vector_table
83	mcr	p15, 0, r2, c12, c0, 0	@ write VBAR
84
85	mrs	r2, cpsr
86
87	/* first frame reserved for svc mode */
88	set_mode_stack	UND_MODE, r0
89	set_mode_stack	ABT_MODE, r0
90	set_mode_stack	IRQ_MODE, r0
91	set_mode_stack	FIQ_MODE, r0
92
93	msr	cpsr_cxsf, r2		@ back to svc mode
94	isb
95	mov	pc, lr
96
97.text
98
99.global secondary_entry
100secondary_entry:
101	/* enable the MMU */
102	mov	r1, #0
103	ldr	r0, =mmu_idmap
104	ldr	r0, [r0]
105	bl	asm_mmu_enable
106
107	/*
108	 * Set the stack, and set up vector table
109	 * and exception stacks. Exception stacks
110	 * space starts at stack top and grows up.
111	 */
112	ldr	r1, =secondary_data
113	ldr	r0, [r1]
114	mov	sp, r0
115	bl	exceptions_init
116
117	/* finish init in C code */
118	bl	secondary_cinit
119
120	/* r0 is now the entry function, run it */
121	blx	r0
122	b	do_idle
123
124.globl halt
125halt:
1261:	wfi
127	b	1b
128
129/*
130 * asm_mmu_enable
131 *   Inputs:
132 *     (r0 - lo, r1 - hi) is the base address of the translation table
133 *   Outputs: none
134 */
135.equ	PRRR,	0xeeaa4400		@ MAIR0 (from Linux kernel)
136.equ	NMRR,	0xff000004		@ MAIR1 (from Linux kernel)
137.globl asm_mmu_enable
138asm_mmu_enable:
139	/* TTBCR */
140	mrc	p15, 0, r2, c2, c0, 2
141	orr	r2, #(1 << 31)		@ TTB_EAE
142	mcr	p15, 0, r2, c2, c0, 2
143
144	/* MAIR */
145	ldr	r2, =PRRR
146	mcr	p15, 0, r2, c10, c2, 0
147	ldr	r2, =NMRR
148	mcr	p15, 0, r2, c10, c2, 1
149
150	/* TTBR0 */
151	mcrr	p15, 0, r0, r1, c2
152	isb
153
154	/* SCTLR */
155	mrc	p15, 0, r2, c1, c0, 0
156	orr	r2, #CR_C
157	orr	r2, #CR_I
158	orr	r2, #CR_M
159	mcr	p15, 0, r2, c1, c0, 0
160	isb
161
162	mov     pc, lr
163
164.globl asm_mmu_disable
165asm_mmu_disable:
166	/* SCTLR */
167	mrc	p15, 0, r0, c1, c0, 0
168	bic	r0, #CR_M
169	mcr	p15, 0, r0, c1, c0, 0
170	isb
171	mov     pc, lr
172
173/*
174 * Vector stubs
175 * Simplified version of the Linux kernel implementation
176 *   arch/arm/kernel/entry-armv.S
177 *
178 * Each mode has an S_FRAME_SIZE sized memory region,
179 * and the mode's stack pointer has been initialized
180 * to the base of that region in exceptions_init.
181 */
182.macro vector_stub, name, vec, mode, correction=0
183.align 5
184vector_\name:
185.if \correction
186	sub	lr, lr, #\correction
187.endif
188	/*
189	 * Save r0, r1, lr_<exception> (parent PC)
190	 * and spsr_<exception> (parent CPSR)
191	 */
192	str	r0, [sp, #S_R0]
193	str	r1, [sp, #S_R1]
194	str	lr, [sp, #S_PC]
195	mrs	r0, spsr
196	str	r0, [sp, #S_PSR]
197
198	/* Prepare for SVC32 mode. */
199	mrs	r0, cpsr
200	bic	r0, #MODE_MASK
201	orr	r0, #SVC_MODE
202	msr	spsr_cxsf, r0
203
204	/* Branch to handler in SVC mode */
205	mov	r0, #\vec
206	mov	r1, sp
207	ldr	lr, =vector_common
208	movs	pc, lr
209.endm
210
211vector_stub 	rst,	0, UND_MODE
212vector_stub	und,	1, UND_MODE
213vector_stub	pabt,	3, ABT_MODE, 4
214vector_stub	dabt,	4, ABT_MODE, 8
215vector_stub	irq,	6, IRQ_MODE, 4
216vector_stub	fiq,	7, FIQ_MODE, 4
217
218.align 5
219vector_svc:
220	/*
221	 * Save r0, r1, lr_<exception> (parent PC)
222	 * and spsr_<exception> (parent CPSR)
223	 */
224	push	{ r1 }
225	lsr	r1, sp, #THREAD_SHIFT
226	lsl	r1, #THREAD_SHIFT
227	add	r1, #THREAD_START_SP
228	str	r0, [r1, #S_R0]
229	pop	{ r0 }
230	str	r0, [r1, #S_R1]
231	str	lr, [r1, #S_PC]
232	mrs	r0, spsr
233	str	r0, [r1, #S_PSR]
234
235	/*
236	 * Branch to handler, still in SVC mode.
237	 * r0 := 2 is the svc vector number.
238	 */
239	mov	r0, #2
240	ldr	lr, =vector_common
241	mov	pc, lr
242
243vector_common:
244	/* make room for pt_regs */
245	sub	sp, #S_FRAME_SIZE
246	tst	sp, #4			@ check stack alignment
247	subne	sp, #4
248
249	/* store registers r0-r12 */
250	stmia	sp, { r0-r12 }		@ stored wrong r0 and r1, fix later
251
252	/* get registers saved in the stub */
253	ldr	r2, [r1, #S_R0]		@ r0
254	ldr	r3, [r1, #S_R1]		@ r1
255	ldr	r4, [r1, #S_PC] 	@ lr_<exception> (parent PC)
256	ldr	r5, [r1, #S_PSR]	@ spsr_<exception> (parent CPSR)
257
258	/* fix r0 and r1 */
259	str	r2, [sp, #S_R0]
260	str	r3, [sp, #S_R1]
261
262	/* store sp_svc, if we were in usr mode we'll fix this later */
263	add	r6, sp, #S_FRAME_SIZE
264	addne	r6, #4			@ stack wasn't aligned
265	str	r6, [sp, #S_SP]
266
267	str	lr, [sp, #S_LR]		@ store lr_svc, fix later for usr mode
268	str	r4, [sp, #S_PC]		@ store lr_<exception>
269	str	r5, [sp, #S_PSR]	@ store spsr_<exception>
270
271	/* set ORIG_r0 */
272	mov	r2, #-1
273	str	r2, [sp, #S_OLD_R0]
274
275	/* if we were in usr mode then we need sp_usr and lr_usr instead */
276	and	r1, r5, #MODE_MASK
277	cmp	r1, #USR_MODE
278	bne	1f
279	add	r1, sp, #S_SP
280	stmia	r1, { sp,lr }^
281
282	/* Call the handler. r0 is the vector number, r1 := pt_regs */
2831:	mov	r1, sp
284	bl	do_handle_exception
285
286	/*
287	 * make sure we restore sp_svc on mode change. No need to
288	 * worry about lr_svc though, as that gets clobbered on
289	 * exception entry anyway.
290	 */
291	str	r6, [sp, #S_SP]
292
293	/* return from exception */
294	msr	spsr_cxsf, r5
295	ldmia	sp, { r0-pc }^
296
297.align 5
298vector_addrexcptn:
299	b	vector_addrexcptn
300
301.section .text.ex
302.align 5
303vector_table:
304	b	vector_rst
305	b	vector_und
306	b	vector_svc
307	b	vector_pabt
308	b	vector_dabt
309	b	vector_addrexcptn	@ should never happen
310	b	vector_irq
311	b	vector_fiq
312