diff --git a/hypervisor/arch/x86/guest/vm.c b/hypervisor/arch/x86/guest/vm.c index 8e7a1bfb1..034d71d79 100644 --- a/hypervisor/arch/x86/guest/vm.c +++ b/hypervisor/arch/x86/guest/vm.c @@ -453,7 +453,7 @@ int32_t create_vm(uint16_t vm_id, struct acrn_vm_config *vm_config, struct acrn_ if (vm_config->load_order == PRE_LAUNCHED_VM) { create_prelaunched_vm_e820(vm); prepare_prelaunched_vm_memmap(vm, vm_config); - (void)init_vm_boot_info(vm); + status = init_vm_boot_info(vm); } } diff --git a/hypervisor/boot/guest/vboot_info.c b/hypervisor/boot/guest/vboot_info.c index 7017b15d1..bf6a7437e 100644 --- a/hypervisor/boot/guest/vboot_info.c +++ b/hypervisor/boot/guest/vboot_info.c @@ -23,6 +23,21 @@ #define ACRN_DBG_BOOT 6U #define MAX_BOOT_PARAMS_LEN 64U +#define INVALID_MOD_IDX 0xFFFFU + +/** + * @pre vm != NULL && mbi != NULL + */ +static void init_vm_ramdisk_info(struct acrn_vm *vm, struct multiboot_module *mod) +{ + void *mod_addr = hpa2hva((uint64_t)mod->mm_mod_start); + uint32_t mod_size = mod->mm_mod_end - mod->mm_mod_start; + + vm->sw.ramdisk_info.src_addr = mod_addr; + vm->sw.ramdisk_info.load_addr = vm->sw.kernel_info.kernel_load_addr + vm->sw.kernel_info.kernel_size; + vm->sw.ramdisk_info.load_addr = (void *)round_page_up((uint64_t)vm->sw.ramdisk_info.load_addr); + vm->sw.ramdisk_info.size = mod_size; +} /* There are two sources for sos_vm kernel cmdline: * - cmdline from direct boot mbi->cmdline @@ -31,68 +46,6 @@ */ static char kernel_cmdline[MAX_BOOTARGS_SIZE + 1U]; -/* now modules support: FIRMWARE & RAMDISK & SeedList */ -static void parse_other_modules(struct acrn_vm *vm, const struct multiboot_module *mods, uint32_t mods_count) -{ - uint32_t i; - - for (i = 0U; i < mods_count; i++) { - uint32_t type_len; - const char *start = (char *)hpa2hva((uint64_t)mods[i].mm_string); - const char *end; - void *mod_addr = hpa2hva((uint64_t)mods[i].mm_mod_start); - uint32_t mod_size = mods[i].mm_mod_end - mods[i].mm_mod_start; - - dev_dbg(ACRN_DBG_BOOT, "other mod-%d start=0x%x, end=0x%x", - i, mods[i].mm_mod_start, mods[i].mm_mod_end); - dev_dbg(ACRN_DBG_BOOT, "cmd addr=0x%x, str=%s", - mods[i].mm_string, start); - - while (*start == ' ') { - start++; - } - - end = start; - while (((*end) != ' ') && ((*end) != '\0')) { - end++; - } - - type_len = end - start; - if (strncmp("FIRMWARE", start, type_len) == 0) { - char dyn_bootargs[100] = {'\0'}; - void *load_addr = gpa2hva(vm, (uint64_t)vm->sw.bootargs_info.load_addr); - uint32_t args_size = vm->sw.bootargs_info.size; - static int32_t copy_once = 1; - - start = end + 1; /*it is fw name for boot args */ - snprintf(dyn_bootargs, 100U, " %s=0x%x@0x%x ", start, mod_size, mod_addr); - dev_dbg(ACRN_DBG_BOOT, "fw-%d: %s", i, dyn_bootargs); - - /*copy boot args to load addr, set src=load addr*/ - if (copy_once != 0) { - copy_once = 0; - (void)strncpy_s(load_addr, MAX_BOOTARGS_SIZE + 1U, - (const char *)vm->sw.bootargs_info.src_addr, - vm->sw.bootargs_info.size); - vm->sw.bootargs_info.src_addr = load_addr; - } - - (void)strncpy_s(load_addr + args_size, 100U, dyn_bootargs, 100U); - vm->sw.bootargs_info.size = strnlen_s(load_addr, MAX_BOOTARGS_SIZE); - - } else if (strncmp("RAMDISK", start, type_len) == 0) { - vm->sw.ramdisk_info.src_addr = mod_addr; - vm->sw.ramdisk_info.load_addr = vm->sw.kernel_info.kernel_load_addr + - vm->sw.kernel_info.kernel_size; - vm->sw.ramdisk_info.load_addr = - (void *)round_page_up((uint64_t)vm->sw.ramdisk_info.load_addr); - vm->sw.ramdisk_info.size = mod_size; - } else { - pr_warn("not support mod, cmd: %s", start); - } - } -} - /** * @pre vm != NULL && cmdline != NULL && cmdstr != NULL */ @@ -167,11 +120,117 @@ static void *get_kernel_load_addr(struct acrn_vm *vm) return load_addr; } +/** + * @pre vm != NULL && mbi != NULL + */ +static int32_t init_vm_kernel_info(struct acrn_vm *vm, struct multiboot_module *mod) +{ + struct acrn_vm_config *vm_config = get_vm_config(vm->vm_id); + + dev_dbg(ACRN_DBG_BOOT, "kernel mod start=0x%x, end=0x%x", + mod->mm_mod_start, mod->mm_mod_end); + + vm->sw.kernel_type = vm_config->os_config.kernel_type; + vm->sw.kernel_info.kernel_src_addr = hpa2hva((uint64_t)mod->mm_mod_start); + vm->sw.kernel_info.kernel_size = mod->mm_mod_end - mod->mm_mod_start; + vm->sw.kernel_info.kernel_load_addr = get_kernel_load_addr(vm); + + return (vm->sw.kernel_info.kernel_load_addr == NULL) ? (-EINVAL) : 0; +} + +/** + * @pre vm != NULL && mbi != NULL + */ +static void init_vm_bootargs_info(struct acrn_vm *vm, struct multiboot_info *mbi) +{ + struct acrn_vm_config *vm_config = get_vm_config(vm->vm_id); + char *bootargs = vm_config->os_config.bootargs; + + if (vm_config->load_order == PRE_LAUNCHED_VM) { + vm->sw.bootargs_info.src_addr = bootargs; + vm->sw.bootargs_info.size = strnlen_s(bootargs, MAX_BOOTARGS_SIZE); + } else { + /* vm_config->load_order == SOS_VM */ + if ((mbi->mi_flags & MULTIBOOT_INFO_HAS_CMDLINE) != 0U) { + /* + * 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); + + vm->sw.bootargs_info.src_addr = kernel_cmdline; + vm->sw.bootargs_info.size = strnlen_s(kernel_cmdline, MAX_BOOTARGS_SIZE); + } else { + vm->sw.bootargs_info.src_addr = bootargs; + vm->sw.bootargs_info.size = strnlen_s(bootargs, MAX_BOOTARGS_SIZE); + } + } + + /* Kernel bootarg and zero page are right before the kernel image */ + if (vm->sw.bootargs_info.size > 0) { + vm->sw.bootargs_info.load_addr = vm->sw.kernel_info.kernel_load_addr - (MEM_1K * 8U); + } else { + vm->sw.bootargs_info.load_addr = NULL; + } +} + +static uint32_t get_mod_idx_by_tag(struct multiboot_module *mods, uint32_t mods_count, const char *tag) +{ + uint32_t i, ret = INVALID_MOD_IDX; + uint32_t tag_len = strnlen_s(tag, MAX_MOD_TAG_LEN); + + for (i = 0; i < mods_count; i++) { + const char *mm_string = (char *)hpa2hva((uint64_t)mods[i].mm_string); + uint32_t mm_str_len = strnlen_s(mm_string, MAX_MOD_TAG_LEN); + + /* when do file stitch by tool, the tag in mm_string might be followed with 0x0d or 0x0a */ + if ((mm_str_len >= tag_len) && (strncmp(mm_string, tag, tag_len) == 0) + && ((mm_string[tag_len] == 0x0d) + || (mm_string[tag_len] == 0x0a) + || (mm_string[tag_len] == 0))){ + ret = i; + break; + } + } + return ret; +} + +/* @pre vm != NULL && mbi != NULL + */ +static int32_t init_vm_sw_load(struct acrn_vm *vm, struct 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); + uint32_t mod_idx; + int32_t ret = -EINVAL; + + dev_dbg(ACRN_DBG_BOOT, "mod counts=%d\n", mbi->mi_mods_count); + + mod_idx = get_mod_idx_by_tag(mods, mbi->mi_mods_count, vm_config->os_config.kernel_mod_tag); + if (mod_idx != INVALID_MOD_IDX) { + ret = init_vm_kernel_info(vm, &mods[mod_idx]); + } + + if (ret == 0) { + init_vm_bootargs_info(vm, mbi); + /* check whether there is a ramdisk module */ + mod_idx = get_mod_idx_by_tag(mods, mbi->mi_mods_count, vm_config->os_config.ramdisk_mod_tag); + if (mod_idx != INVALID_MOD_IDX) { + init_vm_ramdisk_info(vm, &mods[mod_idx]); + /* TODO: prepare other modules like firmware, seedlist */ + } + } else { + pr_err("failed to load VM %d kernel module", vm->vm_id); + } + return ret; +} + +/** + * @pre vm != NULL + */ static int32_t init_general_vm_boot_info(struct acrn_vm *vm) { - struct multiboot_module *mods = NULL; struct multiboot_info *mbi = NULL; - struct acrn_vm_config *vm_config = get_vm_config(vm->vm_id); int32_t ret = -EINVAL; if (boot_regs[0] != MULTIBOOT_INFO_MAGIC) { @@ -183,59 +242,11 @@ static int32_t init_general_vm_boot_info(struct acrn_vm *vm) stac(); dev_dbg(ACRN_DBG_BOOT, "Multiboot detected, flag=0x%x", mbi->mi_flags); if ((mbi->mi_flags & MULTIBOOT_INFO_HAS_MODS) == 0U) { - panic("no sos kernel info found"); - clac(); + panic("no multiboot module info found"); } else { - - dev_dbg(ACRN_DBG_BOOT, "mod counts=%d\n", mbi->mi_mods_count); - - /* mod[0] is for kernel, other mod for ramdisk/firmware info*/ - mods = (struct multiboot_module *)hpa2hva((uint64_t)mbi->mi_mods_addr); - - dev_dbg(ACRN_DBG_BOOT, "mod0 start=0x%x, end=0x%x", - mods[0].mm_mod_start, mods[0].mm_mod_end); - - vm->sw.kernel_type = vm_config->os_config.kernel_type; - vm->sw.kernel_info.kernel_src_addr = hpa2hva((uint64_t)mods[0].mm_mod_start); - vm->sw.kernel_info.kernel_size = mods[0].mm_mod_end - mods[0].mm_mod_start; - vm->sw.kernel_info.kernel_load_addr = get_kernel_load_addr(vm); - - if (vm_config->load_order == PRE_LAUNCHED_VM) { - vm->sw.bootargs_info.src_addr = (void *)vm_config->os_config.bootargs; - vm->sw.bootargs_info.size = - strnlen_s(vm_config->os_config.bootargs, MAX_BOOTARGS_SIZE); - } else { - if ((mbi->mi_flags & MULTIBOOT_INFO_HAS_CMDLINE) != 0U) { - /* - * 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), - vm_config->os_config.bootargs); - - vm->sw.bootargs_info.src_addr = kernel_cmdline; - vm->sw.bootargs_info.size = - strnlen_s(kernel_cmdline, MAX_BOOTARGS_SIZE); - } else { - vm->sw.bootargs_info.src_addr = vm_config->os_config.bootargs; - vm->sw.bootargs_info.size = - strnlen_s(vm_config->os_config.bootargs, MAX_BOOTARGS_SIZE); - } - } - - /* Kernel bootarg and zero page are right before the kernel image */ - vm->sw.bootargs_info.load_addr = - vm->sw.kernel_info.kernel_load_addr - (MEM_1K * 8U); - - if (mbi->mi_mods_count > 1U) { - /*parse other modules, like firmware /ramdisk */ - parse_other_modules(vm, mods + 1, mbi->mi_mods_count - 1); - } - clac(); - if (vm->sw.kernel_info.kernel_load_addr != NULL) { - ret = 0; - } + ret = init_vm_sw_load(vm, mbi); } + clac(); } } return ret; diff --git a/hypervisor/common/vm_load.c b/hypervisor/common/vm_load.c index 028212c95..15d4d641e 100644 --- a/hypervisor/common/vm_load.c +++ b/hypervisor/common/vm_load.c @@ -127,16 +127,11 @@ static void prepare_loading_bzimage(struct acrn_vm *vm, struct acrn_vcpu *vcpu) vcpu_set_gpreg(vcpu, i, 0UL); } - /* Copy Guest OS bootargs to its load location */ - (void)copy_to_gpa(vm, bootargs_info->src_addr, - (uint64_t)bootargs_info->load_addr, - (strnlen_s((char *)bootargs_info->src_addr, MAX_BOOTARGS_SIZE) + 1U)); - /* add "hugepagesz=1G hugepages=x" to cmdline for 1G hugepage * reserving. Current strategy is "total_mem_size in Giga - * remained 1G pages" for reserving. */ - if (is_sos_vm(vm)) { + if (is_sos_vm(vm) && (bootargs_info->load_addr != NULL)) { int64_t reserving_1g_pages; reserving_1g_pages = (vm_config->memory.size >> 30U) - NUM_REMAIN_1G_PAGES; @@ -159,6 +154,7 @@ int32_t direct_boot_sw_loader(struct acrn_vm *vm) { int32_t ret = 0; struct sw_kernel_info *sw_kernel = &(vm->sw.kernel_info); + struct sw_module_info *bootargs_info = &(vm->sw.bootargs_info); struct sw_module_info *ramdisk_info = &(vm->sw.ramdisk_info); /* get primary vcpu */ struct acrn_vcpu *vcpu = vcpu_from_vid(vm, BOOT_CPU_ID); @@ -173,13 +169,18 @@ int32_t direct_boot_sw_loader(struct acrn_vm *vm) (uint64_t)sw_kernel->kernel_load_addr, sw_kernel->kernel_size); /* Check if a RAM disk is present */ - if (ramdisk_info->src_addr != NULL) { + if (ramdisk_info->size != 0U) { /* Copy RAM disk to its load location */ (void)copy_to_gpa(vm, ramdisk_info->src_addr, (uint64_t)ramdisk_info->load_addr, ramdisk_info->size); } - + /* Copy Guest OS bootargs to its load location */ + if (bootargs_info->size != 0U) { + (void)copy_to_gpa(vm, bootargs_info->src_addr, + (uint64_t)bootargs_info->load_addr, + (strnlen_s((char *)bootargs_info->src_addr, MAX_BOOTARGS_SIZE) + 1U)); + } switch (vm->sw.kernel_type) { case KERNEL_BZIMAGE: prepare_loading_bzimage(vm, vcpu); diff --git a/hypervisor/include/arch/x86/vm_config.h b/hypervisor/include/arch/x86/vm_config.h index 9ee140b62..f450ea78a 100644 --- a/hypervisor/include/arch/x86/vm_config.h +++ b/hypervisor/include/arch/x86/vm_config.h @@ -18,6 +18,7 @@ #define PLUG_CPU(n) (1U << (n)) #define MAX_VUART_NUM_PER_VM 2U #define MAX_VM_OS_NAME_LEN 32U +#define MAX_MOD_TAG_LEN 32U /* * PRE_LAUNCHED_VM is launched by ACRN hypervisor, with LAPIC_PT; @@ -68,6 +69,8 @@ enum os_kernel_type { struct acrn_vm_os_config { char name[MAX_VM_OS_NAME_LEN]; /* OS name, useful for debug */ enum os_kernel_type kernel_type; /* used for kernel specifc loading method */ + char kernel_mod_tag[MAX_MOD_TAG_LEN]; /* multiboot module tag for kernel */ + char ramdisk_mod_tag[MAX_MOD_TAG_LEN]; /* multiboot module tag for ramdisk */ char bootargs[MAX_BOOTARGS_SIZE]; /* boot args/cmdline */ } __aligned(8); diff --git a/hypervisor/scenarios/industry/vm_configurations.c b/hypervisor/scenarios/industry/vm_configurations.c index 87b189a76..3747ca0fa 100644 --- a/hypervisor/scenarios/industry/vm_configurations.c +++ b/hypervisor/scenarios/industry/vm_configurations.c @@ -23,6 +23,7 @@ struct acrn_vm_config vm_configs[CONFIG_MAX_VM_NUM] = { .os_config = { .name = "ACRN Service OS", .kernel_type = KERNEL_BZIMAGE, + .kernel_mod_tag = "Linux_bzImage", .bootargs = SOS_VM_BOOTARGS }, .vuart[0] = { diff --git a/hypervisor/scenarios/logical_partition/vm_configurations.c b/hypervisor/scenarios/logical_partition/vm_configurations.c index 6d2b0eca1..0d4edfea5 100644 --- a/hypervisor/scenarios/logical_partition/vm_configurations.c +++ b/hypervisor/scenarios/logical_partition/vm_configurations.c @@ -27,6 +27,7 @@ struct acrn_vm_config vm_configs[CONFIG_MAX_VM_NUM] = { .os_config = { .name = "ClearLinux", .kernel_type = KERNEL_BZIMAGE, + .kernel_mod_tag = "Linux_bzImage", .bootargs = VM0_CONFIG_OS_BOOTARG_CONSOLE \ VM0_CONFIG_OS_BOOTARG_MAXCPUS \ VM0_CONFIG_OS_BOOTARG_ROOT \ @@ -66,6 +67,7 @@ struct acrn_vm_config vm_configs[CONFIG_MAX_VM_NUM] = { .os_config = { .name = "ClearLinux", .kernel_type = KERNEL_BZIMAGE, + .kernel_mod_tag = "Linux_bzImage", .bootargs = VM1_CONFIG_OS_BOOTARG_CONSOLE \ VM1_CONFIG_OS_BOOTARG_MAXCPUS \ VM1_CONFIG_OS_BOOTARG_ROOT \ diff --git a/hypervisor/scenarios/sdc/vm_configurations.c b/hypervisor/scenarios/sdc/vm_configurations.c index f3ec7109c..12db9a511 100644 --- a/hypervisor/scenarios/sdc/vm_configurations.c +++ b/hypervisor/scenarios/sdc/vm_configurations.c @@ -25,6 +25,7 @@ struct acrn_vm_config vm_configs[CONFIG_MAX_VM_NUM] = { .os_config = { .name = "ACRN Service OS", .kernel_type = KERNEL_BZIMAGE, + .kernel_mod_tag = "Linux_bzImage", .bootargs = SOS_VM_BOOTARGS, }, .vuart[0] = {