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