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(); }
bool_t lapic_timer_init(void) { if ( boot_cpu_has(X86_FEATURE_ARAT) ) { lapic_timer_off = lapic_timer_nop; lapic_timer_on = lapic_timer_nop; } else if ( hpet_broadcast_is_available() ) { lapic_timer_off = hpet_broadcast_enter; lapic_timer_on = hpet_broadcast_exit; } else if ( pit_broadcast_is_available() ) { lapic_timer_off = pit_broadcast_enter; lapic_timer_on = pit_broadcast_exit; } else return 0; return 1; }