]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
lscpu: get the processor information by DMI
authorHuang Shijie <shijie@os.amperecomputing.com>
Tue, 15 Jun 2021 10:06:38 +0000 (10:06 +0000)
committerKarel Zak <kzak@redhat.com>
Wed, 16 Jun 2021 09:09:19 +0000 (11:09 +0200)
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 <shijie@os.amperecomputing.com>
Signed-off-by: Karel Zak <kzak@redhat.com>
sys-utils/lscpu-arm.c
sys-utils/lscpu-dmi.c
sys-utils/lscpu.h

index 230eb5fddf69fed91a52c81332a55ab0ddc47598..885aadc367e305f9ef350f8980662e1c1fd7b594 100644 (file)
@@ -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);
index e7ffa88d3abb20d89a6c3aa4c926f11ac09067c6..177b787ebbd541e43370e14e92e56e644256d2e0 100644 (file)
@@ -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;
index 62f5325810265d7977dded70b6d09e2061aa6c07..4dc8e0a239658a716ae9961b4f276239d654e6a5 100644 (file)
@@ -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 */