1d129d8a1SSuraj Jitindar Singh /*
2d129d8a1SSuraj Jitindar Singh * Secondary cpu support
3d129d8a1SSuraj Jitindar Singh *
4d129d8a1SSuraj Jitindar Singh * Copyright 2016 Suraj Jitindar Singh, IBM.
5d129d8a1SSuraj Jitindar Singh *
6d129d8a1SSuraj Jitindar Singh * This work is licensed under the terms of the GNU LGPL, version 2.
7d129d8a1SSuraj Jitindar Singh */
8d129d8a1SSuraj Jitindar Singh
9*c76b0d0aSNicholas Piggin #include <alloc.h>
10d129d8a1SSuraj Jitindar Singh #include <devicetree.h>
11*c76b0d0aSNicholas Piggin #include <asm/atomic.h>
12*c76b0d0aSNicholas Piggin #include <asm/barrier.h>
13*c76b0d0aSNicholas Piggin #include <asm/processor.h>
148b10d4faSNicholas Piggin #include <asm/time.h>
15d129d8a1SSuraj Jitindar Singh #include <asm/setup.h>
16*c76b0d0aSNicholas Piggin #include <asm/opal.h>
17*c76b0d0aSNicholas Piggin #include <asm/hcall.h>
18d129d8a1SSuraj Jitindar Singh #include <asm/rtas.h>
19d129d8a1SSuraj Jitindar Singh #include <asm/smp.h>
20d129d8a1SSuraj Jitindar Singh
21d129d8a1SSuraj Jitindar Singh struct secondary_entry_data {
22d129d8a1SSuraj Jitindar Singh secondary_entry_fn entry;
23d129d8a1SSuraj Jitindar Singh };
24d129d8a1SSuraj Jitindar Singh
25*c76b0d0aSNicholas Piggin int nr_cpus_online = 1;
26*c76b0d0aSNicholas Piggin
stop_self(int cpu_id)27*c76b0d0aSNicholas Piggin static void stop_self(int cpu_id)
28*c76b0d0aSNicholas Piggin {
29*c76b0d0aSNicholas Piggin if (machine_is_powernv()) {
30*c76b0d0aSNicholas Piggin if (opal_call(OPAL_RETURN_CPU, 0, 0, 0) != OPAL_SUCCESS) {
31*c76b0d0aSNicholas Piggin printf("OPAL_RETURN_CPU failed\n");
32*c76b0d0aSNicholas Piggin }
33*c76b0d0aSNicholas Piggin } else {
34*c76b0d0aSNicholas Piggin rtas_stop_self();
35*c76b0d0aSNicholas Piggin }
36*c76b0d0aSNicholas Piggin
37*c76b0d0aSNicholas Piggin printf("failed to stop cpu %d\n", cpu_id);
38*c76b0d0aSNicholas Piggin assert(0);
39*c76b0d0aSNicholas Piggin }
40*c76b0d0aSNicholas Piggin
41*c76b0d0aSNicholas Piggin void main_secondary(struct cpu *cpu);
main_secondary(struct cpu * cpu)42*c76b0d0aSNicholas Piggin void main_secondary(struct cpu *cpu)
43*c76b0d0aSNicholas Piggin {
44*c76b0d0aSNicholas Piggin mtspr(SPR_SPRG0, (unsigned long)cpu);
45*c76b0d0aSNicholas Piggin __current_cpu = cpu;
46*c76b0d0aSNicholas Piggin
47*c76b0d0aSNicholas Piggin enable_mcheck();
48*c76b0d0aSNicholas Piggin
49*c76b0d0aSNicholas Piggin cpu_init_ipis();
50*c76b0d0aSNicholas Piggin
51*c76b0d0aSNicholas Piggin atomic_fetch_inc(&nr_cpus_online);
52*c76b0d0aSNicholas Piggin
53*c76b0d0aSNicholas Piggin cpu->entry(cpu->server_no);
54*c76b0d0aSNicholas Piggin
55*c76b0d0aSNicholas Piggin mb();
56*c76b0d0aSNicholas Piggin atomic_fetch_dec(&nr_cpus_online);
57*c76b0d0aSNicholas Piggin
58*c76b0d0aSNicholas Piggin stop_self(cpu->server_no);
59*c76b0d0aSNicholas Piggin }
60*c76b0d0aSNicholas Piggin
61*c76b0d0aSNicholas Piggin enum OpalThreadStatus {
62*c76b0d0aSNicholas Piggin OPAL_THREAD_INACTIVE = 0x0,
63*c76b0d0aSNicholas Piggin OPAL_THREAD_STARTED = 0x1,
64*c76b0d0aSNicholas Piggin OPAL_THREAD_UNAVAILABLE = 0x2 /* opal-v3 */
65*c76b0d0aSNicholas Piggin };
66*c76b0d0aSNicholas Piggin
67*c76b0d0aSNicholas Piggin #define H_EOI 0x64
68*c76b0d0aSNicholas Piggin #define H_CPPR 0x68
69*c76b0d0aSNicholas Piggin #define H_IPI 0x6c
70*c76b0d0aSNicholas Piggin #define H_XIRR 0x74
71*c76b0d0aSNicholas Piggin
72*c76b0d0aSNicholas Piggin static void (*ipi_fn)(struct pt_regs *regs, void *data);
73*c76b0d0aSNicholas Piggin
dbell_handler(struct pt_regs * regs,void * data)74*c76b0d0aSNicholas Piggin static void dbell_handler(struct pt_regs *regs, void *data)
75*c76b0d0aSNicholas Piggin {
76*c76b0d0aSNicholas Piggin /* sync */
77*c76b0d0aSNicholas Piggin ipi_fn(regs, data);
78*c76b0d0aSNicholas Piggin }
79*c76b0d0aSNicholas Piggin
extint_handler(struct pt_regs * regs,void * data)80*c76b0d0aSNicholas Piggin static void extint_handler(struct pt_regs *regs, void *data)
81*c76b0d0aSNicholas Piggin {
82*c76b0d0aSNicholas Piggin int32_t xirr;
83*c76b0d0aSNicholas Piggin int32_t xisr;
84*c76b0d0aSNicholas Piggin int64_t rc;
85*c76b0d0aSNicholas Piggin
86*c76b0d0aSNicholas Piggin asm volatile("mr r3,%1 ; sc 1 ; mr %0,r4" : "=r"(xirr) : "r"(H_XIRR));
87*c76b0d0aSNicholas Piggin xisr = xirr & 0xffffff;
88*c76b0d0aSNicholas Piggin
89*c76b0d0aSNicholas Piggin if (xisr == 2) { /* IPI */
90*c76b0d0aSNicholas Piggin rc = hcall(H_IPI, smp_processor_id(), 0xff);
91*c76b0d0aSNicholas Piggin assert(rc == H_SUCCESS);
92*c76b0d0aSNicholas Piggin }
93*c76b0d0aSNicholas Piggin
94*c76b0d0aSNicholas Piggin xirr |= (5 << 24);
95*c76b0d0aSNicholas Piggin rc = hcall(H_EOI, xirr);
96*c76b0d0aSNicholas Piggin assert(rc == H_SUCCESS);
97*c76b0d0aSNicholas Piggin
98*c76b0d0aSNicholas Piggin /* lower IPI */
99*c76b0d0aSNicholas Piggin ipi_fn(regs, data);
100*c76b0d0aSNicholas Piggin }
101*c76b0d0aSNicholas Piggin
cpu_init_ipis(void)102*c76b0d0aSNicholas Piggin void cpu_init_ipis(void)
103*c76b0d0aSNicholas Piggin {
104*c76b0d0aSNicholas Piggin if (machine_is_powernv()) {
105*c76b0d0aSNicholas Piggin /* skiboot can leave some messages set */
106*c76b0d0aSNicholas Piggin unsigned long rb = (5 << (63-36));
107*c76b0d0aSNicholas Piggin asm volatile("msgclr %0" :: "r"(rb) : "memory");
108*c76b0d0aSNicholas Piggin }
109*c76b0d0aSNicholas Piggin }
110*c76b0d0aSNicholas Piggin
local_ipi_enable(void)111*c76b0d0aSNicholas Piggin void local_ipi_enable(void)
112*c76b0d0aSNicholas Piggin {
113*c76b0d0aSNicholas Piggin if (machine_is_pseries()) {
114*c76b0d0aSNicholas Piggin hcall(H_CPPR, 5);
115*c76b0d0aSNicholas Piggin }
116*c76b0d0aSNicholas Piggin }
117*c76b0d0aSNicholas Piggin
local_ipi_disable(void)118*c76b0d0aSNicholas Piggin void local_ipi_disable(void)
119*c76b0d0aSNicholas Piggin {
120*c76b0d0aSNicholas Piggin if (machine_is_pseries()) {
121*c76b0d0aSNicholas Piggin hcall(H_CPPR, 0);
122*c76b0d0aSNicholas Piggin }
123*c76b0d0aSNicholas Piggin }
124*c76b0d0aSNicholas Piggin
register_ipi(void (* fn)(struct pt_regs *,void *),void * data)125*c76b0d0aSNicholas Piggin void register_ipi(void (*fn)(struct pt_regs *, void *), void *data)
126*c76b0d0aSNicholas Piggin {
127*c76b0d0aSNicholas Piggin ipi_fn = fn;
128*c76b0d0aSNicholas Piggin if (machine_is_powernv()) {
129*c76b0d0aSNicholas Piggin handle_exception(0xe80, &dbell_handler, data);
130*c76b0d0aSNicholas Piggin } else {
131*c76b0d0aSNicholas Piggin handle_exception(0x500, &extint_handler, data);
132*c76b0d0aSNicholas Piggin }
133*c76b0d0aSNicholas Piggin }
134*c76b0d0aSNicholas Piggin
unregister_ipi(void)135*c76b0d0aSNicholas Piggin void unregister_ipi(void)
136*c76b0d0aSNicholas Piggin {
137*c76b0d0aSNicholas Piggin if (machine_is_powernv()) {
138*c76b0d0aSNicholas Piggin handle_exception(0xe80, NULL, NULL);
139*c76b0d0aSNicholas Piggin } else {
140*c76b0d0aSNicholas Piggin handle_exception(0x500, NULL, NULL);
141*c76b0d0aSNicholas Piggin }
142*c76b0d0aSNicholas Piggin }
143*c76b0d0aSNicholas Piggin
send_ipi(int cpu_id)144*c76b0d0aSNicholas Piggin void send_ipi(int cpu_id)
145*c76b0d0aSNicholas Piggin {
146*c76b0d0aSNicholas Piggin if (machine_is_powernv()) {
147*c76b0d0aSNicholas Piggin unsigned long rb = (5 << (63-36)) | cpu_id;
148*c76b0d0aSNicholas Piggin asm volatile("lwsync" ::: "memory");
149*c76b0d0aSNicholas Piggin asm volatile("msgsnd %0" :: "r"(rb) : "memory");
150*c76b0d0aSNicholas Piggin } else {
151*c76b0d0aSNicholas Piggin hcall(H_IPI, cpu_id, 4);
152*c76b0d0aSNicholas Piggin }
153*c76b0d0aSNicholas Piggin }
154*c76b0d0aSNicholas Piggin
155*c76b0d0aSNicholas Piggin static int nr_started = 1;
156*c76b0d0aSNicholas Piggin
157*c76b0d0aSNicholas Piggin extern void start_secondary(uint64_t server_no); /* asm entry point */
158*c76b0d0aSNicholas Piggin
cpu_is_running(int cpu_id)159*c76b0d0aSNicholas Piggin static bool cpu_is_running(int cpu_id)
160*c76b0d0aSNicholas Piggin {
161*c76b0d0aSNicholas Piggin if (machine_is_powernv()) {
162*c76b0d0aSNicholas Piggin int64_t ret;
163*c76b0d0aSNicholas Piggin uint8_t status;
164*c76b0d0aSNicholas Piggin
165*c76b0d0aSNicholas Piggin ret = opal_call(OPAL_QUERY_CPU_STATUS, cpu_id, (unsigned long)&status, 0);
166*c76b0d0aSNicholas Piggin if (ret != OPAL_SUCCESS) {
167*c76b0d0aSNicholas Piggin printf("OPAL_QUERY_CPU_STATUS failed for cpu %d\n", cpu_id);
168*c76b0d0aSNicholas Piggin return false;
169*c76b0d0aSNicholas Piggin }
170*c76b0d0aSNicholas Piggin return (status != OPAL_THREAD_INACTIVE);
171*c76b0d0aSNicholas Piggin } else {
172*c76b0d0aSNicholas Piggin uint32_t query_token;
173*c76b0d0aSNicholas Piggin int outputs[1], ret;
174*c76b0d0aSNicholas Piggin
175*c76b0d0aSNicholas Piggin ret = rtas_token("query-cpu-stopped-state", &query_token);
176*c76b0d0aSNicholas Piggin if (ret != 0) {
177*c76b0d0aSNicholas Piggin printf("rtas token query-cpu-stopped-state failed\n");
178*c76b0d0aSNicholas Piggin return false;
179*c76b0d0aSNicholas Piggin }
180*c76b0d0aSNicholas Piggin
181*c76b0d0aSNicholas Piggin ret = rtas_call(query_token, 1, 2, outputs, cpu_id);
182*c76b0d0aSNicholas Piggin if (ret) {
183*c76b0d0aSNicholas Piggin printf("query-cpu-stopped-state failed for cpu %d\n", cpu_id);
184*c76b0d0aSNicholas Piggin return ret;
185*c76b0d0aSNicholas Piggin }
186*c76b0d0aSNicholas Piggin if (outputs[0]) /* cpu not in stopped state */
187*c76b0d0aSNicholas Piggin return true;
188*c76b0d0aSNicholas Piggin return false;
189*c76b0d0aSNicholas Piggin }
190*c76b0d0aSNicholas Piggin }
191*c76b0d0aSNicholas Piggin
192d129d8a1SSuraj Jitindar Singh /*
193d129d8a1SSuraj Jitindar Singh * Start stopped thread cpu_id at entry
194d129d8a1SSuraj Jitindar Singh * Returns: <0 on failure to start stopped cpu
195d129d8a1SSuraj Jitindar Singh * 0 on success
196d129d8a1SSuraj Jitindar Singh * >0 on cpu not in stopped state
197d129d8a1SSuraj Jitindar Singh */
start_thread(int cpu_id,secondary_entry_fn entry)198*c76b0d0aSNicholas Piggin static int start_thread(int cpu_id, secondary_entry_fn entry)
199d129d8a1SSuraj Jitindar Singh {
200*c76b0d0aSNicholas Piggin struct cpu *cpu;
201*c76b0d0aSNicholas Piggin uint64_t tb;
202d129d8a1SSuraj Jitindar Singh
203*c76b0d0aSNicholas Piggin if (nr_started >= NR_CPUS) {
204*c76b0d0aSNicholas Piggin /* Reached limit */
205*c76b0d0aSNicholas Piggin return -1;
206*c76b0d0aSNicholas Piggin }
207*c76b0d0aSNicholas Piggin
208*c76b0d0aSNicholas Piggin if (cpu_id == smp_processor_id()) {
209*c76b0d0aSNicholas Piggin /* Boot CPU already started */
210*c76b0d0aSNicholas Piggin return -1;
211*c76b0d0aSNicholas Piggin }
212*c76b0d0aSNicholas Piggin
213*c76b0d0aSNicholas Piggin tb = get_tb();
214*c76b0d0aSNicholas Piggin while (cpu_is_running(cpu_id)) {
215*c76b0d0aSNicholas Piggin if (get_tb() - tb > 3*tb_hz) {
216*c76b0d0aSNicholas Piggin printf("Unable to start running CPU:%d\n", cpu_id);
217*c76b0d0aSNicholas Piggin return 1;
218*c76b0d0aSNicholas Piggin }
219*c76b0d0aSNicholas Piggin }
220*c76b0d0aSNicholas Piggin
221*c76b0d0aSNicholas Piggin cpu = &cpus[nr_started];
222*c76b0d0aSNicholas Piggin nr_started++;
223*c76b0d0aSNicholas Piggin
224*c76b0d0aSNicholas Piggin cpu_init(cpu, cpu_id);
225*c76b0d0aSNicholas Piggin cpu->entry = entry;
226*c76b0d0aSNicholas Piggin
227*c76b0d0aSNicholas Piggin if (machine_is_powernv()) {
228*c76b0d0aSNicholas Piggin if (opal_call(OPAL_START_CPU, cpu_id, (unsigned long)start_secondary, 0) != OPAL_SUCCESS) {
229*c76b0d0aSNicholas Piggin printf("failed to start cpu %d\n", cpu_id);
230*c76b0d0aSNicholas Piggin return -1;
231*c76b0d0aSNicholas Piggin }
232*c76b0d0aSNicholas Piggin } else {
233*c76b0d0aSNicholas Piggin uint32_t start_token;
234*c76b0d0aSNicholas Piggin int ret;
235*c76b0d0aSNicholas Piggin
2362565dce1SThomas Huth ret = rtas_token("start-cpu", &start_token);
2372565dce1SThomas Huth assert(ret == 0);
238d129d8a1SSuraj Jitindar Singh
239*c76b0d0aSNicholas Piggin ret = rtas_call(start_token, 3, 1, NULL, cpu_id, start_secondary, cpu_id);
240d129d8a1SSuraj Jitindar Singh if (ret) {
241d129d8a1SSuraj Jitindar Singh printf("failed to start cpu %d\n", cpu_id);
242*c76b0d0aSNicholas Piggin return ret;
243*c76b0d0aSNicholas Piggin }
244d129d8a1SSuraj Jitindar Singh }
245d129d8a1SSuraj Jitindar Singh
246*c76b0d0aSNicholas Piggin return 0;
247d129d8a1SSuraj Jitindar Singh }
248d129d8a1SSuraj Jitindar Singh
249d129d8a1SSuraj Jitindar Singh /*
250d129d8a1SSuraj Jitindar Singh * Start all stopped threads (vcpus) on cpu_node
251d129d8a1SSuraj Jitindar Singh * Returns: Number of stopped cpus which were successfully started
252d129d8a1SSuraj Jitindar Singh */
start_core(int cpu_node,secondary_entry_fn entry)253*c76b0d0aSNicholas Piggin static void start_core(int cpu_node, secondary_entry_fn entry)
254d129d8a1SSuraj Jitindar Singh {
255*c76b0d0aSNicholas Piggin int len, i, nr_threads;
256d129d8a1SSuraj Jitindar Singh const struct fdt_property *prop;
257d129d8a1SSuraj Jitindar Singh u32 *threads;
258d129d8a1SSuraj Jitindar Singh
259d129d8a1SSuraj Jitindar Singh /* Get the id array of threads on this cpu_node */
260d129d8a1SSuraj Jitindar Singh prop = fdt_get_property(dt_fdt(), cpu_node,
261d129d8a1SSuraj Jitindar Singh "ibm,ppc-interrupt-server#s", &len);
262d129d8a1SSuraj Jitindar Singh assert(prop);
263d129d8a1SSuraj Jitindar Singh
264d129d8a1SSuraj Jitindar Singh nr_threads = len >> 2; /* Divide by 4 since 4 bytes per thread */
265*c76b0d0aSNicholas Piggin
266d129d8a1SSuraj Jitindar Singh threads = (u32 *)prop->data; /* Array of valid ids */
267d129d8a1SSuraj Jitindar Singh
268*c76b0d0aSNicholas Piggin for (i = 0; i < nr_threads; i++)
269*c76b0d0aSNicholas Piggin start_thread(fdt32_to_cpu(threads[i]), entry);
270d129d8a1SSuraj Jitindar Singh }
271d129d8a1SSuraj Jitindar Singh
start_each_secondary(int fdtnode,u64 regval __unused,void * info)2727a20b74eSAndrew Jones static void start_each_secondary(int fdtnode, u64 regval __unused, void *info)
273d129d8a1SSuraj Jitindar Singh {
274d129d8a1SSuraj Jitindar Singh struct secondary_entry_data *datap = info;
275d129d8a1SSuraj Jitindar Singh
276*c76b0d0aSNicholas Piggin start_core(fdtnode, datap->entry);
277d129d8a1SSuraj Jitindar Singh }
278d129d8a1SSuraj Jitindar Singh
279d129d8a1SSuraj Jitindar Singh /*
280d129d8a1SSuraj Jitindar Singh * Start all stopped cpus on the guest at entry with register 3 set to r3
281d129d8a1SSuraj Jitindar Singh * We expect that we come in with only one thread currently started
282d129d8a1SSuraj Jitindar Singh * Returns: TRUE on success
283d129d8a1SSuraj Jitindar Singh * FALSE on failure
284d129d8a1SSuraj Jitindar Singh */
start_all_cpus(secondary_entry_fn entry)285*c76b0d0aSNicholas Piggin bool start_all_cpus(secondary_entry_fn entry)
286d129d8a1SSuraj Jitindar Singh {
287*c76b0d0aSNicholas Piggin struct secondary_entry_data data = { entry };
288*c76b0d0aSNicholas Piggin uint64_t tb;
289d129d8a1SSuraj Jitindar Singh int ret;
290d129d8a1SSuraj Jitindar Singh
291*c76b0d0aSNicholas Piggin assert(nr_cpus_online == 1);
292*c76b0d0aSNicholas Piggin assert(nr_started == 1);
293d129d8a1SSuraj Jitindar Singh ret = dt_for_each_cpu_node(start_each_secondary, &data);
294d129d8a1SSuraj Jitindar Singh assert(ret == 0);
295*c76b0d0aSNicholas Piggin assert(nr_started == nr_cpus_present);
296d129d8a1SSuraj Jitindar Singh
297*c76b0d0aSNicholas Piggin tb = get_tb();
298*c76b0d0aSNicholas Piggin while (nr_cpus_online < nr_cpus_present) {
299*c76b0d0aSNicholas Piggin if (get_tb() - tb > 3*tb_hz) {
300*c76b0d0aSNicholas Piggin printf("failed to start all secondaries\n");
301*c76b0d0aSNicholas Piggin assert(0);
302*c76b0d0aSNicholas Piggin }
303*c76b0d0aSNicholas Piggin cpu_relax();
304*c76b0d0aSNicholas Piggin }
305*c76b0d0aSNicholas Piggin
306*c76b0d0aSNicholas Piggin return 1;
307*c76b0d0aSNicholas Piggin }
308*c76b0d0aSNicholas Piggin
309*c76b0d0aSNicholas Piggin /*
310*c76b0d0aSNicholas Piggin * Start stopped thread cpu_id at entry
311*c76b0d0aSNicholas Piggin * Returns: <0 on failure to start stopped cpu
312*c76b0d0aSNicholas Piggin * 0 on success
313*c76b0d0aSNicholas Piggin * >0 on cpu not in stopped state
314*c76b0d0aSNicholas Piggin */
wait_thread(int cpu_id)315*c76b0d0aSNicholas Piggin static int wait_thread(int cpu_id)
316*c76b0d0aSNicholas Piggin {
317*c76b0d0aSNicholas Piggin uint64_t tb;
318*c76b0d0aSNicholas Piggin
319*c76b0d0aSNicholas Piggin /* Skip the caller */
320*c76b0d0aSNicholas Piggin if (cpu_id == smp_processor_id()) {
321*c76b0d0aSNicholas Piggin return 0;
322*c76b0d0aSNicholas Piggin }
323*c76b0d0aSNicholas Piggin
324*c76b0d0aSNicholas Piggin tb = get_tb();
325*c76b0d0aSNicholas Piggin while (cpu_is_running(cpu_id)) {
326*c76b0d0aSNicholas Piggin if (get_tb() - tb > 3*tb_hz) {
327*c76b0d0aSNicholas Piggin printf("Timeout waiting to stop CPU:%d\n", cpu_id);
328*c76b0d0aSNicholas Piggin return 1;
329*c76b0d0aSNicholas Piggin }
330*c76b0d0aSNicholas Piggin }
331*c76b0d0aSNicholas Piggin
332*c76b0d0aSNicholas Piggin return 0;
333*c76b0d0aSNicholas Piggin }
334*c76b0d0aSNicholas Piggin
335*c76b0d0aSNicholas Piggin /*
336*c76b0d0aSNicholas Piggin * Wait for running threads (vcpus) on cpu_node to stop
337*c76b0d0aSNicholas Piggin */
wait_core(int cpu_node)338*c76b0d0aSNicholas Piggin static void wait_core(int cpu_node)
339*c76b0d0aSNicholas Piggin {
340*c76b0d0aSNicholas Piggin int len, i, nr_threads;
341*c76b0d0aSNicholas Piggin const struct fdt_property *prop;
342*c76b0d0aSNicholas Piggin u32 *threads;
343*c76b0d0aSNicholas Piggin
344*c76b0d0aSNicholas Piggin /* Get the id array of threads on this cpu_node */
345*c76b0d0aSNicholas Piggin prop = fdt_get_property(dt_fdt(), cpu_node,
346*c76b0d0aSNicholas Piggin "ibm,ppc-interrupt-server#s", &len);
347*c76b0d0aSNicholas Piggin assert(prop);
348*c76b0d0aSNicholas Piggin
349*c76b0d0aSNicholas Piggin nr_threads = len >> 2; /* Divide by 4 since 4 bytes per thread */
350*c76b0d0aSNicholas Piggin
351*c76b0d0aSNicholas Piggin threads = (u32 *)prop->data; /* Array of valid ids */
352*c76b0d0aSNicholas Piggin
353*c76b0d0aSNicholas Piggin for (i = 0; i < nr_threads; i++)
354*c76b0d0aSNicholas Piggin wait_thread(fdt32_to_cpu(threads[i]));
355*c76b0d0aSNicholas Piggin }
356*c76b0d0aSNicholas Piggin
wait_each_secondary(int fdtnode,u64 regval __unused,void * info)357*c76b0d0aSNicholas Piggin static void wait_each_secondary(int fdtnode, u64 regval __unused, void *info)
358*c76b0d0aSNicholas Piggin {
359*c76b0d0aSNicholas Piggin wait_core(fdtnode);
360*c76b0d0aSNicholas Piggin }
361*c76b0d0aSNicholas Piggin
stop_all_cpus(void)362*c76b0d0aSNicholas Piggin void stop_all_cpus(void)
363*c76b0d0aSNicholas Piggin {
364*c76b0d0aSNicholas Piggin while (nr_cpus_online > 1)
365*c76b0d0aSNicholas Piggin cpu_relax();
366*c76b0d0aSNicholas Piggin
367*c76b0d0aSNicholas Piggin dt_for_each_cpu_node(wait_each_secondary, NULL);
368*c76b0d0aSNicholas Piggin mb();
369*c76b0d0aSNicholas Piggin nr_started = 1;
370d129d8a1SSuraj Jitindar Singh }
371