• Seiji Aguchi's avatar
    efivars: Disable external interrupt while holding efivars->lock · 71727cd9
    Seiji Aguchi 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>
    Cc: Josh Boyer <jwboyer@redhat.com>
    Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
    
    71727cd9
efivars.c 48.5 KB