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