machine_kexec.c revision 5aafec15bdc54cf0722696c95091d7bd674bfcad
1/* 2 * machine_kexec.c - handle transition of Linux booting another kernel 3 */ 4 5#include <linux/mm.h> 6#include <linux/kexec.h> 7#include <linux/delay.h> 8#include <linux/reboot.h> 9#include <linux/io.h> 10#include <asm/pgtable.h> 11#include <asm/pgalloc.h> 12#include <asm/mmu_context.h> 13#include <asm/cacheflush.h> 14#include <asm/mach-types.h> 15 16extern const unsigned char relocate_new_kernel[]; 17extern const unsigned int relocate_new_kernel_size; 18 19extern void setup_mm_for_reboot(void); 20 21extern unsigned long kexec_start_address; 22extern unsigned long kexec_indirection_page; 23extern unsigned long kexec_mach_type; 24extern unsigned long kexec_boot_atags; 25 26static atomic_t waiting_for_crash_ipi; 27 28/* 29 * Provide a dummy crash_notes definition while crash dump arrives to arm. 30 * This prevents breakage of crash_notes attribute in kernel/ksysfs.c. 31 */ 32 33int machine_kexec_prepare(struct kimage *image) 34{ 35 unsigned long page_list; 36 void *reboot_code_buffer; 37 page_list = image->head & PAGE_MASK; 38 39 reboot_code_buffer = page_address(image->control_code_page); 40 41 /* Prepare parameters for reboot_code_buffer*/ 42 kexec_start_address = image->start; 43 kexec_indirection_page = page_list; 44 kexec_mach_type = machine_arch_type; 45 kexec_boot_atags = image->start - KEXEC_ARM_ZIMAGE_OFFSET + KEXEC_ARM_ATAGS_OFFSET; 46 47 /* copy our kernel relocation code to the control code page */ 48 memcpy(reboot_code_buffer, 49 relocate_new_kernel, relocate_new_kernel_size); 50 51 flush_icache_range((unsigned long) reboot_code_buffer, 52 (unsigned long) reboot_code_buffer + KEXEC_CONTROL_PAGE_SIZE); 53 return 0; 54} 55 56void machine_kexec_cleanup(struct kimage *image) 57{ 58} 59 60void machine_crash_nonpanic_core(void *unused) 61{ 62 struct pt_regs regs; 63 64 crash_setup_regs(®s, NULL); 65 printk(KERN_DEBUG "CPU %u will stop doing anything useful since another CPU has crashed\n", 66 smp_processor_id()); 67 crash_save_cpu(®s, smp_processor_id()); 68 flush_cache_all(); 69 70 atomic_dec(&waiting_for_crash_ipi); 71 while (1) 72 cpu_relax(); 73} 74 75void machine_crash_shutdown(struct pt_regs *regs) 76{ 77 unsigned long msecs; 78 79 local_irq_disable(); 80 81 atomic_set(&waiting_for_crash_ipi, num_online_cpus() - 1); 82 smp_call_function(machine_crash_nonpanic_core, NULL, false); 83 msecs = 1000; /* Wait at most a second for the other cpus to stop */ 84 while ((atomic_read(&waiting_for_crash_ipi) > 0) && msecs) { 85 mdelay(1); 86 msecs--; 87 } 88 if (atomic_read(&waiting_for_crash_ipi) > 0) 89 printk(KERN_WARNING "Non-crashing CPUs did not react to IPI\n"); 90 91 crash_save_cpu(regs, smp_processor_id()); 92 93 printk(KERN_INFO "Loading crashdump kernel...\n"); 94} 95 96/* 97 * Function pointer to optional machine-specific reinitialization 98 */ 99void (*kexec_reinit)(void); 100 101void machine_kexec(struct kimage *image) 102{ 103 unsigned long reboot_code_buffer_phys; 104 void *reboot_code_buffer; 105 106 /* we need both effective and real address here */ 107 reboot_code_buffer_phys = 108 page_to_pfn(image->control_code_page) << PAGE_SHIFT; 109 reboot_code_buffer = page_address(image->control_code_page); 110 111 printk(KERN_INFO "Bye!\n"); 112 113 if (kexec_reinit) 114 kexec_reinit(); 115 local_irq_disable(); 116 local_fiq_disable(); 117 setup_mm_for_reboot(); 118 flush_cache_all(); 119 outer_flush_all(); 120 outer_disable(); 121 cpu_proc_fin(); 122 outer_inv_all(); 123 flush_cache_all(); 124 cpu_reset(reboot_code_buffer_phys); 125} 126