hv: optimize the assignment of load addresses for multiboot images

bootargs_load_addr (GPA) and zero page which locates at one page follows it:
- SOS: currently it's fixed at 0x24EFC000. Theoretically, this address may
  not exist if the system has small memory size.
- pre-launched VMs: currently it's at (vm_config->memory.size - 8KB).
  It doesn't work if the guest has been assigned for more than 4GB memory
  size, because zero page must be under 4GB.
- This patch reserves 8KB for bootargs_load_addr right before kernel_load_addr
  for either SOS or pre-launched VMs.

ramdisk_load_addr (GPA):
- pre-launched VMs: currently it doesn't allow ramdisk.
- SOS: currently it's assigned at mods[].mm_mod_start. It's a bug because it
  misses the hpa2gpa() conversion.
- This patch puts ramdisk_load_addr right after (kernel_load_addr + kernel_size),
  which has 2 benefits:
  - for pre-launched VMs, mods[].mm_mod_start may be out of its GPA range.
  - it may be better to consolidate everything (bootarg, kernel, ramdisk) in
    consecutive GPA, other than spread them out in different places.

Tracked-On: #2587
Signed-off-by: Zide Chen <zide.chen@intel.com>
Reviewed-by: Eddie Dong <eddie.dong@intel.com>
Reviewed-by: Victor Sun <victor.sun@intel.com>
Acked-by: Anthony Xu <anthony.xu@intel.com>
This commit is contained in:
Zide Chen 2019-02-21 08:53:25 -08:00 committed by wenlingz
parent 3f0ff2ec43
commit cf1515d63c

View File

@ -6,13 +6,10 @@
#include <hypervisor.h>
#include <multiboot.h>
#include <e820.h>
#include <zeropage.h>
#include <sbl_seed_parse.h>
#include <abl_seed_parse.h>
#define BOOT_ARGS_LOAD_ADDR 0x24EFC000
#define ACRN_DBG_BOOT 6U
#define MAX_BOOT_PARAMS_LEN 64U
@ -49,10 +46,11 @@ int32_t init_vm_boot_info(struct acrn_vm *vm)
vm->sw.kernel_type = VM_LINUX_GUEST;
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 = (void *)(16 * 1024 * 1024UL);
vm->sw.kernel_info.kernel_load_addr = (void *)(MEM_1M * 16U);
vm->sw.linux_info.bootargs_src_addr = (void *)vm_config->os_config.bootargs;
vm->sw.linux_info.bootargs_size = strnlen_s(vm_config->os_config.bootargs, MEM_2K);
vm->sw.linux_info.bootargs_load_addr = (void *)(vm_config->memory.size - 8*1024UL);
vm->sw.linux_info.bootargs_load_addr =
vm->sw.kernel_info.kernel_load_addr - (MEM_1K * 8U);
clac();
ret = 0;
}
@ -110,7 +108,7 @@ static void parse_other_modules(struct acrn_vm *vm, const struct multiboot_modul
if (copy_once != 0) {
copy_once = 0;
(void)strncpy_s(load_addr, MEM_2K, (const char *)vm->sw.linux_info.bootargs_src_addr,
vm->sw.linux_info.bootargs_size);
vm->sw.linux_info.bootargs_size);
vm->sw.linux_info.bootargs_src_addr = load_addr;
}
@ -119,7 +117,10 @@ static void parse_other_modules(struct acrn_vm *vm, const struct multiboot_modul
} else if (strncmp("RAMDISK", start, type_len) == 0) {
vm->sw.linux_info.ramdisk_src_addr = mod_addr;
vm->sw.linux_info.ramdisk_load_addr = (void *)(uint64_t)mods[i].mm_mod_start;
vm->sw.linux_info.ramdisk_load_addr = vm->sw.kernel_info.kernel_load_addr +
vm->sw.kernel_info.kernel_size;
vm->sw.linux_info.ramdisk_load_addr =
(void *)round_page_up((uint64_t)vm->sw.linux_info.ramdisk_load_addr);
vm->sw.linux_info.ramdisk_size = mod_size;
} else {
pr_warn("not support mod, cmd: %s", start);
@ -240,10 +241,12 @@ int32_t init_vm_boot_info(struct acrn_vm *vm)
} else {
vm->sw.linux_info.bootargs_src_addr = hpa2hva((uint64_t)mods[0].mm_string);
vm->sw.linux_info.bootargs_size =
strnlen_s(hpa2hva((uint64_t)mods[0].mm_string), MEM_2K);
strnlen_s(hpa2hva((uint64_t)mods[0].mm_string), MEM_2K);
}
vm->sw.linux_info.bootargs_load_addr = (void *)BOOT_ARGS_LOAD_ADDR;
/* Kernel bootarg and zero page are right before the kernel image */
vm->sw.linux_info.bootargs_load_addr =
vm->sw.kernel_info.kernel_load_addr - (MEM_1K * 8U);
if (mbi->mi_mods_count > 1U) {
/*parse other modules, like firmware /ramdisk */