linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: "Chang S. Bae" <chang.seok.bae@intel.com>
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 v2a 4/6] x86/microcode/intel: Implement staging handler
Date: Fri, 21 Mar 2025 14:19:09 -0700	[thread overview]
Message-ID: <20250321211909.13927-1-chang.seok.bae@intel.com> (raw)
In-Reply-To: <b01224ee-c935-4b08-a76f-5dc49341182d@intel.com>

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 <chang.seok.bae@intel.com>
---
V2 -> V2a:
* Adjust the code with the global variable removal (Dave [1]).

Note: this quick revision is just intended to ensure that the feedback
has been properly addressed.

[1]: https://lore.kernel.org/lkml/b01224ee-c935-4b08-a76f-5dc49341182d@intel.com/
---
 arch/x86/kernel/cpu/microcode/intel.c | 122 +++++++++++++++++++++++++-
 1 file changed, 118 insertions(+), 4 deletions(-)

diff --git a/arch/x86/kernel/cpu/microcode/intel.c b/arch/x86/kernel/cpu/microcode/intel.c
index 5d0216e9aee5..44b94d4d05f7 100644
--- a/arch/x86/kernel/cpu/microcode/intel.c
+++ b/arch/x86/kernel/cpu/microcode/intel.c
@@ -20,6 +20,8 @@
 #include <linux/cpu.h>
 #include <linux/uio.h>
 #include <linux/mm.h>
+#include <linux/delay.h>
+#include <linux/io.h>
 
 #include <asm/cpu_device_id.h>
 #include <asm/processor.h>
@@ -33,6 +35,29 @@ static const char ucode_path[] = "kernel/x86/microcode/GenuineIntel.bin";
 
 #define UCODE_BSP_LOADED	((struct microcode_intel *)0x1UL)
 
+/* 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;
@@ -321,13 +346,102 @@ static __init struct microcode_intel *scan_microcode(void *data, size_t size,
 }
 
 /*
- * Handle the staging process using the mailbox MMIO interface.
- * Return the result state.
+ * Prepare for a new microcode transfer by resetting hardware and
+ * initializing software states.
+ */
+static void init_stage(struct staging_state *ss)
+{
+	ss->ucode_ptr = ucode_patch_late;
+	ss->ucode_len = get_totalsize(&ucode_patch_late->hdr);
+
+	/* Reset tracking variables */
+	ss->offset = 0;
+	ss->bytes_sent = 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, ss->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(unsigned int offset)
+{
+	return offset == 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(struct staging_state *ss)
+{
+	WARN_ON_ONCE(ss->ucode_len < ss->offset);
+	ss->chunk_size = min(MBOX_XACTION_SIZE, ss->ucode_len - ss->offset);
+
+	if (ss->bytes_sent + ss->chunk_size > MBOX_XACTION_MAX(ss->ucode_len)) {
+		ss->state = 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(struct staging_state *unused)
+{
+	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(struct staging_state *unused)
+{
+	pr_debug_once("Staging mailbox response handling code needs to be implemented.\n\n");
+	return false;
+}
+
+/*
+ * 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 = {};
+
+	ss.mmio_base = 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 (!is_stage_complete(ss.offset) && can_send_next_chunk(&ss)) {
+		/* Send a chunk of microcode each time: */
+		if (!send_data_chunk(&ss))
+			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(&ss))
+			break;
+	}
+
+	iounmap(ss.mmio_base);
+	return ss.state;
 }
 
 static void stage_microcode(void)
-- 
2.45.2


  reply	other threads:[~2025-03-21 21:19 UTC|newest]

Thread overview: 66+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-03-20 23:40 [PATCH v2 0/6] x86: Support for Intel Microcode Staging Feature Chang S. Bae
2025-03-20 23:40 ` [PATCH v2 1/6] x86/microcode: Introduce staging step to reduce late-loading time Chang S. Bae
2025-03-20 23:40 ` [PATCH v2 2/6] x86/microcode/intel: Define staging state struct Chang S. Bae
2025-03-20 23:40 ` [PATCH v2 3/6] x86/microcode/intel: Establish staging control logic Chang S. Bae
2025-03-21 21:18   ` [PATCH v2a " Chang S. Bae
2025-03-26  7:35     ` Chao Gao
2025-03-26 18:43       ` Chang S. Bae
2025-03-27  1:44         ` Chao Gao
2025-03-28 14:12           ` Chang S. Bae
2025-03-20 23:40 ` [PATCH v2 4/6] x86/microcode/intel: Implement staging handler Chang S. Bae
2025-03-21  0:15   ` Dave Hansen
2025-03-21 21:19     ` Chang S. Bae [this message]
2025-03-26  8:34       ` [PATCH v2a " Chao Gao
2025-03-26 18:43         ` Chang S. Bae
2025-03-21 21:19     ` [PATCH v2 " Chang S. Bae
2025-03-20 23:40 ` [PATCH v2 5/6] x86/microcode/intel: Support mailbox transfer Chang S. Bae
2025-03-21 21:19   ` [PATCH v2a " Chang S. Bae
2025-03-27  3:32   ` [PATCH v2 " Chao Gao
2025-03-27 14:11     ` Chang S. Bae
2025-03-31 19:16     ` Dave Hansen
2025-03-20 23:40 ` [PATCH v2 6/6] x86/microcode/intel: Enable staging when available Chang S. Bae
2025-04-09 23:27 ` [PATCH v3 0/6] x86: Support for Intel Microcode Staging Feature Chang S. Bae
2025-04-09 23:27   ` [PATCH v3 1/6] x86/microcode: Introduce staging step to reduce late-loading time Chang S. Bae
2025-04-09 23:27   ` [PATCH v3 2/6] x86/microcode/intel: Establish staging control logic Chang S. Bae
2025-04-09 23:27   ` [PATCH v3 3/6] x86/microcode/intel: Define staging state struct Chang S. Bae
2025-04-09 23:27   ` [PATCH v3 4/6] x86/microcode/intel: Implement staging handler Chang S. Bae
2025-04-09 23:27   ` [PATCH v3 5/6] x86/microcode/intel: Support mailbox transfer Chang S. Bae
2025-04-16 14:14     ` Chao Gao
2025-04-16 17:22       ` Chang S. Bae
2025-04-16 17:37         ` Dave Hansen
2025-04-09 23:27   ` [PATCH v3 6/6] x86/microcode/intel: Enable staging when available Chang S. Bae
2025-08-13 17:26   ` [PATCH v4 0/6] x86: Support for Intel Microcode Staging Feature Chang S. Bae
2025-08-13 17:26     ` [PATCH v4 1/6] x86/microcode: Introduce staging step to reduce late-loading time Chang S. Bae
2025-08-18  7:45       ` Chao Gao
2025-08-13 17:26     ` [PATCH v4 2/6] x86/microcode/intel: Establish staging control logic Chang S. Bae
2025-08-13 18:21       ` Dave Hansen
2025-08-13 20:46         ` Chang S. Bae
2025-08-13 20:55           ` Dave Hansen
2025-08-14 18:30             ` Chang S. Bae
2025-08-22 22:39             ` [PATCH] x86/cpu/topology: Make primary thread mask available with SMP=n Chang S. Bae
2025-08-23 16:05               ` Chang S. Bae
2025-08-22 22:39         ` [PATCH v4a 2/6] x86/microcode/intel: Establish staging control logic Chang S. Bae
2025-08-22 23:34           ` Dave Hansen
2025-08-13 17:26     ` [PATCH v4 3/6] x86/microcode/intel: Define staging state struct Chang S. Bae
2025-08-13 18:25       ` Dave Hansen
2025-08-22 22:39         ` [PATCH v4a " Chang S. Bae
2025-08-13 17:26     ` [PATCH v4 4/6] x86/microcode/intel: Implement staging handler Chang S. Bae
2025-08-13 18:44       ` Dave Hansen
2025-08-22 22:39         ` [PATCH v4a " Chang S. Bae
2025-08-13 17:26     ` [PATCH v4 5/6] x86/microcode/intel: Support mailbox transfer Chang S. Bae
2025-08-13 19:07       ` Dave Hansen
2025-08-22 22:40         ` [PATCH v4a " Chang S. Bae
2025-08-13 17:26     ` [PATCH v4 6/6] x86/microcode/intel: Enable staging when available Chang S. Bae
2025-08-18  8:35       ` Chao Gao
2025-08-22 22:42         ` Chang S. Bae
2025-08-13 19:08     ` [PATCH v4 0/6] x86: Support for Intel Microcode Staging Feature Dave Hansen
2025-08-23 15:52     ` [PATCH v5 0/7] " Chang S. Bae
2025-08-23 15:52       ` [PATCH v5 1/7] x86/cpu/topology: Make primary thread mask available with SMP=n Chang S. Bae
2025-08-23 15:52       ` [PATCH v5 2/7] x86/microcode: Introduce staging step to reduce late-loading time Chang S. Bae
2025-08-23 15:52       ` [PATCH v5 3/7] x86/microcode/intel: Establish staging control logic Chang S. Bae
2025-08-23 15:52       ` [PATCH v5 4/7] x86/microcode/intel: Define staging state struct Chang S. Bae
2025-08-23 15:52       ` [PATCH v5 5/7] x86/microcode/intel: Implement staging handler Chang S. Bae
2025-08-23 15:52       ` [PATCH v5 6/7] x86/microcode/intel: Support mailbox transfer Chang S. Bae
2025-08-23 15:52       ` [PATCH v5 7/7] x86/microcode/intel: Enable staging when available Chang S. Bae
2025-08-26 22:13       ` [PATCH v5 0/7] x86: Support for Intel Microcode Staging Feature Luck, Tony
2025-08-26 22:15         ` Chang S. Bae

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20250321211909.13927-1-chang.seok.bae@intel.com \
    --to=chang.seok.bae@intel.com \
    --cc=bp@alien8.de \
    --cc=colinmitchell@google.com \
    --cc=dave.hansen@linux.intel.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mingo@redhat.com \
    --cc=tglx@linutronix.de \
    --cc=x86@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).