summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/arm/include/asm/efi.h4
-rw-r--r--arch/arm64/include/asm/efi.h4
-rw-r--r--arch/x86/include/asm/efi.h9
-rw-r--r--drivers/firmware/efi/runtime-wrappers.c53
-rw-r--r--include/linux/efi.h51
5 files changed, 69 insertions, 52 deletions
diff --git a/arch/arm/include/asm/efi.h b/arch/arm/include/asm/efi.h
index a708fa1f0905..766bf9b78160 100644
--- a/arch/arm/include/asm/efi.h
+++ b/arch/arm/include/asm/efi.h
@@ -28,10 +28,10 @@ int efi_set_mapping_permissions(struct mm_struct *mm, efi_memory_desc_t *md);
#define arch_efi_call_virt_setup() efi_virtmap_load()
#define arch_efi_call_virt_teardown() efi_virtmap_unload()
-#define arch_efi_call_virt(f, args...) \
+#define arch_efi_call_virt(p, f, args...) \
({ \
efi_##f##_t *__f; \
- __f = efi.systab->runtime->f; \
+ __f = p->f; \
__f(args); \
})
diff --git a/arch/arm64/include/asm/efi.h b/arch/arm64/include/asm/efi.h
index 622db3c6474e..bd887663689b 100644
--- a/arch/arm64/include/asm/efi.h
+++ b/arch/arm64/include/asm/efi.h
@@ -23,10 +23,10 @@ int efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md);
efi_virtmap_load(); \
})
-#define arch_efi_call_virt(f, args...) \
+#define arch_efi_call_virt(p, f, args...) \
({ \
efi_##f##_t *__f; \
- __f = efi.systab->runtime->f; \
+ __f = p->f; \
__f(args); \
})
diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h
index 78d1e7467eae..55b4596ef688 100644
--- a/arch/x86/include/asm/efi.h
+++ b/arch/x86/include/asm/efi.h
@@ -41,10 +41,9 @@ extern unsigned long asmlinkage efi_call_phys(void *, ...);
/*
* Wrap all the virtual calls in a way that forces the parameters on the stack.
*/
-#define arch_efi_call_virt(f, args...) \
+#define arch_efi_call_virt(p, f, args...) \
({ \
- ((efi_##f##_t __attribute__((regparm(0)))*) \
- efi.systab->runtime->f)(args); \
+ ((efi_##f##_t __attribute__((regparm(0)))*) p->f)(args); \
})
#define efi_ioremap(addr, size, type, attr) ioremap_cache(addr, size)
@@ -81,8 +80,8 @@ struct efi_scratch {
} \
})
-#define arch_efi_call_virt(f, args...) \
- efi_call((void *)efi.systab->runtime->f, args) \
+#define arch_efi_call_virt(p, f, args...) \
+ efi_call((void *)p->f, args) \
#define arch_efi_call_virt_teardown() \
({ \
diff --git a/drivers/firmware/efi/runtime-wrappers.c b/drivers/firmware/efi/runtime-wrappers.c
index 23bef6bb73ee..41958774cde3 100644
--- a/drivers/firmware/efi/runtime-wrappers.c
+++ b/drivers/firmware/efi/runtime-wrappers.c
@@ -22,7 +22,16 @@
#include <linux/stringify.h>
#include <asm/efi.h>
-static void efi_call_virt_check_flags(unsigned long flags, const char *call)
+/*
+ * Wrap around the new efi_call_virt_generic() macros so that the
+ * code doesn't get too cluttered:
+ */
+#define efi_call_virt(f, args...) \
+ efi_call_virt_pointer(efi.systab->runtime, f, args)
+#define __efi_call_virt(f, args...) \
+ __efi_call_virt_pointer(efi.systab->runtime, f, args)
+
+void efi_call_virt_check_flags(unsigned long flags, const char *call)
{
unsigned long cur_flags, mismatch;
@@ -39,48 +48,6 @@ static void efi_call_virt_check_flags(unsigned long flags, const char *call)
}
/*
- * Arch code can implement the following three template macros, avoiding
- * reptition for the void/non-void return cases of {__,}efi_call_virt:
- *
- * * arch_efi_call_virt_setup
- *
- * Sets up the environment for the call (e.g. switching page tables,
- * allowing kernel-mode use of floating point, if required).
- *
- * * arch_efi_call_virt
- *
- * Performs the call. The last expression in the macro must be the call
- * itself, allowing the logic to be shared by the void and non-void
- * cases.
- *
- * * arch_efi_call_virt_teardown
- *
- * Restores the usual kernel environment once the call has returned.
- */
-
-#define efi_call_virt(f, args...) \
-({ \
- efi_status_t __s; \
- unsigned long flags; \
- arch_efi_call_virt_setup(); \
- local_save_flags(flags); \
- __s = arch_efi_call_virt(f, args); \
- efi_call_virt_check_flags(flags, __stringify(f)); \
- arch_efi_call_virt_teardown(); \
- __s; \
-})
-
-#define __efi_call_virt(f, args...) \
-({ \
- unsigned long flags; \
- arch_efi_call_virt_setup(); \
- local_save_flags(flags); \
- arch_efi_call_virt(f, args); \
- efi_call_virt_check_flags(flags, __stringify(f)); \
- arch_efi_call_virt_teardown(); \
-})
-
-/*
* According to section 7.1 of the UEFI spec, Runtime Services are not fully
* reentrant, and there are particular combinations of calls that need to be
* serialized. (source: UEFI Specification v2.4A)
diff --git a/include/linux/efi.h b/include/linux/efi.h
index 03009695760d..75d148dc9c3f 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -1480,4 +1480,55 @@ efi_status_t efi_setup_gop(efi_system_table_t *sys_table_arg,
unsigned long size);
bool efi_runtime_disabled(void);
+extern void efi_call_virt_check_flags(unsigned long flags, const char *call);
+
+/*
+ * Arch code can implement the following three template macros, avoiding
+ * reptition for the void/non-void return cases of {__,}efi_call_virt():
+ *
+ * * arch_efi_call_virt_setup()
+ *
+ * Sets up the environment for the call (e.g. switching page tables,
+ * allowing kernel-mode use of floating point, if required).
+ *
+ * * arch_efi_call_virt()
+ *
+ * Performs the call. The last expression in the macro must be the call
+ * itself, allowing the logic to be shared by the void and non-void
+ * cases.
+ *
+ * * arch_efi_call_virt_teardown()
+ *
+ * Restores the usual kernel environment once the call has returned.
+ */
+
+#define efi_call_virt_pointer(p, f, args...) \
+({ \
+ efi_status_t __s; \
+ unsigned long __flags; \
+ \
+ arch_efi_call_virt_setup(); \
+ \
+ local_save_flags(__flags); \
+ __s = arch_efi_call_virt(p, f, args); \
+ efi_call_virt_check_flags(__flags, __stringify(f)); \
+ \
+ arch_efi_call_virt_teardown(); \
+ \
+ __s; \
+})
+
+#define __efi_call_virt_pointer(p, f, args...) \
+({ \
+ unsigned long __flags; \
+ \
+ arch_efi_call_virt_setup(); \
+ \
+ local_save_flags(__flags); \
+ arch_efi_call_virt(p, f, args); \
+ efi_call_virt_check_flags(__flags, __stringify(f)); \
+ \
+ arch_efi_call_virt_teardown(); \
+})
+
#endif /* _LINUX_EFI_H */