Merge branch 'efi-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
authorLinus Torvalds <torvalds@linux-foundation.org>
Mon, 13 Aug 2018 17:25:08 +0000 (10:25 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Mon, 13 Aug 2018 17:25:08 +0000 (10:25 -0700)
Pull EFI updates from Thomas Gleixner:
 "The EFI pile:

   - Make mixed mode UEFI runtime service invocations mutually
     exclusive, as mandated by the UEFI spec

   - Perform UEFI runtime services calls from a work queue so the calls
     into the firmware occur from a kernel thread

   - Honor the UEFI memory map attributes for live memory regions
     configured by UEFI as a framebuffer. This works around a coherency
     problem with KVM guests running on ARM.

   - Cleanups, improvements and fixes all over the place"

* 'efi-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  efivars: Call guid_parse() against guid_t type of variable
  efi/cper: Use consistent types for UUIDs
  efi/x86: Replace references to efi_early->is64 with efi_is_64bit()
  efi: Deduplicate efi_open_volume()
  efi/x86: Add missing NULL initialization in UGA draw protocol discovery
  efi/x86: Merge 32-bit and 64-bit UGA draw protocol setup routines
  efi/x86: Align efi_uga_draw_protocol typedef names to convention
  efi/x86: Merge the setup_efi_pci32() and setup_efi_pci64() routines
  efi/x86: Prevent reentrant firmware calls in mixed mode
  efi/esrt: Only call efi_mem_reserve() for boot services memory
  fbdev/efifb: Honour UEFI memory map attributes when mapping the FB
  efi: Drop type and attribute checks in efi_mem_desc_lookup()
  efi/libstub/arm: Add opt-in Kconfig option for the DTB loader
  efi: Remove the declaration of efi_late_init() as the function is unused
  efi/cper: Avoid using get_seconds()
  efi: Use a work queue to invoke EFI Runtime Services
  efi/x86: Use non-blocking SetVariable() for efi_delete_dummy_variable()
  efi/x86: Clean up the eboot code

1  2 
arch/x86/platform/efi/efi_64.c

index 5f2eb32316073f15307aa28ac8b37a17230ea751,448267f1c073fd82e27627697c068bb7f1251a1a..ee5d08f25ce45f21aa81550ce317760a2c745900
@@@ -417,7 -417,7 +417,7 @@@ static void __init __map_region(efi_mem
        if (!(md->attribute & EFI_MEMORY_WB))
                flags |= _PAGE_PCD;
  
 -      if (sev_active())
 +      if (sev_active() && md->type != EFI_MEMORY_MAPPED_IO)
                flags |= _PAGE_ENC;
  
        pfn = md->phys_addr >> PAGE_SHIFT;
@@@ -636,6 -636,8 +636,8 @@@ void efi_switch_mm(struct mm_struct *mm
  #ifdef CONFIG_EFI_MIXED
  extern efi_status_t efi64_thunk(u32, ...);
  
+ static DEFINE_SPINLOCK(efi_runtime_lock);
  #define runtime_service32(func)                                                \
  ({                                                                     \
        u32 table = (u32)(unsigned long)efi.systab;                      \
  #define efi_thunk(f, ...)                                             \
  ({                                                                    \
        efi_status_t __s;                                               \
-       unsigned long __flags;                                          \
        u32 __func;                                                     \
                                                                        \
-       local_irq_save(__flags);                                        \
        arch_efi_call_virt_setup();                                     \
                                                                        \
        __func = runtime_service32(f);                                  \
        __s = efi64_thunk(__func, __VA_ARGS__);                         \
                                                                        \
        arch_efi_call_virt_teardown();                                  \
-       local_irq_restore(__flags);                                     \
                                                                        \
        __s;                                                            \
  })
@@@ -702,14 -701,17 +701,17 @@@ static efi_status_t efi_thunk_get_time(
  {
        efi_status_t status;
        u32 phys_tm, phys_tc;
+       unsigned long flags;
  
        spin_lock(&rtc_lock);
+       spin_lock_irqsave(&efi_runtime_lock, flags);
  
        phys_tm = virt_to_phys_or_null(tm);
        phys_tc = virt_to_phys_or_null(tc);
  
        status = efi_thunk(get_time, phys_tm, phys_tc);
  
+       spin_unlock_irqrestore(&efi_runtime_lock, flags);
        spin_unlock(&rtc_lock);
  
        return status;
@@@ -719,13 -721,16 +721,16 @@@ static efi_status_t efi_thunk_set_time(
  {
        efi_status_t status;
        u32 phys_tm;
+       unsigned long flags;
  
        spin_lock(&rtc_lock);
+       spin_lock_irqsave(&efi_runtime_lock, flags);
  
        phys_tm = virt_to_phys_or_null(tm);
  
        status = efi_thunk(set_time, phys_tm);
  
+       spin_unlock_irqrestore(&efi_runtime_lock, flags);
        spin_unlock(&rtc_lock);
  
        return status;
@@@ -737,8 -742,10 +742,10 @@@ efi_thunk_get_wakeup_time(efi_bool_t *e
  {
        efi_status_t status;
        u32 phys_enabled, phys_pending, phys_tm;
+       unsigned long flags;
  
        spin_lock(&rtc_lock);
+       spin_lock_irqsave(&efi_runtime_lock, flags);
  
        phys_enabled = virt_to_phys_or_null(enabled);
        phys_pending = virt_to_phys_or_null(pending);
        status = efi_thunk(get_wakeup_time, phys_enabled,
                             phys_pending, phys_tm);
  
+       spin_unlock_irqrestore(&efi_runtime_lock, flags);
        spin_unlock(&rtc_lock);
  
        return status;
@@@ -757,13 -765,16 +765,16 @@@ efi_thunk_set_wakeup_time(efi_bool_t en
  {
        efi_status_t status;
        u32 phys_tm;
+       unsigned long flags;
  
        spin_lock(&rtc_lock);
+       spin_lock_irqsave(&efi_runtime_lock, flags);
  
        phys_tm = virt_to_phys_or_null(tm);
  
        status = efi_thunk(set_wakeup_time, enabled, phys_tm);
  
+       spin_unlock_irqrestore(&efi_runtime_lock, flags);
        spin_unlock(&rtc_lock);
  
        return status;
@@@ -781,6 -792,9 +792,9 @@@ efi_thunk_get_variable(efi_char16_t *na
        efi_status_t status;
        u32 phys_name, phys_vendor, phys_attr;
        u32 phys_data_size, phys_data;
+       unsigned long flags;
+       spin_lock_irqsave(&efi_runtime_lock, flags);
  
        phys_data_size = virt_to_phys_or_null(data_size);
        phys_vendor = virt_to_phys_or_null(vendor);
        status = efi_thunk(get_variable, phys_name, phys_vendor,
                           phys_attr, phys_data_size, phys_data);
  
+       spin_unlock_irqrestore(&efi_runtime_lock, flags);
        return status;
  }
  
@@@ -800,6 -816,34 +816,34 @@@ efi_thunk_set_variable(efi_char16_t *na
  {
        u32 phys_name, phys_vendor, phys_data;
        efi_status_t status;
+       unsigned long flags;
+       spin_lock_irqsave(&efi_runtime_lock, flags);
+       phys_name = virt_to_phys_or_null_size(name, efi_name_size(name));
+       phys_vendor = virt_to_phys_or_null(vendor);
+       phys_data = virt_to_phys_or_null_size(data, data_size);
+       /* If data_size is > sizeof(u32) we've got problems */
+       status = efi_thunk(set_variable, phys_name, phys_vendor,
+                          attr, data_size, phys_data);
+       spin_unlock_irqrestore(&efi_runtime_lock, flags);
+       return status;
+ }
+ static efi_status_t
+ efi_thunk_set_variable_nonblocking(efi_char16_t *name, efi_guid_t *vendor,
+                                  u32 attr, unsigned long data_size,
+                                  void *data)
+ {
+       u32 phys_name, phys_vendor, phys_data;
+       efi_status_t status;
+       unsigned long flags;
+       if (!spin_trylock_irqsave(&efi_runtime_lock, flags))
+               return EFI_NOT_READY;
  
        phys_name = virt_to_phys_or_null_size(name, efi_name_size(name));
        phys_vendor = virt_to_phys_or_null(vendor);
        status = efi_thunk(set_variable, phys_name, phys_vendor,
                           attr, data_size, phys_data);
  
+       spin_unlock_irqrestore(&efi_runtime_lock, flags);
        return status;
  }
  
@@@ -819,6 -865,9 +865,9 @@@ efi_thunk_get_next_variable(unsigned lo
  {
        efi_status_t status;
        u32 phys_name_size, phys_name, phys_vendor;
+       unsigned long flags;
+       spin_lock_irqsave(&efi_runtime_lock, flags);
  
        phys_name_size = virt_to_phys_or_null(name_size);
        phys_vendor = virt_to_phys_or_null(vendor);
        status = efi_thunk(get_next_variable, phys_name_size,
                           phys_name, phys_vendor);
  
+       spin_unlock_irqrestore(&efi_runtime_lock, flags);
        return status;
  }
  
@@@ -835,10 -886,15 +886,15 @@@ efi_thunk_get_next_high_mono_count(u32 
  {
        efi_status_t status;
        u32 phys_count;
+       unsigned long flags;
+       spin_lock_irqsave(&efi_runtime_lock, flags);
  
        phys_count = virt_to_phys_or_null(count);
        status = efi_thunk(get_next_high_mono_count, phys_count);
  
+       spin_unlock_irqrestore(&efi_runtime_lock, flags);
        return status;
  }
  
@@@ -847,10 -903,15 +903,15 @@@ efi_thunk_reset_system(int reset_type, 
                       unsigned long data_size, efi_char16_t *data)
  {
        u32 phys_data;
+       unsigned long flags;
+       spin_lock_irqsave(&efi_runtime_lock, flags);
  
        phys_data = virt_to_phys_or_null_size(data, data_size);
  
        efi_thunk(reset_system, reset_type, status, data_size, phys_data);
+       spin_unlock_irqrestore(&efi_runtime_lock, flags);
  }
  
  static efi_status_t
@@@ -872,10 -933,13 +933,13 @@@ efi_thunk_query_variable_info(u32 attr
  {
        efi_status_t status;
        u32 phys_storage, phys_remaining, phys_max;
+       unsigned long flags;
  
        if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
                return EFI_UNSUPPORTED;
  
+       spin_lock_irqsave(&efi_runtime_lock, flags);
        phys_storage = virt_to_phys_or_null(storage_space);
        phys_remaining = virt_to_phys_or_null(remaining_space);
        phys_max = virt_to_phys_or_null(max_variable_size);
        status = efi_thunk(query_variable_info, attr, phys_storage,
                           phys_remaining, phys_max);
  
+       spin_unlock_irqrestore(&efi_runtime_lock, flags);
+       return status;
+ }
+ static efi_status_t
+ efi_thunk_query_variable_info_nonblocking(u32 attr, u64 *storage_space,
+                                         u64 *remaining_space,
+                                         u64 *max_variable_size)
+ {
+       efi_status_t status;
+       u32 phys_storage, phys_remaining, phys_max;
+       unsigned long flags;
+       if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
+               return EFI_UNSUPPORTED;
+       if (!spin_trylock_irqsave(&efi_runtime_lock, flags))
+               return EFI_NOT_READY;
+       phys_storage = virt_to_phys_or_null(storage_space);
+       phys_remaining = virt_to_phys_or_null(remaining_space);
+       phys_max = virt_to_phys_or_null(max_variable_size);
+       status = efi_thunk(query_variable_info, attr, phys_storage,
+                          phys_remaining, phys_max);
+       spin_unlock_irqrestore(&efi_runtime_lock, flags);
        return status;
  }
  
@@@ -908,9 -1001,11 +1001,11 @@@ void efi_thunk_runtime_setup(void
        efi.get_variable = efi_thunk_get_variable;
        efi.get_next_variable = efi_thunk_get_next_variable;
        efi.set_variable = efi_thunk_set_variable;
+       efi.set_variable_nonblocking = efi_thunk_set_variable_nonblocking;
        efi.get_next_high_mono_count = efi_thunk_get_next_high_mono_count;
        efi.reset_system = efi_thunk_reset_system;
        efi.query_variable_info = efi_thunk_query_variable_info;
+       efi.query_variable_info_nonblocking = efi_thunk_query_variable_info_nonblocking;
        efi.update_capsule = efi_thunk_update_capsule;
        efi.query_capsule_caps = efi_thunk_query_capsule_caps;
  }