From patchwork Fri Jan 13 19:21:48 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Douglas Goldstein X-Patchwork-Id: 9516299 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 579706077E for ; Fri, 13 Jan 2017 19:24:41 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 4136C2876B for ; Fri, 13 Jan 2017 19:24:41 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 354DC2876E; Fri, 13 Jan 2017 19:24:41 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-3.6 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_MED,RCVD_IN_SORBS_SPAM,T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 165902876B for ; Fri, 13 Jan 2017 19:24:40 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1cS7QR-0003iP-5l; Fri, 13 Jan 2017 19:22:11 +0000 Received: from mail6.bemta3.messagelabs.com ([195.245.230.39]) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1cS7QP-0003hE-Ut for xen-devel@lists.xen.org; Fri, 13 Jan 2017 19:22:10 +0000 Received: from [85.158.137.68] by server-5.bemta-3.messagelabs.com id 57/5E-19998-1E829785; Fri, 13 Jan 2017 19:22:09 +0000 X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFtrHIsWRWlGSWpSXmKPExsVyMfTqEd0HGpU RBrOf8Vks+biYxYHR4+ju30wBjFGsmXlJ+RUJrBkLjh5lK1jpXbHqVD9bA+MFmy5GLg4hgUmM ElOvzGMDcVgE9jNLPJ6+DMyREFjGKvF8exN7FyMnkBMjcWrBLGYIu1Ri0cYbYHEhAQWJ3xMOM UGMWs4kcfLNe7AEm4CGxJNfM9hAbBEBaYlrny8zghQxCzxhklixD6JIWMBaouHLYzCbRUBVYv rub0wgNq9AnMTjm9fYILbJSyw8fwQozsHBKZAq0bWYBWJxisSXszMZcQhPYBRawMiwilGjOLW oLLVI19BIL6koMz2jJDcxM0fX0MBYLze1uDgxPTUnMalYLzk/dxMjMBQZgGAH46tu50OMkhxM SqK831UrIoT4kvJTKjMSizPii0pzUosPMcpwcChJ8F5Tr4wQEixKTU+tSMvMAUYFTFqCg0dJh DcTJM1bXJCYW5yZDpE6xWjM0dN1+iUTx55dl18yCbHk5eelSonzXgUpFQApzSjNgxsEi9ZLjL JSwryMQKcJ8RSkFuVmlqDKv2IU52BUEuYtA5nCk5lXArfvFdApTECnXLQpBzmlJBEhJdXAWCW ybUPhkiPfk7sP95oul2ifxOx3TSHWdskvi0clooXl8Z4HFAr/fs+qPmYxO/L73jP5LIypO9S+ al8M5whKVJWWdt0V3c4z0UL6EHtUiOWVDlftiRbdDH99DziZHTG8rSu/eck3rk9n3rzZyOnGu JU5xGvD5kunv3/0e+ByaFft+njJfb4lSizFGYmGWsxFxYkAxSl08NECAAA= X-Env-Sender: cardoe@cardoe.com X-Msg-Ref: server-12.tower-31.messagelabs.com!1484335327!63704476!1 X-Originating-IP: [209.85.213.196] X-SpamReason: No, hits=0.5 required=7.0 tests=BODY_RANDOM_LONG X-StarScan-Received: X-StarScan-Version: 9.1.1; banners=-,-,- X-VirusChecked: Checked Received: (qmail 46284 invoked from network); 13 Jan 2017 19:22:08 -0000 Received: from mail-yb0-f196.google.com (HELO mail-yb0-f196.google.com) (209.85.213.196) by server-12.tower-31.messagelabs.com with AES128-GCM-SHA256 encrypted SMTP; 13 Jan 2017 19:22:08 -0000 Received: by mail-yb0-f196.google.com with SMTP id w194so2135012ybe.1 for ; Fri, 13 Jan 2017 11:22:07 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cardoe.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :in-reply-to:references; bh=dGBEn48wpABEC123HtWyDg3oXX3nEW6v9svzfXjNlRY=; b=D8tRSMosubWABR3Hu668xiPahLB/m7Wrh4obt65DIAI1E0hOVBK606vEAO45Omd6z5 Gz1WQXViViw5/bpis46ngpDSvAcU/Cs7pOi5PPc6cm2eZpmr9NO4qYEJLEZ79moUgAmF oHIwQNfRHPgFFBeJNpk7rpmAoono6ZAVLi1D0= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:in-reply-to:references; bh=dGBEn48wpABEC123HtWyDg3oXX3nEW6v9svzfXjNlRY=; b=sJfq6LDG37iSfI5jAG0OX6TyBJhPGh+Wv2HGs2gfPGcdOVgxxsEtoqZKgX57UawCjO h2sWLNZaMFOdHqL5vJfvbbr5Brg/aPRgmOhH8kTsqrjs6seQoUHMoUZ6EG/8WQS7IH70 vnEMwmFMM56zzY4Y7pp2tDoLtJosu75L1tD/Huwh+6HRCKowdPkV4MQU22jL9MX5H57Q aF55yv3j4dtQssRbbFEf8kWccRmno6TKuFo+o8pCjG3tKtwDpIdGPRHm5mqqR/r+Li4W X2bESEdwKK7fnMCnfMLJT7BtVQ2p6U2MvxbBZLVNHU4hyFhjQnL76UFhNVyUk7E19FYT +q8w== X-Gm-Message-State: AIkVDXI8KNMw2/jg/rT4+aPq8OKRmqFQYOQ3ZF6Uw4ZAxn228T0853d4GDCgBnZoWFARLw== X-Received: by 10.37.1.67 with SMTP id 64mr5896799ybb.24.1484335326590; Fri, 13 Jan 2017 11:22:06 -0800 (PST) Received: from swanson.attlocal.net (104-179-196-18.lightspeed.brhmal.sbcglobal.net. [104.179.196.18]) by smtp.gmail.com with ESMTPSA id p3sm5534168ywc.22.2017.01.13.11.22.05 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 13 Jan 2017 11:22:06 -0800 (PST) From: Doug Goldstein To: xen-devel@lists.xen.org Date: Fri, 13 Jan 2017 13:21:48 -0600 Message-Id: X-Mailer: git-send-email 2.10.2 In-Reply-To: References: In-Reply-To: References: Cc: jgross@suse.com, sstabellini@kernel.org, konrad.wilk@oracle.com, Andrew Cooper , Daniel Kiper , Doug Goldstein , pgnet.dev@gmail.com, ning.sun@intel.com, julien.grall@arm.com, Jan Beulich , qiaowei.ren@intel.com, gang.wei@intel.com, fu.wei@linaro.org Subject: [Xen-devel] [PATCH 3/4] efi: create new early memory allocator X-BeenThere: xen-devel@lists.xen.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: xen-devel-bounces@lists.xen.org Sender: "Xen-devel" X-Virus-Scanned: ClamAV using ClamSMTP From: Daniel Kiper 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(). The new allocator is quite generic and can be used on ARM platforms too. Signed-off-by: Daniel Kiper Reviewed-by: Doug Goldstein --- Doug v1 - removed stale paragraph v11 - suggestions/fixes: - #ifdef only EBMALLOC_SIZE from ebmalloc machinery (suggested by Jan Beulich). v10 - suggestions/fixes: - remove unneeded ARM free_ebmalloc_unused_mem() stub. 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 | 50 ++++++++++++++++++++++++++++++++++++++- 3 files changed, 54 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 0ccef1d..d4b7d25 100644 --- a/xen/arch/x86/setup.c +++ b/xen/arch/x86/setup.c @@ -1124,8 +1124,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 df8c702..36dbb71 100644 --- a/xen/common/efi/boot.c +++ b/xen/common/efi/boot.c @@ -98,6 +98,54 @@ static CHAR16 __initdata newline[] = L"\r\n"; #define PrintStr(s) StdOut->OutputString(StdOut, s) #define PrintErr(s) StdErr->OutputString(StdErr, s) +#ifdef 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, as it is right now, 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, + * - use ebmalloc() in ARM/common EFI boot code, + * - call free_ebmalloc_unused_mem() somewhere in init code. + */ +#define EBMALLOC_SIZE MB(0) +#else +#define EBMALLOC_SIZE MB(1) +#endif + +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 __maybe_unused *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 __maybe_unused 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); +} + /* * Include architecture specific implementation here, which references the * static globals defined above. @@ -1251,6 +1299,8 @@ void __init efi_init_memory(void) } *extra, *extra_head = NULL; #endif + free_ebmalloc_unused_mem(); + if ( !efi_enabled(EFI_BOOT) ) return;