[PATCH 1/4] lscpu: use cluster on aarch64 machine which doesn't have ACPI PPTT

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Masayoshi Mizuma <m.mizuma@xxxxxxxxxxxxxx>

lscpu may show the wrong number of sockets if the machine is aarch64 and
doesn't have ACPI PPTT.

That's because lscpu show the number of sockets by using a sysfs entry
(cpu/cpuX/topology/core_siblings). The sysfs entry is set by MPIDR_EL1
register if the machine doesn't have ACPI PPTT. MPIDR_EL1 doesn't show
the physical socket information directly. It shows the affinity level.

According to linux/arch/arm64/kernel/topology.c:store_cpu_topology(),
the top level of affinity is called as 'Cluster'.

Use Cluster instead of Socket on the machine which doesn't have ACPI PPTT.

Note, ARM SBBR v1.2 requires ACPI PPTT, so this patch is needed for the
machine which is based on SBBR v1.0 and v1.1.

Signed-off-by: Masayoshi Mizuma <m.mizuma@xxxxxxxxxxxxxx>
---
 sys-utils/lscpu.1 |  3 +++
 sys-utils/lscpu.c | 69 ++++++++++++++++++++++++++++++++++++++++++-----
 2 files changed, 65 insertions(+), 7 deletions(-)

diff --git a/sys-utils/lscpu.1 b/sys-utils/lscpu.1
index 1ef6ce021..928d39dee 100644
--- a/sys-utils/lscpu.1
+++ b/sys-utils/lscpu.1
@@ -52,6 +52,9 @@ The logical core number.  A core can contain several CPUs.
 .B SOCKET
 The logical socket number.  A socket can contain several cores.
 .TP
+.B CLUSTER
+The logical cluster number.  A cluster can contain several cores.
+.TP
 .B BOOK
 The logical book number.  A book can contain several sockets.
 .TP
diff --git a/sys-utils/lscpu.c b/sys-utils/lscpu.c
index ca085b665..8c823c170 100644
--- a/sys-utils/lscpu.c
+++ b/sys-utils/lscpu.c
@@ -68,6 +68,7 @@
 #define _PATH_SYS_HYP_FEATURES	"/sys/hypervisor/properties/features"
 #define _PATH_SYS_CPU		_PATH_SYS_SYSTEM "/cpu"
 #define _PATH_SYS_NODE		_PATH_SYS_SYSTEM "/node"
+#define _PATH_ACPI_PPTT		"/sys/firmware/acpi/tables/PPTT"
 
 /* Xen Domain feature flag used for /sys/hypervisor/properties/features */
 #define XENFEAT_supervisor_mode_kernel		3
@@ -155,6 +156,7 @@ enum {
 	COL_CPU_CPU,
 	COL_CPU_CORE,
 	COL_CPU_SOCKET,
+	COL_CPU_CLUSTER,
 	COL_CPU_NODE,
 	COL_CPU_BOOK,
 	COL_CPU_DRAWER,
@@ -196,6 +198,7 @@ static struct lscpu_coldesc coldescs_cpu[] =
 {
 	[COL_CPU_CPU]          = { "CPU", N_("logical CPU number"), SCOLS_FL_RIGHT, 1 },
 	[COL_CPU_CORE]         = { "CORE", N_("logical core number"), SCOLS_FL_RIGHT },
+	[COL_CPU_CLUSTER]      = { "CLUSTER", N_("logical cluster number"), SCOLS_FL_RIGHT },
 	[COL_CPU_SOCKET]       = { "SOCKET", N_("logical socket number"), SCOLS_FL_RIGHT },
 	[COL_CPU_NODE]         = { "NODE", N_("logical NUMA node number"), SCOLS_FL_RIGHT },
 	[COL_CPU_BOOK]         = { "BOOK", N_("logical book number"), SCOLS_FL_RIGHT },
@@ -224,6 +227,26 @@ static struct lscpu_coldesc coldescs_cache[] =
 	[COL_CACHE_COHERENCYSIZE] = { "COHERENCY-SIZE", N_("minimum amount of data in bytes transferred from memory to cache"), SCOLS_FL_RIGHT }
 };
 
+static int is_fallback_to_cluster(struct lscpu_desc *desc)
+{
+	char *arch;
+	struct stat st;
+	struct utsname utsbuf;
+
+	if (desc)
+		arch = desc->arch;
+	else {
+		if (uname(&utsbuf) == -1)
+			err(EXIT_FAILURE, _("error: uname failed"));
+		arch = utsbuf.machine;
+	}
+
+	if (!(strcmp(arch, "aarch64")) && (stat(_PATH_ACPI_PPTT, &st) < 0))
+		return 1;
+	else
+		return 0;
+}
+
 
 static int get_cache_full_size(struct lscpu_desc *desc, struct cpu_cache *ca, uint64_t *res);
 
@@ -231,12 +254,21 @@ static int
 cpu_column_name_to_id(const char *name, size_t namesz)
 {
 	size_t i;
+	int is_cluster = is_fallback_to_cluster(NULL);
 
 	for (i = 0; i < ARRAY_SIZE(coldescs_cpu); i++) {
 		const char *cn = coldescs_cpu[i].name;
 
-		if (!strncasecmp(name, cn, namesz) && !*(cn + namesz))
+		if (!strncasecmp(name, cn, namesz) && !*(cn + namesz)) {
+			if ((!strncasecmp(cn, "cluster", namesz)) && (!is_cluster)) {
+				warnx(_("%s doesn't work on this machine. Use socket."), name);
+				return -1;
+			} else if ((!strncasecmp(cn, "socket", namesz)) && (is_cluster)) {
+				warnx(_("%s doesn't work on this machine. Use cluster."), name);
+				return -1;
+			}
 			return i;
+		}
 	}
 	warnx(_("unknown column: %s"), name);
 	return -1;
@@ -1506,6 +1538,7 @@ get_cell_data(struct lscpu_desc *desc, int idx, int col,
 		}
 		break;
 	case COL_CPU_SOCKET:
+	case COL_CPU_CLUSTER:
 		if (mod->physical) {
 			if (desc->socketids[idx] ==  -1)
 				snprintf(buf, bufsz, "-");
@@ -2100,6 +2133,7 @@ print_summary(struct lscpu_desc *desc, struct lscpu_modifier *mod)
 		int threads_per_core, cores_per_socket, sockets_per_book;
 		int books_per_drawer, drawers;
 		FILE *fd;
+		int is_cluster;
 
 		threads_per_core = cores_per_socket = sockets_per_book = 0;
 		books_per_drawer = drawers = 0;
@@ -2124,12 +2158,19 @@ print_summary(struct lscpu_desc *desc, struct lscpu_modifier *mod)
 			if (fd)
 				fclose(fd);
 		}
+
+		is_cluster = is_fallback_to_cluster(desc);
+
 		if (desc->mtid)
 			threads_per_core = atoi(desc->mtid) + 1;
 		add_summary_n(tb, _("Thread(s) per core:"),
 			threads_per_core ?: desc->nthreads / desc->ncores);
-		add_summary_n(tb, _("Core(s) per socket:"),
-			cores_per_socket ?: desc->ncores / desc->nsockets);
+		if (is_cluster)
+			add_summary_n(tb, _("Core(s) per cluster:"),
+				cores_per_socket ?: desc->ncores / desc->nsockets);
+		else
+			add_summary_n(tb, _("Core(s) per socket:"),
+				cores_per_socket ?: desc->ncores / desc->nsockets);
 		if (desc->nbooks) {
 			add_summary_n(tb, _("Socket(s) per book:"),
 				sockets_per_book ?: desc->nsockets / desc->nbooks);
@@ -2141,7 +2182,11 @@ print_summary(struct lscpu_desc *desc, struct lscpu_modifier *mod)
 				add_summary_n(tb, _("Book(s):"), books_per_drawer ?: desc->nbooks);
 			}
 		} else {
-			add_summary_n(tb, _("Socket(s):"), sockets_per_book ?: desc->nsockets);
+			if (is_cluster)
+				add_summary_n(tb, _("Cluster(s):"), desc->nsockets);
+			else
+				add_summary_n(tb, _("Socket(s):"),
+						sockets_per_book ?: desc->nsockets);
 		}
 	}
 	if (desc->nnodes)
@@ -2300,6 +2345,7 @@ int main(int argc, char *argv[])
 	int columns[ARRAY_SIZE(coldescs_cpu)], ncolumns = 0;
 	int cpu_modifier_specified = 0;
 	size_t setsize;
+	int is_cluster;
 
 	enum {
 		OPT_OUTPUT_ALL = CHAR_MAX + 1,
@@ -2479,6 +2525,8 @@ int main(int argc, char *argv[])
 	read_hypervisor(desc, mod);
 	arm_cpu_decode(desc);
 
+	is_cluster = is_fallback_to_cluster(desc);
+
 	switch(mod->mode) {
 	case OUTPUT_SUMMARY:
 		print_summary(desc, mod);
@@ -2501,7 +2549,10 @@ int main(int argc, char *argv[])
 		if (!ncolumns) {
 			columns[ncolumns++] = COL_CPU_CPU;
 			columns[ncolumns++] = COL_CPU_CORE;
-			columns[ncolumns++] = COL_CPU_SOCKET;
+			if (is_cluster)
+				columns[ncolumns++] = COL_CPU_CLUSTER;
+			else
+				columns[ncolumns++] = COL_CPU_SOCKET;
 			columns[ncolumns++] = COL_CPU_NODE;
 			columns[ncolumns++] = COL_CPU_CACHE;
 			mod->compat = 1;
@@ -2518,8 +2569,12 @@ int main(int argc, char *argv[])
 				columns[ncolumns++] = COL_CPU_DRAWER;
 			if (desc->bookmaps)
 				columns[ncolumns++] = COL_CPU_BOOK;
-			if (desc->socketmaps)
-				columns[ncolumns++] = COL_CPU_SOCKET;
+			if (desc->socketmaps) {
+				if (is_cluster)
+					columns[ncolumns++] = COL_CPU_CLUSTER;
+				else
+					columns[ncolumns++] = COL_CPU_SOCKET;
+			}
 			if (desc->coremaps)
 				columns[ncolumns++] = COL_CPU_CORE;
 			if (desc->caches)
-- 
2.27.0




[Index of Archives]     [Netdev]     [Ethernet Bridging]     [Linux Wireless]     [Kernel Newbies]     [Security]     [Linux for Hams]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux Admin]     [Samba]

  Powered by Linux