aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/kernel/smp.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/s390/kernel/smp.c')
-rw-r--r--arch/s390/kernel/smp.c117
1 files changed, 34 insertions, 83 deletions
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
index 62822245f9be..19090f7d4f51 100644
--- a/arch/s390/kernel/smp.c
+++ b/arch/s390/kernel/smp.c
@@ -230,18 +230,37 @@ static inline void do_store_status(void)
230 } 230 }
231} 231}
232 232
233static inline void do_wait_for_stop(void)
234{
235 int cpu;
236
237 /* Wait for all other cpus to enter stopped state */
238 for_each_online_cpu(cpu) {
239 if (cpu == smp_processor_id())
240 continue;
241 while(!smp_cpu_not_running(cpu))
242 cpu_relax();
243 }
244}
245
233/* 246/*
234 * this function sends a 'stop' sigp to all other CPUs in the system. 247 * this function sends a 'stop' sigp to all other CPUs in the system.
235 * it goes straight through. 248 * it goes straight through.
236 */ 249 */
237void smp_send_stop(void) 250void smp_send_stop(void)
238{ 251{
252 /* Disable all interrupts/machine checks */
253 __load_psw_mask(PSW_KERNEL_BITS & ~PSW_MASK_MCHECK);
254
239 /* write magic number to zero page (absolute 0) */ 255 /* write magic number to zero page (absolute 0) */
240 lowcore_ptr[smp_processor_id()]->panic_magic = __PANIC_MAGIC; 256 lowcore_ptr[smp_processor_id()]->panic_magic = __PANIC_MAGIC;
241 257
242 /* stop other processors. */ 258 /* stop other processors. */
243 do_send_stop(); 259 do_send_stop();
244 260
261 /* wait until other processors are stopped */
262 do_wait_for_stop();
263
245 /* store status of other processors. */ 264 /* store status of other processors. */
246 do_store_status(); 265 do_store_status();
247} 266}
@@ -250,88 +269,28 @@ void smp_send_stop(void)
250 * Reboot, halt and power_off routines for SMP. 269 * Reboot, halt and power_off routines for SMP.
251 */ 270 */
252 271
253static void do_machine_restart(void * __unused)
254{
255 int cpu;
256 static atomic_t cpuid = ATOMIC_INIT(-1);
257
258 if (atomic_cmpxchg(&cpuid, -1, smp_processor_id()) != -1)
259 signal_processor(smp_processor_id(), sigp_stop);
260
261 /* Wait for all other cpus to enter stopped state */
262 for_each_online_cpu(cpu) {
263 if (cpu == smp_processor_id())
264 continue;
265 while(!smp_cpu_not_running(cpu))
266 cpu_relax();
267 }
268
269 /* Store status of other cpus. */
270 do_store_status();
271
272 /*
273 * Finally call reipl. Because we waited for all other
274 * cpus to enter this function we know that they do
275 * not hold any s390irq-locks (the cpus have been
276 * interrupted by an external interrupt and s390irq
277 * locks are always held disabled).
278 */
279 do_reipl();
280}
281
282void machine_restart_smp(char * __unused) 272void machine_restart_smp(char * __unused)
283{ 273{
284 on_each_cpu(do_machine_restart, NULL, 0, 0); 274 smp_send_stop();
285} 275 do_reipl();
286
287static void do_wait_for_stop(void)
288{
289 unsigned long cr[16];
290
291 __ctl_store(cr, 0, 15);
292 cr[0] &= ~0xffff;
293 cr[6] = 0;
294 __ctl_load(cr, 0, 15);
295 for (;;)
296 enabled_wait();
297}
298
299static void do_machine_halt(void * __unused)
300{
301 static atomic_t cpuid = ATOMIC_INIT(-1);
302
303 if (atomic_cmpxchg(&cpuid, -1, smp_processor_id()) == -1) {
304 smp_send_stop();
305 if (MACHINE_IS_VM && strlen(vmhalt_cmd) > 0)
306 cpcmd(vmhalt_cmd, NULL, 0, NULL);
307 signal_processor(smp_processor_id(),
308 sigp_stop_and_store_status);
309 }
310 do_wait_for_stop();
311} 276}
312 277
313void machine_halt_smp(void) 278void machine_halt_smp(void)
314{ 279{
315 on_each_cpu(do_machine_halt, NULL, 0, 0); 280 smp_send_stop();
316} 281 if (MACHINE_IS_VM && strlen(vmhalt_cmd) > 0)
317 282 __cpcmd(vmhalt_cmd, NULL, 0, NULL);
318static void do_machine_power_off(void * __unused) 283 signal_processor(smp_processor_id(), sigp_stop_and_store_status);
319{ 284 for (;;);
320 static atomic_t cpuid = ATOMIC_INIT(-1);
321
322 if (atomic_cmpxchg(&cpuid, -1, smp_processor_id()) == -1) {
323 smp_send_stop();
324 if (MACHINE_IS_VM && strlen(vmpoff_cmd) > 0)
325 cpcmd(vmpoff_cmd, NULL, 0, NULL);
326 signal_processor(smp_processor_id(),
327 sigp_stop_and_store_status);
328 }
329 do_wait_for_stop();
330} 285}
331 286
332void machine_power_off_smp(void) 287void machine_power_off_smp(void)
333{ 288{
334 on_each_cpu(do_machine_power_off, NULL, 0, 0); 289 smp_send_stop();
290 if (MACHINE_IS_VM && strlen(vmpoff_cmd) > 0)
291 __cpcmd(vmpoff_cmd, NULL, 0, NULL);
292 signal_processor(smp_processor_id(), sigp_stop_and_store_status);
293 for (;;);
335} 294}
336 295
337/* 296/*
@@ -501,8 +460,6 @@ __init smp_count_cpus(void)
501 */ 460 */
502extern void init_cpu_timer(void); 461extern void init_cpu_timer(void);
503extern void init_cpu_vtimer(void); 462extern void init_cpu_vtimer(void);
504extern int pfault_init(void);
505extern void pfault_fini(void);
506 463
507int __devinit start_secondary(void *cpuvoid) 464int __devinit start_secondary(void *cpuvoid)
508{ 465{
@@ -514,11 +471,9 @@ int __devinit start_secondary(void *cpuvoid)
514#ifdef CONFIG_VIRT_TIMER 471#ifdef CONFIG_VIRT_TIMER
515 init_cpu_vtimer(); 472 init_cpu_vtimer();
516#endif 473#endif
517#ifdef CONFIG_PFAULT
518 /* Enable pfault pseudo page faults on this cpu. */ 474 /* Enable pfault pseudo page faults on this cpu. */
519 if (MACHINE_IS_VM) 475 pfault_init();
520 pfault_init(); 476
521#endif
522 /* Mark this cpu as online */ 477 /* Mark this cpu as online */
523 cpu_set(smp_processor_id(), cpu_online_map); 478 cpu_set(smp_processor_id(), cpu_online_map);
524 /* Switch on interrupts */ 479 /* Switch on interrupts */
@@ -708,11 +663,8 @@ __cpu_disable(void)
708 } 663 }
709 cpu_clear(cpu, cpu_online_map); 664 cpu_clear(cpu, cpu_online_map);
710 665
711#ifdef CONFIG_PFAULT
712 /* Disable pfault pseudo page faults on this cpu. */ 666 /* Disable pfault pseudo page faults on this cpu. */
713 if (MACHINE_IS_VM) 667 pfault_fini();
714 pfault_fini();
715#endif
716 668
717 memset(&cr_parms.orvals, 0, sizeof(cr_parms.orvals)); 669 memset(&cr_parms.orvals, 0, sizeof(cr_parms.orvals));
718 memset(&cr_parms.andvals, 0xff, sizeof(cr_parms.andvals)); 670 memset(&cr_parms.andvals, 0xff, sizeof(cr_parms.andvals));
@@ -860,4 +812,3 @@ EXPORT_SYMBOL(smp_ctl_clear_bit);
860EXPORT_SYMBOL(smp_call_function); 812EXPORT_SYMBOL(smp_call_function);
861EXPORT_SYMBOL(smp_get_cpu); 813EXPORT_SYMBOL(smp_get_cpu);
862EXPORT_SYMBOL(smp_put_cpu); 814EXPORT_SYMBOL(smp_put_cpu);
863