machine_kexec.c (6037B)
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * machine_kexec.c for kexec 4 * Created by <nschichan@corp.free.fr> on Thu Oct 12 15:15:06 2006 5 */ 6#include <linux/compiler.h> 7#include <linux/kexec.h> 8#include <linux/mm.h> 9#include <linux/delay.h> 10#include <linux/libfdt.h> 11 12#include <asm/cacheflush.h> 13#include <asm/page.h> 14 15extern const unsigned char relocate_new_kernel[]; 16extern const size_t relocate_new_kernel_size; 17 18extern unsigned long kexec_start_address; 19extern unsigned long kexec_indirection_page; 20 21static unsigned long reboot_code_buffer; 22 23#ifdef CONFIG_SMP 24static void (*relocated_kexec_smp_wait)(void *); 25 26atomic_t kexec_ready_to_reboot = ATOMIC_INIT(0); 27void (*_crash_smp_send_stop)(void) = NULL; 28#endif 29 30void (*_machine_kexec_shutdown)(void) = NULL; 31void (*_machine_crash_shutdown)(struct pt_regs *regs) = NULL; 32 33static void kexec_image_info(const struct kimage *kimage) 34{ 35 unsigned long i; 36 37 pr_debug("kexec kimage info:\n"); 38 pr_debug(" type: %d\n", kimage->type); 39 pr_debug(" start: %lx\n", kimage->start); 40 pr_debug(" head: %lx\n", kimage->head); 41 pr_debug(" nr_segments: %lu\n", kimage->nr_segments); 42 43 for (i = 0; i < kimage->nr_segments; i++) { 44 pr_debug(" segment[%lu]: %016lx - %016lx, 0x%lx bytes, %lu pages\n", 45 i, 46 kimage->segment[i].mem, 47 kimage->segment[i].mem + kimage->segment[i].memsz, 48 (unsigned long)kimage->segment[i].memsz, 49 (unsigned long)kimage->segment[i].memsz / PAGE_SIZE); 50 } 51} 52 53#ifdef CONFIG_UHI_BOOT 54 55static int uhi_machine_kexec_prepare(struct kimage *kimage) 56{ 57 int i; 58 59 /* 60 * In case DTB file is not passed to the new kernel, a flat device 61 * tree will be created by kexec tool. It holds modified command 62 * line for the new kernel. 63 */ 64 for (i = 0; i < kimage->nr_segments; i++) { 65 struct fdt_header fdt; 66 67 if (kimage->segment[i].memsz <= sizeof(fdt)) 68 continue; 69 70 if (copy_from_user(&fdt, kimage->segment[i].buf, sizeof(fdt))) 71 continue; 72 73 if (fdt_check_header(&fdt)) 74 continue; 75 76 kexec_args[0] = -2; 77 kexec_args[1] = (unsigned long) 78 phys_to_virt((unsigned long)kimage->segment[i].mem); 79 break; 80 } 81 82 return 0; 83} 84 85int (*_machine_kexec_prepare)(struct kimage *) = uhi_machine_kexec_prepare; 86 87#else 88 89int (*_machine_kexec_prepare)(struct kimage *) = NULL; 90 91#endif /* CONFIG_UHI_BOOT */ 92 93int 94machine_kexec_prepare(struct kimage *kimage) 95{ 96#ifdef CONFIG_SMP 97 if (!kexec_nonboot_cpu_func()) 98 return -EINVAL; 99#endif 100 101 kexec_image_info(kimage); 102 103 if (_machine_kexec_prepare) 104 return _machine_kexec_prepare(kimage); 105 106 return 0; 107} 108 109void 110machine_kexec_cleanup(struct kimage *kimage) 111{ 112} 113 114#ifdef CONFIG_SMP 115static void kexec_shutdown_secondary(void *param) 116{ 117 int cpu = smp_processor_id(); 118 119 if (!cpu_online(cpu)) 120 return; 121 122 /* We won't be sent IPIs any more. */ 123 set_cpu_online(cpu, false); 124 125 local_irq_disable(); 126 while (!atomic_read(&kexec_ready_to_reboot)) 127 cpu_relax(); 128 129 kexec_reboot(); 130 131 /* NOTREACHED */ 132} 133#endif 134 135void 136machine_shutdown(void) 137{ 138 if (_machine_kexec_shutdown) 139 _machine_kexec_shutdown(); 140 141#ifdef CONFIG_SMP 142 smp_call_function(kexec_shutdown_secondary, NULL, 0); 143 144 while (num_online_cpus() > 1) { 145 cpu_relax(); 146 mdelay(1); 147 } 148#endif 149} 150 151void 152machine_crash_shutdown(struct pt_regs *regs) 153{ 154 if (_machine_crash_shutdown) 155 _machine_crash_shutdown(regs); 156 else 157 default_machine_crash_shutdown(regs); 158} 159 160#ifdef CONFIG_SMP 161void kexec_nonboot_cpu_jump(void) 162{ 163 local_flush_icache_range((unsigned long)relocated_kexec_smp_wait, 164 reboot_code_buffer + relocate_new_kernel_size); 165 166 relocated_kexec_smp_wait(NULL); 167} 168#endif 169 170void kexec_reboot(void) 171{ 172 void (*do_kexec)(void) __noreturn; 173 174 /* 175 * We know we were online, and there will be no incoming IPIs at 176 * this point. Mark online again before rebooting so that the crash 177 * analysis tool will see us correctly. 178 */ 179 set_cpu_online(smp_processor_id(), true); 180 181 /* Ensure remote CPUs observe that we're online before rebooting. */ 182 smp_mb__after_atomic(); 183 184#ifdef CONFIG_SMP 185 if (smp_processor_id() > 0) { 186 /* 187 * Instead of cpu_relax() or wait, this is needed for kexec 188 * smp reboot. Kdump usually doesn't require an smp new 189 * kernel, but kexec may do. 190 */ 191 kexec_nonboot_cpu(); 192 193 /* NOTREACHED */ 194 } 195#endif 196 197 /* 198 * Make sure we get correct instructions written by the 199 * machine_kexec() CPU. 200 */ 201 local_flush_icache_range(reboot_code_buffer, 202 reboot_code_buffer + relocate_new_kernel_size); 203 204 do_kexec = (void *)reboot_code_buffer; 205 do_kexec(); 206} 207 208void 209machine_kexec(struct kimage *image) 210{ 211 unsigned long entry; 212 unsigned long *ptr; 213 214 reboot_code_buffer = 215 (unsigned long)page_address(image->control_code_page); 216 217 kexec_start_address = 218 (unsigned long) phys_to_virt(image->start); 219 220 if (image->type == KEXEC_TYPE_DEFAULT) { 221 kexec_indirection_page = 222 (unsigned long) phys_to_virt(image->head & PAGE_MASK); 223 } else { 224 kexec_indirection_page = (unsigned long)&image->head; 225 } 226 227 memcpy((void*)reboot_code_buffer, relocate_new_kernel, 228 relocate_new_kernel_size); 229 230 /* 231 * The generic kexec code builds a page list with physical 232 * addresses. they are directly accessible through KSEG0 (or 233 * CKSEG0 or XPHYS if on 64bit system), hence the 234 * phys_to_virt() call. 235 */ 236 for (ptr = &image->head; (entry = *ptr) && !(entry &IND_DONE); 237 ptr = (entry & IND_INDIRECTION) ? 238 phys_to_virt(entry & PAGE_MASK) : ptr + 1) { 239 if (*ptr & IND_SOURCE || *ptr & IND_INDIRECTION || 240 *ptr & IND_DESTINATION) 241 *ptr = (unsigned long) phys_to_virt(*ptr); 242 } 243 244 /* Mark offline BEFORE disabling local irq. */ 245 set_cpu_online(smp_processor_id(), false); 246 247 /* 248 * we do not want to be bothered. 249 */ 250 local_irq_disable(); 251 252 printk("Will call new kernel at %08lx\n", image->start); 253 printk("Bye ...\n"); 254 /* Make reboot code buffer available to the boot CPU. */ 255 __flush_cache_all(); 256#ifdef CONFIG_SMP 257 /* All secondary cpus now may jump to kexec_wait cycle */ 258 relocated_kexec_smp_wait = reboot_code_buffer + 259 (void *)(kexec_smp_wait - relocate_new_kernel); 260 smp_wmb(); 261 atomic_set(&kexec_ready_to_reboot, 1); 262#endif 263 kexec_reboot(); 264}