^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * arch/ia64/kernel/machine_kexec.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Handle transition of Linux booting another kernel
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright (C) 2005 Hewlett-Packard Development Comapny, L.P.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Copyright (C) 2005 Khalid Aziz <khalid.aziz@hp.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Copyright (C) 2006 Intel Corp, Zou Nan hai <nanhai.zou@intel.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/mm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/kexec.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/cpu.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/efi.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/numa.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/mmzone.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <asm/numa.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <asm/mmu_context.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <asm/setup.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <asm/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <asm/meminit.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <asm/processor.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <asm/sal.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <asm/mca.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) typedef void (*relocate_new_kernel_t)(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) unsigned long indirection_page,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) unsigned long start_address,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) struct ia64_boot_param *boot_param,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) unsigned long pal_addr) __noreturn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) struct kimage *ia64_kimage;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) struct resource efi_memmap_res = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) .name = "EFI Memory Map",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) .start = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) .end = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) .flags = IORESOURCE_BUSY | IORESOURCE_MEM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) struct resource boot_param_res = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) .name = "Boot parameter",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) .start = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) .end = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) .flags = IORESOURCE_BUSY | IORESOURCE_MEM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) * Do what every setup is needed on image and the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) * reboot code buffer to allow us to avoid allocations
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) * later.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) int machine_kexec_prepare(struct kimage *image)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) void *control_code_buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) const unsigned long *func;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) func = (unsigned long *)&relocate_new_kernel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) /* Pre-load control code buffer to minimize work in kexec path */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) control_code_buffer = page_address(image->control_code_page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) memcpy((void *)control_code_buffer, (const void *)func[0],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) relocate_new_kernel_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) flush_icache_range((unsigned long)control_code_buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) (unsigned long)control_code_buffer + relocate_new_kernel_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) ia64_kimage = image;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) void machine_kexec_cleanup(struct kimage *image)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) * Do not allocate memory (or fail in any way) in machine_kexec().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) * We are past the point of no return, committed to rebooting now.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) static void ia64_machine_kexec(struct unw_frame_info *info, void *arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) struct kimage *image = arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) relocate_new_kernel_t rnk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) void *pal_addr = efi_get_pal_addr();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) unsigned long code_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) int ii;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) u64 fp, gp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) ia64_fptr_t *init_handler = (ia64_fptr_t *)ia64_os_init_on_kdump;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) BUG_ON(!image);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) code_addr = (unsigned long)page_address(image->control_code_page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) if (image->type == KEXEC_TYPE_CRASH) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) crash_save_this_cpu();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) current->thread.ksp = (__u64)info->sw - 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) /* Register noop init handler */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) fp = ia64_tpa(init_handler->fp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) gp = ia64_tpa(ia64_getreg(_IA64_REG_GP));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) ia64_sal_set_vectors(SAL_VECTOR_OS_INIT, fp, gp, 0, fp, gp, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) /* Unregister init handlers of current kernel */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) ia64_sal_set_vectors(SAL_VECTOR_OS_INIT, 0, 0, 0, 0, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) /* Unregister mca handler - No more recovery on current kernel */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) ia64_sal_set_vectors(SAL_VECTOR_OS_MCA, 0, 0, 0, 0, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) /* Interrupts aren't acceptable while we reboot */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) local_irq_disable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) /* Mask CMC and Performance Monitor interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) ia64_setreg(_IA64_REG_CR_PMV, 1 << 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) ia64_setreg(_IA64_REG_CR_CMCV, 1 << 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) /* Mask ITV and Local Redirect Registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) ia64_set_itv(1 << 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) ia64_set_lrr0(1 << 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) ia64_set_lrr1(1 << 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) /* terminate possible nested in-service interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) for (ii = 0; ii < 16; ii++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) ia64_eoi();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) /* unmask TPR and clear any pending interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) ia64_setreg(_IA64_REG_CR_TPR, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) ia64_srlz_d();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) while (ia64_get_ivr() != IA64_SPURIOUS_INT_VECTOR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) ia64_eoi();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) rnk = (relocate_new_kernel_t)&code_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) (*rnk)(image->head, image->start, ia64_boot_param,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) GRANULEROUNDDOWN((unsigned long) pal_addr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) BUG();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) void machine_kexec(struct kimage *image)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) BUG_ON(!image);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) unw_init_running(ia64_machine_kexec, image);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) for(;;);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) void arch_crash_save_vmcoreinfo(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) #if defined(CONFIG_DISCONTIGMEM) || defined(CONFIG_SPARSEMEM)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) VMCOREINFO_SYMBOL(pgdat_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) VMCOREINFO_LENGTH(pgdat_list, MAX_NUMNODES);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) #ifdef CONFIG_NUMA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) VMCOREINFO_SYMBOL(node_memblk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) VMCOREINFO_LENGTH(node_memblk, NR_NODE_MEMBLKS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) VMCOREINFO_STRUCT_SIZE(node_memblk_s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) VMCOREINFO_OFFSET(node_memblk_s, start_paddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) VMCOREINFO_OFFSET(node_memblk_s, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) #if CONFIG_PGTABLE_LEVELS == 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) VMCOREINFO_CONFIG(PGTABLE_3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) #elif CONFIG_PGTABLE_LEVELS == 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) VMCOREINFO_CONFIG(PGTABLE_4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)