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