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