[PATCH v3 07/13] x86/dt: Parse the Wakeup Mailbox for Intel processors

Ricardo Neri
2025-05-03T19:10:16Z

The Wakeup Mailbox is a mechanism to boot secondary CPUs used on systems
that do not want or cannot use the INIT + StartUp IPI messages.

Add `intel,wakeup-mailbox` to the set of supported enable methods. Also add
functionality to find and parse the parameters of the mailbox from the
DeviceTree from the platform firmware.

The operation and structure of the Wakeup Mailbox are described in the
corresponding DeviceTree schema that accompanies the documentation of the
Linux kernel.

The Wakeup Mailbox is compatible with the Multiprocessor Wakeup Mailbox
Structure described in the ACPI specification. Reuse the existing
functionality to set the memory location of the mailbox and update the
wakeup_secondary_cpu_64() APIC callback.

do_boot_cpu() uses wakeup_secondary_cpu_64() when set. If a wakeup mailbox
is found (enumerated via an ACPI table or a DeviceTree node) it will be
used unconditionally. For cases in which this behavior is not desired, this
APIC callback can be updated later during boot using platform-specific
hooks.

Originally-by: Yunhong Jiang <yunhong.jiang@linux.intel.com>
Signed-off-by: Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
---
Changes since v2:
- Added extra sanity checks when parsing the mailbox node.
- Probe the mailbox using its `compatible` property
- Setup the Wakeup Mailbox if the `enable-method` is found in the CPU
nodes.
- Cleaned up unneeded ifdeffery.
- Clarified the mechanisms used to override the wakeup_secondary_64()
callback to not use the mailbox when not desired. (Michael)
- Edited the commit message for clarity.

Changes since v1:
- Disabled CPU offlining.
- Modified dtb_parse_mp_wake() to return the address of the mailbox.
---
arch/x86/kernel/devicetree.c | 57 ++++++++++++++++++++++++++++++++++--
1 file changed, 55 insertions(+), 2 deletions(-)

diff --git a/arch/x86/kernel/devicetree.c b/arch/x86/kernel/devicetree.c
index 5835afc74acd..d03d9e23c693 100644
--- a/arch/x86/kernel/devicetree.c
+++ b/arch/x86/kernel/devicetree.c
@@ -17,6 +17,7 @@
#include <linux/pci.h>
#include <linux/of_pci.h>
#include <linux/initrd.h>
+#include <linux/smp.h>

#include <asm/irqdomain.h>
#include <asm/hpet.h>
@@ -128,7 +129,59 @@ static void __init dtb_setup_hpet(void)
#ifdef CONFIG_X86_LOCAL_APIC

#ifdef CONFIG_SMP
-static const char *dtb_supported_enable_methods[] __initconst = { };
+
+#ifdef CONFIG_X86_64
+
+#define WAKEUP_MAILBOX_SIZE 0x1000
+#define WAKEUP_MAILBOX_ALIGN 0x1000
+
+static int __init dtb_parse_wakeup_mailbox(const char *enable_method)
+{
+ struct device_node *node;
+ struct resource res;
+ int ret = 0;
+
+ if (strcmp(enable_method, "intel,wakeup-mailbox"))
+ return -EINVAL;
+
+ node = of_find_compatible_node(NULL, NULL, "intel,wakeup-mailbox");
+ if (!node)
+ return -ENODEV;
+
+ ret = of_address_to_resource(node, 0, &res);
+ if (ret)
+ goto done;
+
+ /* The mailbox is a 4KB-aligned region.*/
+ if (res.start & (WAKEUP_MAILBOX_ALIGN - 1)) {
+ ret = -EINVAL;
+ goto done;
+ }
+
+ /* The mailbox has a size of 4KB. */
+ if (res.end - res.start + 1 != WAKEUP_MAILBOX_SIZE) {
+ ret = -EINVAL;
+ goto done;
+ }
+
+ /* Not supported when the mailbox is used. */
+ cpu_hotplug_disable_offlining();
+
+ setup_mp_wakeup_mailbox(res.start);
+done:
+ of_node_put(node);
+ return ret;
+}
+#else /* !CONFIG_X86_64 */
+static inline int dtb_parse_wakeup_mailbox(const char *enable_method)
+{
+ return -ENOTSUPP;
+}
+#endif /* CONFIG_X86_64 */
+
+static const char *dtb_supported_enable_methods[] __initconst = {
+ "intel,wakeup-mailbox"
+};

static bool __init dtb_enable_method_is_valid(const char *enable_method_a,
const char *enable_method_b)
@@ -155,7 +208,7 @@ static int __init dtb_configure_enable_method(const char *enable_method)
if (!enable_method || IS_ERR(enable_method))
return 0;

- return -ENOTSUPP;
+ return dtb_parse_wakeup_mailbox(enable_method);
}
#else /* !CONFIG_SMP */
static inline bool dtb_enable_method_is_valid(const char *enable_method_a,
--
2.43.0