HV: init hv_e820 from efi mmap if boot from uefi
Hypervisor use e820_alloc_memory() api to allocate memory for trampoline code and ept pages, whereas the usable ram in hv_e820 might include efi boot service region if system boot from uefi environment, this would result in some uefi service broken in SOS. These boot service region should be filtered from hv_e820. This patch will parse the efi memory descriptor entries info from efi memory map pointer when system boot from uefi environment, and then initialize hv_e820 accordingly, that all efi boot service region would be kept as reserved in hv_e820. Please note the original efi memory map could be above 4GB address space, so the efi memory parsing process must be done after enable_paging(). Tracked-On: #5626 Signed-off-by: Victor Sun <victor.sun@intel.com> Reviewed-by: Jason Chen CJ <jason.cj.chen@intel.com>
This commit is contained in:
parent
9ac8e292fd
commit
9dfac7a7a3
|
@ -10,6 +10,7 @@
|
|||
#include <asm/e820.h>
|
||||
#include <asm/mmu.h>
|
||||
#include <boot.h>
|
||||
#include <efi_mmap.h>
|
||||
#include <logmsg.h>
|
||||
#include <asm/guest/ept.h>
|
||||
|
||||
|
@ -97,13 +98,95 @@ uint64_t e820_alloc_memory(uint32_t size_arg, uint64_t max_addr)
|
|||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void init_e820_from_efi_mmap(void)
|
||||
{
|
||||
uint32_t i, e820_idx = 0U;
|
||||
uint64_t top_addr_space = CONFIG_PLATFORM_RAM_SIZE + PLATFORM_LO_MMIO_SIZE;
|
||||
const struct efi_memory_desc *efi_mmap_entry = get_efi_mmap_entry();
|
||||
|
||||
for (i = 0U; i < get_efi_mmap_entries_count(); i++) {
|
||||
if (e820_idx >= E820_MAX_ENTRIES) {
|
||||
pr_err("Too many efi memmap entries !");
|
||||
break;
|
||||
}
|
||||
|
||||
hv_e820[e820_idx].baseaddr = efi_mmap_entry[i].phys_addr;
|
||||
hv_e820[e820_idx].length = efi_mmap_entry[i].num_pages * PAGE_SIZE;
|
||||
if (hv_e820[e820_idx].baseaddr >= top_addr_space) {
|
||||
hv_e820[e820_idx].length = 0UL;
|
||||
} else {
|
||||
if ((hv_e820[e820_idx].baseaddr + hv_e820[e820_idx].length) > top_addr_space) {
|
||||
hv_e820[e820_idx].length = top_addr_space - hv_e820[e820_idx].baseaddr;
|
||||
}
|
||||
}
|
||||
|
||||
/* The EFI BOOT Service releated regions need to be set to reserved and avoid being touched by
|
||||
* hypervisor, because at least below software modules rely on them:
|
||||
* 1. EFI ESRT(The EFI System Resource Table) which used for UEFI firmware upgrade;
|
||||
* 2. Image resource in ACPI BGRT(Boottime Graphics Resource Table) which used for boot time logo;
|
||||
*/
|
||||
switch (efi_mmap_entry[i].type) {
|
||||
case EFI_LOADER_CODE:
|
||||
case EFI_LOADER_DATA:
|
||||
case EFI_CONVENTIONAL_MEMORY:
|
||||
if ((efi_mmap_entry[i].attribute & EFI_MEMORY_WB) != 0UL) {
|
||||
hv_e820[e820_idx].type = E820_TYPE_RAM;
|
||||
} else {
|
||||
hv_e820[e820_idx].type = E820_TYPE_RESERVED;
|
||||
}
|
||||
break;
|
||||
case EFI_UNUSABLE_MEMORY:
|
||||
hv_e820[e820_idx].type = E820_TYPE_UNUSABLE;
|
||||
break;
|
||||
case EFI_ACPI_RECLAIM_MEMORY:
|
||||
hv_e820[e820_idx].type = E820_TYPE_ACPI_RECLAIM;
|
||||
break;
|
||||
case EFI_ACPI_MEMORY_NVS:
|
||||
hv_e820[e820_idx].type = E820_TYPE_ACPI_NVS;
|
||||
break;
|
||||
/* case EFI_RESERVED_MEMORYTYPE:
|
||||
* case EFI_BOOT_SERVICES_CODE:
|
||||
* case EFI_BOOT_SERVICES_DATA:
|
||||
* case EFI_RUNTIME_SERVICES_CODE:
|
||||
* case EFI_RUNTIME_SERVICES_DATA:
|
||||
* case EFI_MEMORYMAPPED_IO:
|
||||
* case EFI_MEMORYMAPPED_IOPORTSPACE:
|
||||
* case EFI_PALCODE:
|
||||
* case EFI_PERSISTENT_MEMORY:
|
||||
*/
|
||||
default:
|
||||
hv_e820[e820_idx].type = E820_TYPE_RESERVED;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Given the efi memmap has been sorted, the hv_e820[] is also sorted.
|
||||
* Then the algorithm is very simple, just merge with previous mmap entry
|
||||
* if type is same and base addr is continuous.
|
||||
*/
|
||||
if ((e820_idx > 0U) && (hv_e820[e820_idx].type == hv_e820[e820_idx - 1U].type)
|
||||
&& (hv_e820[e820_idx].baseaddr ==
|
||||
(hv_e820[e820_idx - 1U].baseaddr
|
||||
+ hv_e820[e820_idx - 1U].length))) {
|
||||
hv_e820[e820_idx - 1U].length += hv_e820[e820_idx].length;
|
||||
} else {
|
||||
dev_dbg(DBG_LEVEL_E820, "efi mmap hv_e820[%d]: type: 0x%x Base: 0x%016lx length: 0x%016lx",
|
||||
e820_idx, hv_e820[e820_idx].type, hv_e820[e820_idx].baseaddr, hv_e820[e820_idx].length);
|
||||
e820_idx ++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
hv_e820_entries_nr = e820_idx;
|
||||
|
||||
}
|
||||
|
||||
/* HV read multiboot header to get e820 entries info and calc total RAM info */
|
||||
void init_e820(void)
|
||||
static void init_e820_from_mmap(struct acrn_boot_info *abi)
|
||||
{
|
||||
uint32_t i;
|
||||
uint64_t top_addr_space = CONFIG_PLATFORM_RAM_SIZE + PLATFORM_LO_MMIO_SIZE;
|
||||
|
||||
struct acrn_boot_info *abi = get_acrn_boot_info();
|
||||
struct abi_mmap *mmap = abi->mmap_entry;
|
||||
|
||||
hv_e820_entries_nr = abi->mmap_entries;
|
||||
|
@ -111,7 +194,6 @@ void init_e820(void)
|
|||
dev_dbg(DBG_LEVEL_E820, "mmap addr 0x%x entries %d\n",
|
||||
abi->mmap_entry, hv_e820_entries_nr);
|
||||
|
||||
|
||||
for (i = 0U; i < hv_e820_entries_nr; i++) {
|
||||
if (mmap[i].baseaddr >= top_addr_space) {
|
||||
mmap[i].length = 0UL;
|
||||
|
@ -125,9 +207,20 @@ void init_e820(void)
|
|||
hv_e820[i].length = mmap[i].length;
|
||||
hv_e820[i].type = mmap[i].type;
|
||||
|
||||
dev_dbg(DBG_LEVEL_E820, "mmap table: %d type: 0x%x", i, mmap[i].type);
|
||||
dev_dbg(DBG_LEVEL_E820, "Base: 0x%016lx length: 0x%016lx\n",
|
||||
mmap[i].baseaddr, mmap[i].length);
|
||||
dev_dbg(DBG_LEVEL_E820, "mmap hv_e820[%d]: type: 0x%x Base: 0x%016lx length: 0x%016lx", i,
|
||||
mmap[i].type, mmap[i].baseaddr, mmap[i].length);
|
||||
}
|
||||
}
|
||||
|
||||
void init_e820(void)
|
||||
{
|
||||
struct acrn_boot_info *abi = get_acrn_boot_info();
|
||||
|
||||
if (boot_from_uefi(abi)) {
|
||||
init_efi_mmap_entries(&abi->uefi_info);
|
||||
init_e820_from_efi_mmap();
|
||||
} else {
|
||||
init_e820_from_mmap(abi);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -34,6 +34,10 @@ int32_t sanitize_acrn_boot_info(struct acrn_boot_info *abi)
|
|||
}
|
||||
|
||||
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!");
|
||||
|
|
|
@ -7,6 +7,43 @@
|
|||
#ifndef EFI_H
|
||||
#define EFI_H
|
||||
|
||||
/* EFI Memory Attribute values: */
|
||||
#define EFI_MEMORY_UC 0x0000000000000001UL /* uncached */
|
||||
#define EFI_MEMORY_WC 0x0000000000000002UL /* write-coalescing */
|
||||
#define EFI_MEMORY_WT 0x0000000000000004UL /* write-through */
|
||||
#define EFI_MEMORY_WB 0x0000000000000008UL /* write-back */
|
||||
/*
|
||||
#define EFI_MEMORY_UCE 0x0000000000000010UL
|
||||
#define EFI_MEMORY_WP 0x0000000000001000UL
|
||||
#define EFI_MEMORY_RP 0x0000000000002000UL
|
||||
#define EFI_MEMORY_XP 0x0000000000004000UL
|
||||
#define EFI_MEMORY_NV 0x0000000000008000UL
|
||||
#define EFI_MEMORY_MORE_RELIABLE 0x0000000000010000UL
|
||||
#define EFI_MEMORY_RO 0x0000000000020000UL
|
||||
#define EFI_MEMORY_SP 0x0000000000040000UL
|
||||
#define EFI_MEMORY_CPU_CRYPTO 0x0000000000080000UL
|
||||
#define EFI_MEMORY_RUNTIME 0x8000000000000000UL
|
||||
*/
|
||||
|
||||
enum efi_memory_type {
|
||||
EFI_RESERVED_MEMORYTYPE,
|
||||
EFI_LOADER_CODE,
|
||||
EFI_LOADER_DATA,
|
||||
EFI_BOOT_SERVICES_CODE,
|
||||
EFI_BOOT_SERVICES_DATA,
|
||||
EFI_RUNTIME_SERVICES_CODE,
|
||||
EFI_RUNTIME_SERVICES_DATA,
|
||||
EFI_CONVENTIONAL_MEMORY,
|
||||
EFI_UNUSABLE_MEMORY,
|
||||
EFI_ACPI_RECLAIM_MEMORY,
|
||||
EFI_ACPI_MEMORY_NVS,
|
||||
EFI_MEMORYMAPPED_IO,
|
||||
EFI_MEMORYMAPPED_IOPORTSPACE,
|
||||
EFI_PALCODE,
|
||||
EFI_PERSISTENT_MEMORY,
|
||||
EFI_MAX_MEMORYTYPE
|
||||
};
|
||||
|
||||
struct efi_memory_desc {
|
||||
uint32_t type;
|
||||
uint32_t pad;
|
||||
|
|
Loading…
Reference in New Issue