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

[PATCH 2/3] x86/ucode: Rework AMD's microcode_fits()



This function is overloaded, creating complexity; 3 of 4 callers already only
want it for it's "applicable to this CPU or not" answer, and handle revision
calculations separately.

Change it to be microcode_fits_cpu(), returning a simple boolean.  The
checking of the equiv table can be simplified substantially too; A mapping
will only be inserted if it's correct for the CPU, so any nonzero equiv.sig
suffices to know that equiv.id is correct.

Drop compare_header() too, which is simiarly overloaded, and use
compare_revisions() directly.

Notably, this removes a path where cpu_request_microcode() inspects
currently-loaded microcode revision, just to discard the answer.

No functional change.

Signed-off-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
---
CC: Jan Beulich <JBeulich@xxxxxxxx>
CC: Roger Pau Monné <roger.pau@xxxxxxxxxx>
---
 xen/arch/x86/cpu/microcode/amd.c | 49 ++++++++++++++++----------------
 1 file changed, 24 insertions(+), 25 deletions(-)

diff --git a/xen/arch/x86/cpu/microcode/amd.c b/xen/arch/x86/cpu/microcode/amd.c
index c7a779c1d885..3861fec6565a 100644
--- a/xen/arch/x86/cpu/microcode/amd.c
+++ b/xen/arch/x86/cpu/microcode/amd.c
@@ -182,36 +182,31 @@ static enum microcode_match_result compare_revisions(
     return OLD_UCODE;
 }
 
-static enum microcode_match_result microcode_fits(
-    const struct microcode_patch *patch)
-{
-    unsigned int cpu = smp_processor_id();
-    const struct cpu_signature *sig = &per_cpu(cpu_sig, cpu);
-
-    if ( equiv.sig != sig->sig ||
-         equiv.id  != patch->processor_rev_id )
-        return MIS_UCODE;
-
-    return compare_revisions(sig->rev, patch->patch_id);
-}
-
-static enum microcode_match_result compare_header(
-    const struct microcode_patch *new, const struct microcode_patch *old)
+/*
+ * Check whether this microcode patch is applicable for the current CPU.
+ *
+ * AMD microcode blobs only have the "equivalent CPU identifier" which is a 16
+ * bit contraction of the 32 bit Family/Model/Stepping.
+ *
+ * We expect to only be run after scan_equiv_cpu_table() has found a valid
+ * mapping for the current CPU.  If this is violated, the 0 in equiv.id will
+ * cause the patch to be rejected too.
+ */
+static bool microcode_fits_cpu(const struct microcode_patch *patch)
 {
-    if ( new->processor_rev_id != old->processor_rev_id )
-        return MIS_UCODE;
+    ASSERT(equiv.sig);
 
-    return compare_revisions(old->patch_id, new->patch_id);
+    return equiv.id == patch->processor_rev_id;
 }
 
 static enum microcode_match_result cf_check compare_patch(
     const struct microcode_patch *new, const struct microcode_patch *old)
 {
     /* Both patches to compare are supposed to be applicable to local CPU. */
-    ASSERT(microcode_fits(new) != MIS_UCODE);
-    ASSERT(microcode_fits(old) != MIS_UCODE);
+    ASSERT(microcode_fits_cpu(new));
+    ASSERT(microcode_fits_cpu(old));
 
-    return compare_header(new, old);
+    return compare_revisions(old->patch_id, new->patch_id);
 }
 
 static int cf_check apply_microcode(const struct microcode_patch *patch,
@@ -221,12 +216,14 @@ static int cf_check apply_microcode(const struct 
microcode_patch *patch,
     unsigned int cpu = smp_processor_id();
     struct cpu_signature *sig = &per_cpu(cpu_sig, cpu);
     uint32_t rev, old_rev = sig->rev;
-    enum microcode_match_result result = microcode_fits(patch);
+    enum microcode_match_result result;
     bool ucode_force = flags & XENPF_UCODE_FORCE;
 
-    if ( result == MIS_UCODE )
+    if ( !microcode_fits_cpu(patch) )
         return -EINVAL;
 
+    result = compare_revisions(old_rev, patch->patch_id);
+
     /*
      * Allow application of the same revision to pick up SMT-specific changes
      * even if the revision of the other SMT thread is already up-to-date.
@@ -396,8 +393,10 @@ static struct microcode_patch *cf_check 
cpu_request_microcode(
              * If the new ucode covers current CPU, compare ucodes and store 
the
              * one with higher revision.
              */
-            if ( (microcode_fits(mc->patch) != MIS_UCODE) &&
-                 (!saved || (compare_header(mc->patch, saved) == NEW_UCODE)) )
+            if ( microcode_fits_cpu(mc->patch) &&
+                 (!saved ||
+                  compare_revisions(saved->patch_id,
+                                    mc->patch->patch_id) == NEW_UCODE) )
             {
                 saved = mc->patch;
                 saved_size = mc->len;
-- 
2.39.5




 


Rackspace

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