From nobody Fri Oct 3 21:53:40 2025 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.8]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 79D9723E352 for ; Sat, 23 Aug 2025 15:52:20 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.8 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755964343; cv=none; b=S2HP/p9R7JBIUmvRrRLUV25urphNPDWQ2oJ4HkL8fyytwVCKX88CbysMplbtrCbTHF3QlY2ZMauWMorTWfktLN11u8juFIJOVDoSoB5Dq/XOjXzZr3PoVa+LIIBmyuaIf9o6ZEADc3kIsL73WabGUDazHBO9si6YXjPjZxV8wpg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755964343; c=relaxed/simple; bh=Gg34nZmCyvn+O83V3Yqh6+BSEaUXFq4f9DlM0O6eqFU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Srhng9xBl6qSH4shjb2srC8Ytug0RsfPXdAVJcz3vAVZgySEb/BoLOfCzmmQWhscqTOV7q8lpoSXM/QOKcTQP8Mg5T1Bn/i7UWU5xaG8D+EVzHeECEztNJqAIJ8tuAPZJL6KanhTbQx5+CS/qOUsGmYeIgV3Lg/AY9yqeRwdtR8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=YyXFlKDB; arc=none smtp.client-ip=192.198.163.8 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="YyXFlKDB" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1755964342; x=1787500342; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=Gg34nZmCyvn+O83V3Yqh6+BSEaUXFq4f9DlM0O6eqFU=; b=YyXFlKDBeM/epjv5IYRTD3rRSeEFeiM1Pn80EZtUX5N5hCv2dpslmR2A tsjLGkHySP4Xz01Ih7hDw5Cf+kULyWvTWIolBNKg42JbFwUW5SuRPMFw6 nGreoPOBqYgeod01b+T683VpxJi5NQ/JXd/XhwHyvXOQ/kpNtmL/DdCsD p25zT5tXwsQaxOpBFQPHEIf45nVBgCa/kU66OxLO6S7gWVaUtIezmvBLW ogKJ+WVTzMF1VncXtleXwjnv5X5pbMea6JmHj2aupvi1BmEfy9HF9jSGf AZUtdJfj5X0/yoYIwvU50Xq52TdJjsnS9pUW7obkotwCoWxmvSRWUal4C w==; X-CSE-ConnectionGUID: NkORsQ6LTNuQcn+btXQmBw== X-CSE-MsgGUID: ih1D6oroQYOOw75faWknFg== X-IronPort-AV: E=McAfee;i="6800,10657,11531"; a="75832792" X-IronPort-AV: E=Sophos;i="6.17,312,1747724400"; d="scan'208";a="75832792" Received: from fmviesa010.fm.intel.com ([10.60.135.150]) by fmvoesa102.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 23 Aug 2025 08:52:20 -0700 X-CSE-ConnectionGUID: 5V5DUiA4TXSQoM4RkzWDjw== X-CSE-MsgGUID: 4R9D6fTwQ5u1VYOHagap2A== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.17,312,1747724400"; d="scan'208";a="169748223" Received: from cbae1-mobl.amr.corp.intel.com (HELO cbae1-mobl.intel.com) ([10.124.85.190]) by fmviesa010.fm.intel.com with ESMTP; 23 Aug 2025 08:52:18 -0700 From: "Chang S. Bae" To: linux-kernel@vger.kernel.org Cc: x86@kernel.org, tglx@linutronix.de, mingo@redhat.com, bp@alien8.de, dave.hansen@linux.intel.com, chao.gao@intel.com, abusse@amazon.de, chang.seok.bae@intel.com Subject: [PATCH v5 1/7] x86/cpu/topology: Make primary thread mask available with SMP=n Date: Sat, 23 Aug 2025 08:52:04 -0700 Message-ID: <20250823155214.17465-2-chang.seok.bae@intel.com> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20250823155214.17465-1-chang.seok.bae@intel.com> References: <20250813172649.15474-1-chang.seok.bae@intel.com> <20250823155214.17465-1-chang.seok.bae@intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" cpu_primary_thread_mask is only defined when CONFIG_SMP=3Dy. However, even in UP kernels there is always exactly one CPU, which can reasonably be treated as the primary thread. Historically, topology_is_primary_thread() always returned true with CONFIG_SMP=3Dn. A recent commit: 4b455f59945aa ("cpu/SMT: Provide a default topology_is_primary_thread()") replaced it with a generic implementation with the note: "When disabling SMT, the primary thread of the SMT will remain enabled/active. Architectures that have a special primary thread (e.g. x86) need to override this function. ..." For consistency and clarity, make the primary thread mask available regardless of SMP, similar to cpu_possible_mask and cpu_present_mask. Move __cpu_primary_thread_mask into common code to prevent build issues. Let cpu_mark_primary_thread() configure the mask even for UP kernels, alongside other masks. Then, topology_is_primary_thread() can consistently reference it. Signed-off-by: Chang S. Bae Reviewed-by: Tony Luck --- V4 -> V5: New patch Preparatory patch to set up the mask correctly before its new use in patch3. --- arch/x86/include/asm/topology.h | 12 ++++++------ arch/x86/kernel/cpu/topology.c | 4 ---- arch/x86/kernel/cpu/topology_common.c | 3 +++ arch/x86/kernel/smpboot.c | 3 --- 4 files changed, 9 insertions(+), 13 deletions(-) diff --git a/arch/x86/include/asm/topology.h b/arch/x86/include/asm/topolog= y.h index 6c79ee7c0957..281252af6e9d 100644 --- a/arch/x86/include/asm/topology.h +++ b/arch/x86/include/asm/topology.h @@ -218,6 +218,12 @@ static inline unsigned int topology_amd_nodes_per_pkg(= void) return __amd_nodes_per_pkg; } =20 +#else /* CONFIG_SMP */ +static inline int topology_phys_to_logical_pkg(unsigned int pkg) { return = 0; } +static inline int topology_max_smt_threads(void) { return 1; } +static inline unsigned int topology_amd_nodes_per_pkg(void) { return 1; } +#endif /* !CONFIG_SMP */ + extern struct cpumask __cpu_primary_thread_mask; #define cpu_primary_thread_mask ((const struct cpumask *)&__cpu_primary_th= read_mask) =20 @@ -231,12 +237,6 @@ static inline bool topology_is_primary_thread(unsigned= int cpu) } #define topology_is_primary_thread topology_is_primary_thread =20 -#else /* CONFIG_SMP */ -static inline int topology_phys_to_logical_pkg(unsigned int pkg) { return = 0; } -static inline int topology_max_smt_threads(void) { return 1; } -static inline unsigned int topology_amd_nodes_per_pkg(void) { return 1; } -#endif /* !CONFIG_SMP */ - static inline void arch_fix_phys_package_id(int num, u32 slot) { } diff --git a/arch/x86/kernel/cpu/topology.c b/arch/x86/kernel/cpu/topology.c index e35ccdc84910..f083023f7dd9 100644 --- a/arch/x86/kernel/cpu/topology.c +++ b/arch/x86/kernel/cpu/topology.c @@ -75,15 +75,11 @@ bool arch_match_cpu_phys_id(int cpu, u64 phys_id) return phys_id =3D=3D (u64)cpuid_to_apicid[cpu]; } =20 -#ifdef CONFIG_SMP static void cpu_mark_primary_thread(unsigned int cpu, unsigned int apicid) { if (!(apicid & (__max_threads_per_core - 1))) cpumask_set_cpu(cpu, &__cpu_primary_thread_mask); } -#else -static inline void cpu_mark_primary_thread(unsigned int cpu, unsigned int = apicid) { } -#endif =20 /* * Convert the APIC ID to a domain level ID by masking out the low bits diff --git a/arch/x86/kernel/cpu/topology_common.c b/arch/x86/kernel/cpu/to= pology_common.c index b5a5e1411469..71625795d711 100644 --- a/arch/x86/kernel/cpu/topology_common.c +++ b/arch/x86/kernel/cpu/topology_common.c @@ -16,6 +16,9 @@ EXPORT_SYMBOL_GPL(x86_topo_system); unsigned int __amd_nodes_per_pkg __ro_after_init; EXPORT_SYMBOL_GPL(__amd_nodes_per_pkg); =20 +/* CPUs which are the primary SMT threads */ +struct cpumask __cpu_primary_thread_mask __read_mostly; + void topology_set_dom(struct topo_scan *tscan, enum x86_topology_domains d= om, unsigned int shift, unsigned int ncpus) { diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index 33e166f6ab12..7804175d2d87 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -103,9 +103,6 @@ EXPORT_PER_CPU_SYMBOL(cpu_core_map); DEFINE_PER_CPU_READ_MOSTLY(cpumask_var_t, cpu_die_map); EXPORT_PER_CPU_SYMBOL(cpu_die_map); =20 -/* CPUs which are the primary SMT threads */ -struct cpumask __cpu_primary_thread_mask __read_mostly; - /* Representing CPUs for which sibling maps can be computed */ static cpumask_var_t cpu_sibling_setup_mask; =20 --=20 2.48.1 From nobody Fri Oct 3 21:53:40 2025 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.8]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 749C52222CA for ; Sat, 23 Aug 2025 15:52:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.8 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755964343; cv=none; b=sFxbNyXlSDSF9k8FwnglR+j459JiFGo5HhetBp3udqYZDBha5P15c78hqWz7fj71/tuD2WVLMIaBSwc9TV6jr+Zm/70w0/q6EhDJiMWNt4y+SNh6HoT19D0anm0xHjHjuALGeHyOSHqr7P3ag3f/Ni6vCODsyx81LGEVowZI5xI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755964343; c=relaxed/simple; bh=L97mc+FM3e6R49U9cy769SVCezMA7UhyhVjow4A4W7g=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=pGA1HG+n7dBvhpDS7RW55vG8vgCnQguCV4jwpM8ugMst04uIi4PwCtAc04PZDV/zuFupJFlt+VJGJ/iVHKbutLyXtAzY2br5eacrnEMXN4K+iKt9NXJlXmrgVTh/n5diyamhiGUSWZuvx7jmyF49hv/IS5wgfFdNfJmpfRAfQQk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=S1Xs3BMr; arc=none smtp.client-ip=192.198.163.8 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="S1Xs3BMr" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1755964342; x=1787500342; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=L97mc+FM3e6R49U9cy769SVCezMA7UhyhVjow4A4W7g=; b=S1Xs3BMr+vwXcTUIYnjmsCIly2Xbn0xfuicGyelv/vyl9FIfXMvtyVsz FjnikTYmDJZ0Yk9fyeQpl/N2assOnbgUVVlRkQf553OMbEG3+/HLtObr/ XH/S3YyVQhxhbfEBHQfy8SbCRqRSFO7mlU+Z4O+jslkf2CAuylifVl2bT 11lwNsa+g2J75uSaFLNAjuPbTxGxhGjKrzu9r8Q7P0mCs3N2MwcRYgQwj PNy4e/gFqoq3IcNoCPKXlieAAL1V6MlZVVlHsBx/U/Ac9AyUtTOc1lLv4 RWTTd+J3dg8NtOPOvBVVXoAHtmLjLvxSXQqp5T7BewjywZ/cddJeuNiv4 g==; X-CSE-ConnectionGUID: OvPMYqK0QjyGVR71REH9wg== X-CSE-MsgGUID: U29bAvHpQRCho3dI/nccCg== X-IronPort-AV: E=McAfee;i="6800,10657,11531"; a="75832798" X-IronPort-AV: E=Sophos;i="6.17,312,1747724400"; d="scan'208";a="75832798" Received: from fmviesa010.fm.intel.com ([10.60.135.150]) by fmvoesa102.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 23 Aug 2025 08:52:20 -0700 X-CSE-ConnectionGUID: X/mmExHIRFmRqwUxaY6A8g== X-CSE-MsgGUID: uRKG3OogTKKLdvPXRxun8w== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.17,312,1747724400"; d="scan'208";a="169748227" Received: from cbae1-mobl.amr.corp.intel.com (HELO cbae1-mobl.intel.com) ([10.124.85.190]) by fmviesa010.fm.intel.com with ESMTP; 23 Aug 2025 08:52:20 -0700 From: "Chang S. Bae" To: linux-kernel@vger.kernel.org Cc: x86@kernel.org, tglx@linutronix.de, mingo@redhat.com, bp@alien8.de, dave.hansen@linux.intel.com, chao.gao@intel.com, abusse@amazon.de, chang.seok.bae@intel.com Subject: [PATCH v5 2/7] x86/microcode: Introduce staging step to reduce late-loading time Date: Sat, 23 Aug 2025 08:52:05 -0700 Message-ID: <20250823155214.17465-3-chang.seok.bae@intel.com> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20250823155214.17465-1-chang.seok.bae@intel.com> References: <20250813172649.15474-1-chang.seok.bae@intel.com> <20250823155214.17465-1-chang.seok.bae@intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" As microcode patch sizes continue to grow, late-loading latency spikes can lead to timeouts and disruptions in running workloads. This trend of increasing patch sizes is expected to continue, so a foundational solution is needed to address the issue. To mitigate the problem, a new staging feature is introduced. This option processes most of the microcode update (excluding activation) on a non-critical path, allowing CPUs to remain operational during the majority of the update. By offloading work from the critical path, staging can significantly reduces latency spikes. Integrate staging as a preparatory step in late-loading. Introduce a new callback for staging, which is invoked at the beginning of load_late_stop_cpus(), before CPUs enter the rendezvous phase. Staging follows an opportunistic model: * If successful, it reduces CPU rendezvous time * Even though it fails, the process falls back to the legacy path to finish the loading process but with potentially higher latency. Extend struct microcode_ops to incorporate staging properties, which will be implemented in the vendor code separately. Signed-off-by: Chang S. Bae Tested-by: Anselm Busse Reviewed-by: Chao Gao Reviewed-by: Tony Luck --- V4 -> V5: * Collect Chao's review tag V1 -> V2: * Move invocation inside of load_late_stop_cpus() (Boris) * Add more note about staging (Dave) There were discussions about whether staging success should be enforced by a configurable option. That topic is identified as follow-up work, separate from this series. https://lore.kernel.org/lkml/54308373-7867-4b76-be34-63730953f83c@intel= .com/ --- arch/x86/kernel/cpu/microcode/core.c | 11 +++++++++++ arch/x86/kernel/cpu/microcode/internal.h | 4 +++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/arch/x86/kernel/cpu/microcode/core.c b/arch/x86/kernel/cpu/mic= rocode/core.c index b92e09a87c69..34e569ee1db2 100644 --- a/arch/x86/kernel/cpu/microcode/core.c +++ b/arch/x86/kernel/cpu/microcode/core.c @@ -552,6 +552,17 @@ static int load_late_stop_cpus(bool is_safe) pr_err("You should switch to early loading, if possible.\n"); } =20 + /* + * Pre-load the microcode image into a staging device. This + * process is preemptible and does not require stopping CPUs. + * Successful staging simplifies the subsequent late-loading + * process, reducing rendezvous time. + * + * Even if the transfer fails, the update will proceed as usual. + */ + if (microcode_ops->use_staging) + microcode_ops->stage_microcode(); + atomic_set(&late_cpus_in, num_online_cpus()); atomic_set(&offline_in_nmi, 0); loops_per_usec =3D loops_per_jiffy / (TICK_NSEC / 1000); diff --git a/arch/x86/kernel/cpu/microcode/internal.h b/arch/x86/kernel/cpu= /microcode/internal.h index 50a9702ae4e2..adf02ebbf7a3 100644 --- a/arch/x86/kernel/cpu/microcode/internal.h +++ b/arch/x86/kernel/cpu/microcode/internal.h @@ -31,10 +31,12 @@ struct microcode_ops { * See also the "Synchronization" section in microcode_core.c. */ enum ucode_state (*apply_microcode)(int cpu); + void (*stage_microcode)(void); int (*collect_cpu_info)(int cpu, struct cpu_signature *csig); void (*finalize_late_load)(int result); unsigned int nmi_safe : 1, - use_nmi : 1; + use_nmi : 1, + use_staging : 1; }; =20 struct early_load_data { --=20 2.48.1 From nobody Fri Oct 3 21:53:40 2025 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.8]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id BCAF629D294 for ; Sat, 23 Aug 2025 15:52:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.8 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755964343; cv=none; b=lVcfRs9wlJ8hyPkNGfXbk1Mcwj3ni1kZVHmOOs8jiHCbJtHOBpTjS7Yc3/XQllMnrpy19betYlm1Q7ns+pV2EcfJ/DRypuF64QwoQs+G+UDxtFZIk42BCU4eQfPAFALexbZuPXWBnzeBE/dDxZRHrQ59Ligc7C/mIpyKhSXz8VQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755964343; c=relaxed/simple; bh=Uud7x/kFOg3GusvE/Dmo+ob/jebuwykp9zsf6p/X4aw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=VEFdLcsVxugK4k7xUPjXN/a5l/sp0fbxnuiM4pji7k+2UFjxHbtRZidN7rrSMRBJtkedWxNiN6GerT/mKRAeb3nTlOfebVL2EiiP0PdxlHlcdVObr2bmg9jdLlBhRYZitYiywDybpDLZVKkdSgYecMsTmsL98QDUUfbkHuVRaF4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=lBPEeCgl; arc=none smtp.client-ip=192.198.163.8 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="lBPEeCgl" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1755964342; x=1787500342; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=Uud7x/kFOg3GusvE/Dmo+ob/jebuwykp9zsf6p/X4aw=; b=lBPEeCglkEcUS0dCcKwXjop78CDoRq2STK+SqMoYzHeRZIP2Z+dLwBQ8 8ZNV4FjbBqbGn4IwEqIpuWlcLxQlWmDiWC+uYtBsnH40igzyrXFodI3df XL5zBuvzWYZFKk2l0b+zV55PGNGO7Gs5vCO6vQWxGAzbI+eKRx2NXKBpA Po0o9Pls1SsHAFHnzWmJXdJrhNBYQWG+u1GsyrBmM4bbthafeBhiQ61Xf EhqnkRV9LG4wupkShBwi6EStqcsUcWCllrLKzIf2uf3OhWuT3oXWpTqt1 F9J4gV4wwVtQuPuJQqYNLEWqu9oaSMtxztVhDfxAc//OVUMYBIJEdPGVI Q==; X-CSE-ConnectionGUID: QrO9qYIxS4CI4qq5S3mHpQ== X-CSE-MsgGUID: nlzLY26yS/Gw8RBmJ5CQfA== X-IronPort-AV: E=McAfee;i="6800,10657,11531"; a="75832805" X-IronPort-AV: E=Sophos;i="6.17,312,1747724400"; d="scan'208";a="75832805" Received: from fmviesa010.fm.intel.com ([10.60.135.150]) by fmvoesa102.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 23 Aug 2025 08:52:21 -0700 X-CSE-ConnectionGUID: uQktACwlTs2Bl447PmWG+Q== X-CSE-MsgGUID: 37SbrWMOSRii2lfjNFjSGQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.17,312,1747724400"; d="scan'208";a="169748230" Received: from cbae1-mobl.amr.corp.intel.com (HELO cbae1-mobl.intel.com) ([10.124.85.190]) by fmviesa010.fm.intel.com with ESMTP; 23 Aug 2025 08:52:21 -0700 From: "Chang S. Bae" To: linux-kernel@vger.kernel.org Cc: x86@kernel.org, tglx@linutronix.de, mingo@redhat.com, bp@alien8.de, dave.hansen@linux.intel.com, chao.gao@intel.com, abusse@amazon.de, chang.seok.bae@intel.com Subject: [PATCH v5 3/7] x86/microcode/intel: Establish staging control logic Date: Sat, 23 Aug 2025 08:52:06 -0700 Message-ID: <20250823155214.17465-4-chang.seok.bae@intel.com> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20250823155214.17465-1-chang.seok.bae@intel.com> References: <20250813172649.15474-1-chang.seok.bae@intel.com> <20250823155214.17465-1-chang.seok.bae@intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" When microcode staging is initiated, operations are carried out through an MMIO interface. Each package has a unique interface specified by the IA32_MCU_STAGING_MBOX_ADDR MSR, which maps to a set of 32-bit registers. Prepare staging with the following steps: 1. Ensure the microcode image is 32-bit aligned to match the MMIO register size. 2. Identify each MMIO interface based on its per-package scope. 3. Invoke the staging function for each identified interface, which will be implemented separately. Also, define cpu_primary_thread_mask for the CONFIG_SMP=3Dn case, allowing consistent use when narrowing down primary threads to locate the per-package interface. Suggested-by: Thomas Gleixner Signed-off-by: Chang S. Bae Tested-by: Anselm Busse Link: https://lore.kernel.org/all/871pznq229.ffs@tglx Reviewed-by: Tony Luck --- V4 -> V5: * Rebase on the primary thread cpumask fix (Dave) * Clean up the rev print code (Dave) * rdmsrl_on_cpu() -> rdmsrq_on_cpu (Chao) V2 -> V3: * Remove a global variable and adjust stage_microcode() (Dave). * Simplify for_each_cpu() loop control code * Handle rdmsrl_on_cpu() return code explicitly (Chao) V1 -> V2: * Adjust to reference the staging_state struct. * Add lockdep_assert_cpus_held() (Boris) --- arch/x86/include/asm/msr-index.h | 2 ++ arch/x86/kernel/cpu/microcode/intel.c | 49 +++++++++++++++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-in= dex.h index b65c3ba5fa14..0356155f9264 100644 --- a/arch/x86/include/asm/msr-index.h +++ b/arch/x86/include/asm/msr-index.h @@ -913,6 +913,8 @@ #define MSR_IA32_UCODE_WRITE 0x00000079 #define MSR_IA32_UCODE_REV 0x0000008b =20 +#define MSR_IA32_MCU_STAGING_MBOX_ADDR 0x000007a5 + /* Intel SGX Launch Enclave Public Key Hash MSRs */ #define MSR_IA32_SGXLEPUBKEYHASH0 0x0000008C #define MSR_IA32_SGXLEPUBKEYHASH1 0x0000008D diff --git a/arch/x86/kernel/cpu/microcode/intel.c b/arch/x86/kernel/cpu/mi= crocode/intel.c index 371ca6eac00e..d309fb1f058f 100644 --- a/arch/x86/kernel/cpu/microcode/intel.c +++ b/arch/x86/kernel/cpu/microcode/intel.c @@ -299,6 +299,54 @@ static __init struct microcode_intel *scan_microcode(v= oid *data, size_t size, return size ? NULL : patch; } =20 +/* + * Handle the staging process using the mailbox MMIO interface. + * Return the result state. + */ +static enum ucode_state do_stage(u64 mmio_pa) +{ + pr_debug_once("Staging implementation is pending.\n"); + return UCODE_ERROR; +} + +static void stage_microcode(void) +{ + unsigned int pkg_id =3D UINT_MAX; + enum ucode_state ret; + int cpu, err; + u64 mmio_pa; + + if (!IS_ALIGNED(get_totalsize(&ucode_patch_late->hdr), sizeof(u32))) + return; + + lockdep_assert_cpus_held(); + + /* + * The MMIO address is unique per package, and all the SMT + * primary threads are online here. Find each MMIO space by + * their package ids to avoid duplicate staging. + */ + for_each_cpu(cpu, cpu_primary_thread_mask) { + if (topology_logical_package_id(cpu) =3D=3D pkg_id) + continue; + pkg_id =3D topology_logical_package_id(cpu); + + err =3D rdmsrq_on_cpu(cpu, MSR_IA32_MCU_STAGING_MBOX_ADDR, &mmio_pa); + if (WARN_ON_ONCE(err)) + return; + + ret =3D do_stage(mmio_pa); + if (ret !=3D UCODE_OK) { + pr_err("Error: staging failed with %s for CPU%d at package %u.\n", + ret =3D=3D UCODE_TIMEOUT ? "timeout" : "error state", + cpu, pkg_id); + return; + } + } + + pr_info("Staging of patch revision 0x%x succeeded.\n", ucode_patch_late->= hdr.rev); +} + static enum ucode_state __apply_microcode(struct ucode_cpu_info *uci, struct microcode_intel *mc, u32 *cur_rev) @@ -627,6 +675,7 @@ static struct microcode_ops microcode_intel_ops =3D { .collect_cpu_info =3D collect_cpu_info, .apply_microcode =3D apply_microcode_late, .finalize_late_load =3D finalize_late_load, + .stage_microcode =3D stage_microcode, .use_nmi =3D IS_ENABLED(CONFIG_X86_64), }; =20 --=20 2.48.1 From nobody Fri Oct 3 21:53:40 2025 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.8]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2268A2E8DE0 for ; Sat, 23 Aug 2025 15:52:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.8 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755964344; cv=none; b=iDcGJKRNvskSIOSvsE2FBIUrWHybaZrJ+6SGr/2P1cTsA/A+IhCa0IBIbY1zpIGiaRe4wChKan7k5e8w68j//iO+e3igubbTpBTdzbX9R0lia9ddg26lfoD1BSbeU1UkzvNA6h/zIBd4wjowdGQsfAz/KibGZhKv77MPH0Mj1Uw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755964344; c=relaxed/simple; bh=U3WZe67KVW53Wrj061ZZoAB+Wiwidzdr71kt/hN+IVE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=rZR8GueWbwI4IcbM/FxpqxNbX96EQJBU85csyD4pJAOGDbciFbDhVWEktcKiNeVsP/XYw8LY1P7RGNHdbVBxXYZ+tWMyLhlMyZ6GnvNZEHjVOXfwCSN7EadUCF7gWwrbbBkYFh63sVFZjPvcgQfyhNrl1slQewGPweGgwtl+oo4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=eCsSXpLT; arc=none smtp.client-ip=192.198.163.8 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="eCsSXpLT" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1755964343; x=1787500343; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=U3WZe67KVW53Wrj061ZZoAB+Wiwidzdr71kt/hN+IVE=; b=eCsSXpLTUzXTj5K6q0bnnO8rFOmegWP/Z0HKJQWUS1c7LmUGIs7SOAAO 6eMDSA4i11tUCdIvCcSjW/pU35FrENALq+OoPsXZ/VuYGpUvfeZvj0UXW iKYCtBLu6Sw4NkihbDqGt/vm5dpkwGnfeY+MBLRAPLGaOO1sF95pwseNj x718R6FkYZDPNF/729dzoKQhwaX5epG/uZQTlXQMOzWj0M1UfyGG7JIxp Jq26SwJLq3Fd6RXG6ohTm1390wKiTJDvjZ4gsy7P3AsPxPxREt5+QTEkg q2Vj5xotM8T+oNoUliEoefEdQokaHvO0eOmwgavMFYNkU4pVFRJu+wQWI A==; X-CSE-ConnectionGUID: BHyGT22pRA651PLpBI10Zw== X-CSE-MsgGUID: imz5YIQpTQy/0iM3Dcgy7g== X-IronPort-AV: E=McAfee;i="6800,10657,11531"; a="75832812" X-IronPort-AV: E=Sophos;i="6.17,312,1747724400"; d="scan'208";a="75832812" Received: from fmviesa010.fm.intel.com ([10.60.135.150]) by fmvoesa102.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 23 Aug 2025 08:52:22 -0700 X-CSE-ConnectionGUID: eRX3GnGVRDWa+sbcQXIVgQ== X-CSE-MsgGUID: s3aJnEWhTj6Dd458dJAR2A== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.17,312,1747724400"; d="scan'208";a="169748234" Received: from cbae1-mobl.amr.corp.intel.com (HELO cbae1-mobl.intel.com) ([10.124.85.190]) by fmviesa010.fm.intel.com with ESMTP; 23 Aug 2025 08:52:22 -0700 From: "Chang S. Bae" To: linux-kernel@vger.kernel.org Cc: x86@kernel.org, tglx@linutronix.de, mingo@redhat.com, bp@alien8.de, dave.hansen@linux.intel.com, chao.gao@intel.com, abusse@amazon.de, chang.seok.bae@intel.com Subject: [PATCH v5 4/7] x86/microcode/intel: Define staging state struct Date: Sat, 23 Aug 2025 08:52:07 -0700 Message-ID: <20250823155214.17465-5-chang.seok.bae@intel.com> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20250823155214.17465-1-chang.seok.bae@intel.com> References: <20250813172649.15474-1-chang.seok.bae@intel.com> <20250823155214.17465-1-chang.seok.bae@intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" To facilitate a structured staging handler, a set of functions will be introduced. Define staging_state struct to simplify function prototypes by consolidating relevant data, instead of passing multiple local variables. Signed-off-by: Chang S. Bae Tested-by: Anselm Busse Reviewed-by: Tony Luck --- V4 -> V5: Drop the ucode_ptr field (Dave) V1 -> V2: New patch Prior to V2, local variables were used to track state values, with the intention of improving readability by explicitly passing them between functions. However, given feedbacks, introducing a dedicated data structure looks to provide a benefit by simplifying the main loop. --- arch/x86/kernel/cpu/microcode/intel.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/arch/x86/kernel/cpu/microcode/intel.c b/arch/x86/kernel/cpu/mi= crocode/intel.c index d309fb1f058f..3ca22457d839 100644 --- a/arch/x86/kernel/cpu/microcode/intel.c +++ b/arch/x86/kernel/cpu/microcode/intel.c @@ -54,6 +54,25 @@ struct extended_sigtable { struct extended_signature sigs[]; }; =20 +/** + * struct staging_state - Tracks the current staging process state + * + * @mmio_base: MMIO base address for staging + * @ucode_len: Total size of the microcode image + * @chunk_size: Size of each data piece + * @bytes_sent: Total bytes transmitted so far + * @offset: Current offset in the microcode image + * @state: Current state of the staging process + */ +struct staging_state { + void __iomem *mmio_base; + unsigned int ucode_len; + unsigned int chunk_size; + unsigned int bytes_sent; + unsigned int offset; + enum ucode_state state; +}; + #define DEFAULT_UCODE_TOTALSIZE (DEFAULT_UCODE_DATASIZE + MC_HEADER_SIZE) #define EXT_HEADER_SIZE (sizeof(struct extended_sigtable)) #define EXT_SIGNATURE_SIZE (sizeof(struct extended_signature)) --=20 2.48.1 From nobody Fri Oct 3 21:53:40 2025 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.8]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1F09F2E972E for ; Sat, 23 Aug 2025 15:52:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.8 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755964345; cv=none; b=SNDbQaJBYFFAG5T29BQ0+/g61dh2wSojWMsRqTHaHXrWi/Ew780ZW7Jl2csARJ1kyzQpkp9lthlnNDQqcJVih9vfrY532vQO8dhmFZZsrT5WirelIOp6nIZsO/W/YJBv3/44HnrTN3qrZJmj8Wi4dr9oaA0Ueo46Ph/ykYW1Ygo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755964345; c=relaxed/simple; bh=+NHb2Cj+YRmDz2jUfs/X7Xja6xMCOyN80MXM0sfpC5Y=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Ew/ktuAPqtcFcC6tMQooTA6nTyA2XaxlkxcqV6xknv1/PrY7zt8+DFv8bIVSfHwOXr1//igIna8iL0bgLkZLs20DT74CdOhJKC2Tv/JQlRrBewtMivKfag/p3iUOZ6ECC5KTl1XC/mvnYI/Hkg7pe2OE0FUNg1rDWDyuo5xo6N8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=QVgq9snX; arc=none smtp.client-ip=192.198.163.8 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="QVgq9snX" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1755964344; x=1787500344; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=+NHb2Cj+YRmDz2jUfs/X7Xja6xMCOyN80MXM0sfpC5Y=; b=QVgq9snXMLajtnLmgc2HQpP3QCGbpqjK4eIQ3BR7Thqu/roKPXGfY66c HNilrnj5V9OJE5SouQNLBoQ0g6gkvHjt5loTT43J7njjETgiuc9f6anbZ /IOuCSm0MfFqPvIHV/1b1B/fg9S9rYn/gT3wPfyEoC5u8c/Bvw42aO8Bl 0HpiTyGCQZXyOgFXpyBH/DuGuev/pgOmWoRVIuddpxF9M5pPoH5Xxvej9 ZfmAIRTOJMmIyj2OLtpanhE8d+cdQXAB7j3w1WJQxximYgVuu8B4ClJk6 n+2keMCfnTt2ryF3PY3XZIcxH5QzIN/I6h/sRDSp1+as1ICNd9llE3HUo Q==; X-CSE-ConnectionGUID: +bP+vbo0Qo+lMZjH5b+oaw== X-CSE-MsgGUID: VLzhhDh7SEyb9Y7qKCjk2Q== X-IronPort-AV: E=McAfee;i="6800,10657,11531"; a="75832818" X-IronPort-AV: E=Sophos;i="6.17,312,1747724400"; d="scan'208";a="75832818" Received: from fmviesa010.fm.intel.com ([10.60.135.150]) by fmvoesa102.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 23 Aug 2025 08:52:23 -0700 X-CSE-ConnectionGUID: yRUoPYvkQ1q52skpGzjaOw== X-CSE-MsgGUID: r/6VSp3zQJ2HGYemLQGjxQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.17,312,1747724400"; d="scan'208";a="169748239" Received: from cbae1-mobl.amr.corp.intel.com (HELO cbae1-mobl.intel.com) ([10.124.85.190]) by fmviesa010.fm.intel.com with ESMTP; 23 Aug 2025 08:52:23 -0700 From: "Chang S. Bae" To: linux-kernel@vger.kernel.org Cc: x86@kernel.org, tglx@linutronix.de, mingo@redhat.com, bp@alien8.de, dave.hansen@linux.intel.com, chao.gao@intel.com, abusse@amazon.de, chang.seok.bae@intel.com Subject: [PATCH v5 5/7] x86/microcode/intel: Implement staging handler Date: Sat, 23 Aug 2025 08:52:08 -0700 Message-ID: <20250823155214.17465-6-chang.seok.bae@intel.com> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20250823155214.17465-1-chang.seok.bae@intel.com> References: <20250813172649.15474-1-chang.seok.bae@intel.com> <20250823155214.17465-1-chang.seok.bae@intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Previously, per-package staging invocations and their associated state data were established. The next step is to implement the actual staging handler according to the specified protocol. Below are key aspects to note: (a) Each staging process must begin by resetting the staging hardware. (b) The staging hardware processes up to a page-sized chunk of the microcode image per iteration, requiring software to submit data incrementally. (c) Once a data chunk is processed, the hardware responds with an offset in the image for the next chunk. (d) The offset may indicate completion or request retransmission of an already transferred chunk. As long as the total transferred data remains within the predefined limit (twice the image size), retransmissions should be acceptable. With that, incorporate these code sequences to the staging handler: 1. Initialization: Map the MMIO space via ioremap(). Reset the staging hardware and initialize software state, ensuring a fresh staging process aligned with (a). 2. Processing Loop: Introduce a loop iterating over data chunk, following (b), with proper termination conditions established from (d) -- stop staging when the hardware signals completion, or if the total transmitted data exceeds the predefined limit. 3. Loop Body: Finally, compose the loop body with two steps -- transmitting a data chunk and retrieving the next offset from the hardware response, aligning with (b) and (c). Since data transmission and mailbox format handling require additional details, they are implemented separately in next changes. Signed-off-by: Chang S. Bae Tested-by: Anselm Busse Reviewed-by: Tony Luck --- V4 -> V5: * Convert helper functions to return error codes (Dave) * Consolidate loop-control logic * Refactor next-chunk calculation/check for clarity * Remove offset sanity check (moved to next patch) V2 -> V3: * Rework code to eliminate global variables (Dave) * Remove redundant variable resets (Chao) V1 -> V2: * Re-write the changelog for clarity (Dave). * Move staging handling code into intel.c (Boris). * Add extensive comments to clarify staging logic and hardware interactions, along with function renaming (Dave). --- arch/x86/kernel/cpu/microcode/intel.c | 137 +++++++++++++++++++++++++- 1 file changed, 133 insertions(+), 4 deletions(-) diff --git a/arch/x86/kernel/cpu/microcode/intel.c b/arch/x86/kernel/cpu/mi= crocode/intel.c index 3ca22457d839..a1b13202330d 100644 --- a/arch/x86/kernel/cpu/microcode/intel.c +++ b/arch/x86/kernel/cpu/microcode/intel.c @@ -20,6 +20,8 @@ #include #include #include +#include +#include =20 #include #include @@ -33,6 +35,16 @@ static const char ucode_path[] =3D "kernel/x86/microcode= /GenuineIntel.bin"; =20 #define UCODE_BSP_LOADED ((struct microcode_intel *)0x1UL) =20 +/* Defines for the microcode staging mailbox interface */ + +#define MBOX_REG_NUM 4 +#define MBOX_REG_SIZE sizeof(u32) + +#define MBOX_CONTROL_OFFSET 0x0 +#define MBOX_STATUS_OFFSET 0x4 + +#define MASK_MBOX_CTRL_ABORT BIT(0) + /* 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; @@ -319,13 +331,130 @@ static __init struct microcode_intel *scan_microcode= (void *data, size_t size, } =20 /* - * Handle the staging process using the mailbox MMIO interface. - * Return the result state. + * Prepare for a new microcode transfer: reset hardware and record the + * image size. + */ +static void init_stage(struct staging_state *ss) +{ + ss->ucode_len =3D get_totalsize(&ucode_patch_late->hdr); + + /* + * Abort any ongoing process, effectively resetting the device. + * Unlike regular mailbox data processing requests, this + * operation does not require a status check. + */ + writel(MASK_MBOX_CTRL_ABORT, ss->mmio_base + MBOX_CONTROL_OFFSET); +} + +/* + * Return PAGE_SIZE, or remaining bytes if this is the final chunk + */ +static inline unsigned int calc_next_chunk_size(unsigned int ucode_len, un= signed int offset) +{ + return min(PAGE_SIZE, ucode_len - offset); +} + +/* + * Update the chunk size and decide whether another chunk can be sent. + * This accounts for remaining data and retry limits. + */ +static bool can_send_next_chunk(struct staging_state *ss) +{ + ss->chunk_size =3D calc_next_chunk_size(ss->ucode_len, ss->offset); + /* + * Each microcode image is divided into chunks, each at most + * one page size. A 10-chunk image would typically require 10 + * transactions. + * + * However, the hardware managing the mailbox has limited + * resources and may not cache the entire image, potentially + * requesting the same chunk multiple times. + * + * To tolerate this behavior, allow up to twice the expected + * number of transactions (i.e., a 10-chunk image can take up to + * 20 attempts). + * + * If the number of attempts exceeds this limit, the hardware is + * likely stuck and mark the state as timeout. + */ + if (ss->bytes_sent + ss->chunk_size > ss->ucode_len * 2) { + ss->state =3D UCODE_TIMEOUT; + return false; + } + + return true; +} + +/* + * Determine whether staging is complete: either the hardware signaled + * the end offset, or no more transactions are permitted (retry limit + * reached). + */ +static inline bool staging_is_complete(struct staging_state *ss) +{ + return (ss->offset =3D=3D UINT_MAX) || !can_send_next_chunk(ss); +} + +/* + * Transmit a chunk of the microcode image to the hardware. + * Return 0 on success, or an error code on failure. + */ +static int send_data_chunk(struct staging_state *ss, void *ucode_ptr __may= be_unused) +{ + pr_debug_once("Staging mailbox loading code needs to be implemented.\n"); + ss->state =3D UCODE_ERROR; + return -EPROTONOSUPPORT; +} + +/* + * Retrieve the next offset from the hardware response. + * Return 0 on success, or an error code on failure. + */ +static int fetch_next_offset(struct staging_state *ss) +{ + pr_debug_once("Staging mailbox response handling code needs to be impleme= nted.\n\n"); + ss->state =3D UCODE_ERROR; + return -EPROTONOSUPPORT; +} + +/* + * Handle the staging process using the mailbox MMIO interface. The + * microcode image is transferred in chunks until completion. Return the + * result state. */ static enum ucode_state do_stage(u64 mmio_pa) { - pr_debug_once("Staging implementation is pending.\n"); - return UCODE_ERROR; + struct staging_state ss =3D {}; + int err; + + ss.mmio_base =3D ioremap(mmio_pa, MBOX_REG_NUM * MBOX_REG_SIZE); + if (WARN_ON_ONCE(!ss.mmio_base)) + return UCODE_ERROR; + + init_stage(&ss); + + /* Perform the staging process while within the retry limit */ + while (!staging_is_complete(&ss)) { + /* Send a chunk of microcode each time: */ + err =3D send_data_chunk(&ss, ucode_patch_late); + if (err) + break; + /* + * Then, ask the hardware which piece of the image it + * needs next. The same piece may be sent more than once. + */ + err =3D fetch_next_offset(&ss); + if (err) + break; + } + + iounmap(ss.mmio_base); + + /* + * The helpers update ss.state on error. The final state is + * returned to the caller. + */ + return ss.state; } =20 static void stage_microcode(void) --=20 2.48.1 From nobody Fri Oct 3 21:53:40 2025 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.8]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D9C1E2E9EB6 for ; Sat, 23 Aug 2025 15:52:24 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.8 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755964346; cv=none; b=M/DFYdfnLQs6If9UrkhRatTbSkHwOzWjKujD/XBKHpdHyhQuMGx0aXIduDbx4HbDb93bgtmwW0cDhVUU5klHSwjem6GVxnkMejnJSHrFsZf7oKvF1A/TWSFNM+t7UybYXUKk5HEdF5qVvVc8wDCdY+wlrBJQscrJJJT3p5ceaAc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755964346; c=relaxed/simple; bh=oOCHdwhJ2hlEVHdewE67M/hBZ7Bq05iNcMK6LOevBAQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=SAJieKvhwG2eXsTDP8YnYxUcvfzTqNZ6bLe3d6sD9x+c1Q2NECuGBrpfkts1k5v5d4IdCLaaeaabIuznNh2I6SKBTTAFM8fZuQkhmpCE4MdjuFo27Rtos5el5Nh9MSO4P3IqmZONhqXtPuwJChGj8l32px5MVRoQneH/i8g77WA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=D8yx24Ye; arc=none smtp.client-ip=192.198.163.8 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="D8yx24Ye" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1755964345; x=1787500345; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=oOCHdwhJ2hlEVHdewE67M/hBZ7Bq05iNcMK6LOevBAQ=; b=D8yx24Yedvjm8daUjlbx+5dnUBNKVh6LNFeUaWJS1HE7u8YdVjqXFA0Z ffCWV7kAfdZBVveAWHi85gRbcHOrhbAv4HOwf4Imdx7jwefpQr3sCDjQy BSKYQLWvQKgYcXcT3Ih0zGf7R8PN/lFzyWlXK9hsbklwAn6A6r2SOiHB5 Zi7eAmR5IhyL+ox1G82JBzhObVanNyBhVHMJem0OUdobYXn9uHJ3sQKUw adAPCO+WA9HmaOsby/Ombn+P9S8TCEulKX7ap3CZvOANIGR1BNmfX5UlQ fhX8dM8oIf9mfAs+FmOAtTzIlGyj69Vlz3pW8WivWRPO/NSRsH6BLFCxZ g==; X-CSE-ConnectionGUID: pQg7VnQFQkm2xC+VOSgEnQ== X-CSE-MsgGUID: qJkM+pVtQx2nj2RgGc4hLw== X-IronPort-AV: E=McAfee;i="6800,10657,11531"; a="75832825" X-IronPort-AV: E=Sophos;i="6.17,312,1747724400"; d="scan'208";a="75832825" Received: from fmviesa010.fm.intel.com ([10.60.135.150]) by fmvoesa102.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 23 Aug 2025 08:52:24 -0700 X-CSE-ConnectionGUID: Nfh+ptDhRTS6vjQ40Cnt9A== X-CSE-MsgGUID: 5ECjXZgBS0+xtuMJG+900A== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.17,312,1747724400"; d="scan'208";a="169748243" Received: from cbae1-mobl.amr.corp.intel.com (HELO cbae1-mobl.intel.com) ([10.124.85.190]) by fmviesa010.fm.intel.com with ESMTP; 23 Aug 2025 08:52:24 -0700 From: "Chang S. Bae" To: linux-kernel@vger.kernel.org Cc: x86@kernel.org, tglx@linutronix.de, mingo@redhat.com, bp@alien8.de, dave.hansen@linux.intel.com, chao.gao@intel.com, abusse@amazon.de, chang.seok.bae@intel.com Subject: [PATCH v5 6/7] x86/microcode/intel: Support mailbox transfer Date: Sat, 23 Aug 2025 08:52:09 -0700 Message-ID: <20250823155214.17465-7-chang.seok.bae@intel.com> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20250823155214.17465-1-chang.seok.bae@intel.com> References: <20250813172649.15474-1-chang.seok.bae@intel.com> <20250823155214.17465-1-chang.seok.bae@intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Previously, the functions for sending microcode data and retrieving the next offset were placeholders, as they required handling the specific mailbox format. Implement them as following: =3D=3D Mailbox Format =3D=3D The staging mailbox consists of two primary sections: 'header' and 'data'. While the microcode must be transferred following this format, the actual data transfer mechanism involves reading and writing to specific MMIO registers. =3D=3D Mailbox Data Registers =3D=3D Unlike conventional interfaces that allocate MMIO space for each data chunk, the staging interface features a "narrow" interface, using only two dword-sized registers for read and write operations. For example, if writing 2 dwords of data to a device. Typically, the device would expose 2 dwords of "wide" MMIO space. To send the data to the device: writel(buf[0], io_addr + 0); writel(buf[1], io_addr + 1); But, this interface is a bit different. Instead of having a "wide" interface where there is separate MMIO space for each word in a transaction, it has a "narrow" interface where several words are written to the same spot in MMIO space: writel(buf[0], io_addr); writel(buf[1], io_addr); The same goes for the read side. =3D=3D Implementation Summary =3D=3D Given that, introduce two layers of helper functions at first: * Low-level helpers for reading and writing to data registers directly. * Wrapper functions for handling mailbox header and data sections. Using them, implement send_data_chunk() and fetch_next_offset() functions. Add explicit error and timeout handling routine in wait_for_transaction(), finishing up the transfer. Both hardware error states and implicit errors -- invalid header or offset -- result in UCODE_ERROR. Emit a clear message for the latter. Note: The kernel has support for similar mailboxes. But none of them are compatible with this one. Trying to share code resulted in a bloated mess, so this code is standalone. Signed-off-by: Chang S. Bae Tested-by: Anselm Busse Reviewed-by: Tony Luck --- V4 -> V5: Addressed Dave's feedback * fetch_next_offset(): - Make dword reads explicit - Consolidate offset validation -- adding another user for the end-offset checker - Convert WARN_* with pr_err_once() * Simplify transaction waiting logic a bit V2 -> V3: * Update code to reflect the removal of a global variable (Dave). V1 -> V2: * Add lots of code comments and edit the changelog (Dave). * Encapsulate register read/write operations for processing header and data sections. --- arch/x86/kernel/cpu/microcode/intel.c | 186 +++++++++++++++++++++++++- 1 file changed, 179 insertions(+), 7 deletions(-) diff --git a/arch/x86/kernel/cpu/microcode/intel.c b/arch/x86/kernel/cpu/mi= crocode/intel.c index a1b13202330d..f6b365eba6a2 100644 --- a/arch/x86/kernel/cpu/microcode/intel.c +++ b/arch/x86/kernel/cpu/microcode/intel.c @@ -22,6 +22,7 @@ #include #include #include +#include =20 #include #include @@ -42,8 +43,31 @@ static const char ucode_path[] =3D "kernel/x86/microcode= /GenuineIntel.bin"; =20 #define MBOX_CONTROL_OFFSET 0x0 #define MBOX_STATUS_OFFSET 0x4 +#define MBOX_WRDATA_OFFSET 0x8 +#define MBOX_RDDATA_OFFSET 0xc =20 #define MASK_MBOX_CTRL_ABORT BIT(0) +#define MASK_MBOX_CTRL_GO BIT(31) + +#define MASK_MBOX_STATUS_ERROR BIT(2) +#define MASK_MBOX_STATUS_READY BIT(31) + +#define MASK_MBOX_RESP_SUCCESS BIT(0) +#define MASK_MBOX_RESP_PROGRESS BIT(1) +#define MASK_MBOX_RESP_ERROR BIT(2) + +#define MBOX_CMD_LOAD 0x3 +#define MBOX_OBJ_STAGING 0xb +#define MBOX_HEADER(size) ((PCI_VENDOR_ID_INTEL) | \ + (MBOX_OBJ_STAGING << 16) | \ + ((u64)((size) / sizeof(u32)) << 32)) + +/* The size of each mailbox header */ +#define MBOX_HEADER_SIZE sizeof(u64) +/* The size of staging hardware response */ +#define MBOX_RESPONSE_SIZE sizeof(u64) + +#define MBOX_XACTION_TIMEOUT_MS (10 * MSEC_PER_SEC) =20 /* Current microcode patch used in early patching on the APs. */ static struct microcode_intel *ucode_patch_va __read_mostly; @@ -330,6 +354,49 @@ static __init struct microcode_intel *scan_microcode(v= oid *data, size_t size, return size ? NULL : patch; } =20 +static inline u32 read_mbox_dword(void __iomem *mmio_base) +{ + u32 dword =3D readl(mmio_base + MBOX_RDDATA_OFFSET); + + /* Acknowledge read completion to the staging hardware */ + writel(0, mmio_base + MBOX_RDDATA_OFFSET); + return dword; +} + +static inline void write_mbox_dword(void __iomem *mmio_base, u32 dword) +{ + writel(dword, mmio_base + MBOX_WRDATA_OFFSET); +} + +static inline u64 read_mbox_header(void __iomem *mmio_base) +{ + u32 high, low; + + low =3D read_mbox_dword(mmio_base); + high =3D read_mbox_dword(mmio_base); + + return ((u64)high << 32) | low; +} + +static inline void write_mbox_header(void __iomem *mmio_base, u64 value) +{ + write_mbox_dword(mmio_base, value); + write_mbox_dword(mmio_base, value >> 32); +} + +static void write_mbox_data(void __iomem *mmio_base, u32 *chunk, unsigned = int chunk_bytes) +{ + int i; + + /* + * The MMIO space is mapped as Uncached (UC). Each write arrives + * at the device as an individual transaction in program order. + * The device can then resemble the sequence accordingly. + */ + for (i =3D 0; i < chunk_bytes / sizeof(u32); i++) + write_mbox_dword(mmio_base, chunk[i]); +} + /* * Prepare for a new microcode transfer: reset hardware and record the * image size. @@ -385,6 +452,14 @@ static bool can_send_next_chunk(struct staging_state *= ss) return true; } =20 +/* + * The hardware indicates completion by returning a sentinel end offset + */ +static inline bool is_end_offset(u32 offset) +{ + return offset =3D=3D UINT_MAX; +} + /* * Determine whether staging is complete: either the hardware signaled * the end offset, or no more transactions are permitted (retry limit @@ -392,18 +467,73 @@ static bool can_send_next_chunk(struct staging_state = *ss) */ static inline bool staging_is_complete(struct staging_state *ss) { - return (ss->offset =3D=3D UINT_MAX) || !can_send_next_chunk(ss); + return is_end_offset(ss->offset) || !can_send_next_chunk(ss); +} + +/* + * Wait for the hardware to complete a transaction. + * Return 0 on success, or an error code on failure. + */ +static int wait_for_transaction(struct staging_state *ss) +{ + u32 timeout, status; + + /* Allow time for hardware to complete the operation: */ + for (timeout =3D 0; timeout < MBOX_XACTION_TIMEOUT_MS; timeout++) { + msleep(1); + + status =3D readl(ss->mmio_base + MBOX_STATUS_OFFSET); + /* Break out early if the hardware is ready: */ + if (status & MASK_MBOX_STATUS_READY) + break; + } + + /* Check for explicit error response */ + if (status & MASK_MBOX_STATUS_ERROR) { + ss->state =3D UCODE_ERROR; + return -EPROTO; + } + + /* + * Hardware is neither responded to the action nor signaled any + * error. Treat this as timeout. + */ + if (!(status & MASK_MBOX_STATUS_READY)) { + ss->state =3D UCODE_TIMEOUT; + return -ETIMEDOUT; + } + + ss->state =3D UCODE_OK; + return 0; } =20 /* * Transmit a chunk of the microcode image to the hardware. * Return 0 on success, or an error code on failure. */ -static int send_data_chunk(struct staging_state *ss, void *ucode_ptr __may= be_unused) +static int send_data_chunk(struct staging_state *ss, void *ucode_ptr) { - pr_debug_once("Staging mailbox loading code needs to be implemented.\n"); - ss->state =3D UCODE_ERROR; - return -EPROTONOSUPPORT; + u32 *src_chunk =3D ucode_ptr + ss->offset; + u16 mbox_size; + + /* + * Write a 'request' mailbox object in this order: + * 1. Mailbox header includes total size + * 2. Command header specifies the load operation + * 3. Data section contains a microcode chunk + * + * Thus, the mailbox size is two headers plus the chunk size. + */ + mbox_size =3D MBOX_HEADER_SIZE * 2 + ss->chunk_size; + write_mbox_header(ss->mmio_base, MBOX_HEADER(mbox_size)); + write_mbox_header(ss->mmio_base, MBOX_CMD_LOAD); + write_mbox_data(ss->mmio_base, src_chunk, ss->chunk_size); + ss->bytes_sent +=3D ss->chunk_size; + + /* Notify the hardware that the mailbox is ready for processing. */ + writel(MASK_MBOX_CTRL_GO, ss->mmio_base + MBOX_CONTROL_OFFSET); + + return wait_for_transaction(ss); } =20 /* @@ -412,9 +542,51 @@ static int send_data_chunk(struct staging_state *ss, v= oid *ucode_ptr __maybe_unu */ static int fetch_next_offset(struct staging_state *ss) { - pr_debug_once("Staging mailbox response handling code needs to be impleme= nted.\n\n"); + const u64 expected_header =3D MBOX_HEADER(MBOX_HEADER_SIZE + MBOX_RESPONS= E_SIZE); + u32 offset, status; + u64 header; + int err; + + /* + * The 'response' mailbox returns three fields, in order: + * 1. Header + * 2. Next offset in the microcode image + * 3. Status flags + */ + header =3D read_mbox_header(ss->mmio_base); + offset =3D read_mbox_dword(ss->mmio_base); + status =3D read_mbox_dword(ss->mmio_base); + + /* All valid responses must start with the expected header. */ + if (header !=3D expected_header) { + pr_err_once("staging: invalid response header\n"); + err =3D -EINVAL; + goto err_out; + } + + /* + * Verify the offset: If not at the end marker, it must not + * exceed the microcode image length + */ + if (!is_end_offset(offset) && offset > ss->ucode_len) { + pr_err_once("staging: invalid response offset\n"); + err =3D -EINVAL; + goto err_out; + } + + /* Hardware may report errors explicitly in the status field */ + if (status & MASK_MBOX_RESP_ERROR) { + err =3D -EPROTO; + goto err_out; + } + + ss->offset =3D offset; + ss->state =3D UCODE_OK; + return 0; + +err_out: ss->state =3D UCODE_ERROR; - return -EPROTONOSUPPORT; + return err; } =20 /* --=20 2.48.1 From nobody Fri Oct 3 21:53:40 2025 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.8]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9108D2EA148 for ; Sat, 23 Aug 2025 15:52:25 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.8 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755964347; cv=none; b=XWhQ9aO1rVwMpqPcM9mSCq7ljimWVm9Frf3dFRSJqTI/jZ0JLsC9bvkee0SYQBHT2YXJCQD1ZpRxebMw2O2hbTBQAqkcfZUQ9hjU7EYFpwk2xeCJ+FXyKxYaCvgFY7L25w8Z++MbvKYEFShBzWa64cQ1Q1Zus7z5KlqLdaSuUIA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755964347; c=relaxed/simple; bh=msJTNaNSQ6qHiQGGVHZ28t+lSU4y4Ql7Ojc6kM+547k=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Jqob2M6tK4uUqYO6YeKJ9edYJOdTo7wReCiko0ZfdGhhpk9v17mpq/j2ijtTUPCPUf/w+77aa7yfz5t2uJFPGdK6zFfd7elbzSY8gpR8f7S777YT3jzf3owpbtBT+ixj4StCdC15lUAMnYt0WfTVgWho7zSa64anYj3yELH+Mqw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=XVcQXj1h; arc=none smtp.client-ip=192.198.163.8 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="XVcQXj1h" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1755964346; x=1787500346; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=msJTNaNSQ6qHiQGGVHZ28t+lSU4y4Ql7Ojc6kM+547k=; b=XVcQXj1hV64ZBAECR0hBN9N2qLz3yVoc09K3vnh7lDdDRbtSsMxBZyMb eAVlN6mqXX1ZK93UL9o6FjG0/5m89r29lM0/y5TeRmHXpiYbVhLAiMwOC D4OU4p89FJYZF1v+BIAPrg0DzajLqqbloQ+830nEEpA0ZMn+6VbUZA4MP 0JGxGMYe6pdSeELws49qGpch34/MCjeX++u146bryYk/PEgpFkLFzmLxR 9ckBEdRc9XHwdwLiJFYoXCbgVlB89J3B+BzSPAtb+cgXtr/owLUGeeYpt Tn/HtXb5d9sPm/rdzdOwojkosPQaa7YAiplxiMUDYijjpqxePAaK9Wbvb g==; X-CSE-ConnectionGUID: Hc+OoLGNS4u8sw+MA18PdA== X-CSE-MsgGUID: 6G6eXQCvQLaiADAKSGag8A== X-IronPort-AV: E=McAfee;i="6800,10657,11531"; a="75832833" X-IronPort-AV: E=Sophos;i="6.17,312,1747724400"; d="scan'208";a="75832833" Received: from fmviesa010.fm.intel.com ([10.60.135.150]) by fmvoesa102.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 23 Aug 2025 08:52:26 -0700 X-CSE-ConnectionGUID: b4bDQL5YSPWsTvyazriGQQ== X-CSE-MsgGUID: VV4vhXINSqej8sEFXiUInA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.17,312,1747724400"; d="scan'208";a="169748254" Received: from cbae1-mobl.amr.corp.intel.com (HELO cbae1-mobl.intel.com) ([10.124.85.190]) by fmviesa010.fm.intel.com with ESMTP; 23 Aug 2025 08:52:25 -0700 From: "Chang S. Bae" To: linux-kernel@vger.kernel.org Cc: x86@kernel.org, tglx@linutronix.de, mingo@redhat.com, bp@alien8.de, dave.hansen@linux.intel.com, chao.gao@intel.com, abusse@amazon.de, chang.seok.bae@intel.com Subject: [PATCH v5 7/7] x86/microcode/intel: Enable staging when available Date: Sat, 23 Aug 2025 08:52:10 -0700 Message-ID: <20250823155214.17465-8-chang.seok.bae@intel.com> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20250823155214.17465-1-chang.seok.bae@intel.com> References: <20250813172649.15474-1-chang.seok.bae@intel.com> <20250823155214.17465-1-chang.seok.bae@intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" With the staging code being ready, check for staging availability by reading these following MSRs: * IA32_ARCH_CAPABILITIES (bit 16) for the presence of IA32_MCU_ENUMERATION * IA32_MCU_ENUMERATION (bit 4) for the staging feature availability. When available, enable it by setting the feature bit. Signed-off-by: Chang S. Bae Reviewed-by: Chao Gao Tested-by: Anselm Busse Reviewed-by: Tony Luck --- V4 -> V5: * Collect Chao's Review tag * rdmsrl() -> rdmsrq() (Chao) V1 -> V2: * Fold MSR definings (Boris). --- arch/x86/include/asm/msr-index.h | 7 +++++++ arch/x86/kernel/cpu/microcode/intel.c | 17 +++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-in= dex.h index 0356155f9264..2b7b598c414f 100644 --- a/arch/x86/include/asm/msr-index.h +++ b/arch/x86/include/asm/msr-index.h @@ -166,6 +166,10 @@ * Processor MMIO stale data * vulnerabilities. */ +#define ARCH_CAP_MCU_ENUM BIT(16) /* + * Indicates the presence of microcode update + * feature enumeration and status information + */ #define ARCH_CAP_FB_CLEAR BIT(17) /* * VERW clears CPU fill buffer * even on MDS_NO CPUs. @@ -913,6 +917,9 @@ #define MSR_IA32_UCODE_WRITE 0x00000079 #define MSR_IA32_UCODE_REV 0x0000008b =20 +#define MSR_IA32_MCU_ENUMERATION 0x0000007b +#define MCU_STAGING BIT(4) + #define MSR_IA32_MCU_STAGING_MBOX_ADDR 0x000007a5 =20 /* Intel SGX Launch Enclave Public Key Hash MSRs */ diff --git a/arch/x86/kernel/cpu/microcode/intel.c b/arch/x86/kernel/cpu/mi= crocode/intel.c index f6b365eba6a2..7d6582f8a80f 100644 --- a/arch/x86/kernel/cpu/microcode/intel.c +++ b/arch/x86/kernel/cpu/microcode/intel.c @@ -1007,6 +1007,18 @@ static __init void calc_llc_size_per_core(struct cpu= info_x86 *c) llc_size_per_core =3D (unsigned int)llc_size; } =20 +static __init bool staging_available(void) +{ + u64 val; + + val =3D x86_read_arch_cap_msr(); + if (!(val & ARCH_CAP_MCU_ENUM)) + return false; + + rdmsrq(MSR_IA32_MCU_ENUMERATION, val); + return !!(val & MCU_STAGING); +} + struct microcode_ops * __init init_intel_microcode(void) { struct cpuinfo_x86 *c =3D &boot_cpu_data; @@ -1017,6 +1029,11 @@ struct microcode_ops * __init init_intel_microcode(v= oid) return NULL; } =20 + if (staging_available()) { + microcode_intel_ops.use_staging =3D true; + pr_info("Enabled staging feature.\n"); + } + calc_llc_size_per_core(c); =20 return µcode_intel_ops; --=20 2.48.1