1 /* 2 * arch/ia64/kernel/machine_kexec.c 3 * 4 * Handle transition of Linux booting another kernel 5 * Copyright (C) 2005 Hewlett-Packard Development Comapny, L.P. 6 * Copyright (C) 2005 Khalid Aziz <khalid.aziz@hp.com> 7 * Copyright (C) 2006 Intel Corp, Zou Nan hai <nanhai.zou@intel.com> 8 * 9 * This source code is licensed under the GNU General Public License, 10 * Version 2. See the file COPYING for more details. 11 */ 12 13 #include <linux/mm.h> 14 #include <linux/kexec.h> 15 #include <linux/cpu.h> 16 #include <linux/irq.h> 17 #include <linux/efi.h> 18 #include <asm/mmu_context.h> 19 #include <asm/setup.h> 20 #include <asm/delay.h> 21 #include <asm/meminit.h> 22 23 typedef NORET_TYPE void (*relocate_new_kernel_t)( 24 unsigned long indirection_page, 25 unsigned long start_address, 26 struct ia64_boot_param *boot_param, 27 unsigned long pal_addr) ATTRIB_NORET; 28 29 struct kimage *ia64_kimage; 30 31 struct resource efi_memmap_res = { 32 .name = "EFI Memory Map", 33 .start = 0, 34 .end = 0, 35 .flags = IORESOURCE_BUSY | IORESOURCE_MEM 36 }; 37 38 struct resource boot_param_res = { 39 .name = "Boot parameter", 40 .start = 0, 41 .end = 0, 42 .flags = IORESOURCE_BUSY | IORESOURCE_MEM 43 }; 44 45 46 /* 47 * Do what every setup is needed on image and the 48 * reboot code buffer to allow us to avoid allocations 49 * later. 50 */ 51 int machine_kexec_prepare(struct kimage *image) 52 { 53 void *control_code_buffer; 54 const unsigned long *func; 55 56 func = (unsigned long *)&relocate_new_kernel; 57 /* Pre-load control code buffer to minimize work in kexec path */ 58 control_code_buffer = page_address(image->control_code_page); 59 memcpy((void *)control_code_buffer, (const void *)func[0], 60 relocate_new_kernel_size); 61 flush_icache_range((unsigned long)control_code_buffer, 62 (unsigned long)control_code_buffer + relocate_new_kernel_size); 63 ia64_kimage = image; 64 65 return 0; 66 } 67 68 void machine_kexec_cleanup(struct kimage *image) 69 { 70 } 71 72 /* 73 * Do not allocate memory (or fail in any way) in machine_kexec(). 74 * We are past the point of no return, committed to rebooting now. 75 */ 76 static void ia64_machine_kexec(struct unw_frame_info *info, void *arg) 77 { 78 struct kimage *image = arg; 79 relocate_new_kernel_t rnk; 80 void *pal_addr = efi_get_pal_addr(); 81 unsigned long code_addr = (unsigned long)page_address(image->control_code_page); 82 unsigned long vector; 83 int ii; 84 85 BUG_ON(!image); 86 if (image->type == KEXEC_TYPE_CRASH) { 87 crash_save_this_cpu(); 88 current->thread.ksp = (__u64)info->sw - 16; 89 } 90 91 /* Interrupts aren't acceptable while we reboot */ 92 local_irq_disable(); 93 94 /* Mask CMC and Performance Monitor interrupts */ 95 ia64_setreg(_IA64_REG_CR_PMV, 1 << 16); 96 ia64_setreg(_IA64_REG_CR_CMCV, 1 << 16); 97 98 /* Mask ITV and Local Redirect Registers */ 99 ia64_set_itv(1 << 16); 100 ia64_set_lrr0(1 << 16); 101 ia64_set_lrr1(1 << 16); 102 103 /* terminate possible nested in-service interrupts */ 104 for (ii = 0; ii < 16; ii++) 105 ia64_eoi(); 106 107 /* unmask TPR and clear any pending interrupts */ 108 ia64_setreg(_IA64_REG_CR_TPR, 0); 109 ia64_srlz_d(); 110 vector = ia64_get_ivr(); 111 while (vector != IA64_SPURIOUS_INT_VECTOR) { 112 ia64_eoi(); 113 vector = ia64_get_ivr(); 114 } 115 platform_kernel_launch_event(); 116 rnk = (relocate_new_kernel_t)&code_addr; 117 (*rnk)(image->head, image->start, ia64_boot_param, 118 GRANULEROUNDDOWN((unsigned long) pal_addr)); 119 BUG(); 120 } 121 122 void machine_kexec(struct kimage *image) 123 { 124 BUG_ON(!image); 125 unw_init_running(ia64_machine_kexec, image); 126 for(;;); 127 } 128