From bf22e8f194f75a1489ddf49f2899d4d24893f3e7 Mon Sep 17 00:00:00 2001 From: Victor Sun Date: Fri, 14 May 2021 14:43:15 +0800 Subject: [PATCH] HV: add find_space_from_ve820() api The API would search ve820 table and return a valid GPA when the requested size of memory is available in the specified memory range, or return INVALID_GPA if the requested memory slot is not available; Tracked-On: #5626 Signed-off-by: Victor Sun Reviewed-by: Jason Chen CJ --- hypervisor/arch/x86/guest/ve820.c | 52 ++++++++++++++++++++++ hypervisor/include/arch/x86/asm/guest/vm.h | 1 + 2 files changed, 53 insertions(+) diff --git a/hypervisor/arch/x86/guest/ve820.c b/hypervisor/arch/x86/guest/ve820.c index 7e1eee213..5724ed98e 100644 --- a/hypervisor/arch/x86/guest/ve820.c +++ b/hypervisor/arch/x86/guest/ve820.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -19,6 +20,55 @@ static struct e820_entry sos_vm_e820[E820_MAX_ENTRIES]; static struct e820_entry pre_vm_e820[PRE_VM_NUM][E820_MAX_ENTRIES]; +uint64_t find_space_from_ve820(struct acrn_vm *vm, uint32_t size, uint64_t min_addr, uint64_t max_addr) +{ + int32_t i; + uint64_t gpa = INVALID_GPA; + uint64_t round_min_addr = round_page_up(min_addr); + uint64_t round_max_addr = round_page_down(max_addr); + uint32_t round_size = round_page_up(size); + + for (i = (int32_t)(vm->e820_entry_num - 1U); i >= 0; i--) { + struct e820_entry *entry = vm->e820_entries + i; + uint64_t start, end, length; + + start = round_page_up(entry->baseaddr); + end = round_page_down(entry->baseaddr + entry->length); + length = (end > start) ? (end - start) : 0UL; + + if ((entry->type == E820_TYPE_RAM) && (length >= round_size) + && (end > round_min_addr) && (start < round_max_addr)) { + if (((start >= min_addr) && ((start + round_size) <= min(end, round_max_addr))) + || ((start < min_addr) && ((min_addr + round_size) <= min(end, round_max_addr)))) { + gpa = (end > round_max_addr) ? (round_max_addr - round_size) : (end - round_size); + break; + } + } + } + return gpa; +} + +/* a sorted VM e820 table is critical for memory allocation or slot location, + * for example, put ramdisk at the end of TOLUD(Top of LOW Usable DRAM) and + * put kernel at its begining so that provide largest load capicity for them. + */ +static void sort_vm_e820(struct acrn_vm *vm) +{ + uint32_t i,j; + struct e820_entry tmp_entry; + + /* Bubble sort */ + for (i = 0U; i < (vm->e820_entry_num - 1U); i++) { + for (j = 0U; j < (vm->e820_entry_num - i - 1U); j++) { + if (vm->e820_entries[j].baseaddr > vm->e820_entries[j + 1U].baseaddr) { + tmp_entry = vm->e820_entries[j]; + vm->e820_entries[j] = vm->e820_entries[j + 1U]; + vm->e820_entries[j + 1U] = tmp_entry; + } + } + } +} + static void filter_mem_from_sos_e820(struct acrn_vm *vm, uint64_t start_pa, uint64_t end_pa) { uint32_t i; @@ -122,6 +172,7 @@ void create_sos_vm_e820(struct acrn_vm *vm) sos_vm_config->memory.size += entry->length; } } + sort_vm_e820(vm); } static const struct e820_entry pre_ve820_template[E820_MAX_ENTRIES] = { @@ -274,4 +325,5 @@ void create_prelaunched_vm_e820(struct acrn_vm *vm) } vm->e820_entry_num = entry_idx; + sort_vm_e820(vm); } diff --git a/hypervisor/include/arch/x86/asm/guest/vm.h b/hypervisor/include/arch/x86/asm/guest/vm.h index 72197c1e6..1d2d64c5b 100644 --- a/hypervisor/include/arch/x86/asm/guest/vm.h +++ b/hypervisor/include/arch/x86/asm/guest/vm.h @@ -248,6 +248,7 @@ struct acrn_vm *get_sos_vm(void); void create_sos_vm_e820(struct acrn_vm *vm); void create_prelaunched_vm_e820(struct acrn_vm *vm); +uint64_t find_space_from_ve820(struct acrn_vm *vm, uint32_t size, uint64_t min_addr, uint64_t max_addr); int32_t vm_sw_loader(struct acrn_vm *vm);