/****************************************************************************** * Copyright (c) 2004, 2008 IBM Corporation * All rights reserved. * This program and the accompanying materials * are made available under the terms of the BSD License * which accompanies this distribution, and is available at * http://www.opensource.org/licenses/bsd-license.php * * Contributors: * IBM Corporation - initial implementation *****************************************************************************/ #include #include #include #include #include #include #include #include extern void call_client_interface(of_arg_t *); extern void m_sync(void); int callback(int argc, char *argv[]); #define boot_rom_bin_start _binary_______boot_rom_bin_start #define boot_rom_bin_end _binary_______boot_rom_bin_end extern char boot_rom_bin_start; extern char boot_rom_bin_end; #if defined(__GNUC__) # define UNUSED __attribute__((unused)) #else # define UNUSED #endif void * sbrk(int incr) { return (void *) -1; } static void doWait(void) { static const char *wheel = "|/-\\"; static int i = 0; volatile int dly = 0xf0000; while (dly--) asm volatile (" nop "); printf("\b%c", wheel[i++]); i &= 0x3; } static void quiesce(void) { of_arg_t arg = { p32cast "quiesce", 0, 0, }; call_client_interface(&arg); } static int startCpu(int num, int addr, int reg) { of_arg_t arg = { p32cast "start-cpu", 3, 0, {num, addr, reg} }; call_client_interface(&arg); return arg.args[3]; } volatile unsigned long slaveQuitt; int takeoverFlag; void main(int argc, char *argv[]) { phandle_t cpus; phandle_t cpu; unsigned long slaveMask; extern int slaveLoop[]; extern int slaveLoopNoTakeover[]; int index = 0; int delay = 100; unsigned long reg; unsigned long msr; asm volatile ("mfmsr %0":"=r" (msr)); if (msr & 0x1000000000000000) takeoverFlag = 0; else takeoverFlag = 1; cpus = of_finddevice("/cpus"); cpu = of_child(cpus); slaveMask = 0; while (cpu) { char devType[100]; *devType = '\0'; of_getprop(cpu, "device_type", devType, sizeof(devType)); if (strcmp(devType, "cpu") == 0) { of_getprop(cpu, "reg", ®, sizeof(reg)); if (index) { printf("\r\n takeover on cpu%d (%x, %lx) ", index, cpu, reg); slaveQuitt = -1; if (takeoverFlag) startCpu(cpu, (int)(unsigned long)slaveLoop, index); else startCpu(cpu, (int)(unsigned long)slaveLoopNoTakeover, index); slaveMask |= 0x1 << index; delay = 100; while (delay-- && slaveQuitt) doWait(); } index++; } cpu = of_peer(cpu); } printf("\r\n takeover on master cpu "); quiesce(); delay = 5; while (delay--) doWait(); if (takeoverFlag) takeover(); memcpy((void*)TAKEOVERBASEADDRESS, &boot_rom_bin_start, &boot_rom_bin_end - &boot_rom_bin_start); flush_cache((void *)TAKEOVERBASEADDRESS, &boot_rom_bin_end - &boot_rom_bin_start); index = 0; while (slaveMask) { m_sync(); unsigned long shifter = 0x1 << index; if (shifter & slaveMask) { slaveQuitt = index; while (slaveQuitt) m_sync(); slaveMask &= ~shifter; } index++; } asm volatile(" mtctr %0 ; bctr " : : "r" (TAKEOVERBASEADDRESS+0x180) ); } int callback(int argc, char *argv[]) { /* Dummy, only for takeover */ return (0); }