[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20221014200913.14644-4-ashok.raj@intel.com>
Date: Fri, 14 Oct 2022 13:09:03 -0700
From: Ashok Raj <ashok.raj@...el.com>
To: Borislav Petkov <bp@...en8.de>,
Thomas Gleixner <tglx@...utronix.de>
Cc: Tony Luck <tony.luck@...el.com>,
Dave Hansen <dave.hansen@...el.com>,
LKML Mailing List <linux-kernel@...r.kernel.org>,
X86-kernel <x86@...nel.org>,
Tom Lendacky <thomas.lendacky@....com>,
Arjan van de Ven <arjan.van.de.ven@...el.com>,
Jacob Jun Pan <jacob.jun.pan@...el.com>,
Ashok Raj <ashok.raj@...el.com>
Subject: [PATCH 03/13] x86/microcode/intel: Fix a hang if early loading microcode fails
When early loading of microcode fails for any reason other than the wrong
family-model-stepping, Linux can get into an infinite loop retrying the
same failed load.
A single retry is needed to handle any mixed stepping case.
Assume we have a microcode that fails to load for some reason.
load_ucode_ap() seems to retry if the loading fails. But it searches for
a new rev, but ends up finding the same copy. Hence it appears to repeat
the same load, retry loop for ever.
We can fix it as follows.
1) When the load_ucode_intel_bsp() fails, record the revision that failed.
2) In load_ucode_intel_ap() check if AP is same FMS as BP, and the code
that failed earlier isn't going to apply anyway. So use the saved
information to abort loading on AP's altogether.
load_ucode_intel_ap()
{
..
reget:
if (!*iup) {
patch = __load_ucode_intel(&uci);
^^^^^ Finds the same patch every time.
if (!patch)
return;
*iup = patch;
}
uci.mc = *iup;
if (apply_microcode_early(&uci, true)) {
^^^^^^^^^^^^ apply fails
/* Mixed-silicon system? Try to refetch the proper patch: */
*iup = NULL;
goto reget;
^^^^^ Rince repeat.
}
}
Fixes: 06b8534cb728 ("x86/microcode: Rework microcode loading")
Signed-off-by: Ashok Raj <ashok.raj@...el.com>
---
arch/x86/kernel/cpu/microcode/intel.c | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/arch/x86/kernel/cpu/microcode/intel.c b/arch/x86/kernel/cpu/microcode/intel.c
index cf1e2c30b230..0f7e4ba05c39 100644
--- a/arch/x86/kernel/cpu/microcode/intel.c
+++ b/arch/x86/kernel/cpu/microcode/intel.c
@@ -606,6 +606,7 @@ void __init load_ucode_intel_bsp(void)
{
struct microcode_intel *patch;
struct ucode_cpu_info uci;
+ int rev, ret;
patch = __load_ucode_intel(&uci);
if (!patch)
@@ -613,13 +614,18 @@ void __init load_ucode_intel_bsp(void)
uci.mc = patch;
- apply_microcode_early(&uci, true);
+ ret = apply_microcode_early(&uci, true);
+ if (ret) {
+ rev = patch->hdr.rev;
+ pr_err("Revision 0x%x failed during early loading\n", rev);
+ }
}
void load_ucode_intel_ap(void)
{
struct microcode_intel *patch, **iup;
struct ucode_cpu_info uci;
+ bool retried = false;
if (IS_ENABLED(CONFIG_X86_32))
iup = (struct microcode_intel **) __pa_nodebug(&intel_ucode_patch);
@@ -638,9 +644,13 @@ void load_ucode_intel_ap(void)
uci.mc = *iup;
if (apply_microcode_early(&uci, true)) {
+ if (retried)
+ return;
+
/* Mixed-silicon system? Try to refetch the proper patch: */
*iup = NULL;
+ retried = true;
goto reget;
}
}
--
2.34.1
Powered by blists - more mailing lists