x86/efistub: Perform 4/5 level paging switch from the stub
[linux-2.6-microblaze.git] / drivers / firmware / efi / libstub / x86-stub.c
index 9247dbc..af5f506 100644 (file)
@@ -17,6 +17,7 @@
 #include <asm/boot.h>
 
 #include "efistub.h"
+#include "x86-stub.h"
 
 /* Maximum physical address for 64-bit kernel with 4-level paging */
 #define MAXMEM_X86_64_4LEVEL (1ull << 46)
@@ -223,8 +224,8 @@ static void retrieve_apple_device_properties(struct boot_params *boot_params)
        }
 }
 
-static void
-adjust_memory_range_protection(unsigned long start, unsigned long size)
+void efi_adjust_memory_range_protection(unsigned long start,
+                                       unsigned long size)
 {
        efi_status_t status;
        efi_gcd_memory_space_desc_t desc;
@@ -278,35 +279,14 @@ adjust_memory_range_protection(unsigned long start, unsigned long size)
        }
 }
 
-/*
- * Trampoline takes 2 pages and can be loaded in first megabyte of memory
- * with its end placed between 128k and 640k where BIOS might start.
- * (see arch/x86/boot/compressed/pgtable_64.c)
- *
- * We cannot find exact trampoline placement since memory map
- * can be modified by UEFI, and it can alter the computed address.
- */
-
-#define TRAMPOLINE_PLACEMENT_BASE ((128 - 8)*1024)
-#define TRAMPOLINE_PLACEMENT_SIZE (640*1024 - (128 - 8)*1024)
-
 extern const u8 startup_32[], startup_64[];
 
 static void
 setup_memory_protection(unsigned long image_base, unsigned long image_size)
 {
-       /*
-        * Allow execution of possible trampoline used
-        * for switching between 4- and 5-level page tables
-        * and relocated kernel image.
-        */
-
-       adjust_memory_range_protection(TRAMPOLINE_PLACEMENT_BASE,
-                                      TRAMPOLINE_PLACEMENT_SIZE);
-
 #ifdef CONFIG_64BIT
        if (image_base != (unsigned long)startup_32)
-               adjust_memory_range_protection(image_base, image_size);
+               efi_adjust_memory_range_protection(image_base, image_size);
 #else
        /*
         * Clear protection flags on a whole range of possible
@@ -316,8 +296,8 @@ setup_memory_protection(unsigned long image_base, unsigned long image_size)
         * need to remove possible protection on relocated image
         * itself disregarding further relocations.
         */
-       adjust_memory_range_protection(LOAD_PHYSICAL_ADDR,
-                                      KERNEL_IMAGE_SIZE - LOAD_PHYSICAL_ADDR);
+       efi_adjust_memory_range_protection(LOAD_PHYSICAL_ADDR,
+                                          KERNEL_IMAGE_SIZE - LOAD_PHYSICAL_ADDR);
 #endif
 }
 
@@ -839,6 +819,12 @@ void __noreturn efi_stub_entry(efi_handle_t handle,
                efi_dxe_table = NULL;
        }
 
+       status = efi_setup_5level_paging();
+       if (status != EFI_SUCCESS) {
+               efi_err("efi_setup_5level_paging() failed!\n");
+               goto fail;
+       }
+
        /*
         * If the kernel isn't already loaded at a suitable address,
         * relocate it.
@@ -959,6 +945,8 @@ void __noreturn efi_stub_entry(efi_handle_t handle,
                goto fail;
        }
 
+       efi_5level_switch();
+
        if (IS_ENABLED(CONFIG_X86_64))
                bzimage_addr += startup_64 - startup_32;