The ISA information for RISC-V is important for understanding the different extensions supported by the CPU. Print the ISA information in the summary, with the Base ISA and single-letter extensions at the beginning, followed by multi-letter extensions sorted in alphabetical order. The information is the same as the cpuinfo information, except that underscores are replaced by spaces and multi-letter extensions are simply sorted instead of following any ISA string ordering rule. The sample output below shows the difference between cpuinfo and lscpu. cpuinfo output: isa : rv64imafdch_zicbom_zicboz_zicntr_zicsr_zifencei_zihintntl_zihintpause_zihpm_zawrs_zfa_zba_zbb_zbc_zbs_smaia_ssaia_sstc lscpu output: ISA: rv64imafdch smaia ssaia sstc zawrs zba zbb zbc zbs zfa zicbom zicboz zicntr zicsr zifencei zihintntl zihintpause zihpm Signed-off-by: Sunil V L <sunilvl@xxxxxxxxxxxxxxxx> --- Changes in v2: 1) Format the ISA string instead of simply printing the same from cpuinfo. (Feedback from Andrew Jones). --- sys-utils/Makemodule.am | 1 + sys-utils/lscpu-cputype.c | 1 + sys-utils/lscpu-riscv.c | 57 +++++++++++++++++++++++++++++++++++++++ sys-utils/lscpu.c | 5 ++++ sys-utils/lscpu.h | 2 ++ sys-utils/meson.build | 1 + 6 files changed, 67 insertions(+) create mode 100644 sys-utils/lscpu-riscv.c diff --git a/sys-utils/Makemodule.am b/sys-utils/Makemodule.am index 922cce5c5..1055312db 100644 --- a/sys-utils/Makemodule.am +++ b/sys-utils/Makemodule.am @@ -461,6 +461,7 @@ lscpu_SOURCES = sys-utils/lscpu.c \ sys-utils/lscpu-virt.c \ sys-utils/lscpu-arm.c \ sys-utils/lscpu-dmi.c \ + sys-utils/lscpu-riscv.c \ sys-utils/lscpu.h lscpu_LDADD = $(LDADD) libcommon.la libsmartcols.la $(RTAS_LIBS) lscpu_CFLAGS = $(AM_CFLAGS) -I$(ul_libsmartcols_incdir) diff --git a/sys-utils/lscpu-cputype.c b/sys-utils/lscpu-cputype.c index 739dd99c5..bdb33ac78 100644 --- a/sys-utils/lscpu-cputype.c +++ b/sys-utils/lscpu-cputype.c @@ -233,6 +233,7 @@ static const struct cpuinfo_pattern type_patterns[] = DEF_PAT_CPUTYPE( "family", PAT_FAMILY, family), DEF_PAT_CPUTYPE( "features", PAT_FEATURES, flags), /* s390 */ DEF_PAT_CPUTYPE( "flags", PAT_FLAGS, flags), /* x86 */ + DEF_PAT_CPUTYPE( "isa", PAT_ISA, isa), /* riscv */ DEF_PAT_CPUTYPE( "marchid", PAT_FAMILY, family), /* riscv */ DEF_PAT_CPUTYPE( "max thread id", PAT_MAX_THREAD_ID, mtid), /* s390 */ DEF_PAT_CPUTYPE( "mimpid", PAT_MODEL, model), /* riscv */ diff --git a/sys-utils/lscpu-riscv.c b/sys-utils/lscpu-riscv.c new file mode 100644 index 000000000..62f1ad7ab --- /dev/null +++ b/sys-utils/lscpu-riscv.c @@ -0,0 +1,57 @@ +/* + * SPDX-License-Identifier: GPL-2.0-or-later + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Copyright (C) 2025 Ventana Micro Systems Inc. + * + */ +#include "lscpu.h" +#include "strutils.h" +#include "strv.h" + +static int riscv_cmp_func(const void *a, const void *b) +{ + return strcmp(*(const char **)a, *(const char **)b); +} + +bool is_riscv(struct lscpu_cputype *ct) +{ + const char *base_isa[] = {"rv32", "rv64", "rv128"}; + size_t i; + + for (i = 0; i < ARRAY_SIZE(base_isa); i++) { + if (!strncasecmp(ct->isa, base_isa[i], strlen(base_isa[i]))) + return true; + } + + return false; +} + +/* + * Reformat the isa string, but the length stays the same. + */ +void lscpu_format_isa_riscv(struct lscpu_cputype *ct) +{ + char **split; + size_t i; + + split = strv_split(ct->isa, "_"); + + /* Sort multi-letter extensions alphabetically */ + if (strv_length(split) > 1) + qsort(&split[1], strv_length(split) - 1, sizeof(char *), riscv_cmp_func); + + /* Keep Base ISA and single-letter extensions at the start */ + strcpy(ct->isa, split[0]); + + for (i = 1; i < strv_length(split); i++) { + strcat(ct->isa, " "); + strcat(ct->isa, split[i]); + } + + strv_free(split); +} diff --git a/sys-utils/lscpu.c b/sys-utils/lscpu.c index ffec37206..7b2f28e5e 100644 --- a/sys-utils/lscpu.c +++ b/sys-utils/lscpu.c @@ -954,6 +954,11 @@ print_summary_cputype(struct lscpu_cxt *cxt, if (ct->flags) add_summary_s(tb, sec, _("Flags:"), ct->flags); + + if (ct->isa && is_riscv(ct)) { + lscpu_format_isa_riscv(ct); + add_summary_s(tb, sec, _("ISA:"), ct->isa); + } } /* diff --git a/sys-utils/lscpu.h b/sys-utils/lscpu.h index 459fea84d..bd7b64cc5 100644 --- a/sys-utils/lscpu.h +++ b/sys-utils/lscpu.h @@ -278,6 +278,7 @@ struct lscpu_cxt { CPU_ISSET_S((_cpu)->logical_id, (_cxt)->setsize, (_cxt)->present)) int is_arm(struct lscpu_cxt *cxt); +bool is_riscv(struct lscpu_cputype *ct); struct lscpu_cputype *lscpu_new_cputype(void); void lscpu_ref_cputype(struct lscpu_cputype *ct); @@ -320,6 +321,7 @@ int lscpu_create_cpus(struct lscpu_cxt *cxt, cpu_set_t *cpuset, size_t setsize); struct lscpu_cpu *lscpu_cpus_loopup_by_type(struct lscpu_cxt *cxt, struct lscpu_cputype *ct); void lscpu_decode_arm(struct lscpu_cxt *cxt); +void lscpu_format_isa_riscv(struct lscpu_cputype *ct); int lookup(char *line, char *pattern, char **value); diff --git a/sys-utils/meson.build b/sys-utils/meson.build index 2fdcc6393..d9817f922 100644 --- a/sys-utils/meson.build +++ b/sys-utils/meson.build @@ -184,6 +184,7 @@ lscpu_sources = files( 'lscpu-virt.c', 'lscpu-arm.c', 'lscpu-dmi.c', + 'lscpu-riscv.c', ) lscpu_manadocs = files('lscpu.1.adoc') -- 2.43.0