diff mbox series

[3/7] x86/dt: Support the ACPI multiprocessor wakeup for device tree

Message ID 20240806221237.1634126-4-yunhong.jiang@linux.intel.com (mailing list archive)
State Superseded, archived
Headers show
Series x86/acpi: Move ACPI MADT wakeup to generic code | expand

Commit Message

Yunhong Jiang Aug. 6, 2024, 10:12 p.m. UTC
When a TDX guest boots with the device tree instead of ACPI, it can
reuse the ACPI multiprocessor wakeup mechanism to wake up application
processors(AP), without introducing a new mechanism from scrach.

In the ACPI spec, two structures are defined to wake up the APs: the
multiprocessor wakeup structure and the multiprocessor wakeup mailbox
structure. The multiprocessor wakeup structure is passed to OS through a
Multiple APIC Description Table(MADT), one field specifying the physical
address of the multiprocessor wakeup mailbox structure. The OS sends
a message to firmware through the multiprocessor wakeup mailbox
structure, to bring up the APs.

In device tree environment, the multiprocessor wakeup structure is not
used, to reduce the dependency on the generic ACPI table. The
information defined in this structure is defined in the properties of
cpus node in the device tree. The "wakeup-mailbox-addr" property
specifies the physical address of the multiprocessor wakeup mailbox
structure. The OS will follow the ACPI spec to send the message to the
firmware to bring up the APs.

Signed-off-by: Yunhong Jiang <yunhong.jiang@linux.intel.com>
---
 MAINTAINERS                        |  1 +
 arch/x86/Kconfig                   |  2 +-
 arch/x86/include/asm/acpi.h        |  1 -
 arch/x86/include/asm/madt_wakeup.h | 16 ++++++++++
 arch/x86/kernel/madt_wakeup.c      | 47 ++++++++++++++++++++++++++++--
 5 files changed, 63 insertions(+), 4 deletions(-)
 create mode 100644 arch/x86/include/asm/madt_wakeup.h

Comments

Thomas Gleixner Aug. 7, 2024, 4:50 p.m. UTC | #1
On Tue, Aug 06 2024 at 15:12, Yunhong Jiang wrote:
>  
> -static int __init acpi_mp_setup_reset(u64 reset_vector)
> +static int __init __maybe_unused acpi_mp_setup_reset(u64 reset_vector)
>  {
>  	struct x86_mapping_info info = {
>  		.alloc_pgt_page = alloc_pgt_page,
> @@ -226,7 +228,7 @@ static int acpi_wakeup_cpu(u32 apicid, unsigned long start_ip)
>  	return 0;
>  }
>  
> -static void acpi_mp_disable_offlining(struct acpi_madt_multiproc_wakeup *mp_wake)
> +static void __maybe_unused acpi_mp_disable_offlining(struct
> acpi_madt_multiproc_wakeup *mp_wake)

Please move those functions into the #ifdef CONFIG_ACPI

>  {
>  	cpu_hotplug_disable_offlining();
>  
> @@ -248,6 +250,7 @@ static void acpi_mp_disable_offlining(struct acpi_madt_multiproc_wakeup *mp_wake
>  	mp_wake->mailbox_address = 0;
>  }
>  
> +#ifdef CONFIG_ACPI
>  int __init acpi_parse_mp_wake(union acpi_subtable_headers *header,
> +
> +#ifdef CONFIG_OF
> +int __init dtb_parse_mp_wake(u64 *wake_mailbox_paddr)

Why not returning the mailbox physical address and 0 on failure instead
of that pointer and a integer return value which is ignored at the call
site?

> +{
> +	struct device_node *node;
> +	u64 mailaddr;
> +	int ret = 0;
> +
> +	node = of_find_node_by_path("/cpus");
> +	if (!node)
> +		return -ENODEV;
> +
> +	if (of_property_match_string(node, "enable-method",
> +				     "acpi-wakeup-mailbox") < 0) {

Please use the 100 characters line width and spare the line break.

> +		pr_err("No acpi wakeup mailbox enable-method\n");
> +		ret = -ENODEV;
> +		goto done;
> +	}
> +
> +	/*
> +	 * No support to the MADT reset vector yet.

s/to/for/

Also a single line comment is sufficient for this.

> +	 */
> +	cpu_hotplug_disable_offlining();
> +
> +	if (of_property_read_u64(node, "wakeup-mailbox-addr", &mailaddr)) {
> +		pr_err("Invalid wakeup mailbox addr\n");
> +		ret = -EINVAL;
> +		goto done;
> +	}
> +	acpi_mp_wake_mailbox_paddr = mailaddr;
> +	if (wake_mailbox_paddr)
> +		*wake_mailbox_paddr = mailaddr;
> +	pr_info("dt wakeup-mailbox: addr 0x%llx\n", mailaddr);
> +	apic_update_callback(wakeup_secondary_cpu_64, acpi_wakeup_cpu);
> +done:

newline before the label please. Up there you waste 3 lines for a
trivial comment and here you make the code unreadable...

Thanks,

        tglx
diff mbox series

Patch

diff --git a/MAINTAINERS b/MAINTAINERS
index 6cc6d5c367df..de3eaa0fdaaa 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -288,6 +288,7 @@  T:	git git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
 F:	Documentation/ABI/testing/configfs-acpi
 F:	Documentation/ABI/testing/sysfs-bus-acpi
 F:	Documentation/firmware-guide/acpi/
+F:	arch/x86/include/asm/madt_wakeup.h
 F:	arch/x86/kernel/acpi/
 F:	arch/x86/kernel/madt_playdead.S
 F:	arch/x86/kernel/madt_wakeup.c
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 02775a61b557..e92dfefba675 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -1123,7 +1123,7 @@  config X86_LOCAL_APIC
 config ACPI_MADT_WAKEUP
 	def_bool y
 	depends on X86_64
-	depends on ACPI
+	depends on ACPI || OF
 	depends on SMP
 	depends on X86_LOCAL_APIC
 
diff --git a/arch/x86/include/asm/acpi.h b/arch/x86/include/asm/acpi.h
index 21bc53f5ed0c..0e082303ca26 100644
--- a/arch/x86/include/asm/acpi.h
+++ b/arch/x86/include/asm/acpi.h
@@ -83,7 +83,6 @@  union acpi_subtable_headers;
 int __init acpi_parse_mp_wake(union acpi_subtable_headers *header,
 			      const unsigned long end);
 
-void asm_acpi_mp_play_dead(u64 reset_vector, u64 pgd_pa);
 
 /*
  * Check if the CPU can handle C2 and deeper
diff --git a/arch/x86/include/asm/madt_wakeup.h b/arch/x86/include/asm/madt_wakeup.h
new file mode 100644
index 000000000000..faabf51c1e8f
--- /dev/null
+++ b/arch/x86/include/asm/madt_wakeup.h
@@ -0,0 +1,16 @@ 
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __ASM_X86_MADT_WAKEUP_H
+#define __ASM_X86_MADT_WAKEUP_H
+
+void asm_acpi_mp_play_dead(u64 reset_vector, u64 pgd_pa);
+
+#if defined(CONFIG_OF) && defined(CONFIG_ACPI_MADT_WAKEUP)
+int dtb_parse_mp_wake(u64 *wake_mailbox_paddr);
+#else
+static inline int dtb_parse_mp_wake(u64 *wake_mailbox_paddr)
+{
+	return -ENODEV;
+}
+#endif
+
+#endif /* __ASM_X86_MADT_WAKEUP_H */
diff --git a/arch/x86/kernel/madt_wakeup.c b/arch/x86/kernel/madt_wakeup.c
index 6cfe762be28b..f6795a6ab2d3 100644
--- a/arch/x86/kernel/madt_wakeup.c
+++ b/arch/x86/kernel/madt_wakeup.c
@@ -14,6 +14,8 @@ 
 #include <asm/nmi.h>
 #include <asm/processor.h>
 #include <asm/reboot.h>
+#include <asm/madt_wakeup.h>
+#include <asm/prom.h>
 
 /* Physical address of the Multiprocessor Wakeup Structure mailbox */
 static u64 acpi_mp_wake_mailbox_paddr __ro_after_init;
@@ -122,7 +124,7 @@  static int __init init_transition_pgtable(pgd_t *pgd)
 	return 0;
 }
 
-static int __init acpi_mp_setup_reset(u64 reset_vector)
+static int __init __maybe_unused acpi_mp_setup_reset(u64 reset_vector)
 {
 	struct x86_mapping_info info = {
 		.alloc_pgt_page = alloc_pgt_page,
@@ -226,7 +228,7 @@  static int acpi_wakeup_cpu(u32 apicid, unsigned long start_ip)
 	return 0;
 }
 
-static void acpi_mp_disable_offlining(struct acpi_madt_multiproc_wakeup *mp_wake)
+static void __maybe_unused acpi_mp_disable_offlining(struct acpi_madt_multiproc_wakeup *mp_wake)
 {
 	cpu_hotplug_disable_offlining();
 
@@ -248,6 +250,7 @@  static void acpi_mp_disable_offlining(struct acpi_madt_multiproc_wakeup *mp_wake
 	mp_wake->mailbox_address = 0;
 }
 
+#ifdef CONFIG_ACPI
 int __init acpi_parse_mp_wake(union acpi_subtable_headers *header,
 			      const unsigned long end)
 {
@@ -290,3 +293,43 @@  int __init acpi_parse_mp_wake(union acpi_subtable_headers *header,
 
 	return 0;
 }
+#endif /* CONFIG_ACPI */
+
+#ifdef CONFIG_OF
+int __init dtb_parse_mp_wake(u64 *wake_mailbox_paddr)
+{
+	struct device_node *node;
+	u64 mailaddr;
+	int ret = 0;
+
+	node = of_find_node_by_path("/cpus");
+	if (!node)
+		return -ENODEV;
+
+	if (of_property_match_string(node, "enable-method",
+				     "acpi-wakeup-mailbox") < 0) {
+		pr_err("No acpi wakeup mailbox enable-method\n");
+		ret = -ENODEV;
+		goto done;
+	}
+
+	/*
+	 * No support to the MADT reset vector yet.
+	 */
+	cpu_hotplug_disable_offlining();
+
+	if (of_property_read_u64(node, "wakeup-mailbox-addr", &mailaddr)) {
+		pr_err("Invalid wakeup mailbox addr\n");
+		ret = -EINVAL;
+		goto done;
+	}
+	acpi_mp_wake_mailbox_paddr = mailaddr;
+	if (wake_mailbox_paddr)
+		*wake_mailbox_paddr = mailaddr;
+	pr_info("dt wakeup-mailbox: addr 0x%llx\n", mailaddr);
+	apic_update_callback(wakeup_secondary_cpu_64, acpi_wakeup_cpu);
+done:
+	of_node_put(node);
+	return ret;
+}
+#endif /* CONFIG_OF */