Path: blob/master/arch/ia64/kernel/machine_kexec.c
10817 views
/*1* arch/ia64/kernel/machine_kexec.c2*3* Handle transition of Linux booting another kernel4* Copyright (C) 2005 Hewlett-Packard Development Comapny, L.P.5* Copyright (C) 2005 Khalid Aziz <[email protected]>6* Copyright (C) 2006 Intel Corp, Zou Nan hai <[email protected]>7*8* This source code is licensed under the GNU General Public License,9* Version 2. See the file COPYING for more details.10*/1112#include <linux/mm.h>13#include <linux/kexec.h>14#include <linux/cpu.h>15#include <linux/irq.h>16#include <linux/efi.h>17#include <linux/numa.h>18#include <linux/mmzone.h>1920#include <asm/numa.h>21#include <asm/mmu_context.h>22#include <asm/setup.h>23#include <asm/delay.h>24#include <asm/meminit.h>25#include <asm/processor.h>26#include <asm/sal.h>27#include <asm/mca.h>2829typedef NORET_TYPE void (*relocate_new_kernel_t)(30unsigned long indirection_page,31unsigned long start_address,32struct ia64_boot_param *boot_param,33unsigned long pal_addr) ATTRIB_NORET;3435struct kimage *ia64_kimage;3637struct resource efi_memmap_res = {38.name = "EFI Memory Map",39.start = 0,40.end = 0,41.flags = IORESOURCE_BUSY | IORESOURCE_MEM42};4344struct resource boot_param_res = {45.name = "Boot parameter",46.start = 0,47.end = 0,48.flags = IORESOURCE_BUSY | IORESOURCE_MEM49};505152/*53* Do what every setup is needed on image and the54* reboot code buffer to allow us to avoid allocations55* later.56*/57int machine_kexec_prepare(struct kimage *image)58{59void *control_code_buffer;60const unsigned long *func;6162func = (unsigned long *)&relocate_new_kernel;63/* Pre-load control code buffer to minimize work in kexec path */64control_code_buffer = page_address(image->control_code_page);65memcpy((void *)control_code_buffer, (const void *)func[0],66relocate_new_kernel_size);67flush_icache_range((unsigned long)control_code_buffer,68(unsigned long)control_code_buffer + relocate_new_kernel_size);69ia64_kimage = image;7071return 0;72}7374void machine_kexec_cleanup(struct kimage *image)75{76}7778/*79* Do not allocate memory (or fail in any way) in machine_kexec().80* We are past the point of no return, committed to rebooting now.81*/82static void ia64_machine_kexec(struct unw_frame_info *info, void *arg)83{84struct kimage *image = arg;85relocate_new_kernel_t rnk;86void *pal_addr = efi_get_pal_addr();87unsigned long code_addr = (unsigned long)page_address(image->control_code_page);88int ii;89u64 fp, gp;90ia64_fptr_t *init_handler = (ia64_fptr_t *)ia64_os_init_on_kdump;9192BUG_ON(!image);93if (image->type == KEXEC_TYPE_CRASH) {94crash_save_this_cpu();95current->thread.ksp = (__u64)info->sw - 16;9697/* Register noop init handler */98fp = ia64_tpa(init_handler->fp);99gp = ia64_tpa(ia64_getreg(_IA64_REG_GP));100ia64_sal_set_vectors(SAL_VECTOR_OS_INIT, fp, gp, 0, fp, gp, 0);101} else {102/* Unregister init handlers of current kernel */103ia64_sal_set_vectors(SAL_VECTOR_OS_INIT, 0, 0, 0, 0, 0, 0);104}105106/* Unregister mca handler - No more recovery on current kernel */107ia64_sal_set_vectors(SAL_VECTOR_OS_MCA, 0, 0, 0, 0, 0, 0);108109/* Interrupts aren't acceptable while we reboot */110local_irq_disable();111112/* Mask CMC and Performance Monitor interrupts */113ia64_setreg(_IA64_REG_CR_PMV, 1 << 16);114ia64_setreg(_IA64_REG_CR_CMCV, 1 << 16);115116/* Mask ITV and Local Redirect Registers */117ia64_set_itv(1 << 16);118ia64_set_lrr0(1 << 16);119ia64_set_lrr1(1 << 16);120121/* terminate possible nested in-service interrupts */122for (ii = 0; ii < 16; ii++)123ia64_eoi();124125/* unmask TPR and clear any pending interrupts */126ia64_setreg(_IA64_REG_CR_TPR, 0);127ia64_srlz_d();128while (ia64_get_ivr() != IA64_SPURIOUS_INT_VECTOR)129ia64_eoi();130platform_kernel_launch_event();131rnk = (relocate_new_kernel_t)&code_addr;132(*rnk)(image->head, image->start, ia64_boot_param,133GRANULEROUNDDOWN((unsigned long) pal_addr));134BUG();135}136137void machine_kexec(struct kimage *image)138{139BUG_ON(!image);140unw_init_running(ia64_machine_kexec, image);141for(;;);142}143144void arch_crash_save_vmcoreinfo(void)145{146#if defined(CONFIG_DISCONTIGMEM) || defined(CONFIG_SPARSEMEM)147VMCOREINFO_SYMBOL(pgdat_list);148VMCOREINFO_LENGTH(pgdat_list, MAX_NUMNODES);149#endif150#ifdef CONFIG_NUMA151VMCOREINFO_SYMBOL(node_memblk);152VMCOREINFO_LENGTH(node_memblk, NR_NODE_MEMBLKS);153VMCOREINFO_STRUCT_SIZE(node_memblk_s);154VMCOREINFO_OFFSET(node_memblk_s, start_paddr);155VMCOREINFO_OFFSET(node_memblk_s, size);156#endif157#ifdef CONFIG_PGTABLE_3158VMCOREINFO_CONFIG(PGTABLE_3);159#elif CONFIG_PGTABLE_4160VMCOREINFO_CONFIG(PGTABLE_4);161#endif162}163164unsigned long paddr_vmcoreinfo_note(void)165{166return ia64_tpa((unsigned long)(char *)&vmcoreinfo_note);167}168169170171