97 lines
3.3 KiB
Diff
97 lines
3.3 KiB
Diff
|
# Commit 22c5675877c8209adcfdb6bceddb561320374529
|
||
|
# Date 2015-08-25 16:17:13 +0200
|
||
|
# Author Aravind Gopalakrishnan <aravind.gopalakrishnan@amd.com>
|
||
|
# Committer Jan Beulich <jbeulich@suse.com>
|
||
|
x86, amd_ucode: skip microcode updates for final levels
|
||
|
|
||
|
Some of older[Fam10h] systems require that certain number of
|
||
|
applied microcode patch levels should not be overwritten by
|
||
|
the microcode loader. Otherwise, system hangs are known to occur.
|
||
|
|
||
|
The 'final_levels' of patch ids have been obtained empirically.
|
||
|
Refer bug https://bugzilla.suse.com/show_bug.cgi?id=913996
|
||
|
for details of the issue.
|
||
|
|
||
|
The short version is that people have predominantly noticed
|
||
|
system hang issues when trying to update microcode levels
|
||
|
beyond the patch IDs below.
|
||
|
[0x01000098, 0x0100009f, 0x010000af]
|
||
|
|
||
|
From internal discussions, we gathered that OS/hypervisor
|
||
|
cannot reliably perform microcode updates beyond these levels
|
||
|
due to hardware issues. Therefore, we need to abort microcode
|
||
|
update process if we hit any of these levels.
|
||
|
|
||
|
In this patch, we check for those microcode versions and abort
|
||
|
if the current core has one of those final patch levels applied
|
||
|
by the BIOS
|
||
|
|
||
|
A linux version of the patch has already made it into tip-
|
||
|
http://marc.info/?l=linux-kernel&m=143703405627170
|
||
|
|
||
|
Signed-off-by: Aravind Gopalakrishnan <aravind.gopalakrishnan@amd.com>
|
||
|
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
|
||
|
Reviewed-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
|
||
|
|
||
|
--- a/xen/arch/x86/microcode_amd.c
|
||
|
+++ b/xen/arch/x86/microcode_amd.c
|
||
|
@@ -347,6 +347,43 @@ static int container_fast_forward(const
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
+/*
|
||
|
+ * The 'final_levels' of patch ids have been obtained empirically.
|
||
|
+ * Refer bug https://bugzilla.suse.com/show_bug.cgi?id=913996
|
||
|
+ * for details of the issue. The short version is that people
|
||
|
+ * using certain Fam10h systems noticed system hang issues when
|
||
|
+ * trying to update microcode levels beyond the patch IDs below.
|
||
|
+ * From internal discussions, we gathered that OS/hypervisor
|
||
|
+ * cannot reliably perform microcode updates beyond these levels
|
||
|
+ * due to hardware issues. Therefore, we need to abort microcode
|
||
|
+ * update process if we hit any of these levels.
|
||
|
+ */
|
||
|
+static const unsigned int final_levels[] = {
|
||
|
+ 0x01000098,
|
||
|
+ 0x0100009f,
|
||
|
+ 0x010000af
|
||
|
+};
|
||
|
+
|
||
|
+static bool_t check_final_patch_levels(unsigned int cpu)
|
||
|
+{
|
||
|
+ /*
|
||
|
+ * Check the current patch levels on the cpu. If they are equal to
|
||
|
+ * any of the 'final_levels', then we should not update the microcode
|
||
|
+ * patch on the cpu as system will hang otherwise.
|
||
|
+ */
|
||
|
+ struct ucode_cpu_info *uci = &per_cpu(ucode_cpu_info, cpu);
|
||
|
+ unsigned int i;
|
||
|
+
|
||
|
+ if ( boot_cpu_data.x86 != 0x10 )
|
||
|
+ return 0;
|
||
|
+
|
||
|
+ for ( i = 0; i < ARRAY_SIZE(final_levels); i++ )
|
||
|
+ if ( uci->cpu_sig.rev == final_levels[i] )
|
||
|
+ return 1;
|
||
|
+
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
static int cpu_request_microcode(int cpu, const void *buf, size_t bufsize)
|
||
|
{
|
||
|
struct microcode_amd *mc_amd, *mc_old;
|
||
|
@@ -369,6 +406,14 @@ static int cpu_request_microcode(int cpu
|
||
|
goto out;
|
||
|
}
|
||
|
|
||
|
+ if ( check_final_patch_levels(cpu) )
|
||
|
+ {
|
||
|
+ printk(XENLOG_INFO
|
||
|
+ "microcode: Cannot update microcode patch on the cpu as we hit a final level\n");
|
||
|
+ error = -EPERM;
|
||
|
+ goto out;
|
||
|
+ }
|
||
|
+
|
||
|
mc_amd = xmalloc(struct microcode_amd);
|
||
|
if ( !mc_amd )
|
||
|
{
|