Ejemplo n.º 1
0
/* Loads additional segments in case of a panic kernel is being loaded.
 * One segment for storing elf headers for crash memory image.
 */
int load_crashdump_segments(struct kexec_info *info, char* mod_cmdline)
{
	void *tmp;
	unsigned long sz, elfcorehdr;
	int nr_ranges;
	struct memory_range *mem_range;

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

	if (crash_create_elf32_headers(info, &elf_info32,
				       mem_range, nr_ranges,
				       &tmp, &sz,
				       ELF_CORE_HEADER_ALIGN) < 0)
		return -1;

	elfcorehdr = add_buffer_phys_virt(info, tmp, sz, sz, 1024,
					  0, 0xffffffff, -1, 0);

	dbgprintf("Created elf header segment at 0x%lx\n", elfcorehdr);
	add_cmdline_param(mod_cmdline, elfcorehdr, " elfcorehdr=", "K");
	add_cmdline_param(mod_cmdline, elfcorehdr - mem_min, " mem=", "K");

	return 0;
}
Ejemplo n.º 2
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;
}
Ejemplo n.º 3
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,
				uint64_t max_addr, unsigned long min_base)
{
	void *tmp;
	unsigned long sz;
	uint64_t elfcorehdr;
	int nr_ranges, align = 1024, i;
	unsigned long long end;
	struct memory_range *mem_range;

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

	/* 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,
					0, max_addr, 1);
	reserve(info->backup_start, sz);

	/* On ppc64 memory ranges in device-tree is denoted as start
	 * and size rather than start and end, as is the case with
	 * other architectures like i386 . Because of this when loading
	 * the memory ranges in crashdump-elf.c the filesz calculation
	 * [ end - start + 1 ] goes for a toss.
	 *
	 * To be in sync with other archs adjust the end value for
	 * every crash memory range before calling the generic function
	 */

	for (i = 0; i < nr_ranges; i++) {
		end = crash_memory_range[i].end - 1;
		crash_memory_range[i].end = end;
	}


	/* Create elf header segment and store crash image data. */
	if (arch_options.core_header_type == CORE_TYPE_ELF64) {
		if (crash_create_elf64_headers(info, &elf_info64,
					       crash_memory_range, nr_ranges,
					       &tmp, &sz,
					       ELF_CORE_HEADER_ALIGN) < 0)
			return -1;
	}
	else {
		if (crash_create_elf32_headers(info, &elf_info32,
					       crash_memory_range, nr_ranges,
					       &tmp, &sz,
					       ELF_CORE_HEADER_ALIGN) < 0)
			return -1;
	}

	elfcorehdr = add_buffer(info, tmp, sz, sz, align, min_base,
				max_addr, 1);
	reserve(elfcorehdr, sz);
	/* modify and store the cmdline in a global array. This is later
	 * read by flatten_device_tree and modified if required
	 */
	add_cmdline_param(mod_cmdline, elfcorehdr, " elfcorehdr=", "K");
	add_cmdline_param(mod_cmdline, saved_max_mem, " savemaxmem=", "M");
	return 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 max_addr, unsigned long min_base)
{
    void *tmp;
    unsigned long sz, elfcorehdr;
    int nr_ranges, align = 1024;
    struct memory_range *mem_range, *memmap_p;

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

    /*
     * if the core type has not been set on command line, set it here
     * automatically
     */
    if (arch_options.core_header_type == CORE_TYPE_UNDEF) {
        arch_options.core_header_type =
            get_core_type(info, mem_range, nr_ranges);
    }

    /* Memory regions which panic kernel can safely use to boot into */
    sz = (sizeof(struct memory_range) * (KEXEC_MAX_SEGMENTS + 1));
    memmap_p = xmalloc(sz);
    memset(memmap_p, 0, sz);
    add_memmap(memmap_p, BACKUP_SRC_START, BACKUP_SRC_SIZE);
    sz = crash_reserved_mem.end - crash_reserved_mem.start +1;
    add_memmap(memmap_p, crash_reserved_mem.start, sz);

    /* 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,
                                    0, max_addr, -1);
    dbgprintf("Created backup segment at 0x%lx\n", info->backup_start);
    if (delete_memmap(memmap_p, info->backup_start, sz) < 0)
        return -1;

    /* Create elf header segment and store crash image data. */
    if (arch_options.core_header_type == CORE_TYPE_ELF64) {
        if (crash_create_elf64_headers(info, &elf_info64,
                                       crash_memory_range, nr_ranges,
                                       &tmp, &sz,
                                       ELF_CORE_HEADER_ALIGN) < 0)
            return -1;
    }
    else {
        if (crash_create_elf32_headers(info, &elf_info32,
                                       crash_memory_range, nr_ranges,
                                       &tmp, &sz,
                                       ELF_CORE_HEADER_ALIGN) < 0)
            return -1;
    }

    /* Hack: With some ld versions (GNU ld version 2.14.90.0.4 20030523),
     * vmlinux program headers show a gap of two pages between bss segment
     * and data segment but effectively kernel considers it as bss segment
     * and overwrites the any data placed there. Hence bloat the memsz of
     * elf core header segment to 16K to avoid being placed in such gaps.
     * This is a makeshift solution until it is fixed in kernel.
     */
    elfcorehdr = add_buffer(info, tmp, sz, 16*1024, align, min_base,
                            max_addr, -1);
    dbgprintf("Created elf header segment at 0x%lx\n", elfcorehdr);
    if (delete_memmap(memmap_p, elfcorehdr, sz) < 0)
        return -1;
    cmdline_add_memmap(mod_cmdline, memmap_p);
    cmdline_add_elfcorehdr(mod_cmdline, elfcorehdr);
    return 0;
}