* [PATCH v2 1/5] x86/ucode: Abort parallel load early on any control thread error
2025-10-27 22:16 [PATCH for-4.21 0/5] x86/ucode: Support loading latest ucode from linux-firwmare Andrew Cooper
@ 2025-10-27 22:16 ` Andrew Cooper
2025-10-27 22:16 ` [PATCH v2 2/5] x86/ucode: Refine TLB flush fix for AMD Fam17h CPUs Andrew Cooper
` (4 subsequent siblings)
5 siblings, 0 replies; 12+ messages in thread
From: Andrew Cooper @ 2025-10-27 22:16 UTC (permalink / raw)
To: Xen-devel; +Cc: Andrew Cooper, Jan Beulich, Jan Beulich, Roger Pau Monné
EIO is not the only error that ucode_ops.apply_microcode() can produce.
EINVAL, EEXISTS and ENXIO can be generated too, each of which mean that Xen is
unhappy in some way with the proposed blob.
Some of these can be bypassed with --force, which will cause the parallel load
to be attempted.
Fixes: 5ed12565aa32 ("microcode: rendezvous CPUs in NMI handler and load ucode")
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Acked-by: Jan Beulich <jbeulich@suse.com>
---
CC: Jan Beulich <JBeulich@suse.com>
CC: Roger Pau Monné <roger.pau@citrix.com>
---
xen/arch/x86/cpu/microcode/core.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/xen/arch/x86/cpu/microcode/core.c b/xen/arch/x86/cpu/microcode/core.c
index 1b093bc98a58..2705bb43c97f 100644
--- a/xen/arch/x86/cpu/microcode/core.c
+++ b/xen/arch/x86/cpu/microcode/core.c
@@ -392,10 +392,10 @@ static int control_thread_fn(const struct microcode_patch *patch,
atomic_inc(&cpu_updated);
atomic_inc(&cpu_out);
- if ( ret == -EIO )
+ if ( ret )
{
printk(XENLOG_ERR
- "Late loading aborted: CPU%u failed to update ucode\n", cpu);
+ "Late loading aborted: CPU%u failed to update ucode: %d\n", cpu, ret);
goto out;
}
--
2.39.5
^ permalink raw reply related [flat|nested] 12+ messages in thread* [PATCH v2 2/5] x86/ucode: Refine TLB flush fix for AMD Fam17h CPUs
2025-10-27 22:16 [PATCH for-4.21 0/5] x86/ucode: Support loading latest ucode from linux-firwmare Andrew Cooper
2025-10-27 22:16 ` [PATCH v2 1/5] x86/ucode: Abort parallel load early on any control thread error Andrew Cooper
@ 2025-10-27 22:16 ` Andrew Cooper
2025-10-27 22:17 ` [PATCH v2 3/5] x86/ucode: Cross check the minimum revision Andrew Cooper
` (3 subsequent siblings)
5 siblings, 0 replies; 12+ messages in thread
From: Andrew Cooper @ 2025-10-27 22:16 UTC (permalink / raw)
To: Xen-devel; +Cc: Andrew Cooper, Jan Beulich, Jan Beulich, Roger Pau Monné
In the time since Xen discovered this, Linux stubled on it too and AMD
produced a narrower fix, limited to Fam17h CPUs only. To my knowledge,
there's no erratum or other public statement from AMD on the matter.
Adjust Xen to match the narrower fix.
Link: https://lore.kernel.org/lkml/ZyulbYuvrkshfsd2@antipodes/T/#u
Fixes: f19a199281a2 ("x86/AMD: flush TLB after ucode update")
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Acked-by: Jan Beulich <jbeulich@suse.com>
---
CC: Jan Beulich <JBeulich@suse.com>
CC: Roger Pau Monné <roger.pau@citrix.com>
v2:
* Keep memory clobber.
---
xen/arch/x86/cpu/microcode/amd.c | 14 +++++++++++---
xen/arch/x86/flushtlb.c | 3 +--
xen/arch/x86/include/asm/flushtlb.h | 5 +++++
3 files changed, 17 insertions(+), 5 deletions(-)
diff --git a/xen/arch/x86/cpu/microcode/amd.c b/xen/arch/x86/cpu/microcode/amd.c
index 59332da2b827..457810182480 100644
--- a/xen/arch/x86/cpu/microcode/amd.c
+++ b/xen/arch/x86/cpu/microcode/amd.c
@@ -306,10 +306,18 @@ static int cf_check apply_microcode(const struct microcode_patch *patch,
sig->rev = rev;
/*
- * Some processors leave the ucode blob mapping as UC after the update.
- * Flush the mapping to regain normal cacheability.
+ * Fam17h processors leave the mapping of the ucode as UC after the
+ * update. Flush the mapping to regain normal cacheability.
+ *
+ * We do not know the granularity of mapping, and at 3200 bytes in size
+ * there is a good chance of crossing a 4k page boundary. Shoot-down the
+ * start and end just to be safe.
*/
- flush_area_local(patch, FLUSH_TLB_GLOBAL | FLUSH_ORDER(0));
+ if ( boot_cpu_data.family == 0x17 )
+ {
+ invlpg(patch);
+ invlpg((const void *)patch + F17H_MPB_MAX_SIZE - 1);
+ }
/* check current patch id and patch's id for match */
if ( hw_err || (rev != patch->patch_id) )
diff --git a/xen/arch/x86/flushtlb.c b/xen/arch/x86/flushtlb.c
index 94b2a30e8d30..09e676c151fa 100644
--- a/xen/arch/x86/flushtlb.c
+++ b/xen/arch/x86/flushtlb.c
@@ -222,8 +222,7 @@ unsigned int flush_area_local(const void *va, unsigned int flags)
}
}
else
- asm volatile ( "invlpg %0"
- : : "m" (*(const char *)(va)) : "memory" );
+ invlpg(va);
}
else
do_tlb_flush();
diff --git a/xen/arch/x86/include/asm/flushtlb.h b/xen/arch/x86/include/asm/flushtlb.h
index 019d886f2b80..7bcbca2b7f31 100644
--- a/xen/arch/x86/include/asm/flushtlb.h
+++ b/xen/arch/x86/include/asm/flushtlb.h
@@ -98,6 +98,11 @@ static inline unsigned long read_cr3(void)
return cr3;
}
+static inline void invlpg(const void *p)
+{
+ asm volatile ( "invlpg %0" :: "m" (*(const char *)p) : "memory" );
+}
+
/* Write pagetable base and implicitly tick the tlbflush clock. */
void switch_cr3_cr4(unsigned long cr3, unsigned long cr4);
--
2.39.5
^ permalink raw reply related [flat|nested] 12+ messages in thread* [PATCH v2 3/5] x86/ucode: Cross check the minimum revision
2025-10-27 22:16 [PATCH for-4.21 0/5] x86/ucode: Support loading latest ucode from linux-firwmare Andrew Cooper
2025-10-27 22:16 ` [PATCH v2 1/5] x86/ucode: Abort parallel load early on any control thread error Andrew Cooper
2025-10-27 22:16 ` [PATCH v2 2/5] x86/ucode: Refine TLB flush fix for AMD Fam17h CPUs Andrew Cooper
@ 2025-10-27 22:17 ` Andrew Cooper
2025-10-27 22:17 ` [PATCH v2 4/5] x86/ucode: Refine the boundary checks for Entrysign Andrew Cooper
` (2 subsequent siblings)
5 siblings, 0 replies; 12+ messages in thread
From: Andrew Cooper @ 2025-10-27 22:17 UTC (permalink / raw)
To: Xen-devel; +Cc: Andrew Cooper, Jan Beulich, Jan Beulich, Roger Pau Monné
For Zen3-5 microcode blobs signed with the updated signature scheme, the
checksum field has been reused to be a min_revision field, referring to the
microcode revision which fixed Entrysign (SB-7033, CVE-2024-36347).
Cross-check this when trying to load microcode, but allow --force to override
it. If the signature scheme is genuinely different, a #GP will occur.
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Acked-by: Jan Beulich <jbeulich@suse.com>
---
CC: Jan Beulich <JBeulich@suse.com>
CC: Roger Pau Monné <roger.pau@citrix.com>
v2:
* Tweak comment
---
xen/arch/x86/cpu/microcode/amd.c | 49 +++++++++++++++++++++++++++++++-
1 file changed, 48 insertions(+), 1 deletion(-)
diff --git a/xen/arch/x86/cpu/microcode/amd.c b/xen/arch/x86/cpu/microcode/amd.c
index 457810182480..ba03401c24c5 100644
--- a/xen/arch/x86/cpu/microcode/amd.c
+++ b/xen/arch/x86/cpu/microcode/amd.c
@@ -42,7 +42,10 @@ struct microcode_patch {
uint8_t mc_patch_data_id[2];
uint8_t mc_patch_data_len;
uint8_t init_flag;
- uint32_t mc_patch_data_checksum;
+ union {
+ uint32_t checksum; /* Fam12h and earlier */
+ uint32_t min_rev; /* Zen3-5, post Entrysign */
+ };
uint32_t nb_dev_id;
uint32_t sb_dev_id;
uint16_t processor_rev_id;
@@ -270,6 +273,42 @@ static int cf_check amd_compare(
return compare_revisions(old->patch_id, new->patch_id);
}
+/*
+ * Check whether this patch has a minimum revision given, and whether the
+ * condition is satisfied.
+ *
+ * In linux-firmware for CPUs suffering from the Entrysign vulnerability,
+ * ucodes signed with the updated signature algorithm have reused the checksum
+ * field as a min-revision field. From public archives, the checksum field
+ * appears to have been unused since Fam12h.
+ *
+ * Returns false if there is a min revision given, and it suggests that that
+ * the patch cannot be loaded on the current system. True otherwise.
+ */
+static bool check_min_rev(const struct microcode_patch *patch)
+{
+ ASSERT(microcode_fits_cpu(patch));
+
+ if ( patch->processor_rev_id < 0xa000 || /* pre Zen3? */
+ patch->min_rev == 0 ) /* No min rev specified */
+ return true;
+
+ /*
+ * Sanity check, as this is a reused field. If this is a true
+ * min_revision field, it will differ only in the bottom byte from the
+ * patch_id. Otherwise, it's probably a checksum.
+ */
+ if ( (patch->patch_id ^ patch->min_rev) & ~0xff )
+ {
+ printk(XENLOG_WARNING
+ "microcode: patch %#x has unexpected min_rev %#x\n",
+ patch->patch_id, patch->min_rev);
+ return true;
+ }
+
+ return this_cpu(cpu_sig).rev >= patch->min_rev;
+}
+
static int cf_check apply_microcode(const struct microcode_patch *patch,
unsigned int flags)
{
@@ -299,6 +338,14 @@ static int cf_check apply_microcode(const struct microcode_patch *patch,
return -ENXIO;
}
+ if ( !ucode_force && !check_min_rev(patch) )
+ {
+ printk(XENLOG_ERR
+ "microcode: CPU%u current rev %#x below patch min_rev %#x\n",
+ cpu, sig->rev, patch->min_rev);
+ return -ENXIO;
+ }
+
hw_err = wrmsr_safe(MSR_AMD_PATCHLOADER, (unsigned long)patch);
/* get patch id after patching */
--
2.39.5
^ permalink raw reply related [flat|nested] 12+ messages in thread* [PATCH v2 4/5] x86/ucode: Refine the boundary checks for Entrysign
2025-10-27 22:16 [PATCH for-4.21 0/5] x86/ucode: Support loading latest ucode from linux-firwmare Andrew Cooper
` (2 preceding siblings ...)
2025-10-27 22:17 ` [PATCH v2 3/5] x86/ucode: Cross check the minimum revision Andrew Cooper
@ 2025-10-27 22:17 ` Andrew Cooper
2025-10-28 9:32 ` Jan Beulich
2025-10-27 22:17 ` [PATCH v2 5/5] x86/ucode: Relax digest check when Entrysign is fixed in firmware Andrew Cooper
2025-10-28 14:48 ` [PATCH for-4.21 0/5] x86/ucode: Support loading latest ucode from linux-firwmare Oleksii Kurochko
5 siblings, 1 reply; 12+ messages in thread
From: Andrew Cooper @ 2025-10-27 22:17 UTC (permalink / raw)
To: Xen-devel; +Cc: Andrew Cooper, Jan Beulich, Roger Pau Monné
After initial publication, the SB-7033 / CVE-2024-36347 bulletin was updated
to list Zen5 CPUs as vulnerable. Use Fam1ah as an upper bound, and adjust the
command line documentation.
When the Zen6 (also Fam1ah processors) model numbers are known, they'll want
excluding from the family ranges.
Fixes: 630e8875ab36 ("x86/ucode: Perform extra SHA2 checks on AMD Fam17h/19h microcode")
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
---
CC: Jan Beulich <JBeulich@suse.com>
CC: Roger Pau Monné <roger.pau@citrix.com>
v2:
* New
---
docs/misc/xen-command-line.pandoc | 7 ++++---
xen/arch/x86/cpu/microcode/amd.c | 9 +++++++--
2 files changed, 11 insertions(+), 5 deletions(-)
diff --git a/docs/misc/xen-command-line.pandoc b/docs/misc/xen-command-line.pandoc
index 28a98321c762..34004ce282be 100644
--- a/docs/misc/xen-command-line.pandoc
+++ b/docs/misc/xen-command-line.pandoc
@@ -2826,9 +2826,10 @@ stop_machine context. In NMI handler, even NMIs are blocked, which is
considered safer. The default value is `true`.
The `digest-check=` option is active by default and controls whether to
-perform additional authenticity checks. Collisions in the signature algorithm
-used by AMD Fam17h/19h processors have been found. Xen contains a table of
-digests of microcode patches with known-good provenance, and will block
+perform additional authenticity checks. The Entrysign vulnerability (AMD
+SB-7033, CVE-2024-36347) on Zen1-5 processors allows forging the signature on
+arbitrary microcode such that it is accepted by the CPU. Xen contains a table
+of digests of microcode patches with known-good provenance, and will block
loading of patches that do not match.
### unrestricted_guest (Intel)
diff --git a/xen/arch/x86/cpu/microcode/amd.c b/xen/arch/x86/cpu/microcode/amd.c
index ba03401c24c5..f331d9dfee6e 100644
--- a/xen/arch/x86/cpu/microcode/amd.c
+++ b/xen/arch/x86/cpu/microcode/amd.c
@@ -125,7 +125,7 @@ static bool check_digest(const struct container_microcode *mc)
* microcode updates. Mitigate by checking the digest of the patch
* against a list of known provenance.
*/
- if ( boot_cpu_data.family < 0x17 ||
+ if ( boot_cpu_data.family < 0x17 || boot_cpu_data.family > 0x1a ||
!opt_digest_check )
return true;
@@ -571,7 +571,12 @@ static const struct microcode_ops __initconst_cf_clobber amd_ucode_ops = {
void __init ucode_probe_amd(struct microcode_ops *ops)
{
- if ( !opt_digest_check && boot_cpu_data.family >= 0x17 )
+ /*
+ * The Entrysign vulnerability (SB-7033, CVE-2024-36347) affects Zen1-5
+ * CPUs. Taint Xen if digest checking is turned off.
+ */
+ if ( boot_cpu_data.family >= 0x17 && boot_cpu_data.family <= 0x1a &&
+ !opt_digest_check )
{
printk(XENLOG_WARNING
"Microcode patch additional digest checks disabled\n");
--
2.39.5
^ permalink raw reply related [flat|nested] 12+ messages in thread* Re: [PATCH v2 4/5] x86/ucode: Refine the boundary checks for Entrysign
2025-10-27 22:17 ` [PATCH v2 4/5] x86/ucode: Refine the boundary checks for Entrysign Andrew Cooper
@ 2025-10-28 9:32 ` Jan Beulich
2025-10-28 10:34 ` Andrew Cooper
0 siblings, 1 reply; 12+ messages in thread
From: Jan Beulich @ 2025-10-28 9:32 UTC (permalink / raw)
To: Andrew Cooper; +Cc: Roger Pau Monné, Xen-devel
On 27.10.2025 23:17, Andrew Cooper wrote:
> After initial publication, the SB-7033 / CVE-2024-36347 bulletin was updated
> to list Zen5 CPUs as vulnerable. Use Fam1ah as an upper bound, and adjust the
> command line documentation.
>
> When the Zen6 (also Fam1ah processors) model numbers are known, they'll want
> excluding from the family ranges.
I.e. we're firmly promised the problem won't be there anymore going forward?
> Fixes: 630e8875ab36 ("x86/ucode: Perform extra SHA2 checks on AMD Fam17h/19h microcode")
> Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Acked-by: Jan Beulich <jbeulich@suse.com>
^ permalink raw reply [flat|nested] 12+ messages in thread* Re: [PATCH v2 4/5] x86/ucode: Refine the boundary checks for Entrysign
2025-10-28 9:32 ` Jan Beulich
@ 2025-10-28 10:34 ` Andrew Cooper
0 siblings, 0 replies; 12+ messages in thread
From: Andrew Cooper @ 2025-10-28 10:34 UTC (permalink / raw)
To: Jan Beulich; +Cc: Roger Pau Monné, Xen-devel
On 28/10/2025 9:32 am, Jan Beulich wrote:
> On 27.10.2025 23:17, Andrew Cooper wrote:
>> After initial publication, the SB-7033 / CVE-2024-36347 bulletin was updated
>> to list Zen5 CPUs as vulnerable. Use Fam1ah as an upper bound, and adjust the
>> command line documentation.
>>
>> When the Zen6 (also Fam1ah processors) model numbers are known, they'll want
>> excluding from the family ranges.
> I.e. we're firmly promised the problem won't be there anymore going forward?
This is what I hear from AMD, yes.
>
>> Fixes: 630e8875ab36 ("x86/ucode: Perform extra SHA2 checks on AMD Fam17h/19h microcode")
>> Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
> Acked-by: Jan Beulich <jbeulich@suse.com>
>
Thanks.
~Andrew
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH v2 5/5] x86/ucode: Relax digest check when Entrysign is fixed in firmware
2025-10-27 22:16 [PATCH for-4.21 0/5] x86/ucode: Support loading latest ucode from linux-firwmare Andrew Cooper
` (3 preceding siblings ...)
2025-10-27 22:17 ` [PATCH v2 4/5] x86/ucode: Refine the boundary checks for Entrysign Andrew Cooper
@ 2025-10-27 22:17 ` Andrew Cooper
2025-10-28 9:47 ` Jan Beulich
2025-10-28 14:48 ` [PATCH for-4.21 0/5] x86/ucode: Support loading latest ucode from linux-firwmare Oleksii Kurochko
5 siblings, 1 reply; 12+ messages in thread
From: Andrew Cooper @ 2025-10-27 22:17 UTC (permalink / raw)
To: Xen-devel; +Cc: Andrew Cooper, Jan Beulich, Roger Pau Monné
When Entrysign has been mitigated in firwmare, it is believed to be safe to
rely on the CPU patchloader again. This avoids us needing to maintain the
digest table for all new microcode indefinitely.
Relax the digest check when firmware looks to be up to date, and leave behind
a clear message when not.
This is best-effort only. If a malicious microcode has been loaded prior to
Xen running, then all bets are off.
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
---
CC: Jan Beulich <JBeulich@suse.com>
CC: Roger Pau Monné <roger.pau@citrix.com>
v2:
* Corrections to the revision table.
* Updates to various comments.
* Add a "WARNING: " prefix to the message about vulnerability
---
xen/arch/x86/cpu/microcode/amd.c | 86 +++++++++++++++++++++++++++-
xen/arch/x86/cpu/microcode/core.c | 2 +
xen/arch/x86/cpu/microcode/private.h | 2 +
3 files changed, 87 insertions(+), 3 deletions(-)
diff --git a/xen/arch/x86/cpu/microcode/amd.c b/xen/arch/x86/cpu/microcode/amd.c
index f331d9dfee6e..9ecf6c37d3f4 100644
--- a/xen/arch/x86/cpu/microcode/amd.c
+++ b/xen/arch/x86/cpu/microcode/amd.c
@@ -101,6 +101,7 @@ static const struct patch_digest {
} patch_digests[] = {
#include "amd-patch-digests.c"
};
+static bool __ro_after_init entrysign_mitigiated_in_firmware;
static int cf_check cmp_patch_id(const void *key, const void *elem)
{
@@ -122,11 +123,11 @@ static bool check_digest(const struct container_microcode *mc)
/*
* Zen1 thru Zen5 CPUs are known to use a weak signature algorithm on
- * microcode updates. Mitigate by checking the digest of the patch
- * against a list of known provenance.
+ * microcode updates. If this has not been mitigated in firmware,
+ * checking the digest of the patch against a list of known provenance.
*/
if ( boot_cpu_data.family < 0x17 || boot_cpu_data.family > 0x1a ||
- !opt_digest_check )
+ entrysign_mitigiated_in_firmware || !opt_digest_check )
return true;
pd = bsearch(&patch->patch_id, patch_digests, ARRAY_SIZE(patch_digests),
@@ -603,3 +604,82 @@ static void __init __constructor test_digests_sorted(void)
}
}
#endif /* CONFIG_SELF_TESTS */
+
+/*
+ * The Entrysign vulnerability affects all Zen1 thru Zen5 CPUs. Firmware
+ * fixes were produced from Nov 2024. Zen3 thru Zen5 can continue to take
+ * OS-loadable microcode updates using a new signature scheme, as long as
+ * firmware has been updated first.
+ */
+void __init amd_check_entrysign(void)
+{
+ unsigned int curr_rev;
+ uint8_t fixed_rev;
+
+ if ( boot_cpu_data.vendor != X86_VENDOR_AMD ||
+ boot_cpu_data.family < 0x17 ||
+ boot_cpu_data.family > 0x1a )
+ return;
+
+ /*
+ * Table taken from Linux, which is the only known source of information
+ * about client revisions. Note, Linux expresses "last-vulnerable-rev"
+ * while Xen wants "first-fixed-rev".
+ */
+ curr_rev = this_cpu(cpu_sig).rev;
+ switch ( curr_rev >> 8 )
+ {
+ case 0x080012: fixed_rev = 0x78; break;
+ case 0x080082: fixed_rev = 0x10; break;
+ case 0x083010: fixed_rev = 0x7d; break;
+ case 0x086001: fixed_rev = 0x0f; break;
+ case 0x086081: fixed_rev = 0x09; break;
+ case 0x087010: fixed_rev = 0x35; break;
+ case 0x08a000: fixed_rev = 0x0b; break;
+ case 0x0a0010: fixed_rev = 0x7b; break;
+ case 0x0a0011: fixed_rev = 0xdb; break;
+ case 0x0a0012: fixed_rev = 0x44; break;
+ case 0x0a0082: fixed_rev = 0x0f; break;
+ case 0x0a1011: fixed_rev = 0x54; break;
+ case 0x0a1012: fixed_rev = 0x4f; break;
+ case 0x0a1081: fixed_rev = 0x0a; break;
+ case 0x0a2010: fixed_rev = 0x30; break;
+ case 0x0a2012: fixed_rev = 0x13; break;
+ case 0x0a4041: fixed_rev = 0x0a; break;
+ case 0x0a5000: fixed_rev = 0x14; break;
+ case 0x0a6012: fixed_rev = 0x0b; break;
+ case 0x0a7041: fixed_rev = 0x0a; break;
+ case 0x0a7052: fixed_rev = 0x09; break;
+ case 0x0a7080: fixed_rev = 0x0a; break;
+ case 0x0a70c0: fixed_rev = 0x0a; break;
+ case 0x0aa001: fixed_rev = 0x17; break;
+ case 0x0aa002: fixed_rev = 0x19; break;
+ case 0x0b0021: fixed_rev = 0x47; break;
+ case 0x0b1010: fixed_rev = 0x47; break;
+ case 0x0b2040: fixed_rev = 0x32; break;
+ case 0x0b4040: fixed_rev = 0x32; break;
+ case 0x0b6000: fixed_rev = 0x32; break;
+ case 0x0b7000: fixed_rev = 0x32; break;
+ default:
+ printk(XENLOG_WARNING
+ "Unrecognised CPU %02x-%02x-%02x ucode 0x%08x, assuming vulnerable to Entrysign\n",
+ boot_cpu_data.family, boot_cpu_data.model,
+ boot_cpu_data.stepping, curr_rev);
+ return;
+ }
+
+ /*
+ * This check is best-effort. If the platform looks to be out of date, it
+ * probably is. If the platform looks to be fixed, it either genuinely
+ * is, or malware has gotten in before Xen booted and all bets are off.
+ */
+ if ( (uint8_t)curr_rev >= fixed_rev )
+ {
+ entrysign_mitigiated_in_firmware = true;
+ return;
+ }
+
+ printk(XENLOG_WARNING
+ "WARNING: Platform vulnerable to Entrysign (SB-7033, CVE-2024-36347) - firmware update required\n");
+ add_taint(TAINT_CPU_OUT_OF_SPEC);
+}
diff --git a/xen/arch/x86/cpu/microcode/core.c b/xen/arch/x86/cpu/microcode/core.c
index 2705bb43c97f..1d1a5aa4b097 100644
--- a/xen/arch/x86/cpu/microcode/core.c
+++ b/xen/arch/x86/cpu/microcode/core.c
@@ -750,6 +750,8 @@ static int __init early_microcode_load(struct boot_info *bi)
int idx = opt_mod_idx;
int rc;
+ amd_check_entrysign();
+
/*
* Cmdline parsing ensures this invariant holds, so that we don't end up
* trying to mix multiple ways of finding the microcode.
diff --git a/xen/arch/x86/cpu/microcode/private.h b/xen/arch/x86/cpu/microcode/private.h
index f5e2bfee00d9..e6c965dc99dd 100644
--- a/xen/arch/x86/cpu/microcode/private.h
+++ b/xen/arch/x86/cpu/microcode/private.h
@@ -81,8 +81,10 @@ extern bool opt_digest_check;
*/
#ifdef CONFIG_AMD
void ucode_probe_amd(struct microcode_ops *ops);
+void amd_check_entrysign(void);
#else
static inline void ucode_probe_amd(struct microcode_ops *ops) {}
+static inline void amd_check_entrysign(void) {}
#endif
#ifdef CONFIG_INTEL
--
2.39.5
^ permalink raw reply related [flat|nested] 12+ messages in thread* Re: [PATCH v2 5/5] x86/ucode: Relax digest check when Entrysign is fixed in firmware
2025-10-27 22:17 ` [PATCH v2 5/5] x86/ucode: Relax digest check when Entrysign is fixed in firmware Andrew Cooper
@ 2025-10-28 9:47 ` Jan Beulich
2025-10-28 11:31 ` Andrew Cooper
0 siblings, 1 reply; 12+ messages in thread
From: Jan Beulich @ 2025-10-28 9:47 UTC (permalink / raw)
To: Andrew Cooper; +Cc: Roger Pau Monné, Xen-devel
On 27.10.2025 23:17, Andrew Cooper wrote:
> When Entrysign has been mitigated in firwmare, it is believed to be safe to
> rely on the CPU patchloader again. This avoids us needing to maintain the
> digest table for all new microcode indefinitely.
>
> Relax the digest check when firmware looks to be up to date, and leave behind
> a clear message when not.
>
> This is best-effort only. If a malicious microcode has been loaded prior to
> Xen running, then all bets are off.
>
> Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Like for patch 4, adjustments for Zen6 are then going to be needed here too,
aiui. May be worth repeating that statement here.
> @@ -603,3 +604,82 @@ static void __init __constructor test_digests_sorted(void)
> }
> }
> #endif /* CONFIG_SELF_TESTS */
> +
> +/*
> + * The Entrysign vulnerability affects all Zen1 thru Zen5 CPUs. Firmware
> + * fixes were produced from Nov 2024. Zen3 thru Zen5 can continue to take
> + * OS-loadable microcode updates using a new signature scheme, as long as
> + * firmware has been updated first.
> + */
> +void __init amd_check_entrysign(void)
> +{
> + unsigned int curr_rev;
> + uint8_t fixed_rev;
> +
> + if ( boot_cpu_data.vendor != X86_VENDOR_AMD ||
Given the function name, might this check better live at the call site?
> + boot_cpu_data.family < 0x17 ||
> + boot_cpu_data.family > 0x1a )
> + return;
> +
> + /*
> + * Table taken from Linux, which is the only known source of information
> + * about client revisions. Note, Linux expresses "last-vulnerable-rev"
> + * while Xen wants "first-fixed-rev".
> + */
> + curr_rev = this_cpu(cpu_sig).rev;
> + switch ( curr_rev >> 8 )
> + {
> + case 0x080012: fixed_rev = 0x78; break;
> + case 0x080082: fixed_rev = 0x10; break;
> + case 0x083010: fixed_rev = 0x7d; break;
> + case 0x086001: fixed_rev = 0x0f; break;
> + case 0x086081: fixed_rev = 0x09; break;
> + case 0x087010: fixed_rev = 0x35; break;
> + case 0x08a000: fixed_rev = 0x0b; break;
> + case 0x0a0010: fixed_rev = 0x7b; break;
> + case 0x0a0011: fixed_rev = 0xdb; break;
> + case 0x0a0012: fixed_rev = 0x44; break;
> + case 0x0a0082: fixed_rev = 0x0f; break;
> + case 0x0a1011: fixed_rev = 0x54; break;
> + case 0x0a1012: fixed_rev = 0x4f; break;
> + case 0x0a1081: fixed_rev = 0x0a; break;
> + case 0x0a2010: fixed_rev = 0x30; break;
> + case 0x0a2012: fixed_rev = 0x13; break;
> + case 0x0a4041: fixed_rev = 0x0a; break;
> + case 0x0a5000: fixed_rev = 0x14; break;
> + case 0x0a6012: fixed_rev = 0x0b; break;
> + case 0x0a7041: fixed_rev = 0x0a; break;
> + case 0x0a7052: fixed_rev = 0x09; break;
> + case 0x0a7080: fixed_rev = 0x0a; break;
> + case 0x0a70c0: fixed_rev = 0x0a; break;
> + case 0x0aa001: fixed_rev = 0x17; break;
> + case 0x0aa002: fixed_rev = 0x19; break;
> + case 0x0b0021: fixed_rev = 0x47; break;
> + case 0x0b1010: fixed_rev = 0x47; break;
> + case 0x0b2040: fixed_rev = 0x32; break;
> + case 0x0b4040: fixed_rev = 0x32; break;
> + case 0x0b6000: fixed_rev = 0x32; break;
> + case 0x0b7000: fixed_rev = 0x32; break;
Acked-by: Jan Beulich <jbeulich@suse.com>
(after cross checking with up-to-date Linux, i.e. including your recent
correction there)
Jan
^ permalink raw reply [flat|nested] 12+ messages in thread* Re: [PATCH v2 5/5] x86/ucode: Relax digest check when Entrysign is fixed in firmware
2025-10-28 9:47 ` Jan Beulich
@ 2025-10-28 11:31 ` Andrew Cooper
2025-10-28 13:29 ` Jan Beulich
0 siblings, 1 reply; 12+ messages in thread
From: Andrew Cooper @ 2025-10-28 11:31 UTC (permalink / raw)
To: Jan Beulich; +Cc: Roger Pau Monné, Xen-devel
On 28/10/2025 9:47 am, Jan Beulich wrote:
> On 27.10.2025 23:17, Andrew Cooper wrote:
>> When Entrysign has been mitigated in firwmare, it is believed to be safe to
>> rely on the CPU patchloader again. This avoids us needing to maintain the
>> digest table for all new microcode indefinitely.
>>
>> Relax the digest check when firmware looks to be up to date, and leave behind
>> a clear message when not.
>>
>> This is best-effort only. If a malicious microcode has been loaded prior to
>> Xen running, then all bets are off.
>>
>> Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
> Like for patch 4, adjustments for Zen6 are then going to be needed here too,
> aiui. May be worth repeating that statement here.
Ok.
>
>> @@ -603,3 +604,82 @@ static void __init __constructor test_digests_sorted(void)
>> }
>> }
>> #endif /* CONFIG_SELF_TESTS */
>> +
>> +/*
>> + * The Entrysign vulnerability affects all Zen1 thru Zen5 CPUs. Firmware
>> + * fixes were produced from Nov 2024. Zen3 thru Zen5 can continue to take
>> + * OS-loadable microcode updates using a new signature scheme, as long as
>> + * firmware has been updated first.
>> + */
>> +void __init amd_check_entrysign(void)
>> +{
>> + unsigned int curr_rev;
>> + uint8_t fixed_rev;
>> +
>> + if ( boot_cpu_data.vendor != X86_VENDOR_AMD ||
> Given the function name, might this check better live at the call site?
Possibly, but I really don't want to split the vendor check away from
the family ranges.
A family check without a vendor check in eyeshot is
suspicious-going-on-buggy, and this is called once at init.
>
>> + boot_cpu_data.family < 0x17 ||
>> + boot_cpu_data.family > 0x1a )
>> + return;
>> +
>> + /*
>> + * Table taken from Linux, which is the only known source of information
>> + * about client revisions. Note, Linux expresses "last-vulnerable-rev"
>> + * while Xen wants "first-fixed-rev".
>> + */
>> + curr_rev = this_cpu(cpu_sig).rev;
>> + switch ( curr_rev >> 8 )
>> + {
>> + case 0x080012: fixed_rev = 0x78; break;
>> + case 0x080082: fixed_rev = 0x10; break;
>> + case 0x083010: fixed_rev = 0x7d; break;
>> + case 0x086001: fixed_rev = 0x0f; break;
>> + case 0x086081: fixed_rev = 0x09; break;
>> + case 0x087010: fixed_rev = 0x35; break;
>> + case 0x08a000: fixed_rev = 0x0b; break;
>> + case 0x0a0010: fixed_rev = 0x7b; break;
>> + case 0x0a0011: fixed_rev = 0xdb; break;
>> + case 0x0a0012: fixed_rev = 0x44; break;
>> + case 0x0a0082: fixed_rev = 0x0f; break;
>> + case 0x0a1011: fixed_rev = 0x54; break;
>> + case 0x0a1012: fixed_rev = 0x4f; break;
>> + case 0x0a1081: fixed_rev = 0x0a; break;
>> + case 0x0a2010: fixed_rev = 0x30; break;
>> + case 0x0a2012: fixed_rev = 0x13; break;
>> + case 0x0a4041: fixed_rev = 0x0a; break;
>> + case 0x0a5000: fixed_rev = 0x14; break;
>> + case 0x0a6012: fixed_rev = 0x0b; break;
>> + case 0x0a7041: fixed_rev = 0x0a; break;
>> + case 0x0a7052: fixed_rev = 0x09; break;
>> + case 0x0a7080: fixed_rev = 0x0a; break;
>> + case 0x0a70c0: fixed_rev = 0x0a; break;
>> + case 0x0aa001: fixed_rev = 0x17; break;
>> + case 0x0aa002: fixed_rev = 0x19; break;
>> + case 0x0b0021: fixed_rev = 0x47; break;
>> + case 0x0b1010: fixed_rev = 0x47; break;
>> + case 0x0b2040: fixed_rev = 0x32; break;
>> + case 0x0b4040: fixed_rev = 0x32; break;
>> + case 0x0b6000: fixed_rev = 0x32; break;
>> + case 0x0b7000: fixed_rev = 0x32; break;
> Acked-by: Jan Beulich <jbeulich@suse.com>
> (after cross checking with up-to-date Linux, i.e. including your recent
> correction there)
Thanks.
~Andrew
^ permalink raw reply [flat|nested] 12+ messages in thread* Re: [PATCH v2 5/5] x86/ucode: Relax digest check when Entrysign is fixed in firmware
2025-10-28 11:31 ` Andrew Cooper
@ 2025-10-28 13:29 ` Jan Beulich
0 siblings, 0 replies; 12+ messages in thread
From: Jan Beulich @ 2025-10-28 13:29 UTC (permalink / raw)
To: Andrew Cooper; +Cc: Roger Pau Monné, Xen-devel
On 28.10.2025 12:31, Andrew Cooper wrote:
> On 28/10/2025 9:47 am, Jan Beulich wrote:
>> On 27.10.2025 23:17, Andrew Cooper wrote:
>>> @@ -603,3 +604,82 @@ static void __init __constructor test_digests_sorted(void)
>>> }
>>> }
>>> #endif /* CONFIG_SELF_TESTS */
>>> +
>>> +/*
>>> + * The Entrysign vulnerability affects all Zen1 thru Zen5 CPUs. Firmware
>>> + * fixes were produced from Nov 2024. Zen3 thru Zen5 can continue to take
>>> + * OS-loadable microcode updates using a new signature scheme, as long as
>>> + * firmware has been updated first.
>>> + */
>>> +void __init amd_check_entrysign(void)
>>> +{
>>> + unsigned int curr_rev;
>>> + uint8_t fixed_rev;
>>> +
>>> + if ( boot_cpu_data.vendor != X86_VENDOR_AMD ||
>> Given the function name, might this check better live at the call site?
>
> Possibly, but I really don't want to split the vendor check away from
> the family ranges.
>
> A family check without a vendor check in eyeshot is
> suspicious-going-on-buggy, and this is called once at init.
Well, okay, I'm certainly not going to insist. It merely occurred to me that
normally we would call amd_*() functions only once we know we run on AMD (or
sometimes Hygon) hardware.
Jan
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH for-4.21 0/5] x86/ucode: Support loading latest ucode from linux-firwmare
2025-10-27 22:16 [PATCH for-4.21 0/5] x86/ucode: Support loading latest ucode from linux-firwmare Andrew Cooper
` (4 preceding siblings ...)
2025-10-27 22:17 ` [PATCH v2 5/5] x86/ucode: Relax digest check when Entrysign is fixed in firmware Andrew Cooper
@ 2025-10-28 14:48 ` Oleksii Kurochko
5 siblings, 0 replies; 12+ messages in thread
From: Oleksii Kurochko @ 2025-10-28 14:48 UTC (permalink / raw)
To: Andrew Cooper, Xen-devel; +Cc: Jan Beulich, Roger Pau Monné
[-- Attachment #1: Type: text/plain, Size: 1449 bytes --]
On 10/27/25 11:16 PM, Andrew Cooper wrote:
> linux-firmware now contains microcode signed with the new signature scheme.
> Xen currently refuses to load these as we've not updated the digest list.
>
> The plan was always to stop using the digest list in due course, which is what
> this series does. A fix for the RDSEED vulnerability is imminent, and it's
> critical that Xen can load this microcode.
>
> As such, this is intended for backport to all trees including security trees,
> and therefore really does need to get into Xen 4.21
Considering that it is security related and will be backported anyway it should
be considered to be in Xen 4.21:
Release-Acked-By: Oleksii Kurochko<oleksii.kurochko@gmail.com>
Thanks.
~ Oleksii
>
> Andrew Cooper (5):
> x86/ucode: Abort parallel load early on any control thread error
> x86/ucode: Refine TLB flush fix for AMD Fam17h CPUs
> x86/ucode: Cross check the minimum revision
> x86/ucode: Refine the boundary checks for Entrysign
> x86/ucode: Relax digest check when Entrysign is fixed in firmware
>
> docs/misc/xen-command-line.pandoc | 7 +-
> xen/arch/x86/cpu/microcode/amd.c | 158 +++++++++++++++++++++++++--
> xen/arch/x86/cpu/microcode/core.c | 6 +-
> xen/arch/x86/cpu/microcode/private.h | 2 +
> xen/arch/x86/flushtlb.c | 3 +-
> xen/arch/x86/include/asm/flushtlb.h | 5 +
> 6 files changed, 165 insertions(+), 16 deletions(-)
>
[-- Attachment #2: Type: text/html, Size: 2031 bytes --]
^ permalink raw reply [flat|nested] 12+ messages in thread