start.S revision 265998
1139804Simp/*-
297372Smarcel * Copyright (C) 2010 Nathan Whitehorn
397372Smarcel * All rights reserved.
497372Smarcel *
597372Smarcel * Redistribution and use in source and binary forms, with or without
697372Smarcel * modification, are permitted provided that the following conditions
797372Smarcel * are met:
897372Smarcel * 1. Redistributions of source code must retain the above copyright
997372Smarcel *    notice, this list of conditions and the following disclaimer.
1097372Smarcel * 2. Redistributions in binary form must reproduce the above copyright
1197372Smarcel *    notice, this list of conditions and the following disclaimer in the
1297372Smarcel *    documentation and/or other materials provided with the distribution.
1397372Smarcel *
1497372Smarcel * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1597372Smarcel * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1697372Smarcel * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
1797372Smarcel * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
1897372Smarcel * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
1997372Smarcel * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
2097372Smarcel * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
2197372Smarcel * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
2297372Smarcel * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
2397372Smarcel * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2497372Smarcel *
2597372Smarcel * $FreeBSD: stable/10/sys/boot/powerpc/ps3/start.S 265998 2014-05-14 01:16:05Z ian $
2697372Smarcel */
27116182Sobrien
28116182Sobrien#define LOCORE
29116182Sobrien
3097372Smarcel#include <machine/trap.h>
3197372Smarcel
3297372Smarcel/*
3397372Smarcel * KBoot and simulators will start this program from the _start symbol, with
3497372Smarcel * r3 pointing to a flattened device tree (kexec), r4 the physical address
3597372Smarcel * at which we were loaded, and r5 0 (kexec) or a pointer to Open Firmware
3697372Smarcel * (simulator). If r4 is non-zero, the first order of business is relocating
3797372Smarcel * ourselves to 0. In the kboot case, the PPE secondary thread will enter
38102263Sbde * at 0x60.
3997372Smarcel *
40181803Sbz * If started directly by the LV1 hypervisor, we are loaded to address 0
4197372Smarcel * and execution on both threads begins at 0x100 (EXC_RST).
4297372Smarcel */
4397372Smarcel
4497372Smarcel#define CACHELINE_SIZE			128
4597372Smarcel#define SPR_CTRL			136
4697372Smarcel
4797372Smarcel/* KBoot thread 0 entry -- do relocation, then jump to main */
4897372Smarcel.global _start
4997372Smarcel_start:
5097372Smarcel	mfmsr   %r31
5197372Smarcel	clrldi  %r31,%r31,1
5297372Smarcel	mtmsrd  %r31
5397372Smarcel	isync
5497372Smarcel	cmpwi	%r4,0
5597372Smarcel	bne	relocate_self
5697372Smarcelrelocated_start:
5797372Smarcel	lis	%r1,0x100
5897372Smarcel	bl	main
5997372Smarcel
6097372Smarcel. = 0x40
6197372Smarcel.global secondary_spin_sem
6297372Smarcelsecondary_spin_sem:
6397372Smarcel	.long	0
6497372Smarcel
6597372Smarcel. = 0x60
6697372Smarcelthread1_start_kboot:
6797372Smarcel	mfmsr   %r31
6897372Smarcel	clrldi  %r31,%r31,1
6997372Smarcel	mtmsrd  %r31
7097372Smarcel	isync
7197372Smarcel
7297372Smarcel	ba	thread1_start	/* kboot copies the first 256 bytes to
7397372Smarcel				 * address 0, so we are safe to jump
7497372Smarcel				 * (and stay) there */
7597372Smarcel
7697372Smarcelthread1_start:
7797372Smarcel	li	%r3,secondary_spin_sem@l
7897372Smarcel1:	lwz	%r1,0(%r3)	/* Spin on SECONDARY_SPIN_SEM_ADDRESS */
7997372Smarcel	cmpwi	%r1,0
8097372Smarcel	beq	1b		/* If the semaphore is still zero, spin again */
8197372Smarcel
8297372Smarcel	/* We have been woken up by thread 0 */
8397372Smarcel	li	%r0,0x100	/* Invalidate reset vector cache line */
8497372Smarcel	icbi	0,%r0
8597372Smarcel	isync
8697372Smarcel	sync
8797372Smarcel	ba	0x100		/* Jump to the reset vector */
8897372Smarcel
8997372Smarcel. = EXC_RST
9097372Smarcelexc_rst:
9197372Smarcel	mfmsr   %r31
9297372Smarcel	clrldi  %r31,%r31,1
9397372Smarcel	mtmsrd  %r31
9497372Smarcel	isync
9597372Smarcel
96108172Shsu	mfspr	%r3,SPR_CTRL
97181803Sbz	/* The first two bits of r0 are 01 (thread 1) or 10 (thread 0) */
9897372Smarcel	cntlzw	%r3,%r3		/* Now 0 for thread 0, 1 for thread 1 */
9997372Smarcel
10097372Smarcel	cmpwi	%r3,0
10197372Smarcel	bne	thread1_start	/* Send thread 1 to wait */
10297372Smarcel
10397372Smarcel	b	relocated_start /* Main entry point for thread 0 */
10497372Smarcel
105108172Shsu#define EXCEPTION_HANDLER(exc) \
10697372Smarcel. = exc; \
10797372Smarcel	li	%r3, exc; \
10897372Smarcel	mfsrr0	%r4; \
10997372Smarcel	mfmsr	%r5; \
110108172Shsu	clrldi  %r6,%r5,1; \
11197372Smarcel	mtmsrd  %r6; \
11297372Smarcel	isync; \
11397372Smarcel	lis	%r1,0x100; \
114124835Srse	bl	ppc_exception
11597372Smarcel
11697372SmarcelEXCEPTION_HANDLER(EXC_MCHK)
11797372SmarcelEXCEPTION_HANDLER(EXC_DSI)
11897372SmarcelEXCEPTION_HANDLER(EXC_DSE)
11997372SmarcelEXCEPTION_HANDLER(EXC_ISI)
120168975SpjdEXCEPTION_HANDLER(EXC_ISE)
12197372SmarcelEXCEPTION_HANDLER(EXC_EXI)
12297372SmarcelEXCEPTION_HANDLER(EXC_ALI)
12397372SmarcelEXCEPTION_HANDLER(EXC_PGM)
12497372SmarcelEXCEPTION_HANDLER(EXC_FPU)
12597372SmarcelEXCEPTION_HANDLER(EXC_DECR)
12697372SmarcelEXCEPTION_HANDLER(EXC_SC)
12797372Smarcel
12897372Smarcelrelocate_self:
12997372Smarcel	/* We enter this with r4 the physical offset for our relocation */
13097372Smarcel	lis	%r8,_end@ha	/* r8: copy length */
13197372Smarcel	addi	%r8,%r8,_end@l
13297372Smarcel	li	%r5,0x100	/* r5: dest address */
13397372Smarcel1:	add	%r6,%r4,%r5	/* r6: source address */
13497372Smarcel	ld	%r7,0(%r6)
135150303Smarcel	std	%r7,0(%r5)
136150303Smarcel	addi	%r5,%r5,8
13797372Smarcel	cmpw	%r5,%r8
13897372Smarcel	blt	1b
13997372Smarcel
140150303Smarcel	/*
14197372Smarcel	 * Now invalidate the cacheline with the second half of relocate_self,
14297372Smarcel	 * and do an absolute branch there in case we overwrote part of
14397372Smarcel	 * ourselves.
14497372Smarcel	 */
14597372Smarcel
14697372Smarcel	lis	%r9,relocate_self_cache@ha
14797372Smarcel	addi	%r9,%r9,relocate_self_cache@l
14897372Smarcel	dcbst	0,%r9
14997372Smarcel	sync
15097372Smarcel	icbi	0,%r9
15197372Smarcel	sync
15297372Smarcel	isync
15397372Smarcel	ba	relocate_self_cache
15497372Smarcel
15597372Smarcelrelocate_self_cache:
15697372Smarcel	/* Now invalidate the icache */
157150303Smarcel	li	%r5,0x100
15897372Smarcel2:	dcbst	0,%r5
15997372Smarcel	sync
16097372Smarcel	icbi	0,%r5
16197372Smarcel	sync
16297372Smarcel	isync
16397372Smarcel	cmpw	%r5,%r8
164150303Smarcel	addi	%r5,%r5,CACHELINE_SIZE
165150303Smarcel	blt	2b
16697372Smarcel
16797372Smarcel	/* All done: absolute jump to relocated entry point */
16897372Smarcel	ba	relocated_start
169150303Smarcel
17097372Smarcel