xref: /kvm-unit-tests/powerpc/cstart64.S (revision 56fb1494500b1ef61ed097acfd4e204b9d4857b7)
1/*
2 * Entry point and assembler functions for ppc64 tests.
3 *
4 * Copyright (C) 2016, 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/hcall.h>
10#include <asm/ppc_asm.h>
11#include <asm/rtas.h>
12#include <asm/ptrace.h>
13
14#include "spapr.h"
15
16#define P_HANDLER	0x2ff8
17
18.section .init
19
20/*
21 * start is the entry point. r3 points to the DTB
22 */
23.globl start
24start:
25	FIXUP_ENDIAN
26	/* Switch to 64-bit mode */
27	mfmsr	r1
28	li	r2,1
29	sldi	r2,r2,MSR_SF_BIT
30	or	r1,r1,r2
31	mtmsrd	r1
32	/*
33	 * We were loaded at QEMU's kernel load address, but we're not
34	 * allowed to link there due to how QEMU deals with linker VMAs,
35	 * so we just linked at zero. This means the first thing to do is
36	 * to find our stack and toc, and then do a relocate.
37	 */
38	LOAD_REG_IMMEDIATE(r31, SPAPR_KERNEL_LOAD_ADDR)
39	ld	r1, (p_stack - start)(r31)
40	ld	r2, (p_toc - start)(r31)
41	add	r1, r1, r31
42	add	r2, r2, r31
43
44	/* save DTB pointer */
45	std	r3, 56(r1)
46
47	/*
48	 * Call relocate. relocate is C code, but careful to not use
49	 * any global references, as they may use absolute addresses,
50	 * which are, obviously, not yet relocated.
51	 */
52	mr	r3, r31
53	ld	r4, (p_dyn - start)(r31)
54	add	r4, r4, r31
55	bl	relocate
56
57	/* compute address of call_handler */
58
59	LOAD_REG_ADDR(r4, call_handler)
60	std	r4, P_HANDLER(0)
61
62	/* relocate vector table to base address 0x0 (MSR_IP = 0) */
63
64	/* source: r4, dest end: r5, destination: r6 */
65
66	LOAD_REG_ADDR(r4, __start_interrupts)
67	LOAD_REG_ADDR(r5, __end_interrupts)
68	sub	r5,r5,r4
69	li	r6,0x100
70
71	sub	r4,r4,r6
72	add	r5,r5,r6
73	addi	r6,r6,-8
742:	li	r0,8
75	mtctr	r0
76	/* copy a cache line size */
773:	addi	r6,r6,8
78	ldx	r0,r6,r4
79	stdx	r0,0,r6
80	bdnz	3b
81	dcbst	0,r6
82	/* flush icache */
83	sync
84	icbi	0,r6
85	cmpld	0,r6,r5
86	blt	2b
87	sync
88	isync
89
90	/* patch sc1 if needed */
91	bl	hcall_have_broken_sc1
92	cmpwi	r3, 0
93	beq	1f
94	LOAD_REG_ADDR(r3, hcall)
95	LOAD_REG_IMMEDIATE(r4, SC1_REPLACEMENT)
96	stw	r4, 0(r3)
97
98	/* complete setup */
991:	ld	r3, 56(r1)
100	bl	setup
101
102	/* run the test */
103	LOAD_REG_ADDR(r3, __argc)
104	LOAD_REG_ADDR(r4, __argv)
105	LOAD_REG_ADDR(r5, __environ)
106	lwz	r3, 0(r3)
107	bl	main
108	bl	exit
109	b	halt
110
111.align 3
112p_stack:	.llong  stackptr
113p_toc:		.llong  tocptr
114p_dyn:		.llong  dynamic_start
115
116.text
117.align 3
118
119.globl hcall
120hcall:
121	sc	1
122	blr
123
124.globl halt
125halt:
1261:	b	1b
127
128.globl enter_rtas
129enter_rtas:
130	LOAD_REG_ADDR(r11, rtas_entry)
131	ld	r10, 0(r11)
132
133	cmpdi	r10,0
134	bne	external_rtas
135
136	/* Use H_RTAS directly */
137	mr	r4,r3
138	lis	r3,KVMPPC_H_RTAS@h
139	ori	r3,r3,KVMPPC_H_RTAS@l
140	b	hcall
141
142external_rtas:
143	/* Use external RTAS blob */
144	mflr	r0
145	std	r0, 16(r1)
146
147	LOAD_REG_ADDR(r11, rtas_return_loc)
148	mtlr	r11
149
150	mfmsr	r11
151	LOAD_REG_IMMEDIATE(r9, RTAS_MSR_MASK)
152	and	r11, r11, r9
153	mtsrr0	r10
154	mtsrr1	r11
155	rfid
156	b       .
157
158rtas_return_loc:
159	FIXUP_ENDIAN
160	ld	r0, 16(r1)
161	mtlr	r0
162	blr
163
164call_handler:
165	/* save context */
166
167	/* GPRs */
168
169	.irp i, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 \
170	        17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
171		SAVE_GPR(\i, r1)
172	.endr
173	mfsprg1	r0
174	std	r0,GPR1(r1)
175
176	/* lr, xer, ccr */
177
178	mflr	r0
179	std	r0,_LINK(r1)
180
181	mfxer	r0
182	std	r0,_XER(r1)
183
184	mfcr	r0
185	std	r0,_CCR(r1)
186
187	/* restore TOC pointer */
188
189	LOAD_REG_IMMEDIATE(r31, SPAPR_KERNEL_LOAD_ADDR)
190	ld	r2, (p_toc - start)(r31)
191
192	/* FIXME: build stack frame */
193
194	/* call generic handler */
195
196	addi	r3,r1,STACK_FRAME_OVERHEAD
197	bl	do_handle_exception
198
199	/* restore context */
200
201	ld	r0,_CTR(r1)
202	mtctr	r0
203
204	ld	r0,_LINK(r1)
205	mtlr	r0
206
207	ld	r0,_XER(r1)
208	mtxer	r0
209
210	ld	r0,_CCR(r1)
211	mtcr	r0
212
213	ld	r0, _NIP(r1)
214	mtsrr0	r0
215
216	ld	r0, _MSR(r1)
217	mtsrr1	r0
218
219	.irp i, 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 \
220	        17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
221		REST_GPR(\i, r1)
222	.endr
223
224	/* restore r1, as we don't need it anymore */
225
226	REST_GPR(1,r1)
227
228	rfid
229	b .
230
231.section .text.ex
232
233/* [H]VECTOR must not be more than 8 instructions to fit in 0x20 vectors */
234.macro VECTOR vec
235	. = \vec
236
237	mtsprg1	r1	/* save r1 */
238	mfsprg0	r1	/* get exception stack address */
239	subi	r1,r1, INT_FRAME_SIZE
240
241	/* save r0 and ctr to call generic handler */
242	SAVE_GPR(0,r1)
243
244	li	r0,\vec
245	std	r0,_TRAP(r1)
246
247	b	handler_trampoline
248.endm
249
250.macro HVECTOR vec
251	. = \vec
252
253	mtsprg1	r1	/* save r1 */
254	mfsprg0	r1	/* get exception stack address */
255	subi	r1,r1, INT_FRAME_SIZE
256
257	/* save r0 and ctr to call generic handler */
258	SAVE_GPR(0,r1)
259
260	li	r0,\vec
261	std	r0,_TRAP(r1)
262
263	b	handler_htrampoline
264.endm
265
266	. = 0x100
267	.globl __start_interrupts
268__start_interrupts:
269
270VECTOR(0x100)
271VECTOR(0x200)
272VECTOR(0x300)
273VECTOR(0x380)
274VECTOR(0x400)
275VECTOR(0x480)
276VECTOR(0x500)
277VECTOR(0x600)
278VECTOR(0x700)
279VECTOR(0x800)
280VECTOR(0x900)
281HVECTOR(0x980)
282VECTOR(0xa00)
283VECTOR(0xc00)
284VECTOR(0xd00)
285HVECTOR(0xe00)
286HVECTOR(0xe20)
287HVECTOR(0xe40)
288HVECTOR(0xe60)
289HVECTOR(0xe80)
290HVECTOR(0xea0)
291VECTOR(0xf00)
292VECTOR(0xf20)
293VECTOR(0xf40)
294VECTOR(0xf60)
295HVECTOR(0xf80)
296
297handler_trampoline:
298	mfctr	r0
299	std	r0,_CTR(r1)
300
301	ld	r0, P_HANDLER(0)
302	mtctr	r0
303
304	/* nip and msr */
305	mfsrr0	r0
306	std	r0, _NIP(r1)
307
308	mfsrr1	r0
309	std	r0, _MSR(r1)
310
311	bctr
312
313handler_htrampoline:
314	mfctr	r0
315	std	r0,_CTR(r1)
316
317	ld	r0, P_HANDLER(0)
318	mtctr	r0
319
320	/* nip and msr */
321	mfspr	r0, SPR_HSRR0
322	std	r0, _NIP(r1)
323
324	mfspr	r0, SPR_HSRR1
325	std	r0, _MSR(r1)
326
327	bctr
328
329	.align 7
330	.globl __end_interrupts
331__end_interrupts:
332	.org	P_HANDLER
333	.llong	0
334