Beispiel #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;
}
/* 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, i;
	struct memory_range *mem_range, *memmap_p;

	struct crash_elf_info elf_info =
	{
		class: ELFCLASS64,
		data: ELFDATA2LSB,
		machine: EM_X86_64,
		backup_src_start: BACKUP_SRC_START,
		backup_src_end: BACKUP_SRC_END,
		page_offset: page_offset,
	};

	if (get_kernel_paddr(info))
		return -1;

	if (get_kernel_vaddr_and_size(info))
		return -1;

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

	/* 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*/
	if (!(info->kexec_flags & KEXEC_PRESERVE_CONTEXT)) {
		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);
		if (delete_memmap(memmap_p, info->backup_start, sz) < 0)
			return -1;
	}

	/* Create elf header segment and store crash image data. */
	if (crash_create_elf64_headers(info, &elf_info,
				       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);
	if (delete_memmap(memmap_p, elfcorehdr, sz) < 0)
		return -1;
	cmdline_add_memmap(mod_cmdline, memmap_p);
	cmdline_add_elfcorehdr(mod_cmdline, elfcorehdr);

	/* Inform second kernel about the presence of ACPI tables. */
	for (i = 0; i < CRASH_MAX_MEMORY_RANGES; i++) {
		unsigned long start, end;
		if ( !( mem_range[i].type == RANGE_ACPI
			|| mem_range[i].type == RANGE_ACPI_NVS) )
			continue;
		start = mem_range[i].start;
		end = mem_range[i].end;
		cmdline_add_memmap_acpi(mod_cmdline, start, end);
	}
	return 0;
}