mail archive of the barebox mailing list
 help / color / mirror / Atom feed
* [PATCH master 0/4] ARM: psci: client: unbreak hypervisor boot
@ 2022-11-01  6:26 Ahmad Fatoum
  2022-11-01  6:26 ` [PATCH master 1/4] ARM: psci: of: fixup only version if node already exists Ahmad Fatoum
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Ahmad Fatoum @ 2022-11-01  6:26 UTC (permalink / raw)
  To: barebox

PSCI fixup logic is useful when kernel DT contains just arm,psci and
expects firmware to update compatible as PSCI v0.1 doesn't have a
command for querying PSCI version. The fixup was too zealous though and
hardcoded the method to smc, breaking hvc boot. The result was also not
confirming to the current bindings, so fix that up.

This fixes boot on QEMU ARM Virt64, which previously crashed when smc
was executed.

Ahmad Fatoum (4):
  ARM: psci: of: fixup only version if node already exists
  ARM: psci: client: match most specific compatible first
  ARM: psci: client: always register OF fixup
  ARM: psci: keep older PSCI versions in compatible fixup

 arch/arm/cpu/psci-client.c | 12 ++++--------
 arch/arm/cpu/psci-of.c     | 39 +++++++++++++++++++++-----------------
 2 files changed, 26 insertions(+), 25 deletions(-)

-- 
2.30.2




^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH master 1/4] ARM: psci: of: fixup only version if node already exists
  2022-11-01  6:26 [PATCH master 0/4] ARM: psci: client: unbreak hypervisor boot Ahmad Fatoum
@ 2022-11-01  6:26 ` Ahmad Fatoum
  2022-11-01  6:26 ` [PATCH master 2/4] ARM: psci: client: match most specific compatible first Ahmad Fatoum
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: Ahmad Fatoum @ 2022-11-01  6:26 UTC (permalink / raw)
  To: barebox; +Cc: Ahmad Fatoum

When barebox is booted as QEMU -kernel, PSCI will have method = "hvc",
because QEMU will act as Hypervisor. barebox handles this correctly and
will use hvc instead of smc, but of_psci_fixup() always fixes up
method = "smc" thereby breaking kernel boot.

Fix this by only updating version if the node already exists and
omitting everything else.

Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
 arch/arm/cpu/psci-of.c | 39 +++++++++++++++++++++++----------------
 1 file changed, 23 insertions(+), 16 deletions(-)

diff --git a/arch/arm/cpu/psci-of.c b/arch/arm/cpu/psci-of.c
index ef83b0edee69..e08a04b36d05 100644
--- a/arch/arm/cpu/psci-of.c
+++ b/arch/arm/cpu/psci-of.c
@@ -7,16 +7,10 @@
 #include <asm/psci.h>
 #include <linux/arm-smccc.h>
 
-int of_psci_fixup(struct device_node *root, unsigned long psci_version)
+static int of_psci_version_fixup(struct device_node *psci,
+				 unsigned long psci_version)
 {
-	struct device_node *psci;
-	int ret;
 	const char *compat;
-	struct device_node *cpus, *cpu;
-
-	psci = of_create_node(root, "/psci");
-	if (!psci)
-		return -EINVAL;
 
 	if (psci_version >= ARM_PSCI_VER_1_0) {
 		compat = "arm,psci-1.0";
@@ -27,6 +21,27 @@ int of_psci_fixup(struct device_node *root, unsigned long psci_version)
 		return -EINVAL;
 	}
 
+	return of_property_write_string(psci, "compatible", compat);
+}
+
+int of_psci_fixup(struct device_node *root, unsigned long psci_version)
+{
+	struct device_node *psci;
+	int ret;
+	struct device_node *cpus, *cpu;
+
+	psci = of_find_node_by_path_from(root, "/psci");
+	if (psci)
+		return of_psci_version_fixup(psci, psci_version);
+
+	psci = of_create_node(root, "/psci");
+	if (!psci)
+		return -EINVAL;
+
+	ret = of_property_write_string(psci, "method", "smc");
+	if (ret)
+		return ret;
+
 	cpus = of_find_node_by_path_from(root, "/cpus");
 	if (!cpus) {
 		pr_err("Cannot find /cpus node, PSCI fixup aborting\n");
@@ -42,13 +57,5 @@ int of_psci_fixup(struct device_node *root, unsigned long psci_version)
 		pr_debug("Fixed %s\n", cpu->full_name);
 	}
 
-	ret = of_property_write_string(psci, "compatible", compat);
-	if (ret)
-		return ret;
-
-	ret = of_property_write_string(psci, "method", "smc");
-	if (ret)
-		return ret;
-
 	return 0;
 }
-- 
2.30.2




^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH master 2/4] ARM: psci: client: match most specific compatible first
  2022-11-01  6:26 [PATCH master 0/4] ARM: psci: client: unbreak hypervisor boot Ahmad Fatoum
  2022-11-01  6:26 ` [PATCH master 1/4] ARM: psci: of: fixup only version if node already exists Ahmad Fatoum
@ 2022-11-01  6:26 ` Ahmad Fatoum
  2022-11-01  6:26 ` [PATCH master 3/4] ARM: psci: client: always register OF fixup Ahmad Fatoum
  2022-11-01  6:26 ` [PATCH master 4/4] ARM: psci: keep older PSCI versions in compatible fixup Ahmad Fatoum
  3 siblings, 0 replies; 5+ messages in thread
From: Ahmad Fatoum @ 2022-11-01  6:26 UTC (permalink / raw)
  To: barebox; +Cc: Ahmad Fatoum

The PSCI client driver will use the barebox compatible to determine
whether it's safe to use the ARM_PSCI_0_2_FN_PSCI_VERSION command.

For this reason, we need to match against the newer PSCI compatibles
first, because otherwise

  compatible = "arm,psci-1.0", "arm,psci-0.2", "arm,psci";

would have us end up with PSCI v0.1 instead.

Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
 arch/arm/cpu/psci-client.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm/cpu/psci-client.c b/arch/arm/cpu/psci-client.c
index 7d5b3768b59e..8e151177c2d7 100644
--- a/arch/arm/cpu/psci-client.c
+++ b/arch/arm/cpu/psci-client.c
@@ -176,9 +176,9 @@ static int __init psci_probe(struct device_d *dev)
 }
 
 static __maybe_unused struct of_device_id psci_dt_ids[] = {
-	{ .compatible = "arm,psci",	.data = (void*)ARM_PSCI_VER(0,1) },
-	{ .compatible = "arm,psci-0.2",	.data = (void*)ARM_PSCI_VER(0,2) },
 	{ .compatible = "arm,psci-1.0",	.data = (void*)ARM_PSCI_VER(1,0) },
+	{ .compatible = "arm,psci-0.2",	.data = (void*)ARM_PSCI_VER(0,2) },
+	{ .compatible = "arm,psci",	.data = (void*)ARM_PSCI_VER(0,1) },
 	{ /* sentinel */ },
 };
 
-- 
2.30.2




^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH master 3/4] ARM: psci: client: always register OF fixup
  2022-11-01  6:26 [PATCH master 0/4] ARM: psci: client: unbreak hypervisor boot Ahmad Fatoum
  2022-11-01  6:26 ` [PATCH master 1/4] ARM: psci: of: fixup only version if node already exists Ahmad Fatoum
  2022-11-01  6:26 ` [PATCH master 2/4] ARM: psci: client: match most specific compatible first Ahmad Fatoum
@ 2022-11-01  6:26 ` Ahmad Fatoum
  2022-11-01  6:26 ` [PATCH master 4/4] ARM: psci: keep older PSCI versions in compatible fixup Ahmad Fatoum
  3 siblings, 0 replies; 5+ messages in thread
From: Ahmad Fatoum @ 2022-11-01  6:26 UTC (permalink / raw)
  To: barebox; +Cc: Ahmad Fatoum

We currently only register the device tree fixup if PSCI version in
device tree disagrees with version read from firmware. The barebox
PSCI DT version may differ from the kernel version though, so we
should rather run the fixup always. If the kernel has already an
up-to-date compatible, it won't change. But for cases where firmware is
expected to fill out the correct PSCI version, barebox will do what's
expected.

While at it, move the of_version logic together to make it easier
to follow.

Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
 arch/arm/cpu/psci-client.c | 8 ++------
 1 file changed, 2 insertions(+), 6 deletions(-)

diff --git a/arch/arm/cpu/psci-client.c b/arch/arm/cpu/psci-client.c
index 8e151177c2d7..218170dfa4ba 100644
--- a/arch/arm/cpu/psci-client.c
+++ b/arch/arm/cpu/psci-client.c
@@ -119,10 +119,6 @@ static int __init psci_probe(struct device_d *dev)
 	ulong of_version, actual_version;
 	int ret;
 
-	ret = dev_get_drvdata(dev, (const void **)&of_version);
-	if (ret)
-		return -ENODEV;
-
 	ret = of_property_read_string(dev->device_node, "method", &method);
 	if (ret) {
 		dev_warn(dev, "missing \"method\" property\n");
@@ -139,6 +135,7 @@ static int __init psci_probe(struct device_d *dev)
 	}
 
 
+	of_version = (ulong)device_get_match_data(dev);
 	if (of_version < ARM_PSCI_VER(0,2)) {
 		version = of_version;
 
@@ -155,8 +152,7 @@ static int __init psci_probe(struct device_d *dev)
 	dev_info(dev, "detected version %u.%u\n",
 		 version >> 16, version & 0xffff);
 
-	if (actual_version != of_version)
-		of_register_fixup(of_psci_do_fixup, &version);
+	of_register_fixup(of_psci_do_fixup, &version);
 
 	ret = poweroff_handler_register_fn(psci_poweroff);
 	if (ret)
-- 
2.30.2




^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH master 4/4] ARM: psci: keep older PSCI versions in compatible fixup
  2022-11-01  6:26 [PATCH master 0/4] ARM: psci: client: unbreak hypervisor boot Ahmad Fatoum
                   ` (2 preceding siblings ...)
  2022-11-01  6:26 ` [PATCH master 3/4] ARM: psci: client: always register OF fixup Ahmad Fatoum
@ 2022-11-01  6:26 ` Ahmad Fatoum
  3 siblings, 0 replies; 5+ messages in thread
From: Ahmad Fatoum @ 2022-11-01  6:26 UTC (permalink / raw)
  To: barebox; +Cc: Ahmad Fatoum

The psci device tree binding mandates keeping older ARM PSCI compatibles
as less-specific compatible entries. Have the barebox fixup comply
with this.

Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
 arch/arm/cpu/psci-of.c | 20 +++++++++-----------
 1 file changed, 9 insertions(+), 11 deletions(-)

diff --git a/arch/arm/cpu/psci-of.c b/arch/arm/cpu/psci-of.c
index e08a04b36d05..0d25e8b2fdb2 100644
--- a/arch/arm/cpu/psci-of.c
+++ b/arch/arm/cpu/psci-of.c
@@ -10,18 +10,16 @@
 static int of_psci_version_fixup(struct device_node *psci,
 				 unsigned long psci_version)
 {
-	const char *compat;
-
-	if (psci_version >= ARM_PSCI_VER_1_0) {
-		compat = "arm,psci-1.0";
-	} else if (psci_version >= ARM_PSCI_VER_0_2) {
-		compat = "arm,psci-0.2";
-	} else {
-		pr_err("Unsupported PSCI version %ld\n", psci_version);
-		return -EINVAL;
-	}
+	if (psci_version >= ARM_PSCI_VER_1_0)
+		return of_property_write_strings(psci, "compatible",
+			"arm,psci-1.0", "arm,psci-0.2", "arm,psci", NULL);
+
+	if (psci_version >= ARM_PSCI_VER_0_2)
+		return of_property_write_strings(psci, "compatible",
+			"arm,psci-0.2", "arm,psci", NULL);
 
-	return of_property_write_string(psci, "compatible", compat);
+	pr_err("Unsupported PSCI version %ld\n", psci_version);
+	return -EINVAL;
 }
 
 int of_psci_fixup(struct device_node *root, unsigned long psci_version)
-- 
2.30.2




^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2022-11-01  6:28 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-11-01  6:26 [PATCH master 0/4] ARM: psci: client: unbreak hypervisor boot Ahmad Fatoum
2022-11-01  6:26 ` [PATCH master 1/4] ARM: psci: of: fixup only version if node already exists Ahmad Fatoum
2022-11-01  6:26 ` [PATCH master 2/4] ARM: psci: client: match most specific compatible first Ahmad Fatoum
2022-11-01  6:26 ` [PATCH master 3/4] ARM: psci: client: always register OF fixup Ahmad Fatoum
2022-11-01  6:26 ` [PATCH master 4/4] ARM: psci: keep older PSCI versions in compatible fixup Ahmad Fatoum

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox