On Thu, 3 Aug 2023 at 15:24, Ard Biesheuvel <a...@kernel.org> wrote: > > 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 > 1GiB 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 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 entrypoint in this case. > > This involves inspecting the xloadflags field in the setup header to > check whether the 64-bit entrypoint 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. (Note that Linux's 32-bit startup > code creates multiple shadow mappings of the first 1GiB of physical > memory up to the 4 GiB mark so anything that resides there becomes > inaccessible until the 64-bit startup code replaces the preliminary > mappings with more accurate ones) > > 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.ki...@oracle.com> > Cc: Julian Andres Klode <julian.kl...@canonical.com> > Signed-off-by: Ard Biesheuvel <a...@kernel.org>
Ping? > --- > 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 997647a33326eeb8..a83cc52a656d587b 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 (GRUB_MACHINE_EFI) && defined (__x86_64__) > + 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 0fd6e1212fd2fa86..d4b550869534e255 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; > -- > 2.39.2 > _______________________________________________ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel