hv: add memory allocation functions for trampoline code relocation

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 <gen.zheng@intel.com>
Signed-off-by: Jason Chen CJ <jason.cj.chen@intel.com>
Signed-off-by: Zide Chen <zide.chen@intel.com>
Acked-by: Eddie Dong <eddie.dong@intel.com>
Acked-by: Xu, Anthony <anthony.xu@intel.com>
This commit is contained in:
Zide Chen 2018-05-02 23:21:07 -07:00 committed by lijinxia
parent 1f074a2f2a
commit 77580edff0
4 changed files with 114 additions and 0 deletions

View File

@ -603,6 +603,59 @@ 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 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;
/* Search for available low memory */
if ((entry->type != E820_TYPE_RAM)
|| (length < size)
|| (start + size > MEM_1M)) {
continue;
}
/* found exact size of e820 entry */
if (length == size) {
entry->type = E820_TYPE_RESERVED;
e820_mem.total_mem_size -= size;
return start;
}
/*
* found entry with available memory larger than requested
* alocate memory from the end of this entry at page boundary
*/
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;
/* Shrink the existing entry and total available memory */
entry->length -= new_entry->length;
e820_mem.total_mem_size -= new_entry->length;
e820_entries++;
return new_entry->baseaddr;
}
pr_fatal("Can't allocate memory under 1M from E820\n");
return ACRN_INVALID_HPA;
}
#ifdef CONFIG_START_VM0_BSP_64BIT
/*******************************************************************
* GUEST initial page table

View File

@ -164,6 +164,65 @@ 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 = nr_pages << EFI_PAGE_SHIFT;
/* allocate in low memory only */
if (start >= 1 << 20)
continue;
if (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.

View File

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

View File

@ -60,6 +60,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 {