2  * machine_kexec.c - handle transition of Linux booting another kernel 
   6 #include <linux/kexec.h> 
   7 #include <linux/delay.h> 
   8 #include <linux/reboot.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> 
  16 extern const unsigned char relocate_new_kernel
[]; 
  17 extern const unsigned int relocate_new_kernel_size
; 
  19 extern void setup_mm_for_reboot(char mode
); 
  21 extern unsigned long kexec_start_address
; 
  22 extern unsigned long kexec_indirection_page
; 
  23 extern unsigned long kexec_mach_type
; 
  24 extern unsigned long kexec_boot_atags
; 
  26 static atomic_t waiting_for_crash_ipi
; 
  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. 
  33 int machine_kexec_prepare(struct kimage 
*image
) 
  38 void machine_kexec_cleanup(struct kimage 
*image
) 
  42 void machine_crash_nonpanic_core(void *unused
) 
  46         crash_setup_regs(®s
, NULL
); 
  47         printk(KERN_DEBUG 
"CPU %u will stop doing anything useful since another CPU has crashed\n", 
  49         crash_save_cpu(®s
, smp_processor_id()); 
  52         atomic_dec(&waiting_for_crash_ipi
); 
  57 void machine_crash_shutdown(struct pt_regs 
*regs
) 
  63         atomic_set(&waiting_for_crash_ipi
, num_online_cpus() - 1); 
  64         smp_call_function(machine_crash_nonpanic_core
, NULL
, false); 
  65         msecs 
= 1000; /* Wait at most a second for the other cpus to stop */ 
  66         while ((atomic_read(&waiting_for_crash_ipi
) > 0) && msecs
) { 
  70         if (atomic_read(&waiting_for_crash_ipi
) > 0) 
  71                 printk(KERN_WARNING 
"Non-crashing CPUs did not react to IPI\n"); 
  73         crash_save_cpu(regs
, smp_processor_id()); 
  75         printk(KERN_INFO 
"Loading crashdump kernel...\n"); 
  79  * Function pointer to optional machine-specific reinitialization 
  81 void (*kexec_reinit
)(void); 
  83 void machine_kexec(struct kimage 
*image
) 
  85         unsigned long page_list
; 
  86         unsigned long reboot_code_buffer_phys
; 
  87         void *reboot_code_buffer
; 
  90         page_list 
= image
->head 
& PAGE_MASK
; 
  92         /* we need both effective and real address here */ 
  93         reboot_code_buffer_phys 
= 
  94             page_to_pfn(image
->control_code_page
) << PAGE_SHIFT
; 
  95         reboot_code_buffer 
= page_address(image
->control_code_page
); 
  97         /* Prepare parameters for reboot_code_buffer*/ 
  98         kexec_start_address 
= image
->start
; 
  99         kexec_indirection_page 
= page_list
; 
 100         kexec_mach_type 
= machine_arch_type
; 
 101         kexec_boot_atags 
= image
->start 
- KEXEC_ARM_ZIMAGE_OFFSET 
+ KEXEC_ARM_ATAGS_OFFSET
; 
 103         /* copy our kernel relocation code to the control code page */ 
 104         memcpy(reboot_code_buffer
, 
 105                relocate_new_kernel
, relocate_new_kernel_size
); 
 108         flush_icache_range((unsigned long) reboot_code_buffer
, 
 109                            (unsigned long) reboot_code_buffer 
+ KEXEC_CONTROL_PAGE_SIZE
); 
 110         printk(KERN_INFO 
"Bye!\n"); 
 116         setup_mm_for_reboot(0); /* mode is not used, so just pass 0*/ 
 118 #ifdef CONFIG_OUTER_CACHE 
 123 #ifdef CONFIG_OUTER_CACHE 
 127         cpu_reset(reboot_code_buffer_phys
);