X-Git-Url: https://gerrit.opnfv.org/gerrit/gitweb?a=blobdiff_plain;f=qemu%2Froms%2FSLOF%2Fclients%2Ftakeover%2Fmain.c;fp=qemu%2Froms%2FSLOF%2Fclients%2Ftakeover%2Fmain.c;h=360d8eaed465aed8908ecba0cd9265da38efb195;hb=e44e3482bdb4d0ebde2d8b41830ac2cdb07948fb;hp=0000000000000000000000000000000000000000;hpb=9ca8dbcc65cfc63d6f5ef3312a33184e1d726e00;p=kvmfornfv.git diff --git a/qemu/roms/SLOF/clients/takeover/main.c b/qemu/roms/SLOF/clients/takeover/main.c new file mode 100644 index 000000000..360d8eaed --- /dev/null +++ b/qemu/roms/SLOF/clients/takeover/main.c @@ -0,0 +1,163 @@ +/****************************************************************************** + * 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); +}