]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
lscpu: Implement options for dumping ARM implementer/model name tables
authorMartin Storsjö <martin@martin.st>
Thu, 22 Jan 2026 22:56:56 +0000 (00:56 +0200)
committerMartin Storsjö <martin@martin.st>
Tue, 27 Jan 2026 10:28:37 +0000 (12:28 +0200)
This allows extracting the contents of the tables, which itself
is uncopyrightable, for use in other projects with different
code licenses.

bash-completion/lscpu
sys-utils/lscpu-arm.c
sys-utils/lscpu.1.adoc
sys-utils/lscpu.c
sys-utils/lscpu.h

index eb07cf9f20c484d10da26ab6d6bf94db99d4dd80..8d54df1889d60c037972474bd973fb9543412b60 100644 (file)
@@ -30,6 +30,8 @@ _lscpu_module()
                -*)
                        OPTS_ALL="--all
                                --annotate
+                               --arm-id
+                               --arm-model
                                --online
                                --bytes
                                --caches
index 591e12064702aeb6a424888d0cc3db8934f79993..ed255a3c791a14b14eec07d6fa6e4c733b498a73 100644 (file)
@@ -16,6 +16,7 @@
  *  - SMBIOS tables (if applicable)
  */
 #include "lscpu.h"
+#include <libsmartcols.h>
 
 struct id_part {
     const int id;
@@ -492,3 +493,107 @@ void lscpu_decode_arm(struct lscpu_cxt *cxt)
        for (i = 0; i < cxt->ncputypes; i++)
                arm_decode(cxt, cxt->cputypes[i]);
 }
+
+static struct libscols_table *arm_mktable(struct lscpu_cxt *cxt, const char *tabname)
+{
+       struct libscols_table *tb;
+
+       scols_init_debug(0);
+
+       tb = scols_new_table();
+       if (!tb)
+                err(EXIT_FAILURE, _("failed to allocate output table"));
+       if (cxt->json) {
+               scols_table_enable_json(tb, 1);
+               scols_table_set_name(tb, tabname);
+       }
+       if (cxt->raw)
+               scols_table_enable_raw(tb, 1);
+
+       scols_table_new_column(tb, _("id"), 0, 0);
+       scols_table_new_column(tb, _("name"), 0, 0);
+
+       return tb;
+}
+
+/*
+ * [--arm-id] backend
+ */
+void lscpu_print_arm_implementers(struct lscpu_cxt *cxt)
+{
+       size_t i;
+       struct libscols_table *tb;
+
+       tb = arm_mktable(cxt, "arm-implementers");
+
+       for (i = 0; hw_implementer[i].id != -1; i++) {
+               struct libscols_line *ln;
+               ln = scols_table_new_line(tb, NULL);
+               if (!ln)
+                       err(EXIT_FAILURE, _("failed to allocate output line"));
+               scols_line_sprintf(ln, 0, "0x%02x", hw_implementer[i].id);
+               scols_line_set_data(ln, 1, hw_implementer[i].name);
+       }
+
+       scols_print_table(tb);
+       scols_unref_table(tb);
+}
+
+/*
+ * [--arm-id=<impl>] backend
+ */
+void lscpu_print_arm_models(struct lscpu_cxt *cxt, int implementer)
+{
+       size_t i;
+       struct libscols_table *tb;
+       const struct id_part *parts = NULL;
+
+       for (i = 0; hw_implementer[i].id != -1; i++) {
+               if (hw_implementer[i].id == implementer) {
+                       parts = hw_implementer[i].parts;
+                       break;
+               }
+       }
+       if (!parts)
+               errx(EXIT_FAILURE, _("implementer not found"));
+
+       tb = arm_mktable(cxt, "arm-models");
+
+       for (i = 0; parts[i].id != -1; i++) {
+               struct libscols_line *ln;
+               ln = scols_table_new_line(tb, NULL);
+               if (!ln)
+                       err(EXIT_FAILURE, _("failed to allocate output line"));
+               scols_line_sprintf(ln, 0, "0x%03x", parts[i].id);
+               scols_line_set_data(ln, 1, parts[i].name);
+       }
+
+       scols_print_table(tb);
+       scols_unref_table(tb);
+}
+
+/*
+ * [--arm-id=<impl> --arm-model=<model>] backend
+ */
+void lscpu_print_arm_model(struct lscpu_cxt *cxt __attribute__((__unused__)), int implementer, int model)
+{
+       size_t i;
+       const struct id_part *parts = NULL;
+
+       for (i = 0; hw_implementer[i].id != -1; i++) {
+               if (hw_implementer[i].id == implementer) {
+                       parts = hw_implementer[i].parts;
+                       break;
+               }
+       }
+       if (!parts)
+               errx(EXIT_FAILURE, _("implementer not found"));
+
+       for (i = 0; parts[i].id != -1; i++) {
+               if (parts[i].id == model) {
+                       printf("%s\n", parts[i].name);
+                       return;
+               }
+       }
+       errx(EXIT_FAILURE, _("model not found"));
+}
index bf95ce464d8242c87cdfa16246726eae2c896af1..0636ef87c68106512ba990cb8fc3548c586d4c37 100644 (file)
@@ -108,6 +108,16 @@ Display physical IDs for all columns with topology elements (core, socket, etc.)
 +
 The CPU logical numbers are not affected by this option.
 
+*--arm-id*[**=**_list_]::
+Print a list of the known ARM core implementers and their human readable names.
++
+If an argument is given, print a list of the individual core IDs and their
+names, for the given implementer.
+
+*--arm-model* _id_::
+Print the name for this specific core model. This requires passing
+*--arm-id=_id_* to indicate the implementer id as well.
+
 include::man-common/annotate.adoc[]
 
 == ENVIRONMENT
index c0ac61bbfefaacc5884493ce6926534500b89bee..4556aa6df4168b838ee08415fa894ba58a5e581b 100644 (file)
@@ -1216,6 +1216,8 @@ static void __attribute__((__noreturn__)) usage(void)
        fputs(_(" -y, --physical          print physical instead of logical IDs\n"), out);
        fputs(_("     --hierarchic[=when] use subsections in summary (auto, never, always)\n"), out);
        fputs(_("     --output-all        print all available columns for -e, -p or -C\n"), out);
+       fputs(_("     --arm-id[=<id>]     print the known ARM implementers and their names. If an id is given, print all the cores for that implementer.\n"), out);
+       fputs(_("     --arm-model <id>    print the name of the given ARM implementer and model. Requires --arm-id=<id>.\n"), out);
        fputs(USAGE_SEPARATOR, out);
        fprintf(out, USAGE_LIST_COLUMNS_OPTION(25));
        fprintf(out, USAGE_HELP_OPTIONS(25));
@@ -1258,11 +1260,15 @@ int main(int argc, char *argv[])
        char *outarg = NULL;
        size_t i, ncolumns = 0;
        char *annotate_opt_arg = NULL;
+       unsigned int arm_id = 0xf00; /* Valid values are 0-0xff */
+       unsigned int arm_model = 0xf000; /* Valid values are 0-0xfff */
 
        enum {
                OPT_OUTPUT_ALL = CHAR_MAX + 1,
                OPT_HIERARCHIC,
                OPT_ANNOTATE,
+               OPT_ARM_ID,
+               OPT_ARM_MODEL,
        };
        static const struct option longopts[] = {
                { "all",        no_argument,       NULL, 'a' },
@@ -1283,6 +1289,8 @@ int main(int argc, char *argv[])
                { "output-all", no_argument,       NULL, OPT_OUTPUT_ALL },
                { "hierarchic", optional_argument, NULL, OPT_HIERARCHIC },
                { "list-columns", no_argument,     NULL, 'H' },
+               { "arm-id",     optional_argument, NULL, OPT_ARM_ID },
+               { "arm-model",  required_argument, NULL, OPT_ARM_MODEL },
                { NULL,         0, NULL, 0 }
        };
 
@@ -1372,6 +1380,18 @@ int main(int argc, char *argv[])
                        } else
                                hierarchic = 1;
                        break;
+               case OPT_ARM_ID:
+                       if (optarg) {
+                               if (cxt->mode != LSCPU_OUTPUT_ARM_SINGLE_MODEL)
+                                       cxt->mode = LSCPU_OUTPUT_ARM_MODELS;
+                               arm_id = str2unum_or_err(optarg, 0, _("failed to parse implementer id"), 0xFF);
+                       } else
+                               cxt->mode = LSCPU_OUTPUT_ARM_IMPLEMENTERS;
+                       break;
+               case OPT_ARM_MODEL:
+                       cxt->mode = LSCPU_OUTPUT_ARM_SINGLE_MODEL;
+                       arm_model = str2unum_or_err(optarg, 0, _("failed to parse model id"), 0xFFF);
+                       break;
                case 'H':
                        collist = 1;
                        break;
@@ -1407,6 +1427,9 @@ int main(int argc, char *argv[])
                return EXIT_FAILURE;
        }
 
+       if (cxt->mode == LSCPU_OUTPUT_ARM_SINGLE_MODEL && arm_id > 0xff)
+               errx(EXIT_FAILURE, _("--arm-model option needs to be used with --arm-id"));
+
        if (argc != optind) {
                warnx(_("bad usage"));
                errtryhelp(EXIT_FAILURE);
@@ -1532,6 +1555,15 @@ int main(int argc, char *argv[])
 
                print_cpus_parsable(cxt, columns, ncolumns);
                break;
+       case LSCPU_OUTPUT_ARM_IMPLEMENTERS:
+               lscpu_print_arm_implementers(cxt);
+               break;
+       case LSCPU_OUTPUT_ARM_MODELS:
+               lscpu_print_arm_models(cxt, arm_id);
+               break;
+       case LSCPU_OUTPUT_ARM_SINGLE_MODEL:
+               lscpu_print_arm_model(cxt, arm_id, arm_model);
+               break;
        }
 
        lscpu_free_context(cxt);
index 713ef04b135b5c8957f375c411fdc2c9150457ea..0fae5d29ec6b2f1036ded7424ae6de509320457b 100644 (file)
@@ -212,7 +212,10 @@ enum {
        LSCPU_OUTPUT_SUMMARY = 0,       /* default */
        LSCPU_OUTPUT_CACHES,
        LSCPU_OUTPUT_PARSABLE,
-       LSCPU_OUTPUT_READABLE
+       LSCPU_OUTPUT_READABLE,
+       LSCPU_OUTPUT_ARM_IMPLEMENTERS,
+       LSCPU_OUTPUT_ARM_MODELS,
+       LSCPU_OUTPUT_ARM_SINGLE_MODEL,
 };
 
 struct lscpu_cxt {
@@ -324,6 +327,9 @@ struct lscpu_cpu *lscpu_cpus_loopup_by_type(struct lscpu_cxt *cxt, struct lscpu_
 
 void lscpu_decode_arm(struct lscpu_cxt *cxt);
 void lscpu_format_isa_riscv(struct lscpu_cputype *ct);
+void lscpu_print_arm_implementers(struct lscpu_cxt *cxt);
+void lscpu_print_arm_models(struct lscpu_cxt *cxt, int implementer);
+void lscpu_print_arm_model(struct lscpu_cxt *cxt, int implementer, int model);
 
 int lookup(char *line, char *pattern, char **value);