mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-04-30 04:33:58 +00:00
We should not hardcode the VM ramdisk load address right after kernel load address because of two reasons: 1. Per Linux kernel boot protocol, the Kernel need a size of contiguous memory(i.e. init_size field in zeropage) from its load address to boot, then the address would overlap with ramdisk; 2. The hardcoded address could not be ensured as a valid address in guest e820 table, especially with a huge ramdisk; Also we should not hardcode the VM kernel load address to its pref_address which work for non-relocatable kernel only. For a relocatable kernel, it could run from any valid address where bootloader load to. The patch will set the VM kernel and ramdisk load address by scanning guest e820 table with find_space_from_ve820() api: 1. For SOS VM, the ramdisk has been loaded by multiboot bootloader already so set the load address as module source address, the relocatable kernel would be relocated to a appropriate address out space of hypervisor and boot modules to avoid guest memory copy corruption; 2. For pre-launched VM, the kernel would be loaded to pref_address first, then ramdisk will be put to a appropriate address out space of kernel according to guest memory layout and maximum ramdisk address limit under 4GB; Tracked-On: #5879 Signed-off-by: Victor Sun <victor.sun@intel.com> Reviewed-by: Jason Chen CJ <jason.cj.chen@intel.com>
80 lines
1.7 KiB
C
80 lines
1.7 KiB
C
/*
|
|
* Copyright (C) 2021 Intel Corporation.
|
|
*
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*/
|
|
|
|
#include <types.h>
|
|
#include <errno.h>
|
|
#include <asm/pgtable.h>
|
|
#include <boot.h>
|
|
#include <rtl.h>
|
|
#include <logmsg.h>
|
|
|
|
static struct acrn_boot_info acrn_bi = { 0U };
|
|
|
|
/**
|
|
* @pre (p_start != NULL) && (p_end != NULL)
|
|
*/
|
|
void get_boot_mods_range(uint64_t *p_start, uint64_t *p_end)
|
|
{
|
|
uint32_t i;
|
|
uint64_t start = ~0UL, end = 0UL;
|
|
struct acrn_boot_info *abi = get_acrn_boot_info();
|
|
|
|
for (i = 0; i < abi->mods_count; i++) {
|
|
if (hva2hpa(abi->mods[i].start) < start) {
|
|
start = hva2hpa(abi->mods[i].start);
|
|
}
|
|
if (hva2hpa(abi->mods[i].start + abi->mods[i].size) > end) {
|
|
end = hva2hpa(abi->mods[i].start + abi->mods[i].size);
|
|
}
|
|
}
|
|
*p_start = start;
|
|
*p_end = end;
|
|
}
|
|
|
|
void init_acrn_boot_info(uint32_t *registers)
|
|
{
|
|
(void)init_multiboot_info(registers);
|
|
/* TODO: add more boot protocol support here */
|
|
}
|
|
|
|
int32_t sanitize_acrn_boot_info(struct acrn_boot_info *abi)
|
|
{
|
|
int32_t abi_status = 0;
|
|
|
|
if (abi->mods_count == 0U) {
|
|
pr_err("no boot module info found");
|
|
abi_status = -EINVAL;
|
|
}
|
|
|
|
if (abi->mmap_entries == 0U) {
|
|
pr_err("no boot mmap info found");
|
|
abi_status = -EINVAL;
|
|
}
|
|
|
|
printf("%s environment detected.\n", boot_from_uefi(abi) ? "UEFI" : "Non-UEFI");
|
|
if (boot_from_uefi(abi) && (abi->uefi_info.memmap == 0U) && (abi->uefi_info.memmap_hi == 0U)) {
|
|
pr_err("no efi memmap found!");
|
|
abi_status = -EINVAL;
|
|
}
|
|
|
|
if (abi->loader_name[0] == '\0') {
|
|
pr_err("no bootloader name found!");
|
|
abi_status = -EINVAL;
|
|
} else {
|
|
printf("%s Bootloader: %s\n", abi->protocol_name, abi->loader_name);
|
|
}
|
|
|
|
return abi_status;
|
|
}
|
|
|
|
/*
|
|
* @post retval != NULL
|
|
*/
|
|
struct acrn_boot_info *get_acrn_boot_info(void)
|
|
{
|
|
return &acrn_bi;
|
|
}
|