[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH 04/12] x86/boot: introduce module release


  • To: "Daniel P. Smith" <dpsmith@xxxxxxxxxxxxxxxxxxxx>, <xen-devel@xxxxxxxxxxxxxxxxxxxx>
  • From: Jason Andryuk <jason.andryuk@xxxxxxx>
  • Date: Wed, 6 Nov 2024 17:16:29 -0500
  • Arc-authentication-results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 165.204.84.17) smtp.rcpttodomain=apertussolutions.com smtp.mailfrom=amd.com; dmarc=pass (p=quarantine sp=quarantine pct=100) action=none header.from=amd.com; dkim=none (message not signed); arc=none (0)
  • Arc-message-signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=E80QCvVYRMVdrgjpY5Lml6kcF0rOZlAtuXbSg4ACi0w=; b=leTODSwLkyMHrRYINucoguiPD2PTJPHnD/S8l9GPKO+XdDB/8DhdGPWnT/pQ1cdqnZvjzMO7RZ25WbGs/XWYq/XXKhDDS3uBMEO6VTtnSM2PX3PKaHpjl/9bUruOhooy+m6UEt+eP8vRIblyyMZq7e78PlXVx6dCHgRetWSQfbRV+fdq8XWnDlI9YtU/83ndzp1OjwETMJh74QUYiNnHQ84y68jvoUzRKRGiztdYwbQER7Gl9k3e1gETsERkFuxcrQ4GhKTKqbyw+LX2I6sAYfR0c3dXtmkws2uYRRqARNuTE2XCjV7JfF71L4kZNWFjRcKqaKKpmdlFMeXDVNyi/A==
  • Arc-seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=Ds4uHz19NAy8yqQ1JDuAK4Q1FpPxaJwJQqpbmmklH+Krxd2okSlurdWfDJIMgaszhnziCFBq47i7z+v8ntQu3n6oqVWuEBrCgh5FnxQHENt33yQGvAFu3TLCvUt1EkBvD41/XwpQYUE06td+IxLM3AGQNePtXtv3sKl6IfrXUwJdlu/34QU37d/Pw8eORm4I2odf7Bvk3IXjDpcjNgolwQGhmZtO1m5hiIr7UdsxyTlpXV8Av/byGEltP3/oPa4nkCwfub7O6nWom/gtc5eLzNNBDVAwz17Z7+lNgNFSf6MM7XETNkYJzX8MILSTeC+Jr0FQNrRr+rjHmfGVk+iVAA==
  • Cc: <christopher.w.clark@xxxxxxxxx>, <stefano.stabellini@xxxxxxx>, Jan Beulich <jbeulich@xxxxxxxx>, Andrew Cooper <andrew.cooper3@xxxxxxxxxx>, Roger Pau Monné <roger.pau@xxxxxxxxxx>
  • Delivery-date: Wed, 06 Nov 2024 22:17:03 +0000
  • List-id: Xen developer discussion <xen-devel.lists.xenproject.org>

On 2024-11-02 13:25, Daniel P. Smith wrote:
A precarious approach was used to release the pages used to hold a boot module.
The precariousness stemmed from the fact that in the case of PV dom0, the
initrd module pages may be either mapped or explicitly copied into the dom0
address space. So to handle this situation, the PV dom0 construction code will
set the size of the module to zero, relying on discard_initial_images() to skip
any modules with a size of zero.

A function is introduced to release a module when it is no longer needed that
accepts a boolean parameter, free_mem, to indicate if the corresponding pages
can be freed. To track that a module has been released, the boot module flag
`released` is introduced.

The previous release model was a free all at once except those of size zeros,
which would handle any unused modules passed. The new model is one of, free
consumed module after usage is complete, thus unconsumed modules do not have a
consumer to free them.

Slightly confusing. Maybe just "The new model is to free modules after they are consumed. Thus unconsumed modules are not freed."

To address this, the discard_uknown_boot_modules() is

"unknown"

introduced and called after the last module identification occurs, initrd, to
free the pages of any boot modules that are identified as not being released.
After domain construction completes, all modules should be freed. A walk of the
boot modules is added after domain construction to validate and notify if a
module is found not to have been released.

Signed-off-by: Daniel P. Smith <dpsmith@xxxxxxxxxxxxxxxxxxxx>
---
Changes since v7:
- This is a new approach as an alternative to the `consumed` flag.
---
  xen/arch/x86/cpu/microcode/core.c   |  4 ++
  xen/arch/x86/hvm/dom0_build.c       |  7 ++--
  xen/arch/x86/include/asm/bootinfo.h |  2 +
  xen/arch/x86/include/asm/setup.h    |  3 +-
  xen/arch/x86/pv/dom0_build.c        | 20 ++--------
  xen/arch/x86/setup.c                | 57 +++++++++++++++++++++++------
  xen/xsm/xsm_core.c                  |  5 +++
  7 files changed, 67 insertions(+), 31 deletions(-)


diff --git a/xen/arch/x86/setup.c b/xen/arch/x86/setup.c
index d061ece0541f..e6d2d25fd038 100644
--- a/xen/arch/x86/setup.c
+++ b/xen/arch/x86/setup.c
@@ -341,27 +341,55 @@ unsigned long __init initial_images_nrpages(nodeid_t node)
      return nr;
  }
-void __init discard_initial_images(void) /* a.k.a. Free boot modules */
+void __init release_boot_module(struct boot_module *bm, bool free_mem)
+{
+    uint64_t start = pfn_to_paddr(bm->mod->mod_start);
+    uint64_t size  = bm->mod->mod_end;
+
+    if ( bm->released )
+    {
+        printk(XENLOG_WARNING "Attempt second release boot module of type 
%d\n",
+               bm->type);
+        return;
+    }
+
+    if ( free_mem )
+        init_domheap_pages(start, start + PAGE_ALIGN(size));
+
+    bm->released = true;
+}
+
+void __init release_module(const module_t *m, bool free_mem)
  {
      struct boot_info *bi = &xen_boot_info;
      unsigned int i;
- for ( i = 0; i < bi->nr_modules; ++i )
+    for ( i = 0; i < bi->nr_modules; i++ )
      {
-        uint64_t start = pfn_to_paddr(bi->mods[i].mod->mod_start);
-        uint64_t size  = bi->mods[i].mod->mod_end;
+        if ( bi->mods[i].mod == m )
+            release_boot_module(&bi->mods[i], free_mem);
+    }
+}
- /*
-         * Sometimes the initrd is mapped, rather than copied, into dom0.
-         * Size being 0 is how we're instructed to leave the module alone.
-         */
-        if ( size == 0 )
+static void __init discard_unknown_boot_modules(void)
+{
+    struct boot_info *bi = &xen_boot_info;
+    unsigned int i, count = 0;
+
+    for_each_boot_module_by_type(i, bi, BOOTMOD_UNKNOWN)

for_each_boot_module_by_type ( i, bi, BOOTMOD_UNKNOWN )

To match style from 74af2d98276d ("x86/boot: eliminate module_map")

+    {
+        struct boot_module *bm = &bi->mods[i];
+
+        if ( bm == NULL || bm->released )
              continue;
- init_domheap_pages(start, start + PAGE_ALIGN(size));
+        release_boot_module(bm, true);
+        count++;
      }
- bi->nr_modules = 0;
+    if ( count )
+        printk(XENLOG_DEBUG "Releasing pages for uknown boot module %d\n",

"unknown". Since the operation already happened, maybe "Released pages for %d unknown boot modules"? I'm not sure of the value of that message. It would be more informative to provide the module index and maybe a page count. The index would at least point to which module is unused.

+               count);
  }
static void __init init_idle_domain(void)
@@ -2111,6 +2139,8 @@ void asmlinkage __init noreturn __start_xen(void)
                     initrdidx);
      }
+ discard_unknown_boot_modules();
+
      /*
       * We're going to setup domain0 using the module(s) that we stashed safely
       * above our heap. The second module, if present, is an initrd ramdisk.
@@ -2122,6 +2152,11 @@ void asmlinkage __init noreturn __start_xen(void)
      if ( !dom0 )
          panic("Could not set up DOM0 guest OS\n");
+ /* Check and warn if any modules did not get released */
+    for ( i = 0; i < bi->nr_modules; i++ )
+        if ( !bi->mods[i].released )
+            printk(XENLOG_ERR "Boot module %d not released, memory leaked", i);
+

Why not release the memory here instead of leaking it?

I feel like the corner case of mapping the dom0 initrd is leading to this manual approach or releasing modules individually. That logic then has to be spread around. discard_initial_images() kept the logic centralized. Maybe just replace the mod_end == 0 special case with a "don't release me" flag that is checked in discard_initial_images()?

Regards,
Jason



 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.