Skip to content

Commit ea7ca85

Browse files
jsun26intelwenlingz
authored andcommitted
HV: use tag to specify multiboot module
Previously multiboot mods[0] is designed for kernel module for all pre-launched VMs including SOS VM, and mods[0].mm_string is used to store kernel cmdline. This design could not satisfy the requirement of hybrid mode scenarios that each VM might use their own kernel image also ramdisk image. To resolve this problem, we will use a tag in mods mm_string field to specify the module type. If the tag could be matched with os_config of VM configurations, the corresponding module would be loaded; Tracked-On: #3214 Signed-off-by: Victor Sun <victor.sun@intel.com> Reviewed-by: Jason Chen CJ <jason.cj.chen@intel.com>
1 parent d0fa83b commit ea7ca85

File tree

7 files changed

+143
-124
lines changed

7 files changed

+143
-124
lines changed

hypervisor/arch/x86/guest/vm.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -453,7 +453,7 @@ int32_t create_vm(uint16_t vm_id, struct acrn_vm_config *vm_config, struct acrn_
453453
if (vm_config->load_order == PRE_LAUNCHED_VM) {
454454
create_prelaunched_vm_e820(vm);
455455
prepare_prelaunched_vm_memmap(vm, vm_config);
456-
(void)init_vm_boot_info(vm);
456+
status = init_vm_boot_info(vm);
457457
}
458458
}
459459

hypervisor/boot/guest/vboot_info.c

Lines changed: 126 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,21 @@
2323
#define ACRN_DBG_BOOT 6U
2424

2525
#define MAX_BOOT_PARAMS_LEN 64U
26+
#define INVALID_MOD_IDX 0xFFFFU
27+
28+
/**
29+
* @pre vm != NULL && mbi != NULL
30+
*/
31+
static void init_vm_ramdisk_info(struct acrn_vm *vm, struct multiboot_module *mod)
32+
{
33+
void *mod_addr = hpa2hva((uint64_t)mod->mm_mod_start);
34+
uint32_t mod_size = mod->mm_mod_end - mod->mm_mod_start;
35+
36+
vm->sw.ramdisk_info.src_addr = mod_addr;
37+
vm->sw.ramdisk_info.load_addr = vm->sw.kernel_info.kernel_load_addr + vm->sw.kernel_info.kernel_size;
38+
vm->sw.ramdisk_info.load_addr = (void *)round_page_up((uint64_t)vm->sw.ramdisk_info.load_addr);
39+
vm->sw.ramdisk_info.size = mod_size;
40+
}
2641

2742
/* There are two sources for sos_vm kernel cmdline:
2843
* - cmdline from direct boot mbi->cmdline
@@ -31,68 +46,6 @@
3146
*/
3247
static char kernel_cmdline[MAX_BOOTARGS_SIZE + 1U];
3348

34-
/* now modules support: FIRMWARE & RAMDISK & SeedList */
35-
static void parse_other_modules(struct acrn_vm *vm, const struct multiboot_module *mods, uint32_t mods_count)
36-
{
37-
uint32_t i;
38-
39-
for (i = 0U; i < mods_count; i++) {
40-
uint32_t type_len;
41-
const char *start = (char *)hpa2hva((uint64_t)mods[i].mm_string);
42-
const char *end;
43-
void *mod_addr = hpa2hva((uint64_t)mods[i].mm_mod_start);
44-
uint32_t mod_size = mods[i].mm_mod_end - mods[i].mm_mod_start;
45-
46-
dev_dbg(ACRN_DBG_BOOT, "other mod-%d start=0x%x, end=0x%x",
47-
i, mods[i].mm_mod_start, mods[i].mm_mod_end);
48-
dev_dbg(ACRN_DBG_BOOT, "cmd addr=0x%x, str=%s",
49-
mods[i].mm_string, start);
50-
51-
while (*start == ' ') {
52-
start++;
53-
}
54-
55-
end = start;
56-
while (((*end) != ' ') && ((*end) != '\0')) {
57-
end++;
58-
}
59-
60-
type_len = end - start;
61-
if (strncmp("FIRMWARE", start, type_len) == 0) {
62-
char dyn_bootargs[100] = {'\0'};
63-
void *load_addr = gpa2hva(vm, (uint64_t)vm->sw.bootargs_info.load_addr);
64-
uint32_t args_size = vm->sw.bootargs_info.size;
65-
static int32_t copy_once = 1;
66-
67-
start = end + 1; /*it is fw name for boot args */
68-
snprintf(dyn_bootargs, 100U, " %s=0x%x@0x%x ", start, mod_size, mod_addr);
69-
dev_dbg(ACRN_DBG_BOOT, "fw-%d: %s", i, dyn_bootargs);
70-
71-
/*copy boot args to load addr, set src=load addr*/
72-
if (copy_once != 0) {
73-
copy_once = 0;
74-
(void)strncpy_s(load_addr, MAX_BOOTARGS_SIZE + 1U,
75-
(const char *)vm->sw.bootargs_info.src_addr,
76-
vm->sw.bootargs_info.size);
77-
vm->sw.bootargs_info.src_addr = load_addr;
78-
}
79-
80-
(void)strncpy_s(load_addr + args_size, 100U, dyn_bootargs, 100U);
81-
vm->sw.bootargs_info.size = strnlen_s(load_addr, MAX_BOOTARGS_SIZE);
82-
83-
} else if (strncmp("RAMDISK", start, type_len) == 0) {
84-
vm->sw.ramdisk_info.src_addr = mod_addr;
85-
vm->sw.ramdisk_info.load_addr = vm->sw.kernel_info.kernel_load_addr +
86-
vm->sw.kernel_info.kernel_size;
87-
vm->sw.ramdisk_info.load_addr =
88-
(void *)round_page_up((uint64_t)vm->sw.ramdisk_info.load_addr);
89-
vm->sw.ramdisk_info.size = mod_size;
90-
} else {
91-
pr_warn("not support mod, cmd: %s", start);
92-
}
93-
}
94-
}
95-
9649
/**
9750
* @pre vm != NULL && cmdline != NULL && cmdstr != NULL
9851
*/
@@ -167,11 +120,117 @@ static void *get_kernel_load_addr(struct acrn_vm *vm)
167120
return load_addr;
168121
}
169122

123+
/**
124+
* @pre vm != NULL && mbi != NULL
125+
*/
126+
static int32_t init_vm_kernel_info(struct acrn_vm *vm, struct multiboot_module *mod)
127+
{
128+
struct acrn_vm_config *vm_config = get_vm_config(vm->vm_id);
129+
130+
dev_dbg(ACRN_DBG_BOOT, "kernel mod start=0x%x, end=0x%x",
131+
mod->mm_mod_start, mod->mm_mod_end);
132+
133+
vm->sw.kernel_type = vm_config->os_config.kernel_type;
134+
vm->sw.kernel_info.kernel_src_addr = hpa2hva((uint64_t)mod->mm_mod_start);
135+
vm->sw.kernel_info.kernel_size = mod->mm_mod_end - mod->mm_mod_start;
136+
vm->sw.kernel_info.kernel_load_addr = get_kernel_load_addr(vm);
137+
138+
return (vm->sw.kernel_info.kernel_load_addr == NULL) ? (-EINVAL) : 0;
139+
}
140+
141+
/**
142+
* @pre vm != NULL && mbi != NULL
143+
*/
144+
static void init_vm_bootargs_info(struct acrn_vm *vm, struct multiboot_info *mbi)
145+
{
146+
struct acrn_vm_config *vm_config = get_vm_config(vm->vm_id);
147+
char *bootargs = vm_config->os_config.bootargs;
148+
149+
if (vm_config->load_order == PRE_LAUNCHED_VM) {
150+
vm->sw.bootargs_info.src_addr = bootargs;
151+
vm->sw.bootargs_info.size = strnlen_s(bootargs, MAX_BOOTARGS_SIZE);
152+
} else {
153+
/* vm_config->load_order == SOS_VM */
154+
if ((mbi->mi_flags & MULTIBOOT_INFO_HAS_CMDLINE) != 0U) {
155+
/*
156+
* If there is cmdline from mbi->mi_cmdline, merge it with
157+
* vm_config->os_config.bootargs
158+
*/
159+
merge_cmdline(vm, hpa2hva((uint64_t)mbi->mi_cmdline), bootargs);
160+
161+
vm->sw.bootargs_info.src_addr = kernel_cmdline;
162+
vm->sw.bootargs_info.size = strnlen_s(kernel_cmdline, MAX_BOOTARGS_SIZE);
163+
} else {
164+
vm->sw.bootargs_info.src_addr = bootargs;
165+
vm->sw.bootargs_info.size = strnlen_s(bootargs, MAX_BOOTARGS_SIZE);
166+
}
167+
}
168+
169+
/* Kernel bootarg and zero page are right before the kernel image */
170+
if (vm->sw.bootargs_info.size > 0) {
171+
vm->sw.bootargs_info.load_addr = vm->sw.kernel_info.kernel_load_addr - (MEM_1K * 8U);
172+
} else {
173+
vm->sw.bootargs_info.load_addr = NULL;
174+
}
175+
}
176+
177+
static uint32_t get_mod_idx_by_tag(struct multiboot_module *mods, uint32_t mods_count, const char *tag)
178+
{
179+
uint32_t i, ret = INVALID_MOD_IDX;
180+
uint32_t tag_len = strnlen_s(tag, MAX_MOD_TAG_LEN);
181+
182+
for (i = 0; i < mods_count; i++) {
183+
const char *mm_string = (char *)hpa2hva((uint64_t)mods[i].mm_string);
184+
uint32_t mm_str_len = strnlen_s(mm_string, MAX_MOD_TAG_LEN);
185+
186+
/* when do file stitch by tool, the tag in mm_string might be followed with 0x0d or 0x0a */
187+
if ((mm_str_len >= tag_len) && (strncmp(mm_string, tag, tag_len) == 0)
188+
&& ((mm_string[tag_len] == 0x0d)
189+
|| (mm_string[tag_len] == 0x0a)
190+
|| (mm_string[tag_len] == 0))){
191+
ret = i;
192+
break;
193+
}
194+
}
195+
return ret;
196+
}
197+
198+
/* @pre vm != NULL && mbi != NULL
199+
*/
200+
static int32_t init_vm_sw_load(struct acrn_vm *vm, struct multiboot_info *mbi)
201+
{
202+
struct acrn_vm_config *vm_config = get_vm_config(vm->vm_id);
203+
struct multiboot_module *mods = (struct multiboot_module *)hpa2hva((uint64_t)mbi->mi_mods_addr);
204+
uint32_t mod_idx;
205+
int32_t ret = -EINVAL;
206+
207+
dev_dbg(ACRN_DBG_BOOT, "mod counts=%d\n", mbi->mi_mods_count);
208+
209+
mod_idx = get_mod_idx_by_tag(mods, mbi->mi_mods_count, vm_config->os_config.kernel_mod_tag);
210+
if (mod_idx != INVALID_MOD_IDX) {
211+
ret = init_vm_kernel_info(vm, &mods[mod_idx]);
212+
}
213+
214+
if (ret == 0) {
215+
init_vm_bootargs_info(vm, mbi);
216+
/* check whether there is a ramdisk module */
217+
mod_idx = get_mod_idx_by_tag(mods, mbi->mi_mods_count, vm_config->os_config.ramdisk_mod_tag);
218+
if (mod_idx != INVALID_MOD_IDX) {
219+
init_vm_ramdisk_info(vm, &mods[mod_idx]);
220+
/* TODO: prepare other modules like firmware, seedlist */
221+
}
222+
} else {
223+
pr_err("failed to load VM %d kernel module", vm->vm_id);
224+
}
225+
return ret;
226+
}
227+
228+
/**
229+
* @pre vm != NULL
230+
*/
170231
static int32_t init_general_vm_boot_info(struct acrn_vm *vm)
171232
{
172-
struct multiboot_module *mods = NULL;
173233
struct multiboot_info *mbi = NULL;
174-
struct acrn_vm_config *vm_config = get_vm_config(vm->vm_id);
175234
int32_t ret = -EINVAL;
176235

177236
if (boot_regs[0] != MULTIBOOT_INFO_MAGIC) {
@@ -183,59 +242,11 @@ static int32_t init_general_vm_boot_info(struct acrn_vm *vm)
183242
stac();
184243
dev_dbg(ACRN_DBG_BOOT, "Multiboot detected, flag=0x%x", mbi->mi_flags);
185244
if ((mbi->mi_flags & MULTIBOOT_INFO_HAS_MODS) == 0U) {
186-
panic("no sos kernel info found");
187-
clac();
245+
panic("no multiboot module info found");
188246
} else {
189-
190-
dev_dbg(ACRN_DBG_BOOT, "mod counts=%d\n", mbi->mi_mods_count);
191-
192-
/* mod[0] is for kernel, other mod for ramdisk/firmware info*/
193-
mods = (struct multiboot_module *)hpa2hva((uint64_t)mbi->mi_mods_addr);
194-
195-
dev_dbg(ACRN_DBG_BOOT, "mod0 start=0x%x, end=0x%x",
196-
mods[0].mm_mod_start, mods[0].mm_mod_end);
197-
198-
vm->sw.kernel_type = vm_config->os_config.kernel_type;
199-
vm->sw.kernel_info.kernel_src_addr = hpa2hva((uint64_t)mods[0].mm_mod_start);
200-
vm->sw.kernel_info.kernel_size = mods[0].mm_mod_end - mods[0].mm_mod_start;
201-
vm->sw.kernel_info.kernel_load_addr = get_kernel_load_addr(vm);
202-
203-
if (vm_config->load_order == PRE_LAUNCHED_VM) {
204-
vm->sw.bootargs_info.src_addr = (void *)vm_config->os_config.bootargs;
205-
vm->sw.bootargs_info.size =
206-
strnlen_s(vm_config->os_config.bootargs, MAX_BOOTARGS_SIZE);
207-
} else {
208-
if ((mbi->mi_flags & MULTIBOOT_INFO_HAS_CMDLINE) != 0U) {
209-
/*
210-
* If there is cmdline from mbi->mi_cmdline, merge it with
211-
* vm_config->os_config.bootargs
212-
*/
213-
merge_cmdline(vm, hpa2hva((uint64_t)mbi->mi_cmdline),
214-
vm_config->os_config.bootargs);
215-
216-
vm->sw.bootargs_info.src_addr = kernel_cmdline;
217-
vm->sw.bootargs_info.size =
218-
strnlen_s(kernel_cmdline, MAX_BOOTARGS_SIZE);
219-
} else {
220-
vm->sw.bootargs_info.src_addr = vm_config->os_config.bootargs;
221-
vm->sw.bootargs_info.size =
222-
strnlen_s(vm_config->os_config.bootargs, MAX_BOOTARGS_SIZE);
223-
}
224-
}
225-
226-
/* Kernel bootarg and zero page are right before the kernel image */
227-
vm->sw.bootargs_info.load_addr =
228-
vm->sw.kernel_info.kernel_load_addr - (MEM_1K * 8U);
229-
230-
if (mbi->mi_mods_count > 1U) {
231-
/*parse other modules, like firmware /ramdisk */
232-
parse_other_modules(vm, mods + 1, mbi->mi_mods_count - 1);
233-
}
234-
clac();
235-
if (vm->sw.kernel_info.kernel_load_addr != NULL) {
236-
ret = 0;
237-
}
247+
ret = init_vm_sw_load(vm, mbi);
238248
}
249+
clac();
239250
}
240251
}
241252
return ret;

hypervisor/common/vm_load.c

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -127,16 +127,11 @@ static void prepare_loading_bzimage(struct acrn_vm *vm, struct acrn_vcpu *vcpu)
127127
vcpu_set_gpreg(vcpu, i, 0UL);
128128
}
129129

130-
/* Copy Guest OS bootargs to its load location */
131-
(void)copy_to_gpa(vm, bootargs_info->src_addr,
132-
(uint64_t)bootargs_info->load_addr,
133-
(strnlen_s((char *)bootargs_info->src_addr, MAX_BOOTARGS_SIZE) + 1U));
134-
135130
/* add "hugepagesz=1G hugepages=x" to cmdline for 1G hugepage
136131
* reserving. Current strategy is "total_mem_size in Giga -
137132
* remained 1G pages" for reserving.
138133
*/
139-
if (is_sos_vm(vm)) {
134+
if (is_sos_vm(vm) && (bootargs_info->load_addr != NULL)) {
140135
int64_t reserving_1g_pages;
141136

142137
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)
159154
{
160155
int32_t ret = 0;
161156
struct sw_kernel_info *sw_kernel = &(vm->sw.kernel_info);
157+
struct sw_module_info *bootargs_info = &(vm->sw.bootargs_info);
162158
struct sw_module_info *ramdisk_info = &(vm->sw.ramdisk_info);
163159
/* get primary vcpu */
164160
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)
173169
(uint64_t)sw_kernel->kernel_load_addr, sw_kernel->kernel_size);
174170

175171
/* Check if a RAM disk is present */
176-
if (ramdisk_info->src_addr != NULL) {
172+
if (ramdisk_info->size != 0U) {
177173
/* Copy RAM disk to its load location */
178174
(void)copy_to_gpa(vm, ramdisk_info->src_addr,
179175
(uint64_t)ramdisk_info->load_addr,
180176
ramdisk_info->size);
181177
}
182-
178+
/* Copy Guest OS bootargs to its load location */
179+
if (bootargs_info->size != 0U) {
180+
(void)copy_to_gpa(vm, bootargs_info->src_addr,
181+
(uint64_t)bootargs_info->load_addr,
182+
(strnlen_s((char *)bootargs_info->src_addr, MAX_BOOTARGS_SIZE) + 1U));
183+
}
183184
switch (vm->sw.kernel_type) {
184185
case KERNEL_BZIMAGE:
185186
prepare_loading_bzimage(vm, vcpu);

hypervisor/include/arch/x86/vm_config.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#define PLUG_CPU(n) (1U << (n))
1919
#define MAX_VUART_NUM_PER_VM 2U
2020
#define MAX_VM_OS_NAME_LEN 32U
21+
#define MAX_MOD_TAG_LEN 32U
2122

2223
/*
2324
* PRE_LAUNCHED_VM is launched by ACRN hypervisor, with LAPIC_PT;
@@ -68,6 +69,8 @@ enum os_kernel_type {
6869
struct acrn_vm_os_config {
6970
char name[MAX_VM_OS_NAME_LEN]; /* OS name, useful for debug */
7071
enum os_kernel_type kernel_type; /* used for kernel specifc loading method */
72+
char kernel_mod_tag[MAX_MOD_TAG_LEN]; /* multiboot module tag for kernel */
73+
char ramdisk_mod_tag[MAX_MOD_TAG_LEN]; /* multiboot module tag for ramdisk */
7174
char bootargs[MAX_BOOTARGS_SIZE]; /* boot args/cmdline */
7275
} __aligned(8);
7376

hypervisor/scenarios/industry/vm_configurations.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ struct acrn_vm_config vm_configs[CONFIG_MAX_VM_NUM] = {
2323
.os_config = {
2424
.name = "ACRN Service OS",
2525
.kernel_type = KERNEL_BZIMAGE,
26+
.kernel_mod_tag = "Linux_bzImage",
2627
.bootargs = SOS_VM_BOOTARGS
2728
},
2829
.vuart[0] = {

hypervisor/scenarios/logical_partition/vm_configurations.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ struct acrn_vm_config vm_configs[CONFIG_MAX_VM_NUM] = {
2727
.os_config = {
2828
.name = "ClearLinux",
2929
.kernel_type = KERNEL_BZIMAGE,
30+
.kernel_mod_tag = "Linux_bzImage",
3031
.bootargs = VM0_CONFIG_OS_BOOTARG_CONSOLE \
3132
VM0_CONFIG_OS_BOOTARG_MAXCPUS \
3233
VM0_CONFIG_OS_BOOTARG_ROOT \
@@ -66,6 +67,7 @@ struct acrn_vm_config vm_configs[CONFIG_MAX_VM_NUM] = {
6667
.os_config = {
6768
.name = "ClearLinux",
6869
.kernel_type = KERNEL_BZIMAGE,
70+
.kernel_mod_tag = "Linux_bzImage",
6971
.bootargs = VM1_CONFIG_OS_BOOTARG_CONSOLE \
7072
VM1_CONFIG_OS_BOOTARG_MAXCPUS \
7173
VM1_CONFIG_OS_BOOTARG_ROOT \

hypervisor/scenarios/sdc/vm_configurations.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ struct acrn_vm_config vm_configs[CONFIG_MAX_VM_NUM] = {
2525
.os_config = {
2626
.name = "ACRN Service OS",
2727
.kernel_type = KERNEL_BZIMAGE,
28+
.kernel_mod_tag = "Linux_bzImage",
2829
.bootargs = SOS_VM_BOOTARGS,
2930
},
3031
.vuart[0] = {

0 commit comments

Comments
 (0)