1457c8996SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 262a31a03SHiroshi Shimamoto /* 362a31a03SHiroshi Shimamoto * Architecture specific (i386/x86_64) functions for kexec based crash dumps. 462a31a03SHiroshi Shimamoto * 562a31a03SHiroshi Shimamoto * Created by: Hariprasad Nellitheertha (hari@in.ibm.com) 662a31a03SHiroshi Shimamoto * 762a31a03SHiroshi Shimamoto * Copyright (C) IBM Corporation, 2004. All rights reserved. 8dd5f7260SVivek Goyal * Copyright (C) Red Hat Inc., 2014. All rights reserved. 9dd5f7260SVivek Goyal * Authors: 10dd5f7260SVivek Goyal * Vivek Goyal <vgoyal@redhat.com> 1162a31a03SHiroshi Shimamoto * 1262a31a03SHiroshi Shimamoto */ 1362a31a03SHiroshi Shimamoto 14dd5f7260SVivek Goyal #define pr_fmt(fmt) "kexec: " fmt 15dd5f7260SVivek Goyal 1662a31a03SHiroshi Shimamoto #include <linux/types.h> 1762a31a03SHiroshi Shimamoto #include <linux/kernel.h> 1862a31a03SHiroshi Shimamoto #include <linux/smp.h> 1962a31a03SHiroshi Shimamoto #include <linux/reboot.h> 2062a31a03SHiroshi Shimamoto #include <linux/kexec.h> 2162a31a03SHiroshi Shimamoto #include <linux/delay.h> 2262a31a03SHiroshi Shimamoto #include <linux/elf.h> 2362a31a03SHiroshi Shimamoto #include <linux/elfcore.h> 24186f4360SPaul Gortmaker #include <linux/export.h> 25dd5f7260SVivek Goyal #include <linux/slab.h> 26d6472302SStephen Rothwell #include <linux/vmalloc.h> 276f599d84SLianbo Jiang #include <linux/memblock.h> 2862a31a03SHiroshi Shimamoto 2962a31a03SHiroshi Shimamoto #include <asm/processor.h> 3062a31a03SHiroshi Shimamoto #include <asm/hardirq.h> 3162a31a03SHiroshi Shimamoto #include <asm/nmi.h> 3262a31a03SHiroshi Shimamoto #include <asm/hw_irq.h> 3362a31a03SHiroshi Shimamoto #include <asm/apic.h> 345520b7e7SIngo Molnar #include <asm/e820/types.h> 358643e28dSJiang Liu #include <asm/io_apic.h> 360c1b2724SOGAWA Hirofumi #include <asm/hpet.h> 3762a31a03SHiroshi Shimamoto #include <linux/kdebug.h> 3896b89dc6SJaswinder Singh Rajput #include <asm/cpu.h> 39ed23dc6fSGlauber Costa #include <asm/reboot.h> 402340b62fSEduardo Habkost #include <asm/virtext.h> 41da06a43dSTakao Indoh #include <asm/intel_pt.h> 4289f579ceSYi Wang #include <asm/crash.h> 436f599d84SLianbo Jiang #include <asm/cmdline.h> 448e294786SEduardo Habkost 45dd5f7260SVivek Goyal /* Used while preparing memory map entries for second kernel */ 46dd5f7260SVivek Goyal struct crash_memmap_data { 47dd5f7260SVivek Goyal struct boot_params *params; 48dd5f7260SVivek Goyal /* Type of memory */ 49dd5f7260SVivek Goyal unsigned int type; 50dd5f7260SVivek Goyal }; 51dd5f7260SVivek Goyal 52f23d1f4aSZhang Yanfei /* 53f23d1f4aSZhang Yanfei * This is used to VMCLEAR all VMCSs loaded on the 54f23d1f4aSZhang Yanfei * processor. And when loading kvm_intel module, the 55f23d1f4aSZhang Yanfei * callback function pointer will be assigned. 56f23d1f4aSZhang Yanfei * 57f23d1f4aSZhang Yanfei * protected by rcu. 58f23d1f4aSZhang Yanfei */ 590ca0d818SZhang Yanfei crash_vmclear_fn __rcu *crash_vmclear_loaded_vmcss = NULL; 60f23d1f4aSZhang Yanfei EXPORT_SYMBOL_GPL(crash_vmclear_loaded_vmcss); 61f23d1f4aSZhang Yanfei 62f23d1f4aSZhang Yanfei static inline void cpu_crash_vmclear_loaded_vmcss(void) 63f23d1f4aSZhang Yanfei { 640ca0d818SZhang Yanfei crash_vmclear_fn *do_vmclear_operation = NULL; 65f23d1f4aSZhang Yanfei 66f23d1f4aSZhang Yanfei rcu_read_lock(); 67f23d1f4aSZhang Yanfei do_vmclear_operation = rcu_dereference(crash_vmclear_loaded_vmcss); 68f23d1f4aSZhang Yanfei if (do_vmclear_operation) 69f23d1f4aSZhang Yanfei do_vmclear_operation(); 70f23d1f4aSZhang Yanfei rcu_read_unlock(); 71f23d1f4aSZhang Yanfei } 72f23d1f4aSZhang Yanfei 73b2bbe71bSEduardo Habkost #if defined(CONFIG_SMP) && defined(CONFIG_X86_LOCAL_APIC) 74b2bbe71bSEduardo Habkost 759c48f1c6SDon Zickus static void kdump_nmi_callback(int cpu, struct pt_regs *regs) 7662a31a03SHiroshi Shimamoto { 77a7d41820SEduardo Habkost crash_save_cpu(regs, cpu); 78a7d41820SEduardo Habkost 79f23d1f4aSZhang Yanfei /* 80f23d1f4aSZhang Yanfei * VMCLEAR VMCSs loaded on all cpus if needed. 81f23d1f4aSZhang Yanfei */ 82f23d1f4aSZhang Yanfei cpu_crash_vmclear_loaded_vmcss(); 83f23d1f4aSZhang Yanfei 842340b62fSEduardo Habkost /* Disable VMX or SVM if needed. 852340b62fSEduardo Habkost * 862340b62fSEduardo Habkost * We need to disable virtualization on all CPUs. 872340b62fSEduardo Habkost * Having VMX or SVM enabled on any CPU may break rebooting 882340b62fSEduardo Habkost * after the kdump kernel has finished its task. 892340b62fSEduardo Habkost */ 902340b62fSEduardo Habkost cpu_emergency_vmxoff(); 912340b62fSEduardo Habkost cpu_emergency_svm_disable(); 922340b62fSEduardo Habkost 93da06a43dSTakao Indoh /* 94da06a43dSTakao Indoh * Disable Intel PT to stop its logging 95da06a43dSTakao Indoh */ 96da06a43dSTakao Indoh cpu_emergency_stop_pt(); 97da06a43dSTakao Indoh 98a7d41820SEduardo Habkost disable_local_APIC(); 99a7d41820SEduardo Habkost } 100a7d41820SEduardo Habkost 1010ee59413SHidehiro Kawai void kdump_nmi_shootdown_cpus(void) 102d1e7b91cSEduardo Habkost { 1038e294786SEduardo Habkost nmi_shootdown_cpus(kdump_nmi_callback); 104d1e7b91cSEduardo Habkost 10562a31a03SHiroshi Shimamoto disable_local_APIC(); 10662a31a03SHiroshi Shimamoto } 107d1e7b91cSEduardo Habkost 1080ee59413SHidehiro Kawai /* Override the weak function in kernel/panic.c */ 1090ee59413SHidehiro Kawai void crash_smp_send_stop(void) 1100ee59413SHidehiro Kawai { 1110ee59413SHidehiro Kawai static int cpus_stopped; 1120ee59413SHidehiro Kawai 1130ee59413SHidehiro Kawai if (cpus_stopped) 1140ee59413SHidehiro Kawai return; 1150ee59413SHidehiro Kawai 1160ee59413SHidehiro Kawai if (smp_ops.crash_stop_other_cpus) 1170ee59413SHidehiro Kawai smp_ops.crash_stop_other_cpus(); 1180ee59413SHidehiro Kawai else 1190ee59413SHidehiro Kawai smp_send_stop(); 1200ee59413SHidehiro Kawai 1210ee59413SHidehiro Kawai cpus_stopped = 1; 1220ee59413SHidehiro Kawai } 1230ee59413SHidehiro Kawai 12462a31a03SHiroshi Shimamoto #else 1250ee59413SHidehiro Kawai void crash_smp_send_stop(void) 12662a31a03SHiroshi Shimamoto { 12762a31a03SHiroshi Shimamoto /* There are no cpus to shootdown */ 12862a31a03SHiroshi Shimamoto } 12962a31a03SHiroshi Shimamoto #endif 13062a31a03SHiroshi Shimamoto 131ed23dc6fSGlauber Costa void native_machine_crash_shutdown(struct pt_regs *regs) 13262a31a03SHiroshi Shimamoto { 13362a31a03SHiroshi Shimamoto /* This function is only called after the system 13462a31a03SHiroshi Shimamoto * has panicked or is otherwise in a critical state. 13562a31a03SHiroshi Shimamoto * The minimum amount of code to allow a kexec'd kernel 13662a31a03SHiroshi Shimamoto * to run successfully needs to happen here. 13762a31a03SHiroshi Shimamoto * 13862a31a03SHiroshi Shimamoto * In practice this means shooting down the other cpus in 13962a31a03SHiroshi Shimamoto * an SMP system. 14062a31a03SHiroshi Shimamoto */ 14162a31a03SHiroshi Shimamoto /* The kernel is broken so disable interrupts */ 14262a31a03SHiroshi Shimamoto local_irq_disable(); 14362a31a03SHiroshi Shimamoto 1440ee59413SHidehiro Kawai crash_smp_send_stop(); 1452340b62fSEduardo Habkost 146f23d1f4aSZhang Yanfei /* 147f23d1f4aSZhang Yanfei * VMCLEAR VMCSs loaded on this cpu if needed. 148f23d1f4aSZhang Yanfei */ 149f23d1f4aSZhang Yanfei cpu_crash_vmclear_loaded_vmcss(); 150f23d1f4aSZhang Yanfei 1512340b62fSEduardo Habkost /* Booting kdump kernel with VMX or SVM enabled won't work, 1522340b62fSEduardo Habkost * because (among other limitations) we can't disable paging 1532340b62fSEduardo Habkost * with the virt flags. 1542340b62fSEduardo Habkost */ 1552340b62fSEduardo Habkost cpu_emergency_vmxoff(); 1562340b62fSEduardo Habkost cpu_emergency_svm_disable(); 1572340b62fSEduardo Habkost 158da06a43dSTakao Indoh /* 159da06a43dSTakao Indoh * Disable Intel PT to stop its logging 160da06a43dSTakao Indoh */ 161da06a43dSTakao Indoh cpu_emergency_stop_pt(); 162da06a43dSTakao Indoh 16317405453SYoshihiro YUNOMAE #ifdef CONFIG_X86_IO_APIC 16417405453SYoshihiro YUNOMAE /* Prevent crash_kexec() from deadlocking on ioapic_lock. */ 16517405453SYoshihiro YUNOMAE ioapic_zap_locks(); 166339b2ae0SBaoquan He clear_IO_APIC(); 16762a31a03SHiroshi Shimamoto #endif 168522e6646SFenghua Yu lapic_shutdown(); 169339b2ae0SBaoquan He restore_boot_irq_mode(); 1700c1b2724SOGAWA Hirofumi #ifdef CONFIG_HPET_TIMER 1710c1b2724SOGAWA Hirofumi hpet_disable(); 1720c1b2724SOGAWA Hirofumi #endif 17362a31a03SHiroshi Shimamoto crash_save_cpu(regs, safe_smp_processor_id()); 17462a31a03SHiroshi Shimamoto } 175dd5f7260SVivek Goyal 17674ca317cSVivek Goyal #ifdef CONFIG_KEXEC_FILE 17753b76073STiezhu Yang 1781d2e733bSTom Lendacky static int get_nr_ram_ranges_callback(struct resource *res, void *arg) 179dd5f7260SVivek Goyal { 180e3c41e37SLee, Chun-Yi unsigned int *nr_ranges = arg; 181dd5f7260SVivek Goyal 182dd5f7260SVivek Goyal (*nr_ranges)++; 183dd5f7260SVivek Goyal return 0; 184dd5f7260SVivek Goyal } 185dd5f7260SVivek Goyal 186dd5f7260SVivek Goyal /* Gather all the required information to prepare elf headers for ram regions */ 1878d5f894aSAKASHI Takahiro static struct crash_mem *fill_up_crash_elf_data(void) 188dd5f7260SVivek Goyal { 189dd5f7260SVivek Goyal unsigned int nr_ranges = 0; 1908d5f894aSAKASHI Takahiro struct crash_mem *cmem; 191dd5f7260SVivek Goyal 1929eff3037SBorislav Petkov walk_system_ram_res(0, -1, &nr_ranges, get_nr_ram_ranges_callback); 1938d5f894aSAKASHI Takahiro if (!nr_ranges) 1948d5f894aSAKASHI Takahiro return NULL; 195dd5f7260SVivek Goyal 1968d5f894aSAKASHI Takahiro /* 1978d5f894aSAKASHI Takahiro * Exclusion of crash region and/or crashk_low_res may cause 1988d5f894aSAKASHI Takahiro * another range split. So add extra two slots here. 1998d5f894aSAKASHI Takahiro */ 2008d5f894aSAKASHI Takahiro nr_ranges += 2; 2014df43095SGustavo A. R. Silva cmem = vzalloc(struct_size(cmem, ranges, nr_ranges)); 2028d5f894aSAKASHI Takahiro if (!cmem) 2038d5f894aSAKASHI Takahiro return NULL; 204dd5f7260SVivek Goyal 2058d5f894aSAKASHI Takahiro cmem->max_nr_ranges = nr_ranges; 2068d5f894aSAKASHI Takahiro cmem->nr_ranges = 0; 207dd5f7260SVivek Goyal 2088d5f894aSAKASHI Takahiro return cmem; 209dd5f7260SVivek Goyal } 210dd5f7260SVivek Goyal 211dd5f7260SVivek Goyal /* 212dd5f7260SVivek Goyal * Look for any unwanted ranges between mstart, mend and remove them. This 2138d5f894aSAKASHI Takahiro * might lead to split and split ranges are put in cmem->ranges[] array 214dd5f7260SVivek Goyal */ 2158d5f894aSAKASHI Takahiro static int elf_header_exclude_ranges(struct crash_mem *cmem) 216dd5f7260SVivek Goyal { 217dd5f7260SVivek Goyal int ret = 0; 218dd5f7260SVivek Goyal 2197c321eb2SLianbo Jiang /* Exclude the low 1M because it is always reserved */ 220a3e1c3bbSLianbo Jiang ret = crash_exclude_mem_range(cmem, 0, (1<<20)-1); 2217c321eb2SLianbo Jiang if (ret) 2227c321eb2SLianbo Jiang return ret; 2237c321eb2SLianbo Jiang 224dd5f7260SVivek Goyal /* Exclude crashkernel region */ 225babac4a8SAKASHI Takahiro ret = crash_exclude_mem_range(cmem, crashk_res.start, crashk_res.end); 226dd5f7260SVivek Goyal if (ret) 227dd5f7260SVivek Goyal return ret; 228dd5f7260SVivek Goyal 2299eff3037SBorislav Petkov if (crashk_low_res.end) 230babac4a8SAKASHI Takahiro ret = crash_exclude_mem_range(cmem, crashk_low_res.start, 231babac4a8SAKASHI Takahiro crashk_low_res.end); 232dd5f7260SVivek Goyal 233dd5f7260SVivek Goyal return ret; 234dd5f7260SVivek Goyal } 235dd5f7260SVivek Goyal 2361d2e733bSTom Lendacky static int prepare_elf64_ram_headers_callback(struct resource *res, void *arg) 237dd5f7260SVivek Goyal { 2388d5f894aSAKASHI Takahiro struct crash_mem *cmem = arg; 239dd5f7260SVivek Goyal 240cbe66016SAKASHI Takahiro cmem->ranges[cmem->nr_ranges].start = res->start; 241cbe66016SAKASHI Takahiro cmem->ranges[cmem->nr_ranges].end = res->end; 242cbe66016SAKASHI Takahiro cmem->nr_ranges++; 243dd5f7260SVivek Goyal 244cbe66016SAKASHI Takahiro return 0; 245dd5f7260SVivek Goyal } 246dd5f7260SVivek Goyal 247dd5f7260SVivek Goyal /* Prepare elf headers. Return addr and size */ 248dd5f7260SVivek Goyal static int prepare_elf_headers(struct kimage *image, void **addr, 249dd5f7260SVivek Goyal unsigned long *sz) 250dd5f7260SVivek Goyal { 2518d5f894aSAKASHI Takahiro struct crash_mem *cmem; 2527c321eb2SLianbo Jiang int ret; 253dd5f7260SVivek Goyal 2548d5f894aSAKASHI Takahiro cmem = fill_up_crash_elf_data(); 2558d5f894aSAKASHI Takahiro if (!cmem) 256dd5f7260SVivek Goyal return -ENOMEM; 257dd5f7260SVivek Goyal 2589eff3037SBorislav Petkov ret = walk_system_ram_res(0, -1, cmem, prepare_elf64_ram_headers_callback); 259cbe66016SAKASHI Takahiro if (ret) 260cbe66016SAKASHI Takahiro goto out; 261cbe66016SAKASHI Takahiro 262cbe66016SAKASHI Takahiro /* Exclude unwanted mem ranges */ 2638d5f894aSAKASHI Takahiro ret = elf_header_exclude_ranges(cmem); 264cbe66016SAKASHI Takahiro if (ret) 265cbe66016SAKASHI Takahiro goto out; 266cbe66016SAKASHI Takahiro 267dd5f7260SVivek Goyal /* By default prepare 64bit headers */ 2689eff3037SBorislav Petkov ret = crash_prepare_elf64_headers(cmem, IS_ENABLED(CONFIG_X86_64), addr, sz); 269cbe66016SAKASHI Takahiro 270cbe66016SAKASHI Takahiro out: 2718d5f894aSAKASHI Takahiro vfree(cmem); 272dd5f7260SVivek Goyal return ret; 273dd5f7260SVivek Goyal } 274dd5f7260SVivek Goyal 2758ec67d97SIngo Molnar static int add_e820_entry(struct boot_params *params, struct e820_entry *entry) 276dd5f7260SVivek Goyal { 277dd5f7260SVivek Goyal unsigned int nr_e820_entries; 278dd5f7260SVivek Goyal 279dd5f7260SVivek Goyal nr_e820_entries = params->e820_entries; 28008b46d5dSIngo Molnar if (nr_e820_entries >= E820_MAX_ENTRIES_ZEROPAGE) 281dd5f7260SVivek Goyal return 1; 282dd5f7260SVivek Goyal 2839eff3037SBorislav Petkov memcpy(¶ms->e820_table[nr_e820_entries], entry, sizeof(struct e820_entry)); 284dd5f7260SVivek Goyal params->e820_entries++; 285dd5f7260SVivek Goyal return 0; 286dd5f7260SVivek Goyal } 287dd5f7260SVivek Goyal 2881d2e733bSTom Lendacky static int memmap_entry_callback(struct resource *res, void *arg) 289dd5f7260SVivek Goyal { 290dd5f7260SVivek Goyal struct crash_memmap_data *cmd = arg; 291dd5f7260SVivek Goyal struct boot_params *params = cmd->params; 2928ec67d97SIngo Molnar struct e820_entry ei; 293dd5f7260SVivek Goyal 2941d2e733bSTom Lendacky ei.addr = res->start; 2959275b933Skbuild test robot ei.size = resource_size(res); 296dd5f7260SVivek Goyal ei.type = cmd->type; 297dd5f7260SVivek Goyal add_e820_entry(params, &ei); 298dd5f7260SVivek Goyal 299dd5f7260SVivek Goyal return 0; 300dd5f7260SVivek Goyal } 301dd5f7260SVivek Goyal 302dd5f7260SVivek Goyal static int memmap_exclude_ranges(struct kimage *image, struct crash_mem *cmem, 303dd5f7260SVivek Goyal unsigned long long mstart, 304dd5f7260SVivek Goyal unsigned long long mend) 305dd5f7260SVivek Goyal { 306dd5f7260SVivek Goyal unsigned long start, end; 307dd5f7260SVivek Goyal 308dd5f7260SVivek Goyal cmem->ranges[0].start = mstart; 309dd5f7260SVivek Goyal cmem->ranges[0].end = mend; 310dd5f7260SVivek Goyal cmem->nr_ranges = 1; 311dd5f7260SVivek Goyal 312dd5f7260SVivek Goyal /* Exclude elf header region */ 313179350f0SLakshmi Ramasubramanian start = image->elf_load_addr; 314179350f0SLakshmi Ramasubramanian end = start + image->elf_headers_sz - 1; 315babac4a8SAKASHI Takahiro return crash_exclude_mem_range(cmem, start, end); 316dd5f7260SVivek Goyal } 317dd5f7260SVivek Goyal 318dd5f7260SVivek Goyal /* Prepare memory map for crash dump kernel */ 319dd5f7260SVivek Goyal int crash_setup_memmap_entries(struct kimage *image, struct boot_params *params) 320dd5f7260SVivek Goyal { 321dd5f7260SVivek Goyal int i, ret = 0; 322dd5f7260SVivek Goyal unsigned long flags; 3238ec67d97SIngo Molnar struct e820_entry ei; 324dd5f7260SVivek Goyal struct crash_memmap_data cmd; 325dd5f7260SVivek Goyal struct crash_mem *cmem; 326dd5f7260SVivek Goyal 3275849cdf8SMike Galbraith cmem = vzalloc(struct_size(cmem, ranges, 1)); 328dd5f7260SVivek Goyal if (!cmem) 329dd5f7260SVivek Goyal return -ENOMEM; 330dd5f7260SVivek Goyal 331dd5f7260SVivek Goyal memset(&cmd, 0, sizeof(struct crash_memmap_data)); 332dd5f7260SVivek Goyal cmd.params = params; 333dd5f7260SVivek Goyal 3347c321eb2SLianbo Jiang /* Add the low 1M */ 3357c321eb2SLianbo Jiang cmd.type = E820_TYPE_RAM; 3367c321eb2SLianbo Jiang flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY; 3377c321eb2SLianbo Jiang walk_iomem_res_desc(IORES_DESC_NONE, flags, 0, (1<<20)-1, &cmd, 3387c321eb2SLianbo Jiang memmap_entry_callback); 339dd5f7260SVivek Goyal 340dd5f7260SVivek Goyal /* Add ACPI tables */ 34109821ff1SIngo Molnar cmd.type = E820_TYPE_ACPI; 342dd5f7260SVivek Goyal flags = IORESOURCE_MEM | IORESOURCE_BUSY; 343f0f4711aSToshi Kani walk_iomem_res_desc(IORES_DESC_ACPI_TABLES, flags, 0, -1, &cmd, 344dd5f7260SVivek Goyal memmap_entry_callback); 345dd5f7260SVivek Goyal 346dd5f7260SVivek Goyal /* Add ACPI Non-volatile Storage */ 34709821ff1SIngo Molnar cmd.type = E820_TYPE_NVS; 348f0f4711aSToshi Kani walk_iomem_res_desc(IORES_DESC_ACPI_NV_STORAGE, flags, 0, -1, &cmd, 349dd5f7260SVivek Goyal memmap_entry_callback); 350dd5f7260SVivek Goyal 351980621daSLianbo Jiang /* Add e820 reserved ranges */ 352980621daSLianbo Jiang cmd.type = E820_TYPE_RESERVED; 353980621daSLianbo Jiang flags = IORESOURCE_MEM; 354980621daSLianbo Jiang walk_iomem_res_desc(IORES_DESC_RESERVED, flags, 0, -1, &cmd, 355980621daSLianbo Jiang memmap_entry_callback); 356980621daSLianbo Jiang 357dd5f7260SVivek Goyal /* Add crashk_low_res region */ 358dd5f7260SVivek Goyal if (crashk_low_res.end) { 359dd5f7260SVivek Goyal ei.addr = crashk_low_res.start; 3601429b568SJulia Lawall ei.size = resource_size(&crashk_low_res); 36109821ff1SIngo Molnar ei.type = E820_TYPE_RAM; 362dd5f7260SVivek Goyal add_e820_entry(params, &ei); 363dd5f7260SVivek Goyal } 364dd5f7260SVivek Goyal 365dd5f7260SVivek Goyal /* Exclude some ranges from crashk_res and add rest to memmap */ 3669eff3037SBorislav Petkov ret = memmap_exclude_ranges(image, cmem, crashk_res.start, crashk_res.end); 367dd5f7260SVivek Goyal if (ret) 368dd5f7260SVivek Goyal goto out; 369dd5f7260SVivek Goyal 370dd5f7260SVivek Goyal for (i = 0; i < cmem->nr_ranges; i++) { 371dd5f7260SVivek Goyal ei.size = cmem->ranges[i].end - cmem->ranges[i].start + 1; 372dd5f7260SVivek Goyal 373dd5f7260SVivek Goyal /* If entry is less than a page, skip it */ 374dd5f7260SVivek Goyal if (ei.size < PAGE_SIZE) 375dd5f7260SVivek Goyal continue; 376dd5f7260SVivek Goyal ei.addr = cmem->ranges[i].start; 37709821ff1SIngo Molnar ei.type = E820_TYPE_RAM; 378dd5f7260SVivek Goyal add_e820_entry(params, &ei); 379dd5f7260SVivek Goyal } 380dd5f7260SVivek Goyal 381dd5f7260SVivek Goyal out: 382dd5f7260SVivek Goyal vfree(cmem); 383dd5f7260SVivek Goyal return ret; 384dd5f7260SVivek Goyal } 385dd5f7260SVivek Goyal 386dd5f7260SVivek Goyal int crash_load_segments(struct kimage *image) 387dd5f7260SVivek Goyal { 388dd5f7260SVivek Goyal int ret; 389ec2b9bfaSThiago Jung Bauermann struct kexec_buf kbuf = { .image = image, .buf_min = 0, 390ec2b9bfaSThiago Jung Bauermann .buf_max = ULONG_MAX, .top_down = false }; 391dd5f7260SVivek Goyal 392dd5f7260SVivek Goyal /* Prepare elf headers and add a segment */ 393ec2b9bfaSThiago Jung Bauermann ret = prepare_elf_headers(image, &kbuf.buffer, &kbuf.bufsz); 394dd5f7260SVivek Goyal if (ret) 395dd5f7260SVivek Goyal return ret; 396dd5f7260SVivek Goyal 397179350f0SLakshmi Ramasubramanian image->elf_headers = kbuf.buffer; 398179350f0SLakshmi Ramasubramanian image->elf_headers_sz = kbuf.bufsz; 399dd5f7260SVivek Goyal 400ec2b9bfaSThiago Jung Bauermann kbuf.memsz = kbuf.bufsz; 401ec2b9bfaSThiago Jung Bauermann kbuf.buf_align = ELF_CORE_HEADER_ALIGN; 402993a1103SDave Young kbuf.mem = KEXEC_BUF_MEM_UNKNOWN; 403ec2b9bfaSThiago Jung Bauermann ret = kexec_add_buffer(&kbuf); 404dd5f7260SVivek Goyal if (ret) { 405179350f0SLakshmi Ramasubramanian vfree((void *)image->elf_headers); 406dd5f7260SVivek Goyal return ret; 407dd5f7260SVivek Goyal } 408179350f0SLakshmi Ramasubramanian image->elf_load_addr = kbuf.mem; 409dd5f7260SVivek Goyal pr_debug("Loaded ELF headers at 0x%lx bufsz=0x%lx memsz=0x%lx\n", 410*b57a7c9dSEric DeVolder image->elf_load_addr, kbuf.bufsz, kbuf.memsz); 411dd5f7260SVivek Goyal 412dd5f7260SVivek Goyal return ret; 413dd5f7260SVivek Goyal } 41474ca317cSVivek Goyal #endif /* CONFIG_KEXEC_FILE */ 415