]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
lscpu: use maximum CPU speed from DMI, avoid duplicate version string
authorKarel Zak <kzak@redhat.com>
Thu, 21 Aug 2025 09:35:17 +0000 (11:35 +0200)
committerKarel Zak <kzak@redhat.com>
Thu, 21 Aug 2025 09:43:29 +0000 (11:43 +0200)
* Read maximum CPU speed from DMI
* Don't use max speed if nonsensical
* Avoid appending "CPU @ speed" to the version string if it's already included.
  (This is a code robustness improvement as DMI is currently read for ARMs only,
   and the issue was detected on Intel.)

Fixes: https://github.com/util-linux/util-linux/commit/a772d7c493afcec32f0123fc947013f74db6e45d
Signed-off-by: Karel Zak <kzak@redhat.com>
sys-utils/lscpu-dmi.c
sys-utils/lscpu.h

index 2171f762316d67977dfdbf726f743aacf136c030..a04cbb5677910144081d50f6d10e3837a1424ac4 100644 (file)
@@ -76,6 +76,7 @@ int parse_dmi_table(uint16_t len, uint16_t num,
                                di->processor_manufacturer = dmi_string(&h, data[0x7]);
                                di->processor_version = dmi_string(&h, data[0x10]);
                                di->current_speed = *((uint16_t *)(&data[0x16]));
+                               di->max_speed = *((uint16_t *)(&data[0x14]));
                                di->part_num = dmi_string(&h, data[0x22]);
 
                                if (data[0x6] == 0xfe)
@@ -122,10 +123,22 @@ int dmi_decode_cputype(struct lscpu_cputype *ct)
        if (di.processor_manufacturer)
                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);
+       /* The CPU version string may include the maximum speed (e.g., on Intel); in
+        * this case, use the version string as the complete model name. */
+       if (di.processor_version && strstr(di.processor_version, " CPU @ "))
+               ct->bios_modelname = xstrdup(di.processor_version);
+       else {
+               /* DMI may provide incorrect data (max_speed < current_speed) */
+               uint16_t speed = max(di.current_speed, di.max_speed);
+
+               snprintf(buf, sizeof(buf), "%s %s CPU @ %d.%dGHz",
+                       (di.processor_version ?: ""),
+                       (di.part_num ?: ""),
+                       speed/1000,
+                       (speed % 1000) / 100);
+
+               ct->bios_modelname = xstrdup(buf);
+       }
 
        /* Get CPU family */
        memset(buf, 0, sizeof(buf));
index bd7b64cc57c7d247d9a09414ccf6579680b568f4..e132d63c65069ef63842ed6109ec89556bd83b74 100644 (file)
@@ -346,6 +346,7 @@ struct dmi_info {
        char *processor_manufacturer;
        char *processor_version;
        uint16_t current_speed;
+       uint16_t max_speed;
        char *part_num;
 };