From a772d7c493afcec32f0123fc947013f74db6e45d Mon Sep 17 00:00:00 2001 From: Huang Shijie Date: Tue, 15 Jun 2021 10:06:38 +0000 Subject: [PATCH] lscpu: get the processor information by DMI 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: 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 use 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 BIOS Vendor ID: Ampere(R) Model name: Neoverse-N1 BIOS Model name: Ampere(R) Altra(R) Processor Q00-00 CPU @ 3.0GHz Model: 1 Thread(s) per core: 1 Core(s) per socket: 80 Socket(s): 2 ........................................ --------------------------------------------- [kzak@redhat.com: - s/sprintf/snprintf/] Signed-off-by: Huang Shijie Signed-off-by: Karel Zak --- sys-utils/lscpu-arm.c | 2 ++ sys-utils/lscpu-dmi.c | 40 ++++++++++++++++++++++++++++++++++++++++ sys-utils/lscpu.h | 7 +++++++ 3 files changed, 49 insertions(+) diff --git a/sys-utils/lscpu-arm.c b/sys-utils/lscpu-arm.c index 230eb5fdd..885aadc36 100644 --- a/sys-utils/lscpu-arm.c +++ b/sys-utils/lscpu-arm.c @@ -361,6 +361,8 @@ static void arm_decode(struct lscpu_cxt *cxt, struct lscpu_cputype *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); diff --git a/sys-utils/lscpu-dmi.c b/sys-utils/lscpu-dmi.c index e7ffa88d3..177b787eb 100644 --- a/sys-utils/lscpu-dmi.c +++ b/sys-utils/lscpu-dmi.c @@ -67,6 +67,13 @@ 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_manufacturer = dmi_string(&h, data[0x7]); + di->processor_version = dmi_string(&h, data[0x10]); + di->current_speed = *((uint16_t *)(&data[0x16])); + di->part_num = dmi_string(&h, data[0x22]); + } di->sockets++; break; default: @@ -81,6 +88,39 @@ 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; + } + + ct->bios_vendor = xstrdup(di.processor_manufacturer); + + snprintf(buf, sizeof(buf), + "%s %s CPU @ %d.%dGHz", di.processor_version, di.part_num, + di.current_speed/1000, (di.current_speed % 1000) / 100); + ct->bios_modelname = 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..4dc8e0a23 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 */ + char *processor_manufacturer; + 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 */