[PATCH] x86/ucode: Support discrete modules being CPIO archives

Andrew Cooper posted 1 patch 3 months, 3 weeks ago
Patches applied successfully (tree, apply log)
git fetch https://gitlab.com/xen-project/patchew/xen tags/patchew/20260223185054.3598305-1-andrew.cooper3@citrix.com
CHANGELOG.md                      |  1 +
docs/misc/xen-command-line.pandoc | 19 ++++++++-----------
xen/arch/x86/cpu/microcode/core.c | 20 +++++++++++++++++++-
3 files changed, 28 insertions(+), 12 deletions(-)
[PATCH] x86/ucode: Support discrete modules being CPIO archives
Posted by Andrew Cooper 3 months, 3 weeks ago
Multiple downstream distros have tried passing discrete CPIO archives and
tripped over this not working.  It turns out to be easy to support, so do so.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
---
CC: Jan Beulich <JBeulich@suse.com>
CC: Roger Pau Monné <roger.pau@citrix.com>
CC: Teddy Astie <teddy.astie@vates.tech>

v2:
 * Docs update too.
 * Set opt_scan in early_microcode_load() so microcode_init_cache() operates
   properly
---
 CHANGELOG.md                      |  1 +
 docs/misc/xen-command-line.pandoc | 19 ++++++++-----------
 xen/arch/x86/cpu/microcode/core.c | 20 +++++++++++++++++++-
 3 files changed, 28 insertions(+), 12 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 18f3d10f20d2..c191e504aba9 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -13,6 +13,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
    - Support for Bus Lock Threshold on AMD Zen5 and later CPUs, used by Xen to
      mitigate (by rate-limiting) the system wide impact of an HVM guest
      misusing atomic instructions.
+   - Support for CPIO microcode in discrete multiboot modules.
 
 ### Removed
  - On x86:
diff --git a/docs/misc/xen-command-line.pandoc b/docs/misc/xen-command-line.pandoc
index c1f2def9f99c..ebdca007d26b 100644
--- a/docs/misc/xen-command-line.pandoc
+++ b/docs/misc/xen-command-line.pandoc
@@ -2764,23 +2764,20 @@ Controls for CPU microcode loading, available when `CONFIG_MICROCODE_LOADING`
 is enabled.
 
 In order to load microcode at boot, Xen needs to find a suitable update
-amongst the modules provided by the bootloader.  Two kinds of microcode update
-are supported:
+amongst the modules provided by the bootloader.  Two formats are supported:
 
  1. Raw microcode containers.  The format of the container is CPU vendor
     specific.
 
- 2. CPIO archive.  This is Linux's preferred mechanism, and involves having
-    the raw containers expressed as files
+ 2. CPIO archive, which involves having the raw containers expressed as files
     (e.g. `kernel/x86/microcode/{GenuineIntel,AuthenticAMD}.bin`) in a CPIO
-    archive, typically prepended to the initrd.
+    archive.  Linux commonly prepends this to the initrd.
 
-The `<integer>` and `scan=<bool>` options are mutually exclusive and select
-between these two options.  Further restrictions exist for booting xen.efi
-(see below).
+The `<integer>` and `scan=<bool>` options are mutually exclusive and work as
+follows.  Further restrictions exist for booting xen.efi (see below).
 
- *  The `<integer>` option nominates a specific multiboot module as a raw
-    container (option 1 above).  Valid options start from 1 (module 0 is
+ *  The `<integer>` option nominates a specific multiboot module as containing
+    microcode in either format.  Valid options start from 1 (module 0 is
     always the dom0 kernel).  A negative number may be used, and will
     back-reference from the end of the module list.  i.e. `ucode=-1` will
     nominate the final multiboot module.
@@ -2794,7 +2791,7 @@ When booting xen.efi natively, the concept of multiboot modules doesn't exist.
 Instead:
 
  *  In the [EFI configuration file](efi.html), `ucode=<filename>` can be used
-    to identify a file as a raw container (option 1 above).  Use of this
+    to identify a file as containing microcode in either format.  Use of this
     mechanism will disable both `<integer>` and `scan=`.
 
  *  If `ucode=<filename>` in the EFI configuration file is not used, it is
diff --git a/xen/arch/x86/cpu/microcode/core.c b/xen/arch/x86/cpu/microcode/core.c
index ea0b35c4991d..9b8d1e09cb98 100644
--- a/xen/arch/x86/cpu/microcode/core.c
+++ b/xen/arch/x86/cpu/microcode/core.c
@@ -767,6 +767,7 @@ static int __init early_microcode_load(struct boot_info *bi)
     void *data = NULL;
     size_t size;
     const struct microcode_patch *patch;
+    struct cpio_data cd;
     int idx = opt_mod_idx;
     int rc;
 
@@ -783,7 +784,6 @@ static int __init early_microcode_load(struct boot_info *bi)
         for ( idx = 0; idx < bi->nr_modules; ++idx )
         {
             const struct boot_module *bm = &bi->mods[idx];
-            struct cpio_data cd;
 
             /* Search anything unclaimed or likely to be a CPIO archive. */
             if ( bm->kind != BOOTMOD_UNKNOWN && bm->kind != BOOTMOD_RAMDISK )
@@ -851,6 +851,24 @@ static int __init early_microcode_load(struct boot_info *bi)
                    idx, size);
             return -ENODEV;
         }
+
+        /*
+         * If this blob appears to be a CPIO archive, try interpreting it as
+         * one.  Otherwise treat it as a raw vendor blob.
+         */
+        cd = find_cpio_data(ucode_ops.cpio_path, data, size);
+        if ( cd.data )
+        {
+            data = cd.data;
+            size = cd.size;
+
+            /*
+             * (Ab)use opt_scan to inform microcode_init_cache() that
+             * early_mod_idx refers to a CPIO archive.
+             */
+            opt_scan = true;
+        }
+
         goto found;
     }
 

base-commit: 5eb84d6c992cf4e81936872c441b649057947442
-- 
2.39.5


Re: [PATCH] x86/ucode: Support discrete modules being CPIO archives
Posted by Teddy Astie 3 months, 2 weeks ago
Le 23/02/2026 à 19:52, Andrew Cooper a écrit :
> Multiple downstream distros have tried passing discrete CPIO archives and
> tripped over this not working.  It turns out to be easy to support, so do so.
> 
> Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>

Tested-by: Teddy Astie <teddy.astie@vates.tech>

> ---
> CC: Jan Beulich <JBeulich@suse.com>
> CC: Roger Pau Monné <roger.pau@citrix.com>
> CC: Teddy Astie <teddy.astie@vates.tech>
> 
> v2:
>   * Docs update too.
>   * Set opt_scan in early_microcode_load() so microcode_init_cache() operates
>     properly
> ---
>   CHANGELOG.md                      |  1 +
>   docs/misc/xen-command-line.pandoc | 19 ++++++++-----------
>   xen/arch/x86/cpu/microcode/core.c | 20 +++++++++++++++++++-
>   3 files changed, 28 insertions(+), 12 deletions(-)
> 
> diff --git a/CHANGELOG.md b/CHANGELOG.md
> index 18f3d10f20d2..c191e504aba9 100644
> --- a/CHANGELOG.md
> +++ b/CHANGELOG.md
> @@ -13,6 +13,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
>      - Support for Bus Lock Threshold on AMD Zen5 and later CPUs, used by Xen to
>        mitigate (by rate-limiting) the system wide impact of an HVM guest
>        misusing atomic instructions.
> +   - Support for CPIO microcode in discrete multiboot modules.
>   
>   ### Removed
>    - On x86:
> diff --git a/docs/misc/xen-command-line.pandoc b/docs/misc/xen-command-line.pandoc
> index c1f2def9f99c..ebdca007d26b 100644
> --- a/docs/misc/xen-command-line.pandoc
> +++ b/docs/misc/xen-command-line.pandoc
> @@ -2764,23 +2764,20 @@ Controls for CPU microcode loading, available when `CONFIG_MICROCODE_LOADING`
>   is enabled.
>   
>   In order to load microcode at boot, Xen needs to find a suitable update
> -amongst the modules provided by the bootloader.  Two kinds of microcode update
> -are supported:
> +amongst the modules provided by the bootloader.  Two formats are supported:
>   
>    1. Raw microcode containers.  The format of the container is CPU vendor
>       specific.
>   
> - 2. CPIO archive.  This is Linux's preferred mechanism, and involves having
> -    the raw containers expressed as files
> + 2. CPIO archive, which involves having the raw containers expressed as files
>       (e.g. `kernel/x86/microcode/{GenuineIntel,AuthenticAMD}.bin`) in a CPIO
> -    archive, typically prepended to the initrd.
> +    archive.  Linux commonly prepends this to the initrd.
>   
> -The `<integer>` and `scan=<bool>` options are mutually exclusive and select
> -between these two options.  Further restrictions exist for booting xen.efi
> -(see below).
> +The `<integer>` and `scan=<bool>` options are mutually exclusive and work as
> +follows.  Further restrictions exist for booting xen.efi (see below).
>   
> - *  The `<integer>` option nominates a specific multiboot module as a raw
> -    container (option 1 above).  Valid options start from 1 (module 0 is
> + *  The `<integer>` option nominates a specific multiboot module as containing
> +    microcode in either format.  Valid options start from 1 (module 0 is
>       always the dom0 kernel).  A negative number may be used, and will
>       back-reference from the end of the module list.  i.e. `ucode=-1` will
>       nominate the final multiboot module.
> @@ -2794,7 +2791,7 @@ When booting xen.efi natively, the concept of multiboot modules doesn't exist.
>   Instead:
>   
>    *  In the [EFI configuration file](efi.html), `ucode=<filename>` can be used
> -    to identify a file as a raw container (option 1 above).  Use of this
> +    to identify a file as containing microcode in either format.  Use of this
>       mechanism will disable both `<integer>` and `scan=`.
>   
>    *  If `ucode=<filename>` in the EFI configuration file is not used, it is
> diff --git a/xen/arch/x86/cpu/microcode/core.c b/xen/arch/x86/cpu/microcode/core.c
> index ea0b35c4991d..9b8d1e09cb98 100644
> --- a/xen/arch/x86/cpu/microcode/core.c
> +++ b/xen/arch/x86/cpu/microcode/core.c
> @@ -767,6 +767,7 @@ static int __init early_microcode_load(struct boot_info *bi)
>       void *data = NULL;
>       size_t size;
>       const struct microcode_patch *patch;
> +    struct cpio_data cd;
>       int idx = opt_mod_idx;
>       int rc;
>   
> @@ -783,7 +784,6 @@ static int __init early_microcode_load(struct boot_info *bi)
>           for ( idx = 0; idx < bi->nr_modules; ++idx )
>           {
>               const struct boot_module *bm = &bi->mods[idx];
> -            struct cpio_data cd;
>   
>               /* Search anything unclaimed or likely to be a CPIO archive. */
>               if ( bm->kind != BOOTMOD_UNKNOWN && bm->kind != BOOTMOD_RAMDISK )
> @@ -851,6 +851,24 @@ static int __init early_microcode_load(struct boot_info *bi)
>                      idx, size);
>               return -ENODEV;
>           }
> +
> +        /*
> +         * If this blob appears to be a CPIO archive, try interpreting it as
> +         * one.  Otherwise treat it as a raw vendor blob.
> +         */
> +        cd = find_cpio_data(ucode_ops.cpio_path, data, size);
> +        if ( cd.data )
> +        {
> +            data = cd.data;
> +            size = cd.size;
> +
> +            /*
> +             * (Ab)use opt_scan to inform microcode_init_cache() that
> +             * early_mod_idx refers to a CPIO archive.
> +             */
> +            opt_scan = true;
> +        }
> +
>           goto found;
>       }
>   
> 
> base-commit: 5eb84d6c992cf4e81936872c441b649057947442



--
Teddy Astie | Vates XCP-ng Developer

XCP-ng & Xen Orchestra - Vates solutions

web: https://vates.tech
Re: [PATCH] x86/ucode: Support discrete modules being CPIO archives
Posted by Jan Beulich 3 months, 3 weeks ago
On 23.02.2026 19:50, Andrew Cooper wrote:
> Multiple downstream distros have tried passing discrete CPIO archives and
> tripped over this not working.  It turns out to be easy to support, so do so.
> 
> Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>

Reviewed-by: Jan Beulich <jbeulich@suse.com>