From: "Chang S. Bae" <chang.seok.bae@intel.com>
To: linux-kernel@vger.kernel.org
Cc: x86@kernel.org, tglx@kernel.org, mingo@redhat.com, bp@alien8.de,
dave.hansen@linux.intel.com, kevin.shu@intel.com,
chang.seok.bae@intel.com
Subject: [PATCH RFC v1 8/8] x86/microcode/intel: Enable uniform loading
Date: Sat, 12 Sep 2026 00:08:14 +0000 [thread overview]
Message-ID: <20260912000815.997720-9-chang.seok.bae@intel.com> (raw)
In-Reply-To: <20260912000815.997720-1-chang.seok.bae@intel.com>
Uniform scopes are now available for both early- and late-loading paths.
This feature simplifies the loading process by reducing the number of
update triggers.
Ignoring the CPU's uniform scope results in more triggers than necessary.
While this behavior is acceptable, it can increase update latency,
particularly for the late-loading path. Enable the feature.
Certain invalid states, such as incomplete firmware configuration or an
unknown loading scope, can leave the update mechanism unreliable. Detect
those conditions early and disable the loader before any update occurs.
Module, tile, and die scopes are also possible, but currently reserved
for future implementations. Treat them as equivalent to the default
per-core scope.
Signed-off-by: Chang S. Bae <chang.seok.bae@intel.com>
---
arch/x86/include/asm/microcode.h | 2 +
arch/x86/include/asm/msr-index.h | 10 ++++
arch/x86/kernel/cpu/microcode/core.c | 5 ++
arch/x86/kernel/cpu/microcode/intel.c | 69 +++++++++++++++++++++++++++
4 files changed, 86 insertions(+)
diff --git a/arch/x86/include/asm/microcode.h b/arch/x86/include/asm/microcode.h
index 645e65ac1586..710b79aa03ec 100644
--- a/arch/x86/include/asm/microcode.h
+++ b/arch/x86/include/asm/microcode.h
@@ -21,11 +21,13 @@ void load_ucode_bsp(void);
void load_ucode_ap(void);
void microcode_bsp_resume(void);
bool __init microcode_loader_disabled(void);
+void __init microcode_disable_loader(void);
#else
static inline void load_ucode_bsp(void) { }
static inline void load_ucode_ap(void) { }
static inline void microcode_bsp_resume(void) { }
static inline bool __init microcode_loader_disabled(void) { return false; }
+static inline bool __init microcode_disable_loader(void) { }
#endif
extern unsigned long initrd_start_early;
diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h
index 3a8e51a0c9e8..6a412371e02f 100644
--- a/arch/x86/include/asm/msr-index.h
+++ b/arch/x86/include/asm/msr-index.h
@@ -975,7 +975,17 @@
#define MSR_IA32_UCODE_WRITE 0x00000079
#define MSR_IA32_MCU_ENUMERATION 0x0000007b
+#define MCU_UNIFORM_AVAIL BIT(0)
+#define MCU_UNIFORM_CONFIG_REQD BIT(1)
+#define MCU_UNIFORM_CONFIG_COMPLETE BIT(2)
#define MCU_STAGING BIT(4)
+#define MCU_UNIFORM_SCOPE GENMASK(15, 8)
+#define MCU_UNIFORM_SCOPE_CORE 0x02
+#define MCU_UNIFORM_SCOPE_MODULE 0x03
+#define MCU_UNIFORM_SCOPE_TILE 0x04
+#define MCU_UNIFORM_SCOPE_DIE 0x05
+#define MCU_UNIFORM_SCOPE_PACKAGE 0x80
+#define MCU_UNIFORM_SCOPE_PLATFORM 0xc0
#define MSR_IA32_UCODE_REV 0x0000008b
diff --git a/arch/x86/kernel/cpu/microcode/core.c b/arch/x86/kernel/cpu/microcode/core.c
index ed547f2b4601..887ffdc814de 100644
--- a/arch/x86/kernel/cpu/microcode/core.c
+++ b/arch/x86/kernel/cpu/microcode/core.c
@@ -111,6 +111,11 @@ static bool amd_check_current_patch_level(void)
return false;
}
+void __init microcode_disable_loader(void)
+{
+ dis_ucode_ldr = true;
+}
+
bool __init microcode_loader_disabled(void)
{
if (dis_ucode_ldr)
diff --git a/arch/x86/kernel/cpu/microcode/intel.c b/arch/x86/kernel/cpu/microcode/intel.c
index 6178bddb7f60..e6c2b693f30b 100644
--- a/arch/x86/kernel/cpu/microcode/intel.c
+++ b/arch/x86/kernel/cpu/microcode/intel.c
@@ -23,6 +23,7 @@
#include <linux/uio.h>
#include <linux/io.h>
#include <linux/mm.h>
+#include <linux/bitfield.h>
#include <asm/cpu_device_id.h>
#include <asm/cpuid/api.h>
@@ -69,6 +70,8 @@ static const char ucode_path[] = "kernel/x86/microcode/GenuineIntel.bin";
#define MBOX_XACTION_TIMEOUT_MS (10 * MSEC_PER_SEC)
+#define CPUID_EDX_ARCH_CAP BIT(29)
+
/* Current microcode patch used in early patching on the APs. */
static struct microcode_intel *ucode_patch_va __read_mostly;
static struct microcode_intel *ucode_patch_late __read_mostly;
@@ -737,11 +740,21 @@ static int __init save_builtin_microcode(void)
}
early_initcall(save_builtin_microcode);
+static __init void setup_uniform(void);
+
/* Load microcode on BSP from initrd or builtin blobs */
void __init load_ucode_intel_bsp(struct early_load_data *ed)
{
struct ucode_cpu_info uci;
+ /*
+ * The loader could be disabled during the uniform setup if any firmware
+ * misconfiguration is found.
+ */
+ setup_uniform();
+ if (microcode_loader_disabled())
+ return;
+
uci.mc = get_microcode_blob(&uci, false);
ed->old_rev = uci.cpu_sig.rev;
@@ -989,6 +1002,62 @@ static __init bool staging_available(void)
return !!(val & MCU_STAGING);
}
+static __init void setup_uniform(void)
+{
+ u64 val;
+
+ if (native_cpuid_eax(0) < 7)
+ return;
+
+ if (!(native_cpuid_edx(7) & CPUID_EDX_ARCH_CAP))
+ return;
+
+ if (!(native_rdmsrq(MSR_IA32_ARCH_CAPABILITIES) & ARCH_CAP_MCU_ENUM))
+ return;
+
+ val = native_rdmsrq(MSR_IA32_MCU_ENUMERATION);
+ if (!(val & MCU_UNIFORM_AVAIL))
+ return;
+
+ /*
+ * Ensure that the firmware did all the necessary steps. Any improper
+ * configuration makes the update mechanism unusable.
+ */
+ if (val & MCU_UNIFORM_CONFIG_REQD && !(val & MCU_UNIFORM_CONFIG_COMPLETE)) {
+ microcode_disable_loader();
+ pr_err("loading disabled: incomplete firmware configuration.\n");
+ return;
+ }
+
+ /*
+ * Configure the uniform scope accordingly. To make it simple, treat all
+ * scopes narrower than the package scope as per-core scope.
+ */
+ switch (FIELD_GET(MCU_UNIFORM_SCOPE, val)) {
+ case MCU_UNIFORM_SCOPE_MODULE:
+ case MCU_UNIFORM_SCOPE_TILE:
+ case MCU_UNIFORM_SCOPE_DIE:
+ pr_info("Uniform scope is narrower than package, using core scope.\n");
+ fallthrough;
+ case MCU_UNIFORM_SCOPE_CORE:
+ microcode_intel_ops.uniform_scope = UNIFORM_CORE;
+ break;
+ case MCU_UNIFORM_SCOPE_PACKAGE:
+ microcode_intel_ops.uniform_scope = UNIFORM_PKG;
+ break;
+ case MCU_UNIFORM_SCOPE_PLATFORM:
+ microcode_intel_ops.uniform_scope = UNIFORM_SYS;
+ break;
+ default:
+ microcode_disable_loader();
+ pr_err("loading disabled: unknown uniform scope.\n");
+ return;
+ }
+
+ microcode_intel_ops.use_uniform = true;
+ pr_info("Enabled uniform feature.\n");
+}
+
bool __init intel_primary_aware(void)
{
if (!microcode_intel_ops.use_uniform)
--
2.53.0
next prev parent reply other threads:[~2026-09-12 0:35 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-12 0:08 [PATCH RFC v1 0/8] x86/microcode: Enable uniform feature Chang S. Bae
2026-09-12 0:08 ` [PATCH RFC v1 1/8] cpu/hotplug: Allow architecture-specific primary CPU bringup Chang S. Bae
2026-09-12 0:08 ` [PATCH RFC v1 2/8] x86/hotplug: Implement SMT-primary selection for parallel bringup Chang S. Bae
2026-09-12 0:08 ` [PATCH RFC v1 3/8] x86/cpu/topology: Introduce primary core mask Chang S. Bae
2026-09-12 0:08 ` [PATCH RFC v1 4/8] x86/microcode: Extend struct microcode_ops for uniform loading Chang S. Bae
2026-09-12 0:08 ` [PATCH RFC v1 5/8] x86/microcode: Clarify online enforcement with " Chang S. Bae
2026-09-12 0:08 ` [PATCH RFC v1 6/8] x86/microcode: Support uniform scope for late loading Chang S. Bae
2026-09-12 0:08 ` [PATCH RFC v1 7/8] x86/microcode/intel: Support uniform scope for early loading Chang S. Bae
2026-09-12 0:08 ` Chang S. Bae [this message]
2026-09-16 0:45 ` [PATCH RFC v1 0/8] x86/microcode: Enable uniform feature Borislav Petkov
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260912000815.997720-9-chang.seok.bae@intel.com \
--to=chang.seok.bae@intel.com \
--cc=bp@alien8.de \
--cc=dave.hansen@linux.intel.com \
--cc=kevin.shu@intel.com \
--cc=linux-kernel@vger.kernel.org \
--cc=mingo@redhat.com \
--cc=tglx@kernel.org \
--cc=x86@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®