Merge remote-tracking branch 'tip/x86/efi-mixed' into efi-for-mingo
[cascardo/linux.git] / arch / x86 / platform / efi / efi_64.c
index 12112ab..7e7f195 100644 (file)
@@ -139,16 +139,29 @@ void efi_sync_low_kernel_mappings(void)
                sizeof(pgd_t) * num_pgds);
 }
 
-void efi_setup_page_tables(void)
+int efi_setup_page_tables(unsigned long pa_memmap, unsigned num_pages)
 {
        unsigned long text;
-       unsigned npages;
        struct page *page;
+       unsigned npages;
+       pgd_t *pgd;
+
+       if (efi_enabled(EFI_OLD_MEMMAP))
+               return 0;
 
        efi_scratch.efi_pgt = (pgd_t *)(unsigned long)real_mode_header->trampoline_pgd;
+       pgd = __va(efi_scratch.efi_pgt);
 
-       if (efi_enabled(EFI_OLD_MEMMAP))
-               return;
+       /*
+        * It can happen that the physical address of new_memmap lands in memory
+        * which is not mapped in the EFI page table. Therefore we need to go
+        * and ident-map those pages containing the map before calling
+        * phys_efi_set_virtual_address_map().
+        */
+       if (kernel_map_pages_in_pgd(pgd, pa_memmap, pa_memmap, num_pages, _PAGE_NX)) {
+               pr_err("Error ident-mapping new memmap (0x%lx)!\n", pa_memmap);
+               return 1;
+       }
 
        efi_scratch.use_pgd = true;
 
@@ -159,7 +172,7 @@ void efi_setup_page_tables(void)
         * stack pointer being < 4GB.
         */
        if (!IS_ENABLED(CONFIG_EFI_MIXED))
-               return;
+               return 0;
 
        page = alloc_page(GFP_KERNEL|__GFP_DMA32);
        if (!page)
@@ -171,10 +184,19 @@ void efi_setup_page_tables(void)
        npages = (_end - _text) >> PAGE_SHIFT;
        text = __pa(_text);
 
-       if (kernel_map_pages_in_pgd(__va(efi_scratch.efi_pgt),
-                                   text >> PAGE_SHIFT, text, npages, 0)) {
+       if (kernel_map_pages_in_pgd(pgd, text >> PAGE_SHIFT, text, npages, 0)) {
                pr_err("Failed to map kernel text 1:1\n");
+               return 1;
        }
+
+       return 0;
+}
+
+void efi_cleanup_page_tables(unsigned long pa_memmap, unsigned num_pages)
+{
+       pgd_t *pgd = (pgd_t *)__va(real_mode_header->trampoline_pgd);
+
+       kernel_unmap_pages_in_pgd(pgd, pa_memmap, num_pages);
 }
 
 static void __init __map_region(efi_memory_desc_t *md, u64 va)
@@ -285,6 +307,15 @@ void __init efi_runtime_mkexec(void)
                runtime_code_page_mkexec();
 }
 
+void __init efi_dump_pagetable(void)
+{
+#ifdef CONFIG_EFI_PGT_DUMP
+       pgd_t *pgd = (pgd_t *)__va(real_mode_header->trampoline_pgd);
+
+       ptdump_walk_pgd_level(NULL, pgd);
+#endif
+}
+
 #ifdef CONFIG_EFI_MIXED
 extern efi_status_t efi64_thunk(u32, ...);