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

[Xen-changelog] [xen master] x86/ucode/amd: Move check_final_patch_levels() to apply_microcode()



commit 0c770820a792a7ab7450fac58e404ce2b9dd40a1
Author:     Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
AuthorDate: Mon Mar 30 13:14:01 2020 +0100
Commit:     Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
CommitDate: Wed Apr 1 14:00:12 2020 +0100

    x86/ucode/amd: Move check_final_patch_levels() to apply_microcode()
    
    The microcode revision of whichever CPU runs cpu_request_microcode() is not
    necessarily applicable to other CPUs.
    
    If the BIOS left us with asymmetric microcode, rejecting updates in
    cpu_request_microcode() would prevent us levelling the system even if only 
up
    to the final level.  Also, failing to cache microcode misses an opportunity 
to
    get beyond the final level via the S3 path.
    
    Move check_final_patch_levels() earlier and use it in apply_microcode().
    Reword the error message to be more informative, and use -ENXIO as this 
corner
    case has nothing to do with permissions.
    
    Signed-off-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
    Reviewed-by: Jan Beulich <jbeulich@xxxxxxxx>
---
 xen/arch/x86/cpu/microcode/amd.c | 83 ++++++++++++++++++----------------------
 1 file changed, 38 insertions(+), 45 deletions(-)

diff --git a/xen/arch/x86/cpu/microcode/amd.c b/xen/arch/x86/cpu/microcode/amd.c
index 3262cf243f..fd18041642 100644
--- a/xen/arch/x86/cpu/microcode/amd.c
+++ b/xen/arch/x86/cpu/microcode/amd.c
@@ -119,6 +119,36 @@ static bool_t verify_patch_size(uint32_t patch_size)
     return (patch_size <= max_size);
 }
 
+static bool check_final_patch_levels(const struct cpu_signature *sig)
+{
+    /*
+     * 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,
+    };
+    unsigned int i;
+
+    if ( boot_cpu_data.x86 != 0x10 )
+        return false;
+
+    for ( i = 0; i < ARRAY_SIZE(final_levels); i++ )
+        if ( sig->rev == final_levels[i] )
+            return true;
+
+    return false;
+}
+
 static bool_t find_equiv_cpu_id(const struct equiv_cpu_entry *equiv_cpu_table,
                                 unsigned int current_cpu_id,
                                 unsigned int *equiv_cpu_id)
@@ -229,6 +259,14 @@ static int apply_microcode(const struct microcode_patch 
*patch)
     if ( !match_cpu(patch) )
         return -EINVAL;
 
+    if ( check_final_patch_levels(sig) )
+    {
+        printk(XENLOG_ERR
+               "microcode: CPU%u current rev %#x unsafe to update\n",
+               cpu, sig->rev);
+        return -ENXIO;
+    }
+
     hdr = patch->mpb;
 
     hw_err = wrmsr_safe(MSR_AMD_PATCHLOADER, (unsigned long)hdr);
@@ -374,43 +412,6 @@ static int container_fast_forward(const void *data, size_t 
size_left, size_t *of
     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.
-     */
-    const struct cpu_signature *sig = &per_cpu(cpu_sig, cpu);
-    unsigned int i;
-
-    if ( boot_cpu_data.x86 != 0x10 )
-        return 0;
-
-    for ( i = 0; i < ARRAY_SIZE(final_levels); i++ )
-        if ( sig->rev == final_levels[i] )
-            return 1;
-
-    return 0;
-}
-
 static struct microcode_patch *cpu_request_microcode(const void *buf,
                                                      size_t bufsize)
 {
@@ -433,14 +434,6 @@ static struct microcode_patch *cpu_request_microcode(const 
void *buf,
         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 = xzalloc(struct microcode_amd);
     if ( !mc_amd )
     {
--
generated by git-patchbot for /home/xen/git/xen.git#master

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/xen-changelog

 


Rackspace

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