Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit dd39ecf5 authored by Huang Ying's avatar Huang Ying Committed by Ingo Molnar
Browse files

x86: EFI: Back efi_ioremap with init_memory_mapping instead of FIX_MAP



Impact: Fix boot failure on EFI system with large runtime memory range

Brian Maly reported that some EFI system with large runtime memory
range can not boot. Because the FIX_MAP used to map runtime memory
range is smaller than run time memory range.

This patch fixes this issue by re-implement efi_ioremap() with
init_memory_mapping().

Reported-and-tested-by: default avatarBrian Maly <bmaly@redhat.com>
Signed-off-by: default avatarHuang Ying <ying.huang@intel.com>
Cc: Brian Maly <bmaly@redhat.com>
Cc: Yinghai Lu <yinghai@kernel.org>
LKML-Reference: <1236135513.6204.306.camel@yhuang-dev.sh.intel.com>
Signed-off-by: default avatarIngo Molnar <mingo@elte.hu>
parent ff0c0874
Loading
Loading
Loading
Loading
+0 −2
Original line number Diff line number Diff line
@@ -37,8 +37,6 @@ extern unsigned long asmlinkage efi_call_phys(void *, ...);

#else /* !CONFIG_X86_32 */

#define MAX_EFI_IO_PAGES	100

extern u64 efi_call0(void *fp);
extern u64 efi_call1(void *fp, u64 arg1);
extern u64 efi_call2(void *fp, u64 arg1, u64 arg2);
+0 −4
Original line number Diff line number Diff line
@@ -16,7 +16,6 @@
#include <asm/apicdef.h>
#include <asm/page.h>
#include <asm/vsyscall.h>
#include <asm/efi.h>

/*
 * Here we define all the compile-time 'special' virtual
@@ -43,9 +42,6 @@ enum fixed_addresses {
	FIX_APIC_BASE,	/* local (CPU) APIC) -- required for SMP or not */
	FIX_IO_APIC_BASE_0,
	FIX_IO_APIC_BASE_END = FIX_IO_APIC_BASE_0 + MAX_IO_APICS - 1,
	FIX_EFI_IO_MAP_LAST_PAGE,
	FIX_EFI_IO_MAP_FIRST_PAGE = FIX_EFI_IO_MAP_LAST_PAGE
				  + MAX_EFI_IO_PAGES - 1,
#ifdef CONFIG_PARAVIRT
	FIX_PARAVIRT_BOOTMAP,
#endif
+5 −2
Original line number Diff line number Diff line
@@ -467,7 +467,7 @@ void __init efi_enter_virtual_mode(void)
	efi_memory_desc_t *md;
	efi_status_t status;
	unsigned long size;
	u64 end, systab, addr, npages;
	u64 end, systab, addr, npages, end_pfn;
	void *p, *va;

	efi.systab = NULL;
@@ -479,7 +479,10 @@ void __init efi_enter_virtual_mode(void)
		size = md->num_pages << EFI_PAGE_SHIFT;
		end = md->phys_addr + size;

		if (PFN_UP(end) <= max_low_pfn_mapped)
		end_pfn = PFN_UP(end);
		if (end_pfn <= max_low_pfn_mapped
		    || (end_pfn > (1UL << (32 - PAGE_SHIFT))
			&& end_pfn <= max_pfn_mapped))
			va = __va(md->phys_addr);
		else
			va = efi_ioremap(md->phys_addr, size);
+4 −17
Original line number Diff line number Diff line
@@ -99,24 +99,11 @@ void __init efi_call_phys_epilog(void)

void __iomem *__init efi_ioremap(unsigned long phys_addr, unsigned long size)
{
	static unsigned pages_mapped __initdata;
	unsigned i, pages;
	unsigned long offset;
	unsigned long last_map_pfn;

	pages = PFN_UP(phys_addr + size) - PFN_DOWN(phys_addr);
	offset = phys_addr & ~PAGE_MASK;
	phys_addr &= PAGE_MASK;

	if (pages_mapped + pages > MAX_EFI_IO_PAGES)
	last_map_pfn = init_memory_mapping(phys_addr, phys_addr + size);
	if ((last_map_pfn << PAGE_SHIFT) < phys_addr + size)
		return NULL;

	for (i = 0; i < pages; i++) {
		__set_fixmap(FIX_EFI_IO_MAP_FIRST_PAGE - pages_mapped,
			     phys_addr, PAGE_KERNEL);
		phys_addr += PAGE_SIZE;
		pages_mapped++;
	}

	return (void __iomem *)__fix_to_virt(FIX_EFI_IO_MAP_FIRST_PAGE - \
					     (pages_mapped - pages)) + offset;
	return (void __iomem *)__va(phys_addr);
}