All of lore.kernel.org
 help / color / mirror / Atom feed
From: Andrew Jones <drjones@redhat.com>
To: linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org
Cc: jeremy.linton@arm.com, ard.biesheuvel@linaro.org,
	sudeep.holla@arm.com, shunyong.yang@hxt-semitech.com,
	yu.zheng@hxt-semitech.com, catalin.marinas@arm.com,
	will.deacon@arm.com
Subject: [PATCH] arm64: acpi: reenumerate topology ids
Date: Thu, 28 Jun 2018 16:51:28 +0200	[thread overview]
Message-ID: <20180628145128.10057-1-drjones@redhat.com> (raw)

When booting with devicetree, and the devicetree has the cpu-map
node, the topology IDs that are visible from sysfs are generated
with counters. ACPI, on the other hand, uses ACPI table pointer
offsets, which, while guaranteed to be unique, look a bit weird.
Instead, we can generate DT identical topology IDs for ACPI by
just using counters for the leaf nodes and by remapping the
non-leaf table pointer offsets to counters.

Cc: Jeremy Linton <jeremy.linton@arm.com>
Cc: Sudeep Holla <sudeep.holla@arm.com>
Signed-off-by: Andrew Jones <drjones@redhat.com>
---

v1:
Reworked this since the RFC in order to make the algorithm more
obvious. It wasn't clear in the RFC that the ACPI nodes could be
in any order, although they could have been. I've tested that
this works with nodes in arbitrary order by hacking the QEMU
PPTT table generator[*].

Note, while this produces equivalent topology IDs to what the
DT cpu-map node produces for all sane configs, if PEs are
threads (have MPIDR.MT set), but the cpu-map does not specify
threads, then, while the DT parsing code will happily call the
threads "cores", ACPI will see that the PPTT leaf nodes are for
threads and produce different topology IDs. I see this difference
as a bug with the DT parsing which can be addressed separately.

[*] https://github.com/rhdrjones/qemu/commits/virt-cpu-topology


 arch/arm64/kernel/topology.c | 70 ++++++++++++++++++++++++++++++++++----------
 1 file changed, 55 insertions(+), 15 deletions(-)

diff --git a/arch/arm64/kernel/topology.c b/arch/arm64/kernel/topology.c
index f845a8617812..7ef457401b24 100644
--- a/arch/arm64/kernel/topology.c
+++ b/arch/arm64/kernel/topology.c
@@ -316,6 +316,10 @@ static void __init reset_cpu_topology(void)
 }
 
 #ifdef CONFIG_ACPI
+
+#define acpi_topology_mktag(x)	(-((x) + 1))
+#define acpi_topology_istag(x)	((x) < 0)
+
 /*
  * Propagate the topology information of the processor_topology_node tree to the
  * cpu_topology array.
@@ -323,27 +327,31 @@ static void __init reset_cpu_topology(void)
 static int __init parse_acpi_topology(void)
 {
 	bool is_threaded;
-	int cpu, topology_id;
+	int package_id = 0;
+	int cpu, ret;
 
 	is_threaded = read_cpuid_mpidr() & MPIDR_MT_BITMASK;
 
+	/*
+	 * Loop through all PEs twice. In the first loop store parent
+	 * tags into the IDs. In the second loop we reset the IDs as
+	 * 0..N-1 per parent tag.
+	 */
+
 	for_each_possible_cpu(cpu) {
 		int i, cache_id;
 
-		topology_id = find_acpi_cpu_topology(cpu, 0);
-		if (topology_id < 0)
-			return topology_id;
-
-		if (is_threaded) {
-			cpu_topology[cpu].thread_id = topology_id;
-			topology_id = find_acpi_cpu_topology(cpu, 1);
-			cpu_topology[cpu].core_id   = topology_id;
-		} else {
-			cpu_topology[cpu].thread_id  = -1;
-			cpu_topology[cpu].core_id    = topology_id;
-		}
-		topology_id = find_acpi_cpu_topology_package(cpu);
-		cpu_topology[cpu].package_id = topology_id;
+		ret = find_acpi_cpu_topology(cpu, 0);
+		if (ret < 0)
+			return ret;
+
+		if (is_threaded)
+			ret = find_acpi_cpu_topology(cpu, 1);
+		else
+			cpu_topology[cpu].thread_id = -1;
+		cpu_topology[cpu].core_id = acpi_topology_mktag(ret);
+		ret = find_acpi_cpu_topology_package(cpu);
+		cpu_topology[cpu].package_id = acpi_topology_mktag(ret);
 
 		i = acpi_find_last_cache_level(cpu);
 
@@ -358,6 +366,38 @@ static int __init parse_acpi_topology(void)
 		}
 	}
 
+	for_each_possible_cpu(cpu) {
+		int package_tag = cpu_topology[cpu].package_id;
+		int core_id = 0, cpu2;
+
+		if (!acpi_topology_istag(package_tag))
+			continue;
+
+		for_each_possible_cpu(cpu2) {
+			if (cpu_topology[cpu2].package_id != package_tag)
+				continue;
+
+			if (is_threaded) {
+				int core_tag = cpu_topology[cpu2].core_id;
+				int thread_id = 0, cpu3;
+
+				for_each_possible_cpu(cpu3) {
+					if (cpu_topology[cpu3].core_id != core_tag)
+						continue;
+
+					cpu_topology[cpu3].thread_id = thread_id++;
+					cpu_topology[cpu3].core_id = core_id;
+					cpu_topology[cpu3].package_id = package_id;
+				}
+				++core_id;
+			} else {
+				cpu_topology[cpu2].core_id = core_id++;
+				cpu_topology[cpu2].package_id = package_id;
+			}
+		}
+		++package_id;
+	}
+
 	return 0;
 }
 
-- 
1.8.3.1


WARNING: multiple messages have this Message-ID (diff)
From: drjones@redhat.com (Andrew Jones)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH] arm64: acpi: reenumerate topology ids
Date: Thu, 28 Jun 2018 16:51:28 +0200	[thread overview]
Message-ID: <20180628145128.10057-1-drjones@redhat.com> (raw)

When booting with devicetree, and the devicetree has the cpu-map
node, the topology IDs that are visible from sysfs are generated
with counters. ACPI, on the other hand, uses ACPI table pointer
offsets, which, while guaranteed to be unique, look a bit weird.
Instead, we can generate DT identical topology IDs for ACPI by
just using counters for the leaf nodes and by remapping the
non-leaf table pointer offsets to counters.

Cc: Jeremy Linton <jeremy.linton@arm.com>
Cc: Sudeep Holla <sudeep.holla@arm.com>
Signed-off-by: Andrew Jones <drjones@redhat.com>
---

v1:
Reworked this since the RFC in order to make the algorithm more
obvious. It wasn't clear in the RFC that the ACPI nodes could be
in any order, although they could have been. I've tested that
this works with nodes in arbitrary order by hacking the QEMU
PPTT table generator[*].

Note, while this produces equivalent topology IDs to what the
DT cpu-map node produces for all sane configs, if PEs are
threads (have MPIDR.MT set), but the cpu-map does not specify
threads, then, while the DT parsing code will happily call the
threads "cores", ACPI will see that the PPTT leaf nodes are for
threads and produce different topology IDs. I see this difference
as a bug with the DT parsing which can be addressed separately.

[*] https://github.com/rhdrjones/qemu/commits/virt-cpu-topology


 arch/arm64/kernel/topology.c | 70 ++++++++++++++++++++++++++++++++++----------
 1 file changed, 55 insertions(+), 15 deletions(-)

diff --git a/arch/arm64/kernel/topology.c b/arch/arm64/kernel/topology.c
index f845a8617812..7ef457401b24 100644
--- a/arch/arm64/kernel/topology.c
+++ b/arch/arm64/kernel/topology.c
@@ -316,6 +316,10 @@ static void __init reset_cpu_topology(void)
 }
 
 #ifdef CONFIG_ACPI
+
+#define acpi_topology_mktag(x)	(-((x) + 1))
+#define acpi_topology_istag(x)	((x) < 0)
+
 /*
  * Propagate the topology information of the processor_topology_node tree to the
  * cpu_topology array.
@@ -323,27 +327,31 @@ static void __init reset_cpu_topology(void)
 static int __init parse_acpi_topology(void)
 {
 	bool is_threaded;
-	int cpu, topology_id;
+	int package_id = 0;
+	int cpu, ret;
 
 	is_threaded = read_cpuid_mpidr() & MPIDR_MT_BITMASK;
 
+	/*
+	 * Loop through all PEs twice. In the first loop store parent
+	 * tags into the IDs. In the second loop we reset the IDs as
+	 * 0..N-1 per parent tag.
+	 */
+
 	for_each_possible_cpu(cpu) {
 		int i, cache_id;
 
-		topology_id = find_acpi_cpu_topology(cpu, 0);
-		if (topology_id < 0)
-			return topology_id;
-
-		if (is_threaded) {
-			cpu_topology[cpu].thread_id = topology_id;
-			topology_id = find_acpi_cpu_topology(cpu, 1);
-			cpu_topology[cpu].core_id   = topology_id;
-		} else {
-			cpu_topology[cpu].thread_id  = -1;
-			cpu_topology[cpu].core_id    = topology_id;
-		}
-		topology_id = find_acpi_cpu_topology_package(cpu);
-		cpu_topology[cpu].package_id = topology_id;
+		ret = find_acpi_cpu_topology(cpu, 0);
+		if (ret < 0)
+			return ret;
+
+		if (is_threaded)
+			ret = find_acpi_cpu_topology(cpu, 1);
+		else
+			cpu_topology[cpu].thread_id = -1;
+		cpu_topology[cpu].core_id = acpi_topology_mktag(ret);
+		ret = find_acpi_cpu_topology_package(cpu);
+		cpu_topology[cpu].package_id = acpi_topology_mktag(ret);
 
 		i = acpi_find_last_cache_level(cpu);
 
@@ -358,6 +366,38 @@ static int __init parse_acpi_topology(void)
 		}
 	}
 
+	for_each_possible_cpu(cpu) {
+		int package_tag = cpu_topology[cpu].package_id;
+		int core_id = 0, cpu2;
+
+		if (!acpi_topology_istag(package_tag))
+			continue;
+
+		for_each_possible_cpu(cpu2) {
+			if (cpu_topology[cpu2].package_id != package_tag)
+				continue;
+
+			if (is_threaded) {
+				int core_tag = cpu_topology[cpu2].core_id;
+				int thread_id = 0, cpu3;
+
+				for_each_possible_cpu(cpu3) {
+					if (cpu_topology[cpu3].core_id != core_tag)
+						continue;
+
+					cpu_topology[cpu3].thread_id = thread_id++;
+					cpu_topology[cpu3].core_id = core_id;
+					cpu_topology[cpu3].package_id = package_id;
+				}
+				++core_id;
+			} else {
+				cpu_topology[cpu2].core_id = core_id++;
+				cpu_topology[cpu2].package_id = package_id;
+			}
+		}
+		++package_id;
+	}
+
 	return 0;
 }
 
-- 
1.8.3.1

             reply	other threads:[~2018-06-27 19:48 UTC|newest]

Thread overview: 40+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-06-28 14:51 Andrew Jones [this message]
2018-06-28 14:51 ` [PATCH] arm64: acpi: reenumerate topology ids Andrew Jones
2018-06-28 16:30 ` Sudeep Holla
2018-06-28 16:30   ` Sudeep Holla
2018-06-28 17:12   ` Jeremy Linton
2018-06-28 17:12     ` Jeremy Linton
2018-06-29 10:53     ` Sudeep Holla
2018-06-29 10:53       ` Sudeep Holla
2018-06-29 11:42       ` Andrew Jones
2018-06-29 11:42         ` Andrew Jones
2018-06-29 11:55         ` Andrew Jones
2018-06-29 11:55           ` Andrew Jones
2018-06-29 13:48           ` Sudeep Holla
2018-06-29 13:48             ` Sudeep Holla
2018-06-29 13:38         ` Sudeep Holla
2018-06-29 13:38           ` Sudeep Holla
2018-06-29 16:03           ` Andrew Jones
2018-06-29 16:03             ` Andrew Jones
2018-06-28 17:32   ` Andrew Jones
2018-06-28 17:32     ` Andrew Jones
2018-06-29 10:29     ` Sudeep Holla
2018-06-29 10:29       ` Sudeep Holla
2018-06-29 11:23       ` Andrew Jones
2018-06-29 11:23         ` Andrew Jones
2018-06-29 13:29         ` Sudeep Holla
2018-06-29 13:29           ` Sudeep Holla
2018-06-29 15:46           ` Andrew Jones
2018-06-29 15:46             ` Andrew Jones
2018-06-29 15:55             ` Sudeep Holla
2018-06-29 15:55               ` Sudeep Holla
2018-06-29 16:48             ` Jeremy Linton
2018-06-29 16:48               ` Jeremy Linton
2018-06-29 17:03               ` Andrew Jones
2018-06-29 17:03                 ` Andrew Jones
2018-06-29 17:23                 ` Sudeep Holla
2018-06-29 17:23                   ` Sudeep Holla
2018-06-29 18:03                   ` Andrew Jones
2018-06-29 18:03                     ` Andrew Jones
2018-07-02 14:58             ` Jeffrey Hugo
2018-07-02 14:58               ` Jeffrey Hugo

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=20180628145128.10057-1-drjones@redhat.com \
    --to=drjones@redhat.com \
    --cc=ard.biesheuvel@linaro.org \
    --cc=catalin.marinas@arm.com \
    --cc=jeremy.linton@arm.com \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=shunyong.yang@hxt-semitech.com \
    --cc=sudeep.holla@arm.com \
    --cc=will.deacon@arm.com \
    --cc=yu.zheng@hxt-semitech.com \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.