HV: modularization: use abi_module struct in acrn boot info

Use more generic abi_module struct to replace multiboot_module struct in
acrn_boot_info;

Tracked-On: #5661

Signed-off-by: Victor Sun <victor.sun@intel.com>
Reviewed-by: Jason Chen CJ <jason.cj.chen@intel.com>
This commit is contained in:
Victor Sun 2021-06-08 15:17:50 +08:00 committed by wenlingz
parent 16624bab5e
commit c59ea6c250
5 changed files with 70 additions and 53 deletions

View File

@ -23,7 +23,7 @@ int32_t sanitize_acrn_boot_info(struct acrn_boot_info *abi)
{ {
int32_t abi_status = 0; int32_t abi_status = 0;
if (abi->mi_mods_count == 0U) { if (abi->mods_count == 0U) {
pr_err("no boot module info found"); pr_err("no boot module info found");
abi_status = -EINVAL; abi_status = -EINVAL;
} }

View File

@ -24,24 +24,22 @@
/** /**
* @pre vm != NULL && mod != NULL * @pre vm != NULL && mod != NULL
*/ */
static void init_vm_ramdisk_info(struct acrn_vm *vm, const struct multiboot_module *mod) static void init_vm_ramdisk_info(struct acrn_vm *vm, const struct abi_module *mod)
{ {
void *mod_addr = hpa2hva((uint64_t)mod->mm_mod_start); if (mod->start != NULL) {
vm->sw.ramdisk_info.src_addr = mod->start;
if ((mod_addr != NULL) && (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 = 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.load_addr = (void *)round_page_up((uint64_t)vm->sw.ramdisk_info.load_addr);
vm->sw.ramdisk_info.size = mod->mm_mod_end - mod->mm_mod_start; vm->sw.ramdisk_info.size = mod->size;
} }
} }
/** /**
* @pre vm != NULL && mod != NULL * @pre vm != NULL && mod != NULL
*/ */
static void init_vm_acpi_info(struct acrn_vm *vm, const struct multiboot_module *mod) static void init_vm_acpi_info(struct acrn_vm *vm, const struct abi_module *mod)
{ {
vm->sw.acpi_info.src_addr = hpa2hva((uint64_t)mod->mm_mod_start); vm->sw.acpi_info.src_addr = mod->start;
vm->sw.acpi_info.load_addr = (void *)VIRT_ACPI_DATA_ADDR; vm->sw.acpi_info.load_addr = (void *)VIRT_ACPI_DATA_ADDR;
vm->sw.acpi_info.size = ACPI_MODULE_SIZE; vm->sw.acpi_info.size = ACPI_MODULE_SIZE;
} }
@ -88,24 +86,24 @@ static void *get_kernel_load_addr(struct acrn_vm *vm)
/** /**
* @pre vm != NULL && mod != NULL * @pre vm != NULL && mod != NULL
*/ */
static int32_t init_vm_kernel_info(struct acrn_vm *vm, const struct multiboot_module *mod) static int32_t init_vm_kernel_info(struct acrn_vm *vm, const struct abi_module *mod)
{ {
struct acrn_vm_config *vm_config = get_vm_config(vm->vm_id); struct acrn_vm_config *vm_config = get_vm_config(vm->vm_id);
dev_dbg(DBG_LEVEL_BOOT, "kernel mod start=0x%x, end=0x%x", dev_dbg(DBG_LEVEL_BOOT, "kernel mod start=0x%x, size=0x%x",
mod->mm_mod_start, mod->mm_mod_end); (uint64_t)mod->start, mod->size);
vm->sw.kernel_type = vm_config->os_config.kernel_type; 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_src_addr = mod->start;
if ((vm->sw.kernel_info.kernel_src_addr != NULL) && (mod->mm_mod_end > mod->mm_mod_start)){ if (vm->sw.kernel_info.kernel_src_addr != NULL) {
vm->sw.kernel_info.kernel_size = mod->mm_mod_end - mod->mm_mod_start; vm->sw.kernel_info.kernel_size = mod->size;
vm->sw.kernel_info.kernel_load_addr = get_kernel_load_addr(vm); vm->sw.kernel_info.kernel_load_addr = get_kernel_load_addr(vm);
} }
return (vm->sw.kernel_info.kernel_load_addr == NULL) ? (-EINVAL) : 0; return (vm->sw.kernel_info.kernel_load_addr == NULL) ? (-EINVAL) : 0;
} }
/* cmdline parsed from multiboot module string, for pre-launched VMs and SOS VM only. */ /* cmdline parsed from abi module string, for pre-launched VMs and SOS VM only. */
static char mod_cmdline[PRE_VM_NUM + SOS_VM_NUM][MAX_BOOTARGS_SIZE] = { '\0' }; static char mod_cmdline[PRE_VM_NUM + SOS_VM_NUM][MAX_BOOTARGS_SIZE] = { '\0' };
/** /**
@ -116,7 +114,7 @@ static void init_vm_bootargs_info(struct acrn_vm *vm, const struct acrn_boot_inf
struct acrn_vm_config *vm_config = get_vm_config(vm->vm_id); struct acrn_vm_config *vm_config = get_vm_config(vm->vm_id);
vm->sw.bootargs_info.src_addr = vm_config->os_config.bootargs; vm->sw.bootargs_info.src_addr = vm_config->os_config.bootargs;
/* If multiboot string of the kernel module exists, it would OVERRIDE the pre-configured build-in VM bootargs, /* If module string of the kernel module exists, it would OVERRIDE the pre-configured build-in VM bootargs,
* which means we give user a chance to re-configure VM bootargs at bootloader runtime. e.g. GRUB menu * which means we give user a chance to re-configure VM bootargs at bootloader runtime. e.g. GRUB menu
*/ */
if (mod_cmdline[vm->vm_id][0] != '\0') { if (mod_cmdline[vm->vm_id][0] != '\0') {
@ -164,22 +162,22 @@ static void init_vm_bootargs_info(struct acrn_vm *vm, const struct acrn_boot_inf
/* @pre abi != NULL && tag != NULL /* @pre abi != NULL && tag != NULL
*/ */
static struct multiboot_module *get_mod_by_tag(const struct acrn_boot_info *abi, const char *tag) static struct abi_module *get_mod_by_tag(const struct acrn_boot_info *abi, const char *tag)
{ {
uint8_t i; uint8_t i;
struct multiboot_module *mod = NULL; struct abi_module *mod = NULL;
struct multiboot_module *mods = (struct multiboot_module *)(&abi->mi_mods[0]); struct abi_module *mods = (struct abi_module *)(&abi->mods[0]);
uint32_t tag_len = strnlen_s(tag, MAX_MOD_TAG_LEN); uint32_t tag_len = strnlen_s(tag, MAX_MOD_TAG_LEN);
for (i = 0U; i < abi->mi_mods_count; i++) { for (i = 0U; i < abi->mods_count; i++) {
const char *mm_string = (char *)hpa2hva((uint64_t)(mods + i)->mm_string); const char *string = (char *)hpa2hva((uint64_t)(mods + i)->string);
uint32_t mm_str_len = strnlen_s(mm_string, MAX_MOD_TAG_LEN); uint32_t str_len = strnlen_s(string, MAX_MOD_TAG_LEN);
const char *p_chr = mm_string + tag_len; /* point to right after the end of tag */ const char *p_chr = string + tag_len; /* point to right after the end of tag */
/* The tag must be located at the first word in mm_string and end with SPACE/TAB or EOL since /* The tag must be located at the first word in string and end with SPACE/TAB or EOL since
* when do file stitch by tool, the tag in mm_string might be followed by EOL(0x0d/0x0a). * when do file stitch by tool, the tag in string might be followed by EOL(0x0d/0x0a).
*/ */
if ((mm_str_len >= tag_len) && (strncmp(mm_string, tag, tag_len) == 0) if ((str_len >= tag_len) && (strncmp(string, tag, tag_len) == 0)
&& (is_space(*p_chr) || is_eol(*p_chr))) { && (is_space(*p_chr) || is_eol(*p_chr))) {
mod = mods + i; mod = mods + i;
break; break;
@ -188,8 +186,8 @@ static struct multiboot_module *get_mod_by_tag(const struct acrn_boot_info *abi,
/* GRUB might put module at address 0 or under 1MB in the case that the module size is less then 1MB /* GRUB might put module at address 0 or under 1MB in the case that the module size is less then 1MB
* ACRN will not support these cases * ACRN will not support these cases
*/ */
if ((mod != NULL) && ((mod->mm_mod_start == 0U) || (mod->mm_mod_end <= MEM_1M))) { if ((mod != NULL) && (mod->start == NULL)) {
pr_err("Unsupported multiboot module: start at 0x%x, end at 0x%x", mod->mm_mod_start, mod->mm_mod_end); pr_err("Unsupported module: start at HPA 0, size 0x%x .", mod->size);
mod = NULL; mod = NULL;
} }
@ -201,21 +199,21 @@ static struct multiboot_module *get_mod_by_tag(const struct acrn_boot_info *abi,
static int32_t init_vm_sw_load(struct acrn_vm *vm, const struct acrn_boot_info *abi) static int32_t init_vm_sw_load(struct acrn_vm *vm, const struct acrn_boot_info *abi)
{ {
struct acrn_vm_config *vm_config = get_vm_config(vm->vm_id); struct acrn_vm_config *vm_config = get_vm_config(vm->vm_id);
struct multiboot_module *mod; struct abi_module *mod;
int32_t ret = -EINVAL; int32_t ret = -EINVAL;
dev_dbg(DBG_LEVEL_BOOT, "mod counts=%d\n", abi->mi_mods_count); dev_dbg(DBG_LEVEL_BOOT, "mod counts=%d\n", abi->mods_count);
/* find kernel module first */ /* find kernel module first */
mod = get_mod_by_tag(abi, vm_config->os_config.kernel_mod_tag); mod = get_mod_by_tag(abi, vm_config->os_config.kernel_mod_tag);
if (mod != NULL) { if (mod != NULL) {
const char *mm_string = (char *)hpa2hva((uint64_t)mod->mm_string); const char *string = (char *)hpa2hva((uint64_t)mod->string);
uint32_t mm_str_len = strnlen_s(mm_string, MAX_BOOTARGS_SIZE); uint32_t str_len = strnlen_s(string, MAX_BOOTARGS_SIZE);
uint32_t tag_len = strnlen_s(vm_config->os_config.kernel_mod_tag, MAX_MOD_TAG_LEN); uint32_t tag_len = strnlen_s(vm_config->os_config.kernel_mod_tag, MAX_MOD_TAG_LEN);
const char *p_chr = mm_string + tag_len + 1; /* point to the possible start of cmdline */ const char *p_chr = string + tag_len + 1; /* point to the possible start of cmdline */
/* check whether there is a cmdline configured in module string */ /* check whether there is a cmdline configured in module string */
if (((mm_str_len > (tag_len + 1U))) && (is_space(*(p_chr - 1))) && (!is_eol(*p_chr))) { if (((str_len > (tag_len + 1U))) && (is_space(*(p_chr - 1))) && (!is_eol(*p_chr))) {
(void)strncpy_s(&mod_cmdline[vm->vm_id][0], MAX_BOOTARGS_SIZE, (void)strncpy_s(&mod_cmdline[vm->vm_id][0], MAX_BOOTARGS_SIZE,
p_chr, (MAX_BOOTARGS_SIZE - 1U)); p_chr, (MAX_BOOTARGS_SIZE - 1U));
} }
@ -236,7 +234,7 @@ static int32_t init_vm_sw_load(struct acrn_vm *vm, const struct acrn_boot_info *
if (is_prelaunched_vm(vm)) { if (is_prelaunched_vm(vm)) {
mod = get_mod_by_tag(abi, vm_config->acpi_config.acpi_mod_tag); mod = get_mod_by_tag(abi, vm_config->acpi_config.acpi_mod_tag);
if ((mod != NULL) && ((mod->mm_mod_end - mod->mm_mod_start) == ACPI_MODULE_SIZE)) { if ((mod != NULL) && (mod->size == ACPI_MODULE_SIZE)) {
init_vm_acpi_info(vm, mod); init_vm_acpi_info(vm, mod);
} else { } else {
pr_err("failed to load VM %d acpi module", vm->vm_id); pr_err("failed to load VM %d acpi module", vm->vm_id);

View File

@ -17,6 +17,7 @@
#define MAX_BOOTARGS_SIZE 2048U #define MAX_BOOTARGS_SIZE 2048U
#define MAX_LOADER_NAME_SIZE 32U #define MAX_LOADER_NAME_SIZE 32U
#define MAX_PROTOCOL_NAME_SIZE 16U #define MAX_PROTOCOL_NAME_SIZE 16U
#define MAX_MOD_STRING_SIZE 2048U
/* The modules in multiboot are: Pre-launched VM: kernel/ramdisk/acpi; SOS VM: kernel/ramdisk */ /* The modules in multiboot are: Pre-launched VM: kernel/ramdisk/acpi; SOS VM: kernel/ramdisk */
#define MAX_MODULE_NUM (3U * PRE_VM_NUM + 2U * SOS_VM_NUM) #define MAX_MODULE_NUM (3U * PRE_VM_NUM + 2U * SOS_VM_NUM)
@ -24,14 +25,20 @@
/* The vACPI module size is fixed to 1MB */ /* The vACPI module size is fixed to 1MB */
#define ACPI_MODULE_SIZE MEM_1M #define ACPI_MODULE_SIZE MEM_1M
struct abi_module {
void *start; /* HVA */
uint32_t size;
const char string[MAX_MOD_STRING_SIZE];
};
struct acrn_boot_info { struct acrn_boot_info {
char protocol_name[MAX_PROTOCOL_NAME_SIZE]; char protocol_name[MAX_PROTOCOL_NAME_SIZE];
const char cmdline[MAX_BOOTARGS_SIZE]; const char cmdline[MAX_BOOTARGS_SIZE];
const char loader_name[MAX_LOADER_NAME_SIZE]; const char loader_name[MAX_LOADER_NAME_SIZE];
uint32_t mi_mods_count; uint32_t mods_count;
struct multiboot_module mi_mods[MAX_MODULE_NUM]; struct abi_module mods[MAX_MODULE_NUM];
uint32_t mi_mmap_entries; uint32_t mi_mmap_entries;
struct multiboot_mmap mi_mmap_entry[MAX_MMAP_ENTRIES]; struct multiboot_mmap mi_mmap_entry[MAX_MMAP_ENTRIES];

View File

@ -14,6 +14,7 @@
* @pre abi != NULL * @pre abi != NULL
*/ */
int32_t multiboot_to_acrn_bi(struct acrn_boot_info *abi, void *mb_info) { int32_t multiboot_to_acrn_bi(struct acrn_boot_info *abi, void *mb_info) {
uint32_t i;
struct multiboot_info *mbi = (struct multiboot_info *)(hpa2hva_early((uint64_t)mb_info)); struct multiboot_info *mbi = (struct multiboot_info *)(hpa2hva_early((uint64_t)mb_info));
struct multiboot_mmap *mmap = (struct multiboot_mmap *)hpa2hva_early((uint64_t)mbi->mi_mmap_addr); struct multiboot_mmap *mmap = (struct multiboot_mmap *)hpa2hva_early((uint64_t)mbi->mi_mmap_addr);
struct multiboot_module *mods = (struct multiboot_module *)hpa2hva_early((uint64_t)mbi->mi_mods_addr); struct multiboot_module *mods = (struct multiboot_module *)hpa2hva_early((uint64_t)mbi->mi_mods_addr);
@ -26,7 +27,6 @@ int32_t multiboot_to_acrn_bi(struct acrn_boot_info *abi, void *mb_info) {
strnlen_s((char *)hpa2hva_early((uint64_t)mbi->mi_loader_name), (MAX_LOADER_NAME_SIZE - 1U))); strnlen_s((char *)hpa2hva_early((uint64_t)mbi->mi_loader_name), (MAX_LOADER_NAME_SIZE - 1U)));
abi->mi_mmap_entries = mbi->mi_mmap_length / sizeof(struct multiboot_mmap); abi->mi_mmap_entries = mbi->mi_mmap_length / sizeof(struct multiboot_mmap);
abi->mi_mods_count = mbi->mi_mods_count;
if (((mbi->mi_flags & MULTIBOOT_INFO_HAS_MMAP) != 0U) && (abi->mi_mmap_entries != 0U) && (mmap != NULL)) { if (((mbi->mi_flags & MULTIBOOT_INFO_HAS_MMAP) != 0U) && (abi->mi_mmap_entries != 0U) && (mmap != NULL)) {
@ -42,16 +42,23 @@ int32_t multiboot_to_acrn_bi(struct acrn_boot_info *abi, void *mb_info) {
abi->mi_mmap_entries = 0U; abi->mi_mmap_entries = 0U;
} }
if (((mbi->mi_flags & MULTIBOOT_INFO_HAS_MODS) != 0U) && (abi->mi_mods_count != 0U) && (mods != NULL)) { abi->mods_count = mbi->mi_mods_count;
if (abi->mi_mods_count > MAX_MODULE_NUM) { if (((mbi->mi_flags & MULTIBOOT_INFO_HAS_MODS) != 0U) && (mbi->mi_mods_count != 0U) && (mods != NULL)) {
abi->mi_mods_count = MAX_MODULE_NUM; if (abi->mods_count > MAX_MODULE_NUM) {
abi->mods_count = MAX_MODULE_NUM;
} }
(void)memcpy_s((void *)(&abi->mi_mods[0]), for (i = 0U; i < abi->mods_count; i++) {
(abi->mi_mods_count * sizeof(struct multiboot_module)), abi->mods[i].start = hpa2hva_early((uint64_t)(mods + i)->mm_mod_start);
mods, (abi->mi_mods_count * sizeof(struct multiboot_module))); if ((mods + i)->mm_mod_end > (mods + i)->mm_mod_start) {
abi->mods[i].size = (mods + i)->mm_mod_end - (mods + i)->mm_mod_start;
}
(void)strncpy_s((void *)(abi->mods[i].string), MAX_MOD_STRING_SIZE,
(char *)hpa2hva_early((uint64_t)(mods + i)->mm_string),
strnlen_s((char *)hpa2hva_early((uint64_t)(mods + i)->mm_string), MAX_BOOTARGS_SIZE));
}
} else { } else {
abi->mi_mods_count = 0U; abi->mods_count = 0U;
} }
return 0; return 0;

View File

@ -37,11 +37,14 @@ static void mb2_mmap_to_abi(struct acrn_boot_info *abi, const struct multiboot2_
static void mb2_mods_to_abi(struct acrn_boot_info *abi, static void mb2_mods_to_abi(struct acrn_boot_info *abi,
uint32_t mbi_mod_idx, const struct multiboot2_tag_module *mb2_tag_mods) uint32_t mbi_mod_idx, const struct multiboot2_tag_module *mb2_tag_mods)
{ {
if (mbi_mod_idx < MAX_MODULE_NUM) { abi->mods[mbi_mod_idx].start = hpa2hva_early((uint64_t)mb2_tag_mods->mod_start);
abi->mi_mods[mbi_mod_idx].mm_mod_start = mb2_tag_mods->mod_start; if (mb2_tag_mods->mod_end > mb2_tag_mods->mod_start) {
abi->mi_mods[mbi_mod_idx].mm_mod_end = mb2_tag_mods->mod_end; abi->mods[mbi_mod_idx].size = mb2_tag_mods->mod_end - mb2_tag_mods->mod_start;
abi->mi_mods[mbi_mod_idx].mm_string = (uint32_t)(uint64_t)mb2_tag_mods->cmdline;
} }
(void)strncpy_s((void *)(abi->mods[mbi_mod_idx].string), MAX_MOD_STRING_SIZE,
(char *)hpa2hva_early((uint64_t)mb2_tag_mods->cmdline),
strnlen_s((char *)hpa2hva_early((uint64_t)mb2_tag_mods->cmdline), MAX_MOD_STRING_SIZE));
} }
/** /**
@ -94,8 +97,10 @@ int32_t multiboot2_to_acrn_bi(struct acrn_boot_info *abi, void *mb2_info)
mb2_mmap_to_abi(abi, (const struct multiboot2_tag_mmap *)mb2_tag); mb2_mmap_to_abi(abi, (const struct multiboot2_tag_mmap *)mb2_tag);
break; break;
case MULTIBOOT2_TAG_TYPE_MODULE: case MULTIBOOT2_TAG_TYPE_MODULE:
mb2_mods_to_abi(abi, mod_idx, (const struct multiboot2_tag_module *)mb2_tag); if (mod_idx < MAX_MODULE_NUM) {
mod_idx++; mb2_mods_to_abi(abi, mod_idx, (const struct multiboot2_tag_module *)mb2_tag);
mod_idx++;
}
break; break;
case MULTIBOOT2_TAG_TYPE_BOOT_LOADER_NAME: case MULTIBOOT2_TAG_TYPE_BOOT_LOADER_NAME:
str = ((struct multiboot2_tag_string *)mb2_tag)->string; str = ((struct multiboot2_tag_string *)mb2_tag)->string;
@ -132,7 +137,7 @@ int32_t multiboot2_to_acrn_bi(struct acrn_boot_info *abi, void *mb2_info)
+ ((mb2_tag->size + (MULTIBOOT2_INFO_ALIGN - 1U)) & ~(MULTIBOOT2_INFO_ALIGN - 1U))); + ((mb2_tag->size + (MULTIBOOT2_INFO_ALIGN - 1U)) & ~(MULTIBOOT2_INFO_ALIGN - 1U)));
} }
abi->mi_mods_count = mod_idx; abi->mods_count = mod_idx;
return ret; return ret;
} }