mbox series

[GIT,PULL,0/5] EFI fixes for v4.20

Message ID 20181114175544.12860-1-ard.biesheuvel@linaro.org
Headers show
Series EFI fixes for v4.20 | expand

Message

Ard Biesheuvel Nov. 14, 2018, 5:55 p.m. UTC
The following changes since commit ccda4af0f4b92f7b4c308d3acc262f4a7e3affad:

  Linux 4.20-rc2 (2018-11-11 17:12:31 -0600)

are available in the Git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/efi/efi.git efi-urgent

for you to fetch changes up to 844d2592ed2f1903f8e38d8d395fd0d38ecdd536:

  efi: permit calling efi_mem_reserve_persistent from atomic context (2018-11-14 05:49:28 -0800)

----------------------------------------------------------------
EFI fixes for v4.20:
- fix incorrect 'on stack' annotation of efi_rts_work (all EFI arches)
- revert deferred memory map unmapping on ARM
- pack the FDT before handing over to the OS (ARM, arm64)
- fixes for new persistent memreserve feature (ARM, arm64)

----------------------------------------------------------------
Ard Biesheuvel (4):
      efi: arm: revert deferred unmap of early memmap mapping
      efi/arm: libstub: pack FDT after populating it
      efi/arm: defer persistent reservations until after paging_init()
      efi: permit calling efi_mem_reserve_persistent from atomic context

Waiman Long (1):
      efi: Fix debugobjects warning on efi_rts_work

 arch/arm64/kernel/setup.c               |  1 +
 drivers/firmware/efi/arm-init.c         |  4 ++++
 drivers/firmware/efi/arm-runtime.c      |  2 +-
 drivers/firmware/efi/efi.c              | 35 ++++++++++++++++++++++-----------
 drivers/firmware/efi/libstub/arm-stub.c |  3 +++
 drivers/firmware/efi/libstub/fdt.c      |  4 ++++
 drivers/firmware/efi/memmap.c           |  3 +++
 drivers/firmware/efi/runtime-wrappers.c |  2 +-
 include/linux/efi.h                     |  7 +++++++
 9 files changed, 47 insertions(+), 14 deletions(-)

Comments

Jeremy Linton Nov. 27, 2018, 6:59 p.m. UTC | #1
Hi Ard,


On 11/14/2018 11:55 AM, Ard Biesheuvel wrote:
> Currently, efi_mem_reserve_persistent() may not be called from atomic

> context, since both the kmalloc() call and the memremap() call may

> sleep.

> 

> The kmalloc() call is easy enough to fix, but the memremap() call

> needs to be moved into an init hook since we cannot control the

> memory allocation behavior of memremap() at the call site.


So, at first glance this looks correct until I noticed that 
its_cpu_init_lpis() is being called before the early_initcalls are run.

This results in the WARN_ON triggering with the following backtrace:

[    0.000000]  its_cpu_init_lpis+0x1d4/0x2e0
[    0.000000]  its_cpu_init+0x78/0x1b4
[    0.000000]  gic_init_bases+0x2c4/0x2e0
[    0.000000]  gic_acpi_init+0x158/0x270
[    0.000000]  acpi_match_madt+0x4c/0x84
[    0.000000]  acpi_table_parse_entries_array+0x140/0x218
[    0.000000]  acpi_table_parse_entries+0x70/0x98
[    0.000000]  acpi_table_parse_madt+0x40/0x50
[    0.000000]  __acpi_probe_device_table+0x88/0xe0
[    0.000000]  irqchip_init+0x38/0x40
[    0.000000]  init_IRQ+0xfc/0x130
[    0.000000]  start_kernel+0x344/0x4cc

due to the efi_memreserve_root not yet being set.



> 

> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>

> ---

>   drivers/firmware/efi/efi.c | 31 +++++++++++++++++++------------

>   1 file changed, 19 insertions(+), 12 deletions(-)

> 

> diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c

> index 72a4da76d274..fad7c62cfc0e 100644

> --- a/drivers/firmware/efi/efi.c

> +++ b/drivers/firmware/efi/efi.c

> @@ -967,36 +967,43 @@ bool efi_is_table_address(unsigned long phys_addr)

>   }

>   

>   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)

>   {

> -	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;

>   

> -	rsv = kmalloc(sizeof(*rsv), GFP_KERNEL);

> +	rsv = kmalloc(sizeof(*rsv), GFP_ATOMIC);

>   	if (!rsv)

>   		return -ENOMEM;

>   

> -	parent = memremap(efi.mem_reserve, sizeof(*rsv), MEMREMAP_WB);

> -	if (!parent) {

> -		kfree(rsv);

> -		return -ENOMEM;

> -	}

> -

>   	rsv->base = addr;

>   	rsv->size = size;

>   

>   	spin_lock(&efi_mem_reserve_persistent_lock);

> -	rsv->next = parent->next;

> -	parent->next = __pa(rsv);

> +	rsv->next = efi_memreserve_root->next;

> +	efi_memreserve_root->next = __pa(rsv);

>   	spin_unlock(&efi_mem_reserve_persistent_lock);

>   

> -	memunmap(parent);

> +	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

>   static int update_efi_random_seed(struct notifier_block *nb,

>