All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/5] lscpu: Fix socket information on aarch64 machine
@ 2020-11-14  4:12 Masayoshi Mizuma
  2020-11-14  4:12 ` [PATCH v2 1/5] lscpu: use cluster on aarch64 machine which doesn't have ACPI PPTT Masayoshi Mizuma
                   ` (4 more replies)
  0 siblings, 5 replies; 8+ messages in thread
From: Masayoshi Mizuma @ 2020-11-14  4:12 UTC (permalink / raw)
  To: util-linux; +Cc: Masayoshi Mizuma, Masayoshi Mizuma

From: Masayoshi Mizuma <m.mizuma@jp.fujitsu.com>

lscpu may show the wrong number of physical sockets on aarch64 machine
as 'Socket(s)'.

That is because lscpu uses a sysfs entry (cpu/cpuX/topology/core_siblings) to
get the number of sockets. For aarch64, the sysfs entry is set from MPIDR_EL1
register if the machine doesn't have ACPI PPTT. According to ARM Architecture
Reference Manual, the register shows the topology as the affinity, but doesn't
show the physical socket information.

There are such aarch64 machines because ARM SBBR v1.0 and v1.1 don't require 
ACPI PPTT. SBBR v1.2 requires ACPI PPTT.

For the aarch64 machine, probably 'Cluster(s)' is good instead of 'Socket(s)'
according to linux/arch/arm64/kernel/topology.c:store_cpu_topology().

To get the number of sockets on the machine, SMBIOS Processor information (Type04)
is useful for lscpu because the SMBIOS information is a mandatory
feature for the aarch64 machine which is based on ARM SBBR v1.0 and newer.

With these patches, lscpu shows as following on the machine:

  For unprivileged user:
    $ lscpu 
    Architecture:            aarch64
    ...
        Socket(s):           -
        Cluster(s):          4

  For root:
    # lscpu 
    Architecture:            aarch64
    ...
        Socket(s):           1
        Cluster(s):          4

Changelog:
	v2: Rebased to the latest lscpu

Masayoshi Mizuma (5):
  lscpu: use cluster on aarch64 machine which doesn't have ACPI PPTT
  lscpu-virt: split hypervisor_from_dmi_table()
  lscpu-dmi: Move some functions related to DMI to lscpu-dmi
  lscpu: add helper to get physical sockets
  lscpu: show the number of physical socket on aarch64 machine without
    ACPI PPTT

 include/c.h             |   1 +
 sys-utils/Makemodule.am |   1 +
 sys-utils/lscpu-arm.c   |  25 ++++++++++
 sys-utils/lscpu-dmi.c   | 108 ++++++++++++++++++++++++++++++++++++++++
 sys-utils/lscpu-virt.c  |  62 ++++++-----------------
 sys-utils/lscpu.1       |   3 ++
 sys-utils/lscpu.c       |  47 ++++++++++++++---
 sys-utils/lscpu.h       |  39 +++++++--------
 8 files changed, 209 insertions(+), 77 deletions(-)
 create mode 100644 sys-utils/lscpu-dmi.c

-- 
2.27.0


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

* [PATCH v2 1/5] lscpu: use cluster on aarch64 machine which doesn't have ACPI PPTT
  2020-11-14  4:12 [PATCH v2 0/5] lscpu: Fix socket information on aarch64 machine Masayoshi Mizuma
@ 2020-11-14  4:12 ` Masayoshi Mizuma
  2020-11-19  8:38   ` Karel Zak
  2020-11-14  4:12 ` [PATCH v2 2/5] lscpu-virt: split hypervisor_from_dmi_table() Masayoshi Mizuma
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 8+ messages in thread
From: Masayoshi Mizuma @ 2020-11-14  4:12 UTC (permalink / raw)
  To: util-linux; +Cc: Masayoshi Mizuma, Masayoshi Mizuma

From: Masayoshi Mizuma <m.mizuma@jp.fujitsu.com>

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

That's because lscpu shows 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.

This patch is useful for aarch64 machine which is based on ARM
SBBR v1.0 and v1.1, the specs don't require ACPI PPTT. ARM SBBR v1.2
requires ACPI PPTT.

Signed-off-by: Masayoshi Mizuma <m.mizuma@jp.fujitsu.com>
---
 include/c.h           |  1 +
 sys-utils/lscpu-arm.c | 23 +++++++++++++++++++++++
 sys-utils/lscpu.1     |  3 +++
 sys-utils/lscpu.c     | 42 +++++++++++++++++++++++++++++++++++-------
 sys-utils/lscpu.h     |  3 +++
 5 files changed, 65 insertions(+), 7 deletions(-)

diff --git a/include/c.h b/include/c.h
index ae0813109..e92636177 100644
--- a/include/c.h
+++ b/include/c.h
@@ -16,6 +16,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <errno.h>
+#include <sys/utsname.h>
 
 #include <assert.h>
 
diff --git a/sys-utils/lscpu-arm.c b/sys-utils/lscpu-arm.c
index 1cbc9775f..7ef05e8e7 100644
--- a/sys-utils/lscpu-arm.c
+++ b/sys-utils/lscpu-arm.c
@@ -362,10 +362,33 @@ static void arm_decode(struct lscpu_cxt *cxt, struct lscpu_cputype *ct)
 	arm_rXpY_decode(ct);
 }
 
+int lscpu_is_cluster_arm(struct lscpu_cxt *cxt)
+{
+	char *arch;
+	struct stat st;
+	struct utsname utsbuf;
+
+	if (cxt)
+		arch = cxt->arch->name;
+	else {
+		if (uname(&utsbuf) == -1)
+			err(EXIT_FAILURE, _("error: uname failed"));
+		arch = utsbuf.machine;
+	}
+
+	if (!(strcmp(arch, "aarch64")) && (stat(_PATH_ACPI_PPTT, &st) < 0)
+			&& (cxt->ncputypes == 1))
+		return 1;
+	else
+		return 0;
+}
+
 void lscpu_decode_arm(struct lscpu_cxt *cxt)
 {
 	size_t i;
 
+	cxt->is_cluster = lscpu_is_cluster_arm(cxt);
+
 	for (i = 0; i < cxt->ncputypes; i++)
 		arm_decode(cxt, cxt->cputypes[i]);
 }
diff --git a/sys-utils/lscpu.1 b/sys-utils/lscpu.1
index ed14dc663..a41125395 100644
--- a/sys-utils/lscpu.1
+++ b/sys-utils/lscpu.1
@@ -55,6 +55,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 6e501b044..c5a4cc984 100644
--- a/sys-utils/lscpu.c
+++ b/sys-utils/lscpu.c
@@ -95,6 +95,7 @@ enum {
 	COL_CPU_CPU,
 	COL_CPU_CORE,
 	COL_CPU_SOCKET,
+	COL_CPU_CLUSTER,
 	COL_CPU_NODE,
 	COL_CPU_BOOK,
 	COL_CPU_DRAWER,
@@ -138,6 +139,7 @@ static struct lscpu_coldesc coldescs_cpu[] =
 	[COL_CPU_BOGOMIPS]     = { "BOGOMIPS", N_("crude measurement of CPU speed"), SCOLS_FL_RIGHT, 1 },
 	[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 },
@@ -181,12 +183,21 @@ static int
 cpu_column_name_to_id(const char *name, size_t namesz)
 {
 	size_t i;
+	int is_cluster = lscpu_is_cluster_arm(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;
@@ -337,6 +348,7 @@ static char *get_cell_data(
 		fill_id(cxt, cpu, core, buf, bufsz);
 		break;
 	case COL_CPU_SOCKET:
+	case COL_CPU_CLUSTER:
 		fill_id(cxt, cpu, socket, buf, bufsz);
 		break;
 	case COL_CPU_DRAWER:
@@ -843,7 +855,10 @@ print_summary_cputype(struct lscpu_cxt *cxt,
 		add_summary_s(tb, sec, _("Model:"), ct->revision ? ct->revision : ct->model);
 
 	add_summary_n(tb, sec, _("Thread(s) per core:"), ct->nthreads_per_core);
-	add_summary_n(tb, sec, _("Core(s) per socket:"), ct->ncores_per_socket);
+	if (cxt->is_cluster)
+		add_summary_n(tb, sec, _("Core(s) per cluster:"), ct->ncores_per_socket);
+	else
+		add_summary_n(tb, sec, _("Core(s) per socket:"), ct->ncores_per_socket);
 
 	if (ct->nbooks) {
 		add_summary_n(tb, sec, _("Socket(s) per book:"), ct->nsockets_per_book);
@@ -852,8 +867,14 @@ print_summary_cputype(struct lscpu_cxt *cxt,
 			add_summary_n(tb, sec, _("Drawer(s):"), ct->ndrawers_per_system ?: ct->ndrawers);
 		} else
 			add_summary_n(tb, sec, _("Book(s):"), ct->nbooks_per_drawer ?: ct->nbooks);
-	} else
-		add_summary_n(tb, sec, _("Socket(s):"), ct->nsockets_per_book ?: ct->nsockets);
+	} else {
+		if (cxt->is_cluster)
+			add_summary_n(tb, sec, _("Cluster(s):"),
+					ct->nsockets_per_book ?: ct->nsockets);
+		else
+			add_summary_n(tb, sec, _("Socket(s):"),
+					ct->nsockets_per_book ?: ct->nsockets);
+	}
 
 	if (ct->stepping)
 		add_summary_s(tb, sec, _("Stepping:"), ct->stepping);
@@ -1325,8 +1346,12 @@ int main(int argc, char *argv[])
 				columns[ncolumns++] = COL_CPU_DRAWER;
 			if (ct && ct->nbooks)
 				columns[ncolumns++] = COL_CPU_BOOK;
-			if (ct && ct->nsockets)
-				columns[ncolumns++] = COL_CPU_SOCKET;
+			if (ct && ct->nsockets) {
+				if (cxt->is_cluster)
+					columns[ncolumns++] = COL_CPU_CLUSTER;
+				else
+					columns[ncolumns++] = COL_CPU_SOCKET;
+			}
 			if (ct && ct->ncores)
 				columns[ncolumns++] = COL_CPU_CORE;
 			if (cxt->ncaches)
@@ -1350,7 +1375,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 (cxt->is_cluster)
+				columns[ncolumns++] = COL_CPU_CLUSTER;
+			else
+				columns[ncolumns++] = COL_CPU_SOCKET;
 			columns[ncolumns++] = COL_CPU_NODE;
 			columns[ncolumns++] = COL_CPU_CACHE;
 			cxt->show_compatible = 1;
diff --git a/sys-utils/lscpu.h b/sys-utils/lscpu.h
index 465bd3fe2..227e7f391 100644
--- a/sys-utils/lscpu.h
+++ b/sys-utils/lscpu.h
@@ -33,6 +33,7 @@ UL_DEBUG_DECLARE_MASK(lscpu);
 #define _PATH_SYS_NODE		_PATH_SYS_SYSTEM "/node"
 #define _PATH_SYS_DMI		"/sys/firmware/dmi/tables/DMI"
 #define _PATH_SYS_DMI_TYPE4	"/sys/firmware/dmi/entries/4-0/raw"
+#define _PATH_ACPI_PPTT		"/sys/firmware/acpi/tables/PPTT"
 
 struct lscpu_cache {
 	int		id;		/* unique identifier */
@@ -242,6 +243,7 @@ struct lscpu_cxt {
 		     json : 1,
 		     bytes : 1;
 
+	int is_cluster; /* For aarch64 if the machine doesn't have ACPI PPTT */
 };
 
 #define is_cpu_online(_cxt, _cpu) \
@@ -291,6 +293,7 @@ int lscpu_cpu_set_type(struct lscpu_cpu *cpu, struct lscpu_cputype *type);
 int lscpu_create_cpus(struct lscpu_cxt *cxt, cpu_set_t *cpuset, size_t setsize);
 struct lscpu_cpu *lscpu_cpus_loopup_by_type(struct lscpu_cxt *cxt, struct lscpu_cputype *ct);
 
+int lscpu_is_cluster_arm(struct lscpu_cxt *cxt);
 void lscpu_decode_arm(struct lscpu_cxt *cxt);
 
 int lookup(char *line, char *pattern, char **value);
-- 
2.27.0


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

* [PATCH v2 2/5] lscpu-virt: split hypervisor_from_dmi_table()
  2020-11-14  4:12 [PATCH v2 0/5] lscpu: Fix socket information on aarch64 machine Masayoshi Mizuma
  2020-11-14  4:12 ` [PATCH v2 1/5] lscpu: use cluster on aarch64 machine which doesn't have ACPI PPTT Masayoshi Mizuma
@ 2020-11-14  4:12 ` Masayoshi Mizuma
  2020-11-14  4:12 ` [PATCH v2 3/5] lscpu-dmi: Move some functions related to DMI to lscpu-dmi Masayoshi Mizuma
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 8+ messages in thread
From: Masayoshi Mizuma @ 2020-11-14  4:12 UTC (permalink / raw)
  To: util-linux; +Cc: Masayoshi Mizuma, Masayoshi Mizuma

From: Masayoshi Mizuma <m.mizuma@jp.fujitsu.com>

Split hypervisor_from_dmi_table() to parsing dmi table and checking the
hypervisor vendor.

Signed-off-by: Masayoshi Mizuma <m.mizuma@jp.fujitsu.com>
---
 sys-utils/lscpu-virt.c | 54 ++++++++++++++++++++++++++----------------
 sys-utils/lscpu.h      |  6 +++++
 2 files changed, 40 insertions(+), 20 deletions(-)

diff --git a/sys-utils/lscpu-virt.c b/sys-utils/lscpu-virt.c
index 527f7caa4..32558fd9f 100644
--- a/sys-utils/lscpu-virt.c
+++ b/sys-utils/lscpu-virt.c
@@ -76,20 +76,13 @@ nothing:
 	return NULL;
 }
 
-static int hypervisor_from_dmi_table(uint32_t base, uint16_t len,
-				uint16_t num, const char *devmem)
+static int parse_dmi_table(uint16_t len, uint16_t num,
+				uint8_t *data,
+				struct dmi_info *di)
 {
-	uint8_t *buf;
-	uint8_t *data;
+	uint8_t *buf = data;
+	int rc = -1;
 	int i = 0;
-	char *vendor = NULL;
-	char *product = NULL;
-	char *manufacturer = NULL;
-	int rc = VIRT_VENDOR_NONE;
-
-	data = buf = get_mem_chunk(base, len, devmem);
-	if (!buf)
-		goto done;
 
 	 /* 4 is the length of an SMBIOS structure header */
 	while (i < num && data + 4 <= buf + len) {
@@ -113,11 +106,11 @@ static int hypervisor_from_dmi_table(uint32_t base, uint16_t len,
 		next += 2;
 		switch (h.type) {
 			case 0:
-				vendor = dmi_string(&h, data[0x04]);
+				di->vendor = dmi_string(&h, data[0x04]);
 				break;
 			case 1:
-				manufacturer = dmi_string(&h, data[0x04]);
-				product = dmi_string(&h, data[0x05]);
+				di->manufacturer = dmi_string(&h, data[0x04]);
+				di->product = dmi_string(&h, data[0x05]);
 				break;
 			default:
 				break;
@@ -126,15 +119,36 @@ static int hypervisor_from_dmi_table(uint32_t base, uint16_t len,
 		data = next;
 		i++;
 	}
-	if (manufacturer && !strcmp(manufacturer, "innotek GmbH"))
+	rc = 0;
+done:
+	return rc;
+}
+
+static int hypervisor_from_dmi_table(uint32_t base, uint16_t len,
+				uint16_t num, const char *devmem)
+{
+	uint8_t *data;
+	int rc = VIRT_VENDOR_NONE;
+	struct dmi_info di;
+
+	data = get_mem_chunk(base, len, devmem);
+	if (!data)
+		return rc;
+
+	memset(&di, 0, sizeof(struct dmi_info));
+	rc = parse_dmi_table(len, num, data, &di);
+	if (rc < 0)
+		goto done;
+
+	if (di.manufacturer && !strcmp(di.manufacturer, "innotek GmbH"))
 		rc = VIRT_VENDOR_INNOTEK;
-	else if (manufacturer && strstr(manufacturer, "HITACHI") &&
-					product && strstr(product, "LPAR"))
+	else if (di.manufacturer && strstr(di.manufacturer, "HITACHI") &&
+					di.product && strstr(di.product, "LPAR"))
 		rc = VIRT_VENDOR_HITACHI;
-	else if (vendor && !strcmp(vendor, "Parallels"))
+	else if (di.vendor && !strcmp(di.vendor, "Parallels"))
 		rc = VIRT_VENDOR_PARALLELS;
 done:
-	free(buf);
+	free(data);
 	return rc;
 }
 
diff --git a/sys-utils/lscpu.h b/sys-utils/lscpu.h
index 227e7f391..b199de3dd 100644
--- a/sys-utils/lscpu.h
+++ b/sys-utils/lscpu.h
@@ -306,6 +306,12 @@ struct lscpu_dmi_header
 	uint8_t *data;
 };
 
+struct dmi_info {
+	char *vendor;
+	char *product;
+	char *manufacturer;
+};
+
 static inline void to_dmi_header(struct lscpu_dmi_header *h, uint8_t *data)
 {
 	h->type = data[0];
-- 
2.27.0


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

* [PATCH v2 3/5] lscpu-dmi: Move some functions related to DMI to lscpu-dmi
  2020-11-14  4:12 [PATCH v2 0/5] lscpu: Fix socket information on aarch64 machine Masayoshi Mizuma
  2020-11-14  4:12 ` [PATCH v2 1/5] lscpu: use cluster on aarch64 machine which doesn't have ACPI PPTT Masayoshi Mizuma
  2020-11-14  4:12 ` [PATCH v2 2/5] lscpu-virt: split hypervisor_from_dmi_table() Masayoshi Mizuma
@ 2020-11-14  4:12 ` Masayoshi Mizuma
  2020-11-14  4:12 ` [PATCH v2 4/5] lscpu: add helper to get physical sockets Masayoshi Mizuma
  2020-11-14  4:12 ` [PATCH v2 5/5] lscpu: show the number of physical socket on aarch64 machine without ACPI PPTT Masayoshi Mizuma
  4 siblings, 0 replies; 8+ messages in thread
From: Masayoshi Mizuma @ 2020-11-14  4:12 UTC (permalink / raw)
  To: util-linux; +Cc: Masayoshi Mizuma, Masayoshi Mizuma

From: Masayoshi Mizuma <m.mizuma@jp.fujitsu.com>

Move some functions related to DMI to lscpu-dmi.

Signed-off-by: Masayoshi Mizuma <m.mizuma@jp.fujitsu.com>
---
 sys-utils/Makemodule.am |  1 +
 sys-utils/lscpu-dmi.c   | 79 +++++++++++++++++++++++++++++++++++++++++
 sys-utils/lscpu-virt.c  | 50 +-------------------------
 sys-utils/lscpu.h       | 28 +++------------
 4 files changed, 86 insertions(+), 72 deletions(-)
 create mode 100644 sys-utils/lscpu-dmi.c

diff --git a/sys-utils/Makemodule.am b/sys-utils/Makemodule.am
index 5459a3a2e..df8fd403a 100644
--- a/sys-utils/Makemodule.am
+++ b/sys-utils/Makemodule.am
@@ -396,6 +396,7 @@ lscpu_SOURCES = sys-utils/lscpu.c \
 		sys-utils/lscpu-topology.c \
 		sys-utils/lscpu-virt.c \
 		sys-utils/lscpu-arm.c \
+		sys-utils/lscpu-dmi.c \
 		sys-utils/lscpu.h
 lscpu_LDADD = $(LDADD) libcommon.la libsmartcols.la $(RTAS_LIBS)
 lscpu_CFLAGS = $(AM_CFLAGS) -I$(ul_libsmartcols_incdir)
diff --git a/sys-utils/lscpu-dmi.c b/sys-utils/lscpu-dmi.c
new file mode 100644
index 000000000..00d4439f8
--- /dev/null
+++ b/sys-utils/lscpu-dmi.c
@@ -0,0 +1,79 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2020 FUJITSU LIMITED.  All rights reserved.
+ */
+
+#include "lscpu.h"
+
+void to_dmi_header(struct lscpu_dmi_header *h, uint8_t *data)
+{
+	h->type = data[0];
+	h->length = data[1];
+	memcpy(&h->handle, data + 2, sizeof(h->handle));
+	h->data = data;
+}
+
+char *dmi_string(const struct lscpu_dmi_header *dm, uint8_t s)
+{
+	char *bp = (char *)dm->data;
+
+	if (!s || !bp)
+		return NULL;
+
+	bp += dm->length;
+	while (s > 1 && *bp) {
+		bp += strlen(bp);
+		bp++;
+		s--;
+	}
+
+	return !*bp ? NULL : bp;
+}
+
+int parse_dmi_table(uint16_t len, uint16_t num,
+				uint8_t *data,
+				struct dmi_info *di)
+{
+	uint8_t *buf = data;
+	int rc = -1;
+	int i = 0;
+
+	 /* 4 is the length of an SMBIOS structure header */
+	while (i < num && data + 4 <= buf + len) {
+		uint8_t *next;
+		struct lscpu_dmi_header h;
+
+		to_dmi_header(&h, data);
+
+		/*
+		 * If a short entry is found (less than 4 bytes), not only it
+		 * is invalid, but we cannot reliably locate the next entry.
+		 * Better stop at this point.
+		 */
+		if (h.length < 4)
+			goto done;
+
+		/* look for the next handle */
+		next = data + h.length;
+		while (next - buf + 1 < len && (next[0] != 0 || next[1] != 0))
+			next++;
+		next += 2;
+		switch (h.type) {
+		case 0:
+			di->vendor = dmi_string(&h, data[0x04]);
+			break;
+		case 1:
+			di->manufacturer = dmi_string(&h, data[0x04]);
+			di->product = dmi_string(&h, data[0x05]);
+			break;
+		default:
+			break;
+		}
+
+		data = next;
+		i++;
+	}
+	rc = 0;
+done:
+	return rc;
+}
diff --git a/sys-utils/lscpu-virt.c b/sys-utils/lscpu-virt.c
index 32558fd9f..3b9d090a2 100644
--- a/sys-utils/lscpu-virt.c
+++ b/sys-utils/lscpu-virt.c
@@ -52,7 +52,7 @@ static const int hv_graphics_pci[] = {
 #define WORD(x) (uint16_t)(*(const uint16_t *)(x))
 #define DWORD(x) (uint32_t)(*(const uint32_t *)(x))
 
-static void *get_mem_chunk(size_t base, size_t len, const char *devmem)
+void *get_mem_chunk(size_t base, size_t len, const char *devmem)
 {
 	void *p = NULL;
 	int fd;
@@ -76,54 +76,6 @@ nothing:
 	return NULL;
 }
 
-static int parse_dmi_table(uint16_t len, uint16_t num,
-				uint8_t *data,
-				struct dmi_info *di)
-{
-	uint8_t *buf = data;
-	int rc = -1;
-	int i = 0;
-
-	 /* 4 is the length of an SMBIOS structure header */
-	while (i < num && data + 4 <= buf + len) {
-		uint8_t *next;
-		struct lscpu_dmi_header h;
-
-		to_dmi_header(&h, data);
-
-		/*
-		 * If a short entry is found (less than 4 bytes), not only it
-		 * is invalid, but we cannot reliably locate the next entry.
-		 * Better stop at this point.
-		 */
-		if (h.length < 4)
-			goto done;
-
-		/* look for the next handle */
-		next = data + h.length;
-		while (next - buf + 1 < len && (next[0] != 0 || next[1] != 0))
-			next++;
-		next += 2;
-		switch (h.type) {
-			case 0:
-				di->vendor = dmi_string(&h, data[0x04]);
-				break;
-			case 1:
-				di->manufacturer = dmi_string(&h, data[0x04]);
-				di->product = dmi_string(&h, data[0x05]);
-				break;
-			default:
-				break;
-		}
-
-		data = next;
-		i++;
-	}
-	rc = 0;
-done:
-	return rc;
-}
-
 static int hypervisor_from_dmi_table(uint32_t base, uint16_t len,
 				uint16_t num, const char *devmem)
 {
diff --git a/sys-utils/lscpu.h b/sys-utils/lscpu.h
index b199de3dd..565f6aee5 100644
--- a/sys-utils/lscpu.h
+++ b/sys-utils/lscpu.h
@@ -298,6 +298,8 @@ void lscpu_decode_arm(struct lscpu_cxt *cxt);
 
 int lookup(char *line, char *pattern, char **value);
 
+void *get_mem_chunk(size_t base, size_t len, const char *devmem);
+
 struct lscpu_dmi_header
 {
 	uint8_t type;
@@ -312,28 +314,8 @@ struct dmi_info {
 	char *manufacturer;
 };
 
-static inline void to_dmi_header(struct lscpu_dmi_header *h, uint8_t *data)
-{
-	h->type = data[0];
-	h->length = data[1];
-	memcpy(&h->handle, data + 2, sizeof(h->handle));
-	h->data = data;
-}
-
-static inline char *dmi_string(const struct lscpu_dmi_header *dm, uint8_t s)
-{
-	char *bp = (char *)dm->data;
-
-	if (!s || !bp)
-		return NULL;
-
-	bp += dm->length;
-	while (s > 1 && *bp) {
-		bp += strlen(bp);
-		bp++;
-		s--;
-	}
 
-	return !*bp ? NULL : bp;
-}
+void to_dmi_header(struct lscpu_dmi_header *h, uint8_t *data);
+char *dmi_string(const struct lscpu_dmi_header *dm, uint8_t s);
+int parse_dmi_table(uint16_t len, uint16_t num, uint8_t *data, struct dmi_info *di);
 #endif /* LSCPU_H */
-- 
2.27.0


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

* [PATCH v2 4/5] lscpu: add helper to get physical sockets
  2020-11-14  4:12 [PATCH v2 0/5] lscpu: Fix socket information on aarch64 machine Masayoshi Mizuma
                   ` (2 preceding siblings ...)
  2020-11-14  4:12 ` [PATCH v2 3/5] lscpu-dmi: Move some functions related to DMI to lscpu-dmi Masayoshi Mizuma
@ 2020-11-14  4:12 ` Masayoshi Mizuma
  2020-11-14  4:12 ` [PATCH v2 5/5] lscpu: show the number of physical socket on aarch64 machine without ACPI PPTT Masayoshi Mizuma
  4 siblings, 0 replies; 8+ messages in thread
From: Masayoshi Mizuma @ 2020-11-14  4:12 UTC (permalink / raw)
  To: util-linux; +Cc: Masayoshi Mizuma, Masayoshi Mizuma

From: Masayoshi Mizuma <m.mizuma@jp.fujitsu.com>

Add a helper function, get_number_of_physical_sockets_from_dmi(),
to get physical sockets from DMI table in case of the sysfs for
cpu topology doesn't have the physical socket information.

get_number_of_physical_sockets_from_dmi() parse the DMI table
and counts the number of SMBIOS Processor Information (Type04)
structure.

Signed-off-by: Masayoshi Mizuma <m.mizuma@jp.fujitsu.com>
---
 sys-utils/lscpu-dmi.c | 29 +++++++++++++++++++++++++++++
 sys-utils/lscpu.h     |  2 ++
 2 files changed, 31 insertions(+)

diff --git a/sys-utils/lscpu-dmi.c b/sys-utils/lscpu-dmi.c
index 00d4439f8..e7ffa88d3 100644
--- a/sys-utils/lscpu-dmi.c
+++ b/sys-utils/lscpu-dmi.c
@@ -66,6 +66,9 @@ int parse_dmi_table(uint16_t len, uint16_t num,
 			di->manufacturer = dmi_string(&h, data[0x04]);
 			di->product = dmi_string(&h, data[0x05]);
 			break;
+		case 4:
+			di->sockets++;
+			break;
 		default:
 			break;
 		}
@@ -77,3 +80,29 @@ int parse_dmi_table(uint16_t len, uint16_t num,
 done:
 	return rc;
 }
+
+size_t get_number_of_physical_sockets_from_dmi(void)
+{
+	static char const sys_fw_dmi_tables[] = _PATH_SYS_DMI;
+	struct dmi_info di;
+	struct stat st;
+	uint8_t *data;
+	int rc = 0;
+
+	if (stat(sys_fw_dmi_tables, &st))
+		return rc;
+
+	data = get_mem_chunk(0, st.st_size, sys_fw_dmi_tables);
+	if (!data)
+		return rc;
+
+	memset(&di, 0, sizeof(struct dmi_info));
+	rc = parse_dmi_table(st.st_size, st.st_size/4, data, &di);
+
+	free(data);
+
+	if ((rc < 0) || !di.sockets)
+		return 0;
+	else
+		return di.sockets;
+}
diff --git a/sys-utils/lscpu.h b/sys-utils/lscpu.h
index 565f6aee5..d137b94b1 100644
--- a/sys-utils/lscpu.h
+++ b/sys-utils/lscpu.h
@@ -312,10 +312,12 @@ struct dmi_info {
 	char *vendor;
 	char *product;
 	char *manufacturer;
+	int sockets;
 };
 
 
 void to_dmi_header(struct lscpu_dmi_header *h, uint8_t *data);
 char *dmi_string(const struct lscpu_dmi_header *dm, uint8_t s);
 int parse_dmi_table(uint16_t len, uint16_t num, uint8_t *data, struct dmi_info *di);
+size_t get_number_of_physical_sockets_from_dmi(void);
 #endif /* LSCPU_H */
-- 
2.27.0


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

* [PATCH v2 5/5] lscpu: show the number of physical socket on aarch64 machine without ACPI PPTT
  2020-11-14  4:12 [PATCH v2 0/5] lscpu: Fix socket information on aarch64 machine Masayoshi Mizuma
                   ` (3 preceding siblings ...)
  2020-11-14  4:12 ` [PATCH v2 4/5] lscpu: add helper to get physical sockets Masayoshi Mizuma
@ 2020-11-14  4:12 ` Masayoshi Mizuma
  4 siblings, 0 replies; 8+ messages in thread
From: Masayoshi Mizuma @ 2020-11-14  4:12 UTC (permalink / raw)
  To: util-linux; +Cc: Masayoshi Mizuma, Masayoshi Mizuma

From: Masayoshi Mizuma <m.mizuma@jp.fujitsu.com>

Show the number of the number of physical socket even if the sysfs doesn't
have the physical socket information.

Note, lscpu shows the number of physical socket as 'Socket(s):' only if
root user runs it because accessing the DMI table requires root
privilege.

Signed-off-by: Masayoshi Mizuma <m.mizuma@jp.fujitsu.com>
---
 sys-utils/lscpu-arm.c | 2 ++
 sys-utils/lscpu.c     | 9 +++++++--
 sys-utils/lscpu.h     | 2 ++
 3 files changed, 11 insertions(+), 2 deletions(-)

diff --git a/sys-utils/lscpu-arm.c b/sys-utils/lscpu-arm.c
index 7ef05e8e7..72c2abf65 100644
--- a/sys-utils/lscpu-arm.c
+++ b/sys-utils/lscpu-arm.c
@@ -360,6 +360,8 @@ static void arm_decode(struct lscpu_cxt *cxt, struct lscpu_cputype *ct)
 
 	arm_ids_decode(ct);
 	arm_rXpY_decode(ct);
+	if (cxt->is_cluster)
+		ct->nr_socket_on_cluster = get_number_of_physical_sockets_from_dmi();
 }
 
 int lscpu_is_cluster_arm(struct lscpu_cxt *cxt)
diff --git a/sys-utils/lscpu.c b/sys-utils/lscpu.c
index c5a4cc984..0c7d86a00 100644
--- a/sys-utils/lscpu.c
+++ b/sys-utils/lscpu.c
@@ -868,10 +868,15 @@ print_summary_cputype(struct lscpu_cxt *cxt,
 		} else
 			add_summary_n(tb, sec, _("Book(s):"), ct->nbooks_per_drawer ?: ct->nbooks);
 	} else {
-		if (cxt->is_cluster)
+		if (cxt->is_cluster) {
+			if (ct->nr_socket_on_cluster > 0)
+				add_summary_n(tb, sec, _("Socket(s):"), ct->nr_socket_on_cluster);
+			else
+				add_summary_s(tb, sec, _("Socket(s):"), "-");
+
 			add_summary_n(tb, sec, _("Cluster(s):"),
 					ct->nsockets_per_book ?: ct->nsockets);
-		else
+		} else
 			add_summary_n(tb, sec, _("Socket(s):"),
 					ct->nsockets_per_book ?: ct->nsockets);
 	}
diff --git a/sys-utils/lscpu.h b/sys-utils/lscpu.h
index d137b94b1..4511c317c 100644
--- a/sys-utils/lscpu.h
+++ b/sys-utils/lscpu.h
@@ -101,6 +101,8 @@ struct lscpu_cputype {
 			has_configured : 1,
 			has_polarization : 1,
 			has_addresses : 1;
+
+	size_t nr_socket_on_cluster; /* the number of sockets if the is_cluster is 1 */
 };
 
 /* dispatching modes */
-- 
2.27.0


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

* Re: [PATCH v2 1/5] lscpu: use cluster on aarch64 machine which doesn't have ACPI PPTT
  2020-11-14  4:12 ` [PATCH v2 1/5] lscpu: use cluster on aarch64 machine which doesn't have ACPI PPTT Masayoshi Mizuma
@ 2020-11-19  8:38   ` Karel Zak
  2020-11-20  3:25     ` Masayoshi Mizuma
  0 siblings, 1 reply; 8+ messages in thread
From: Karel Zak @ 2020-11-19  8:38 UTC (permalink / raw)
  To: Masayoshi Mizuma; +Cc: util-linux, Masayoshi Mizuma

On Fri, Nov 13, 2020 at 11:12:25PM -0500, Masayoshi Mizuma wrote:
>  cpu_column_name_to_id(const char *name, size_t namesz)
>  {
>  	size_t i;
> +	int is_cluster = lscpu_is_cluster_arm(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;
> +			}

This is very unusual for your utils and it makes scripts with lscpu
non-portable. It would be better to remove this change.

We usually follow the columns as specified by user and if we can't
fill any data then we return nothing (or "-"). For example you can use
"-o DRAWER" on system where this stuff is not supported.

>  			return i;
> +		}
>  	}
>  	warnx(_("unknown column: %s"), name);
>  	return -1;
> @@ -337,6 +348,7 @@ static char *get_cell_data(
>  		fill_id(cxt, cpu, core, buf, bufsz);
>  		break;
>  	case COL_CPU_SOCKET:
> +	case COL_CPU_CLUSTER:
>  		fill_id(cxt, cpu, socket, buf, bufsz);
>  		break;

  What about:

  case COL_CPU_SOCKET:
    fill_id(cxt, cpu, socket, buf, bufsz); 
    break;
  case COL_CPU_CLUSTER:
    if (cxt->is_cluster)
        fill_id(cxt, cpu, socket, buf, bufsz);
    break;

 It means "SOCKET" works everywhere, "CLUSTER" returns data only on
 ARMs with cluster(s).

    Karel

-- 
 Karel Zak  <kzak@redhat.com>
 http://karelzak.blogspot.com


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

* Re: [PATCH v2 1/5] lscpu: use cluster on aarch64 machine which doesn't have ACPI PPTT
  2020-11-19  8:38   ` Karel Zak
@ 2020-11-20  3:25     ` Masayoshi Mizuma
  0 siblings, 0 replies; 8+ messages in thread
From: Masayoshi Mizuma @ 2020-11-20  3:25 UTC (permalink / raw)
  To: Karel Zak; +Cc: util-linux, Masayoshi Mizuma

On Thu, Nov 19, 2020 at 09:38:20AM +0100, Karel Zak wrote:
> On Fri, Nov 13, 2020 at 11:12:25PM -0500, Masayoshi Mizuma wrote:
> >  cpu_column_name_to_id(const char *name, size_t namesz)
> >  {
> >  	size_t i;
> > +	int is_cluster = lscpu_is_cluster_arm(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;
> > +			}
> 
> This is very unusual for your utils and it makes scripts with lscpu
> non-portable. It would be better to remove this change.
> 
> We usually follow the columns as specified by user and if we can't
> fill any data then we return nothing (or "-"). For example you can use
> "-o DRAWER" on system where this stuff is not supported.

Thanks, got it. I'll remove this change.

> 
> >  			return i;
> > +		}
> >  	}
> >  	warnx(_("unknown column: %s"), name);
> >  	return -1;
> > @@ -337,6 +348,7 @@ static char *get_cell_data(
> >  		fill_id(cxt, cpu, core, buf, bufsz);
> >  		break;
> >  	case COL_CPU_SOCKET:
> > +	case COL_CPU_CLUSTER:
> >  		fill_id(cxt, cpu, socket, buf, bufsz);
> >  		break;
> 
>   What about:
> 
>   case COL_CPU_SOCKET:
>     fill_id(cxt, cpu, socket, buf, bufsz); 
>     break;
>   case COL_CPU_CLUSTER:
>     if (cxt->is_cluster)
>         fill_id(cxt, cpu, socket, buf, bufsz);
>     break;
> 
>  It means "SOCKET" works everywhere, "CLUSTER" returns data only on
>  ARMs with cluster(s).

Great idea! I'll fix it as that.

Thanks!
Masa

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

end of thread, other threads:[~2020-11-20  3:25 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-11-14  4:12 [PATCH v2 0/5] lscpu: Fix socket information on aarch64 machine Masayoshi Mizuma
2020-11-14  4:12 ` [PATCH v2 1/5] lscpu: use cluster on aarch64 machine which doesn't have ACPI PPTT Masayoshi Mizuma
2020-11-19  8:38   ` Karel Zak
2020-11-20  3:25     ` Masayoshi Mizuma
2020-11-14  4:12 ` [PATCH v2 2/5] lscpu-virt: split hypervisor_from_dmi_table() Masayoshi Mizuma
2020-11-14  4:12 ` [PATCH v2 3/5] lscpu-dmi: Move some functions related to DMI to lscpu-dmi Masayoshi Mizuma
2020-11-14  4:12 ` [PATCH v2 4/5] lscpu: add helper to get physical sockets Masayoshi Mizuma
2020-11-14  4:12 ` [PATCH v2 5/5] lscpu: show the number of physical socket on aarch64 machine without ACPI PPTT Masayoshi Mizuma

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.