Skip to content

Commit 77580ed

Browse files
ZideChen0lijinxia
authored andcommitted
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>
1 parent 1f074a2 commit 77580ed

File tree

4 files changed

+114
-0
lines changed

4 files changed

+114
-0
lines changed

hypervisor/arch/x86/guest/guest.c

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -603,6 +603,59 @@ int prepare_vm0_memmap_and_e820(struct vm *vm)
603603
return 0;
604604
}
605605

606+
uint64_t e820_alloc_low_memory(uint32_t size)
607+
{
608+
uint32_t i;
609+
struct e820_entry *entry, *new_entry;
610+
611+
/* We want memory in page boundary and integral multiple of pages */
612+
size = ROUND_PAGE_UP(size);
613+
614+
for (i = 0; i < e820_entries; i++) {
615+
entry = &e820[i];
616+
uint64_t start, end, length;
617+
618+
start = ROUND_PAGE_UP(entry->baseaddr);
619+
end = ROUND_PAGE_DOWN(entry->baseaddr + entry->length);
620+
length = end - start;
621+
length = (end > start) ? (end - start) : 0;
622+
623+
/* Search for available low memory */
624+
if ((entry->type != E820_TYPE_RAM)
625+
|| (length < size)
626+
|| (start + size > MEM_1M)) {
627+
continue;
628+
}
629+
630+
/* found exact size of e820 entry */
631+
if (length == size) {
632+
entry->type = E820_TYPE_RESERVED;
633+
e820_mem.total_mem_size -= size;
634+
return start;
635+
}
636+
637+
/*
638+
* found entry with available memory larger than requested
639+
* alocate memory from the end of this entry at page boundary
640+
*/
641+
new_entry = &e820[e820_entries];
642+
new_entry->type = E820_TYPE_RESERVED;
643+
new_entry->baseaddr = end - size;
644+
new_entry->length = entry->baseaddr +
645+
entry->length - new_entry->baseaddr;
646+
647+
/* Shrink the existing entry and total available memory */
648+
entry->length -= new_entry->length;
649+
e820_mem.total_mem_size -= new_entry->length;
650+
e820_entries++;
651+
652+
return new_entry->baseaddr;
653+
}
654+
655+
pr_fatal("Can't allocate memory under 1M from E820\n");
656+
return ACRN_INVALID_HPA;
657+
}
658+
606659
#ifdef CONFIG_START_VM0_BSP_64BIT
607660
/*******************************************************************
608661
* GUEST initial page table

hypervisor/bsp/uefi/efi/malloc.c

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,65 @@ EFI_STATUS emalloc(UINTN size, UINTN align, EFI_PHYSICAL_ADDRESS *addr)
164164
return err;
165165
}
166166

167+
EFI_STATUS emalloc_for_low_mem(EFI_PHYSICAL_ADDRESS *addr, UINTN size)
168+
{
169+
UINTN map_size, map_key, desc_size;
170+
EFI_MEMORY_DESCRIPTOR *map_buf;
171+
UINTN d, map_end;
172+
UINT32 desc_version;
173+
EFI_STATUS err;
174+
UINTN nr_pages = EFI_SIZE_TO_PAGES(size);
175+
176+
err = memory_map(&map_buf, &map_size, &map_key,
177+
&desc_size, &desc_version);
178+
179+
if (err != EFI_SUCCESS)
180+
goto fail;
181+
182+
d = (UINTN)map_buf;
183+
map_end = (UINTN)map_buf + map_size;
184+
185+
for (; d < map_end; d += desc_size) {
186+
EFI_MEMORY_DESCRIPTOR *desc;
187+
EFI_PHYSICAL_ADDRESS start, end, aligned;
188+
189+
desc = (EFI_MEMORY_DESCRIPTOR *)d;
190+
if (desc->Type != EfiConventionalMemory)
191+
continue;
192+
193+
if (desc->NumberOfPages < nr_pages)
194+
continue;
195+
196+
start = desc->PhysicalStart;
197+
end = start + (desc->NumberOfPages << EFI_PAGE_SHIFT);
198+
size = nr_pages << EFI_PAGE_SHIFT;
199+
200+
/* allocate in low memory only */
201+
if (start >= 1 << 20)
202+
continue;
203+
204+
if (end > 1 << 20)
205+
end = (1 << 20);
206+
207+
if (end - start >= size) {
208+
aligned = end - size;
209+
err = allocate_pages(AllocateAddress, EfiReservedMemoryType,
210+
nr_pages, &aligned);
211+
if (err == EFI_SUCCESS) {
212+
*addr = aligned;
213+
break;
214+
}
215+
}
216+
}
217+
218+
if (d == map_end)
219+
err = EFI_OUT_OF_RESOURCES;
220+
221+
free_pool(map_buf);
222+
fail:
223+
return err;
224+
}
225+
167226
/* FIXME: This function cannot guarantee to return address under 4G,
168227
* and the hypervisor cannot handle params, which address is above 4G,
169228
* delivered from efi stub.

hypervisor/bsp/uefi/efi/stdlib.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ extern void *calloc(UINTN nmemb, UINTN size);
5050

5151
extern EFI_STATUS emalloc(UINTN, UINTN, EFI_PHYSICAL_ADDRESS *);
5252
extern EFI_STATUS __emalloc(UINTN, UINTN, EFI_PHYSICAL_ADDRESS *, EFI_MEMORY_TYPE);
53+
extern EFI_STATUS emalloc_for_low_mem(EFI_PHYSICAL_ADDRESS *addr, UINTN size);
5354
extern void efree(EFI_PHYSICAL_ADDRESS, UINTN);
5455

5556
static inline void memset(void *dstv, char ch, UINTN size)

hypervisor/include/arch/x86/guest/guest.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ struct e820_mem_params {
6060
};
6161

6262
int prepare_vm0_memmap_and_e820(struct vm *vm);
63+
uint64_t e820_alloc_low_memory(uint32_t size);
6364

6465
/* Definition for a mem map lookup */
6566
struct vm_lu_mem_map {

0 commit comments

Comments
 (0)