[PATCH 7/8] x86: enable 64-bit kernel boot from 64-bit U-Boot
Simon Glass
sjg at chromium.org
Sun Apr 26 22:15:52 CEST 2020
Hi Aiden,
On Tue, 21 Apr 2020 at 18:45, <aiden.park at intel.com> wrote:
>
> From: Aiden Park <aiden.park at intel.com>
>
> Signed-off-by: Aiden Park <aiden.park at intel.com>
> ---
> arch/x86/cpu/x86_64/Makefile | 2 +-
> arch/x86/cpu/x86_64/call64.S | 21 +++++++++++++++++++++
> arch/x86/cpu/x86_64/cpu.c | 10 ++++++++++
> arch/x86/include/asm/bootparam.h | 10 +++++++++-
> arch/x86/include/asm/zimage.h | 2 +-
> arch/x86/lib/bootm.c | 10 +++++++---
> arch/x86/lib/zimage.c | 24 ++++++++++++++++--------
> 7 files changed, 65 insertions(+), 14 deletions(-)
> create mode 100644 arch/x86/cpu/x86_64/call64.S
>
> diff --git a/arch/x86/cpu/x86_64/Makefile b/arch/x86/cpu/x86_64/Makefile
> index 400f0ffe39..951e503a1f 100644
> --- a/arch/x86/cpu/x86_64/Makefile
> +++ b/arch/x86/cpu/x86_64/Makefile
> @@ -3,4 +3,4 @@
> # Written by Simon Glass <sjg at chromium.org>
> #
>
> -obj-y += cpu.o interrupts.o setjmp.o
> +obj-y += cpu.o interrupts.o setjmp.o call64.o
> diff --git a/arch/x86/cpu/x86_64/call64.S b/arch/x86/cpu/x86_64/call64.S
> new file mode 100644
> index 0000000000..e2cfe15080
> --- /dev/null
> +++ b/arch/x86/cpu/x86_64/call64.S
> @@ -0,0 +1,21 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * Copyright (C) 2020 Intel Corporation <www.intel.com>
> + */
> +
> +.code64
> +.globl cpu_call64
> +cpu_call64:
> + /*
> + * cpu_call64(ulong pgtable, ulong setup_base, ulong target)
> + *
> + * rdi - pgtable (unused - already in 64-bit with paging)
> + * rsi - setup_base
> + * rdx - target
> + *
> + */
> + cli
> + mov %rdx, %rcx
> + mov %rsi, %rdx
> + call *%rcx
> + ret
> diff --git a/arch/x86/cpu/x86_64/cpu.c b/arch/x86/cpu/x86_64/cpu.c
> index 90925e46ea..0730c43f1c 100644
> --- a/arch/x86/cpu/x86_64/cpu.c
> +++ b/arch/x86/cpu/x86_64/cpu.c
> @@ -7,6 +7,7 @@
> #include <common.h>
> #include <cpu_func.h>
> #include <debug_uart.h>
> +#include <asm/cpu.h>
>
> /*
> * Global declaration of gd.
> @@ -67,3 +68,12 @@ int x86_cpu_reinit_f(void)
> {
> return 0;
> }
> +
> +int cpu_jump_to_64bit(ulong setup_base, ulong load_address)
> +{
> + ulong target = load_address + 0x200;
> +
> + cpu_call64(0, setup_base, target);
> +
> + return -EFAULT;
> +}
> diff --git a/arch/x86/include/asm/bootparam.h b/arch/x86/include/asm/bootparam.h
> index d961dddc9e..73c94a33ec 100644
> --- a/arch/x86/include/asm/bootparam.h
> +++ b/arch/x86/include/asm/bootparam.h
> @@ -59,7 +59,15 @@ struct setup_header {
> __u32 initrd_addr_max;
> __u32 kernel_alignment;
> __u8 relocatable_kernel;
> - __u8 _pad2[3];
> + __u8 min_alignment;
> + __u16 xloadflags;
> +#define XLF_KERNEL_64 BIT(0)
> +#define XLF_CAN_BE_LOADED_ABOVE_4G BIT(1)
> +#define XLF_EFI_HANDOVER_32 BIT(2)
> +#define XLF_EFI_HANDOVER_64 BIT(3)
> +#define XLF_EFI_KEXEC BIT(4)
> +#define XLF_5LEVEL BIT(5)
> +#define XLF_5LEVEL_ENABLED BIT(6)
> __u32 cmdline_size;
> __u32 hardware_subarch;
> __u64 hardware_subarch_data;
> diff --git a/arch/x86/include/asm/zimage.h b/arch/x86/include/asm/zimage.h
> index 80e128ccf3..cadeb04168 100644
> --- a/arch/x86/include/asm/zimage.h
> +++ b/arch/x86/include/asm/zimage.h
> @@ -31,7 +31,7 @@
> #define ZIMAGE_LOAD_ADDR 0x10000
>
> struct boot_params *load_zimage(char *image, unsigned long kernel_size,
> - ulong *load_addressp);
> + ulong *load_addressp, bool *image_64bit);
Please put a 'p' on the end, so image_64bitp, since it a return value.
> int setup_zimage(struct boot_params *setup_base, char *cmd_line, int auto_boot,
> unsigned long initrd_addr, unsigned long initrd_size);
> void setup_video(struct screen_info *screen_info);
> diff --git a/arch/x86/lib/bootm.c b/arch/x86/lib/bootm.c
> index 07d8f1f279..ebed9e4605 100644
> --- a/arch/x86/lib/bootm.c
> +++ b/arch/x86/lib/bootm.c
> @@ -74,6 +74,7 @@ static int boot_prep_linux(bootm_headers_t *images)
> void *data = NULL;
> size_t len;
> int ret;
> + bool image_64bit;
>
> #ifdef CONFIG_OF_LIBFDT
> if (images->ft_len) {
> @@ -116,7 +117,8 @@ static int boot_prep_linux(bootm_headers_t *images)
> ulong load_address;
> char *base_ptr;
>
> - base_ptr = (char *)load_zimage(data, len, &load_address);
> + base_ptr = (char *)load_zimage(data, len, &load_address,
> + &image_64bit);
> if (!base_ptr) {
> puts("## Kernel loading failed ...\n");
> goto error;
> @@ -124,6 +126,10 @@ static int boot_prep_linux(bootm_headers_t *images)
> images->os.load = load_address;
> cmd_line_dest = base_ptr + COMMAND_LINE_OFFSET;
> images->ep = (ulong)base_ptr;
> +#if CONFIG_IS_ENABLED(X86_64)
> + if (image_64bit)
if (CONFIG_IS_ENABLED(X86_64) && image_64bit)
> + images->os.arch = IH_ARCH_X86_64;
> +#endif
> } else if (images->ep) {
> cmd_line_dest = (void *)images->ep + COMMAND_LINE_OFFSET;
> } else {
> @@ -164,9 +170,7 @@ int boot_linux_kernel(ulong setup_base, ulong load_address, bool image_64bit)
> * TODO(sjg at chromium.org): Support booting both 32-bit and
> * 64-bit kernels from 64-bit U-Boot.
> */
> -#if !CONFIG_IS_ENABLED(X86_64)
if()
> return cpu_jump_to_64bit(setup_base, load_address);
> -#endif
> } else {
> /*
> * Set %ebx, %ebp, and %edi to 0, %esi to point to the
> diff --git a/arch/x86/lib/zimage.c b/arch/x86/lib/zimage.c
> index ffc09630b7..c84e2d39b2 100644
> --- a/arch/x86/lib/zimage.c
> +++ b/arch/x86/lib/zimage.c
> @@ -129,7 +129,7 @@ static int setup_device_tree(struct setup_header *hdr, const void *fdt_blob)
> }
>
> struct boot_params *load_zimage(char *image, unsigned long kernel_size,
> - ulong *load_addressp)
> + ulong *load_addressp, bool *image_64bit)
image_64bitp
> {
> struct boot_params *setup_base;
> int setup_size;
> @@ -179,6 +179,9 @@ struct boot_params *load_zimage(char *image, unsigned long kernel_size,
> big_image = (bootproto >= 0x0200) &&
> (hdr->loadflags & BIG_KERNEL_FLAG);
>
> + /* Determine 64-bit kernel */
> + *image_64bit = (hdr->xloadflags & XLF_KERNEL_64) ? true : false;
> +
Drop ()
In fact I suspect you can do:
*image_64bit = hdr->xloadflags & XLF_KERNEL_64)
> /* Determine load address */
> if (big_image)
> *load_addressp = BZIMAGE_LOAD_ADDR;
> @@ -313,12 +316,13 @@ void __setup_pcat_compatibility(void)
> int do_zboot(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
> {
> struct boot_params *base_ptr;
> - void *bzImage_addr = NULL;
> + void *bzimage_addr = NULL;
Good change, but really should be in a separate patch.
> ulong load_address;
> char *s;
> - ulong bzImage_size = 0;
> + ulong bzimage_size = 0;
> ulong initrd_addr = 0;
> ulong initrd_size = 0;
> + bool image_64bit;
>
> disable_interrupts();
>
> @@ -333,11 +337,11 @@ int do_zboot(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
> }
>
> if (s)
> - bzImage_addr = (void *)simple_strtoul(s, NULL, 16);
> + bzimage_addr = (void *)simple_strtoul(s, NULL, 16);
>
> if (argc >= 3) {
> /* argv[2] holds the size of the bzImage */
> - bzImage_size = simple_strtoul(argv[2], NULL, 16);
> + bzimage_size = simple_strtoul(argv[2], NULL, 16);
> }
>
> if (argc >= 4)
> @@ -346,8 +350,13 @@ int do_zboot(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
> initrd_size = simple_strtoul(argv[4], NULL, 16);
>
> /* Lets look for */
> - base_ptr = load_zimage(bzImage_addr, bzImage_size, &load_address);
> + base_ptr = load_zimage(bzimage_addr, bzimage_size, &load_address,
> + &image_64bit);
> +#if !CONFIG_IS_ENABLED(X86_64)
if()
But why not just set it always?
> + image_64bit = false;
> +#endif
>
> + /* we assume that the kernel is in place */
> if (!base_ptr) {
> puts("## Kernel loading failed ...\n");
> return -1;
> @@ -358,8 +367,7 @@ int do_zboot(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
> return -1;
> }
>
> - /* we assume that the kernel is in place */
> - return boot_linux_kernel((ulong)base_ptr, load_address, false);
> + return boot_linux_kernel((ulong)base_ptr, load_address, image_64bit);
> }
>
> U_BOOT_CMD(
> --
> 2.20.1
>
Regards,
Simon
More information about the U-Boot
mailing list