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:
Victor Sun 2019-02-01 23:12:09 +08:00 committed by Eddie Dong
parent 11bfe3d43e
commit 0f745b4d15
5 changed files with 122 additions and 119 deletions

View File

@ -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

View File

@ -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);

View File

@ -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 */

View File

@ -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

View File

@ -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];