xref: /kvm-unit-tests/powerpc/cstart64.S (revision 6163f75d09a0a96a5c3db82dd768b13f79629c00)
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	/*
27	 * We were loaded at QEMU's kernel load address, but we're not
28	 * allowed to link there due to how QEMU deals with linker VMAs,
29	 * so we just linked at zero. This means the first thing to do is
30	 * to find our stack and toc, and then do a relocate.
31	 */
32	LOAD_REG_IMMEDIATE(r31, SPAPR_KERNEL_LOAD_ADDR)
33	ld	r1, (p_stack - start)(r31)
34	ld	r2, (p_toc - start)(r31)
35	add	r1, r1, r31
36	add	r2, r2, r31
37
38	/* save DTB pointer */
39	std	r3, 56(r1)
40
41	/*
42	 * Call relocate. relocate is C code, but careful to not use
43	 * any global references, as they may use absolute addresses,
44	 * which are, obviously, not yet relocated.
45	 */
46	mr	r3, r31
47	ld	r4, (p_dyn - start)(r31)
48	add	r4, r4, r31
49	bl	relocate
50
51	/* compute address of call_handler */
52
53	LOAD_REG_ADDR(r4, call_handler)
54	std	r4, P_HANDLER(0)
55
56	/* relocate vector table to base address 0x0 (MSR_IP = 0) */
57
58	/* source: r4, dest end: r5, destination: r6 */
59
60	LOAD_REG_ADDR(r4, __start_interrupts)
61	LOAD_REG_ADDR(r5, __end_interrupts)
62	sub	r5,r5,r4
63	li	r6,0x100
64
65	sub	r4,r4,r6
66	add	r5,r5,r6
67	addi	r6,r6,-8
682:	li	r0,8
69	mtctr	r0
70	/* copy a cache line size */
713:	addi	r6,r6,8
72	ldx	r0,r6,r4
73	stdx	r0,0,r6
74	bdnz	3b
75	dcbst	0,r6
76	/* flush icache */
77	sync
78	icbi	0,r6
79	cmpld	0,r6,r5
80	blt	2b
81	sync
82	isync
83
84	/* patch sc1 if needed */
85	bl	hcall_have_broken_sc1
86	cmpwi	r3, 0
87	beq	1f
88	LOAD_REG_ADDR(r3, hcall)
89	LOAD_REG_IMMEDIATE(r4, SC1_REPLACEMENT)
90	stw	r4, 0(r3)
91
92	/* complete setup */
931:	ld	r3, 56(r1)
94	bl	setup
95
96	/* run the test */
97	LOAD_REG_ADDR(r3, __argc)
98	LOAD_REG_ADDR(r4, __argv)
99	LOAD_REG_ADDR(r5, __environ)
100	lwz	r3, 0(r3)
101	bl	main
102	bl	exit
103	b	halt
104
105.align 3
106p_stack:	.llong  stackptr
107p_toc:		.llong  tocptr
108p_dyn:		.llong  dynamic_start
109
110.text
111.align 3
112
113.globl hcall
114hcall:
115	sc	1
116	blr
117
118.globl halt
119halt:
1201:	b	1b
121
122.globl enter_rtas
123enter_rtas:
124	LOAD_REG_ADDR(r11, rtas_entry)
125	ld	r10, 0(r11)
126
127	cmpdi	r10,0
128	bne	external_rtas
129
130	/* Use H_RTAS directly */
131	mr	r4,r3
132	lis	r3,KVMPPC_H_RTAS@h
133	ori	r3,r3,KVMPPC_H_RTAS@l
134	b	hcall
135
136external_rtas:
137	/* Use external RTAS blob */
138	mflr	r0
139	std	r0, 16(r1)
140
141	LOAD_REG_ADDR(r11, rtas_return_loc)
142	mtlr	r11
143
144	mfmsr	r11
145	LOAD_REG_IMMEDIATE(r9, RTAS_MSR_MASK)
146	and	r11, r11, r9
147	mtsrr0	r10
148	mtsrr1	r11
149	rfid
150	b       .
151
152rtas_return_loc:
153	FIXUP_ENDIAN
154	ld	r0, 16(r1)
155	mtlr	r0
156	blr
157
158call_handler:
159	/* save context */
160
161	/* GPRs */
162
163	.irp i, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 \
164	        17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
165		SAVE_GPR(\i, r1)
166	.endr
167	mfsprg1	r0
168	std	r0,GPR1(r1)
169
170	/* lr, xer, ccr */
171
172	mflr	r0
173	std	r0,_LINK(r1)
174
175	mfxer	r0
176	std	r0,_XER(r1)
177
178	mfcr	r0
179	std	r0,_CCR(r1)
180
181	/* nip and msr */
182
183	mfsrr0	r0
184	std	r0, _NIP(r1)
185
186	mfsrr1	r0
187	std	r0, _MSR(r1)
188
189	/* restore TOC pointer */
190
191	LOAD_REG_IMMEDIATE(r31, SPAPR_KERNEL_LOAD_ADDR)
192	ld	r2, (p_toc - start)(r31)
193
194	/* FIXME: build stack frame */
195
196	/* call generic handler */
197
198	addi	r3,r1,STACK_FRAME_OVERHEAD
199	bl	do_handle_exception
200
201	/* restore context */
202
203	ld	r0,_CTR(r1)
204	mtctr	r0
205
206	ld	r0,_LINK(r1)
207	mtlr	r0
208
209	ld	r0,_XER(r1)
210	mtxer	r0
211
212	ld	r0,_CCR(r1)
213	mtcr	r0
214
215	ld	r0, _NIP(r1)
216	mtsrr0	r0
217
218	ld	r0, _MSR(r1)
219	mtsrr1	r0
220
221	.irp i, 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 \
222	        17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
223		REST_GPR(\i, r1)
224	.endr
225
226	/* restore r1, as we don't need it anymore */
227
228	REST_GPR(1,r1)
229
230	rfid
231	b .
232
233.section .text.ex
234
235.macro VECTOR vec
236	. = \vec
237
238	mtsprg1	r1	/* save r1 */
239	mfsprg0	r1	/* get exception stack address */
240	subi	r1,r1, INT_FRAME_SIZE
241
242	/* save r0 and ctr to call generic handler */
243
244	SAVE_GPR(0,r1)
245
246	mfctr	r0
247	std	r0,_CTR(r1)
248
249	ld	r0, P_HANDLER(0)
250	mtctr	r0
251
252	li	r0,\vec
253	std	r0,_TRAP(r1)
254
255	bctr
256.endm
257
258	. = 0x100
259	.globl __start_interrupts
260__start_interrupts:
261
262VECTOR(0x100)
263VECTOR(0x200)
264VECTOR(0x300)
265VECTOR(0x400)
266VECTOR(0x500)
267VECTOR(0x600)
268VECTOR(0x700)
269VECTOR(0x800)
270VECTOR(0x900)
271
272	.align 7
273	.globl __end_interrupts
274__end_interrupts:
275	.org	P_HANDLER
276	.llong	0
277