--- /dev/null
+From 785107923a83d8456bbd8564e288a24d84109a46 Mon Sep 17 00:00:00 2001
+From: Josh Triplett <josh@joshtriplett.org>
+Date: Fri, 28 Sep 2012 17:55:44 -0700
+Subject: efi: Defer freeing boot services memory until after ACPI init
+
+From: Josh Triplett <josh@joshtriplett.org>
+
+commit 785107923a83d8456bbd8564e288a24d84109a46 upstream.
+
+Some new ACPI 5.0 tables reference resources stored in boot services
+memory, so keep that memory around until we have ACPI and can extract
+data from it.
+
+Signed-off-by: Josh Triplett <josh@joshtriplett.org>
+Link: http://lkml.kernel.org/r/baaa6d44bdc4eb0c58e5d1b4ccd2c729f854ac55.1348876882.git.josh@joshtriplett.org
+Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
+Cc: Matt Fleming <matt@console-pimps.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/x86/platform/efi/efi.c | 31 ++++++++++++++++++-------------
+ include/linux/efi.h | 5 +++++
+ init/main.c | 3 +++
+ 3 files changed, 26 insertions(+), 13 deletions(-)
+
+--- a/arch/x86/platform/efi/efi.c
++++ b/arch/x86/platform/efi/efi.c
+@@ -419,10 +419,21 @@ void __init efi_reserve_boot_services(vo
+ }
+ }
+
+-static void __init efi_free_boot_services(void)
++static void __init efi_unmap_memmap(void)
++{
++ if (memmap.map) {
++ early_iounmap(memmap.map, memmap.nr_map * memmap.desc_size);
++ memmap.map = NULL;
++ }
++}
++
++void __init efi_free_boot_services(void)
+ {
+ void *p;
+
++ if (!efi_native)
++ return;
++
+ for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
+ efi_memory_desc_t *md = p;
+ unsigned long long start = md->phys_addr;
+@@ -438,6 +449,8 @@ static void __init efi_free_boot_service
+
+ free_bootmem_late(start, size);
+ }
++
++ efi_unmap_memmap();
+ }
+
+ static int __init efi_systab_init(void *phys)
+@@ -787,8 +800,10 @@ void __init efi_enter_virtual_mode(void)
+ * non-native EFI
+ */
+
+- if (!efi_native)
+- goto out;
++ if (!efi_native) {
++ efi_unmap_memmap();
++ return;
++ }
+
+ /* Merge contiguous regions of the same type and attribute */
+ for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
+@@ -878,13 +893,6 @@ void __init efi_enter_virtual_mode(void)
+ }
+
+ /*
+- * Thankfully, it does seem that no runtime services other than
+- * SetVirtualAddressMap() will touch boot services code, so we can
+- * get rid of it all at this point
+- */
+- efi_free_boot_services();
+-
+- /*
+ * Now that EFI is in virtual mode, update the function
+ * pointers in the runtime service table to the new virtual addresses.
+ *
+@@ -907,9 +915,6 @@ void __init efi_enter_virtual_mode(void)
+ if (__supported_pte_mask & _PAGE_NX)
+ runtime_code_page_mkexec();
+
+-out:
+- early_iounmap(memmap.map, memmap.nr_map * memmap.desc_size);
+- memmap.map = NULL;
+ kfree(new_memmap);
+ }
+
+--- a/include/linux/efi.h
++++ b/include/linux/efi.h
+@@ -496,6 +496,11 @@ extern void efi_map_pal_code (void);
+ extern void efi_memmap_walk (efi_freemem_callback_t callback, void *arg);
+ extern void efi_gettimeofday (struct timespec *ts);
+ extern void efi_enter_virtual_mode (void); /* switch EFI to virtual mode, if possible */
++#ifdef CONFIG_X86
++extern void efi_free_boot_services(void);
++#else
++static inline void efi_free_boot_services(void) {}
++#endif
+ extern u64 efi_get_iobase (void);
+ extern u32 efi_mem_type (unsigned long phys_addr);
+ extern u64 efi_mem_attributes (unsigned long phys_addr);
+--- a/init/main.c
++++ b/init/main.c
+@@ -630,6 +630,9 @@ asmlinkage void __init start_kernel(void
+ acpi_early_init(); /* before LAPIC and SMP init */
+ sfi_init_late();
+
++ if (efi_enabled)
++ efi_free_boot_services();
++
+ ftrace_init();
+
+ /* Do the rest non-__init'ed, we're now alive */
--- /dev/null
+From 5189c2a7c7769ee9d037d76c1a7b8550ccf3481c Mon Sep 17 00:00:00 2001
+From: Olof Johansson <olof@lixom.net>
+Date: Wed, 24 Oct 2012 10:00:44 -0700
+Subject: x86: efi: Turn off efi_enabled after setup on mixed fw/kernel
+
+From: Olof Johansson <olof@lixom.net>
+
+commit 5189c2a7c7769ee9d037d76c1a7b8550ccf3481c upstream.
+
+When 32-bit EFI is used with 64-bit kernel (or vice versa), turn off
+efi_enabled once setup is done. Beyond setup, it is normally used to
+determine if runtime services are available and we will have none.
+
+This will resolve issues stemming from efivars modprobe panicking on a
+32/64-bit setup, as well as some reboot issues on similar setups.
+
+Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=45991
+
+Reported-by: Marko Kohtala <marko.kohtala@gmail.com>
+Reported-by: Maxim Kammerer <mk@dee.su>
+Signed-off-by: Olof Johansson <olof@lixom.net>
+Acked-by: Maarten Lankhorst <maarten.lankhorst@canonical.com>
+Cc: Matthew Garrett <mjg@redhat.com>
+Signed-off-by: Matt Fleming <matt.fleming@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/x86/include/asm/efi.h | 1 +
+ arch/x86/kernel/setup.c | 12 ++++++++++++
+ arch/x86/platform/efi/efi.c | 18 ++++++++++--------
+ 3 files changed, 23 insertions(+), 8 deletions(-)
+
+--- a/arch/x86/include/asm/efi.h
++++ b/arch/x86/include/asm/efi.h
+@@ -98,6 +98,7 @@ extern void efi_set_executable(efi_memor
+ extern int efi_memblock_x86_reserve_range(void);
+ extern void efi_call_phys_prelog(void);
+ extern void efi_call_phys_epilog(void);
++extern void efi_unmap_memmap(void);
+
+ #ifndef CONFIG_EFI
+ /*
+--- a/arch/x86/kernel/setup.c
++++ b/arch/x86/kernel/setup.c
+@@ -1053,6 +1053,18 @@ void __init setup_arch(char **cmdline_p)
+ mcheck_init();
+
+ arch_init_ideal_nops();
++
++#ifdef CONFIG_EFI
++ /* Once setup is done above, disable efi_enabled on mismatched
++ * firmware/kernel archtectures since there is no support for
++ * runtime services.
++ */
++ if (efi_enabled && IS_ENABLED(CONFIG_X86_64) != efi_64bit) {
++ pr_info("efi: Setup done, disabling due to 32/64-bit mismatch\n");
++ efi_unmap_memmap();
++ efi_enabled = 0;
++ }
++#endif
+ }
+
+ #ifdef CONFIG_X86_32
+--- a/arch/x86/platform/efi/efi.c
++++ b/arch/x86/platform/efi/efi.c
+@@ -69,11 +69,15 @@ EXPORT_SYMBOL(efi);
+ struct efi_memory_map memmap;
+
+ bool efi_64bit;
+-static bool efi_native;
+
+ static struct efi efi_phys __initdata;
+ static efi_system_table_t efi_systab __initdata;
+
++static inline bool efi_is_native(void)
++{
++ return IS_ENABLED(CONFIG_X86_64) == efi_64bit;
++}
++
+ static int __init setup_noefi(char *arg)
+ {
+ efi_enabled = 0;
+@@ -419,7 +423,7 @@ void __init efi_reserve_boot_services(vo
+ }
+ }
+
+-static void __init efi_unmap_memmap(void)
++void __init efi_unmap_memmap(void)
+ {
+ if (memmap.map) {
+ early_iounmap(memmap.map, memmap.nr_map * memmap.desc_size);
+@@ -431,7 +435,7 @@ void __init efi_free_boot_services(void)
+ {
+ void *p;
+
+- if (!efi_native)
++ if (!efi_is_native())
+ return;
+
+ for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
+@@ -683,12 +687,10 @@ void __init efi_init(void)
+ return;
+ }
+ efi_phys.systab = (efi_system_table_t *)boot_params.efi_info.efi_systab;
+- efi_native = !efi_64bit;
+ #else
+ efi_phys.systab = (efi_system_table_t *)
+ (boot_params.efi_info.efi_systab |
+ ((__u64)boot_params.efi_info.efi_systab_hi<<32));
+- efi_native = efi_64bit;
+ #endif
+
+ if (efi_systab_init(efi_phys.systab)) {
+@@ -722,7 +724,7 @@ void __init efi_init(void)
+ * that doesn't match the kernel 32/64-bit mode.
+ */
+
+- if (!efi_native)
++ if (!efi_is_native())
+ pr_info("No EFI runtime due to 32/64-bit mismatch with kernel\n");
+ else if (efi_runtime_init()) {
+ efi_enabled = 0;
+@@ -734,7 +736,7 @@ void __init efi_init(void)
+ return;
+ }
+ #ifdef CONFIG_X86_32
+- if (efi_native) {
++ if (efi_is_native()) {
+ x86_platform.get_wallclock = efi_get_time;
+ x86_platform.set_wallclock = efi_set_rtc_mmss;
+ }
+@@ -800,7 +802,7 @@ void __init efi_enter_virtual_mode(void)
+ * non-native EFI
+ */
+
+- if (!efi_native) {
++ if (!efi_is_native()) {
+ efi_unmap_memmap();
+ return;
+ }