/****************************************************************************** * Copyright (c) 2004, 2007 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 #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; extern ihandle_t fd_array[32]; size_t write(int fd, void *buf, size_t cnt) { of_write((ihandle_t) fd_array[1], buf, cnt); return 0; } void * sbrk(int incr) { return (void *) -1; } void doWait(void) { static const char *wheel = "|/-\\"; static int i = 0; volatile int dly = 0xf0000; while (dly--); printf("\b%c", wheel[i++]); i &= 0x3; } void quiesce(void) { of_arg_t arg = { p32cast "quiesce", 0, 0, }; call_client_interface(&arg); } 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; int main(int argc, char *argv[]) { phandle_t cpus; phandle_t cpu; unsigned long slaveMask; extern int slaveLoop[]; extern int slaveLoopNoTakeover[]; char devtype[100]; int rcode; 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, %x) ", index, cpu, reg); slaveQuitt = -1; if (takeoverFlag) startCpu(cpu, (int) slaveLoop, index); else startCpu(cpu, (int) 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) rcode = 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) { unsigned long shifter = 0x1 << index; if (shifter & slaveMask) { slaveQuitt = index; while (slaveQuitt); slaveMask &= ~shifter; } index++; } asm volatile(" mtctr %0 ; bctr " : : "r" (TAKEOVERBASEADDRESS+0x180) ); } int callback(int argc, char *argv[]) { /* Dummy, only for takeover */ return (0); }