void reload_ucode_amd(void) {}
#endif
-extern bool check_current_patch_level(u32 *rev);
+extern bool check_current_patch_level(u32 *rev, bool early);
#endif /* _ASM_X86_MICROCODE_AMD_H */
return patch_size;
}
+/*
+ * Those patch levels cannot be updated to newer ones and thus should be final.
+ */
+static u32 final_levels[] = {
+ 0x01000098,
+ 0x0100009f,
+ 0x010000af,
+ 0, /* T-101 terminator */
+};
+
/*
* Check the current patch level on this CPU.
*
* - true: if update should stop
* - false: otherwise
*/
-bool check_current_patch_level(u32 *rev)
+bool check_current_patch_level(u32 *rev, bool early)
{
- u32 dummy;
+ u32 lvl, dummy, i;
+ bool ret = false;
+ u32 *levels;
+
+ native_rdmsr(MSR_AMD64_PATCH_LEVEL, lvl, dummy);
+
+ if (IS_ENABLED(CONFIG_X86_32) && early)
+ levels = (u32 *)__pa_nodebug(&final_levels);
+ else
+ levels = final_levels;
+
+ for (i = 0; levels[i]; i++) {
+ if (lvl == levels[i]) {
+ lvl = 0;
+ ret = true;
+ break;
+ }
+ }
- native_rdmsr(MSR_AMD64_PATCH_LEVEL, *rev, dummy);
+ if (rev)
+ *rev = lvl;
- return false;
+ return ret;
}
int __apply_microcode_amd(struct microcode_amd *mc_amd)
mc_amd = p->data;
uci->mc = p->data;
- if (check_current_patch_level(&rev))
+ if (check_current_patch_level(&rev, false))
return -1;
/* need to apply patch? */
return;
}
- if (check_current_patch_level(&rev))
+ if (check_current_patch_level(&rev, true))
return;
while (left > 0) {
if (!container)
return;
- if (check_current_patch_level(&rev))
+ /*
+ * 64-bit runs with paging enabled, thus early==false.
+ */
+ if (check_current_patch_level(&rev, false))
return;
eax = cpuid_eax(0x00000001);
struct microcode_amd *mc;
u32 rev;
- if (check_current_patch_level(&rev))
+ /*
+ * early==false because this is a syscore ->resume path and by
+ * that time paging is long enabled.
+ */
+ if (check_current_patch_level(&rev, false))
return;
mc = (struct microcode_amd *)amd_ucode_patch;