Commit 8dbe3395 authored by Kirill A. Shutemov's avatar Kirill A. Shutemov Committed by Ard Biesheuvel
Browse files

efi/unaccepted: Make sure unaccepted table is mapped



Unaccepted table is now allocated from EFI_ACPI_RECLAIM_MEMORY. It
translates into E820_TYPE_ACPI, which is not added to memblock and
therefore not mapped in the direct mapping.

This causes a crash on the first touch of the table.

Use memblock_add() to make sure that the table is mapped in direct
mapping.

Align the range to the nearest page borders. Ranges smaller than page
size are not mapped.

Fixes: e7761d82 ("efi/unaccepted: Use ACPI reclaim memory for unaccepted memory table")
Reported-by: default avatarHongyu Ning <hongyu.ning@intel.com>
Signed-off-by: default avatarKirill A. Shutemov <kirill.shutemov@linux.intel.com>
Signed-off-by: default avatarArd Biesheuvel <ardb@kernel.org>
parent 79b83606
Loading
Loading
Loading
Loading
+29 −3
Original line number Diff line number Diff line
@@ -623,6 +623,34 @@ static __init int match_config_table(const efi_guid_t *guid,
	return 0;
}

/**
 * reserve_unaccepted - Map and reserve unaccepted configuration table
 * @unaccepted: Pointer to unaccepted memory table
 *
 * memblock_add() makes sure that the table is mapped in direct mapping. During
 * normal boot it happens automatically because the table is allocated from
 * usable memory. But during crashkernel boot only memory specifically reserved
 * for crash scenario is mapped. memblock_add() forces the table to be mapped
 * in crashkernel case.
 *
 * Align the range to the nearest page borders. Ranges smaller than page size
 * are not going to be mapped.
 *
 * memblock_reserve() makes sure that future allocations will not touch the
 * table.
 */

static __init void reserve_unaccepted(struct efi_unaccepted_memory *unaccepted)
{
	phys_addr_t start, size;

	start = PAGE_ALIGN_DOWN(efi.unaccepted);
	size = PAGE_ALIGN(sizeof(*unaccepted) + unaccepted->size);

	memblock_add(start, size);
	memblock_reserve(start, size);
}

int __init efi_config_parse_tables(const efi_config_table_t *config_tables,
				   int count,
				   const efi_config_table_type_t *arch_tables)
@@ -751,11 +779,9 @@ int __init efi_config_parse_tables(const efi_config_table_t *config_tables,

		unaccepted = early_memremap(efi.unaccepted, sizeof(*unaccepted));
		if (unaccepted) {
			unsigned long size;

			if (unaccepted->version == 1) {
				size = sizeof(*unaccepted) + unaccepted->size;
				memblock_reserve(efi.unaccepted, size);
				reserve_unaccepted(unaccepted);
			} else {
				efi.unaccepted = EFI_INVALID_TABLE_ADDR;
			}