From d7eac3fe6ad5f0c7168846127146be4f6e2c5e4b Mon Sep 17 00:00:00 2001 From: Victor Sun Date: Thu, 27 Feb 2020 15:48:42 +0800 Subject: [PATCH] HV: decouple prelaunch VM ve820 from board configs hypervisor/arch/x86/configs/$(BOARD)/ve820.c is used to store pre-launched VM specific e820 entries according to memory configuration of customer. It should be a scenario based configurations but we had to put it in per board foler because of different board memory settings. This brings concerns to customer on configuration orgnization. Currently the file provides same e820 layout for all pre-launched VMs, but they should have different e820 when their memory are configured differently. Although we have acrn-config tool to generate ve802.c automatically, it is not friendly to modify hardcoded ve820 layout manually, so the patch changes the entries initialization method by calculating each entry item in C code. Tracked-On: #4458 Signed-off-by: Victor Sun Acked-by: Eddie Dong --- hypervisor/Makefile | 2 +- hypervisor/arch/x86/guest/ve820.c | 105 +++++++++++++++++++++++++ hypervisor/include/arch/x86/guest/vm.h | 2 +- 3 files changed, 107 insertions(+), 2 deletions(-) create mode 100644 hypervisor/arch/x86/guest/ve820.c diff --git a/hypervisor/Makefile b/hypervisor/Makefile index 678675798..792968acf 100644 --- a/hypervisor/Makefile +++ b/hypervisor/Makefile @@ -270,6 +270,7 @@ VP_BASE_C_SRCS += arch/x86/guest/virq.c VP_BASE_C_SRCS += arch/x86/guest/virtual_cr.c VP_BASE_C_SRCS += arch/x86/guest/vmexit.c VP_BASE_C_SRCS += arch/x86/guest/ept.c +VP_BASE_C_SRCS += arch/x86/guest/ve820.c VP_BASE_C_SRCS += arch/x86/guest/ucode.c ifeq ($(CONFIG_HYPERV_ENABLED),y) VP_BASE_C_SRCS += arch/x86/guest/hyperv.c @@ -279,7 +280,6 @@ VP_BASE_C_SRCS += common/hv_main.c VP_BASE_C_SRCS += common/vm_load.c VP_BASE_C_SRCS += arch/x86/configs/pci_dev.c VP_BASE_C_SRCS += arch/x86/configs/vacpi.c -VP_BASE_C_SRCS += arch/x86/configs/$(CONFIG_BOARD)/ve820.c # virtual platform device model VP_DM_C_SRCS += dm/vpic.c diff --git a/hypervisor/arch/x86/guest/ve820.c b/hypervisor/arch/x86/guest/ve820.c new file mode 100644 index 000000000..c5408dd7a --- /dev/null +++ b/hypervisor/arch/x86/guest/ve820.c @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#define ENTRY_HPA1 2U +#define ENTRY_HPA1_HI 4U + +static struct e820_entry pre_vm_e820[PRE_VM_NUM][E820_MAX_ENTRIES]; + +static const struct e820_entry pre_ve820_template[E820_MAX_ENTRIES] = { + { /* usable RAM under 1MB */ + .baseaddr = 0x0UL, + .length = 0xF0000UL, /* 960KB */ + .type = E820_TYPE_RAM + }, + { /* mptable */ + .baseaddr = 0xF0000UL, /* 960KB */ + .length = 0x10000UL, /* 64KB */ + .type = E820_TYPE_RESERVED + }, + { /* hpa1 */ + .baseaddr = 0x100000UL, /* 1MB */ + .length = (MEM_2G - MEM_1M), + .type = E820_TYPE_RAM + }, + { /* 32bit PCI hole */ + .baseaddr = 0x80000000UL, /* 2048MB */ + .length = MEM_2G, + .type = E820_TYPE_RESERVED + }, +}; + +/** + * @pre entry != NULL + */ +static inline uint64_t add_ram_entry(struct e820_entry *entry, uint64_t gpa, uint64_t length) +{ + entry->baseaddr = gpa; + entry->length = length; + entry->type = E820_TYPE_RAM; + return round_pde_up(entry->baseaddr + entry->length); +} + +/** + * @pre vm != NULL + * + * ve820 layout for pre-launched VM: + * + * entry0: usable under 1MB + * entry1: reserved for MP Table from 0xf0000 to 0xfffff + * entry2: usable for hpa1 or hpa1_lo from 0x100000 + * entry3: reserved for 32bit PCI hole from 0x80000000 to 0xffffffff + * (entry4): usable for + * a) hpa1_hi, if hpa1 > 2GB + * b) hpa2, if (hpa1 + hpa2) < 2GB + * c) hpa2_lo, if hpa1 < 2GB and (hpa1 + hpa2) > 2GB + * (entry5): usable for + * a) hpa2, if hpa1 > 2GB + * b) hpa2_hi, if hpa1 < 2GB and (hpa1 + hpa2) > 2GB + */ +void create_prelaunched_vm_e820(struct acrn_vm *vm) +{ + struct acrn_vm_config *vm_config = get_vm_config(vm->vm_id); + uint64_t gpa_start = 0x100000000UL; + uint64_t hpa1_hi_size, hpa2_lo_size; + uint64_t remaining_hpa2_size = vm_config->memory.size_hpa2; + uint32_t entry_idx = ENTRY_HPA1_HI; + + vm->e820_entries = pre_vm_e820[vm->vm_id]; + (void)memcpy_s((void *)vm->e820_entries, E820_MAX_ENTRIES * sizeof(struct e820_entry), + (const void *)pre_ve820_template, E820_MAX_ENTRIES * sizeof(struct e820_entry)); + + /* sanitize entry for hpa1 */ + if (vm_config->memory.size > MEM_2G) { + /* need to split hpa1 and add an entry for hpa1_hi */ + hpa1_hi_size = vm_config->memory.size - MEM_2G; + gpa_start = add_ram_entry((vm->e820_entries + entry_idx), gpa_start, hpa1_hi_size); + entry_idx++; + } else { + /* need to revise length of hpa1 entry to its actual size */ + vm->e820_entries[ENTRY_HPA1].length = vm_config->memory.size - MEM_1M; + if ((vm_config->memory.size < MEM_2G) + && (remaining_hpa2_size > (MEM_2G - vm_config->memory.size))) { + /* need to split hpa2 and add an entry for hpa2_lo */ + hpa2_lo_size = remaining_hpa2_size - (MEM_2G - vm_config->memory.size); + gpa_start = add_ram_entry((vm->e820_entries + entry_idx), gpa_start, hpa2_lo_size); + remaining_hpa2_size -= hpa2_lo_size; + entry_idx++; + } + } + + /* check whether need an entry for remaining hpa2 */ + if (remaining_hpa2_size > 0UL) { + gpa_start = add_ram_entry((vm->e820_entries + entry_idx), gpa_start, remaining_hpa2_size); + entry_idx++; + } + + vm->e820_entry_num = entry_idx; +} diff --git a/hypervisor/include/arch/x86/guest/vm.h b/hypervisor/include/arch/x86/guest/vm.h index c9515066d..a54a87320 100644 --- a/hypervisor/include/arch/x86/guest/vm.h +++ b/hypervisor/include/arch/x86/guest/vm.h @@ -123,7 +123,7 @@ struct acrn_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 */ uint32_t e820_entry_num; - const struct e820_entry *e820_entries; + struct e820_entry *e820_entries; uint16_t vm_id; /* Virtual machine identifier */ enum vm_state state; /* VM state */ struct acrn_vuart vuart[MAX_VUART_NUM_PER_VM]; /* Virtual UART */