[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH 17/18] x86/efi: create new early memory allocator
From: |
Daniel Kiper |
Subject: |
[PATCH 17/18] x86/efi: create new early memory allocator |
Date: |
Fri, 30 Jan 2015 18:54:21 +0100 |
There is a problem with place_string() which is used as early memory
allocator. It gets memory chunks starting from start symbol and
going down. Sadly this does not work when Xen is loaded using multiboot2
protocol because start lives on 1 MiB address. So, I tried to use
mem_lower address calculated by GRUB2. However, it works only on some
machines. There are machines in the wild (e.g. Dell PowerEdge R820)
which uses first ~640 KiB for boot services code or data... :-(((
In case of multiboot2 protocol we need that place_string() only allocate
memory chunk for EFI memory map. However, I think that it should be fixed
instead of making another function used just in one case. I thought about
two solutions.
1) We could use native EFI allocation functions (e.g. AllocatePool()
or AllocatePages()) to get memory chunk. However, later (somewhere
in __start_xen()) we must copy its contents to safe place or reserve
this in e820 memory map and map it in Xen virtual address space.
In later case we must also care about conflicts with e.g. crash
kernel regions which could be quite difficult.
2) We may allocate memory area statically somewhere in Xen code which
could be used as memory pool for early dynamic allocations. Looks
quite simple. Additionally, it would not depend on EFI at all and
could be used on legacy BIOS platforms if we need it. However, we
must carefully choose size of this pool. We do not want increase
Xen binary size too much and waste too much memory but also we must fit
at least memory map on x86 EFI platforms. As I saw on small machine,
e.g. IBM System x3550 M2 with 8 GiB RAM, memory map my contain more
than 200 entries. Every entry on x86-64 platform is 40 bytes in size.
So, it means that we need more than 8 KiB for EFI memory map only.
Additionally, if we want to use this memory pool for Xen and modules
command line storage (it would be used when xen.efi is executed as EFI
application) then we should add, I think, about 1 KiB. In this case,
to be on safe side, we should assume at least 64 KiB pool for early
memory allocations, which is about 4 times of our earlier calculations.
If we think that we should not waste unallocated memory in the pool
on running system then we can mark this region as __initdata and move
all required data to dynamically allocated places somewhere in __start_xen().
Now solution #2 is implemented but maybe we should consider #1 too.
Signed-off-by: Daniel Kiper <address@hidden>
---
xen/arch/x86/efi/efi-boot.h | 37 +++++++++++++++++++++++++++++--------
xen/arch/x86/setup.c | 3 +--
2 files changed, 30 insertions(+), 10 deletions(-)
diff --git a/xen/arch/x86/efi/efi-boot.h b/xen/arch/x86/efi/efi-boot.h
index 3a3b4fe..6e98bc8 100644
--- a/xen/arch/x86/efi/efi-boot.h
+++ b/xen/arch/x86/efi/efi-boot.h
@@ -103,9 +103,35 @@ static void __init relocate_trampoline(unsigned long phys)
*(u16 *)(*trampoline_ptr + (long)trampoline_ptr) = phys >> 4;
}
+#define __MALLOC_SIZE 65536
+
+static char __malloc_mem[__MALLOC_SIZE];
+static char *__malloc_free = NULL;
+
+static void __init *__malloc(size_t size)
+{
+ void *ptr;
+
+ /*
+ * Init __malloc_free on runtime. Static initialization
+ * will not work because it puts virtual address there.
+ */
+ if ( __malloc_free == NULL )
+ __malloc_free = __malloc_mem;
+
+ ptr = __malloc_free;
+
+ __malloc_free += size;
+
+ if ( __malloc_free - __malloc_mem > sizeof(__malloc_mem) )
+ blexit(L"Out of static memory\r\n");
+
+ return ptr;
+}
+
static void __init place_string(u32 *addr, const char *s)
{
- static char *__initdata alloc = start;
+ char *alloc = NULL;
if ( s && *s )
{
@@ -113,7 +139,7 @@ static void __init place_string(u32 *addr, const char *s)
const char *old = (char *)(long)*addr;
size_t len2 = *addr ? strlen(old) + 1 : 0;
- alloc -= len1 + len2;
+ alloc = __malloc(len1 + len2);
/*
* Insert new string before already existing one. This is needed
* for options passed on the command line to override options from
@@ -192,12 +218,7 @@ static void __init
efi_arch_process_memory_map(EFI_SYSTEM_TABLE *SystemTable,
static void *__init efi_arch_allocate_mmap_buffer(UINTN *map_size)
{
- place_string(&mbi.mem_upper, NULL);
- mbi.mem_upper -= *map_size;
- mbi.mem_upper &= -__alignof__(EFI_MEMORY_DESCRIPTOR);
- if ( mbi.mem_upper < xen_phys_start )
- return NULL;
- return (void *)(long)mbi.mem_upper;
+ return __malloc(*map_size);
}
static void __init efi_arch_pre_exit_boot(void)
diff --git a/xen/arch/x86/setup.c b/xen/arch/x86/setup.c
index 711fdb0..aebd010 100644
--- a/xen/arch/x86/setup.c
+++ b/xen/arch/x86/setup.c
@@ -962,8 +962,7 @@ void __init noreturn __start_xen(unsigned long mbi_p)
if ( !xen_phys_start )
panic("Not enough memory to relocate Xen.");
- reserve_e820_ram(&boot_e820, efi_loader ? mbi->mem_upper : __pa(&_start),
- __pa(&_end));
+ reserve_e820_ram(&boot_e820, __pa(&_start), __pa(&_end));
/* Late kexec reservation (dynamic start address). */
kexec_reserve_area(&boot_e820);
--
1.7.10.4
- [PATCH 08/18] efi: build xen.gz with EFI code, (continued)
- [PATCH 08/18] efi: build xen.gz with EFI code, Daniel Kiper, 2015/01/30
- [PATCH 07/18] efi: run EFI specific code on EFI platform only, Daniel Kiper, 2015/01/30
- [PATCH 12/18] efi: create efi_find_gop_mode(), Daniel Kiper, 2015/01/30
- [PATCH 09/18] efi: create efi_init(), Daniel Kiper, 2015/01/30
- [PATCH 10/18] efi: create efi_console_set_mode(), Daniel Kiper, 2015/01/30
- [PATCH 11/18] efi: create efi_get_gop(), Daniel Kiper, 2015/01/30
- [PATCH 13/18] efi: create efi_tables(), Daniel Kiper, 2015/01/30
- [PATCH 14/18] efi: create efi_variables(), Daniel Kiper, 2015/01/30
- [PATCH 16/18] efi: create efi_exit_boot(), Daniel Kiper, 2015/01/30
- [PATCH 15/18] efi: create efi_set_gop_mode(), Daniel Kiper, 2015/01/30
- [PATCH 17/18] x86/efi: create new early memory allocator,
Daniel Kiper <=
- [PATCH 18/18] x86: add multiboot2 protocol support for EFI platforms, Daniel Kiper, 2015/01/30
- Re: [PATCH 00/18] x86: multiboot2 protocol support, Daniel Kiper, 2015/01/30
- Re: [PATCH 00/18] x86: multiboot2 protocol support, João Jerónimo, 2015/01/31