diff mbox series

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

Message ID 20230424194911.264850-2-heiko.stuebner@vrull.eu (mailing list archive)
State Rejected
Headers show
Series Expose the isa-string via the AT_BASE_PLATFORM aux vector | expand

Checks

Context Check Description
conchuod/cover_letter success Series has a cover letter
conchuod/tree_selection success Guessed tree name to be for-next at HEAD 310c33dc7a12
conchuod/fixes_present success Fixes tag not required for -next series
conchuod/maintainers_pattern success MAINTAINERS pattern errors before the patch: 1 and now 1
conchuod/verify_signedoff success Signed-off-by tag matches author and committer
conchuod/kdoc success Errors and warnings before: 0 this patch: 0
conchuod/build_rv64_clang_allmodconfig success Errors and warnings before: 18 this patch: 18
conchuod/module_param success Was 0 now: 0
conchuod/build_rv64_gcc_allmodconfig fail Errors and warnings before: 19 this patch: 20
conchuod/build_rv32_defconfig success Build OK
conchuod/dtb_warn_rv64 success Errors and warnings before: 3 this patch: 3
conchuod/header_inline success No static functions without inline keyword in header files
conchuod/checkpatch success total: 0 errors, 0 warnings, 0 checks, 98 lines checked
conchuod/source_inline success Was 0 now: 0
conchuod/build_rv64_nommu_k210_defconfig success Build OK
conchuod/verify_fixes success No Fixes tag
conchuod/build_rv64_nommu_virt_defconfig success Build OK

Commit Message

Heiko Stübner April 24, 2023, 7:49 p.m. UTC
From: Heiko Stuebner <heiko.stuebner@vrull.eu>

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 <heiko.stuebner@vrull.eu>
---
 arch/riscv/kernel/cpu.c | 70 ++++++++++++++++++++++++++++++++++++-----
 1 file changed, 62 insertions(+), 8 deletions(-)

Comments

kernel test robot April 24, 2023, 11:06 p.m. UTC | #1
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/202304250614.g73yVtvv-lkp@intel.com/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 <lkp@intel.com>
| Link: https://lore.kernel.org/oe-kbuild-all/202304250614.g73yVtvv-lkp@intel.com/

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
kernel test robot April 25, 2023, 8:45 a.m. UTC | #2
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/202304251640.IVxoyd0v-lkp@intel.com/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 <lkp@intel.com>
| Link: https://lore.kernel.org/oe-kbuild-all/202304251640.IVxoyd0v-lkp@intel.com/

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
Andrew Jones April 26, 2023, 9:26 a.m. UTC | #3
On Mon, Apr 24, 2023 at 09:49:08PM +0200, Heiko Stuebner wrote:
> From: Heiko Stuebner <heiko.stuebner@vrull.eu>
> 
> 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 <heiko.stuebner@vrull.eu>
> ---
>  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 <ajones@ventanamicro.com>
Andrew Jones April 26, 2023, 9:44 a.m. UTC | #4
On Mon, Apr 24, 2023 at 09:49:08PM +0200, Heiko Stuebner wrote:
> From: Heiko Stuebner <heiko.stuebner@vrull.eu>
> 
> 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 <heiko.stuebner@vrull.eu>
> ---
>  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
> linux-riscv@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-riscv
Palmer Dabbelt May 1, 2023, 2:52 p.m. UTC | #5
On Mon, 24 Apr 2023 12:49:08 PDT (-0700), heiko@sntech.de wrote:
> From: Heiko Stuebner <heiko.stuebner@vrull.eu>
>
> 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 <heiko.stuebner@vrull.eu>
> ---
>  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");
>  }
diff mbox series

Patch

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");
 }