From nobody Wed Dec 17 08:54:36 2025 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.11]) (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 94BCA21D018 for ; Thu, 20 Mar 2025 23:41:14 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.11 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1742514077; cv=none; b=mEWYjw0xJqhVkcT8/POkcAL7g/m6UjIjjGSYycelIU8/gjw8AZbGSpBRZ6T4kVgYjH+4lsECbplgy5ycOAff/MLNcuLhcg2YVCrFjX+dUsaSg/+z9vEbHQJ26OQW2yxt5cUIcqtDADaqAl+Dz4i3rE+VdWxbVEDa7p+luUhHoHQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1742514077; c=relaxed/simple; bh=S25TJROssnqp2lMFYbL4/rzVWT/EIZe1MtkkxmZ/usQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=cZLZ/++HdvEOze7trkFRmCeAjCc1LFLYcG6aw6ybPlxQSU7zAieubFPMnAYBdouncqVgOaFYrzyhFSb935nhXiT4cdAWUiFn4Fj/K7lyvnYjtOUQNnUYZ94RQuxrP+rxisyGeC0NUwbwNKcqdRXLDduNqYGhU4qleNoYrMF61r4= 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=ZWXDP28R; arc=none smtp.client-ip=192.198.163.11 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="ZWXDP28R" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1742514074; x=1774050074; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=S25TJROssnqp2lMFYbL4/rzVWT/EIZe1MtkkxmZ/usQ=; b=ZWXDP28RZ65GN6+Gm4FzKaaJ4saE4t1e+Lfj6t/uyP9PsTQpWhF5Jjbv 32TPboOGgjFEjrlgnwJhHagq+Sjuu2/N8PlskCnpaNfVS5PVbaOxqi+v5 BaOgNf69R9XlU1H/DIrRj/hxVnU/tqSnzRMNQHrG+GfIfvm83/8QehDM2 wo658yG3mYZTFDx1zUj8Vo1DEUEu5IvSz+yh/uWDJudA3jDeTjfUgbGlM nAOAdad6DgDYyQtB9L6ez//x7H54NB04tsCt2GAeKzkS8AgFSpethYImr AHBA7pbZsWps6TDewhggRERbErb+kmb6c6CRaclobU+3Tx9vSS14GAFci w==; X-CSE-ConnectionGUID: zBDs6mXeQkO8jdJtTw5B8w== X-CSE-MsgGUID: iV/JvQasRA2btureVPE0NA== X-IronPort-AV: E=McAfee;i="6700,10204,11379"; a="54439132" X-IronPort-AV: E=Sophos;i="6.14,263,1736841600"; d="scan'208";a="54439132" Received: from fmviesa008.fm.intel.com ([10.60.135.148]) by fmvoesa105.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 Mar 2025 16:41:14 -0700 X-CSE-ConnectionGUID: dDYs4R5RROyRWYCc4qHVew== X-CSE-MsgGUID: qMx5O+BWSracB8OjAOaKhQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.14,263,1736841600"; d="scan'208";a="123418008" Received: from cbae1-mobl.amr.corp.intel.com (HELO cbae1-mobl.intel.com) ([10.124.161.68]) by fmviesa008.fm.intel.com with ESMTP; 20 Mar 2025 16:41:14 -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, colinmitchell@google.com, chang.seok.bae@intel.com Subject: [PATCH v2 1/6] x86/microcode: Introduce staging step to reduce late-loading time Date: Thu, 20 Mar 2025 16:40:53 -0700 Message-ID: <20250320234104.8288-2-chang.seok.bae@intel.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20250320234104.8288-1-chang.seok.bae@intel.com> References: <20250320234104.8288-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 --- V1 -> V2: - Move invocation inside of load_late_stop_cpus() (Boris) - Add more note about staging (Dave) RFC-V1 -> V1: - Rename the function name to the do_something() style (Boris). Note: Now the invocation is placed as part of the late-loading core function following Boris' comment on the last posting [1], which I think can keep the main late-loading logic simple from load_late_locked(). There was some brief discussion about the necessity of enforcing staging as mandatory [2]. But it was not clearly justified yet, so I thought it still makes sense to exclude such policy discussions out of this series. [1] https://lore.kernel.org/lkml/20250218113634.GGZ7RwwkrrXADX0eRo@fat_crat= e.local/ [2] https://lore.kernel.org/lkml/526df712-6091-4b04-97d5-9007789dc750@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 b3658d11e7b6..c4aff44a7ffc 100644 --- a/arch/x86/kernel/cpu/microcode/core.c +++ b/arch/x86/kernel/cpu/microcode/core.c @@ -541,6 +541,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 5df621752fef..4b983b4cddbd 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.45.2 From nobody Wed Dec 17 08:54:36 2025 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.11]) (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 0AD1C22AE68 for ; Thu, 20 Mar 2025 23:41:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.11 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1742514079; cv=none; b=hHwst6HRfSxjLloNjECZGUFjBaqpA8t2MxexTTL8dkByR3gLcK88XVs0joIg/uL1/2+RSzE54Lta0oytkTFm1ZpECKrkO9jJvpBy2j+jyqHxV41LoPaFYYGI6ExM25OER2B9TptcPzNDkoyE1Uhj84mG79AXnh7VH4e0ppYCnVo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1742514079; c=relaxed/simple; bh=6sgvqNek8w2WkzBgdawUu7psYuoacHnTGTRIzEB/zEE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=UN23t5bklC/Iun/4CIMJw84pM1o6xQwFPJtRFuJoqXA2lwE4tj6Sh+VQiUZsOAESS5lmeK95buoIcU1zP7g+UkQ5f3FsI67gjFbhwULUxdRDFroBc+5WiXZVZv1HbviO/RB5wDSOMZSHI3tQsMwMaTsT+UhnDZjewW8k6NKUT7c= 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=WekmP4LY; arc=none smtp.client-ip=192.198.163.11 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="WekmP4LY" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1742514078; x=1774050078; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=6sgvqNek8w2WkzBgdawUu7psYuoacHnTGTRIzEB/zEE=; b=WekmP4LYHxV5Ri1x87rdHqkV3W9VACDzevh6BGa9Ozl3v0TEUbe2Qrhd wimj4xRVJf0MAIW4QY76i1yK0QnNUWpj4fv2I6ttY9IdKl7pPBVgK0Dnl hk4VabLmZDVprDgbXwmF6/BLtiwCVoeEV/z4Hx1tGhngo2gJmxxvZTsU3 /mZH+hYpLA/dXmOi/2PWo1MtG8BipUpYWTmLLZvgv+UeyAc9ch94cTVvz bHKUfP+Ritu8YV6mf326ENzcGRt0y6poUp288+JWvlw9S4mDFEG0hw7S6 8ZrWg+240vjD8sgJhtMS6Ah5/GjThuMyVbyMn9qRh3bxp/pemBc+9IMAB A==; X-CSE-ConnectionGUID: hyVqpZ9EQ+GA/fXiwNPzoQ== X-CSE-MsgGUID: m6oO2A43RaSej43o9ZRiww== X-IronPort-AV: E=McAfee;i="6700,10204,11379"; a="54439139" X-IronPort-AV: E=Sophos;i="6.14,263,1736841600"; d="scan'208";a="54439139" Received: from fmviesa008.fm.intel.com ([10.60.135.148]) by fmvoesa105.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 Mar 2025 16:41:17 -0700 X-CSE-ConnectionGUID: iuXtFZU3TDWLwj773i3Msg== X-CSE-MsgGUID: DBa/xgNJR+WhUYVmtFP3FA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.14,263,1736841600"; d="scan'208";a="123418028" Received: from cbae1-mobl.amr.corp.intel.com (HELO cbae1-mobl.intel.com) ([10.124.161.68]) by fmviesa008.fm.intel.com with ESMTP; 20 Mar 2025 16:41:17 -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, colinmitchell@google.com, chang.seok.bae@intel.com Subject: [PATCH v2 2/6] x86/microcode/intel: Define staging state struct Date: Thu, 20 Mar 2025 16:40:54 -0700 Message-ID: <20250320234104.8288-3-chang.seok.bae@intel.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20250320234104.8288-1-chang.seok.bae@intel.com> References: <20250320234104.8288-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 --- V1 -> V2: New patch In the previous version, 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, which is now prioritized. --- arch/x86/kernel/cpu/microcode/intel.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/arch/x86/kernel/cpu/microcode/intel.c b/arch/x86/kernel/cpu/mi= crocode/intel.c index 819199bc0119..57ed5d414cd1 100644 --- a/arch/x86/kernel/cpu/microcode/intel.c +++ b/arch/x86/kernel/cpu/microcode/intel.c @@ -54,6 +54,27 @@ 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_ptr: Pointer to the microcode image + * @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; + void *ucode_ptr; + 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.45.2 From nobody Wed Dec 17 08:54:36 2025 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.11]) (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 137A122B8B1 for ; Thu, 20 Mar 2025 23:41:20 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.11 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1742514084; cv=none; b=A0BQ/KitEfUFjxTgMKlq2cC7qeAv69LJH7/nZ4LtqgZa9k5vB/rDDbUxblocehnsf1YIHoef53TxQA3nJvB1ftvXSZOP9isLQCk2EZmyV97I2jEi33KLmEI9FMgiOLWL95WiTOhnc3JL3OyLP8TWoZNndbHLgzNZnMa9D2/yGGA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1742514084; c=relaxed/simple; bh=HzxvhWptpt+PUVAgJgNC/pa0J4idK6WbpPo+RPBZ6xY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=MQjIwaR/vaFrzPSMdTH7QhU1S75JekiocVf+DrACfCR366rvsWCQWcTjVtCJWSp8rj9KWBZ0HttvRM1wVsG/Z3fyy/3wuDGaoKRiii7tCutnMeYW2cVXoD5ErVy+LQCP+jHsXFCd7j2Bi3CYCFCy7aBHJTryPjB4GxKgwfVraSw= 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=kbIUSJ/G; arc=none smtp.client-ip=192.198.163.11 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="kbIUSJ/G" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1742514081; x=1774050081; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=HzxvhWptpt+PUVAgJgNC/pa0J4idK6WbpPo+RPBZ6xY=; b=kbIUSJ/GEffgQ4jclup186avNPSPDsAVChPMggvEoGxPdRe+S287NU02 iTFWnrBJLWVUfhhnvU5ZoYZJVUZoLO6c+EwJsskO9iXhXo4+FqZQ2l3F2 sxQXCK9Pmodwa0jFt0Wt1u+bfmT4rrHfsFPl/4F2oszen3tI76UyKIAPU JXsfDqNcBdzKkVTGFrYK+jBZJaUo52vRpl3u6h34Nf2T7AWQe9FNpPeNj InKnM4vmYliD3D7KLaqbqZIOX+qvya6KHOwv77M/axib12h6MwoWIXVVl tk6aGxx4DategJyRp3UfsJXjZe+XRxuLV6F0YT7UxmrJkUlLnT/CzGluM A==; X-CSE-ConnectionGUID: CHc8ctWAQmeRMinUtCr+Vg== X-CSE-MsgGUID: 9/8UkOnhR0CA9JdBYtEpzQ== X-IronPort-AV: E=McAfee;i="6700,10204,11379"; a="54439145" X-IronPort-AV: E=Sophos;i="6.14,263,1736841600"; d="scan'208";a="54439145" Received: from fmviesa008.fm.intel.com ([10.60.135.148]) by fmvoesa105.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 Mar 2025 16:41:20 -0700 X-CSE-ConnectionGUID: fU8Rj+iXQZmTYTfI+einGA== X-CSE-MsgGUID: HlFA+PQZReKlhXLNs4zuuA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.14,263,1736841600"; d="scan'208";a="123418042" Received: from cbae1-mobl.amr.corp.intel.com (HELO cbae1-mobl.intel.com) ([10.124.161.68]) by fmviesa008.fm.intel.com with ESMTP; 20 Mar 2025 16:41:19 -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, colinmitchell@google.com, chang.seok.bae@intel.com Subject: [PATCH v2 3/6] x86/microcode/intel: Establish staging control logic Date: Thu, 20 Mar 2025 16:40:55 -0700 Message-ID: <20250320234104.8288-4-chang.seok.bae@intel.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20250320234104.8288-1-chang.seok.bae@intel.com> References: <20250320234104.8288-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. Suggested-by: Thomas Gleixner Signed-off-by: Chang S. Bae Link: https://lore.kernel.org/all/871pznq229.ffs@tglx --- V1 -> V2: * Adjust to reference the staging_state struct. RFC-V1 -> V1: * Simplify code by leveraging the architectural per-package staging scope (Thomas). * Fix MSR read code (Boris and Dave). * Rename the staging function: staging_work() -> do_stage() (Boris). * Polish the result messages (Boris). * Add a prototype for builds without CONFIG_CPU_SUP_INTEL (Boris). * Massage the changelog. Note: 1. Using a direct reference to 'cpu_primary_thread_mask' in for_each_cpu(...) causes a build error when !CONFIG_SMP. Instead, use the wrapper function topology_is_primary_thread() to avoid it. 2. Ideally, the do_stage() function would be as simple as a single WRMSR execution. If this were the case, the staging flow could be completed with this patch. --- arch/x86/include/asm/msr-index.h | 2 + arch/x86/kernel/cpu/microcode/intel.c | 57 ++++++++++++++++++++++++++- 2 files changed, 57 insertions(+), 2 deletions(-) diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-in= dex.h index bc6d2de109b5..f123abfdffcb 100644 --- a/arch/x86/include/asm/msr-index.h +++ b/arch/x86/include/asm/msr-index.h @@ -891,6 +891,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 57ed5d414cd1..14c20b53f14d 100644 --- a/arch/x86/kernel/cpu/microcode/intel.c +++ b/arch/x86/kernel/cpu/microcode/intel.c @@ -64,8 +64,11 @@ struct extended_sigtable { * @bytes_sent: Total bytes transmitted so far * @offset: Current offset in the microcode image * @state: Current state of the staging process + * + * Staging is performed sequentially per package, so concurrent access is + * not expected. */ -struct staging_state { +static struct staging_state { void __iomem *mmio_base; void *ucode_ptr; unsigned int ucode_len; @@ -73,7 +76,7 @@ struct staging_state { unsigned int bytes_sent; unsigned int offset; enum ucode_state state; -}; +} staging; =20 #define DEFAULT_UCODE_TOTALSIZE (DEFAULT_UCODE_DATASIZE + MC_HEADER_SIZE) #define EXT_HEADER_SIZE (sizeof(struct extended_sigtable)) @@ -320,6 +323,55 @@ 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. The + * caller is expected to check the result in staging.state. + */ +static void do_stage(u64 mmio_pa) +{ + pr_debug_once("Staging implementation is pending.\n"); + staging.state =3D UCODE_ERROR; +} + +static void stage_microcode(void) +{ + unsigned int pkg_id =3D UINT_MAX; + u64 mmio_pa; + int cpu; + + staging.ucode_ptr =3D ucode_patch_late; + staging.ucode_len =3D get_totalsize(&ucode_patch_late->hdr); + if (!IS_ALIGNED(staging.ucode_len, 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_online_mask) { + if (!topology_is_primary_thread(cpu) || + topology_logical_package_id(cpu) =3D=3D pkg_id) + continue; + pkg_id =3D topology_logical_package_id(cpu); + + rdmsrl_on_cpu(cpu, MSR_IA32_MCU_STAGING_MBOX_ADDR, &mmio_pa); + + do_stage(mmio_pa); + if (staging.state !=3D UCODE_OK) { + pr_err("Error: staging failed with %s for CPU%d at package %u.\n", + staging.state =3D=3D UCODE_TIMEOUT ? "timeout" : "error state", + cpu, pkg_id); + return; + } + } + + pr_info("Staging of patch revision 0x%x succeeded.\n", + ((struct microcode_header_intel *)ucode_patch_late)->rev); +} + static enum ucode_state __apply_microcode(struct ucode_cpu_info *uci, struct microcode_intel *mc, u32 *cur_rev) @@ -648,6 +700,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.45.2 From nobody Wed Dec 17 08:54:36 2025 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.11]) (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 6D8E222ACF3 for ; Thu, 20 Mar 2025 23:41:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.11 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1742514086; cv=none; b=oI7LjP7tKEEnzo5IZuC2dX6I7UFkYPpkcKIXOSJgLxuezh6ZZXsllRMmkXtG7VELM6qd6/FlteRq7Au6VkjF0P1FP/bnVTBjnXeqJqPkGo73NYRedNV0XOrmIAjXvetr8tYd1iXDFx2QNSV70T1F9iYqGI1RgfTxLd0aQOKPJOE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1742514086; c=relaxed/simple; bh=JKFenFhNTRKKRxHJ8UZ9oXVmTS+oUwePqrJCVgBFpJ0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Te1aQqu09mUPlC5WsC4h0lIgak1k5Ol/Sow1jRgH15Vj8U0u/7K9YTqvN08169S9361nUEoCBiaLx0xGbxlIGmOn5wANU4tjmpYQZI5WXQFfIyDsS7e854wCSLscvKwe6CUlh6JRbljw7qseazJC6CY3dGIJ/M1cOZltvHlvzvw= 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=YX8slLnz; arc=none smtp.client-ip=192.198.163.11 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="YX8slLnz" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1742514083; x=1774050083; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=JKFenFhNTRKKRxHJ8UZ9oXVmTS+oUwePqrJCVgBFpJ0=; b=YX8slLnzF6CqbE3zGjA/bXlaLqOADkSPi12vV9lL/ST1ZFpLVgZgKycK fZZFXAX4lsXjmkcJbKydCmJlbIjMvOCM9VRX2Sir5OLoqBH3VCJZhdQjt KlLADVja5M/R8rTKZd05TpKtbye/613N3FCHkkgwIGYLOlGbQ9NK+IQlc pZt8Stsb08k73pqJeRyTvMYIyC0LwsX8aTsVga+7ohCo91EivRoR3DCHO +c+OTNnoqA3MLkZQGTgI6YaS2ORrI3gtqc2J+UZIUFcxeKXymqPma9etf iaDe1yrhpEG3fgjw5nVwwLdBzaNE2/N4U5MjQsYByriIg51UQwVbeoENf A==; X-CSE-ConnectionGUID: iQXqJ4boRqesAQYMMaovNA== X-CSE-MsgGUID: qZTulPNUQd+q2dyTR3B/0w== X-IronPort-AV: E=McAfee;i="6700,10204,11379"; a="54439152" X-IronPort-AV: E=Sophos;i="6.14,263,1736841600"; d="scan'208";a="54439152" Received: from fmviesa008.fm.intel.com ([10.60.135.148]) by fmvoesa105.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 Mar 2025 16:41:22 -0700 X-CSE-ConnectionGUID: cPbO6SLoQTq9J+taoJ4XVA== X-CSE-MsgGUID: QQ9MwDLTTl++gkfO2xM8PQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.14,263,1736841600"; d="scan'208";a="123418063" Received: from cbae1-mobl.amr.corp.intel.com (HELO cbae1-mobl.intel.com) ([10.124.161.68]) by fmviesa008.fm.intel.com with ESMTP; 20 Mar 2025 16:41: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, colinmitchell@google.com, chang.seok.bae@intel.com Subject: [PATCH v2 4/6] x86/microcode/intel: Implement staging handler Date: Thu, 20 Mar 2025 16:40:56 -0700 Message-ID: <20250320234104.8288-5-chang.seok.bae@intel.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20250320234104.8288-1-chang.seok.bae@intel.com> References: <20250320234104.8288-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 were established for each MMIO space. The next step is to implement the 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 --- 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 renaming (Dave). A key change to highlight is the updated main loop in do_stage(). With the introduction of global staging data, sub-functions now focus on being more self-explanatory through meaningful naming. RFC-V1 -> V1: * Rename the function name and change the return type. --- arch/x86/kernel/cpu/microcode/intel.c | 116 +++++++++++++++++++++++++- 1 file changed, 113 insertions(+), 3 deletions(-) diff --git a/arch/x86/kernel/cpu/microcode/intel.c b/arch/x86/kernel/cpu/mi= crocode/intel.c index 14c20b53f14d..05b5b73e525a 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,29 @@ 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) + +/* + * Each microcode image is divided into chunks, each at most + * MBOX_XACTION_SIZE in 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 accommodate this behavior, allow up to twice the expected number of + * transactions (i.e., a 10-chunk image can take up to 20 attempts). + */ +#define MBOX_XACTION_SIZE PAGE_SIZE +#define MBOX_XACTION_MAX(imgsz) ((imgsz) * 2) + /* 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; @@ -323,14 +348,99 @@ static __init struct microcode_intel *scan_microcode(= void *data, size_t size, return size ? NULL : patch; } =20 +/* + * Prepare for a new microcode transfer by resetting both hardware and + * software states. + */ +static inline void reset_stage(void) +{ + /* Reset tracking variables */ + staging.offset =3D 0; + staging.bytes_sent =3D 0; + + /* + * 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, staging.mmio_base + MBOX_CONTROL_OFFSET); +} + +/* + * Check if the staging process has completed. The hardware signals + * completion by setting a unique end offset. + */ +static inline bool is_stage_complete(void) +{ + return staging.offset =3D=3D UINT_MAX; +} + +/* + * Determine if the next data chunk can be sent. Each chunk is typically + * one page unless the remaining data is smaller. If the total + * transmitted data exceeds the defined limit, a timeout occurs. + */ +static bool can_send_next_chunk(void) +{ + WARN_ON_ONCE(staging.ucode_len < staging.offset); + staging.chunk_size =3D min(MBOX_XACTION_SIZE, staging.ucode_len - staging= .offset); + + if (staging.bytes_sent + staging.chunk_size > MBOX_XACTION_MAX(staging.uc= ode_len)) { + staging.state =3D UCODE_TIMEOUT; + return false; + } + return true; +} + +/* + * Transmit a chunk of the microcode image to the hardware. + * Return true if the chunk is processed successfully. + */ +static bool send_data_chunk(void) +{ + pr_debug_once("Staging mailbox loading code needs to be implemented.\n"); + return false; +} + +/* + * Retrieve the next offset from the hardware response. + * Return true if the response is valid, false otherwise. + */ +static bool fetch_next_offset(void) +{ + pr_debug_once("Staging mailbox response handling code needs to be impleme= nted.\n\n"); + return false; +} + /* * Handle the staging process using the mailbox MMIO interface. The - * caller is expected to check the result in staging.state. + * microcode image is transferred in chunks until completion. The caller + * is expected to check the result in staging.state. */ static void do_stage(u64 mmio_pa) { - pr_debug_once("Staging implementation is pending.\n"); - staging.state =3D UCODE_ERROR; + staging.mmio_base =3D ioremap(mmio_pa, MBOX_REG_NUM * MBOX_REG_SIZE); + if (WARN_ON_ONCE(!staging.mmio_base)) { + staging.state =3D UCODE_ERROR; + return; + } + + reset_stage(); + + /* Perform the staging process while within the retry limit */ + while (!is_stage_complete() && can_send_next_chunk()) { + /* Send a chunk of microcode each time: */ + if (!send_data_chunk()) + break; + /* + * Then, ask the hardware which piece of the image it + * needs next. The same piece may be sent more than once. + */ + if (!fetch_next_offset()) + break; + } + + iounmap(staging.mmio_base); } =20 static void stage_microcode(void) --=20 2.45.2 From nobody Wed Dec 17 08:54:36 2025 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.11]) (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 419E722B8D2 for ; Thu, 20 Mar 2025 23:41:26 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.11 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1742514088; cv=none; b=XyIENXujJ3tIqDfnZIxUHzSThQQqR/z55IuORtPaZ1hy6e+YYM83ShSnYRSFi+zLB716ASfJDKpQvUTbHiu6nXn2xEJJzP3/aEcgD5nMVnn0/O1Wv9DEIbleKKOdUHSQVazNAIM9H8t53JxSGnYPkZihLCUCTGl+XXSB0Gx7i8A= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1742514088; c=relaxed/simple; bh=4EnL6N2E+dvP8uq/sVmBwRV9HeGLEuCL2dVASUxIipQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=mWG/9GJsxRRQwsG8wVtWSGBiM86ZRTmv80ATT0+AtAu2GFNSPH7zzEiBZx/7yli0updfDY3HMxswj1A3eUwQGNXZKYvAePO5xTXZI4kHw5PgJ0VngiOOGKIr7RQeGvYG7nCyrcP7yFSQyrhEILadSNvYJuvW4Aui/LWgO6a9oyg= 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=XjTdSZ8Z; arc=none smtp.client-ip=192.198.163.11 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="XjTdSZ8Z" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1742514086; x=1774050086; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=4EnL6N2E+dvP8uq/sVmBwRV9HeGLEuCL2dVASUxIipQ=; b=XjTdSZ8ZyrZs2ual5+jCjM5Je7esqZPIdBNBO9aK+qNSZQ2tsP8RUOk1 QVmDoT3Nr3C2a28hbOzRC8034wPtJxAz14J0fwf+EEw/EeqfkfU4ZnmNH zHnt/4VcnwS+fQnOXaw4K0/sfxcnAOIDsDVI3Osmmfs0eWRJ4wTrK1HkP JOFlzIfRlAHNhRS9JCKqYPjkMq0vNRMhriufXZxrGCBKJ9P31YGK7QoRc 4qBgSdE5OFD2Xl12itiO6d2bsqHTUL8ERQBAJQ+eFeZnHSk+PFwQEc8zJ P0NJR3jO0Fv16hRZDPehYQ2kVO0ZmiLbzByexpBbcqx4OM8gJgX/Kke01 A==; X-CSE-ConnectionGUID: WYILw433RI+I+O8UN7VMAA== X-CSE-MsgGUID: GXj4M+FnSeOItTvG014ktg== X-IronPort-AV: E=McAfee;i="6700,10204,11379"; a="54439163" X-IronPort-AV: E=Sophos;i="6.14,263,1736841600"; d="scan'208";a="54439163" Received: from fmviesa008.fm.intel.com ([10.60.135.148]) by fmvoesa105.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 Mar 2025 16:41:26 -0700 X-CSE-ConnectionGUID: fCsL6ljRS8ubdIWHhPlCwA== X-CSE-MsgGUID: UFjsKWoySkGTGwjQdjKUNQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.14,263,1736841600"; d="scan'208";a="123418088" Received: from cbae1-mobl.amr.corp.intel.com (HELO cbae1-mobl.intel.com) ([10.124.161.68]) by fmviesa008.fm.intel.com with ESMTP; 20 Mar 2025 16:41: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, colinmitchell@google.com, chang.seok.bae@intel.com Subject: [PATCH v2 5/6] x86/microcode/intel: Support mailbox transfer Date: Thu, 20 Mar 2025 16:40:57 -0700 Message-ID: <20250320234104.8288-6-chang.seok.bae@intel.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20250320234104.8288-1-chang.seok.bae@intel.com> References: <20250320234104.8288-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. 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 --- 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 | 148 +++++++++++++++++++++++++- 1 file changed, 144 insertions(+), 4 deletions(-) diff --git a/arch/x86/kernel/cpu/microcode/intel.c b/arch/x86/kernel/cpu/mi= crocode/intel.c index 05b5b73e525a..b0d530db72dd 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,30 @@ 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 DWORD_ALIGN(size) ((size) / sizeof(u32)) +#define MBOX_HEADER(mbox_size) (PCI_VENDOR_ID_INTEL | \ + (MBOX_OBJ_STAGING << 16) | \ + ((u64)DWORD_ALIGN(mbox_size) << 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) =20 /* * Each microcode image is divided into chunks, each at most @@ -57,6 +80,7 @@ static const char ucode_path[] =3D "kernel/x86/microcode/= GenuineIntel.bin"; */ #define MBOX_XACTION_SIZE PAGE_SIZE #define MBOX_XACTION_MAX(imgsz) ((imgsz) * 2) +#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; @@ -348,6 +372,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) +{ + u32 dword =3D readl(staging.mmio_base + MBOX_RDDATA_OFFSET); + + /* Acknowledge read completion to the staging firmware */ + writel(0, staging.mmio_base + MBOX_RDDATA_OFFSET); + return dword; +} + +static inline void write_mbox_dword(u32 dword) +{ + writel(dword, staging.mmio_base + MBOX_WRDATA_OFFSET); +} + +static inline u64 read_mbox_header(void) +{ + u32 high, low; + + low =3D read_mbox_dword(); + high =3D read_mbox_dword(); + + return ((u64)high << 32) | low; +} + +static inline void write_mbox_header(u64 value) +{ + write_mbox_dword(value); + write_mbox_dword(value >> 32); +} + +static inline void write_mbox_data(u32 *chunk, unsigned int chunk_size) +{ + 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 < DWORD_ALIGN(chunk_size); i++) + write_mbox_dword(chunk[i]); +} + /* * Prepare for a new microcode transfer by resetting both hardware and * software states. @@ -392,14 +459,71 @@ static bool can_send_next_chunk(void) return true; } =20 +/* + * Wait for the hardware to complete a transaction. + * Return true on success, false on failure. + */ +static bool wait_for_transaction(void) +{ + 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(staging.mmio_base + MBOX_STATUS_OFFSET); + /* Break out early if the hardware is ready: */ + if (status & MASK_MBOX_STATUS_READY) + break; + } + + status =3D readl(staging.mmio_base + MBOX_STATUS_OFFSET); + + /* Check for explicit error response */ + if (status & MASK_MBOX_STATUS_ERROR) { + staging.state =3D UCODE_ERROR; + return false; + } + + /* + * Hardware is neither responded to the action nor + * signaled any error. Treat the case as timeout. + */ + if (!(status & MASK_MBOX_STATUS_READY)) { + staging.state =3D UCODE_TIMEOUT; + return false; + } + + staging.state =3D UCODE_OK; + return true; +} + /* * Transmit a chunk of the microcode image to the hardware. * Return true if the chunk is processed successfully. */ static bool send_data_chunk(void) { - pr_debug_once("Staging mailbox loading code needs to be implemented.\n"); - return false; + u16 mbox_size =3D MBOX_HEADER_SIZE * 2 + staging.chunk_size; + u32 *chunk =3D staging.ucode_ptr + staging.offset; + + /* + * Write 'request' mailbox object in the following order: + * - Mailbox header includes total size + * - Command header specifies the load operation + * - Data section contains a microcode chunk + */ + write_mbox_header(MBOX_HEADER(mbox_size)); + write_mbox_header(MBOX_CMD_LOAD); + write_mbox_data(chunk, staging.chunk_size); + staging.bytes_sent +=3D staging.chunk_size; + + /* + * Notify the hardware that the mailbox is ready for processing. + * The staging firmware will process the request asynchronously. + */ + writel(MASK_MBOX_CTRL_GO, staging.mmio_base + MBOX_CONTROL_OFFSET); + return wait_for_transaction(); } =20 /* @@ -408,8 +532,24 @@ static bool send_data_chunk(void) */ static bool fetch_next_offset(void) { - pr_debug_once("Staging mailbox response handling code needs to be impleme= nted.\n\n"); - return false; + const u16 mbox_size =3D MBOX_HEADER_SIZE + MBOX_RESPONSE_SIZE; + + /* All responses begin with the same header value: */ + WARN_ON_ONCE(read_mbox_header() !=3D MBOX_HEADER(mbox_size)); + + /* + * The 'response' mailbox contains two dword data: + * - First has next offset in microcode image + * - Second delivers status flag + */ + staging.offset =3D read_mbox_dword(); + if (read_mbox_dword() & MASK_MBOX_RESP_ERROR) { + staging.state =3D UCODE_ERROR; + return false; + } + + staging.state =3D UCODE_OK; + return true; } =20 /* --=20 2.45.2 From nobody Wed Dec 17 08:54:36 2025 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.11]) (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 47A0722CBD9 for ; Thu, 20 Mar 2025 23:41:29 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.11 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1742514092; cv=none; b=cIszkhVjt7WIKxQOuH4BmB8f/6u2Mnr9cRKMMAAg2OudvEn0YOR7QdHXsm4DJE67M392VqVtBTsq2GzLSR764wXMLrCX/UVNTe48h0IFfnyJJSaX24QtCr+OAoxZ2qjxoDsrORD0Rbr91UuUkbBNUim5U95qagLIcrZeY2axt88= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1742514092; c=relaxed/simple; bh=2SytMdOfTKn+KUKq8zhEEcNnHiEIOfPDJfVIV/16T1o=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=cDZJhTn5O52YUPg4nswewiwZ1gqRW7Itu1Wlhyob9VerJMJiOp7vqaMvEuJvNXczbs0kQIs3w1KsNtgUWTJZOBd0ScS9YPa3EQiocCKE8LaWJ2o6t7RKodbcyw2OOPZhbUv3z2ZmjquHKyisiyMK+4+CgRIpFefImFqqjH5MaYE= 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=cX7SwNzT; arc=none smtp.client-ip=192.198.163.11 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="cX7SwNzT" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1742514089; x=1774050089; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=2SytMdOfTKn+KUKq8zhEEcNnHiEIOfPDJfVIV/16T1o=; b=cX7SwNzTNjjUB+ZmigtLmdPT8oCfk4oEJ38wlVoMOFXd3PCDJU//Qe7X EHu0jwSQ35KaKJAvKK2gcD3p0qZKYFHfvv28FCAlwICNNxQYqfBAX38DI p+0HZtuX5a8iMyDkCNjAG807U16Rn9/sLfbKqByAdiXoRBo1GJdpAwvSA oKBQIUAQMK38ZFmLaPtG2xaDNf+aWYB/9EnNvHo/DptQ6ue8PzIFtMAHV 69AYywDrFdckDeUYIcjIAVuDlwE6ga1xHa+3j275gJahWVqB+Sh3B+Iqk qjDihnsyBU9YopTg5rrquPUosmmFUEvYsXiqv+/dVzcbjjwMpJyn2r2n9 Q==; X-CSE-ConnectionGUID: HZInPIKeQ4OtNyDllRogWg== X-CSE-MsgGUID: 94njHTN6RGq3YbihxmoUAw== X-IronPort-AV: E=McAfee;i="6700,10204,11379"; a="54439172" X-IronPort-AV: E=Sophos;i="6.14,263,1736841600"; d="scan'208";a="54439172" Received: from fmviesa008.fm.intel.com ([10.60.135.148]) by fmvoesa105.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 Mar 2025 16:41:28 -0700 X-CSE-ConnectionGUID: gt9fm9+nRdSdbgcwbJ9RkA== X-CSE-MsgGUID: T7na1EwVRxGrNH5S+wrAxg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.14,263,1736841600"; d="scan'208";a="123418101" Received: from cbae1-mobl.amr.corp.intel.com (HELO cbae1-mobl.intel.com) ([10.124.161.68]) by fmviesa008.fm.intel.com with ESMTP; 20 Mar 2025 16:41:28 -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, colinmitchell@google.com, chang.seok.bae@intel.com Subject: [PATCH v2 6/6] x86/microcode/intel: Enable staging when available Date: Thu, 20 Mar 2025 16:40:58 -0700 Message-ID: <20250320234104.8288-7-chang.seok.bae@intel.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20250320234104.8288-1-chang.seok.bae@intel.com> References: <20250320234104.8288-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 --- V1 -> V2: Fold MSR definings (Boris). RFC-V1 -> V1: Massage the enabling message. --- 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 f123abfdffcb..50c8c0914454 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. @@ -891,6 +895,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 b0d530db72dd..add0c1edd212 100644 --- a/arch/x86/kernel/cpu/microcode/intel.c +++ b/arch/x86/kernel/cpu/microcode/intel.c @@ -962,6 +962,18 @@ static __init void calc_llc_size_per_core(struct cpuin= fo_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; + + rdmsrl(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; @@ -972,6 +984,11 @@ struct microcode_ops * __init init_intel_microcode(voi= d) 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.45.2