Esempio n. 1
0
/* Gather all the required information to prepare elf headers for ram regions */
static void fill_up_crash_elf_data(struct crash_elf_data *ced,
				   struct kimage *image)
{
	unsigned int nr_ranges = 0;

	ced->image = image;

	walk_system_ram_res(0, -1, &nr_ranges,
				get_nr_ram_ranges_callback);

	ced->max_nr_ranges = nr_ranges;

	/*
	 * We don't create ELF headers for GART aperture as an attempt
	 * to dump this memory in second kernel leads to hang/crash.
	 * If gart aperture is present, one needs to exclude that region
	 * and that could lead to need of extra phdr.
	 */
	walk_iomem_res("GART", IORESOURCE_MEM, 0, -1,
				ced, get_gart_ranges_callback);

	/*
	 * If we have gart region, excluding that could potentially split
	 * a memory range, resulting in extra header. Account for  that.
	 */
	if (ced->gart_end)
		ced->max_nr_ranges++;

	/* Exclusion of crash region could split memory ranges */
	ced->max_nr_ranges++;

	/* If crashk_low_res is not 0, another range split possible */
	if (crashk_low_res.end != 0)
		ced->max_nr_ranges++;
}
Esempio n. 2
0
int crash_load_segments(struct kimage *image)
{
	unsigned long src_start, src_sz, elf_sz;
	void *elf_addr;
	int ret;

	/*
	 * Determine and load a segment for backup area. First 640K RAM
	 * region is backup source
	 */

	ret = walk_system_ram_res(KEXEC_BACKUP_SRC_START, KEXEC_BACKUP_SRC_END,
				image, determine_backup_region);

	/* Zero or postive return values are ok */
	if (ret < 0)
		return ret;

	src_start = image->arch.backup_src_start;
	src_sz = image->arch.backup_src_sz;

	/* Add backup segment. */
	if (src_sz) {
		/*
		 * Ideally there is no source for backup segment. This is
		 * copied in purgatory after crash. Just add a zero filled
		 * segment for now to make sure checksum logic works fine.
		 */
		ret = kexec_add_buffer(image, (char *)&crash_zero_bytes,
				       sizeof(crash_zero_bytes), src_sz,
				       PAGE_SIZE, 0, -1, 0,
				       &image->arch.backup_load_addr);
		if (ret)
			return ret;
		pr_debug("Loaded backup region at 0x%lx backup_start=0x%lx memsz=0x%lx\n",
			 image->arch.backup_load_addr, src_start, src_sz);
	}

	/* Prepare elf headers and add a segment */
	ret = prepare_elf_headers(image, &elf_addr, &elf_sz);
	if (ret)
		return ret;

	image->arch.elf_headers = elf_addr;
	image->arch.elf_headers_sz = elf_sz;

	ret = kexec_add_buffer(image, (char *)elf_addr, elf_sz, elf_sz,
			ELF_CORE_HEADER_ALIGN, 0, -1, 0,
			&image->arch.elf_load_addr);
	if (ret) {
		vfree((void *)image->arch.elf_headers);
		return ret;
	}
	pr_debug("Loaded ELF headers at 0x%lx bufsz=0x%lx memsz=0x%lx\n",
		 image->arch.elf_load_addr, elf_sz, elf_sz);

	return ret;
}
Esempio n. 3
0
static int prepare_elf64_headers(struct crash_elf_data *ced,
		void **addr, unsigned long *sz)
{
	Elf64_Ehdr *ehdr;
	Elf64_Phdr *phdr;
	unsigned long nr_cpus = num_possible_cpus(), nr_phdr, elf_sz;
	unsigned char *buf, *bufp;
	unsigned int cpu;
	unsigned long long notes_addr;
	int ret;

	/* extra phdr for vmcoreinfo elf note */
	nr_phdr = nr_cpus + 1;
	nr_phdr += ced->max_nr_ranges;

	/*
	 * kexec-tools creates an extra PT_LOAD phdr for kernel text mapping
	 * area on x86_64 (ffffffff80000000 - ffffffffa0000000).
	 * I think this is required by tools like gdb. So same physical
	 * memory will be mapped in two elf headers. One will contain kernel
	 * text virtual addresses and other will have __va(physical) addresses.
	 */

	nr_phdr++;
	elf_sz = sizeof(Elf64_Ehdr) + nr_phdr * sizeof(Elf64_Phdr);
	elf_sz = ALIGN(elf_sz, ELF_CORE_HEADER_ALIGN);

	buf = vzalloc(elf_sz);
	if (!buf)
		return -ENOMEM;

	bufp = buf;
	ehdr = (Elf64_Ehdr *)bufp;
	bufp += sizeof(Elf64_Ehdr);
	memcpy(ehdr->e_ident, ELFMAG, SELFMAG);
	ehdr->e_ident[EI_CLASS] = ELFCLASS64;
	ehdr->e_ident[EI_DATA] = ELFDATA2LSB;
	ehdr->e_ident[EI_VERSION] = EV_CURRENT;
	ehdr->e_ident[EI_OSABI] = ELF_OSABI;
	memset(ehdr->e_ident + EI_PAD, 0, EI_NIDENT - EI_PAD);
	ehdr->e_type = ET_CORE;
	ehdr->e_machine = ELF_ARCH;
	ehdr->e_version = EV_CURRENT;
	ehdr->e_phoff = sizeof(Elf64_Ehdr);
	ehdr->e_ehsize = sizeof(Elf64_Ehdr);
	ehdr->e_phentsize = sizeof(Elf64_Phdr);

	/* Prepare one phdr of type PT_NOTE for each present cpu */
	for_each_present_cpu(cpu) {
		phdr = (Elf64_Phdr *)bufp;
		bufp += sizeof(Elf64_Phdr);
		phdr->p_type = PT_NOTE;
		notes_addr = per_cpu_ptr_to_phys(per_cpu_ptr(crash_notes, cpu));
		phdr->p_offset = phdr->p_paddr = notes_addr;
		phdr->p_filesz = phdr->p_memsz = sizeof(note_buf_t);
		(ehdr->e_phnum)++;
	}

	/* Prepare one PT_NOTE header for vmcoreinfo */
	phdr = (Elf64_Phdr *)bufp;
	bufp += sizeof(Elf64_Phdr);
	phdr->p_type = PT_NOTE;
	phdr->p_offset = phdr->p_paddr = paddr_vmcoreinfo_note();
	phdr->p_filesz = phdr->p_memsz = sizeof(vmcoreinfo_note);
	(ehdr->e_phnum)++;

#ifdef CONFIG_X86_64
	/* Prepare PT_LOAD type program header for kernel text region */
	phdr = (Elf64_Phdr *)bufp;
	bufp += sizeof(Elf64_Phdr);
	phdr->p_type = PT_LOAD;
	phdr->p_flags = PF_R|PF_W|PF_X;
	phdr->p_vaddr = (Elf64_Addr)_text;
	phdr->p_filesz = phdr->p_memsz = _end - _text;
	phdr->p_offset = phdr->p_paddr = __pa_symbol(_text);
	(ehdr->e_phnum)++;
#endif

	/* Prepare PT_LOAD headers for system ram chunks. */
	ced->ehdr = ehdr;
	ced->bufp = bufp;
	ret = walk_system_ram_res(0, -1, ced,
			prepare_elf64_ram_headers_callback);
	if (ret < 0)
		return ret;

	*addr = buf;
	*sz = elf_sz;
	return 0;
}
Esempio n. 4
0
/*
 * Helper function for placing a buffer in a kexec segment. This assumes
 * that kexec_mutex is held.
 */
int kexec_add_buffer(struct kimage *image, char *buffer, unsigned long bufsz,
		     unsigned long memsz, unsigned long buf_align,
		     unsigned long buf_min, unsigned long buf_max,
		     bool top_down, unsigned long *load_addr)
{

	struct kexec_segment *ksegment;
	struct kexec_buf buf, *kbuf;
	int ret;

	/* Currently adding segment this way is allowed only in file mode */
	if (!image->file_mode)
		return -EINVAL;

	if (image->nr_segments >= KEXEC_SEGMENT_MAX)
		return -EINVAL;

	/*
	 * Make sure we are not trying to add buffer after allocating
	 * control pages. All segments need to be placed first before
	 * any control pages are allocated. As control page allocation
	 * logic goes through list of segments to make sure there are
	 * no destination overlaps.
	 */
	if (!list_empty(&image->control_pages)) {
		WARN_ON(1);
		return -EINVAL;
	}

	memset(&buf, 0, sizeof(struct kexec_buf));
	kbuf = &buf;
	kbuf->image = image;
	kbuf->buffer = buffer;
	kbuf->bufsz = bufsz;

	kbuf->memsz = ALIGN(memsz, PAGE_SIZE);
	kbuf->buf_align = max(buf_align, PAGE_SIZE);
	kbuf->buf_min = buf_min;
	kbuf->buf_max = buf_max;
	kbuf->top_down = top_down;

	/* Walk the RAM ranges and allocate a suitable range for the buffer */
	if (image->type == KEXEC_TYPE_CRASH)
		ret = walk_iomem_res_desc(crashk_res.desc,
				IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY,
				crashk_res.start, crashk_res.end, kbuf,
				locate_mem_hole_callback);
	else
		ret = walk_system_ram_res(0, -1, kbuf,
					  locate_mem_hole_callback);
	if (ret != 1) {
		/* A suitable memory range could not be found for buffer */
		return -EADDRNOTAVAIL;
	}

	/* Found a suitable memory range */
	ksegment = &image->segment[image->nr_segments];
	ksegment->kbuf = kbuf->buffer;
	ksegment->bufsz = kbuf->bufsz;
	ksegment->mem = kbuf->mem;
	ksegment->memsz = kbuf->memsz;
	image->nr_segments++;
	*load_addr = ksegment->mem;
	return 0;
}