[PATCH] lscpu: get the processor information by DMI

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

 



The patch :367c85c47286 ("lscpu: use SMBIOS tables on ARM for lscpu")
relies on the existence of "/sys/firmware/dmi/entries/4-0/raw",
which may not exist in standard linux kernel.

But "/sys/firmware/dmi/tables/DMI" should exist and can provide the required
processor information.

This patch uses "/sys/firmware/dmi/tables/DMI"
to get the processor information:
  1.) Use the DMI to provide more accurate "Model name" information.
  2.) Add "CPU family" (keep the same output as dmidecode ).

Before this patch, in Ampere Altra platform, the lscpu output is:
   ---------------------------------------------
	Architecture:                    aarch64
	CPU op-mode(s):                  32-bit, 64-bit
	Byte Order:                      Little Endian
	CPU(s):                          160
	On-line CPU(s) list:             0-159
	Vendor ID:                       ARM
	Model name:                      Neoverse-N1
	Model:                           1
	Thread(s) per core:              1
	Core(s) per socket:              80
	Socket(s):                       2
    ........................................
   ---------------------------------------------

After this patch, we can get the lscpu output
in Ampere Altra platform:
   ---------------------------------------------
	Architecture:                    aarch64
	CPU op-mode(s):                  32-bit, 64-bit
	Byte Order:                      Little Endian
	CPU(s):                          160
	On-line CPU(s) list:             0-159
	Vendor ID:                       ARM
	Model name:                      Ampere(R) Altra(R) Processor Q00-00 CPU @ 3.0GHz
	CPU family:                      257
	Model:                           1
	Thread(s) per core:              1
	Core(s) per socket:              80
	Socket(s):                       2
    ........................................
   ---------------------------------------------

Signed-off-by: Huang Shijie <shijie@xxxxxxxxxxxxxxxxxxxxxx>
---
 sys-utils/lscpu-arm.c |  6 +++++-
 sys-utils/lscpu-dmi.c | 49 +++++++++++++++++++++++++++++++++++++++++++
 sys-utils/lscpu.h     |  7 +++++++
 3 files changed, 61 insertions(+), 1 deletion(-)

diff --git a/sys-utils/lscpu-arm.c b/sys-utils/lscpu-arm.c
index 230eb5fdd..0993ea5ad 100644
--- a/sys-utils/lscpu-arm.c
+++ b/sys-utils/lscpu-arm.c
@@ -358,11 +358,15 @@ static int arm_smbios_decode(struct lscpu_cputype *ct)
 
 static void arm_decode(struct lscpu_cxt *cxt, struct lscpu_cputype *ct)
 {
+	/* dmi_decode_cputype may get more accurate information later */
+	arm_ids_decode(ct);
+
 	/* use SMBIOS Type 4 data if available */
 	if (!cxt->noalive && access(_PATH_SYS_DMI_TYPE4, R_OK) == 0)
 		arm_smbios_decode(ct);
+	else if (!cxt->noalive && access(_PATH_SYS_DMI, R_OK) == 0)
+		dmi_decode_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();
diff --git a/sys-utils/lscpu-dmi.c b/sys-utils/lscpu-dmi.c
index e7ffa88d3..155b21e32 100644
--- a/sys-utils/lscpu-dmi.c
+++ b/sys-utils/lscpu-dmi.c
@@ -67,6 +67,17 @@ int parse_dmi_table(uint16_t len, uint16_t num,
 			di->product = dmi_string(&h, data[0x05]);
 			break;
 		case 4:
+			/* Get the first processor information */
+			if (di->sockets == 0) {
+				di->processor_version = dmi_string(&h, data[0x10]);
+				di->current_speed = *((uint16_t *)(&data[0x16]));
+				di->part_num = dmi_string(&h, data[0x22]);
+
+				if (data[0x6] == 0xfe)
+					di->processor_family = *((uint16_t *)(&data[0x28]));
+				else
+					di->processor_family = data[0x6];
+			}
 			di->sockets++;
 			break;
 		default:
@@ -81,6 +92,44 @@ done:
 	return rc;
 }
 
+int dmi_decode_cputype(struct lscpu_cputype *ct)
+{
+	static char const sys_fw_dmi_tables[] = _PATH_SYS_DMI;
+	struct dmi_info di = { };
+	struct stat st;
+	uint8_t *data;
+	int rc = 0;
+	char buf[100] = { };
+
+	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;
+
+	rc = parse_dmi_table(st.st_size, st.st_size/4, data, &di);
+	if (rc < 0) {
+		free(data);
+		return rc;
+	}
+
+	/* Get module name */
+	sprintf(buf, "%s %s CPU @ %d.%dGHz", di.processor_version, di.part_num,
+			di.current_speed/1000, (di.current_speed % 1000) / 100);
+	free(ct->modelname);
+	ct->modelname = xstrdup(buf);
+
+	/* Get CPU family */
+	memset(buf, 0, sizeof(buf));
+	sprintf(buf, "%d", di.processor_family);
+	free(ct->family);
+	ct->family = xstrdup(buf);
+
+	free(data);
+	return 0;
+}
+
 size_t get_number_of_physical_sockets_from_dmi(void)
 {
 	static char const sys_fw_dmi_tables[] = _PATH_SYS_DMI;
diff --git a/sys-utils/lscpu.h b/sys-utils/lscpu.h
index 62f532581..9e6362bf4 100644
--- a/sys-utils/lscpu.h
+++ b/sys-utils/lscpu.h
@@ -316,6 +316,12 @@ struct dmi_info {
 	char *product;
 	char *manufacturer;
 	int sockets;
+
+	/* Processor Information */
+	uint16_t processor_family;
+	char *processor_version;
+	uint16_t current_speed;
+	char *part_num;
 };
 
 
@@ -323,4 +329,5 @@ 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);
+int dmi_decode_cputype(struct lscpu_cputype *);
 #endif /* LSCPU_H */
-- 
2.30.2




[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