This changes the way memblocks are installed based on the contents of the UEFI memory map. Formerly, all regions would be memblock_add()'ed, after which unusable regions would be memblock_reserve()'d as well. To simplify things, but also to allow access to the unusable regions through mmap(/dev/mem), even with CONFIG_STRICT_DEVMEM set, change this so that only usable regions are memblock_add()'ed in the first place. Signed-off-by: Ard Biesheuvel <ard.biesheuvel@xxxxxxxxxx> --- arch/arm64/kernel/efi.c | 69 +++++++++++++++++++------------------------------ 1 file changed, 26 insertions(+), 43 deletions(-) diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c index 3009c22e2620..af2214c692d3 100644 --- a/arch/arm64/kernel/efi.c +++ b/arch/arm64/kernel/efi.c @@ -40,13 +40,6 @@ static int __init uefi_debug_setup(char *str) } early_param("uefi_debug", uefi_debug_setup); -static int __init is_normal_ram(efi_memory_desc_t *md) -{ - if (md->attribute & EFI_MEMORY_WB) - return 1; - return 0; -} - static int __init uefi_init(void) { efi_char16_t *c16; @@ -105,28 +98,11 @@ out: return retval; } -/* - * Return true for RAM regions we want to permanently reserve. - */ -static __init int is_reserve_region(efi_memory_desc_t *md) -{ - switch (md->type) { - case EFI_LOADER_CODE: - case EFI_LOADER_DATA: - case EFI_BOOT_SERVICES_CODE: - case EFI_BOOT_SERVICES_DATA: - case EFI_CONVENTIONAL_MEMORY: - return 0; - default: - break; - } - return is_normal_ram(md); -} - -static __init void reserve_regions(void) +static __init void process_memory_map(void) { efi_memory_desc_t *md; u64 paddr, npages, size; + u32 lost = 0; if (uefi_debug) pr_info("Processing EFI memory map:\n"); @@ -134,31 +110,38 @@ static __init void reserve_regions(void) for_each_efi_memory_desc(&memmap, md) { paddr = md->phys_addr; npages = md->num_pages; + size = npages << EFI_PAGE_SHIFT; if (uefi_debug) { char buf[64]; - pr_info(" 0x%012llx-0x%012llx %s", - paddr, paddr + (npages << EFI_PAGE_SHIFT) - 1, + pr_info(" 0x%012llx-0x%012llx %s\n", + paddr, paddr + size - 1, efi_md_typeattr_format(buf, sizeof(buf), md)); } - memrange_efi_to_native(&paddr, &npages); - size = npages << PAGE_SHIFT; - - if (is_normal_ram(md)) - early_init_dt_add_memory_arch(paddr, size); - - if (is_reserve_region(md)) { - memblock_reserve(paddr, size); - if (uefi_debug) - pr_cont("*"); - } - - if (uefi_debug) - pr_cont("\n"); + if (!efi_mem_is_usable_region(md)) + continue; + + early_init_dt_add_memory_arch(paddr, size); + + /* + * Keep a tally of how much memory we are losing due to + * rounding of regions that are not aligned to the page + * size. We cannot easily recover this memory without + * sorting the memory map and attempting to merge adjacent + * usable regions. + */ + if (PAGE_SHIFT != EFI_PAGE_SHIFT) + lost += (npages << EFI_PAGE_SHIFT) - + round_down(max_t(s64, size - PAGE_ALIGN(paddr) + + md->phys_addr, 0), + PAGE_SIZE); } + if (lost > SZ_1K) + pr_warn("efi: lost %u KB of RAM to rounding\n", lost / SZ_1K); + set_bit(EFI_MEMMAP, &efi.flags); } @@ -182,7 +165,7 @@ void __init efi_init(void) WARN_ON(uefi_init() < 0); - reserve_regions(); + process_memory_map(); } static int __init arm64_enter_virtual_mode(void) -- 1.8.3.2 -- To unsubscribe from this list: send the line "unsubscribe linux-efi" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html