static void nmi_shootdown_cpus(void) { unsigned long msecs; local_irq_disable(); crashing_cpu = smp_processor_id(); local_irq_count(crashing_cpu) = 0; atomic_set(&waiting_for_crash_ipi, num_online_cpus() - 1); /* Would it be better to replace the trap vector here? */ set_nmi_callback(crash_nmi_callback); /* Ensure the new callback function is set before sending out the NMI. */ wmb(); smp_send_nmi_allbutself(); msecs = 1000; /* Wait at most a second for the other cpus to stop */ while ( (atomic_read(&waiting_for_crash_ipi) > 0) && msecs ) { mdelay(1); msecs--; } __stop_this_cpu(); disable_IO_APIC(); local_irq_enable(); }
/* * Stop all CPUs and turn off local APICs and the IO-APIC, so other OSs see a * clean IRQ state. */ void smp_send_stop(void) { int timeout = 10; smp_call_function(stop_this_cpu, NULL, 0); /* Wait 10ms for all other CPUs to go offline. */ while ( (num_online_cpus() > 1) && (timeout-- > 0) ) mdelay(1); local_irq_disable(); __stop_this_cpu(); disable_IO_APIC(); hpet_disable(); local_irq_enable(); }
static void nmi_shootdown_cpus(void) { unsigned long msecs; local_irq_disable(); if ( hpet_broadcast_is_available() ) hpet_disable_legacy_broadcast(); crashing_cpu = smp_processor_id(); local_irq_count(crashing_cpu) = 0; atomic_set(&waiting_for_crash_ipi, num_online_cpus() - 1); /* Would it be better to replace the trap vector here? */ set_nmi_callback(crash_nmi_callback); /* Ensure the new callback function is set before sending out the NMI. */ wmb(); smp_send_nmi_allbutself(); msecs = 1000; /* Wait at most a second for the other cpus to stop */ while ( (atomic_read(&waiting_for_crash_ipi) > 0) && msecs ) { mdelay(1); msecs--; } /* Crash shutdown any IOMMU functionality as the crashdump kernel is not * happy when booting if interrupt/dma remapping is still enabled */ iommu_crash_shutdown(); __stop_this_cpu(); /* This is a bit of a hack due to the problems with the x2apic_enabled * variable, but we can't do any better without a significant refactoring * of the APIC code */ x2apic_enabled = (current_local_apic_mode() == APIC_MODE_X2APIC); disable_IO_APIC(); hpet_disable(); }
static int crash_nmi_callback(struct cpu_user_regs *regs, int cpu) { /* Don't do anything if this handler is invoked on crashing cpu. * Otherwise, system will completely hang. Crashing cpu can get * an NMI if system was initially booted with nmi_watchdog parameter. */ if ( cpu == crashing_cpu ) return 1; local_irq_disable(); kexec_crash_save_cpu(); __stop_this_cpu(); atomic_dec(&waiting_for_crash_ipi); for ( ; ; ) halt(); return 1; }
static void stop_this_cpu(void *dummy) { __stop_this_cpu(); for ( ; ; ) halt(); }