1/*-
2 * Copyright (C) 2010 Nathan Whitehorn
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
18 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
20 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
21 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
22 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
23 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 *
25 * $FreeBSD$
26 */
27
28#define LOCORE
29
30#include <machine/trap_aim.h>
31
32/*
33 * KBoot and simulators will start this program from the _start symbol, with
34 * r3 pointing to a flattened device tree (kexec), r4 the physical address
35 * at which we were loaded, and r5 0 (kexec) or a pointer to Open Firmware
36 * (simulator). If r4 is non-zero, the first order of business is relocating
37 * ourselves to 0. In the kboot case, the PPE secondary thread will enter
38 * at 0x60.
39 *
40 * If started directly by the LV1 hypervisor, we are loaded to address 0
41 * and execution on both threads begins at 0x100 (EXC_RST).
42 */
43
44#define CACHELINE_SIZE			128
45#define SPR_CTRL			136
46
47/* KBoot thread 0 entry -- do relocation, then jump to main */
48.global _start
49_start:
50	mfmsr   %r31
51	clrldi  %r31,%r31,1
52	mtmsrd  %r31
53	isync
54	cmpwi	%r4,0
55	bne	relocate_self
56relocated_start:
57	lis	%r1,0x100
58	bl	main
59
60. = 0x40
61.global secondary_spin_sem
62secondary_spin_sem:
63	.long	0
64
65. = 0x60
66thread1_start_kboot:
67	mfmsr   %r31
68	clrldi  %r31,%r31,1
69	mtmsrd  %r31
70	isync
71
72	ba	thread1_start	/* kboot copies the first 256 bytes to
73				 * address 0, so we are safe to jump
74				 * (and stay) there */
75
76thread1_start:
77	li	%r3,secondary_spin_sem@l
781:	lwz	%r1,0(%r3)	/* Spin on SECONDARY_SPIN_SEM_ADDRESS */
79	cmpwi	%r1,0
80	beq	1b		/* If the semaphore is still zero, spin again */
81
82	/* We have been woken up by thread 0 */
83	li	%r0,0x100	/* Invalidate reset vector cache line */
84	icbi	0,%r0
85	isync
86	sync
87	ba	0x100		/* Jump to the reset vector */
88
89. = EXC_RST
90exc_rst:
91	mfmsr   %r31
92	clrldi  %r31,%r31,1
93	mtmsrd  %r31
94	isync
95
96	mfspr	%r3,SPR_CTRL
97	/* The first two bits of r0 are 01 (thread 1) or 10 (thread 0) */
98	cntlzw	%r3,%r3		/* Now 0 for thread 0, 1 for thread 1 */
99
100	cmpwi	%r3,0
101	bne	thread1_start	/* Send thread 1 to wait */
102
103	b	relocated_start /* Main entry point for thread 0 */
104
105#define EXCEPTION_HANDLER(exc) \
106. = exc; \
107	li	%r3, exc; \
108	mfsrr0	%r4; \
109	mfmsr	%r5; \
110	clrldi  %r6,%r5,1; \
111	mtmsrd  %r6; \
112	isync; \
113	lis	%r1,0x100; \
114	bl	ppc_exception
115
116EXCEPTION_HANDLER(EXC_MCHK)
117EXCEPTION_HANDLER(EXC_DSI)
118EXCEPTION_HANDLER(EXC_DSE)
119EXCEPTION_HANDLER(EXC_ISI)
120EXCEPTION_HANDLER(EXC_ISE)
121EXCEPTION_HANDLER(EXC_EXI)
122EXCEPTION_HANDLER(EXC_ALI)
123EXCEPTION_HANDLER(EXC_PGM)
124EXCEPTION_HANDLER(EXC_FPU)
125EXCEPTION_HANDLER(EXC_DECR)
126EXCEPTION_HANDLER(EXC_SC)
127
128relocate_self:
129	/* We enter this with r4 the physical offset for our relocation */
130	lis	%r8,_end@ha	/* r8: copy length */
131	addi	%r8,%r8,_end@l
132	li	%r5,0x100	/* r5: dest address */
1331:	add	%r6,%r4,%r5	/* r6: source address */
134	ld	%r7,0(%r6)
135	std	%r7,0(%r5)
136	addi	%r5,%r5,8
137	cmpw	%r5,%r8
138	blt	1b
139
140	/*
141	 * Now invalidate the cacheline with the second half of relocate_self,
142	 * and do an absolute branch there in case we overwrote part of
143	 * ourselves.
144	 */
145
146	lis	%r9,relocate_self_cache@ha
147	addi	%r9,%r9,relocate_self_cache@l
148	dcbst	0,%r9
149	sync
150	icbi	0,%r9
151	sync
152	isync
153	ba	relocate_self_cache
154
155relocate_self_cache:
156	/* Now invalidate the icache */
157	li	%r5,0x100
1582:	dcbst	0,%r5
159	sync
160	icbi	0,%r5
161	sync
162	isync
163	cmpw	%r5,%r8
164	addi	%r5,%r5,CACHELINE_SIZE
165	blt	2b
166
167	/* All done: absolute jump to relocated entry point */
168	ba	relocated_start
169
170