xref: /kvm-unit-tests/arm/cstart.S (revision 1392497b5f01b734376e73ce9460413f7f9fe2d4)
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/asm-offsets.h>
10#include <asm/ptrace.h>
11#include <asm/cp15.h>
12
13.arm
14
15.section .init
16
17.globl start
18start:
19	/*
20	 * bootloader params are in r0-r2
21	 * See the kernel doc Documentation/arm/Booting
22	 *   r0 = 0
23	 *   r1 = machine type number
24	 *   r2 = physical address of the dtb
25	 *
26	 * As we have no need for r0's nor r1's value, then
27	 * put the dtb in r0. This allows setup to be consistent
28	 * with arm64.
29	 */
30	ldr	sp, =stacktop
31	mov	r0, r2
32	push	{r0-r1}
33
34	/* set up vector table and mode stacks */
35	bl	exceptions_init
36
37	/* complete setup */
38	pop	{r0-r1}
39	bl	setup
40
41	/* run the test */
42	ldr	r0, =__argc
43	ldr	r0, [r0]
44	ldr	r1, =__argv
45	bl	main
46	bl	exit
47	b	halt
48
49
50.macro set_mode_stack mode, stack
51	add	\stack, #S_FRAME_SIZE
52	msr	cpsr_c, #(\mode | PSR_I_BIT | PSR_F_BIT)
53	isb
54	mov	sp, \stack
55.endm
56
57exceptions_init:
58	mrc	p15, 0, r2, c1, c0, 0	@ read SCTLR
59	bic	r2, #CR_V		@ SCTLR.V := 0
60	mcr	p15, 0, r2, c1, c0, 0	@ write SCTLR
61	ldr	r2, =vector_table
62	mcr	p15, 0, r2, c12, c0, 0	@ write VBAR
63
64	mrs	r2, cpsr
65	ldr	r1, =exception_stacks
66
67	/* first frame reserved for svc mode */
68	set_mode_stack	UND_MODE, r1
69	set_mode_stack	ABT_MODE, r1
70	set_mode_stack	IRQ_MODE, r1
71	set_mode_stack	FIQ_MODE, r1
72
73	msr	cpsr_cxsf, r2		@ back to svc mode
74	isb
75	mov	pc, lr
76
77.text
78
79.globl halt
80halt:
811:	wfi
82	b	1b
83
84/*
85 * asm_mmu_enable
86 *   Inputs:
87 *     (r0 - lo, r1 - hi) is the base address of the translation table
88 *   Outputs: none
89 */
90.equ	PRRR,	0xeeaa4400		@ MAIR0 (from Linux kernel)
91.equ	NMRR,	0xff000004		@ MAIR1 (from Linux kernel)
92.globl asm_mmu_enable
93asm_mmu_enable:
94	/* TTBCR */
95	mrc	p15, 0, r2, c2, c0, 2
96	orr	r2, #(1 << 31)		@ TTB_EAE
97	mcr	p15, 0, r2, c2, c0, 2
98
99	/* MAIR */
100	ldr	r2, =PRRR
101	mcr	p15, 0, r2, c10, c2, 0
102	ldr	r2, =NMRR
103	mcr	p15, 0, r2, c10, c2, 1
104
105	/* TTBR0 */
106	mcrr	p15, 0, r0, r1, c2
107	isb
108
109	/* SCTLR */
110	mrc	p15, 0, r2, c1, c0, 0
111	orr	r2, #CR_C
112	orr	r2, #CR_I
113	orr	r2, #CR_M
114	mcr	p15, 0, r2, c1, c0, 0
115	isb
116
117	mov     pc, lr
118
119/*
120 * Vector stubs
121 * Simplified version of the Linux kernel implementation
122 *   arch/arm/kernel/entry-armv.S
123 *
124 * Each mode has an S_FRAME_SIZE sized stack initialized
125 * in exceptions_init
126 */
127.macro vector_stub, name, vec, mode, correction=0
128.align 5
129vector_\name:
130.if \correction
131	sub	lr, lr, #\correction
132.endif
133	/*
134	 * Save r0, r1, lr_<exception> (parent PC)
135	 * and spsr_<exception> (parent CPSR)
136	 */
137	str	r0, [sp, #S_R0]
138	str	r1, [sp, #S_R1]
139	str	lr, [sp, #S_PC]
140	mrs	r0, spsr
141	str	r0, [sp, #S_PSR]
142
143	/* Prepare for SVC32 mode. */
144	mrs	r0, cpsr
145	bic	r0, #MODE_MASK
146	orr	r0, #SVC_MODE
147	msr	spsr_cxsf, r0
148
149	/* Branch to handler in SVC mode */
150	mov	r0, #\vec
151	mov	r1, sp
152	ldr	lr, =vector_common
153	movs	pc, lr
154.endm
155
156vector_stub 	rst,	0, UND_MODE
157vector_stub	und,	1, UND_MODE
158vector_stub	pabt,	3, ABT_MODE, 4
159vector_stub	dabt,	4, ABT_MODE, 8
160vector_stub	irq,	6, IRQ_MODE, 4
161vector_stub	fiq,	7, FIQ_MODE, 4
162
163.align 5
164vector_svc:
165	/*
166	 * Save r0, r1, lr_<exception> (parent PC)
167	 * and spsr_<exception> (parent CPSR)
168	 */
169	push	{ r1 }
170	ldr	r1, =exception_stacks
171	str	r0, [r1, #S_R0]
172	pop	{ r0 }
173	str	r0, [r1, #S_R1]
174	str	lr, [r1, #S_PC]
175	mrs	r0, spsr
176	str	r0, [r1, #S_PSR]
177
178	/*
179	 * Branch to handler, still in SVC mode.
180	 * r0 := 2 is the svc vector number.
181	 */
182	mov	r0, #2
183	ldr	lr, =vector_common
184	mov	pc, lr
185
186vector_common:
187	/* make room for pt_regs */
188	sub	sp, #S_FRAME_SIZE
189	tst	sp, #4			@ check stack alignment
190	subne	sp, #4
191
192	/* store registers r0-r12 */
193	stmia	sp, { r0-r12 }		@ stored wrong r0 and r1, fix later
194
195	/* get registers saved in the stub */
196	ldr	r2, [r1, #S_R0]		@ r0
197	ldr	r3, [r1, #S_R1]		@ r1
198	ldr	r4, [r1, #S_PC] 	@ lr_<exception> (parent PC)
199	ldr	r5, [r1, #S_PSR]	@ spsr_<exception> (parent CPSR)
200
201	/* fix r0 and r1 */
202	str	r2, [sp, #S_R0]
203	str	r3, [sp, #S_R1]
204
205	/* store sp_svc, if we were in usr mode we'll fix this later */
206	add	r6, sp, #S_FRAME_SIZE
207	addne	r6, #4			@ stack wasn't aligned
208	str	r6, [sp, #S_SP]
209
210	str	lr, [sp, #S_LR]		@ store lr_svc, fix later for usr mode
211	str	r4, [sp, #S_PC]		@ store lr_<exception>
212	str	r5, [sp, #S_PSR]	@ store spsr_<exception>
213
214	/* set ORIG_r0 */
215	mov	r2, #-1
216	str	r2, [sp, #S_OLD_R0]
217
218	/* if we were in usr mode then we need sp_usr and lr_usr instead */
219	and	r1, r5, #MODE_MASK
220	cmp	r1, #USR_MODE
221	bne	1f
222	add	r1, sp, #S_SP
223	stmia	r1, { sp,lr }^
224
225	/* Call the handler. r0 is the vector number, r1 := pt_regs */
2261:	mov	r1, sp
227	bl	do_handle_exception
228
229	/*
230	 * make sure we restore sp_svc on mode change. No need to
231	 * worry about lr_svc though, as that gets clobbered on
232	 * exception entry anyway.
233	 */
234	str	r6, [sp, #S_SP]
235
236	/* return from exception */
237	msr	spsr_cxsf, r5
238	ldmia	sp, { r0-pc }^
239
240.align 5
241vector_addrexcptn:
242	b	vector_addrexcptn
243
244.section .text.ex
245.align 5
246vector_table:
247	b	vector_rst
248	b	vector_und
249	b	vector_svc
250	b	vector_pabt
251	b	vector_dabt
252	b	vector_addrexcptn	@ should never happen
253	b	vector_irq
254	b	vector_fiq
255