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