All of lore.kernel.org
 help / color / mirror / Atom feed
From: Daniel Kiper <daniel.kiper@oracle.com>
To: xen-devel@lists.xenproject.org
Cc: jgross@suse.com, sstabellini@kernel.org,
	andrew.cooper3@citrix.com, cardoe@cardoe.com,
	pgnet.dev@gmail.com, ning.sun@intel.com, julien.grall@arm.com,
	david.vrabel@citrix.com, jbeulich@suse.com,
	qiaowei.ren@intel.com, gang.wei@intel.com, fu.wei@linaro.org
Subject: [PATCH v9 06/13] efi: create new early memory allocator
Date: Thu, 29 Sep 2016 23:42:35 +0200	[thread overview]
Message-ID: <1475185362-14198-7-git-send-email-daniel.kiper@oracle.com> (raw)
In-Reply-To: <1475185362-14198-1-git-send-email-daniel.kiper@oracle.com>

There is a problem with place_string() which is used as early memory
allocator. It gets memory chunks starting from start symbol and goes
down. Sadly this does not work when Xen is loaded using multiboot2
protocol because then the start lives on 1 MiB address and we should
not allocate a memory from below of it. So, I tried to use mem_lower
address calculated by GRUB2. However, this solution 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... :-(((
Hence, we need new memory allocator for Xen EFI boot code which is
quite simple and generic and could be used by place_string() and
efi_arch_allocate_mmap_buffer(). I think about following 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
   it in e820 memory map and map it in Xen virtual address space. This
   means that the code referring to Xen command line, loaded modules and
   EFI memory map, mostly in __start_xen(), will be further complicated
   and diverge from legacy BIOS cases. Additionally, both former things
   have to be placed below 4 GiB because their addresses are stored in
   multiboot_info_t structure which has 32-bit relevant members.

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 may 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 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. However, during
   discussion on Xen-devel Jan Beulich suggested that just in case we should
   use 1 MiB memory pool like it is in original place_string() implementation.
   So, let's use 1 MiB as it was proposed. 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().

2a) We could put memory pool into .bss.page_aligned section. Then allocate
    memory chunks starting from the lowest address. After init phase we can
    free unused portion of the memory pool as in case of .init.text or .init.data
    sections. This way we do not need to allocate any space in image file and
    freeing of unused area in the memory pool is very simple.

Now #2a solution is implemented because it is quite simple and requires
limited number of changes, especially in __start_xen().

New allocator is quite generic and can be used on ARM platforms too.
Though it is not enabled on ARM yet due to lack of some prereq.
List of them is placed before ebmalloc code.

Signed-off-by: Daniel Kiper <daniel.kiper@oracle.com>
---
v9 - suggestions/fixes:
   - call free_ebmalloc_unused_mem() from efi_init_memory()
     instead of xen/arch/arm/setup.c:init_done()
     (suggested by Jan Beulich),
   - improve comments.

v8 - suggestions/fixes:
   - disable whole ebmalloc machinery on ARM platforms,
   - add comment saying what should be done before
     enabling ebmalloc on ARM,
     (suggested by Julien Grall),
   - move ebmalloc code before efi-boot.h inclusion and
     remove unneeded forward declaration
     (suggested by Jan Beulich),
   - remove free_ebmalloc_unused_mem() call from
     xen/arch/arm/setup.c:init_done()
     (suggested by Julien Grall),
   - improve commit message.

v7 - suggestions/fixes:
   - enable most of ebmalloc machinery on ARM platforms
     (suggested by Jan Beulich),
   - remove unneeded cast
     (suggested by Jan Beulich),
   - wrap long line
     (suggested by Jan Beulich),
   - improve commit message.

v6 - suggestions/fixes:
   - optimize ebmalloc allocator,
   - move ebmalloc machinery to xen/common/efi/boot.c
     (suggested by Jan Beulich),
   - enforce PAGE_SIZE ebmalloc_mem alignment
     (suggested by Jan Beulich),
   - ebmalloc() must allocate properly
     aligned memory regions
     (suggested by Jan Beulich),
   - printk() should use XENLOG_INFO
     (suggested by Jan Beulich).

v4 - suggestions/fixes:
   - move from #2 solution to #2a solution,
   - improve commit message.
---
 xen/arch/x86/efi/efi-boot.h |   11 +++------
 xen/arch/x86/setup.c        |    3 +--
 xen/common/efi/boot.c       |   52 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 56 insertions(+), 10 deletions(-)

diff --git a/xen/arch/x86/efi/efi-boot.h b/xen/arch/x86/efi/efi-boot.h
index 388c4ea..62c010e 100644
--- a/xen/arch/x86/efi/efi-boot.h
+++ b/xen/arch/x86/efi/efi-boot.h
@@ -114,7 +114,7 @@ static void __init relocate_trampoline(unsigned long phys)
 
 static void __init place_string(u32 *addr, const char *s)
 {
-    static char *__initdata alloc = start;
+    char *alloc = NULL;
 
     if ( s && *s )
     {
@@ -122,7 +122,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 = ebmalloc(len1 + len2);
         /*
          * Insert new string before already existing one. This is needed
          * for options passed on the command line to override options from
@@ -205,12 +205,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 ebmalloc(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 06f3970..9f50eb0 100644
--- a/xen/arch/x86/setup.c
+++ b/xen/arch/x86/setup.c
@@ -1080,8 +1080,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_enabled(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);
diff --git a/xen/common/efi/boot.c b/xen/common/efi/boot.c
index 1ef5d0b..46559f0 100644
--- a/xen/common/efi/boot.c
+++ b/xen/common/efi/boot.c
@@ -98,6 +98,56 @@ static CHAR16 __initdata newline[] = L"\r\n";
 #define PrintStr(s) StdOut->OutputString(StdOut, s)
 #define PrintErr(s) StdErr->OutputString(StdErr, s)
 
+#ifndef CONFIG_ARM
+
+/*
+ * TODO: Enable EFI boot allocator on ARM.
+ * This code can be common for x86 and ARM.
+ * Things TODO on ARM before enabling ebmalloc:
+ *   - estimate required EBMALLOC_SIZE value,
+ *   - where (in which section) ebmalloc_mem[] should live; if in .bss.page_aligned
+ *     then whole BSS zeroing have to be disabled in xen/arch/arm/arm64/head.S;
+ *     though BSS should be initialized somehow before use of variables living there,
+ *   - expose full blown free_ebmalloc_unused_mem() instead of its stub.
+ */
+
+#define EBMALLOC_SIZE	MB(1)
+
+static char __section(".bss.page_aligned") __aligned(PAGE_SIZE)
+    ebmalloc_mem[EBMALLOC_SIZE];
+static unsigned long __initdata ebmalloc_allocated;
+
+/* EFI boot allocator. */
+static void __init *ebmalloc(size_t size)
+{
+    void *ptr = ebmalloc_mem + ebmalloc_allocated;
+
+    ebmalloc_allocated += (size + sizeof(void *) - 1) & ~(sizeof(void *) - 1);
+
+    if ( ebmalloc_allocated > sizeof(ebmalloc_mem) )
+        blexit(L"Out of static memory\r\n");
+
+    return ptr;
+}
+
+static void __init free_ebmalloc_unused_mem(void)
+{
+    unsigned long start, end;
+
+    start = (unsigned long)ebmalloc_mem + PAGE_ALIGN(ebmalloc_allocated);
+    end = (unsigned long)ebmalloc_mem + sizeof(ebmalloc_mem);
+
+    destroy_xen_mappings(start, end);
+    init_xenheap_pages(__pa(start), __pa(end));
+
+    printk(XENLOG_INFO "Freed %lukB unused BSS memory\n", (end - start) >> 10);
+}
+#else
+static void __init free_ebmalloc_unused_mem(void)
+{
+}
+#endif
+
 /*
  * Include architecture specific implementation here, which references the
  * static globals defined above.
@@ -1251,6 +1301,8 @@ void __init efi_init_memory(void)
     } *extra, *extra_head = NULL;
 #endif
 
+    free_ebmalloc_unused_mem();
+
     if ( !efi_enabled(EFI_BOOT) )
         return;
 
-- 
1.7.10.4


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

  parent reply	other threads:[~2016-09-29 21:43 UTC|newest]

Thread overview: 40+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-09-29 21:42 [PATCH v9 00/13] x86: multiboot2 protocol support Daniel Kiper
2016-09-29 21:42 ` [PATCH v9 01/13] x86: add " Daniel Kiper
2016-09-29 21:42 ` [PATCH v9 02/13] efi: create efi_enabled() Daniel Kiper
2016-09-29 21:42 ` [PATCH v9 03/13] x86: allow EFI reboot method neither on EFI platforms Daniel Kiper
2016-09-29 21:42 ` [PATCH v9 04/13] x86: properly calculate xen ELF end of image address Daniel Kiper
2016-09-30  9:43   ` Jan Beulich
2016-09-29 21:42 ` [PATCH v9 05/13] efi: build xen.gz with EFI code Daniel Kiper
2016-09-29 21:42 ` Daniel Kiper [this message]
2016-09-30  9:46   ` [PATCH v9 06/13] efi: create new early memory allocator Jan Beulich
2016-09-30 10:49     ` Daniel Kiper
2016-10-05  7:02     ` Daniel Kiper
2016-10-05 15:45       ` Julien Grall
2016-10-05 18:30     ` Julien Grall
2016-10-06 12:21       ` Jan Beulich
2016-10-11 13:39         ` Julien Grall
2016-10-12 11:45           ` Jan Beulich
2016-10-12 12:51             ` Julien Grall
2016-10-12 12:59               ` Jan Beulich
2016-10-24  9:03                 ` Daniel Kiper
2016-10-24  9:57                   ` Jan Beulich
2016-11-03 13:48                     ` Daniel Kiper
2016-11-10 10:34                       ` Daniel Kiper
2016-10-31 13:32                 ` Julien Grall
2016-09-29 21:42 ` [PATCH v9 07/13] x86: add multiboot2 protocol support for EFI platforms Daniel Kiper
2016-11-23 18:52   ` Andrew Cooper
2016-11-24 11:08     ` Jan Beulich
2016-11-24 21:44       ` Daniel Kiper
2016-11-25  7:50         ` Jan Beulich
2016-11-30 13:45           ` Daniel Kiper
2016-11-30 13:59             ` Jan Beulich
2016-11-30 17:21               ` Daniel Kiper
2016-11-24 21:31     ` Daniel Kiper
2016-09-29 21:42 ` [PATCH v9 08/13] x86/boot: implement early command line parser in C Daniel Kiper
2016-09-29 21:42 ` [PATCH v9 09/13] x86: change default load address from 1 MiB to 2 MiB Daniel Kiper
2016-09-30 10:02   ` Jan Beulich
2016-09-29 21:42 ` [PATCH v9 10/13] x86/setup: use XEN_IMG_OFFSET instead of Daniel Kiper
2016-09-29 21:42 ` [PATCH v9 11/13] x86: make Xen early boot code relocatable Daniel Kiper
2016-09-29 21:42 ` [PATCH v9 12/13] x86/boot: rename sym_phys() to sym_offs() Daniel Kiper
2016-09-29 21:42 ` [PATCH v9 13/13] x86: add multiboot2 protocol support for relocatable images Daniel Kiper
2016-09-30 10:03   ` Jan Beulich

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1475185362-14198-7-git-send-email-daniel.kiper@oracle.com \
    --to=daniel.kiper@oracle.com \
    --cc=andrew.cooper3@citrix.com \
    --cc=cardoe@cardoe.com \
    --cc=david.vrabel@citrix.com \
    --cc=fu.wei@linaro.org \
    --cc=gang.wei@intel.com \
    --cc=jbeulich@suse.com \
    --cc=jgross@suse.com \
    --cc=julien.grall@arm.com \
    --cc=ning.sun@intel.com \
    --cc=pgnet.dev@gmail.com \
    --cc=qiaowei.ren@intel.com \
    --cc=sstabellini@kernel.org \
    --cc=xen-devel@lists.xenproject.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.