diff --git a/hypervisor/Makefile b/hypervisor/Makefile index f02fe375e..41602cb01 100644 --- a/hypervisor/Makefile +++ b/hypervisor/Makefile @@ -289,6 +289,9 @@ endif ifeq ($(CONFIG_GUEST_KERNEL_RAWIMAGE),y) VP_BASE_C_SRCS += boot/guest/rawimage_loader.c endif +ifeq ($(CONFIG_GUEST_KERNEL_ELF),y) +VP_BASE_C_SRCS += boot/guest/elf_loader.c +endif VP_BASE_C_SRCS += common/hv_main.c VP_BASE_C_SRCS += common/vm_load.c VP_BASE_C_SRCS += arch/x86/configs/pci_dev.c diff --git a/hypervisor/boot/guest/elf_loader.c b/hypervisor/boot/guest/elf_loader.c new file mode 100644 index 000000000..340c99000 --- /dev/null +++ b/hypervisor/boot/guest/elf_loader.c @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2021 Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +/** + * @pre vm != NULL + * must run in stac/clac context + */ +static void *do_load_elf64(struct acrn_vm *vm) +{ + struct sw_kernel_info *sw_kernel = &(vm->sw.kernel_info); + void *p_elf_img = (void *)sw_kernel->kernel_src_addr; + + return p_elf_img; +} + +/** + * @pre vm != NULL + * must run in stac/clac context + */ +static void *do_load_elf32(struct acrn_vm *vm) +{ + struct sw_kernel_info *sw_kernel = &(vm->sw.kernel_info); + void *p_elf_img = (void *)sw_kernel->kernel_src_addr; + + return p_elf_img; +} + +/** + * @pre vm != NULL + */ +static int32_t load_elf(struct acrn_vm *vm) +{ + void *elf_entry = NULL; + struct sw_kernel_info *sw_kernel = &(vm->sw.kernel_info); + void *p_elf_img = (void *)sw_kernel->kernel_src_addr; + int32_t ret = 0; + + stac(); + + if (*(uint32_t *)p_elf_img == ELFMAGIC) { + if (*(uint8_t *)(p_elf_img + EI_CLASS) == ELFCLASS64) { + elf_entry = do_load_elf64(vm); + } else if (*(uint8_t *)(p_elf_img + EI_CLASS) == ELFCLASS32) { + elf_entry = do_load_elf32(vm); + } else { + pr_err("%s, unsupported elf class(%d)", __func__, *(uint8_t *)(p_elf_img + EI_CLASS)); + } + } else { + pr_err("%s, booting elf but no elf header found!", __func__); + } + + clac(); + + sw_kernel->kernel_entry_addr = elf_entry; + + if (elf_entry == NULL) { + ret = -EFAULT; + } + + return ret; +} + +int32_t elf_loader(struct acrn_vm *vm) +{ + uint64_t vgdt_gpa = 0x800; + + /* + * TODO: + * - We need to initialize the guest BSP(boot strap processor) registers according to + * guest boot mode (real mode vs protect mode) + * - The memory layout usage is unclear, only GDT might be needed as its boot param. + * currently we only support Zephyr which has no needs on cmdline/e820/efimmap/etc. + * hardcode the vGDT GPA to 0x800 where is not used by Zephyr so far; + */ + init_vcpu_protect_mode_regs(vcpu_from_vid(vm, BSP_CPU_ID), vgdt_gpa); + + return load_elf(vm); +} diff --git a/hypervisor/boot/include/guest/vboot.h b/hypervisor/boot/include/guest/vboot.h index 960ee474e..63ac5c84c 100644 --- a/hypervisor/boot/include/guest/vboot.h +++ b/hypervisor/boot/include/guest/vboot.h @@ -17,6 +17,8 @@ int32_t bzimage_loader(struct acrn_vm *vm); #ifdef CONFIG_GUEST_KERNEL_RAWIMAGE int32_t rawimage_loader(struct acrn_vm *vm); #endif - +#ifdef CONFIG_GUEST_KERNEL_ELF +int32_t elf_loader(struct acrn_vm *vm); +#endif #endif /* end of include guard: VBOOT_H */ diff --git a/hypervisor/common/vm_load.c b/hypervisor/common/vm_load.c index a2c480bbb..f5ab7bb5f 100644 --- a/hypervisor/common/vm_load.c +++ b/hypervisor/common/vm_load.c @@ -39,6 +39,11 @@ int32_t prepare_os_image(struct acrn_vm *vm) case KERNEL_RAWIMAGE: ret = rawimage_loader(vm); break; +#endif +#ifdef CONFIG_GUEST_KERNEL_ELF + case KERNEL_ELF: + ret = elf_loader(vm); + break; #endif default: ret = -EINVAL;