Commit 236d70f8 authored by Alexander Gordeev's avatar Alexander Gordeev
Browse files

s390/boot: Do not rescue .vmlinux.relocs section



The .vmlinux.relocs section is moved in front of the compressed
kernel. The interim section rescue step is avoided as result.

Suggested-by: default avatarSumanth Korikkar <sumanthk@linux.ibm.com>
Signed-off-by: default avatarAlexander Gordeev <agordeev@linux.ibm.com>
parent 56b1069c
Loading
Loading
Loading
Loading
+13 −22
Original line number Diff line number Diff line
@@ -185,26 +185,7 @@ static void kaslr_adjust_relocs(unsigned long min_addr, unsigned long max_addr,
}

static void kaslr_adjust_got(unsigned long offset) {}
static void rescue_relocs(void) {}
static void free_relocs(void) {}
#else
static int *vmlinux_relocs_64_start;
static int *vmlinux_relocs_64_end;

static void rescue_relocs(void)
{
	unsigned long size = __vmlinux_relocs_64_end - __vmlinux_relocs_64_start;

	vmlinux_relocs_64_start = (void *)physmem_alloc_top_down(RR_RELOC, size, 0);
	vmlinux_relocs_64_end = (void *)vmlinux_relocs_64_start + size;
	memmove(vmlinux_relocs_64_start, __vmlinux_relocs_64_start, size);
}

static void free_relocs(void)
{
	physmem_free(RR_RELOC);
}

static void kaslr_adjust_relocs(unsigned long min_addr, unsigned long max_addr,
				unsigned long offset, unsigned long phys_offset)
{
@@ -212,7 +193,7 @@ static void kaslr_adjust_relocs(unsigned long min_addr, unsigned long max_addr,
	long loc;

	/* Adjust R_390_64 relocations */
	for (reloc = vmlinux_relocs_64_start; reloc < vmlinux_relocs_64_end; reloc++) {
	for (reloc = (int *)__vmlinux_relocs_64_start; reloc < (int *)__vmlinux_relocs_64_end; reloc++) {
		loc = (long)*reloc + phys_offset;
		if (loc < min_addr || loc > max_addr)
			error("64-bit relocation outside of kernel!\n");
@@ -486,7 +467,6 @@ void startup_kernel(void)
	detect_physmem_online_ranges(max_physmem_end);
	save_ipl_cert_comp_list();
	rescue_initrd(safe_addr, ident_map_size);
	rescue_relocs();

	if (kaslr_enabled())
		__kaslr_offset_phys = randomize_within_range(kernel_size, THREAD_SIZE, 0, ident_map_size);
@@ -498,6 +478,18 @@ void startup_kernel(void)

	/* vmlinux decompression is done, shrink reserved low memory */
	physmem_reserve(RR_DECOMPRESSOR, 0, (unsigned long)_decompressor_end);

	/*
	 * In case KASLR is enabled the randomized location of .amode31
	 * section might overlap with .vmlinux.relocs section. To avoid that
	 * the below randomize_within_range() could have been called with
	 * __vmlinux_relocs_64_end as the lower range address. However,
	 * .amode31 section is written to by the decompressed kernel - at
	 * that time the contents of .vmlinux.relocs is not needed anymore.
	 * Conversly, .vmlinux.relocs is read only by the decompressor, even
	 * before the kernel started. Therefore, in case the two sections
	 * overlap there is no risk of corrupting any data.
	 */
	if (kaslr_enabled())
		amode31_lma = randomize_within_range(vmlinux.amode31_size, PAGE_SIZE, 0, SZ_2G);
	if (!amode31_lma)
@@ -521,7 +513,6 @@ void startup_kernel(void)
	kaslr_adjust_relocs(__kaslr_offset_phys, __kaslr_offset_phys + vmlinux.image_size,
			    __kaslr_offset, __kaslr_offset_phys);
	kaslr_adjust_got(__kaslr_offset);
	free_relocs();
	setup_vmem(__kaslr_offset, __kaslr_offset + kernel_size, asce_limit);
	copy_bootdata();

+9 −18
Original line number Diff line number Diff line
@@ -99,6 +99,15 @@ SECTIONS

	_decompressor_end = .;

#ifndef CONFIG_PIE_BUILD
	. = ALIGN(4);
	.vmlinux.relocs : {
		__vmlinux_relocs_64_start = .;
		*(.vmlinux.relocs_64)
		__vmlinux_relocs_64_end = .;
	}
#endif

#ifdef CONFIG_KERNEL_UNCOMPRESSED
	. = ALIGN(PAGE_SIZE);
	. += AMODE31_SIZE;		/* .amode31 section */
@@ -111,24 +120,6 @@ SECTIONS
		_compressed_end = .;
	}

#ifndef CONFIG_PIE_BUILD
	/*
	 * When the kernel is built with CONFIG_KERNEL_UNCOMPRESSED, the entire
	 * uncompressed vmlinux.bin is positioned in the bzImage decompressor
	 * image at the default kernel LMA of 0x100000, enabling it to be
	 * executed in-place. However, the size of .vmlinux.relocs could be
	 * large enough to cause an overlap with the uncompressed kernel at the
	 * address 0x100000. To address this issue, .vmlinux.relocs is
	 * positioned after the .rodata.compressed.
	 */
	. = ALIGN(4);
	.vmlinux.relocs : {
		__vmlinux_relocs_64_start = .;
		*(.vmlinux.relocs_64)
		__vmlinux_relocs_64_end = .;
	}
#endif

#define SB_TRAILER_SIZE 32
	/* Trailer needed for Secure Boot */
	. += SB_TRAILER_SIZE; /* make sure .sb.trailer does not overwrite the previous section */
+0 −1
Original line number Diff line number Diff line
@@ -22,7 +22,6 @@ enum reserved_range_type {
	RR_DECOMPRESSOR,
	RR_INITRD,
	RR_VMLINUX,
	RR_RELOC,
	RR_AMODE31,
	RR_IPLREPORT,
	RR_CERT_COMP_LIST,