static void kexec_smp_down(void *arg) { local_irq_disable(); mb(); /* make sure our irqs are disabled before we say they are */ get_paca()->kexec_state = KEXEC_STATE_IRQS_OFF; while(kexec_all_irq_disabled == 0) cpu_relax(); mb(); /* make sure all irqs are disabled before this */ hw_breakpoint_disable(); /* * Now every CPU has IRQs off, we can clear out any pending * IPIs and be sure that no more will come in after this. */ if (ppc_md.kexec_cpu_down) ppc_md.kexec_cpu_down(0, 1); kexec_smp_wait(); /* NOTREACHED */ }
static void kexec_prepare_cpus_wait(int wait_state) { int my_cpu, i, notified=-1; hw_breakpoint_disable(); my_cpu = get_cpu(); for_each_online_cpu(i) { if (i == my_cpu) continue; while (paca[i].kexec_state < wait_state) { barrier(); if (i != notified) { printk(KERN_INFO "kexec: waiting for cpu %d " "(physical %d) to enter %i state\n", i, paca[i].hw_cpu_id, wait_state); notified = i; } } } mb(); }
static void kexec_prepare_cpus_wait(int wait_state) { int my_cpu, i, notified=-1; hw_breakpoint_disable(); my_cpu = get_cpu(); /* Make sure each CPU has at least made it to the state we need. * * FIXME: There is a (slim) chance of a problem if not all of the CPUs * are correctly onlined. If somehow we start a CPU on boot with RTAS * start-cpu, but somehow that CPU doesn't write callin_cpu_map[] in * time, the boot CPU will timeout. If it does eventually execute * stuff, the secondary will start up (paca[].cpu_start was written) and * get into a peculiar state. If the platform supports * smp_ops->take_timebase(), the secondary CPU will probably be spinning * in there. If not (i.e. pseries), the secondary will continue on and * try to online itself/idle/etc. If it survives that, we need to find * these possible-but-not-online-but-should-be CPUs and chaperone them * into kexec_smp_wait(). */ for_each_online_cpu(i) { if (i == my_cpu) continue; while (paca[i].kexec_state < wait_state) { barrier(); if (i != notified) { printk(KERN_INFO "kexec: waiting for cpu %d " "(physical %d) to enter %i state\n", i, paca[i].hw_cpu_id, wait_state); notified = i; } } } mb(); }