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.
The platform firmware is expected to implement the mailbox as described in the Multiprocessor Wakeup Structure of the ACPI specification. It is also expected to publish the mailbox to the operating system as described in the corresponding DeviceTree schema that accompanies the documentation of the Linux kernel. Reuse the existing functionality to set the memory location of the mailbox and update the wakeup_secondary_cpu_64() APIC callback. Make this functionality available to DeviceTree-based systems by making CONFIG_X86_ MAILBOX_WAKEUP depend on either CONFIG_OF or CONFIG_ACPI_MADT_WAKEUP. 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. Co-developed-by: Yunhong Jiang <yunhong.ji...@linux.intel.com> Signed-off-by: Yunhong Jiang <yunhong.ji...@linux.intel.com> Signed-off-by: Ricardo Neri <ricardo.neri-calde...@linux.intel.com> --- Changes since v4: - Made CONFIG_X86_MAILBOX_WAKEUP depend on CONFIG_OF or CONFIG_ACPI_ MADT_WAKEUP. Changes since v3: - Look for the wakeup mailbox unconditionally, regardless of whether cpu@N nodes have an `enable-method` property. - Add a reference to the ACPI specification. (Rafael) 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/Kconfig | 2 +- arch/x86/kernel/devicetree.c | 47 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index e3009cb59928..027f8ae878ec 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -1116,7 +1116,7 @@ config X86_LOCAL_APIC config X86_MAILBOX_WAKEUP def_bool y - depends on ACPI_MADT_WAKEUP + depends on OF || ACPI_MADT_WAKEUP depends on X86_64 depends on SMP depends on X86_LOCAL_APIC diff --git a/arch/x86/kernel/devicetree.c b/arch/x86/kernel/devicetree.c index dd8748c45529..494a560614a8 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> @@ -125,6 +126,51 @@ static void __init dtb_setup_hpet(void) #endif } +#if defined(CONFIG_X86_64) && defined(CONFIG_SMP) + +#define WAKEUP_MAILBOX_SIZE 0x1000 +#define WAKEUP_MAILBOX_ALIGN 0x1000 + +/** dtb_wakeup_mailbox_setup() - Parse the wakeup mailbox from the device tree + * + * Look for the presence of a wakeup mailbox in the DeviceTree. The mailbox is + * expected to follow the structure and operation described in the Multiprocessor + * Wakeup Structure of the ACPI specification. + */ +static void __init dtb_wakeup_mailbox_setup(void) +{ + struct device_node *node; + struct resource res; + + node = of_find_compatible_node(NULL, NULL, "intel,wakeup-mailbox"); + if (!node) + return; + + if (of_address_to_resource(node, 0, &res)) + goto done; + + /* The mailbox is a 4KB-aligned region.*/ + if (res.start & (WAKEUP_MAILBOX_ALIGN - 1)) + goto done; + + /* The mailbox has a size of 4KB. */ + if (res.end - res.start + 1 != WAKEUP_MAILBOX_SIZE) + goto done; + + /* Not supported when the mailbox is used. */ + cpu_hotplug_disable_offlining(); + + acpi_setup_mp_wakeup_mailbox(res.start); +done: + of_node_put(node); +} +#else /* !CONFIG_X86_64 || !CONFIG_SMP */ +static inline int dtb_wakeup_mailbox_setup(void) +{ + return -EOPNOTSUPP; +} +#endif /* CONFIG_X86_64 && CONFIG_SMP */ + #ifdef CONFIG_X86_LOCAL_APIC static void __init dtb_cpu_setup(void) @@ -287,6 +333,7 @@ static void __init x86_dtb_parse_smp_config(void) dtb_setup_hpet(); dtb_apic_setup(); + dtb_wakeup_mailbox_setup(); } void __init x86_flattree_get_config(void) -- 2.43.0