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