mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-07-29 14:37:36 +00:00
HV: e820 refinement
- add e820 info in struct acrn_vm; - rename rebuild_sos_vm_e820() to create_sos_vm_e820(); - add create_prelaunched_vm_e820() for partition mode; - rename create_e820_table() to create_zeropage_e820() and merge for both sharing mode and partition mode; - move create_xxx_vm_e820() to vm.c; - move create_zeropage_e820() to vm_load.c; Tracked-On: #2291 Signed-off-by: Victor Sun <victor.sun@intel.com> Acked-by: Eddie Dong <eddie.dong@intel.com>
This commit is contained in:
parent
11bfe3d43e
commit
0f745b4d15
@ -51,71 +51,6 @@ static void obtain_e820_mem_info(void)
|
||||
}
|
||||
}
|
||||
|
||||
/* before boot sos_vm(service OS), call it to hide the HV RAM entry in e820 table from sos_vm */
|
||||
void rebuild_sos_vm_e820(void)
|
||||
{
|
||||
uint32_t i;
|
||||
uint64_t entry_start;
|
||||
uint64_t entry_end;
|
||||
uint64_t hv_start_pa = get_hv_image_base();
|
||||
uint64_t hv_end_pa = hv_start_pa + CONFIG_HV_RAM_SIZE;
|
||||
struct e820_entry *entry, new_entry = {0};
|
||||
|
||||
/* hypervisor mem need be filter out from e820 table
|
||||
* it's hv itself + other hv reserved mem like vgt etc
|
||||
*/
|
||||
for (i = 0U; i < e820_entries_count; i++) {
|
||||
entry = &e820[i];
|
||||
entry_start = entry->baseaddr;
|
||||
entry_end = entry->baseaddr + entry->length;
|
||||
|
||||
/* No need handle in these cases*/
|
||||
if ((entry->type != E820_TYPE_RAM) || (entry_end <= hv_start_pa) || (entry_start >= hv_end_pa)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* filter out hv mem and adjust length of this entry*/
|
||||
if ((entry_start < hv_start_pa) && (entry_end <= hv_end_pa)) {
|
||||
entry->length = hv_start_pa - entry_start;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* filter out hv mem and need to create a new entry*/
|
||||
if ((entry_start < hv_start_pa) && (entry_end > hv_end_pa)) {
|
||||
entry->length = hv_start_pa - entry_start;
|
||||
new_entry.baseaddr = hv_end_pa;
|
||||
new_entry.length = entry_end - hv_end_pa;
|
||||
new_entry.type = E820_TYPE_RAM;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* This entry is within the range of hv mem
|
||||
* change to E820_TYPE_RESERVED
|
||||
*/
|
||||
if ((entry_start >= hv_start_pa) && (entry_end <= hv_end_pa)) {
|
||||
entry->type = E820_TYPE_RESERVED;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((entry_start >= hv_start_pa) && (entry_start < hv_end_pa) && (entry_end > hv_end_pa)) {
|
||||
entry->baseaddr = hv_end_pa;
|
||||
entry->length = entry_end - hv_end_pa;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (new_entry.length > 0UL) {
|
||||
e820_entries_count++;
|
||||
ASSERT(e820_entries_count <= E820_MAX_ENTRIES, "e820 entry overflow");
|
||||
entry = &e820[e820_entries_count - 1];
|
||||
entry->baseaddr = new_entry.baseaddr;
|
||||
entry->length = new_entry.length;
|
||||
entry->type = new_entry.type;
|
||||
}
|
||||
|
||||
e820_mem.total_mem_size -= CONFIG_HV_RAM_SIZE;
|
||||
}
|
||||
|
||||
/* get some RAM below 1MB in e820 entries, hide it from sos_vm, return its start address */
|
||||
uint64_t e820_alloc_low_memory(uint32_t size_arg)
|
||||
{
|
||||
@ -225,33 +160,3 @@ const struct e820_mem_params *get_e820_mem_info(void)
|
||||
{
|
||||
return &e820_mem;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PARTITION_MODE
|
||||
uint32_t create_e820_table(struct e820_entry *param_e820)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0U; i < NUM_E820_ENTRIES; i++) {
|
||||
param_e820[i].baseaddr = ve820_entry[i].baseaddr;
|
||||
param_e820[i].length = ve820_entry[i].length;
|
||||
param_e820[i].type = ve820_entry[i].type;
|
||||
}
|
||||
|
||||
return NUM_E820_ENTRIES;
|
||||
}
|
||||
#else
|
||||
uint32_t create_e820_table(struct e820_entry *param_e820)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
ASSERT(e820_entries_count > 0U, "e820 should be inited");
|
||||
|
||||
for (i = 0U; i < e820_entries_count; i++) {
|
||||
param_e820[i].baseaddr = e820[i].baseaddr;
|
||||
param_e820[i].length = e820[i].length;
|
||||
param_e820[i].type = e820[i].type;
|
||||
}
|
||||
|
||||
return e820_entries_count;
|
||||
}
|
||||
#endif
|
||||
|
@ -109,8 +109,92 @@ uint16_t get_vm_pcpu_nums(struct acrn_vm_config *vm_config)
|
||||
}
|
||||
return pcpu_num;
|
||||
}
|
||||
|
||||
/**
|
||||
* @pre vm != NULL
|
||||
*/
|
||||
static void create_prelaunched_vm_e820(struct acrn_vm *vm)
|
||||
{
|
||||
vm->e820_entry_num = NUM_E820_ENTRIES;
|
||||
vm->e820_entries = (struct e820_entry *)ve820_entry;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* before boot sos_vm(service OS), call it to hide the HV RAM entry in e820 table from sos_vm
|
||||
*
|
||||
* @pre vm != NULL && entry != NULL && p_e820_mem != NULL
|
||||
*/
|
||||
static void create_sos_vm_e820(struct acrn_vm *vm)
|
||||
{
|
||||
uint32_t i;
|
||||
uint64_t entry_start;
|
||||
uint64_t entry_end;
|
||||
uint64_t hv_start_pa = get_hv_image_base();
|
||||
uint64_t hv_end_pa = hv_start_pa + CONFIG_HV_RAM_SIZE;
|
||||
uint32_t entries_count = get_e820_entries_count();
|
||||
struct e820_entry *entry, new_entry = {0};
|
||||
struct e820_entry *p_e820 = (struct e820_entry *)get_e820_entry();
|
||||
struct e820_mem_params *p_e820_mem = (struct e820_mem_params *)get_e820_mem_info();
|
||||
|
||||
/* hypervisor mem need be filter out from e820 table
|
||||
* it's hv itself + other hv reserved mem like vgt etc
|
||||
*/
|
||||
for (i = 0U; i < entries_count; i++) {
|
||||
entry = p_e820 + i;
|
||||
entry_start = entry->baseaddr;
|
||||
entry_end = entry->baseaddr + entry->length;
|
||||
|
||||
/* No need handle in these cases*/
|
||||
if ((entry->type != E820_TYPE_RAM) || (entry_end <= hv_start_pa) || (entry_start >= hv_end_pa)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* filter out hv mem and adjust length of this entry*/
|
||||
if ((entry_start < hv_start_pa) && (entry_end <= hv_end_pa)) {
|
||||
entry->length = hv_start_pa - entry_start;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* filter out hv mem and need to create a new entry*/
|
||||
if ((entry_start < hv_start_pa) && (entry_end > hv_end_pa)) {
|
||||
entry->length = hv_start_pa - entry_start;
|
||||
new_entry.baseaddr = hv_end_pa;
|
||||
new_entry.length = entry_end - hv_end_pa;
|
||||
new_entry.type = E820_TYPE_RAM;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* This entry is within the range of hv mem
|
||||
* change to E820_TYPE_RESERVED
|
||||
*/
|
||||
if ((entry_start >= hv_start_pa) && (entry_end <= hv_end_pa)) {
|
||||
entry->type = E820_TYPE_RESERVED;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((entry_start >= hv_start_pa) && (entry_start < hv_end_pa) && (entry_end > hv_end_pa)) {
|
||||
entry->baseaddr = hv_end_pa;
|
||||
entry->length = entry_end - hv_end_pa;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (new_entry.length > 0UL) {
|
||||
entries_count++;
|
||||
ASSERT(entries_count <= E820_MAX_ENTRIES, "e820 entry overflow");
|
||||
entry = p_e820 + entries_count - 1;
|
||||
entry->baseaddr = new_entry.baseaddr;
|
||||
entry->length = new_entry.length;
|
||||
entry->type = new_entry.type;
|
||||
}
|
||||
|
||||
p_e820_mem->total_mem_size -= CONFIG_HV_RAM_SIZE;
|
||||
|
||||
vm->e820_entry_num = entries_count;
|
||||
vm->e820_entries = p_e820;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param[inout] vm pointer to a vm descriptor
|
||||
*
|
||||
@ -127,8 +211,8 @@ static void prepare_sos_vm_memmap(struct acrn_vm *vm)
|
||||
uint64_t *pml4_page = (uint64_t *)vm->arch_vm.nworld_eptp;
|
||||
|
||||
const struct e820_entry *entry;
|
||||
uint32_t entries_count = get_e820_entries_count();
|
||||
const struct e820_entry *p_e820 = get_e820_entry();
|
||||
uint32_t entries_count = vm->e820_entry_num;
|
||||
struct e820_entry *p_e820 = vm->e820_entries;
|
||||
const struct e820_mem_params *p_e820_mem_info = get_e820_mem_info();
|
||||
|
||||
pr_dbg("sos_vm: bottom memory - 0x%llx, top memory - 0x%llx\n",
|
||||
@ -188,11 +272,10 @@ int32_t create_vm(uint16_t vm_id, struct acrn_vm_config *vm_config, struct acrn_
|
||||
vm->arch_vm.nworld_eptp = vm->arch_vm.ept_mem_ops.get_pml4_page(vm->arch_vm.ept_mem_ops.info);
|
||||
sanitize_pte((uint64_t *)vm->arch_vm.nworld_eptp);
|
||||
|
||||
/* Only for SOS: Configure VM software information */
|
||||
/* For UOS: This VM software information is configure in DM */
|
||||
if (is_sos_vm(vm)) {
|
||||
/* Only for SOS_VM */
|
||||
vm->snoopy_mem = false;
|
||||
rebuild_sos_vm_e820();
|
||||
create_sos_vm_e820(vm);
|
||||
prepare_sos_vm_memmap(vm);
|
||||
|
||||
status = init_vm_boot_info(vm);
|
||||
@ -203,7 +286,7 @@ int32_t create_vm(uint16_t vm_id, struct acrn_vm_config *vm_config, struct acrn_
|
||||
}
|
||||
|
||||
} else {
|
||||
/* populate UOS vm fields according to vm_config */
|
||||
/* For PRE_LAUNCHED_VM and NORMAL_VM */
|
||||
if ((vm_config->guest_flags & SECURE_WORLD_ENABLED) != 0U) {
|
||||
vm->sworld_control.flag.supported = 1U;
|
||||
}
|
||||
@ -222,6 +305,7 @@ int32_t create_vm(uint16_t vm_id, struct acrn_vm_config *vm_config, struct acrn_
|
||||
(void)memcpy_s(&vm->GUID[0], sizeof(vm->GUID),
|
||||
&vm_config->GUID[0], sizeof(vm_config->GUID));
|
||||
#ifdef CONFIG_PARTITION_MODE
|
||||
create_prelaunched_vm_e820(vm);
|
||||
ept_mr_add(vm, (uint64_t *)vm->arch_vm.nworld_eptp,
|
||||
vm_config->memory.start_hpa, 0UL, vm_config->memory.size,
|
||||
EPT_RWX|EPT_WB);
|
||||
|
@ -23,6 +23,25 @@ static void prepare_bsp_gdt(struct acrn_vm *vm)
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @pre zp != NULL && vm != NULL
|
||||
*/
|
||||
static uint32_t create_zeropage_e820(struct zero_page *zp, const struct acrn_vm *vm)
|
||||
{
|
||||
uint32_t entry_num = vm->e820_entry_num;
|
||||
struct e820_entry *zp_e820 = zp->entries;
|
||||
struct e820_entry *vm_e820 = vm->e820_entries;
|
||||
|
||||
if ((zp_e820 == NULL) || (vm_e820 == NULL) || (entry_num == 0U) || (entry_num > E820_MAX_ENTRIES)) {
|
||||
pr_err("e820 create error");
|
||||
entry_num = 0U;
|
||||
} else {
|
||||
(void)memcpy_s((void *)zp_e820, entry_num * sizeof(struct e820_entry),
|
||||
(void *)vm_e820, entry_num * sizeof(struct e820_entry));
|
||||
}
|
||||
return entry_num;
|
||||
}
|
||||
|
||||
static uint64_t create_zero_page(struct acrn_vm *vm)
|
||||
{
|
||||
struct zero_page *zeropage;
|
||||
@ -63,7 +82,7 @@ static uint64_t create_zero_page(struct acrn_vm *vm)
|
||||
zeropage->hdr.load_flags |= (1U << 5U); /* quiet */
|
||||
|
||||
/* Create/add e820 table entries in zeropage */
|
||||
zeropage->e820_nentries = (uint8_t)create_e820_table(zeropage->entries);
|
||||
zeropage->e820_nentries = (uint8_t)create_zeropage_e820(zeropage, vm);
|
||||
clac();
|
||||
|
||||
/* Return Physical Base Address of zeropage */
|
||||
|
@ -36,15 +36,9 @@ struct e820_mem_params {
|
||||
/* HV read multiboot header to get e820 entries info and calc total RAM info */
|
||||
void init_e820(void);
|
||||
|
||||
/* before boot sos_vm(service OS), call it to hide the HV RAM entry in e820 table from sos_vm */
|
||||
void rebuild_sos_vm_e820(void);
|
||||
|
||||
/* get some RAM below 1MB in e820 entries, hide it from sos_vm, return its start address */
|
||||
uint64_t e820_alloc_low_memory(uint32_t size_arg);
|
||||
|
||||
/* copy the original e820 entries info to param_e820 */
|
||||
uint32_t create_e820_table(struct e820_entry *param_e820);
|
||||
|
||||
/* get total number of the e820 entries */
|
||||
uint32_t get_e820_entries_count(void);
|
||||
|
||||
@ -54,15 +48,4 @@ const struct e820_entry *get_e820_entry(void);
|
||||
/* get the e820 total memory info */
|
||||
const struct e820_mem_params *get_e820_mem_info(void);
|
||||
|
||||
#ifdef CONFIG_PARTITION_MODE
|
||||
/*
|
||||
* Default e820 mem map:
|
||||
*
|
||||
* Assumption is every VM launched by ACRN in partition mode uses 2G of RAM.
|
||||
* there is reserved memory of 64K for MPtable and PCI hole of 512MB
|
||||
*/
|
||||
#define NUM_E820_ENTRIES 5U
|
||||
extern const struct e820_entry ve820_entry[NUM_E820_ENTRIES];
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include <vpci.h>
|
||||
#include <page.h>
|
||||
#include <cpu_caps.h>
|
||||
#include <e820.h>
|
||||
|
||||
#ifdef CONFIG_PARTITION_MODE
|
||||
#include <mptable.h>
|
||||
@ -132,6 +133,8 @@ struct acrn_vm {
|
||||
struct vm_hw_info hw; /* Reference to this VM's HW information */
|
||||
struct vm_sw_info sw; /* Reference to SW associated with this VM */
|
||||
struct vm_pm_info pm; /* Reference to this VM's arch information */
|
||||
uint32_t e820_entry_num;
|
||||
struct e820_entry *e820_entries;
|
||||
uint16_t vm_id; /* Virtual machine identifier */
|
||||
enum vm_state state; /* VM state */
|
||||
struct acrn_vuart vuart; /* Virtual UART */
|
||||
@ -291,6 +294,15 @@ struct acrn_vm *get_vm_from_vmid(uint16_t vm_id);
|
||||
struct acrn_vm *get_sos_vm(void);
|
||||
|
||||
#ifdef CONFIG_PARTITION_MODE
|
||||
/*
|
||||
* Default e820 mem map:
|
||||
*
|
||||
* Assumption is every VM launched by ACRN in partition mode uses 2G of RAM.
|
||||
* there is reserved memory of 64K for MPtable and PCI hole of 512MB
|
||||
*/
|
||||
#define NUM_E820_ENTRIES 5U
|
||||
extern const struct e820_entry ve820_entry[NUM_E820_ENTRIES];
|
||||
|
||||
struct vm_config_arraies {
|
||||
int32_t num_vm_config;
|
||||
struct acrn_vm_config vm_config_array[CONFIG_MAX_VM_NUM];
|
||||
|
Loading…
Reference in New Issue
Block a user