diff --git a/hypervisor/Makefile b/hypervisor/Makefile index 967c34979..0d81fe04c 100644 --- a/hypervisor/Makefile +++ b/hypervisor/Makefile @@ -193,6 +193,7 @@ endif BOOT_S_SRCS += arch/x86/boot/cpu_primary.S BOOT_S_SRCS += arch/x86/boot/cpu_save_boot_ctx.S BOOT_S_SRCS += arch/x86/boot/trampoline.S +BOOT_C_SRCS += boot/multiboot.c BOOT_C_SRCS += boot/reloc.c # hardware management component diff --git a/hypervisor/arch/x86/cpu.c b/hypervisor/arch/x86/cpu.c index 355ad0a72..8c5a0ac6f 100644 --- a/hypervisor/arch/x86/cpu.c +++ b/hypervisor/arch/x86/cpu.c @@ -116,6 +116,10 @@ void init_pcpu_pre(bool is_bsp) panic("hardware not support!"); } + if (sanitize_multiboot_info() != 0) { + panic("Multiboot info error!"); + } + init_pcpu_model_name(); load_pcpu_state_data(); diff --git a/hypervisor/arch/x86/e820.c b/hypervisor/arch/x86/e820.c index 6a9ff3231..19614abd4 100644 --- a/hypervisor/arch/x86/e820.c +++ b/hypervisor/arch/x86/e820.c @@ -114,54 +114,34 @@ void init_e820(void) uint32_t i; uint64_t top_addr_space = CONFIG_PLATFORM_RAM_SIZE + PLATFORM_LO_MMIO_SIZE; - if (boot_regs[0] == MULTIBOOT_INFO_MAGIC) { - /* - * Before installing new PML4 table in enable_paging(), HPA->HVA is always 1:1 mapping - * and hpa2hva() can't be used to do the conversion. Here we simply treat boot_reg[1] as HPA. - */ - uint64_t hpa = (uint64_t)boot_regs[1]; - struct multiboot_info *mbi = (struct multiboot_info *)hpa; + struct acrn_multiboot_info *mbi = get_multiboot_info(); + struct multiboot_mmap *mmap = mbi->mi_mmap_entry; - pr_info("Multiboot info detected\n"); - if ((mbi->mi_flags & MULTIBOOT_INFO_HAS_MMAP) != 0U) { - /* HPA->HVA is always 1:1 mapping at this moment */ - hpa = (uint64_t)mbi->mi_mmap_addr; - struct multiboot_mmap *mmap = (struct multiboot_mmap *)hpa; + hv_e820_entries_nr = mbi->mi_mmap_entries; - hv_e820_entries_nr = mbi->mi_mmap_length / sizeof(struct multiboot_mmap); - if (hv_e820_entries_nr > E820_MAX_ENTRIES) { - pr_err("Too many E820 entries %d\n", hv_e820_entries_nr); - hv_e820_entries_nr = E820_MAX_ENTRIES; - } + dev_dbg(DBG_LEVEL_E820, "mmap addr 0x%x entries %d\n", + mbi->mi_mmap_entry, hv_e820_entries_nr); - dev_dbg(DBG_LEVEL_E820, "mmap length 0x%x addr 0x%x entries %d\n", - mbi->mi_mmap_length, mbi->mi_mmap_addr, hv_e820_entries_nr); - for (i = 0U; i < hv_e820_entries_nr; i++) { - if (mmap[i].baseaddr >= top_addr_space) { - mmap[i].length = 0UL; - } else { - if ((mmap[i].baseaddr + mmap[i].length) > top_addr_space) { - mmap[i].length = top_addr_space - mmap[i].baseaddr; - } - } - - hv_e820[i].baseaddr = mmap[i].baseaddr; - hv_e820[i].length = mmap[i].length; - hv_e820[i].type = mmap[i].type; - - dev_dbg(DBG_LEVEL_E820, "mmap table: %d type: 0x%x\n", i, mmap[i].type); - dev_dbg(DBG_LEVEL_E820, "Base: 0x%016lx length: 0x%016lx", - mmap[i].baseaddr, mmap[i].length); - } + for (i = 0U; i < hv_e820_entries_nr; i++) { + if (mmap[i].baseaddr >= top_addr_space) { + mmap[i].length = 0UL; } else { - panic("no memory map found from multiboot info"); + if ((mmap[i].baseaddr + mmap[i].length) > top_addr_space) { + mmap[i].length = top_addr_space - mmap[i].baseaddr; + } } - obtain_mem_range_info(); - } else { - panic("no multiboot info found"); + hv_e820[i].baseaddr = mmap[i].baseaddr; + hv_e820[i].length = mmap[i].length; + hv_e820[i].type = mmap[i].type; + + dev_dbg(DBG_LEVEL_E820, "mmap table: %d type: 0x%x\n", i, mmap[i].type); + dev_dbg(DBG_LEVEL_E820, "Base: 0x%016lx length: 0x%016lx", + mmap[i].baseaddr, mmap[i].length); } + + obtain_mem_range_info(); } uint32_t get_e820_entries_count(void) diff --git a/hypervisor/arch/x86/init.c b/hypervisor/arch/x86/init.c index e99e183c6..b991797a8 100644 --- a/hypervisor/arch/x86/init.c +++ b/hypervisor/arch/x86/init.c @@ -14,7 +14,7 @@ #include #include #include -#include +#include /* Push sp magic to top of stack for call trace */ #define SWITCH_TO(rsp, to) \ diff --git a/hypervisor/arch/x86/seed/seed.c b/hypervisor/arch/x86/seed/seed.c index 3cd91ceb1..ee9ddccba 100644 --- a/hypervisor/arch/x86/seed/seed.c +++ b/hypervisor/arch/x86/seed/seed.c @@ -41,17 +41,12 @@ static uint32_t parse_seed_arg(void) { char *cmd_src = NULL; char *arg, *arg_end; - struct multiboot_info *mbi = NULL; + struct acrn_multiboot_info *mbi = get_multiboot_info(); uint32_t i = SEED_ARG_NUM - 1U; uint32_t len; - if (boot_regs[0U] == MULTIBOOT_INFO_MAGIC) { - mbi = (struct multiboot_info *)hpa2hva((uint64_t)boot_regs[1U]); - if (mbi != NULL) { - if ((mbi->mi_flags & MULTIBOOT_INFO_HAS_CMDLINE) != 0U) { - cmd_src = (char *)hpa2hva((uint64_t)mbi->mi_cmdline); - } - } + if ((mbi->mi_flags & MULTIBOOT_INFO_HAS_CMDLINE) != 0U) { + cmd_src = mbi->mi_cmdline; } if (cmd_src != NULL) { diff --git a/hypervisor/boot/cmdline.c b/hypervisor/boot/cmdline.c index a68c98bc1..79096d557 100644 --- a/hypervisor/boot/cmdline.c +++ b/hypervisor/boot/cmdline.c @@ -16,7 +16,7 @@ void parse_hv_cmdline(void) const char *start = NULL; const char *end = NULL; - if ((boot_regs[0] == MULTIBOOT_INFO_MAGIC) && (boot_regs[1] != 0U)) { + if (boot_from_multiboot1()) { struct multiboot_info *mbi = (struct multiboot_info *)(hpa2hva_early((uint64_t)boot_regs[1])); if ((mbi->mi_flags & MULTIBOOT_INFO_HAS_CMDLINE) != 0U) { diff --git a/hypervisor/boot/guest/deprivilege_boot.c b/hypervisor/boot/guest/deprivilege_boot.c index 895c2d68a..24e366f0c 100644 --- a/hypervisor/boot/guest/deprivilege_boot.c +++ b/hypervisor/boot/guest/deprivilege_boot.c @@ -24,11 +24,10 @@ static struct lapic_regs depri_boot_lapic_regs; static void init_depri_boot(void) { static bool depri_initialized = false; - struct multiboot_info *mbi = NULL; + struct acrn_multiboot_info *mbi = get_multiboot_info(); if (!depri_initialized) { - mbi = (struct multiboot_info *) hpa2hva(((uint64_t)(uint32_t)boot_regs[1])); - if ((mbi == NULL) || ((mbi->mi_flags & MULTIBOOT_INFO_HAS_DRIVES) == 0U)) { + if ((mbi->mi_flags & MULTIBOOT_INFO_HAS_DRIVES) == 0U) { pr_err("no multiboot drivers for depri_boot found"); } else { (void)memcpy_s(&depri_boot_ctx, sizeof(struct depri_boot_context), diff --git a/hypervisor/boot/guest/vboot_info.c b/hypervisor/boot/guest/vboot_info.c index 43bfd4b6e..67c80961f 100644 --- a/hypervisor/boot/guest/vboot_info.c +++ b/hypervisor/boot/guest/vboot_info.c @@ -151,7 +151,7 @@ static int32_t init_vm_kernel_info(struct acrn_vm *vm, const struct multiboot_mo /** * @pre vm != NULL && mbi != NULL */ -static void init_vm_bootargs_info(struct acrn_vm *vm, const struct multiboot_info *mbi) +static void init_vm_bootargs_info(struct acrn_vm *vm, const struct acrn_multiboot_info *mbi) { struct acrn_vm_config *vm_config = get_vm_config(vm->vm_id); char *bootargs = vm_config->os_config.bootargs; @@ -162,12 +162,12 @@ static void init_vm_bootargs_info(struct acrn_vm *vm, const struct multiboot_inf } else { /* vm_config->load_order == SOS_VM */ if (((mbi->mi_flags & MULTIBOOT_INFO_HAS_CMDLINE) != 0U) - && (*(char *)hpa2hva(mbi->mi_cmdline) != 0)) { + && (*(mbi->mi_cmdline) != '\0')) { /* * If there is cmdline from mbi->mi_cmdline, merge it with * vm_config->os_config.bootargs */ - merge_cmdline(vm, hpa2hva((uint64_t)mbi->mi_cmdline), bootargs); + merge_cmdline(vm, mbi->mi_cmdline, bootargs); vm->sw.bootargs_info.src_addr = kernel_cmdline; vm->sw.bootargs_info.size = strnlen_s(kernel_cmdline, MAX_BOOTARGS_SIZE); @@ -210,10 +210,10 @@ static uint32_t get_mod_idx_by_tag(const struct multiboot_module *mods, uint32_t /* @pre vm != NULL && mbi != NULL */ -static int32_t init_vm_sw_load(struct acrn_vm *vm, const struct multiboot_info *mbi) +static int32_t init_vm_sw_load(struct acrn_vm *vm, const struct acrn_multiboot_info *mbi) { struct acrn_vm_config *vm_config = get_vm_config(vm->vm_id); - struct multiboot_module *mods = (struct multiboot_module *)hpa2hva((uint64_t)mbi->mi_mods_addr); + struct multiboot_module *mods = (struct multiboot_module *)(&mbi->mi_mods[0]); uint32_t mod_idx; int32_t ret = -EINVAL; @@ -245,25 +245,17 @@ static int32_t init_vm_sw_load(struct acrn_vm *vm, const struct multiboot_info * */ static int32_t init_general_vm_boot_info(struct acrn_vm *vm) { - struct multiboot_info *mbi = NULL; + struct acrn_multiboot_info *mbi = get_multiboot_info(); int32_t ret = -EINVAL; - if (boot_regs[0] != MULTIBOOT_INFO_MAGIC) { - panic("no multiboot info found"); + stac(); + if ((mbi->mi_flags & MULTIBOOT_INFO_HAS_MODS) == 0U) { + panic("no multiboot module info found"); } else { - mbi = (struct multiboot_info *)hpa2hva((uint64_t)boot_regs[1]); - - if (mbi != NULL) { - stac(); - dev_dbg(DBG_LEVEL_BOOT, "Multiboot detected, flag=0x%x", mbi->mi_flags); - if ((mbi->mi_flags & MULTIBOOT_INFO_HAS_MODS) == 0U) { - panic("no multiboot module info found"); - } else { - ret = init_vm_sw_load(vm, mbi); - } - clac(); - } + ret = init_vm_sw_load(vm, mbi); } + clac(); + return ret; } diff --git a/hypervisor/boot/guest/vboot_wrapper.c b/hypervisor/boot/guest/vboot_wrapper.c index 54fb09602..3519794a0 100644 --- a/hypervisor/boot/guest/vboot_wrapper.c +++ b/hypervisor/boot/guest/vboot_wrapper.c @@ -31,8 +31,7 @@ static enum vboot_mode sos_boot_mode; */ void init_vboot(void) { - - struct multiboot_info *mbi; + struct acrn_multiboot_info *mbi = get_multiboot_info(); uint32_t i; const struct vboot_bootloader_map vboot_bootloader_maps[BOOTLOADER_NUM] = { @@ -43,23 +42,18 @@ void init_vboot(void) {"PXELINUX", DIRECT_BOOT_MODE}, }; - mbi = (struct multiboot_info *)hpa2hva((uint64_t)boot_regs[1]); - if (mbi == NULL) { - panic("No multiboot info"); - } else { - for (i = 0U; i < BOOTLOADER_NUM; i++) { - if (strncmp(hpa2hva(mbi->mi_loader_name), vboot_bootloader_maps[i].bootloader_name, - strnlen_s(vboot_bootloader_maps[i].bootloader_name, BOOTLOADER_NAME_SIZE)) == 0) { - /* Only support two vboot mode */ - if (vboot_bootloader_maps[i].mode == DEPRI_BOOT_MODE) { - vboot_ops = get_deprivilege_boot_ops(); - sos_boot_mode = DEPRI_BOOT_MODE; - } else { - vboot_ops = get_direct_boot_ops(); - sos_boot_mode = DIRECT_BOOT_MODE; - } - break; + for (i = 0U; i < BOOTLOADER_NUM; i++) { + if (strncmp(mbi->mi_loader_name, vboot_bootloader_maps[i].bootloader_name, + strnlen_s(vboot_bootloader_maps[i].bootloader_name, BOOTLOADER_NAME_SIZE)) == 0) { + /* Only support two vboot mode */ + if (vboot_bootloader_maps[i].mode == DEPRI_BOOT_MODE) { + vboot_ops = get_deprivilege_boot_ops(); + sos_boot_mode = DEPRI_BOOT_MODE; + } else { + vboot_ops = get_direct_boot_ops(); + sos_boot_mode = DIRECT_BOOT_MODE; } + break; } } diff --git a/hypervisor/boot/include/boot.h b/hypervisor/boot/include/boot.h index 861847dff..17cb115b1 100644 --- a/hypervisor/boot/include/boot.h +++ b/hypervisor/boot/include/boot.h @@ -8,10 +8,37 @@ #define BOOT_H_ #include +#include #define MAX_BOOTARGS_SIZE 2048U +#define MAX_MODULE_COUNT 4U + +struct acrn_multiboot_info { + uint32_t mi_flags; /* the flags is back-compatible with multiboot1 */ + + char *mi_cmdline; + char *mi_loader_name; + + uint32_t mi_mods_count; + struct multiboot_module mi_mods[MAX_MODULE_COUNT]; + + uint32_t mi_drives_length; + uint32_t mi_drives_addr; + + uint32_t mi_mmap_entries; + struct multiboot_mmap mi_mmap_entry[E820_MAX_ENTRIES]; +}; /* boot_regs store the multiboot info magic and address */ extern uint32_t boot_regs[2]; +static inline bool boot_from_multiboot1(void) +{ + return ((boot_regs[0] == MULTIBOOT_INFO_MAGIC) && (boot_regs[1] != 0U)); +} + +struct acrn_multiboot_info *get_multiboot_info(void); +int32_t sanitize_multiboot_info(void); +void parse_hv_cmdline(void); + #endif /* BOOT_H_ */ diff --git a/hypervisor/boot/include/guest/vboot.h b/hypervisor/boot/include/guest/vboot.h index 368ebe33c..8bf89b52b 100644 --- a/hypervisor/boot/include/guest/vboot.h +++ b/hypervisor/boot/include/guest/vboot.h @@ -26,6 +26,5 @@ uint64_t get_ap_trampoline_buf(void); void *get_rsdp_ptr(void); enum vboot_mode get_sos_boot_mode(void); -void parse_hv_cmdline(void); #endif /* end of include guard: VBOOT_H */ diff --git a/hypervisor/boot/multiboot.c b/hypervisor/boot/multiboot.c new file mode 100644 index 000000000..21c016254 --- /dev/null +++ b/hypervisor/boot/multiboot.c @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2020 Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include + +static struct acrn_multiboot_info acrn_mbi = { 0U }; + +int32_t sanitize_multiboot_info(void) +{ + int32_t ret = 0; + + if (boot_from_multiboot1()) { + struct multiboot_info *mbi = (struct multiboot_info *)(hpa2hva_early((uint64_t)boot_regs[1])); + + pr_info("Multiboot1 detected."); + acrn_mbi.mi_flags = mbi->mi_flags; + acrn_mbi.mi_drives_addr = mbi->mi_drives_addr; + acrn_mbi.mi_drives_length = mbi->mi_drives_length; + acrn_mbi.mi_cmdline = (char *)hpa2hva_early((uint64_t)mbi->mi_cmdline); + acrn_mbi.mi_loader_name = (char *)hpa2hva_early((uint64_t)mbi->mi_loader_name); + + acrn_mbi.mi_mmap_entries = mbi->mi_mmap_length / sizeof(struct multiboot_mmap); + if ((acrn_mbi.mi_mmap_entries != 0U) && (mbi->mi_mmap_addr != 0U)) { + if (acrn_mbi.mi_mmap_entries > E820_MAX_ENTRIES) { + pr_err("Too many E820 entries %d\n", acrn_mbi.mi_mmap_entries); + acrn_mbi.mi_mmap_entries = E820_MAX_ENTRIES; + } + (void)memcpy_s((void *)(&acrn_mbi.mi_mmap_entry[0]), + (acrn_mbi.mi_mmap_entries * sizeof(struct multiboot_mmap)), + (const void *)hpa2hva_early((uint64_t)mbi->mi_mmap_addr), + (acrn_mbi.mi_mmap_entries * sizeof(struct multiboot_mmap))); + } else { + acrn_mbi.mi_flags &= ~MULTIBOOT_INFO_HAS_MMAP; + } + + acrn_mbi.mi_mods_count = mbi->mi_mods_count; + if ((mbi->mi_mods_count != 0U) && (mbi->mi_mods_addr != 0U)) { + if (mbi->mi_mods_count > MAX_MODULE_COUNT) { + pr_err("Too many multiboot modules %d\n", mbi->mi_mods_count); + acrn_mbi.mi_mods_count = MAX_MODULE_COUNT; + } + (void)memcpy_s((void *)(&acrn_mbi.mi_mods[0]), + (acrn_mbi.mi_mods_count * sizeof(struct multiboot_module)), + (const void *)hpa2hva_early((uint64_t)mbi->mi_mods_addr), + (acrn_mbi.mi_mods_count * sizeof(struct multiboot_module))); + } else { + acrn_mbi.mi_flags &= ~MULTIBOOT_INFO_HAS_MODS; + } + + } else { + pr_err("no multiboot info found!"); + ret = -ENODEV; + } + + if ((acrn_mbi.mi_flags & MULTIBOOT_INFO_HAS_MMAP) == 0U) { + pr_err("no multiboot memory map info found!"); + ret = -EINVAL; + } + + return ret; +} + +/* + * @post retval != NULL + * @post retval->mi_flags & MULTIBOOT_INFO_HAS_MMAP != 0U + * @post (retval->mi_mmap_entries > 0U) && (retval->mi_mmap_entries <= E820_MAX_ENTRIES) + */ +struct acrn_multiboot_info *get_multiboot_info(void) +{ + return &acrn_mbi; +}