• Josh Boyer's avatar
    efivars: Disable external interrupt while holding efivars->lock · 3b048fc1
    Josh Boyer authored
    commit 81fa4e58 upstream.
    
    [Problem]
    There is a scenario which efi_pstore fails to log messages in a panic case.
    
     - CPUA holds an efi_var->lock in either efivarfs parts
       or efi_pstore with interrupt enabled.
     - CPUB panics and sends IPI to CPUA in smp_send_stop().
     - CPUA stops with holding the lock.
     - CPUB kicks efi_pstore_write() via kmsg_dump(KSMG_DUMP_PANIC)
       but it returns without logging messages.
    
    [Patch Description]
    This patch disables an external interruption while holding efivars->lock
    as follows.
    
    In efi_pstore_write() and get_var_data(), spin_lock/spin_unlock is
    replaced by spin_lock_irqsave/spin_unlock_irqrestore because they may
    be called in an interrupt context.
    
    In other functions, they are replaced by spin_lock_irq/spin_unlock_irq.
    because they are all called from a process context.
    
    By applying this patch, we can avoid the problem above with
    a following senario.
    
     - CPUA holds an efi_var->lock with interrupt disabled.
     - CPUB panics and sends IPI to CPUA in smp_send_stop().
     - CPUA receives the IPI after releasing the lock because it is
       disabling interrupt while holding the lock.
     - CPUB waits for one sec until CPUA releases the lock.
     - CPUB kicks efi_pstore_write() via kmsg_dump(KSMG_DUMP_PANIC)
       And it can hold the lock successfully.
    Signed-off-by: default avatarSeiji Aguchi <seiji.aguchi@hds.com>
    Acked-by: default avatarMike Waychison <mikew@google.com>
    Acked-by: default avatarMatt Fleming <matt.fleming@intel.com>
    Signed-off-by: default avatarTony Luck <tony.luck@intel.com>
    [bwh: Backported to 3.2:
     - Drop efivarfs changes
     - Adjust context
     - Drop change to efi_pstore_erase(), which is implemented using
       efi_pstore_write() here]
    Signed-off-by: default avatarBen Hutchings <ben@decadent.org.uk>
    3b048fc1
efivars.c 32.5 KB