/* * Do not allocate memory (or fail in any way) in machine_kexec(). * We are past the point of no return, committed to rebooting now. */ void machine_kexec(struct kimage *image) { unsigned long page_list[PAGES_NR]; void *control_page; int save_ftrace_enabled; asmlinkage unsigned long (*relocate_kernel_ptr)(unsigned long indirection_page, unsigned long control_page, unsigned long start_address, unsigned int has_pae, unsigned int preserve_context); #ifdef CONFIG_KEXEC_JUMP if (image->preserve_context) save_processor_state(); #endif save_ftrace_enabled = __ftrace_enabled_save(); /* Interrupts aren't acceptable while we reboot */ local_irq_disable(); if (image->preserve_context) { #ifdef CONFIG_X86_IO_APIC /* * We need to put APICs in legacy mode so that we can * get timer interrupts in second kernel. kexec/kdump * paths already have calls to disable_IO_APIC() in * one form or other. kexec jump path also need * one. */ disable_IO_APIC(); #endif } control_page = page_address(image->control_code_page); memcpy(control_page, relocate_kernel, KEXEC_CONTROL_CODE_MAX_SIZE); relocate_kernel_ptr = control_page; page_list[PA_CONTROL_PAGE] = __pa(control_page); page_list[VA_CONTROL_PAGE] = (unsigned long)control_page; page_list[PA_PGD] = __pa(image->arch.pgd); if (image->type == KEXEC_TYPE_DEFAULT) page_list[PA_SWAP_PAGE] = (page_to_pfn(image->swap_page) << PAGE_SHIFT); /* now call it */ image->start = relocate_kernel_ptr((unsigned long)image->head, (unsigned long)page_list, image->start, cpu_has_pae, image->preserve_context); #ifdef CONFIG_KEXEC_JUMP if (image->preserve_context) restore_processor_state(); #endif __ftrace_enabled_restore(save_ftrace_enabled); }
void native_machine_crash_shutdown(struct pt_regs *regs) { /* This function is only called after the system * has panicked or is otherwise in a critical state. * The minimum amount of code to allow a kexec'd kernel * to run successfully needs to happen here. * * In practice this means shooting down the other cpus in * an SMP system. */ /* The kernel is broken so disable interrupts */ local_irq_disable(); /* Make a note of crashing cpu. Will be used in NMI callback.*/ crashing_cpu = safe_smp_processor_id(); nmi_shootdown_cpus(); lapic_shutdown(); #if defined(CONFIG_X86_IO_APIC) disable_IO_APIC(); #endif #ifdef CONFIG_HPET_TIMER hpet_disable(); #endif crash_save_cpu(regs, safe_smp_processor_id()); }
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(); }
void native_machine_crash_shutdown(struct pt_regs *regs) { /* This function is only called after the system * has panicked or is otherwise in a critical state. * The minimum amount of code to allow a kexec'd kernel * to run successfully needs to happen here. * * In practice this means shooting down the other cpus in * an SMP system. */ /* The kernel is broken so disable interrupts */ local_irq_disable(); kdump_nmi_shootdown_cpus(); /* Booting kdump kernel with VMX or SVM enabled won't work, * because (among other limitations) we can't disable paging * with the virt flags. */ cpu_emergency_vmxoff(); cpu_emergency_svm_disable(); lapic_shutdown(); #if defined(CONFIG_X86_IO_APIC) disable_IO_APIC(); #endif #ifdef CONFIG_HPET_TIMER hpet_disable(); #endif //crash_save_cpu(regs, safe_smp_processor_id()); }
void native_machine_shutdown(void) { /* Stop the cpus and apics */ #ifdef CONFIG_X86_IO_APIC disable_IO_APIC(); #endif #ifdef CONFIG_SMP /* * Stop all of the others. Also disable the local irq to * not receive the per-cpu timer interrupt which may trigger * scheduler's load balance. */ local_irq_disable(); stop_other_cpus(); #endif lapic_shutdown(); #ifdef CONFIG_HPET_TIMER hpet_disable(); #endif #ifdef CONFIG_X86_64 x86_platform.iommu_shutdown(); #endif }
void native_machine_crash_shutdown(struct pt_regs *regs) { /* This function is only called after the system * has panicked or is otherwise in a critical state. * The minimum amount of code to allow a kexec'd kernel * to run successfully needs to happen here. * * In practice this means shooting down the other cpus in * an SMP system. */ /* The kernel is broken so disable interrupts */ local_irq_disable(); kdump_nmi_shootdown_cpus(); /* * VMCLEAR VMCSs loaded on this cpu if needed. */ cpu_crash_vmclear_loaded_vmcss(); /* Booting kdump kernel with VMX or SVM enabled won't work, * because (among other limitations) we can't disable paging * with the virt flags. */ cpu_emergency_vmxoff(); cpu_emergency_svm_disable(); lapic_shutdown(); #if defined(CONFIG_X86_IO_APIC) disable_IO_APIC(1); #endif if (mcp55_rewrite) { u32 cfg; printk(KERN_CRIT "REWRITING MCP55 CFG REG\n"); /* * We have a mcp55 chip on board which has been * flagged as only sending legacy interrupts * to the BSP, and we are crashing on an AP * This is obviously bad, and we need to * fix it up. To do this we write to the * flagged device, to the register at offset 0x74 * and we make sure that bit 2 and bit 15 are clear * This forces legacy interrupts to be broadcast * to all cpus */ pci_read_config_dword(mcp55_rewrite, 0x74, &cfg); cfg &= ~((1 << 2) | (1 << 15)); printk(KERN_CRIT "CFG = %x\n", cfg); pci_write_config_dword(mcp55_rewrite, 0x74, cfg); } #ifdef CONFIG_HPET_TIMER hpet_disable(); #endif crash_save_cpu(regs, safe_smp_processor_id()); }
void native_machine_shutdown(void) { /* Stop the cpus and apics */ #ifdef CONFIG_SMP /* The boot cpu is always logical cpu 0 */ int reboot_cpu_id = 0; #endif #ifdef CONFIG_X86_IO_APIC disable_IO_APIC(); #endif #ifdef CONFIG_SMP #ifdef CONFIG_X86_32 /* See if there has been given a command line override */ if ((reboot_cpu != -1) && (reboot_cpu < nr_cpu_ids) && cpu_online(reboot_cpu)) reboot_cpu_id = reboot_cpu; #endif /* Make certain the cpu I'm about to reboot on is online */ if (!cpu_online(reboot_cpu_id)) reboot_cpu_id = smp_processor_id(); /* Make certain I only run on the appropriate processor */ set_cpus_allowed_ptr(current, cpumask_of(reboot_cpu_id)); /* * O.K Now that I'm on the appropriate processor, stop all of the * others. Also disable the local irq to not receive the per-cpu * timer interrupt which may trigger scheduler's load balance. */ local_irq_disable(); stop_other_cpus(); #endif lapic_shutdown(); #ifdef CONFIG_HPET_TIMER hpet_disable(); #endif #ifdef CONFIG_X86_64 x86_platform.iommu_shutdown(); #endif }
/* * 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(); }
void native_machine_crash_shutdown(struct pt_regs *regs) { /* This function is only called after the system * has panicked or is otherwise in a critical state. * The minimum amount of code to allow a kexec'd kernel * to run successfully needs to happen here. * * In practice this means shooting down the other cpus in * an SMP system. */ /* The kernel is broken so disable interrupts */ local_irq_disable(); kdump_nmi_shootdown_cpus(); /* * VMCLEAR VMCSs loaded on this cpu if needed. */ cpu_crash_vmclear_loaded_vmcss(); /* Booting kdump kernel with VMX or SVM enabled won't work, * because (among other limitations) we can't disable paging * with the virt flags. */ cpu_emergency_vmxoff(); cpu_emergency_svm_disable(); /* * Disable Intel PT to stop its logging */ cpu_emergency_stop_pt(); lapic_shutdown(); #ifdef CONFIG_X86_IO_APIC /* Prevent crash_kexec() from deadlocking on ioapic_lock. */ ioapic_zap_locks(); disable_IO_APIC(); #endif #ifdef CONFIG_HPET_TIMER hpet_disable(); #endif crash_save_cpu(regs, safe_smp_processor_id()); }
void machine_restart(char * __unused) { int i; printk("machine restart\n"); #ifdef CONFIG_SMP smp_halt(); #endif if (!reboot_force) { local_irq_disable(); #ifndef CONFIG_SMP disable_local_APIC(); #endif disable_IO_APIC(); local_irq_enable(); } /* Tell the BIOS if we want cold or warm reboot */ *((unsigned short *)__va(0x472)) = reboot_mode; for (;;) { /* Could also try the reset bit in the Hammer NB */ switch (reboot_type) { case BOOT_KBD: for (i=0; i<100; i++) { kb_wait(); udelay(50); outb(0xfe,0x64); /* pulse reset low */ udelay(50); } case BOOT_TRIPLE: __asm__ __volatile__("lidt (%0)": :"r" (&no_idt)); __asm__ __volatile__("int3"); reboot_type = BOOT_KBD; break; } } }
void native_machine_shutdown(void) { /* Stop the cpus and apics */ #ifdef CONFIG_SMP /* The boot cpu is always logical cpu 0 */ int reboot_cpu_id = 0; #ifdef CONFIG_X86_32 /* See if there has been given a command line override */ if ((reboot_cpu != -1) && (reboot_cpu < nr_cpu_ids) && cpu_online(reboot_cpu)) reboot_cpu_id = reboot_cpu; #endif /* Make certain the cpu I'm about to reboot on is online */ if (!cpu_online(reboot_cpu_id)) reboot_cpu_id = smp_processor_id(); /* Make certain I only run on the appropriate processor */ set_cpus_allowed_ptr(current, cpumask_of(reboot_cpu_id)); /* O.K Now that I'm on the appropriate processor, * stop all of the others. */ stop_other_cpus(); #endif lapic_shutdown(); #ifdef CONFIG_X86_IO_APIC disable_IO_APIC(); #endif #ifdef CONFIG_HPET_TIMER hpet_disable(); #endif #ifdef CONFIG_X86_64 x86_platform.iommu_shutdown(); #endif }
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(); }
void native_machine_shutdown(void) { /* Stop the cpus and apics */ #ifdef CONFIG_X86_IO_APIC /* * Disabling IO APIC before local APIC is a workaround for * erratum AVR31 in "Intel Atom Processor C2000 Product Family * Specification Update". In this situation, interrupts that target * a Logical Processor whose Local APIC is either in the process of * being hardware disabled or software disabled are neither delivered * nor discarded. When this erratum occurs, the processor may hang. * * Even without the erratum, it still makes sense to quiet IO APIC * before disabling Local APIC. */ disable_IO_APIC(); #endif #ifdef CONFIG_SMP /* * Stop all of the others. Also disable the local irq to * not receive the per-cpu timer interrupt which may trigger * scheduler's load balance. */ local_irq_disable(); stop_other_cpus(); #endif lapic_shutdown(); #ifdef CONFIG_HPET_TIMER hpet_disable(); #endif #ifdef CONFIG_X86_64 x86_platform.iommu_shutdown(); #endif }