1 /* 2 * machine_kexec.c for kexec 3 * Created by <nschichan@corp.free.fr> on Thu Oct 12 15:15:06 2006 4 * 5 * This source code is licensed under the GNU General Public License, 6 * Version 2. See the file COPYING for more details. 7 */ 8 #include <linux/compiler.h> 9 #include <linux/kexec.h> 10 #include <linux/mm.h> 11 #include <linux/delay.h> 12 13 #include <asm/cacheflush.h> 14 #include <asm/page.h> 15 16 extern const unsigned char relocate_new_kernel[]; 17 extern const size_t relocate_new_kernel_size; 18 19 extern unsigned long kexec_start_address; 20 extern unsigned long kexec_indirection_page; 21 22 int (*_machine_kexec_prepare)(struct kimage *) = NULL; 23 void (*_machine_kexec_shutdown)(void) = NULL; 24 void (*_machine_crash_shutdown)(struct pt_regs *regs) = NULL; 25 #ifdef CONFIG_SMP 26 void (*relocated_kexec_smp_wait) (void *); 27 atomic_t kexec_ready_to_reboot = ATOMIC_INIT(0); 28 void (*_crash_smp_send_stop)(void) = NULL; 29 #endif 30 31 int machine_kexec_prepare(struct kimage * kimage)32machine_kexec_prepare(struct kimage *kimage) 33 { 34 if (_machine_kexec_prepare) 35 return _machine_kexec_prepare(kimage); 36 return 0; 37 } 38 39 void machine_kexec_cleanup(struct kimage * kimage)40machine_kexec_cleanup(struct kimage *kimage) 41 { 42 } 43 44 void machine_shutdown(void)45machine_shutdown(void) 46 { 47 if (_machine_kexec_shutdown) 48 _machine_kexec_shutdown(); 49 } 50 51 void machine_crash_shutdown(struct pt_regs * regs)52machine_crash_shutdown(struct pt_regs *regs) 53 { 54 if (_machine_crash_shutdown) 55 _machine_crash_shutdown(regs); 56 else 57 default_machine_crash_shutdown(regs); 58 } 59 60 typedef void (*noretfun_t)(void) __noreturn; 61 62 void machine_kexec(struct kimage * image)63machine_kexec(struct kimage *image) 64 { 65 unsigned long reboot_code_buffer; 66 unsigned long entry; 67 unsigned long *ptr; 68 69 reboot_code_buffer = 70 (unsigned long)page_address(image->control_code_page); 71 72 kexec_start_address = 73 (unsigned long) phys_to_virt(image->start); 74 75 if (image->type == KEXEC_TYPE_DEFAULT) { 76 kexec_indirection_page = 77 (unsigned long) phys_to_virt(image->head & PAGE_MASK); 78 } else { 79 kexec_indirection_page = (unsigned long)&image->head; 80 } 81 82 memcpy((void*)reboot_code_buffer, relocate_new_kernel, 83 relocate_new_kernel_size); 84 85 /* 86 * The generic kexec code builds a page list with physical 87 * addresses. they are directly accessible through KSEG0 (or 88 * CKSEG0 or XPHYS if on 64bit system), hence the 89 * phys_to_virt() call. 90 */ 91 for (ptr = &image->head; (entry = *ptr) && !(entry &IND_DONE); 92 ptr = (entry & IND_INDIRECTION) ? 93 phys_to_virt(entry & PAGE_MASK) : ptr + 1) { 94 if (*ptr & IND_SOURCE || *ptr & IND_INDIRECTION || 95 *ptr & IND_DESTINATION) 96 *ptr = (unsigned long) phys_to_virt(*ptr); 97 } 98 99 /* Mark offline BEFORE disabling local irq. */ 100 set_cpu_online(smp_processor_id(), false); 101 102 /* 103 * we do not want to be bothered. 104 */ 105 local_irq_disable(); 106 107 printk("Will call new kernel at %08lx\n", image->start); 108 printk("Bye ...\n"); 109 __flush_cache_all(); 110 #ifdef CONFIG_SMP 111 /* All secondary cpus now may jump to kexec_wait cycle */ 112 relocated_kexec_smp_wait = reboot_code_buffer + 113 (void *)(kexec_smp_wait - relocate_new_kernel); 114 smp_wmb(); 115 atomic_set(&kexec_ready_to_reboot, 1); 116 #endif 117 ((noretfun_t) reboot_code_buffer)(); 118 } 119