@@ -847,17 +847,21 @@ int __init early_microcode_init(unsigned long *module_map,
{
const struct cpuinfo_x86 *c = &boot_cpu_data;
int rc = 0;
+ bool can_load = false;
switch ( c->x86_vendor )
{
case X86_VENDOR_AMD:
if ( c->x86 >= 0x10 )
+ {
ucode_ops = amd_ucode_ops;
+ can_load = true;
+ }
break;
case X86_VENDOR_INTEL:
- if ( c->x86 >= 6 )
- ucode_ops = intel_ucode_ops;
+ ucode_ops = intel_ucode_ops;
+ can_load = intel_can_load_microcode();
break;
}
@@ -871,13 +875,17 @@ int __init early_microcode_init(unsigned long *module_map,
/*
* Some hypervisors deliberately report a microcode revision of -1 to
- * mean that they will not accept microcode updates. We take the hint
- * and ignore the microcode interface in that case.
+ * mean that they will not accept microcode updates.
+ *
+ * It's also possible the hardware might have built-in support to disable
+ * updates and someone (e.g: a baremetal cloud provider) disabled them.
+ *
+ * Take the hint in either case and ignore the microcode interface.
*/
- if ( this_cpu(cpu_sig).rev == ~0 )
+ if ( this_cpu(cpu_sig).rev == ~0 || !can_load )
{
printk(XENLOG_INFO "Microcode loading disabled due to: %s\n",
- "rev = ~0");
+ can_load ? "rev = ~0" : "HW toggle");
ucode_ops.apply_microcode = NULL;
return -ENODEV;
}
@@ -385,6 +385,19 @@ static struct microcode_patch *cf_check cpu_request_microcode(
return patch;
}
+bool __init intel_can_load_microcode(void)
+{
+ uint64_t mcu_ctrl;
+
+ if ( !cpu_has_mcu_ctrl )
+ return true;
+
+ rdmsrl(MSR_MCU_CONTROL, mcu_ctrl);
+
+ /* If DIS_MCU_LOAD is set applying microcode updates won't work */
+ return !(mcu_ctrl & MCU_CONTROL_DIS_MCU_LOAD);
+}
+
const struct microcode_ops __initconst_cf_clobber intel_ucode_ops = {
.cpu_request_microcode = cpu_request_microcode,
.collect_cpu_info = collect_cpu_info,
@@ -60,6 +60,13 @@ struct microcode_ops {
const struct microcode_patch *new, const struct microcode_patch *old);
};
+/**
+ * Checks whether we can perform microcode updates on this Intel system
+ *
+ * @return True iff the microcode update facilities are enabled
+ */
+bool intel_can_load_microcode(void);
+
extern const struct microcode_ops amd_ucode_ops, intel_ucode_ops;
#endif /* ASM_X86_MICROCODE_PRIVATE_H */
@@ -201,6 +201,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)
#define cpu_has_rrsba boot_cpu_has(X86_FEATURE_RRSBA)
#define cpu_has_gds_ctrl boot_cpu_has(X86_FEATURE_GDS_CTRL)
@@ -183,6 +183,11 @@
#define MSR_PM_CTL1 0x00000db1
#define PM_CTL1_HDC_ALLOW_BLOCK BIT(0, ULL)
+#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)