Example #1
0
/* Loads additional segments in case of a panic kernel is being loaded.
 * One segment for backup region, another segment for storing elf headers
 * for crash memory image.
 */
int load_crashdump_segments(struct kexec_info *info, char* mod_cmdline,
				unsigned long UNUSED(max_addr),
				unsigned long UNUSED(min_base))
{
	void *tmp;
	unsigned long sz, elfcorehdr;
	int nr_ranges, align = 1024;
	struct memory_range *mem_range;
	crash_create_elf_headers_func crash_create = crash_create_elf32_headers;
	struct crash_elf_info *elf_info = &elf_info32;
	unsigned long start_offset = 0x80000000UL;

#ifdef __mips64
	if (arch_options.core_header_type == CORE_TYPE_ELF64) {
		elf_info = &elf_info64;
		crash_create = crash_create_elf64_headers;
		start_offset = 0xffffffff80000000UL;
	}
#endif

	if (get_kernel_paddr(elf_info))
		return -1;

	if (get_kernel_vaddr_and_size(elf_info, start_offset))
		return -1;

	if (get_crash_memory_ranges(&mem_range, &nr_ranges) < 0)
		return -1;

	info->backup_src_start = BACKUP_SRC_START;
	info->backup_src_size = BACKUP_SRC_SIZE;
	/* Create a backup region segment to store backup data*/
	sz = (BACKUP_SRC_SIZE + align - 1) & ~(align - 1);
	tmp = xmalloc(sz);
	memset(tmp, 0, sz);
	info->backup_start = add_buffer(info, tmp, sz, sz, align,
				crash_reserved_mem.start,
				crash_reserved_mem.end, -1);

	if (crash_create(info, elf_info, crash_memory_range, nr_ranges,
			 &tmp, &sz, ELF_CORE_HEADER_ALIGN) < 0)
		return -1;
	elfcorehdr = add_buffer(info, tmp, sz, sz, align,
		crash_reserved_mem.start,
		crash_reserved_mem.end, -1);

	/*
	 * backup segment is after elfcorehdr, so use elfcorehdr as top of
	 * kernel's available memory
	 */
	cmdline_add_mem(mod_cmdline, crash_reserved_mem.start,
		elfcorehdr - crash_reserved_mem.start);
	cmdline_add_elfcorehdr(mod_cmdline, elfcorehdr);
	cmdline_add_savemaxmem(mod_cmdline, saved_max_mem);

	dbgprintf("CRASH MEMORY RANGES:\n");
	dbgprintf("%016Lx-%016Lx\n", crash_reserved_mem.start,
			crash_reserved_mem.end);
	return 0;
}
/**
 * load_crashdump_segments() - loads additional segments needed for kdump
 * @info: kexec info structure
 * @mod_cmdline: kernel command line
 *
 * This function loads additional segments which are needed for the dump capture
 * kernel. It also updates kernel command line passed in @mod_cmdline to have
 * right parameters for the dump capture kernel.
 *
 * Return %0 in case of success and %-1 in case of error.
 */
int load_crashdump_segments(struct kexec_info *info, char *mod_cmdline)
{
	unsigned long elfcorehdr;
	unsigned long bufsz;
	void *buf;
	int err;

	/*
	 * First fetch all the memory (RAM) ranges that we are going to pass to
	 * the crashdump kernel during panic.
	 */
	err = crash_get_memory_ranges();
	if (err)
		return err;

	/*
	 * Now that we have memory regions sorted, we can use first memory
	 * region as PHYS_OFFSET.
	 */
	phys_offset = crash_memory_ranges[0].start;
	dbgprintf("phys_offset: %#lx\n", phys_offset);

	err = crash_create_elf32_headers(info, &elf_info, crash_memory_ranges,
					 crash_memory_nr_ranges, &buf, &bufsz,
					 ELF_CORE_HEADER_ALIGN);
	if (err)
		return err;

	/*
	 * We allocate ELF core header from the end of the memory area reserved
	 * for the crashkernel. We align the header to SECTION_SIZE (which is
	 * 1MB) so that available memory passed in kernel command line will be
	 * aligned to 1MB. This is because kernel create_mapping() wants memory
	 * regions to be aligned to SECTION_SIZE.
	 */
	elfcorehdr = add_buffer_phys_virt(info, buf, bufsz, bufsz, 1 << 20,
					  crash_reserved_mem.start,
					  crash_reserved_mem.end, -1, 0);

	dbgprintf("elfcorehdr: %#lx\n", elfcorehdr);
	cmdline_add_elfcorehdr(mod_cmdline, elfcorehdr);

	/*
	 * Add 'mem=size' parameter to dump capture kernel command line. This
	 * prevents the dump capture kernel from using any other memory regions
	 * which belong to the primary kernel.
	 */
	cmdline_add_mem(mod_cmdline, elfcorehdr - crash_reserved_mem.start);

	dump_memory_ranges();
	dbgprintf("kernel command line: \"%s\"\n", mod_cmdline);

	return 0;
}