From ceb3076b6980ab70f2524e018cde8e65d5d3f342 Mon Sep 17 00:00:00 2001 From: Zide Chen Date: Wed, 2 May 2018 23:21:07 -0700 Subject: [PATCH] HV: added memory allocation functions for AP trampoline code relocation V2->V3: Fixed the booting issue on MRB board and removed the restriction of allocate memory from address 0 1) Fix the booting from MRB issue -#define CONFIG_LOW_RAM_SIZE 0x000CF000 +#define CONFIG_LOW_RAM_SIZE 0x00010000 2) changed e820_alloc_low_memory() to handle corner case of unaligned e820 entries and enable it to allocate memory at address 0 + a length = end > start ? (end - start) : 0; - /* We don't want the first page */ - if ((length == size) && (start == 0)) - continue; 3) changed emalloc_for_low_mem() to enable to allocate memory at address 0 - /* We don't want the first page */ - if (start == 0) - start = EFI_PAGE_SIZE; V1->V2: moved e820_alloc_low_memory() to guest.c and added the logic to handle unaligned E820 entries emalloc_for_low_mem() is used if CONFIG_EFI_STUB is defined. e820_alloc_low_memory() is used for other cases In either case, the allocated memory will be marked with E820_TYPE_RESERVED Signed-off-by: Zheng, Gen Signed-off-by: Jason Chen CJ Signed-off-by: Zide Chen Acked-by: Eddie Dong Acked-by: Xu, Anthony --- hypervisor/arch/x86/guest/guest.c | 48 ++++++++++++++++++ hypervisor/bsp/sbl/include/bsp/bsp_cfg.h | 2 +- hypervisor/bsp/uefi/efi/malloc.c | 61 +++++++++++++++++++++++ hypervisor/bsp/uefi/efi/stdlib.h | 1 + hypervisor/include/arch/x86/guest/guest.h | 1 + 5 files changed, 112 insertions(+), 1 deletion(-) diff --git a/hypervisor/arch/x86/guest/guest.c b/hypervisor/arch/x86/guest/guest.c index 3ad100043..59bc93d87 100644 --- a/hypervisor/arch/x86/guest/guest.c +++ b/hypervisor/arch/x86/guest/guest.c @@ -341,6 +341,54 @@ int prepare_vm0_memmap_and_e820(struct vm *vm) return 0; } +uint64_t e820_alloc_low_memory(uint32_t size) +{ + uint32_t i; + struct e820_entry *entry, *new_entry; + + /* We want memory in page boundary and want integral multiple of pages */ + size = ROUND_PAGE_UP(size); + + for (i = 0; i < e820_entries; i++) { + entry = &e820[i]; + uint64_t start, end, length; + + start = ROUND_PAGE_UP(entry->baseaddr); + end = ROUND_PAGE_DOWN(entry->baseaddr + entry->length); + length = end - start; + length = (end > start) ? (end - start) : 0; + + if ((entry->type != E820_TYPE_RAM) + || (length < size) + || (start >= MEM_1M) + || (start + size > MEM_1M)) { + continue; + } + + /* Found available memory */ + e820_mem.total_mem_size -= size; + + /* found exact size of e820 entry */ + if (length == size) { + entry->type = E820_TYPE_RESERVED; + return start; + } + + /* create a new entry for the allocated memory */ + new_entry = &e820[e820_entries]; + new_entry->type = E820_TYPE_RESERVED; + new_entry->baseaddr = end - size; + new_entry->length = entry->baseaddr + entry->length - new_entry->baseaddr; + entry->length -= new_entry->length; + e820_entries++; + + return new_entry->baseaddr; + } + + pr_fatal("Can't allocate memory under 1M from E820\n"); + return ACRN_INVALID_HPA; +} + /******************************************************************* * GUEST initial page table * diff --git a/hypervisor/bsp/sbl/include/bsp/bsp_cfg.h b/hypervisor/bsp/sbl/include/bsp/bsp_cfg.h index b39dd7d2f..9721da315 100644 --- a/hypervisor/bsp/sbl/include/bsp/bsp_cfg.h +++ b/hypervisor/bsp/sbl/include/bsp/bsp_cfg.h @@ -41,7 +41,7 @@ #define HEAP_SIZE 0x100000 #define CONSOLE_LOGLEVEL_DEFAULT 2 #define MEM_LOGLEVEL_DEFAULT 4 -#define CONFIG_LOW_RAM_SIZE 0x000CF000 +#define CONFIG_LOW_RAM_SIZE 0x00010000 #define CONFIG_RAM_START 0x6E000000 #define CONFIG_RAM_SIZE 0x02000000 /* 32M */ #define CONFIG_CMA diff --git a/hypervisor/bsp/uefi/efi/malloc.c b/hypervisor/bsp/uefi/efi/malloc.c index 879f7d62c..b5934b48b 100644 --- a/hypervisor/bsp/uefi/efi/malloc.c +++ b/hypervisor/bsp/uefi/efi/malloc.c @@ -164,6 +164,67 @@ fail: return err; } +EFI_STATUS emalloc_for_low_mem(EFI_PHYSICAL_ADDRESS *addr, UINTN size) +{ + UINTN map_size, map_key, desc_size; + EFI_MEMORY_DESCRIPTOR *map_buf; + UINTN d, map_end; + UINT32 desc_version; + EFI_STATUS err; + UINTN nr_pages = EFI_SIZE_TO_PAGES(size); + + err = memory_map(&map_buf, &map_size, &map_key, + &desc_size, &desc_version); + + if (err != EFI_SUCCESS) + goto fail; + + d = (UINTN)map_buf; + map_end = (UINTN)map_buf + map_size; + + for (; d < map_end; d += desc_size) { + EFI_MEMORY_DESCRIPTOR *desc; + EFI_PHYSICAL_ADDRESS start, end, aligned; + + desc = (EFI_MEMORY_DESCRIPTOR *)d; + if (desc->Type != EfiConventionalMemory) + continue; + + if (desc->NumberOfPages < nr_pages) + continue; + + start = desc->PhysicalStart; + end = start + (desc->NumberOfPages << EFI_PAGE_SHIFT); + size = (size + EFI_PAGE_SIZE - 1) & ~(EFI_PAGE_SIZE - 1); + + /* allocate in low memory only */ + if (start >= 1 << 20) + continue; + + if (end > 1 << 20) { + size -= end - (1 << 20); + end = (1 << 20); + } + + if (end - start >= size) { + aligned = end - size; + err = allocate_pages(AllocateAddress, EfiReservedMemoryType, + nr_pages, &aligned); + if (err == EFI_SUCCESS) { + *addr = aligned; + break; + } + } + } + + if (d == map_end) + err = EFI_OUT_OF_RESOURCES; + + free_pool(map_buf); +fail: + return err; +} + /* FIXME: This function cannot guarantee to return address under 4G, * and the hypervisor cannot handle params, which address is above 4G, * delivered from efi stub. diff --git a/hypervisor/bsp/uefi/efi/stdlib.h b/hypervisor/bsp/uefi/efi/stdlib.h index 843dc1fc4..0fcf539f6 100644 --- a/hypervisor/bsp/uefi/efi/stdlib.h +++ b/hypervisor/bsp/uefi/efi/stdlib.h @@ -50,6 +50,7 @@ extern void *calloc(UINTN nmemb, UINTN size); extern EFI_STATUS emalloc(UINTN, UINTN, EFI_PHYSICAL_ADDRESS *); extern EFI_STATUS __emalloc(UINTN, UINTN, EFI_PHYSICAL_ADDRESS *, EFI_MEMORY_TYPE); +extern EFI_STATUS emalloc_for_low_mem(EFI_PHYSICAL_ADDRESS *addr, UINTN size); extern void efree(EFI_PHYSICAL_ADDRESS, UINTN); static inline void memset(void *dstv, char ch, UINTN size) diff --git a/hypervisor/include/arch/x86/guest/guest.h b/hypervisor/include/arch/x86/guest/guest.h index f7199a991..dabeb1e89 100644 --- a/hypervisor/include/arch/x86/guest/guest.h +++ b/hypervisor/include/arch/x86/guest/guest.h @@ -68,6 +68,7 @@ struct e820_mem_params { }; int prepare_vm0_memmap_and_e820(struct vm *vm); +uint64_t e820_alloc_low_memory(uint32_t size); /* Definition for a mem map lookup */ struct vm_lu_mem_map {