df3f53
From 63d8d3e8d54326842677bc3d3a3e43a133846a71 Mon Sep 17 00:00:00 2001
df3f53
From: Masayoshi Mizuma <m.mizuma@jp.fujitsu.com>
df3f53
Date: Tue, 15 Dec 2020 12:07:38 +0100
df3f53
Subject: [PATCH 51/55] lscpu: use cluster on aarch64 machine which doesn't
df3f53
 have ACPI PPTT
df3f53
df3f53
lscpu may show the wrong number of sockets if the machine is aarch64 and
df3f53
doesn't have ACPI PPTT.
df3f53
df3f53
That's because lscpu show the number of sockets by using a sysfs entry
df3f53
(cpu/cpuX/topology/core_siblings). The sysfs entry is set by MPIDR_EL1
df3f53
register if the machine doesn't have ACPI PPTT. MPIDR_EL1 doesn't show
df3f53
the physical socket information directly. It shows the affinity level.
df3f53
df3f53
According to linux/arch/arm64/kernel/topology.c:store_cpu_topology(),
df3f53
the top level of affinity is called as 'Cluster'.
df3f53
df3f53
Use Cluster instead of Socket on the machine which doesn't have ACPI PPTT.
df3f53
df3f53
Note, ARM SBBR v1.2 requires ACPI PPTT, so this patch is needed for the
df3f53
machine which is based on SBBR v1.0 and v1.1.
df3f53
df3f53
[kzak@redhat.com: - port to old code
df3f53
                  - change semantic to be same as current upstream]
df3f53
df3f53
Addresses: https://bugzilla.redhat.com/show_bug.cgi?id=1883056
df3f53
Upstream: 73c0a766ffbe60e013b55cfd716d531b5a6ae22a
df3f53
Upstream: https://marc.info/?l=util-linux-ng&m=159984070611464&w=2
df3f53
Signed-off-by: Masayoshi Mizuma <m.mizuma@jp.fujitsu.com>
df3f53
Signed-off-by: Karel Zak <kzak@redhat.com>
df3f53
---
df3f53
 sys-utils/lscpu.1 |  3 +++
df3f53
 sys-utils/lscpu.c | 65 ++++++++++++++++++++++++++++++++++++++++++-----
df3f53
 sys-utils/lscpu.h |  3 +++
df3f53
 3 files changed, 65 insertions(+), 6 deletions(-)
df3f53
df3f53
diff --git a/sys-utils/lscpu.1 b/sys-utils/lscpu.1
df3f53
index b70f2e151..cf981d708 100644
df3f53
--- a/sys-utils/lscpu.1
df3f53
+++ b/sys-utils/lscpu.1
df3f53
@@ -47,6 +47,9 @@ The logical core number.  A core can contain several CPUs.
df3f53
 .B SOCKET
df3f53
 The logical socket number.  A socket can contain several cores.
df3f53
 .TP
df3f53
+.B CLUSTER
df3f53
+The logical cluster number.  A cluster can contain several cores.
df3f53
+.TP
df3f53
 .B BOOK
df3f53
 The logical book number.  A book can contain several sockets.
df3f53
 .TP
df3f53
diff --git a/sys-utils/lscpu.c b/sys-utils/lscpu.c
df3f53
index 748d545b6..a8b448fa0 100644
df3f53
--- a/sys-utils/lscpu.c
df3f53
+++ b/sys-utils/lscpu.c
df3f53
@@ -70,6 +70,7 @@
df3f53
 #define _PATH_SYS_HYP_FEATURES "/sys/hypervisor/properties/features"
df3f53
 #define _PATH_SYS_CPU		_PATH_SYS_SYSTEM "/cpu"
df3f53
 #define _PATH_SYS_NODE		_PATH_SYS_SYSTEM "/node"
df3f53
+#define _PATH_ACPI_PPTT		"/sys/firmware/acpi/tables/PPTT"
df3f53
 #define _PATH_PROC_XEN		"/proc/xen"
df3f53
 #define _PATH_PROC_XENCAP	_PATH_PROC_XEN "/capabilities"
df3f53
 #define _PATH_PROC_CPUINFO	"/proc/cpuinfo"
df3f53
@@ -168,6 +169,7 @@ enum {
df3f53
 	COL_CPU,
df3f53
 	COL_CORE,
df3f53
 	COL_SOCKET,
df3f53
+	COL_CLUSTER,
df3f53
 	COL_NODE,
df3f53
 	COL_BOOK,
df3f53
 	COL_DRAWER,
df3f53
@@ -194,6 +196,7 @@ static struct lscpu_coldesc coldescs[] =
df3f53
 	[COL_CPU]          = { "CPU", N_("logical CPU number"), 1 },
df3f53
 	[COL_CORE]         = { "CORE", N_("logical core number") },
df3f53
 	[COL_SOCKET]       = { "SOCKET", N_("logical socket number") },
df3f53
+	[COL_CLUSTER]      = { "CLUSTER", N_("logical cluster number") },
df3f53
 	[COL_NODE]         = { "NODE", N_("logical NUMA node number") },
df3f53
 	[COL_BOOK]         = { "BOOK", N_("logical book number") },
df3f53
 	[COL_DRAWER]       = { "DRAWER", N_("logical drawer number") },
df3f53
@@ -383,6 +386,26 @@ static void read_physical_info_powerpc(
df3f53
 }
df3f53
 #endif
df3f53
 
df3f53
+static int is_fallback_to_cluster(struct lscpu_desc *desc)
df3f53
+{
df3f53
+	char *arch;
df3f53
+	struct stat st;
df3f53
+	struct utsname utsbuf;
df3f53
+
df3f53
+	if (desc)
df3f53
+		arch = desc->arch;
df3f53
+	else {
df3f53
+		if (uname(&utsbuf) == -1)
df3f53
+			err(EXIT_FAILURE, _("error: uname failed"));
df3f53
+		arch = utsbuf.machine;
df3f53
+	}
df3f53
+
df3f53
+	if (!(strcmp(arch, "aarch64")) && (stat(_PATH_ACPI_PPTT, &st) < 0))
df3f53
+		return 1;
df3f53
+	else
df3f53
+		return 0;
df3f53
+}
df3f53
+
df3f53
 
df3f53
 static void
df3f53
 read_basicinfo(struct lscpu_desc *desc, struct lscpu_modifier *mod)
df3f53
@@ -1344,6 +1367,10 @@ get_cell_data(struct lscpu_desc *desc, int idx, int col,
df3f53
 				snprintf(buf, bufsz, "%zu", i);
df3f53
 		}
df3f53
 		break;
df3f53
+	case COL_CLUSTER:
df3f53
+		if (!desc->is_cluster)
df3f53
+			break;
df3f53
+		/* fallthrough */
df3f53
 	case COL_SOCKET:
df3f53
 		if (mod->physical) {
df3f53
 			if (desc->socketids[idx] ==  -1)
df3f53
@@ -1799,12 +1826,18 @@ print_summary(struct lscpu_desc *desc, struct lscpu_modifier *mod)
df3f53
 			if (fd)
df3f53
 				fclose(fd);
df3f53
 		}
df3f53
+
df3f53
+
df3f53
 		if (desc->mtid)
df3f53
 			threads_per_core = atoi(desc->mtid) + 1;
df3f53
 		add_summary_n(tb, _("Thread(s) per core:"),
df3f53
 			threads_per_core ?: desc->nthreads / desc->ncores);
df3f53
-		add_summary_n(tb, _("Core(s) per socket:"),
df3f53
-			cores_per_socket ?: desc->ncores / desc->nsockets);
df3f53
+		if (desc->is_cluster)
df3f53
+			add_summary_n(tb, _("Core(s) per cluster:"),
df3f53
+				cores_per_socket ?: desc->ncores / desc->nsockets);
df3f53
+		else
df3f53
+			add_summary_n(tb, _("Core(s) per socket:"),
df3f53
+				cores_per_socket ?: desc->ncores / desc->nsockets);
df3f53
 		if (desc->nbooks) {
df3f53
 			add_summary_n(tb, _("Socket(s) per book:"),
df3f53
 				sockets_per_book ?: desc->nsockets / desc->nbooks);
df3f53
@@ -1816,7 +1849,17 @@ print_summary(struct lscpu_desc *desc, struct lscpu_modifier *mod)
df3f53
 				add_summary_n(tb, _("Book(s):"), books_per_drawer ?: desc->nbooks);
df3f53
 			}
df3f53
 		} else {
df3f53
-			add_summary_n(tb, _("Socket(s):"), sockets_per_book ?: desc->nsockets);
df3f53
+			if (desc->is_cluster) {
df3f53
+				if (desc->nr_socket_on_cluster > 0)
df3f53
+					add_summary_n(tb, _("Socket(s):"), desc->nr_socket_on_cluster);
df3f53
+				else
df3f53
+					add_summary_s(tb, _("Socket(s):"), "-");
df3f53
+
df3f53
+				add_summary_n(tb, _("Cluster(s):"),
df3f53
+						sockets_per_book ?: desc->nsockets);
df3f53
+			} else
df3f53
+				add_summary_n(tb, _("Socket(s):"),
df3f53
+						sockets_per_book ?: desc->nsockets);
df3f53
 		}
df3f53
 	}
df3f53
 	if (desc->nnodes)
df3f53
@@ -2060,10 +2103,13 @@ int main(int argc, char *argv[])
df3f53
 		qsort(desc->ecaches, desc->necaches,
df3f53
 				sizeof(struct cpu_cache), cachecmp);
df3f53
 
df3f53
+	desc->is_cluster = is_fallback_to_cluster(desc);
df3f53
+
df3f53
 	read_nodes(desc);
df3f53
 	read_hypervisor(desc, mod);
df3f53
 	arm_cpu_decode(desc);
df3f53
 
df3f53
+
df3f53
 	switch(mod->mode) {
df3f53
 	case OUTPUT_SUMMARY:
df3f53
 		print_summary(desc, mod);
df3f53
@@ -2072,7 +2118,10 @@ int main(int argc, char *argv[])
df3f53
 		if (!ncolumns) {
df3f53
 			columns[ncolumns++] = COL_CPU;
df3f53
 			columns[ncolumns++] = COL_CORE;
df3f53
-			columns[ncolumns++] = COL_SOCKET;
df3f53
+			if (desc->is_cluster)
df3f53
+				columns[ncolumns++] = COL_CLUSTER;
df3f53
+			else
df3f53
+				columns[ncolumns++] = COL_SOCKET;
df3f53
 			columns[ncolumns++] = COL_NODE;
df3f53
 			columns[ncolumns++] = COL_CACHE;
df3f53
 			mod->compat = 1;
df3f53
@@ -2089,8 +2138,12 @@ int main(int argc, char *argv[])
df3f53
 				columns[ncolumns++] = COL_DRAWER;
df3f53
 			if (desc->bookmaps)
df3f53
 				columns[ncolumns++] = COL_BOOK;
df3f53
-			if (desc->socketmaps)
df3f53
-				columns[ncolumns++] = COL_SOCKET;
df3f53
+			if (desc->socketmaps) {
df3f53
+				if (desc->is_cluster)
df3f53
+					columns[ncolumns++] = COL_CLUSTER;
df3f53
+				else
df3f53
+					columns[ncolumns++] = COL_SOCKET;
df3f53
+			}
df3f53
 			if (desc->coremaps)
df3f53
 				columns[ncolumns++] = COL_CORE;
df3f53
 			if (desc->caches)
df3f53
diff --git a/sys-utils/lscpu.h b/sys-utils/lscpu.h
df3f53
index 3d1885a3e..bffa9df60 100644
df3f53
--- a/sys-utils/lscpu.h
df3f53
+++ b/sys-utils/lscpu.h
df3f53
@@ -158,6 +158,9 @@ struct lscpu_desc {
df3f53
 	int		physsockets;	/* Physical sockets (modules) */
df3f53
 	int		physchips;	/* Physical chips */
df3f53
 	int		physcoresperchip;	/* Physical cores per chip */
df3f53
+
df3f53
+	int		is_cluster;
df3f53
+	int		nr_socket_on_cluster;
df3f53
 };
df3f53
 
df3f53
 enum {
df3f53
-- 
df3f53
2.29.2
df3f53