Commit 90e66ce9 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'x86_boot_for_v5.13' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull x86 boot updates from Borislav Petkov:
 "Consolidation and cleanup of the early memory reservations, along with
  a couple of gcc11 warning fixes"

* tag 'x86_boot_for_v5.13' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  x86/setup: Move trim_snb_memory() later in setup_arch() to fix boot hangs
  x86/setup: Merge several reservations of start of memory
  x86/setup: Consolidate early memory reservations
  x86/boot/compressed: Avoid gcc-11 -Wstringop-overread warning
  x86/boot/tboot: Avoid Wstringop-overread-warning
parents 81a48979 c361e5d4
Loading
Loading
Loading
Loading
+0 −2
Original line number Diff line number Diff line
@@ -430,8 +430,6 @@ asmlinkage __visible void *extract_kernel(void *rmode, memptr heap,
		error("Destination address too large");
#endif
#ifndef CONFIG_RELOCATABLE
	if ((unsigned long)output != LOAD_PHYSICAL_ADDR)
		error("Destination address does not match LOAD_PHYSICAL_ADDR");
	if (virt_addr != LOAD_PHYSICAL_ADDR)
		error("Destination virtual address changed when not relocatable");
#endif
+58 −51
Original line number Diff line number Diff line
@@ -633,8 +633,13 @@ static void __init trim_snb_memory(void)
	printk(KERN_DEBUG "reserving inaccessible SNB gfx pages\n");

	/*
	 * Reserve all memory below the 1 MB mark that has not
	 * already been reserved.
	 * SandyBridge integrated graphics devices have a bug that prevents
	 * them from accessing certain memory ranges, namely anything below
	 * 1M and in the pages listed in bad_pages[] above.
	 *
	 * To avoid these pages being ever accessed by SNB gfx devices
	 * reserve all memory below the 1 MB mark and bad_pages that have
	 * not already been reserved at boot time.
	 */
	memblock_reserve(0, 1<<20);

@@ -645,18 +650,6 @@ static void __init trim_snb_memory(void)
	}
}

/*
 * Here we put platform-specific memory range workarounds, i.e.
 * memory known to be corrupt or otherwise in need to be reserved on
 * specific platforms.
 *
 * If this gets used more widely it could use a real dispatch mechanism.
 */
static void __init trim_platform_memory_ranges(void)
{
	trim_snb_memory();
}

static void __init trim_bios_range(void)
{
	/*
@@ -725,9 +718,39 @@ static int __init parse_reservelow(char *p)

early_param("reservelow", parse_reservelow);

static void __init trim_low_memory_range(void)
static void __init early_reserve_memory(void)
{
	/*
	 * Reserve the memory occupied by the kernel between _text and
	 * __end_of_kernel_reserve symbols. Any kernel sections after the
	 * __end_of_kernel_reserve symbol must be explicitly reserved with a
	 * separate memblock_reserve() or they will be discarded.
	 */
	memblock_reserve(__pa_symbol(_text),
			 (unsigned long)__end_of_kernel_reserve - (unsigned long)_text);

	/*
	 * The first 4Kb of memory is a BIOS owned area, but generally it is
	 * not listed as such in the E820 table.
	 *
	 * Reserve the first memory page and typically some additional
	 * memory (64KiB by default) since some BIOSes are known to corrupt
	 * low memory. See the Kconfig help text for X86_RESERVE_LOW.
	 *
	 * In addition, make sure page 0 is always reserved because on
	 * systems with L1TF its contents can be leaked to user processes.
	 */
	memblock_reserve(0, ALIGN(reserve_low, PAGE_SIZE));

	early_reserve_initrd();

	if (efi_enabled(EFI_BOOT))
		efi_memblock_x86_reserve_range();

	memblock_x86_reserve_range_setup_data();

	reserve_ibft_region();
	reserve_bios_regions();
}

/*
@@ -764,29 +787,6 @@ dump_kernel_offset(struct notifier_block *self, unsigned long v, void *p)

void __init setup_arch(char **cmdline_p)
{
	/*
	 * Reserve the memory occupied by the kernel between _text and
	 * __end_of_kernel_reserve symbols. Any kernel sections after the
	 * __end_of_kernel_reserve symbol must be explicitly reserved with a
	 * separate memblock_reserve() or they will be discarded.
	 */
	memblock_reserve(__pa_symbol(_text),
			 (unsigned long)__end_of_kernel_reserve - (unsigned long)_text);

	/*
	 * Make sure page 0 is always reserved because on systems with
	 * L1TF its contents can be leaked to user processes.
	 */
	memblock_reserve(0, PAGE_SIZE);

	early_reserve_initrd();

	/*
	 * At this point everything still needed from the boot loader
	 * or BIOS or kernel text should be early reserved or marked not
	 * RAM in e820. All other memory is free game.
	 */

#ifdef CONFIG_X86_32
	memcpy(&boot_cpu_data, &new_cpu_data, sizeof(new_cpu_data));

@@ -910,8 +910,18 @@ void __init setup_arch(char **cmdline_p)

	parse_early_param();

	if (efi_enabled(EFI_BOOT))
		efi_memblock_x86_reserve_range();
	/*
	 * Do some memory reservations *before* memory is added to
	 * memblock, so memblock allocations won't overwrite it.
	 * Do it after early param, so we could get (unlikely) panic from
	 * serial.
	 *
	 * After this point everything still needed from the boot loader or
	 * firmware or kernel text should be early reserved or marked not
	 * RAM in e820. All other memory is free game.
	 */
	early_reserve_memory();

#ifdef CONFIG_MEMORY_HOTPLUG
	/*
	 * Memory used by the kernel cannot be hot-removed because Linux
@@ -938,9 +948,6 @@ void __init setup_arch(char **cmdline_p)

	x86_report_nx();

	/* after early param, so could get panic from serial */
	memblock_x86_reserve_range_setup_data();

	if (acpi_mps_check()) {
#ifdef CONFIG_X86_LOCAL_APIC
		disable_apic = 1;
@@ -1032,8 +1039,6 @@ void __init setup_arch(char **cmdline_p)
	 */
	find_smp_config();

	reserve_ibft_region();

	early_alloc_pgt_buf();

	/*
@@ -1054,8 +1059,6 @@ void __init setup_arch(char **cmdline_p)
	 */
	sev_setup_arch();

	reserve_bios_regions();

	efi_fake_memmap();
	efi_find_mirror();
	efi_esrt_init();
@@ -1081,8 +1084,12 @@ void __init setup_arch(char **cmdline_p)

	reserve_real_mode();

	trim_platform_memory_ranges();
	trim_low_memory_range();
	/*
	 * Reserving memory causing GPU hangs on Sandy Bridge integrated
	 * graphics devices should be done after we allocated memory under
	 * 1M for the real mode trampoline.
	 */
	trim_snb_memory();

	init_mem_mapping();

+26 −18
Original line number Diff line number Diff line
@@ -49,6 +49,30 @@ bool tboot_enabled(void)
	return tboot != NULL;
}

/* noinline to prevent gcc from warning about dereferencing constant fixaddr */
static noinline __init bool check_tboot_version(void)
{
	if (memcmp(&tboot_uuid, &tboot->uuid, sizeof(tboot->uuid))) {
		pr_warn("tboot at 0x%llx is invalid\n", boot_params.tboot_addr);
		return false;
	}

	if (tboot->version < 5) {
		pr_warn("tboot version is invalid: %u\n", tboot->version);
		return false;
	}

	pr_info("found shared page at phys addr 0x%llx:\n",
		boot_params.tboot_addr);
	pr_debug("version: %d\n", tboot->version);
	pr_debug("log_addr: 0x%08x\n", tboot->log_addr);
	pr_debug("shutdown_entry: 0x%x\n", tboot->shutdown_entry);
	pr_debug("tboot_base: 0x%08x\n", tboot->tboot_base);
	pr_debug("tboot_size: 0x%x\n", tboot->tboot_size);

	return true;
}

void __init tboot_probe(void)
{
	/* Look for valid page-aligned address for shared page. */
@@ -66,25 +90,9 @@ void __init tboot_probe(void)

	/* Map and check for tboot UUID. */
	set_fixmap(FIX_TBOOT_BASE, boot_params.tboot_addr);
	tboot = (struct tboot *)fix_to_virt(FIX_TBOOT_BASE);
	if (memcmp(&tboot_uuid, &tboot->uuid, sizeof(tboot->uuid))) {
		pr_warn("tboot at 0x%llx is invalid\n", boot_params.tboot_addr);
	tboot = (void *)fix_to_virt(FIX_TBOOT_BASE);
	if (!check_tboot_version())
		tboot = NULL;
		return;
	}
	if (tboot->version < 5) {
		pr_warn("tboot version is invalid: %u\n", tboot->version);
		tboot = NULL;
		return;
	}

	pr_info("found shared page at phys addr 0x%llx:\n",
		boot_params.tboot_addr);
	pr_debug("version: %d\n", tboot->version);
	pr_debug("log_addr: 0x%08x\n", tboot->log_addr);
	pr_debug("shutdown_entry: 0x%x\n", tboot->shutdown_entry);
	pr_debug("tboot_base: 0x%08x\n", tboot->tboot_base);
	pr_debug("tboot_size: 0x%x\n", tboot->tboot_size);
}

static pgd_t *tboot_pg_dir;