From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from list by lists.gnu.org with archive (Exim 4.90_1) id 1nYimZ-0005no-Mx for mharc-grub-devel@gnu.org; Mon, 28 Mar 2022 02:23:15 -0400 Received: from eggs.gnu.org ([209.51.188.92]:50290) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1nYimX-0005hP-1i for grub-devel@gnu.org; Mon, 28 Mar 2022 02:23:13 -0400 Received: from [2607:f8b0:4864:20::630] (port=43821 helo=mail-pl1-x630.google.com) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1nYimV-0005HB-0D for grub-devel@gnu.org; Mon, 28 Mar 2022 02:23:12 -0400 Received: by mail-pl1-x630.google.com with SMTP id w8so13936627pll.10 for ; Sun, 27 Mar 2022 23:23:10 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=axtens.net; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=3541DVpK9cquJ8blyRhzhTK4fai83BpALnh0107ViFg=; b=ovMhENgoUTN5qoWJw9ijBCHrFkZKhvqd/E+GroAtYi7jzuNOXi1BILBD6eqRBL/IuE 11Q37m4871B+sSPp+4LrLbui/tk4qY9T18FHHUcrgjW7A7LULPNc6iLN8+4elaSBklgZ UdYKZzbCSMdFSlisYaD2d03FgtGDuAir12R+E= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=3541DVpK9cquJ8blyRhzhTK4fai83BpALnh0107ViFg=; b=JKCBOJYq1qr93rmQgREmxxckdcEICWWPjKJ9AssBtVt3iIyxURrnNCtGfxRfci2SlK u6eAoodn4nny0/LCGuqKZ/OopZWX12+B8YS72Q3FgTQCUm9eZOKxuUN+TeQm1F4o5VaI KOecvhU1TiXtJIiNup5aK6QxNTf/AArkeeZdbMBoL4sOJ6qj06w/qG4RjY12rrizkCMv n6zivr3sLXVY7yUj5XuCHbBsAed1bPE5UPOXdXdHwBTZZ5f2Ph4KqSwANRa6ZuEM5Ot+ SrtL065Wvg/UT/Vohg9oKI1XTy5zZ2cLmCatphsWDIHc6tI9cHpS58wm77IBxy8jYPen /Nyg== X-Gm-Message-State: AOAM530JekwZQ+G06ln6asSQ5DwzckEAzSuaPwwcYXhocEZpoHQsD4II 6ihO9d78BiHr+Qrn3Acw9NQgE7bYG5lnSw== X-Google-Smtp-Source: ABdhPJxPLiMiewoS/qjtEwV7Y5ydZnlGuCQwehJYNySEeneslJFnRpLI5SXSMEiC5NwDTDfecsXlPA== X-Received: by 2002:a17:903:1208:b0:151:93fd:d868 with SMTP id l8-20020a170903120800b0015193fdd868mr24752373plh.121.1648448589459; Sun, 27 Mar 2022 23:23:09 -0700 (PDT) Received: from localhost ([2001:4479:e000:e400:743e:bc3e:ec72:bf20]) by smtp.gmail.com with ESMTPSA id j7-20020a17090a31c700b001c6dbb70c94sm20722557pjf.18.2022.03.27.23.23.08 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 27 Mar 2022 23:23:09 -0700 (PDT) From: Daniel Axtens To: grub-devel@gnu.org Cc: leif@nuviainc.com, stefanb@linux.ibm.com, ps@pks.im, dkiper@net-space.pl, Daniel Axtens Subject: [PATCH v2 06/15] mm: Allow dynamically requesting additional memory regions Date: Mon, 28 Mar 2022 17:22:31 +1100 Message-Id: <20220328062240.878781-7-dja@axtens.net> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20220328062240.878781-1-dja@axtens.net> References: <20220328062240.878781-1-dja@axtens.net> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Host-Lookup-Failed: Reverse DNS lookup failed for 2607:f8b0:4864:20::630 (failed) Received-SPF: pass client-ip=2607:f8b0:4864:20::630; envelope-from=dja@axtens.net; helo=mail-pl1-x630.google.com X-Spam_score_int: -6 X-Spam_score: -0.7 X-Spam_bar: / X-Spam_report: (-0.7 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, PDS_HP_HELO_NORDNS=0.659, RCVD_IN_DNSWL_NONE=-0.0001, RDNS_NONE=0.793, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: grub-devel@gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: The development of GNU GRUB List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 28 Mar 2022 06:23:13 -0000 From: Patrick Steinhardt Currently, all platforms will set up their heap on initialization of the platform code. While this works mostly fine, it poses some limitations on memory management on us. Most notably, allocating big chunks of memory in the gigabyte range would require us to pre-request this many bytes from the firmware and add it to the heap from the beginning on some platforms like EFI. As this isn't needed for most configurations, it is inefficient and may even negatively impact some usecases when, e.g., chainloading. Nonetheless, allocating big chunks of memory is required sometimes, where one example is the upcoming support for the Argon2 key derival function in LUKS2. In order to avoid pre-allocating big chunks of memory, this commit implements a runtime mechanism to add more pages to the system. When a given allocation cannot be currently satisfied, we'll call a given callback set up by the platform's own memory management subsystem, asking it to add a memory area with at least `n` bytes. If this succeeds, we retry searching for a valid memory region, which should now succeed. If this fails, we try asking for `n` bytes, possibly spread across multiple regions, in hopes that region merging means that we end up with enough memory for things to work out. Tested-by: Stefan Berger Signed-off-by: Patrick Steinhardt [dja: add this to the documentation at the top of mm.c v2: fallback to non-contiguous] Signed-off-by: Daniel Axtens --- Daniel K: you had a Reviewed-by based on v1, but as the v2 changes are non-trivial I have not included it. I currently default to a fallback to non-contiguous on all platforms: if anyone objects I'm happy to tweak it. --- grub-core/kern/mm.c | 30 ++++++++++++++++++++++++++++++ include/grub/mm.h | 16 ++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/grub-core/kern/mm.c b/grub-core/kern/mm.c index 90fa78a06735..c3bf4646f55e 100644 --- a/grub-core/kern/mm.c +++ b/grub-core/kern/mm.c @@ -28,6 +28,9 @@ - multiple regions may be used as free space. They may not be contiguous. + - if existing regions are insufficient to satisfy an allocation, a new + region can be requested from firmware. + Regions are managed by a singly linked list, and the meta information is stored in the beginning of each region. Space after the meta information is used to allocate memory. @@ -81,6 +84,7 @@ grub_mm_region_t grub_mm_base; +grub_mm_add_region_func_t grub_mm_add_region_fn; /* Get a header from the pointer PTR, and set *P and *R to a pointer to the header and a pointer to its region, respectively. PTR must @@ -437,6 +441,32 @@ grub_memalign (grub_size_t align, grub_size_t size) count++; goto again; + case 1: + /* Request additional pages, contiguous */ + count++; + + if (grub_mm_add_region_fn != NULL && + grub_mm_add_region_fn (size, GRUB_MM_ADD_REGION_CONSECUTIVE) == GRUB_ERR_NONE) + goto again; + + /* fallthrough */ + + case 2: + /* Request additional pages, anything at all */ + count++; + + if (grub_mm_add_region_fn != NULL) + { + /* + * Try again even if this fails, in case it was able to partially + * satisfy the request + */ + grub_mm_add_region_fn (size, GRUB_MM_ADD_REGION_NONE); + goto again; + } + + /* fallthrough */ + default: break; } diff --git a/include/grub/mm.h b/include/grub/mm.h index 44fde7cb9033..5d916809666c 100644 --- a/include/grub/mm.h +++ b/include/grub/mm.h @@ -20,6 +20,7 @@ #ifndef GRUB_MM_H #define GRUB_MM_H 1 +#include #include #include #include @@ -28,6 +29,21 @@ # define NULL ((void *) 0) #endif +#define GRUB_MM_ADD_REGION_NONE 0 +#define GRUB_MM_ADD_REGION_CONSECUTIVE (1 << 0) + +/* + * Function used to request memory regions of `grub_size_t` bytes. The second + * parameter is a bitfield of `GRUB_MM_ADD_REGION` flags. + */ +typedef grub_err_t (*grub_mm_add_region_func_t) (grub_size_t, unsigned int); + +/* + * Set this function pointer to enable adding memory-regions at runtime in case + * a memory allocation cannot be satisfied with existing regions. + */ +extern grub_mm_add_region_func_t EXPORT_VAR(grub_mm_add_region_fn); + void grub_mm_init_region (void *addr, grub_size_t size); void *EXPORT_FUNC(grub_calloc) (grub_size_t nmemb, grub_size_t size); void *EXPORT_FUNC(grub_malloc) (grub_size_t size); -- 2.32.0