Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / SLOF / clients / takeover / main.c
1 /******************************************************************************
2  * Copyright (c) 2004, 2008 IBM Corporation
3  * All rights reserved.
4  * This program and the accompanying materials
5  * are made available under the terms of the BSD License
6  * which accompanies this distribution, and is available at
7  * http://www.opensource.org/licenses/bsd-license.php
8  *
9  * Contributors:
10  *     IBM Corporation - initial implementation
11  *****************************************************************************/
12
13 #include <string.h>
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <of.h>
17 #include <pci.h>
18 #include <cpu.h>
19 #include <ioctl.h>
20 #include <takeover.h>
21
22 extern void call_client_interface(of_arg_t *);
23 extern void m_sync(void);
24
25 int callback(int argc, char *argv[]);
26
27 #define boot_rom_bin_start _binary_______boot_rom_bin_start
28 #define boot_rom_bin_end   _binary_______boot_rom_bin_end
29
30 extern char boot_rom_bin_start;
31 extern char boot_rom_bin_end;
32
33 #if defined(__GNUC__)
34 # define UNUSED __attribute__((unused))
35 #else
36 # define UNUSED
37 #endif
38
39 void *
40 sbrk(int incr)
41 {
42         return (void *) -1;
43 }
44
45 static void
46 doWait(void)
47 {
48         static const char *wheel = "|/-\\";
49         static int i = 0;
50         volatile int dly = 0xf0000;
51         while (dly--)
52                 asm volatile (" nop ");
53         printf("\b%c", wheel[i++]);
54         i &= 0x3;
55 }
56
57 static void
58 quiesce(void)
59 {
60         of_arg_t arg = {
61                 p32cast "quiesce",
62                 0, 0,
63         };
64         call_client_interface(&arg);
65 }
66
67 static int
68 startCpu(int num, int addr, int reg)
69 {
70         of_arg_t arg = {
71                 p32cast "start-cpu",
72                 3, 0,
73                 {num, addr, reg}
74         };
75         call_client_interface(&arg);
76         return arg.args[3];
77 }
78
79 volatile unsigned long slaveQuitt;
80 int takeoverFlag;
81
82 void
83 main(int argc, char *argv[])
84 {
85         phandle_t cpus;
86         phandle_t cpu;
87         unsigned long slaveMask;
88         extern int slaveLoop[];
89         extern int slaveLoopNoTakeover[];
90         int index = 0;
91         int delay = 100;
92         unsigned long reg;
93         unsigned long msr;
94
95         asm volatile ("mfmsr %0":"=r" (msr));
96         if (msr & 0x1000000000000000)
97                 takeoverFlag = 0;
98         else
99                 takeoverFlag = 1;
100
101         cpus = of_finddevice("/cpus");
102         cpu = of_child(cpus);
103         slaveMask = 0;
104         while (cpu) {
105                 char devType[100];
106                 *devType = '\0';
107                 of_getprop(cpu, "device_type", devType, sizeof(devType));
108                 if (strcmp(devType, "cpu") == 0) {
109                         of_getprop(cpu, "reg", &reg, sizeof(reg));
110                         if (index) {
111                                 printf("\r\n takeover on cpu%d (%x, %lx) ", index,
112                                        cpu, reg);
113                                 slaveQuitt = -1;
114                                 if (takeoverFlag)
115                                         startCpu(cpu, (int)(unsigned long)slaveLoop, index);
116                                 else
117                                         startCpu(cpu, (int)(unsigned long)slaveLoopNoTakeover,
118                                                  index);
119                                 slaveMask |= 0x1 << index;
120                                 delay = 100;
121                                 while (delay-- && slaveQuitt)
122                                         doWait();
123                         }
124                         index++;
125                 }
126                 cpu = of_peer(cpu);
127         }
128
129
130         printf("\r\n takeover on master cpu  ");
131         quiesce();
132
133         delay = 5;
134         while (delay--)
135                 doWait();
136         if (takeoverFlag)
137                 takeover();
138
139         memcpy((void*)TAKEOVERBASEADDRESS, &boot_rom_bin_start, &boot_rom_bin_end - &boot_rom_bin_start);
140         flush_cache((void *)TAKEOVERBASEADDRESS, &boot_rom_bin_end - &boot_rom_bin_start);
141         index = 0;
142
143         while (slaveMask) {
144                 m_sync();
145                 unsigned long shifter = 0x1 << index;
146                 if (shifter & slaveMask) {
147                         slaveQuitt = index;
148                         while (slaveQuitt)
149                                 m_sync();
150                         slaveMask &= ~shifter;
151                 }
152                 index++;
153         }
154
155         asm volatile(" mtctr %0 ; bctr " : : "r" (TAKEOVERBASEADDRESS+0x180) );
156 }
157
158 int
159 callback(int argc, char *argv[])
160 {
161         /* Dummy, only for takeover */
162         return (0);
163 }