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

[PATCH v2 4/4] x86/microcode: Prevent attempting updates if DIS_MCU_LOAD is set



If IA32_MSR_MCU_CONTROL exists then it's possible a CPU may be unable to
perform microcode updates. This is controlled through the DIS_MCU_LOAD bit
and is intended for baremetal clouds where the owner may not trust the
tenant to choose the microcode version in use. This patch makes sure we
only expose the microcode loading interface when it can be actually used,
while also allowing reads of current microcode versions.

Patch summary:
 * Read CPUID leaf 7d0 early so DIS_MCU_LOAD can be checked.
 * Hide microcode loading handlers if DIS_MCU_LOAD is set except for
   collect_cpu_info()
 * Update microcode_update_one() so APs can read their
   microcode version even if DIS_MCU_LOAD is set.

Signed-off-by: Alejandro Vallejo <alejandro.vallejo@xxxxxxxxx>

---
v2:
  * Moved check from apply time to init time.
---
 xen/arch/x86/cpu/microcode/core.c     | 31 +++++++++++++++++++++++++--
 xen/arch/x86/include/asm/cpufeature.h |  1 +
 xen/arch/x86/include/asm/msr-index.h  |  5 +++++
 3 files changed, 35 insertions(+), 2 deletions(-)

diff --git a/xen/arch/x86/cpu/microcode/core.c 
b/xen/arch/x86/cpu/microcode/core.c
index 4f60d96d98..a4c123118b 100644
--- a/xen/arch/x86/cpu/microcode/core.c
+++ b/xen/arch/x86/cpu/microcode/core.c
@@ -749,11 +749,12 @@ __initcall(microcode_init);
 /* Load a cached update to current cpu */
 int microcode_update_one(void)
 {
+    if ( ucode_ops.collect_cpu_info )
+        alternative_vcall(ucode_ops.collect_cpu_info);
+
     if ( !ucode_ops.apply_microcode )
         return -EOPNOTSUPP;
 
-    alternative_vcall(ucode_ops.collect_cpu_info);
-
     return microcode_update_cpu(NULL);
 }
 
@@ -849,12 +850,25 @@ static void __init early_read_cpuid_7d0(void)
             = cpuid_count_edx(7, 0);
 }
 
+static bool __init this_cpu_can_install_update(void)
+{
+    uint64_t mcu_ctrl;
+
+    if ( !cpu_has_mcu_ctrl )
+        return true;
+
+    rdmsrl(MSR_MCU_CONTROL, mcu_ctrl);
+    return !(mcu_ctrl & MCU_CONTROL_DIS_MCU_LOAD);
+}
+
 int __init early_microcode_init(unsigned long *module_map,
                                 const struct multiboot_info *mbi)
 {
     const struct cpuinfo_x86 *c = &boot_cpu_data;
     int rc = 0;
 
+    early_read_cpuid_7d0();
+
     switch ( c->x86_vendor )
     {
     case X86_VENDOR_AMD:
@@ -871,6 +885,15 @@ int __init early_microcode_init(unsigned long *module_map,
          * present.
          */
         ucode_ops = intel_ucode_ops;
+
+        /*
+         * In the case where microcode updates are blocked by the
+         * DIS_MCU_LOAD bit we can still read the microcode version even if
+         * we can't change it.
+         */
+        if ( !this_cpu_can_install_update() )
+            ucode_ops = (struct microcode_ops){ .collect_cpu_info =
+                                    intel_ucode_ops.collect_cpu_info };
         break;
     }
 
@@ -900,6 +923,10 @@ int __init early_microcode_init(unsigned long *module_map,
     if ( ucode_mod.mod_end || ucode_blob.size )
         rc = early_microcode_update_cpu();
 
+    /*
+     * We just updated microcode so we must reload the boot_cpu_data bits
+     * we read before because they might be stale after the updata.
+     */
     early_read_cpuid_7d0();
 
     /*
diff --git a/xen/arch/x86/include/asm/cpufeature.h 
b/xen/arch/x86/include/asm/cpufeature.h
index ace31e3b1f..0118171d7e 100644
--- a/xen/arch/x86/include/asm/cpufeature.h
+++ b/xen/arch/x86/include/asm/cpufeature.h
@@ -192,6 +192,7 @@ static inline bool boot_cpu_has(unsigned int feat)
 #define cpu_has_if_pschange_mc_no boot_cpu_has(X86_FEATURE_IF_PSCHANGE_MC_NO)
 #define cpu_has_tsx_ctrl        boot_cpu_has(X86_FEATURE_TSX_CTRL)
 #define cpu_has_taa_no          boot_cpu_has(X86_FEATURE_TAA_NO)
+#define cpu_has_mcu_ctrl        boot_cpu_has(X86_FEATURE_MCU_CTRL)
 #define cpu_has_fb_clear        boot_cpu_has(X86_FEATURE_FB_CLEAR)
 
 /* Synthesized. */
diff --git a/xen/arch/x86/include/asm/msr-index.h 
b/xen/arch/x86/include/asm/msr-index.h
index 2749e433d2..5c1350b5f9 100644
--- a/xen/arch/x86/include/asm/msr-index.h
+++ b/xen/arch/x86/include/asm/msr-index.h
@@ -165,6 +165,11 @@
 #define  PASID_PASID_MASK                   0x000fffff
 #define  PASID_VALID                        (_AC(1, ULL) << 31)
 
+#define MSR_MCU_CONTROL                     0x00001406
+#define  MCU_CONTROL_LOCK                   (_AC(1, ULL) <<  0)
+#define  MCU_CONTROL_DIS_MCU_LOAD           (_AC(1, ULL) <<  1)
+#define  MCU_CONTROL_EN_SMM_BYPASS          (_AC(1, ULL) <<  2)
+
 #define MSR_UARCH_MISC_CTRL                 0x00001b01
 #define  UARCH_CTRL_DOITM                   (_AC(1, ULL) <<  0)
 
-- 
2.34.1




 


Rackspace

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