mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-09-14 05:19:42 +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:
@@ -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 */
|
/* 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)
|
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;
|
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;
|
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
|
#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
|
* @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;
|
uint64_t *pml4_page = (uint64_t *)vm->arch_vm.nworld_eptp;
|
||||||
|
|
||||||
const struct e820_entry *entry;
|
const struct e820_entry *entry;
|
||||||
uint32_t entries_count = get_e820_entries_count();
|
uint32_t entries_count = vm->e820_entry_num;
|
||||||
const struct e820_entry *p_e820 = get_e820_entry();
|
struct e820_entry *p_e820 = vm->e820_entries;
|
||||||
const struct e820_mem_params *p_e820_mem_info = get_e820_mem_info();
|
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",
|
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);
|
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);
|
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)) {
|
if (is_sos_vm(vm)) {
|
||||||
|
/* Only for SOS_VM */
|
||||||
vm->snoopy_mem = false;
|
vm->snoopy_mem = false;
|
||||||
rebuild_sos_vm_e820();
|
create_sos_vm_e820(vm);
|
||||||
prepare_sos_vm_memmap(vm);
|
prepare_sos_vm_memmap(vm);
|
||||||
|
|
||||||
status = init_vm_boot_info(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 {
|
} 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) {
|
if ((vm_config->guest_flags & SECURE_WORLD_ENABLED) != 0U) {
|
||||||
vm->sworld_control.flag.supported = 1U;
|
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),
|
(void)memcpy_s(&vm->GUID[0], sizeof(vm->GUID),
|
||||||
&vm_config->GUID[0], sizeof(vm_config->GUID));
|
&vm_config->GUID[0], sizeof(vm_config->GUID));
|
||||||
#ifdef CONFIG_PARTITION_MODE
|
#ifdef CONFIG_PARTITION_MODE
|
||||||
|
create_prelaunched_vm_e820(vm);
|
||||||
ept_mr_add(vm, (uint64_t *)vm->arch_vm.nworld_eptp,
|
ept_mr_add(vm, (uint64_t *)vm->arch_vm.nworld_eptp,
|
||||||
vm_config->memory.start_hpa, 0UL, vm_config->memory.size,
|
vm_config->memory.start_hpa, 0UL, vm_config->memory.size,
|
||||||
EPT_RWX|EPT_WB);
|
EPT_RWX|EPT_WB);
|
||||||
|
@@ -23,6 +23,25 @@ static void prepare_bsp_gdt(struct acrn_vm *vm)
|
|||||||
return;
|
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)
|
static uint64_t create_zero_page(struct acrn_vm *vm)
|
||||||
{
|
{
|
||||||
struct zero_page *zeropage;
|
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 */
|
zeropage->hdr.load_flags |= (1U << 5U); /* quiet */
|
||||||
|
|
||||||
/* Create/add e820 table entries in zeropage */
|
/* 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();
|
clac();
|
||||||
|
|
||||||
/* Return Physical Base Address of zeropage */
|
/* 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 */
|
/* HV read multiboot header to get e820 entries info and calc total RAM info */
|
||||||
void init_e820(void);
|
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 */
|
/* 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);
|
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 */
|
/* get total number of the e820 entries */
|
||||||
uint32_t get_e820_entries_count(void);
|
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 */
|
/* get the e820 total memory info */
|
||||||
const struct e820_mem_params *get_e820_mem_info(void);
|
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
|
#endif
|
||||||
|
@@ -10,6 +10,7 @@
|
|||||||
#include <vpci.h>
|
#include <vpci.h>
|
||||||
#include <page.h>
|
#include <page.h>
|
||||||
#include <cpu_caps.h>
|
#include <cpu_caps.h>
|
||||||
|
#include <e820.h>
|
||||||
|
|
||||||
#ifdef CONFIG_PARTITION_MODE
|
#ifdef CONFIG_PARTITION_MODE
|
||||||
#include <mptable.h>
|
#include <mptable.h>
|
||||||
@@ -132,6 +133,8 @@ struct acrn_vm {
|
|||||||
struct vm_hw_info hw; /* Reference to this VM's HW information */
|
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_sw_info sw; /* Reference to SW associated with this VM */
|
||||||
struct vm_pm_info pm; /* Reference to this VM's arch information */
|
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 */
|
uint16_t vm_id; /* Virtual machine identifier */
|
||||||
enum vm_state state; /* VM state */
|
enum vm_state state; /* VM state */
|
||||||
struct acrn_vuart vuart; /* Virtual UART */
|
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);
|
struct acrn_vm *get_sos_vm(void);
|
||||||
|
|
||||||
#ifdef CONFIG_PARTITION_MODE
|
#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 {
|
struct vm_config_arraies {
|
||||||
int32_t num_vm_config;
|
int32_t num_vm_config;
|
||||||
struct acrn_vm_config vm_config_array[CONFIG_MAX_VM_NUM];
|
struct acrn_vm_config vm_config_array[CONFIG_MAX_VM_NUM];
|
||||||
|
Reference in New Issue
Block a user