x86/ucode: Work around Granite Rapids erraturm GNR98

Block loads which are known to hang the system.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Teddy Astie <teddy.astie@vates.tech>
Reviewed-by: Roger Pau Monné <roger@xenproject.org>
Acked-by: Jan Beulich <jbeulich@suse.com>
This commit is contained in:
Andrew Cooper committed 2026-09-09 18:07:32 +01:00
1 parent f3a525c259
commit 70cbd9a08d
1 file changed
+40
+40
View File
@@ -27,6 +27,7 @@
#include <xen/string.h>
#include <xen/xmalloc.h>
#include <asm/intel-family.h>
#include <asm/msr.h>
#include <asm/processor.h>
#include <asm/system.h>
@@ -273,6 +274,44 @@ static bool microcode_fits_cpu(const struct microcode_patch *mc)
return false;
}
static bool microcode_safe_to_load(const struct microcode_patch *mc)
{
const struct cpu_signature *cpu_sig = &this_cpu(cpu_sig);
/*
* Treat pre-production as always safe - anyone using pre-production
* microcode knows what they are doing, and can keep any resulting pieces.
*/
if ( (int)cpu_sig->rev < 0 || mc->rev < 0 )
return true;
/*
* GNR98 states that Granite Rapids systems hang when loading new ucode on
* sufficiently old firmware. GNR101 retroactively states that one ucode
* had an incorrect minimum revision field, in light of discovering GNR98.
*
* Both are incomplete statements of the problem.
*
* At the time of writing (August 2026), the believed safe sequence is:
* previous -> [0x01000380...0x010003f3] -> 0x01000405 -> any later
*
* Disallow known-unsafe loads while permitting believed-safe loads. For
* GNR, this allows multi-hop loading to get up to the latest.
*/
if ( boot_cpu_data.vfm == INTEL_GRANITERAPIDS_X &&
boot_cpu_data.stepping == 1 && (cpu_sig->pf & 0x95) &&
((cpu_sig->rev < 0x01000380 && mc->rev >= 0x01000405) ||
(cpu_sig->rev < 0x01000405 && mc->rev > 0x01000405)) )
{
printk_once(XENLOG_WARNING "microcode: Granite Rapids erratum GNR98 detected. Skipping ucode 0x%08x\n"
XENLOG_WARNING "microcode: Firmware update recommended\n",
mc->rev);
return false;
}
return true;
}
static int cf_check intel_compare(
const struct microcode_patch *old, const struct microcode_patch *new)
{
@@ -365,6 +404,7 @@ static struct microcode_patch *cf_check intel_ucode_parse(
* one with higher revision.
*/
if ( microcode_fits_cpu(mc) &&
microcode_safe_to_load(mc) &&
(!saved || compare_revisions(saved->rev, mc->rev) == NEW_UCODE) )
saved = mc;
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.