xref: /kvm-unit-tests/arm/cstart.S (revision 0f7d6d6e74497e57ff3ec1a6a16850c845cb40bf)
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, =stackptr
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 memory region,
125 * and the mode's stack pointer has been initialized
126 * to the base of that region in exceptions_init.
127 */
128.macro vector_stub, name, vec, mode, correction=0
129.align 5
130vector_\name:
131.if \correction
132	sub	lr, lr, #\correction
133.endif
134	/*
135	 * Save r0, r1, lr_<exception> (parent PC)
136	 * and spsr_<exception> (parent CPSR)
137	 */
138	str	r0, [sp, #S_R0]
139	str	r1, [sp, #S_R1]
140	str	lr, [sp, #S_PC]
141	mrs	r0, spsr
142	str	r0, [sp, #S_PSR]
143
144	/* Prepare for SVC32 mode. */
145	mrs	r0, cpsr
146	bic	r0, #MODE_MASK
147	orr	r0, #SVC_MODE
148	msr	spsr_cxsf, r0
149
150	/* Branch to handler in SVC mode */
151	mov	r0, #\vec
152	mov	r1, sp
153	ldr	lr, =vector_common
154	movs	pc, lr
155.endm
156
157vector_stub 	rst,	0, UND_MODE
158vector_stub	und,	1, UND_MODE
159vector_stub	pabt,	3, ABT_MODE, 4
160vector_stub	dabt,	4, ABT_MODE, 8
161vector_stub	irq,	6, IRQ_MODE, 4
162vector_stub	fiq,	7, FIQ_MODE, 4
163
164.align 5
165vector_svc:
166	/*
167	 * Save r0, r1, lr_<exception> (parent PC)
168	 * and spsr_<exception> (parent CPSR)
169	 */
170	push	{ r1 }
171	ldr	r1, =exception_stacks
172	str	r0, [r1, #S_R0]
173	pop	{ r0 }
174	str	r0, [r1, #S_R1]
175	str	lr, [r1, #S_PC]
176	mrs	r0, spsr
177	str	r0, [r1, #S_PSR]
178
179	/*
180	 * Branch to handler, still in SVC mode.
181	 * r0 := 2 is the svc vector number.
182	 */
183	mov	r0, #2
184	ldr	lr, =vector_common
185	mov	pc, lr
186
187vector_common:
188	/* make room for pt_regs */
189	sub	sp, #S_FRAME_SIZE
190	tst	sp, #4			@ check stack alignment
191	subne	sp, #4
192
193	/* store registers r0-r12 */
194	stmia	sp, { r0-r12 }		@ stored wrong r0 and r1, fix later
195
196	/* get registers saved in the stub */
197	ldr	r2, [r1, #S_R0]		@ r0
198	ldr	r3, [r1, #S_R1]		@ r1
199	ldr	r4, [r1, #S_PC] 	@ lr_<exception> (parent PC)
200	ldr	r5, [r1, #S_PSR]	@ spsr_<exception> (parent CPSR)
201
202	/* fix r0 and r1 */
203	str	r2, [sp, #S_R0]
204	str	r3, [sp, #S_R1]
205
206	/* store sp_svc, if we were in usr mode we'll fix this later */
207	add	r6, sp, #S_FRAME_SIZE
208	addne	r6, #4			@ stack wasn't aligned
209	str	r6, [sp, #S_SP]
210
211	str	lr, [sp, #S_LR]		@ store lr_svc, fix later for usr mode
212	str	r4, [sp, #S_PC]		@ store lr_<exception>
213	str	r5, [sp, #S_PSR]	@ store spsr_<exception>
214
215	/* set ORIG_r0 */
216	mov	r2, #-1
217	str	r2, [sp, #S_OLD_R0]
218
219	/* if we were in usr mode then we need sp_usr and lr_usr instead */
220	and	r1, r5, #MODE_MASK
221	cmp	r1, #USR_MODE
222	bne	1f
223	add	r1, sp, #S_SP
224	stmia	r1, { sp,lr }^
225
226	/* Call the handler. r0 is the vector number, r1 := pt_regs */
2271:	mov	r1, sp
228	bl	do_handle_exception
229
230	/*
231	 * make sure we restore sp_svc on mode change. No need to
232	 * worry about lr_svc though, as that gets clobbered on
233	 * exception entry anyway.
234	 */
235	str	r6, [sp, #S_SP]
236
237	/* return from exception */
238	msr	spsr_cxsf, r5
239	ldmia	sp, { r0-pc }^
240
241.align 5
242vector_addrexcptn:
243	b	vector_addrexcptn
244
245.section .text.ex
246.align 5
247vector_table:
248	b	vector_rst
249	b	vector_und
250	b	vector_svc
251	b	vector_pabt
252	b	vector_dabt
253	b	vector_addrexcptn	@ should never happen
254	b	vector_irq
255	b	vector_fiq
256