machine_kexec.c revision 95f72d1ed41a66f1c1c29c24d479de81a0bea36f
19d44190eae97ad4c9ce30f1084e1b0dabd646df5kogiidena/* 29d44190eae97ad4c9ce30f1084e1b0dabd646df5kogiidena * machine_kexec.c - handle transition of Linux booting another kernel 39d44190eae97ad4c9ce30f1084e1b0dabd646df5kogiidena * Copyright (C) 2002-2003 Eric Biederman <ebiederm@xmission.com> 49d44190eae97ad4c9ce30f1084e1b0dabd646df5kogiidena * 59d44190eae97ad4c9ce30f1084e1b0dabd646df5kogiidena * GameCube/ppc32 port Copyright (C) 2004 Albert Herranz 69d44190eae97ad4c9ce30f1084e1b0dabd646df5kogiidena * LANDISK/sh4 supported by kogiidena 79d44190eae97ad4c9ce30f1084e1b0dabd646df5kogiidena * 89d44190eae97ad4c9ce30f1084e1b0dabd646df5kogiidena * This source code is licensed under the GNU General Public License, 99d44190eae97ad4c9ce30f1084e1b0dabd646df5kogiidena * Version 2. See the file COPYING for more details. 109d44190eae97ad4c9ce30f1084e1b0dabd646df5kogiidena */ 119d44190eae97ad4c9ce30f1084e1b0dabd646df5kogiidena#include <linux/mm.h> 129d44190eae97ad4c9ce30f1084e1b0dabd646df5kogiidena#include <linux/kexec.h> 139d44190eae97ad4c9ce30f1084e1b0dabd646df5kogiidena#include <linux/delay.h> 149d44190eae97ad4c9ce30f1084e1b0dabd646df5kogiidena#include <linux/reboot.h> 15c3b4adfa65bae300a143188491e285556ca80fffPaul Mundt#include <linux/numa.h> 167e6b6f2b949a52382f59a93ecbe86e32e4fcec7cPaul Mundt#include <linux/ftrace.h> 17b7cf6ddc13186f9272438a97aa75972d496d0b0aMagnus Damm#include <linux/suspend.h> 1895f72d1ed41a66f1c1c29c24d479de81a0bea36fYinghai Lu#include <linux/memblock.h> 199d44190eae97ad4c9ce30f1084e1b0dabd646df5kogiidena#include <asm/pgtable.h> 209d44190eae97ad4c9ce30f1084e1b0dabd646df5kogiidena#include <asm/pgalloc.h> 219d44190eae97ad4c9ce30f1084e1b0dabd646df5kogiidena#include <asm/mmu_context.h> 229d44190eae97ad4c9ce30f1084e1b0dabd646df5kogiidena#include <asm/io.h> 239d44190eae97ad4c9ce30f1084e1b0dabd646df5kogiidena#include <asm/cacheflush.h> 24191d0d24b632eb69767705acded5cbf7449ad457Paul Mundt#include <asm/sh_bios.h> 25fbb82b03653cdb7fd1863b911e7540011259d2cePaul Mundt#include <asm/reboot.h> 269d44190eae97ad4c9ce30f1084e1b0dabd646df5kogiidena 27b7cf6ddc13186f9272438a97aa75972d496d0b0aMagnus Dammtypedef void (*relocate_new_kernel_t)(unsigned long indirection_page, 28b7cf6ddc13186f9272438a97aa75972d496d0b0aMagnus Damm unsigned long reboot_code_buffer, 29b7cf6ddc13186f9272438a97aa75972d496d0b0aMagnus Damm unsigned long start_address); 309d44190eae97ad4c9ce30f1084e1b0dabd646df5kogiidena 312efe55a9cec8418f0e0cde3dc3787a42fddc4411Tobias Klauserextern const unsigned char relocate_new_kernel[]; 322efe55a9cec8418f0e0cde3dc3787a42fddc4411Tobias Klauserextern const unsigned int relocate_new_kernel_size; 33b7cf6ddc13186f9272438a97aa75972d496d0b0aMagnus Dammextern void *vbr_base; 349d44190eae97ad4c9ce30f1084e1b0dabd646df5kogiidena 35fbb82b03653cdb7fd1863b911e7540011259d2cePaul Mundtvoid native_machine_crash_shutdown(struct pt_regs *regs) 369d44190eae97ad4c9ce30f1084e1b0dabd646df5kogiidena{ 37fbb82b03653cdb7fd1863b911e7540011259d2cePaul Mundt /* Nothing to do for UP, but definitely broken for SMP.. */ 389d44190eae97ad4c9ce30f1084e1b0dabd646df5kogiidena} 399d44190eae97ad4c9ce30f1084e1b0dabd646df5kogiidena 409d44190eae97ad4c9ce30f1084e1b0dabd646df5kogiidena/* 419d44190eae97ad4c9ce30f1084e1b0dabd646df5kogiidena * Do what every setup is needed on image and the 429d44190eae97ad4c9ce30f1084e1b0dabd646df5kogiidena * reboot code buffer to allow us to avoid allocations 439d44190eae97ad4c9ce30f1084e1b0dabd646df5kogiidena * later. 449d44190eae97ad4c9ce30f1084e1b0dabd646df5kogiidena */ 459d44190eae97ad4c9ce30f1084e1b0dabd646df5kogiidenaint machine_kexec_prepare(struct kimage *image) 469d44190eae97ad4c9ce30f1084e1b0dabd646df5kogiidena{ 479d44190eae97ad4c9ce30f1084e1b0dabd646df5kogiidena return 0; 489d44190eae97ad4c9ce30f1084e1b0dabd646df5kogiidena} 499d44190eae97ad4c9ce30f1084e1b0dabd646df5kogiidena 509d44190eae97ad4c9ce30f1084e1b0dabd646df5kogiidenavoid machine_kexec_cleanup(struct kimage *image) 519d44190eae97ad4c9ce30f1084e1b0dabd646df5kogiidena{ 529d44190eae97ad4c9ce30f1084e1b0dabd646df5kogiidena} 539d44190eae97ad4c9ce30f1084e1b0dabd646df5kogiidena 549d44190eae97ad4c9ce30f1084e1b0dabd646df5kogiidenastatic void kexec_info(struct kimage *image) 559d44190eae97ad4c9ce30f1084e1b0dabd646df5kogiidena{ 569d44190eae97ad4c9ce30f1084e1b0dabd646df5kogiidena int i; 579d44190eae97ad4c9ce30f1084e1b0dabd646df5kogiidena printk("kexec information\n"); 589d44190eae97ad4c9ce30f1084e1b0dabd646df5kogiidena for (i = 0; i < image->nr_segments; i++) { 599d44190eae97ad4c9ce30f1084e1b0dabd646df5kogiidena printk(" segment[%d]: 0x%08x - 0x%08x (0x%08x)\n", 609d44190eae97ad4c9ce30f1084e1b0dabd646df5kogiidena i, 619d44190eae97ad4c9ce30f1084e1b0dabd646df5kogiidena (unsigned int)image->segment[i].mem, 624d5ade5b29c618e97a8988efb6967cb4dd0e2183Paul Mundt (unsigned int)image->segment[i].mem + 634d5ade5b29c618e97a8988efb6967cb4dd0e2183Paul Mundt image->segment[i].memsz, 649d44190eae97ad4c9ce30f1084e1b0dabd646df5kogiidena (unsigned int)image->segment[i].memsz); 654d5ade5b29c618e97a8988efb6967cb4dd0e2183Paul Mundt } 669d44190eae97ad4c9ce30f1084e1b0dabd646df5kogiidena printk(" start : 0x%08x\n\n", (unsigned int)image->start); 679d44190eae97ad4c9ce30f1084e1b0dabd646df5kogiidena} 689d44190eae97ad4c9ce30f1084e1b0dabd646df5kogiidena 699d44190eae97ad4c9ce30f1084e1b0dabd646df5kogiidena/* 709d44190eae97ad4c9ce30f1084e1b0dabd646df5kogiidena * Do not allocate memory (or fail in any way) in machine_kexec(). 719d44190eae97ad4c9ce30f1084e1b0dabd646df5kogiidena * We are past the point of no return, committed to rebooting now. 729d44190eae97ad4c9ce30f1084e1b0dabd646df5kogiidena */ 733ab83521378268044a448113c6aa9a9e245f4d2fHuang Yingvoid machine_kexec(struct kimage *image) 749d44190eae97ad4c9ce30f1084e1b0dabd646df5kogiidena{ 759d44190eae97ad4c9ce30f1084e1b0dabd646df5kogiidena unsigned long page_list; 769d44190eae97ad4c9ce30f1084e1b0dabd646df5kogiidena unsigned long reboot_code_buffer; 779d44190eae97ad4c9ce30f1084e1b0dabd646df5kogiidena relocate_new_kernel_t rnk; 78e4e063d0c288bd65c56dd855337780a541ed928dMagnus Damm unsigned long entry; 79e4e063d0c288bd65c56dd855337780a541ed928dMagnus Damm unsigned long *ptr; 807e6b6f2b949a52382f59a93ecbe86e32e4fcec7cPaul Mundt int save_ftrace_enabled; 81e4e063d0c288bd65c56dd855337780a541ed928dMagnus Damm 82e4e063d0c288bd65c56dd855337780a541ed928dMagnus Damm /* 83e4e063d0c288bd65c56dd855337780a541ed928dMagnus Damm * Nicked from the mips version of machine_kexec(): 84e4e063d0c288bd65c56dd855337780a541ed928dMagnus Damm * The generic kexec code builds a page list with physical 85e4e063d0c288bd65c56dd855337780a541ed928dMagnus Damm * addresses. Use phys_to_virt() to convert them to virtual. 86e4e063d0c288bd65c56dd855337780a541ed928dMagnus Damm */ 87e4e063d0c288bd65c56dd855337780a541ed928dMagnus Damm for (ptr = &image->head; (entry = *ptr) && !(entry & IND_DONE); 88e4e063d0c288bd65c56dd855337780a541ed928dMagnus Damm ptr = (entry & IND_INDIRECTION) ? 89e4e063d0c288bd65c56dd855337780a541ed928dMagnus Damm phys_to_virt(entry & PAGE_MASK) : ptr + 1) { 90e4e063d0c288bd65c56dd855337780a541ed928dMagnus Damm if (*ptr & IND_SOURCE || *ptr & IND_INDIRECTION || 91e4e063d0c288bd65c56dd855337780a541ed928dMagnus Damm *ptr & IND_DESTINATION) 92e4e063d0c288bd65c56dd855337780a541ed928dMagnus Damm *ptr = (unsigned long) phys_to_virt(*ptr); 93e4e063d0c288bd65c56dd855337780a541ed928dMagnus Damm } 949d44190eae97ad4c9ce30f1084e1b0dabd646df5kogiidena 95b7cf6ddc13186f9272438a97aa75972d496d0b0aMagnus Damm#ifdef CONFIG_KEXEC_JUMP 96b7cf6ddc13186f9272438a97aa75972d496d0b0aMagnus Damm if (image->preserve_context) 97b7cf6ddc13186f9272438a97aa75972d496d0b0aMagnus Damm save_processor_state(); 98b7cf6ddc13186f9272438a97aa75972d496d0b0aMagnus Damm#endif 99b7cf6ddc13186f9272438a97aa75972d496d0b0aMagnus Damm 1007e6b6f2b949a52382f59a93ecbe86e32e4fcec7cPaul Mundt save_ftrace_enabled = __ftrace_enabled_save(); 1017e6b6f2b949a52382f59a93ecbe86e32e4fcec7cPaul Mundt 1029d44190eae97ad4c9ce30f1084e1b0dabd646df5kogiidena /* Interrupts aren't acceptable while we reboot */ 1039d44190eae97ad4c9ce30f1084e1b0dabd646df5kogiidena local_irq_disable(); 1049d44190eae97ad4c9ce30f1084e1b0dabd646df5kogiidena 1059d44190eae97ad4c9ce30f1084e1b0dabd646df5kogiidena page_list = image->head; 1069d44190eae97ad4c9ce30f1084e1b0dabd646df5kogiidena 1079d44190eae97ad4c9ce30f1084e1b0dabd646df5kogiidena /* we need both effective and real address here */ 1089d44190eae97ad4c9ce30f1084e1b0dabd646df5kogiidena reboot_code_buffer = 1099d44190eae97ad4c9ce30f1084e1b0dabd646df5kogiidena (unsigned long)page_address(image->control_code_page); 1109d44190eae97ad4c9ce30f1084e1b0dabd646df5kogiidena 1119d44190eae97ad4c9ce30f1084e1b0dabd646df5kogiidena /* copy our kernel relocation code to the control code page */ 1129d44190eae97ad4c9ce30f1084e1b0dabd646df5kogiidena memcpy((void *)reboot_code_buffer, relocate_new_kernel, 1139d44190eae97ad4c9ce30f1084e1b0dabd646df5kogiidena relocate_new_kernel_size); 1149d44190eae97ad4c9ce30f1084e1b0dabd646df5kogiidena 115a6bab7b5c18501e4dd3201ae8ac1dc6da5f07accPaul Mundt kexec_info(image); 1169d44190eae97ad4c9ce30f1084e1b0dabd646df5kogiidena flush_cache_all(); 1179d44190eae97ad4c9ce30f1084e1b0dabd646df5kogiidena 118191d0d24b632eb69767705acded5cbf7449ad457Paul Mundt sh_bios_vbr_reload(); 119a6bab7b5c18501e4dd3201ae8ac1dc6da5f07accPaul Mundt 1209d44190eae97ad4c9ce30f1084e1b0dabd646df5kogiidena /* now call it */ 1219d44190eae97ad4c9ce30f1084e1b0dabd646df5kogiidena rnk = (relocate_new_kernel_t) reboot_code_buffer; 122615e73b3cd8876262f61ea28b4147c8de38a043aMagnus Damm (*rnk)(page_list, reboot_code_buffer, 123615e73b3cd8876262f61ea28b4147c8de38a043aMagnus Damm (unsigned long)phys_to_virt(image->start)); 124b7cf6ddc13186f9272438a97aa75972d496d0b0aMagnus Damm 125b7cf6ddc13186f9272438a97aa75972d496d0b0aMagnus Damm#ifdef CONFIG_KEXEC_JUMP 126b7cf6ddc13186f9272438a97aa75972d496d0b0aMagnus Damm asm volatile("ldc %0, vbr" : : "r" (&vbr_base) : "memory"); 127a6bab7b5c18501e4dd3201ae8ac1dc6da5f07accPaul Mundt 128b7cf6ddc13186f9272438a97aa75972d496d0b0aMagnus Damm if (image->preserve_context) 129b7cf6ddc13186f9272438a97aa75972d496d0b0aMagnus Damm restore_processor_state(); 130b7cf6ddc13186f9272438a97aa75972d496d0b0aMagnus Damm 131b7cf6ddc13186f9272438a97aa75972d496d0b0aMagnus Damm /* Convert page list back to physical addresses, what a mess. */ 132b7cf6ddc13186f9272438a97aa75972d496d0b0aMagnus Damm for (ptr = &image->head; (entry = *ptr) && !(entry & IND_DONE); 133b7cf6ddc13186f9272438a97aa75972d496d0b0aMagnus Damm ptr = (*ptr & IND_INDIRECTION) ? 134b7cf6ddc13186f9272438a97aa75972d496d0b0aMagnus Damm phys_to_virt(*ptr & PAGE_MASK) : ptr + 1) { 135b7cf6ddc13186f9272438a97aa75972d496d0b0aMagnus Damm if (*ptr & IND_SOURCE || *ptr & IND_INDIRECTION || 136b7cf6ddc13186f9272438a97aa75972d496d0b0aMagnus Damm *ptr & IND_DESTINATION) 137b7cf6ddc13186f9272438a97aa75972d496d0b0aMagnus Damm *ptr = virt_to_phys(*ptr); 138b7cf6ddc13186f9272438a97aa75972d496d0b0aMagnus Damm } 139b7cf6ddc13186f9272438a97aa75972d496d0b0aMagnus Damm#endif 1407e6b6f2b949a52382f59a93ecbe86e32e4fcec7cPaul Mundt 1417e6b6f2b949a52382f59a93ecbe86e32e4fcec7cPaul Mundt __ftrace_enabled_restore(save_ftrace_enabled); 1429d44190eae97ad4c9ce30f1084e1b0dabd646df5kogiidena} 1439d44190eae97ad4c9ce30f1084e1b0dabd646df5kogiidena 144c3b4adfa65bae300a143188491e285556ca80fffPaul Mundtvoid arch_crash_save_vmcoreinfo(void) 145c3b4adfa65bae300a143188491e285556ca80fffPaul Mundt{ 146c3b4adfa65bae300a143188491e285556ca80fffPaul Mundt#ifdef CONFIG_NUMA 147c3b4adfa65bae300a143188491e285556ca80fffPaul Mundt VMCOREINFO_SYMBOL(node_data); 148c3b4adfa65bae300a143188491e285556ca80fffPaul Mundt VMCOREINFO_LENGTH(node_data, MAX_NUMNODES); 149c3b4adfa65bae300a143188491e285556ca80fffPaul Mundt#endif 150aa424bbb8cf5f7f3c6a70065bcb28a6e6af7897dPaul Mundt#ifdef CONFIG_X2TLB 151aa424bbb8cf5f7f3c6a70065bcb28a6e6af7897dPaul Mundt VMCOREINFO_CONFIG(X2TLB); 152aa424bbb8cf5f7f3c6a70065bcb28a6e6af7897dPaul Mundt#endif 153c3b4adfa65bae300a143188491e285556ca80fffPaul Mundt} 154a5ec39507129a086d8838228ac1ca0a2eab38f91Paul Mundt 155a5ec39507129a086d8838228ac1ca0a2eab38f91Paul Mundtvoid __init reserve_crashkernel(void) 156a5ec39507129a086d8838228ac1ca0a2eab38f91Paul Mundt{ 157a5ec39507129a086d8838228ac1ca0a2eab38f91Paul Mundt unsigned long long crash_size, crash_base; 158a5ec39507129a086d8838228ac1ca0a2eab38f91Paul Mundt int ret; 159a5ec39507129a086d8838228ac1ca0a2eab38f91Paul Mundt 16095f72d1ed41a66f1c1c29c24d479de81a0bea36fYinghai Lu /* this is necessary because of memblock_phys_mem_size() */ 16195f72d1ed41a66f1c1c29c24d479de81a0bea36fYinghai Lu memblock_analyze(); 162a5ec39507129a086d8838228ac1ca0a2eab38f91Paul Mundt 16395f72d1ed41a66f1c1c29c24d479de81a0bea36fYinghai Lu ret = parse_crashkernel(boot_command_line, memblock_phys_mem_size(), 164a5ec39507129a086d8838228ac1ca0a2eab38f91Paul Mundt &crash_size, &crash_base); 165a5ec39507129a086d8838228ac1ca0a2eab38f91Paul Mundt if (ret == 0 && crash_size > 0) { 166a5ec39507129a086d8838228ac1ca0a2eab38f91Paul Mundt crashk_res.start = crash_base; 167a5ec39507129a086d8838228ac1ca0a2eab38f91Paul Mundt crashk_res.end = crash_base + crash_size - 1; 168a5ec39507129a086d8838228ac1ca0a2eab38f91Paul Mundt } 169a5ec39507129a086d8838228ac1ca0a2eab38f91Paul Mundt 170a5ec39507129a086d8838228ac1ca0a2eab38f91Paul Mundt if (crashk_res.end == crashk_res.start) 171a5ec39507129a086d8838228ac1ca0a2eab38f91Paul Mundt goto disable; 172a5ec39507129a086d8838228ac1ca0a2eab38f91Paul Mundt 173a5ec39507129a086d8838228ac1ca0a2eab38f91Paul Mundt crash_size = PAGE_ALIGN(crashk_res.end - crashk_res.start + 1); 174a5ec39507129a086d8838228ac1ca0a2eab38f91Paul Mundt if (!crashk_res.start) { 17595f72d1ed41a66f1c1c29c24d479de81a0bea36fYinghai Lu unsigned long max = memblock_end_of_DRAM() - memory_limit; 17695f72d1ed41a66f1c1c29c24d479de81a0bea36fYinghai Lu crashk_res.start = __memblock_alloc_base(crash_size, PAGE_SIZE, max); 177a5ec39507129a086d8838228ac1ca0a2eab38f91Paul Mundt if (!crashk_res.start) { 178a5ec39507129a086d8838228ac1ca0a2eab38f91Paul Mundt pr_err("crashkernel allocation failed\n"); 179a5ec39507129a086d8838228ac1ca0a2eab38f91Paul Mundt goto disable; 180a5ec39507129a086d8838228ac1ca0a2eab38f91Paul Mundt } 181a5ec39507129a086d8838228ac1ca0a2eab38f91Paul Mundt } else { 18295f72d1ed41a66f1c1c29c24d479de81a0bea36fYinghai Lu ret = memblock_reserve(crashk_res.start, crash_size); 183a5ec39507129a086d8838228ac1ca0a2eab38f91Paul Mundt if (unlikely(ret < 0)) { 184a5ec39507129a086d8838228ac1ca0a2eab38f91Paul Mundt pr_err("crashkernel reservation failed - " 185a5ec39507129a086d8838228ac1ca0a2eab38f91Paul Mundt "memory is in use\n"); 186a5ec39507129a086d8838228ac1ca0a2eab38f91Paul Mundt goto disable; 187a5ec39507129a086d8838228ac1ca0a2eab38f91Paul Mundt } 188a5ec39507129a086d8838228ac1ca0a2eab38f91Paul Mundt } 189a5ec39507129a086d8838228ac1ca0a2eab38f91Paul Mundt 1905e2ff328c0668794ff408a4632f5b8a62827571fPaul Mundt crashk_res.end = crashk_res.start + crash_size - 1; 1915e2ff328c0668794ff408a4632f5b8a62827571fPaul Mundt 1925e2ff328c0668794ff408a4632f5b8a62827571fPaul Mundt /* 1935e2ff328c0668794ff408a4632f5b8a62827571fPaul Mundt * Crash kernel trumps memory limit 1945e2ff328c0668794ff408a4632f5b8a62827571fPaul Mundt */ 19595f72d1ed41a66f1c1c29c24d479de81a0bea36fYinghai Lu if ((memblock_end_of_DRAM() - memory_limit) <= crashk_res.end) { 1965e2ff328c0668794ff408a4632f5b8a62827571fPaul Mundt memory_limit = 0; 1975e2ff328c0668794ff408a4632f5b8a62827571fPaul Mundt pr_info("Disabled memory limit for crashkernel\n"); 1985e2ff328c0668794ff408a4632f5b8a62827571fPaul Mundt } 1995e2ff328c0668794ff408a4632f5b8a62827571fPaul Mundt 2005e2ff328c0668794ff408a4632f5b8a62827571fPaul Mundt pr_info("Reserving %ldMB of memory at 0x%08lx " 201a5ec39507129a086d8838228ac1ca0a2eab38f91Paul Mundt "for crashkernel (System RAM: %ldMB)\n", 202a5ec39507129a086d8838228ac1ca0a2eab38f91Paul Mundt (unsigned long)(crash_size >> 20), 2035e2ff328c0668794ff408a4632f5b8a62827571fPaul Mundt (unsigned long)(crashk_res.start), 20495f72d1ed41a66f1c1c29c24d479de81a0bea36fYinghai Lu (unsigned long)(memblock_phys_mem_size() >> 20)); 205a5ec39507129a086d8838228ac1ca0a2eab38f91Paul Mundt 206a5ec39507129a086d8838228ac1ca0a2eab38f91Paul Mundt return; 207a5ec39507129a086d8838228ac1ca0a2eab38f91Paul Mundt 208a5ec39507129a086d8838228ac1ca0a2eab38f91Paul Mundtdisable: 209a5ec39507129a086d8838228ac1ca0a2eab38f91Paul Mundt crashk_res.start = crashk_res.end = 0; 210a5ec39507129a086d8838228ac1ca0a2eab38f91Paul Mundt} 211