Merge branch 'efi-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull EFI fixes from Ingo Molnar:
 "Misc fixes: two warning splat fixes, a leak fix and persistent memory
  allocation fixes for ARM"

* 'efi-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  efi: Permit calling efi_mem_reserve_persistent() from atomic context
  efi/arm: Defer persistent reservations until after paging_init()
  efi/arm/libstub: Pack FDT after populating it
  efi/arm: Revert deferred unmap of early memmap mapping
  efi: Fix debugobjects warning on 'efi_rts_work'
This commit is contained in:
Linus Torvalds 2018-11-18 10:52:26 -08:00
commit 743a4863fd
9 changed files with 48 additions and 15 deletions

View File

@ -313,6 +313,7 @@ void __init setup_arch(char **cmdline_p)
arm64_memblock_init(); arm64_memblock_init();
paging_init(); paging_init();
efi_apply_persistent_mem_reservations();
acpi_table_upgrade(); acpi_table_upgrade();

View File

@ -265,6 +265,10 @@ void __init efi_init(void)
(params.mmap & ~PAGE_MASK))); (params.mmap & ~PAGE_MASK)));
init_screen_info(); init_screen_info();
/* ARM does not permit early mappings to persist across paging_init() */
if (IS_ENABLED(CONFIG_ARM))
efi_memmap_unmap();
} }
static int __init register_gop_device(void) static int __init register_gop_device(void)

View File

@ -110,7 +110,7 @@ static int __init arm_enable_runtime_services(void)
{ {
u64 mapsize; u64 mapsize;
if (!efi_enabled(EFI_BOOT) || !efi_enabled(EFI_MEMMAP)) { if (!efi_enabled(EFI_BOOT)) {
pr_info("EFI services will not be available.\n"); pr_info("EFI services will not be available.\n");
return 0; return 0;
} }

View File

@ -592,7 +592,11 @@ int __init efi_config_parse_tables(void *config_tables, int count, int sz,
early_memunmap(tbl, sizeof(*tbl)); early_memunmap(tbl, sizeof(*tbl));
} }
return 0;
}
int __init efi_apply_persistent_mem_reservations(void)
{
if (efi.mem_reserve != EFI_INVALID_TABLE_ADDR) { if (efi.mem_reserve != EFI_INVALID_TABLE_ADDR) {
unsigned long prsv = efi.mem_reserve; unsigned long prsv = efi.mem_reserve;
@ -963,37 +967,44 @@ bool efi_is_table_address(unsigned long phys_addr)
} }
static DEFINE_SPINLOCK(efi_mem_reserve_persistent_lock); static DEFINE_SPINLOCK(efi_mem_reserve_persistent_lock);
static struct linux_efi_memreserve *efi_memreserve_root __ro_after_init;
int efi_mem_reserve_persistent(phys_addr_t addr, u64 size) int efi_mem_reserve_persistent(phys_addr_t addr, u64 size)
{ {
struct linux_efi_memreserve *rsv, *parent; struct linux_efi_memreserve *rsv;
if (efi.mem_reserve == EFI_INVALID_TABLE_ADDR) if (!efi_memreserve_root)
return -ENODEV; return -ENODEV;
rsv = kmalloc(sizeof(*rsv), GFP_KERNEL); rsv = kmalloc(sizeof(*rsv), GFP_ATOMIC);
if (!rsv) if (!rsv)
return -ENOMEM; return -ENOMEM;
parent = memremap(efi.mem_reserve, sizeof(*rsv), MEMREMAP_WB);
if (!parent) {
kfree(rsv);
return -ENOMEM;
}
rsv->base = addr; rsv->base = addr;
rsv->size = size; rsv->size = size;
spin_lock(&efi_mem_reserve_persistent_lock); spin_lock(&efi_mem_reserve_persistent_lock);
rsv->next = parent->next; rsv->next = efi_memreserve_root->next;
parent->next = __pa(rsv); efi_memreserve_root->next = __pa(rsv);
spin_unlock(&efi_mem_reserve_persistent_lock); spin_unlock(&efi_mem_reserve_persistent_lock);
memunmap(parent);
return 0; return 0;
} }
static int __init efi_memreserve_root_init(void)
{
if (efi.mem_reserve == EFI_INVALID_TABLE_ADDR)
return -ENODEV;
efi_memreserve_root = memremap(efi.mem_reserve,
sizeof(*efi_memreserve_root),
MEMREMAP_WB);
if (!efi_memreserve_root)
return -ENOMEM;
return 0;
}
early_initcall(efi_memreserve_root_init);
#ifdef CONFIG_KEXEC #ifdef CONFIG_KEXEC
static int update_efi_random_seed(struct notifier_block *nb, static int update_efi_random_seed(struct notifier_block *nb,
unsigned long code, void *unused) unsigned long code, void *unused)

View File

@ -75,6 +75,9 @@ void install_memreserve_table(efi_system_table_t *sys_table_arg)
efi_guid_t memreserve_table_guid = LINUX_EFI_MEMRESERVE_TABLE_GUID; efi_guid_t memreserve_table_guid = LINUX_EFI_MEMRESERVE_TABLE_GUID;
efi_status_t status; efi_status_t status;
if (IS_ENABLED(CONFIG_ARM))
return;
status = efi_call_early(allocate_pool, EFI_LOADER_DATA, sizeof(*rsv), status = efi_call_early(allocate_pool, EFI_LOADER_DATA, sizeof(*rsv),
(void **)&rsv); (void **)&rsv);
if (status != EFI_SUCCESS) { if (status != EFI_SUCCESS) {

View File

@ -158,6 +158,10 @@ static efi_status_t update_fdt(efi_system_table_t *sys_table, void *orig_fdt,
return efi_status; return efi_status;
} }
} }
/* shrink the FDT back to its minimum size */
fdt_pack(fdt);
return EFI_SUCCESS; return EFI_SUCCESS;
fdt_set_fail: fdt_set_fail:

View File

@ -118,6 +118,9 @@ int __init efi_memmap_init_early(struct efi_memory_map_data *data)
void __init efi_memmap_unmap(void) void __init efi_memmap_unmap(void)
{ {
if (!efi_enabled(EFI_MEMMAP))
return;
if (!efi.memmap.late) { if (!efi.memmap.late) {
unsigned long size; unsigned long size;

View File

@ -67,7 +67,7 @@ struct efi_runtime_work efi_rts_work;
} \ } \
\ \
init_completion(&efi_rts_work.efi_rts_comp); \ init_completion(&efi_rts_work.efi_rts_comp); \
INIT_WORK_ONSTACK(&efi_rts_work.work, efi_call_rts); \ INIT_WORK(&efi_rts_work.work, efi_call_rts); \
efi_rts_work.arg1 = _arg1; \ efi_rts_work.arg1 = _arg1; \
efi_rts_work.arg2 = _arg2; \ efi_rts_work.arg2 = _arg2; \
efi_rts_work.arg3 = _arg3; \ efi_rts_work.arg3 = _arg3; \

View File

@ -1167,6 +1167,8 @@ static inline bool efi_enabled(int feature)
extern void efi_reboot(enum reboot_mode reboot_mode, const char *__unused); extern void efi_reboot(enum reboot_mode reboot_mode, const char *__unused);
extern bool efi_is_table_address(unsigned long phys_addr); extern bool efi_is_table_address(unsigned long phys_addr);
extern int efi_apply_persistent_mem_reservations(void);
#else #else
static inline bool efi_enabled(int feature) static inline bool efi_enabled(int feature)
{ {
@ -1185,6 +1187,11 @@ static inline bool efi_is_table_address(unsigned long phys_addr)
{ {
return false; return false;
} }
static inline int efi_apply_persistent_mem_reservations(void)
{
return 0;
}
#endif #endif
extern int efi_status_to_err(efi_status_t status); extern int efi_status_to_err(efi_status_t status);