return dram_base + SZ_512M;
 }
 
+struct efi_arm_entry_state {
+       u32     cpsr_before_ebs;
+       u32     sctlr_before_ebs;
+       u32     cpsr_after_ebs;
+       u32     sctlr_after_ebs;
+};
+
 #endif /* _ASM_ARM_EFI_H */
 
 }
 
 static __initdata unsigned long screen_info_table = EFI_INVALID_TABLE_ADDR;
+static __initdata unsigned long cpu_state_table = EFI_INVALID_TABLE_ADDR;
 
 static const efi_config_table_type_t arch_tables[] __initconst = {
        {LINUX_EFI_ARM_SCREEN_INFO_TABLE_GUID, &screen_info_table},
+       {LINUX_EFI_ARM_CPU_STATE_TABLE_GUID, &cpu_state_table},
        {}
 };
 
 
        init_screen_info();
 
+#ifdef CONFIG_ARM
        /* ARM does not permit early mappings to persist across paging_init() */
-       if (IS_ENABLED(CONFIG_ARM))
-               efi_memmap_unmap();
+       efi_memmap_unmap();
+
+       if (cpu_state_table != EFI_INVALID_TABLE_ADDR) {
+               struct efi_arm_entry_state *state;
+               bool dump_state = true;
+
+               state = early_memremap_ro(cpu_state_table,
+                                         sizeof(struct efi_arm_entry_state));
+               if (state == NULL) {
+                       pr_warn("Unable to map CPU entry state table.\n");
+                       return;
+               }
+
+               if ((state->sctlr_before_ebs & 1) == 0)
+                       pr_warn(FW_BUG "EFI stub was entered with MMU and Dcache disabled, please fix your firmware!\n");
+               else if ((state->sctlr_after_ebs & 1) == 0)
+                       pr_warn(FW_BUG "ExitBootServices() returned with MMU and Dcache disabled, please fix your firmware!\n");
+               else
+                       dump_state = false;
+
+               if (dump_state || efi_enabled(EFI_DBG)) {
+                       pr_info("CPSR at EFI stub entry        : 0x%08x\n", state->cpsr_before_ebs);
+                       pr_info("SCTLR at EFI stub entry       : 0x%08x\n", state->sctlr_before_ebs);
+                       pr_info("CPSR after ExitBootServices() : 0x%08x\n", state->cpsr_after_ebs);
+                       pr_info("SCTLR after ExitBootServices(): 0x%08x\n", state->sctlr_after_ebs);
+               }
+               early_memunmap(state, sizeof(struct efi_arm_entry_state));
+       }
+#endif
 }
 
 static bool efifb_overlaps_pci_range(const struct of_pci_range *range)
 
 
 #include "efistub.h"
 
+static efi_guid_t cpu_state_guid = LINUX_EFI_ARM_CPU_STATE_TABLE_GUID;
+
+struct efi_arm_entry_state *efi_entry_state;
+
+static void get_cpu_state(u32 *cpsr, u32 *sctlr)
+{
+       asm("mrs %0, cpsr" : "=r"(*cpsr));
+       if ((*cpsr & MODE_MASK) == HYP_MODE)
+               asm("mrc p15, 4, %0, c1, c0, 0" : "=r"(*sctlr));
+       else
+               asm("mrc p15, 0, %0, c1, c0, 0" : "=r"(*sctlr));
+}
+
 efi_status_t check_platform_features(void)
 {
+       efi_status_t status;
+       u32 cpsr, sctlr;
        int block;
 
+       get_cpu_state(&cpsr, &sctlr);
+
+       efi_info("Entering in %s mode with MMU %sabled\n",
+                ((cpsr & MODE_MASK) == HYP_MODE) ? "HYP" : "SVC",
+                (sctlr & 1) ? "en" : "dis");
+
+       status = efi_bs_call(allocate_pool, EFI_LOADER_DATA,
+                            sizeof(*efi_entry_state),
+                            (void **)&efi_entry_state);
+       if (status != EFI_SUCCESS) {
+               efi_err("allocate_pool() failed\n");
+               return status;
+       }
+
+       efi_entry_state->cpsr_before_ebs = cpsr;
+       efi_entry_state->sctlr_before_ebs = sctlr;
+
+       status = efi_bs_call(install_configuration_table, &cpu_state_guid,
+                            efi_entry_state);
+       if (status != EFI_SUCCESS) {
+               efi_err("install_configuration_table() failed\n");
+               goto free_state;
+       }
+
        /* non-LPAE kernels can run anywhere */
        if (!IS_ENABLED(CONFIG_ARM_LPAE))
                return EFI_SUCCESS;
        block = cpuid_feature_extract(CPUID_EXT_MMFR0, 0);
        if (block < 5) {
                efi_err("This LPAE kernel is not supported by your CPU\n");
-               return EFI_UNSUPPORTED;
+               status = EFI_UNSUPPORTED;
+               goto drop_table;
        }
        return EFI_SUCCESS;
+
+drop_table:
+       efi_bs_call(install_configuration_table, &cpu_state_guid, NULL);
+free_state:
+       efi_bs_call(free_pool, efi_entry_state);
+       return status;
+}
+
+void efi_handle_post_ebs_state(void)
+{
+       get_cpu_state(&efi_entry_state->cpsr_after_ebs,
+                     &efi_entry_state->sctlr_after_ebs);
 }
 
 static efi_guid_t screen_info_guid = LINUX_EFI_ARM_SCREEN_INFO_TABLE_GUID;
 
        if (status != EFI_SUCCESS)
                goto fail_free_initrd;
 
+       if (IS_ENABLED(CONFIG_ARM))
+               efi_handle_post_ebs_state();
+
        efi_enter_kernel(image_addr, fdt_addr, fdt_totalsize((void *)fdt_addr));
        /* not reached */
 
 
                             unsigned long soft_limit,
                             unsigned long hard_limit);
 
+void efi_handle_post_ebs_state(void);
+
 #endif
 
  * associated with ConOut
  */
 #define LINUX_EFI_ARM_SCREEN_INFO_TABLE_GUID   EFI_GUID(0xe03fc20a, 0x85dc, 0x406e,  0xb9, 0x0e, 0x4a, 0xb5, 0x02, 0x37, 0x1d, 0x95)
+#define LINUX_EFI_ARM_CPU_STATE_TABLE_GUID     EFI_GUID(0xef79e4aa, 0x3c3d, 0x4989,  0xb9, 0x02, 0x07, 0xa9, 0x43, 0xe5, 0x50, 0xd2)
 #define LINUX_EFI_LOADER_ENTRY_GUID            EFI_GUID(0x4a67b082, 0x0a4c, 0x41cf,  0xb6, 0xc7, 0x44, 0x0b, 0x29, 0xbb, 0x8c, 0x4f)
 #define LINUX_EFI_RANDOM_SEED_TABLE_GUID       EFI_GUID(0x1ce1e5bc, 0x7ceb, 0x42f2,  0x81, 0xe5, 0x8a, 0xad, 0xf1, 0x80, 0xf5, 0x7b)
 #define LINUX_EFI_TPM_EVENT_LOG_GUID           EFI_GUID(0xb7799cb0, 0xeca2, 0x4943,  0x96, 0x67, 0x1f, 0xae, 0x07, 0xb7, 0x47, 0xfa)