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

Commit 84a87c62 authored by Ingo Molnar's avatar Ingo Molnar
Browse files

Merge tag 'efi-next' of git://git.kernel.org/pub/scm/linux/kernel/git/mfleming/efi into core/efi



Pull EFI updates from Matt Fleming:

 - Fixes and cleanups for SMBIOS 3.0 DMI code. (Ivan Khoronzhuk)

 - A new efi=debug command line option that enables debug output in the
   EFI boot stub and results in less verbose EFI memory map output by
   default. (Borislav Petkov)

 - Disable interrupts around EFI calls and use a more standard page
   table saving and restoring idiom when making EFI calls. (Ingo Molnar)

 - Reduce the number of memory allocations performed when allocating the
   FDT in EFI boot stub by retrieving size from the FDT header in the
   EFI config table. (Ard Biesheuvel)

Signed-off-by: default avatarIngo Molnar <mingo@kernel.org>
parents e42391cd a643375f
Loading
Loading
Loading
Loading
+2 −1
Original line number Original line Diff line number Diff line
@@ -1036,7 +1036,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
			Format: {"off" | "on" | "skip[mbr]"}
			Format: {"off" | "on" | "skip[mbr]"}


	efi=		[EFI]
	efi=		[EFI]
			Format: { "old_map", "nochunk", "noruntime" }
			Format: { "old_map", "nochunk", "noruntime", "debug" }
			old_map [X86-64]: switch to the old ioremap-based EFI
			old_map [X86-64]: switch to the old ioremap-based EFI
			runtime services mapping. 32-bit still uses this one by
			runtime services mapping. 32-bit still uses this one by
			default.
			default.
@@ -1044,6 +1044,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
			boot stub, as chunking can cause problems with some
			boot stub, as chunking can cause problems with some
			firmware implementations.
			firmware implementations.
			noruntime : disable EFI runtime services support
			noruntime : disable EFI runtime services support
			debug: enable misc debug output


	efi_no_storage_paranoia [EFI; X86]
	efi_no_storage_paranoia [EFI; X86]
			Using this parameter you can use more than 50% of
			Using this parameter you can use more than 50% of
+4 −2
Original line number Original line Diff line number Diff line
@@ -2,6 +2,8 @@
#define _ASM_X86_EFI_H
#define _ASM_X86_EFI_H


#include <asm/i387.h>
#include <asm/i387.h>
#include <asm/pgtable.h>

/*
/*
 * We map the EFI regions needed for runtime services non-contiguously,
 * We map the EFI regions needed for runtime services non-contiguously,
 * with preserved alignment on virtual addresses starting from -4G down
 * with preserved alignment on virtual addresses starting from -4G down
@@ -89,8 +91,8 @@ extern void __iomem *__init efi_ioremap(unsigned long addr, unsigned long size,
extern struct efi_scratch efi_scratch;
extern struct efi_scratch efi_scratch;
extern void __init efi_set_executable(efi_memory_desc_t *md, bool executable);
extern void __init efi_set_executable(efi_memory_desc_t *md, bool executable);
extern int __init efi_memblock_x86_reserve_range(void);
extern int __init efi_memblock_x86_reserve_range(void);
extern void __init efi_call_phys_prolog(void);
extern pgd_t * __init efi_call_phys_prolog(void);
extern void __init efi_call_phys_epilog(void);
extern void __init efi_call_phys_epilog(pgd_t *save_pgd);
extern void __init efi_unmap_memmap(void);
extern void __init efi_unmap_memmap(void);
extern void __init efi_memory_uc(u64 addr, unsigned long size);
extern void __init efi_memory_uc(u64 addr, unsigned long size);
extern void __init efi_map_region(efi_memory_desc_t *md);
extern void __init efi_map_region(efi_memory_desc_t *md);
+14 −3
Original line number Original line Diff line number Diff line
@@ -85,12 +85,20 @@ static efi_status_t __init phys_efi_set_virtual_address_map(
	efi_memory_desc_t *virtual_map)
	efi_memory_desc_t *virtual_map)
{
{
	efi_status_t status;
	efi_status_t status;
	unsigned long flags;
	pgd_t *save_pgd;


	efi_call_phys_prolog();
	save_pgd = efi_call_phys_prolog();

	/* Disable interrupts around EFI calls: */
	local_irq_save(flags);
	status = efi_call_phys(efi_phys.set_virtual_address_map,
	status = efi_call_phys(efi_phys.set_virtual_address_map,
			       memory_map_size, descriptor_size,
			       memory_map_size, descriptor_size,
			       descriptor_version, virtual_map);
			       descriptor_version, virtual_map);
	efi_call_phys_epilog();
	local_irq_restore(flags);

	efi_call_phys_epilog(save_pgd);

	return status;
	return status;
}
}


@@ -491,6 +499,7 @@ void __init efi_init(void)
	if (efi_memmap_init())
	if (efi_memmap_init())
		return;
		return;


	if (efi_enabled(EFI_DBG))
		print_efi_memmap();
		print_efi_memmap();
}
}


@@ -939,6 +948,8 @@ static int __init arch_parse_efi_cmdline(char *str)
{
{
	if (parse_option_str(str, "old_map"))
	if (parse_option_str(str, "old_map"))
		set_bit(EFI_OLD_MEMMAP, &efi.flags);
		set_bit(EFI_OLD_MEMMAP, &efi.flags);
	if (parse_option_str(str, "debug"))
		set_bit(EFI_DBG, &efi.flags);


	return 0;
	return 0;
}
}
+11 −11
Original line number Original line Diff line number Diff line
@@ -33,11 +33,10 @@


/*
/*
 * To make EFI call EFI runtime service in physical addressing mode we need
 * To make EFI call EFI runtime service in physical addressing mode we need
 * prolog/epilog before/after the invocation to disable interrupt, to
 * prolog/epilog before/after the invocation to claim the EFI runtime service
 * claim EFI runtime service handler exclusively and to duplicate a memory in
 * handler exclusively and to duplicate a memory mapping in low memory space,
 * low memory space say 0 - 3G.
 * say 0 - 3G.
 */
 */
static unsigned long efi_rt_eflags;


void efi_sync_low_kernel_mappings(void) {}
void efi_sync_low_kernel_mappings(void) {}
void __init efi_dump_pagetable(void) {}
void __init efi_dump_pagetable(void) {}
@@ -57,21 +56,24 @@ void __init efi_map_region(efi_memory_desc_t *md)
void __init efi_map_region_fixed(efi_memory_desc_t *md) {}
void __init efi_map_region_fixed(efi_memory_desc_t *md) {}
void __init parse_efi_setup(u64 phys_addr, u32 data_len) {}
void __init parse_efi_setup(u64 phys_addr, u32 data_len) {}


void __init efi_call_phys_prolog(void)
pgd_t * __init efi_call_phys_prolog(void)
{
{
	struct desc_ptr gdt_descr;
	struct desc_ptr gdt_descr;
	pgd_t *save_pgd;


	local_irq_save(efi_rt_eflags);
	/* Current pgd is swapper_pg_dir, we'll restore it later: */

	save_pgd = swapper_pg_dir;
	load_cr3(initial_page_table);
	load_cr3(initial_page_table);
	__flush_tlb_all();
	__flush_tlb_all();


	gdt_descr.address = __pa(get_cpu_gdt_table(0));
	gdt_descr.address = __pa(get_cpu_gdt_table(0));
	gdt_descr.size = GDT_SIZE - 1;
	gdt_descr.size = GDT_SIZE - 1;
	load_gdt(&gdt_descr);
	load_gdt(&gdt_descr);

	return save_pgd;
}
}


void __init efi_call_phys_epilog(void)
void __init efi_call_phys_epilog(pgd_t *save_pgd)
{
{
	struct desc_ptr gdt_descr;
	struct desc_ptr gdt_descr;


@@ -79,10 +81,8 @@ void __init efi_call_phys_epilog(void)
	gdt_descr.size = GDT_SIZE - 1;
	gdt_descr.size = GDT_SIZE - 1;
	load_gdt(&gdt_descr);
	load_gdt(&gdt_descr);


	load_cr3(swapper_pg_dir);
	load_cr3(save_pgd);
	__flush_tlb_all();
	__flush_tlb_all();

	local_irq_restore(efi_rt_eflags);
}
}


void __init efi_runtime_mkexec(void)
void __init efi_runtime_mkexec(void)
+16 −13
Original line number Original line Diff line number Diff line
@@ -41,9 +41,6 @@
#include <asm/realmode.h>
#include <asm/realmode.h>
#include <asm/time.h>
#include <asm/time.h>


static pgd_t *save_pgd __initdata;
static unsigned long efi_flags __initdata;

/*
/*
 * We allocate runtime services regions bottom-up, starting from -4G, i.e.
 * We allocate runtime services regions bottom-up, starting from -4G, i.e.
 * 0xffff_ffff_0000_0000 and limit EFI VA mapping space to 64G.
 * 0xffff_ffff_0000_0000 and limit EFI VA mapping space to 64G.
@@ -78,17 +75,18 @@ static void __init early_code_mapping_set_exec(int executable)
	}
	}
}
}


void __init efi_call_phys_prolog(void)
pgd_t * __init efi_call_phys_prolog(void)
{
{
	unsigned long vaddress;
	unsigned long vaddress;
	pgd_t *save_pgd;

	int pgd;
	int pgd;
	int n_pgds;
	int n_pgds;


	if (!efi_enabled(EFI_OLD_MEMMAP))
	if (!efi_enabled(EFI_OLD_MEMMAP))
		return;
		return NULL;


	early_code_mapping_set_exec(1);
	early_code_mapping_set_exec(1);
	local_irq_save(efi_flags);


	n_pgds = DIV_ROUND_UP((max_pfn << PAGE_SHIFT), PGDIR_SIZE);
	n_pgds = DIV_ROUND_UP((max_pfn << PAGE_SHIFT), PGDIR_SIZE);
	save_pgd = kmalloc(n_pgds * sizeof(pgd_t), GFP_KERNEL);
	save_pgd = kmalloc(n_pgds * sizeof(pgd_t), GFP_KERNEL);
@@ -99,24 +97,29 @@ void __init efi_call_phys_prolog(void)
		set_pgd(pgd_offset_k(pgd * PGDIR_SIZE), *pgd_offset_k(vaddress));
		set_pgd(pgd_offset_k(pgd * PGDIR_SIZE), *pgd_offset_k(vaddress));
	}
	}
	__flush_tlb_all();
	__flush_tlb_all();

	return save_pgd;
}
}


void __init efi_call_phys_epilog(void)
void __init efi_call_phys_epilog(pgd_t *save_pgd)
{
{
	/*
	/*
	 * After the lock is released, the original page table is restored.
	 * After the lock is released, the original page table is restored.
	 */
	 */
	int pgd;
	int pgd_idx;
	int n_pgds = DIV_ROUND_UP((max_pfn << PAGE_SHIFT) , PGDIR_SIZE);
	int nr_pgds;


	if (!efi_enabled(EFI_OLD_MEMMAP))
	if (!save_pgd)
		return;
		return;


	for (pgd = 0; pgd < n_pgds; pgd++)
	nr_pgds = DIV_ROUND_UP((max_pfn << PAGE_SHIFT) , PGDIR_SIZE);
		set_pgd(pgd_offset_k(pgd * PGDIR_SIZE), save_pgd[pgd]);

	for (pgd_idx = 0; pgd_idx < nr_pgds; pgd_idx++)
		set_pgd(pgd_offset_k(pgd_idx * PGDIR_SIZE), save_pgd[pgd_idx]);

	kfree(save_pgd);
	kfree(save_pgd);

	__flush_tlb_all();
	__flush_tlb_all();
	local_irq_restore(efi_flags);
	early_code_mapping_set_exec(0);
	early_code_mapping_set_exec(0);
}
}


Loading