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