2023-04-24 19:50:47

by Heiko Stuebner

[permalink] [raw]
Subject: [PATCH 1/4] RISC-V: create ISA string separately - not as part of cpuinfo

From: Heiko Stuebner <[email protected]>

The isa string is a very central part of the RISC-V architecture, so will
be needed in other places as well.

So in a first step decouple the generation of the runtime isa-string from
/proc/cpuinfo - its current only user.

The resulting string should not differ from the previously generated one.

Signed-off-by: Heiko Stuebner <[email protected]>
---
arch/riscv/kernel/cpu.c | 70 ++++++++++++++++++++++++++++++++++++-----
1 file changed, 62 insertions(+), 8 deletions(-)

diff --git a/arch/riscv/kernel/cpu.c b/arch/riscv/kernel/cpu.c
index 3df38052dcbd..ebc478f0a16c 100644
--- a/arch/riscv/kernel/cpu.c
+++ b/arch/riscv/kernel/cpu.c
@@ -193,10 +193,33 @@ static struct riscv_isa_ext_data isa_ext_arr[] = {
__RISCV_ISA_EXT_DATA("", RISCV_ISA_EXT_MAX),
};

-static void print_isa_ext(struct seq_file *f)
+static int strlen_isa_ext(void)
{
struct riscv_isa_ext_data *edata;
- int i = 0, arr_sz;
+ int ext_len = 0, i, arr_sz;
+
+ arr_sz = ARRAY_SIZE(isa_ext_arr) - 1;
+
+ /* No extension support available */
+ if (arr_sz <= 0)
+ return 0;
+
+ for (i = 0; i <= arr_sz; i++) {
+ edata = &isa_ext_arr[i];
+ if (!__riscv_isa_extension_available(NULL, edata->isa_ext_id))
+ continue;
+
+ /* string length + underscore */
+ ext_len += strlen(edata->uprop) + 1;
+ }
+
+ return ext_len;
+}
+
+static void strcat_isa_ext(char *isa_str)
+{
+ struct riscv_isa_ext_data *edata;
+ int i, arr_sz;

arr_sz = ARRAY_SIZE(isa_ext_arr) - 1;

@@ -208,7 +231,8 @@ static void print_isa_ext(struct seq_file *f)
edata = &isa_ext_arr[i];
if (!__riscv_isa_extension_available(NULL, edata->isa_ext_id))
continue;
- seq_printf(f, "_%s", edata->uprop);
+ strcat(isa_str, "_");
+ strcat(isa_str, edata->uprop);
}
}

@@ -220,19 +244,49 @@ static void print_isa_ext(struct seq_file *f)
*/
static const char base_riscv_exts[13] = "imafdqcbkjpvh";

-static void print_isa(struct seq_file *f, const char *isa)
+static char *riscv_create_isa_string(const char *isa)
{
+ int maxlen = 4;
+ char *isa_str;
int i;

- seq_puts(f, "isa\t\t: ");
+ /* calculate the needed string length */
+ for (i = 0; i < sizeof(base_riscv_exts); i++)
+ if (__riscv_isa_extension_available(NULL, base_riscv_exts[i] - 'a'))
+ maxlen++;
+ maxlen += strlen_isa_ext();
+
+ isa_str = kzalloc(maxlen, GFP_KERNEL);
+ if (!isa_str)
+ return ERR_PTR(-ENOMEM);
+
/* Print the rv[64/32] part */
- seq_write(f, isa, 4);
+ strncat(isa_str, isa, 4);
+
for (i = 0; i < sizeof(base_riscv_exts); i++) {
if (__riscv_isa_extension_available(NULL, base_riscv_exts[i] - 'a'))
/* Print only enabled the base ISA extensions */
- seq_write(f, &base_riscv_exts[i], 1);
+ strncat(isa_str, &base_riscv_exts[i], 1);
+ }
+
+ strcat_isa_ext(isa_str);
+
+ return isa_str;
+}
+
+static void print_isa(struct seq_file *f, const char *isa)
+{
+ char *isa_str;
+
+ seq_puts(f, "isa\t\t: ");
+
+ isa_str = riscv_create_isa_string(isa);
+ if (!IS_ERR(isa_str)) {
+ seq_write(f, isa_str, strlen(isa_str));
+ kfree(isa_str);
+ } else {
+ seq_puts(f, "unknown");
}
- print_isa_ext(f);
seq_puts(f, "\n");
}

--
2.39.0


2023-04-24 23:11:19

by kernel test robot

[permalink] [raw]
Subject: Re: [PATCH 1/4] RISC-V: create ISA string separately - not as part of cpuinfo

Hi Heiko,

kernel test robot noticed the following build warnings:

[auto build test WARNING on next-20230424]
[also build test WARNING on v6.3]
[cannot apply to soc/for-next linus/master kees/for-next/execve v6.3 v6.3-rc7 v6.3-rc6]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url: https://github.com/intel-lab-lkp/linux/commits/Heiko-Stuebner/RISC-V-create-ISA-string-separately-not-as-part-of-cpuinfo/20230425-035214
base: next-20230424
patch link: https://lore.kernel.org/r/20230424194911.264850-2-heiko.stuebner%40vrull.eu
patch subject: [PATCH 1/4] RISC-V: create ISA string separately - not as part of cpuinfo
config: riscv-allyesconfig (https://download.01.org/0day-ci/archive/20230425/[email protected]/config)
compiler: riscv64-linux-gcc (GCC) 12.1.0
reproduce (this is a W=1 build):
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# https://github.com/intel-lab-lkp/linux/commit/8f1a5a16616d673f2c82cdc54ff845fd8b125a21
git remote add linux-review https://github.com/intel-lab-lkp/linux
git fetch --no-tags linux-review Heiko-Stuebner/RISC-V-create-ISA-string-separately-not-as-part-of-cpuinfo/20230425-035214
git checkout 8f1a5a16616d673f2c82cdc54ff845fd8b125a21
# save the config file
mkdir build_dir && cp config build_dir/.config
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-12.1.0 make.cross W=1 O=build_dir ARCH=riscv olddefconfig
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-12.1.0 make.cross W=1 O=build_dir ARCH=riscv SHELL=/bin/bash arch/riscv/kernel/

If you fix the issue, kindly add following tag where applicable
| Reported-by: kernel test robot <[email protected]>
| Link: https://lore.kernel.org/oe-kbuild-all/[email protected]/

All warnings (new ones prefixed by >>):

In file included from include/linux/string.h:254,
from include/linux/bitmap.h:11,
from include/linux/cpumask.h:12,
from include/linux/smp.h:13,
from include/linux/lockdep.h:14,
from include/linux/rcupdate.h:29,
from include/linux/rculist.h:11,
from include/linux/pid.h:5,
from include/linux/sched.h:14,
from include/linux/ratelimit.h:6,
from include/linux/dev_printk.h:16,
from include/linux/device.h:15,
from include/linux/node.h:18,
from include/linux/cpu.h:17,
from arch/riscv/kernel/cpu.c:6:
In function 'strnlen',
inlined from 'strncat' at include/linux/fortify-string.h:404:13,
inlined from 'riscv_create_isa_string' at arch/riscv/kernel/cpu.c:269:4:
>> include/linux/fortify-string.h:29:33: warning: 'strlen' argument missing terminating nul [-Wstringop-overread]
29 | __ret = __builtin_strlen(__p); \
| ^~~~~~~~~~~~~~~~~~~~~
include/linux/fortify-string.h:195:24: note: in expansion of macro '__compiletime_strlen'
195 | size_t p_len = __compiletime_strlen(p);
| ^~~~~~~~~~~~~~~~~~~~
arch/riscv/kernel/cpu.c: In function 'riscv_create_isa_string':
arch/riscv/kernel/cpu.c:245:19: note: referenced argument declared here
245 | static const char base_riscv_exts[13] = "imafdqcbkjpvh";
| ^~~~~~~~~~~~~~~


vim +/strlen +29 include/linux/fortify-string.h

a28a6e860c6cf2 Francis Laniel 2021-02-25 18
3009f891bb9f32 Kees Cook 2021-08-02 19 #define __compiletime_strlen(p) \
3009f891bb9f32 Kees Cook 2021-08-02 20 ({ \
e9a40e1585d792 Kees Cook 2022-10-25 21 char *__p = (char *)(p); \
311fb40aa0569a Kees Cook 2022-09-02 22 size_t __ret = SIZE_MAX; \
9f7d69c5cd2390 Kees Cook 2022-09-19 23 size_t __p_size = __member_size(p); \
311fb40aa0569a Kees Cook 2022-09-02 24 if (__p_size != SIZE_MAX && \
d07c0acb4f41cc Kees Cook 2022-09-02 25 __builtin_constant_p(*__p)) { \
95cadae320be46 Qian Cai 2021-10-25 26 size_t __p_len = __p_size - 1; \
95cadae320be46 Qian Cai 2021-10-25 27 if (__builtin_constant_p(__p[__p_len]) && \
95cadae320be46 Qian Cai 2021-10-25 28 __p[__p_len] == '\0') \
95cadae320be46 Qian Cai 2021-10-25 @29 __ret = __builtin_strlen(__p); \
3009f891bb9f32 Kees Cook 2021-08-02 30 } \
95cadae320be46 Qian Cai 2021-10-25 31 __ret; \
3009f891bb9f32 Kees Cook 2021-08-02 32 })
3009f891bb9f32 Kees Cook 2021-08-02 33

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests

2023-04-25 08:50:53

by kernel test robot

[permalink] [raw]
Subject: Re: [PATCH 1/4] RISC-V: create ISA string separately - not as part of cpuinfo

Hi Heiko,

kernel test robot noticed the following build warnings:

[auto build test WARNING on next-20230424]
[also build test WARNING on v6.3]
[cannot apply to soc/for-next linus/master kees/for-next/execve v6.3 v6.3-rc7 v6.3-rc6]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url: https://github.com/intel-lab-lkp/linux/commits/Heiko-Stuebner/RISC-V-create-ISA-string-separately-not-as-part-of-cpuinfo/20230425-035214
base: next-20230424
patch link: https://lore.kernel.org/r/20230424194911.264850-2-heiko.stuebner%40vrull.eu
patch subject: [PATCH 1/4] RISC-V: create ISA string separately - not as part of cpuinfo
config: riscv-allnoconfig (https://download.01.org/0day-ci/archive/20230425/[email protected]/config)
compiler: riscv64-linux-gcc (GCC) 12.1.0
reproduce (this is a W=1 build):
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# https://github.com/intel-lab-lkp/linux/commit/8f1a5a16616d673f2c82cdc54ff845fd8b125a21
git remote add linux-review https://github.com/intel-lab-lkp/linux
git fetch --no-tags linux-review Heiko-Stuebner/RISC-V-create-ISA-string-separately-not-as-part-of-cpuinfo/20230425-035214
git checkout 8f1a5a16616d673f2c82cdc54ff845fd8b125a21
# save the config file
mkdir build_dir && cp config build_dir/.config
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-12.1.0 make.cross W=1 O=build_dir ARCH=riscv olddefconfig
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-12.1.0 make.cross W=1 O=build_dir ARCH=riscv SHELL=/bin/bash arch/riscv/kernel/

If you fix the issue, kindly add following tag where applicable
| Reported-by: kernel test robot <[email protected]>
| Link: https://lore.kernel.org/oe-kbuild-all/[email protected]/

All warnings (new ones prefixed by >>):

arch/riscv/kernel/cpu.c: In function 'riscv_create_isa_string':
>> arch/riscv/kernel/cpu.c:269:25: warning: 'strncat' output may be truncated copying 1 byte from a string of length 13 [-Wstringop-truncation]
269 | strncat(isa_str, &base_riscv_exts[i], 1);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


vim +/strncat +269 arch/riscv/kernel/cpu.c

246
247 static char *riscv_create_isa_string(const char *isa)
248 {
249 int maxlen = 4;
250 char *isa_str;
251 int i;
252
253 /* calculate the needed string length */
254 for (i = 0; i < sizeof(base_riscv_exts); i++)
255 if (__riscv_isa_extension_available(NULL, base_riscv_exts[i] - 'a'))
256 maxlen++;
257 maxlen += strlen_isa_ext();
258
259 isa_str = kzalloc(maxlen, GFP_KERNEL);
260 if (!isa_str)
261 return ERR_PTR(-ENOMEM);
262
263 /* Print the rv[64/32] part */
264 strncat(isa_str, isa, 4);
265
266 for (i = 0; i < sizeof(base_riscv_exts); i++) {
267 if (__riscv_isa_extension_available(NULL, base_riscv_exts[i] - 'a'))
268 /* Print only enabled the base ISA extensions */
> 269 strncat(isa_str, &base_riscv_exts[i], 1);
270 }
271
272 strcat_isa_ext(isa_str);
273
274 return isa_str;
275 }
276

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests

2023-04-26 09:34:20

by Andrew Jones

[permalink] [raw]
Subject: Re: [PATCH 1/4] RISC-V: create ISA string separately - not as part of cpuinfo

On Mon, Apr 24, 2023 at 09:49:08PM +0200, Heiko Stuebner wrote:
> From: Heiko Stuebner <[email protected]>
>
> The isa string is a very central part of the RISC-V architecture, so will
> be needed in other places as well.
>
> So in a first step decouple the generation of the runtime isa-string from
> /proc/cpuinfo - its current only user.
>
> The resulting string should not differ from the previously generated one.
>
> Signed-off-by: Heiko Stuebner <[email protected]>
> ---
> arch/riscv/kernel/cpu.c | 70 ++++++++++++++++++++++++++++++++++++-----
> 1 file changed, 62 insertions(+), 8 deletions(-)
>
> diff --git a/arch/riscv/kernel/cpu.c b/arch/riscv/kernel/cpu.c
> index 3df38052dcbd..ebc478f0a16c 100644
> --- a/arch/riscv/kernel/cpu.c
> +++ b/arch/riscv/kernel/cpu.c
> @@ -193,10 +193,33 @@ static struct riscv_isa_ext_data isa_ext_arr[] = {
> __RISCV_ISA_EXT_DATA("", RISCV_ISA_EXT_MAX),
> };
>
> -static void print_isa_ext(struct seq_file *f)
> +static int strlen_isa_ext(void)
> {
> struct riscv_isa_ext_data *edata;
> - int i = 0, arr_sz;
> + int ext_len = 0, i, arr_sz;
> +
> + arr_sz = ARRAY_SIZE(isa_ext_arr) - 1;

I see this subtracting of 1 here and then using <= below comes from
the current print_isa_ext(), but it seems odd. How about just

static int strlen_isa_ext(void)
{
int ext_len = 0;

for (int i = 0; i < ARRAY_SIZE(isa_ext_arr); ++i) {
struct riscv_isa_ext_data *edata = &isa_ext_arr[i];
...
}

return ext_len;
}

> +
> + /* No extension support available */
> + if (arr_sz <= 0)
> + return 0;
> +
> + for (i = 0; i <= arr_sz; i++) {
> + edata = &isa_ext_arr[i];
> + if (!__riscv_isa_extension_available(NULL, edata->isa_ext_id))
> + continue;
> +
> + /* string length + underscore */
> + ext_len += strlen(edata->uprop) + 1;
> + }
> +
> + return ext_len;
> +}
> +
> +static void strcat_isa_ext(char *isa_str)
> +{
> + struct riscv_isa_ext_data *edata;
> + int i, arr_sz;
>
> arr_sz = ARRAY_SIZE(isa_ext_arr) - 1;
>
> @@ -208,7 +231,8 @@ static void print_isa_ext(struct seq_file *f)
> edata = &isa_ext_arr[i];
> if (!__riscv_isa_extension_available(NULL, edata->isa_ext_id))
> continue;
> - seq_printf(f, "_%s", edata->uprop);
> + strcat(isa_str, "_");
> + strcat(isa_str, edata->uprop);
> }
> }
>
> @@ -220,19 +244,49 @@ static void print_isa_ext(struct seq_file *f)
> */
> static const char base_riscv_exts[13] = "imafdqcbkjpvh";
>
> -static void print_isa(struct seq_file *f, const char *isa)
> +static char *riscv_create_isa_string(const char *isa)
> {
> + int maxlen = 4;
> + char *isa_str;
> int i;
>
> - seq_puts(f, "isa\t\t: ");
> + /* calculate the needed string length */
> + for (i = 0; i < sizeof(base_riscv_exts); i++)
> + if (__riscv_isa_extension_available(NULL, base_riscv_exts[i] - 'a'))
> + maxlen++;
> + maxlen += strlen_isa_ext();
> +
> + isa_str = kzalloc(maxlen, GFP_KERNEL);
> + if (!isa_str)
> + return ERR_PTR(-ENOMEM);
> +
> /* Print the rv[64/32] part */
> - seq_write(f, isa, 4);
> + strncat(isa_str, isa, 4);
> +
> for (i = 0; i < sizeof(base_riscv_exts); i++) {
> if (__riscv_isa_extension_available(NULL, base_riscv_exts[i] - 'a'))
> /* Print only enabled the base ISA extensions */
> - seq_write(f, &base_riscv_exts[i], 1);
> + strncat(isa_str, &base_riscv_exts[i], 1);
> + }
> +
> + strcat_isa_ext(isa_str);
> +
> + return isa_str;
> +}
> +
> +static void print_isa(struct seq_file *f, const char *isa)
> +{
> + char *isa_str;
> +
> + seq_puts(f, "isa\t\t: ");
> +
> + isa_str = riscv_create_isa_string(isa);
> + if (!IS_ERR(isa_str)) {
> + seq_write(f, isa_str, strlen(isa_str));
> + kfree(isa_str);
> + } else {
> + seq_puts(f, "unknown");
> }
> - print_isa_ext(f);
> seq_puts(f, "\n");
> }
>
> --
> 2.39.0

Otherwise,

Reviewed-by: Andrew Jones <[email protected]>

2023-04-26 09:45:45

by Andrew Jones

[permalink] [raw]
Subject: Re: [PATCH 1/4] RISC-V: create ISA string separately - not as part of cpuinfo

On Mon, Apr 24, 2023 at 09:49:08PM +0200, Heiko Stuebner wrote:
> From: Heiko Stuebner <[email protected]>
>
> The isa string is a very central part of the RISC-V architecture, so will
> be needed in other places as well.
>
> So in a first step decouple the generation of the runtime isa-string from
> /proc/cpuinfo - its current only user.
>
> The resulting string should not differ from the previously generated one.
>
> Signed-off-by: Heiko Stuebner <[email protected]>
> ---
> arch/riscv/kernel/cpu.c | 70 ++++++++++++++++++++++++++++++++++++-----
> 1 file changed, 62 insertions(+), 8 deletions(-)
>
> diff --git a/arch/riscv/kernel/cpu.c b/arch/riscv/kernel/cpu.c
> index 3df38052dcbd..ebc478f0a16c 100644
> --- a/arch/riscv/kernel/cpu.c
> +++ b/arch/riscv/kernel/cpu.c
> @@ -193,10 +193,33 @@ static struct riscv_isa_ext_data isa_ext_arr[] = {
> __RISCV_ISA_EXT_DATA("", RISCV_ISA_EXT_MAX),
> };
>
> -static void print_isa_ext(struct seq_file *f)
> +static int strlen_isa_ext(void)
> {
> struct riscv_isa_ext_data *edata;
> - int i = 0, arr_sz;
> + int ext_len = 0, i, arr_sz;
> +
> + arr_sz = ARRAY_SIZE(isa_ext_arr) - 1;
> +
> + /* No extension support available */
> + if (arr_sz <= 0)
> + return 0;
> +
> + for (i = 0; i <= arr_sz; i++) {
> + edata = &isa_ext_arr[i];
> + if (!__riscv_isa_extension_available(NULL, edata->isa_ext_id))
> + continue;
> +
> + /* string length + underscore */
> + ext_len += strlen(edata->uprop) + 1;
> + }
> +
> + return ext_len;
> +}
> +
> +static void strcat_isa_ext(char *isa_str)
> +{
> + struct riscv_isa_ext_data *edata;
> + int i, arr_sz;
>
> arr_sz = ARRAY_SIZE(isa_ext_arr) - 1;
>
> @@ -208,7 +231,8 @@ static void print_isa_ext(struct seq_file *f)
> edata = &isa_ext_arr[i];
> if (!__riscv_isa_extension_available(NULL, edata->isa_ext_id))
> continue;
> - seq_printf(f, "_%s", edata->uprop);
> + strcat(isa_str, "_");
> + strcat(isa_str, edata->uprop);
> }
> }
>
> @@ -220,19 +244,49 @@ static void print_isa_ext(struct seq_file *f)
> */
> static const char base_riscv_exts[13] = "imafdqcbkjpvh";
>
> -static void print_isa(struct seq_file *f, const char *isa)
> +static char *riscv_create_isa_string(const char *isa)
> {
> + int maxlen = 4;
> + char *isa_str;
> int i;
>
> - seq_puts(f, "isa\t\t: ");
> + /* calculate the needed string length */
> + for (i = 0; i < sizeof(base_riscv_exts); i++)
> + if (__riscv_isa_extension_available(NULL, base_riscv_exts[i] - 'a'))
> + maxlen++;
> + maxlen += strlen_isa_ext();
> +
> + isa_str = kzalloc(maxlen, GFP_KERNEL);
> + if (!isa_str)
> + return ERR_PTR(-ENOMEM);
> +
> /* Print the rv[64/32] part */
> - seq_write(f, isa, 4);
> + strncat(isa_str, isa, 4);
> +
> for (i = 0; i < sizeof(base_riscv_exts); i++) {
> if (__riscv_isa_extension_available(NULL, base_riscv_exts[i] - 'a'))
> /* Print only enabled the base ISA extensions */
> - seq_write(f, &base_riscv_exts[i], 1);
> + strncat(isa_str, &base_riscv_exts[i], 1);
> + }
> +
> + strcat_isa_ext(isa_str);
> +
> + return isa_str;
> +}
> +
> +static void print_isa(struct seq_file *f, const char *isa)
> +{
> + char *isa_str;
> +
> + seq_puts(f, "isa\t\t: ");
> +
> + isa_str = riscv_create_isa_string(isa);

Shouldn't there be another patch in this series that switches this
to using the new riscv_base_platform. The allocation/regeneration/freeing
doesn't seem necessary each time we cat cpuinfo.

Thanks,
drew

> + if (!IS_ERR(isa_str)) {
> + seq_write(f, isa_str, strlen(isa_str));
> + kfree(isa_str);
> + } else {
> + seq_puts(f, "unknown");
> }
> - print_isa_ext(f);
> seq_puts(f, "\n");
> }
>
> --
> 2.39.0
>
>
> _______________________________________________
> linux-riscv mailing list
> [email protected]
> http://lists.infradead.org/mailman/listinfo/linux-riscv

2023-05-01 14:54:18

by Palmer Dabbelt

[permalink] [raw]
Subject: Re: [PATCH 1/4] RISC-V: create ISA string separately - not as part of cpuinfo

On Mon, 24 Apr 2023 12:49:08 PDT (-0700), [email protected] wrote:
> From: Heiko Stuebner <[email protected]>
>
> The isa string is a very central part of the RISC-V architecture, so will
> be needed in other places as well.
>
> So in a first step decouple the generation of the runtime isa-string from
> /proc/cpuinfo - its current only user.

I'm also going to leave this one out, both because it fails to build and
because the proposed second user isn't going to fly. I'm not opposed to
the refactoring, but too late for this merge window.

> The resulting string should not differ from the previously generated one.
>
> Signed-off-by: Heiko Stuebner <[email protected]>
> ---
> arch/riscv/kernel/cpu.c | 70 ++++++++++++++++++++++++++++++++++++-----
> 1 file changed, 62 insertions(+), 8 deletions(-)
>
> diff --git a/arch/riscv/kernel/cpu.c b/arch/riscv/kernel/cpu.c
> index 3df38052dcbd..ebc478f0a16c 100644
> --- a/arch/riscv/kernel/cpu.c
> +++ b/arch/riscv/kernel/cpu.c
> @@ -193,10 +193,33 @@ static struct riscv_isa_ext_data isa_ext_arr[] = {
> __RISCV_ISA_EXT_DATA("", RISCV_ISA_EXT_MAX),
> };
>
> -static void print_isa_ext(struct seq_file *f)
> +static int strlen_isa_ext(void)
> {
> struct riscv_isa_ext_data *edata;
> - int i = 0, arr_sz;
> + int ext_len = 0, i, arr_sz;
> +
> + arr_sz = ARRAY_SIZE(isa_ext_arr) - 1;
> +
> + /* No extension support available */
> + if (arr_sz <= 0)
> + return 0;
> +
> + for (i = 0; i <= arr_sz; i++) {
> + edata = &isa_ext_arr[i];
> + if (!__riscv_isa_extension_available(NULL, edata->isa_ext_id))
> + continue;
> +
> + /* string length + underscore */
> + ext_len += strlen(edata->uprop) + 1;
> + }
> +
> + return ext_len;
> +}
> +
> +static void strcat_isa_ext(char *isa_str)
> +{
> + struct riscv_isa_ext_data *edata;
> + int i, arr_sz;
>
> arr_sz = ARRAY_SIZE(isa_ext_arr) - 1;
>
> @@ -208,7 +231,8 @@ static void print_isa_ext(struct seq_file *f)
> edata = &isa_ext_arr[i];
> if (!__riscv_isa_extension_available(NULL, edata->isa_ext_id))
> continue;
> - seq_printf(f, "_%s", edata->uprop);
> + strcat(isa_str, "_");
> + strcat(isa_str, edata->uprop);
> }
> }
>
> @@ -220,19 +244,49 @@ static void print_isa_ext(struct seq_file *f)
> */
> static const char base_riscv_exts[13] = "imafdqcbkjpvh";
>
> -static void print_isa(struct seq_file *f, const char *isa)
> +static char *riscv_create_isa_string(const char *isa)
> {
> + int maxlen = 4;
> + char *isa_str;
> int i;
>
> - seq_puts(f, "isa\t\t: ");
> + /* calculate the needed string length */
> + for (i = 0; i < sizeof(base_riscv_exts); i++)
> + if (__riscv_isa_extension_available(NULL, base_riscv_exts[i] - 'a'))
> + maxlen++;
> + maxlen += strlen_isa_ext();
> +
> + isa_str = kzalloc(maxlen, GFP_KERNEL);
> + if (!isa_str)
> + return ERR_PTR(-ENOMEM);
> +
> /* Print the rv[64/32] part */
> - seq_write(f, isa, 4);
> + strncat(isa_str, isa, 4);
> +
> for (i = 0; i < sizeof(base_riscv_exts); i++) {
> if (__riscv_isa_extension_available(NULL, base_riscv_exts[i] - 'a'))
> /* Print only enabled the base ISA extensions */
> - seq_write(f, &base_riscv_exts[i], 1);
> + strncat(isa_str, &base_riscv_exts[i], 1);
> + }
> +
> + strcat_isa_ext(isa_str);
> +
> + return isa_str;
> +}
> +
> +static void print_isa(struct seq_file *f, const char *isa)
> +{
> + char *isa_str;
> +
> + seq_puts(f, "isa\t\t: ");
> +
> + isa_str = riscv_create_isa_string(isa);
> + if (!IS_ERR(isa_str)) {
> + seq_write(f, isa_str, strlen(isa_str));
> + kfree(isa_str);
> + } else {
> + seq_puts(f, "unknown");
> }
> - print_isa_ext(f);
> seq_puts(f, "\n");
> }