diff options
Diffstat (limited to 'user/grub/0008-efi-pure64.patch')
-rw-r--r-- | user/grub/0008-efi-pure64.patch | 110 |
1 files changed, 110 insertions, 0 deletions
diff --git a/user/grub/0008-efi-pure64.patch b/user/grub/0008-efi-pure64.patch new file mode 100644 index 000000000..e07323c63 --- /dev/null +++ b/user/grub/0008-efi-pure64.patch @@ -0,0 +1,110 @@ +From 67ae3981dc5113e5af3a0539174bcd7eab8f7722 Mon Sep 17 00:00:00 2001 +From: Ard Biesheuvel <ardb@kernel.org> +Date: Thu, 3 Aug 2023 15:24:09 +0200 +Subject: loader/i386/linux: Prefer entry in long mode when booting via EFI + +The x86_64 Linux kernel can be booted in 32-bit mode, in which case the +startup code creates a set of preliminary page tables that map the first +4 GiB of physical memory 1:1 and enables paging. This is a prerequisite +for 64-bit execution and can therefore only be implemented in 32-bit code. + +The x86_64 Linux kernel can also be booted in 64-bit mode directly: this +implies that paging is already enabled and it is the responsibility of +the bootloader to ensure that the active page tables cover the entire +loaded image, including its BSS space, the size of which is described in +the image's setup header. + +Given that the EFI spec mandates execution in long mode for x86_64 and +stipulates that all system memory is mapped 1:1, the Linux/x86 +requirements for 64-bit entry can be met trivially when booting on +x86_64 via EFI. So, enter via the 64-bit entry point in this case. + +This involves inspecting the xloadflags field in the setup header to +check whether the 64-bit entry point is supported. This field was +introduced in Linux version v3.8 (early 2013). + +This change ensures that all EFI firmware tables and other assets passed +by the firmware or bootloader in memory remain mapped and accessible +throughout the early startup code. + +Avoiding the drop out of long mode will also be needed to support +upcoming CPU designs that no longer implement 32-bit mode at all +(as recently announced by Intel [0]). + +[0] https://www.intel.com/content/www/us/en/developer/articles/technical/envisioning-future-simplified-architecture.html + +Cc: Daniel Kiper <daniel.kiper@oracle.com> +Cc: Julian Andres Klode <julian.klode@canonical.com> +Signed-off-by: Ard Biesheuvel <ardb@kernel.org> +Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com> +--- + grub-core/loader/i386/linux.c | 12 ++++++++++++ + include/grub/i386/linux.h | 15 +++++++++++++-- + 2 files changed, 25 insertions(+), 2 deletions(-) + +diff --git a/grub-core/loader/i386/linux.c b/grub-core/loader/i386/linux.c +index 997647a..977757f 100644 +--- a/grub-core/loader/i386/linux.c ++++ b/grub-core/loader/i386/linux.c +@@ -624,6 +624,18 @@ grub_linux_boot (void) + } + #endif + ++#if defined (__x86_64__) && defined (GRUB_MACHINE_EFI) ++ if (grub_le_to_cpu16 (ctx.params->version) >= 0x020c && ++ (linux_params.xloadflags & LINUX_X86_XLF_KERNEL_64) != 0) ++ { ++ struct grub_relocator64_efi_state state64; ++ ++ state64.rsi = ctx.real_mode_target; ++ state64.rip = ctx.params->code32_start + LINUX_X86_STARTUP64_OFFSET; ++ return grub_relocator64_efi_boot (relocator, state64); ++ } ++#endif ++ + /* FIXME. */ + /* asm volatile ("lidt %0" : : "m" (idt_desc)); */ + state.ebp = state.edi = state.ebx = 0; +diff --git a/include/grub/i386/linux.h b/include/grub/i386/linux.h +index 0fd6e12..d4b5508 100644 +--- a/include/grub/i386/linux.h ++++ b/include/grub/i386/linux.h +@@ -69,6 +69,16 @@ + #define GRUB_LINUX_OFW_SIGNATURE \ + (' ' << 24 | 'W' << 16 | 'F' << 8 | 'O') + ++#define LINUX_X86_XLF_KERNEL_64 (1<<0) ++#define LINUX_X86_XLF_CAN_BE_LOADED_ABOVE_4G (1<<1) ++#define LINUX_X86_XLF_EFI_HANDOVER_32 (1<<2) ++#define LINUX_X86_XLF_EFI_HANDOVER_64 (1<<3) ++#define LINUX_X86_XLF_EFI_KEXEC (1<<4) ++#define LINUX_X86_XLF_5LEVEL (1<<5) ++#define LINUX_X86_XLF_5LEVEL_ENABLED (1<<6) ++ ++#define LINUX_X86_STARTUP64_OFFSET 0x200 ++ + #ifndef ASM_FILE + + #define GRUB_E820_RAM 1 +@@ -138,7 +148,7 @@ struct linux_i386_kernel_header + grub_uint32_t kernel_alignment; + grub_uint8_t relocatable; + grub_uint8_t min_alignment; +- grub_uint8_t pad[2]; ++ grub_uint16_t xloadflags; + grub_uint32_t cmdline_size; + grub_uint32_t hardware_subarch; + grub_uint64_t hardware_subarch_data; +@@ -315,7 +325,8 @@ struct linux_kernel_params + grub_uint32_t initrd_addr_max; /* Maximum initrd address */ + grub_uint32_t kernel_alignment; /* Alignment of the kernel */ + grub_uint8_t relocatable_kernel; /* Is the kernel relocatable */ +- grub_uint8_t pad1[3]; ++ grub_uint8_t min_alignment; ++ grub_uint16_t xloadflags; + grub_uint32_t cmdline_size; /* Size of the kernel command line */ + grub_uint32_t hardware_subarch; + grub_uint64_t hardware_subarch_data; +-- +cgit v1.1 + |