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