LoongArch: Add glibc.cpu.hwcap support.

Message ID 20230917094855.3654948-1-caiyinyu@loongson.cn
State Committed
Commit a53451559dc9cce765ea5bcbb92c4007e058e92b
Headers
Series LoongArch: Add glibc.cpu.hwcap support. |

Checks

Context Check Description
redhat-pt-bot/TryBot-apply_patch success Patch applied to master at the time it was sent
redhat-pt-bot/TryBot-32bit success Build for i686
linaro-tcwg-bot/tcwg_glibc_build--master-aarch64 success Testing passed
linaro-tcwg-bot/tcwg_glibc_check--master-aarch64 success Testing passed
linaro-tcwg-bot/tcwg_glibc_build--master-arm success Testing passed
linaro-tcwg-bot/tcwg_glibc_check--master-arm success Testing passed

Commit Message

caiyinyu Sept. 17, 2023, 9:48 a.m. UTC
  Key Points:
1. On lasx & lsx platforms, We must use _dl_runtime_{profile, resolve}_{lsx, lasx}
   to save vector registers.
2. Via "tunables", users can choose str/mem_{lasx,lsx,unaligned} functions with
   `export GLIBC_TUNABLES=glibc.cpu.hwcaps=LASX,...`.
   Note: glibc.cpu.hwcaps doesn't affect _dl_runtime_{profile, resolve}_{lsx, lasx}
   selection.

Usage Notes:
1. Only valid inputs: LASX, LSX, UAL. Case-sensitive, comma-separated, no spaces.
2. Example: `export GLIBC_TUNABLES=glibc.cpu.hwcaps=LASX,UAL` turns on LASX & UAL.
   Unmentioned features turn off. With default ifunc: lasx > lsx > unaligned >
   aligned > generic, effect is: lasx > unaligned > aligned > generic; lsx off.
3. Incorrect GLIBC_TUNABLES settings will show error messages.
   For example: On lsx platforms, you cannot enable lasx features. If you do
   that, you will get error messages.
4. Valid input examples:
   - GLIBC_TUNABLES=glibc.cpu.hwcaps=LASX: lasx > aligned > generic.
   - GLIBC_TUNABLES=glibc.cpu.hwcaps=LSX,UAL: lsx > unaligned > aligned > generic.
   - GLIBC_TUNABLES=glibc.cpu.hwcaps=LASX,UAL,LASX,UAL,LSX,LASX,UAL: Repetitions
     allowed but not recommended. Results in: lasx > lsx > unaligned > aligned >
     generic.
---
 sysdeps/loongarch/Makefile                    |  4 +
 sysdeps/loongarch/Versions                    |  5 ++
 sysdeps/loongarch/cpu-tunables.c              | 89 +++++++++++++++++++
 sysdeps/loongarch/dl-get-cpu-features.c       | 25 ++++++
 sysdeps/loongarch/dl-machine.h                | 27 +++++-
 sysdeps/loongarch/dl-tunables.list            | 25 ++++++
 .../unix/sysv/linux/loongarch/cpu-features.c  | 29 ++++++
 .../unix/sysv/linux/loongarch/cpu-features.h  | 18 +++-
 .../unix/sysv/linux/loongarch/dl-procinfo.c   | 60 +++++++++++++
 sysdeps/unix/sysv/linux/loongarch/dl-sysdep.c | 21 +++++
 .../unix/sysv/linux/loongarch/libc-start.c    | 34 +++++++
 11 files changed, 329 insertions(+), 8 deletions(-)
 create mode 100644 sysdeps/loongarch/Versions
 create mode 100644 sysdeps/loongarch/cpu-tunables.c
 create mode 100644 sysdeps/loongarch/dl-get-cpu-features.c
 create mode 100644 sysdeps/loongarch/dl-tunables.list
 create mode 100644 sysdeps/unix/sysv/linux/loongarch/cpu-features.c
 create mode 100644 sysdeps/unix/sysv/linux/loongarch/dl-procinfo.c
 create mode 100644 sysdeps/unix/sysv/linux/loongarch/dl-sysdep.c
 create mode 100644 sysdeps/unix/sysv/linux/loongarch/libc-start.c
  

Comments

Adhemerval Zanella Netto Sept. 19, 2023, 9:33 a.m. UTC | #1
On 17/09/23 06:48, caiyinyu wrote:
> Key Points:
> 1. On lasx & lsx platforms, We must use _dl_runtime_{profile, resolve}_{lsx, lasx}
>    to save vector registers.
> 2. Via "tunables", users can choose str/mem_{lasx,lsx,unaligned} functions with
>    `export GLIBC_TUNABLES=glibc.cpu.hwcaps=LASX,...`.
>    Note: glibc.cpu.hwcaps doesn't affect _dl_runtime_{profile, resolve}_{lsx, lasx}
>    selection.
> 
> Usage Notes:
> 1. Only valid inputs: LASX, LSX, UAL. Case-sensitive, comma-separated, no spaces.
> 2. Example: `export GLIBC_TUNABLES=glibc.cpu.hwcaps=LASX,UAL` turns on LASX & UAL.
>    Unmentioned features turn off. With default ifunc: lasx > lsx > unaligned >
>    aligned > generic, effect is: lasx > unaligned > aligned > generic; lsx off.
> 3. Incorrect GLIBC_TUNABLES settings will show error messages.
>    For example: On lsx platforms, you cannot enable lasx features. If you do
>    that, you will get error messages.
> 4. Valid input examples:
>    - GLIBC_TUNABLES=glibc.cpu.hwcaps=LASX: lasx > aligned > generic.
>    - GLIBC_TUNABLES=glibc.cpu.hwcaps=LSX,UAL: lsx > unaligned > aligned > generic.
>    - GLIBC_TUNABLES=glibc.cpu.hwcaps=LASX,UAL,LASX,UAL,LSX,LASX,UAL: Repetitions
>      allowed but not recommended. Results in: lasx > lsx > unaligned > aligned >
>      generic.

This patch and a bunch other for Loongarch landed without any sort of
review. I know that this mostly touch arch-specific code and in the end
it would up to arch-maintaners to actually review and install this; but
I also would be good to have at some some of minimum review from another
loongarch maintaner.

Below some comments, which should be catch by a proper review.

> ---
>  sysdeps/loongarch/Makefile                    |  4 +
>  sysdeps/loongarch/Versions                    |  5 ++
>  sysdeps/loongarch/cpu-tunables.c              | 89 +++++++++++++++++++
>  sysdeps/loongarch/dl-get-cpu-features.c       | 25 ++++++
>  sysdeps/loongarch/dl-machine.h                | 27 +++++-
>  sysdeps/loongarch/dl-tunables.list            | 25 ++++++
>  .../unix/sysv/linux/loongarch/cpu-features.c  | 29 ++++++
>  .../unix/sysv/linux/loongarch/cpu-features.h  | 18 +++-
>  .../unix/sysv/linux/loongarch/dl-procinfo.c   | 60 +++++++++++++
>  sysdeps/unix/sysv/linux/loongarch/dl-sysdep.c | 21 +++++
>  .../unix/sysv/linux/loongarch/libc-start.c    | 34 +++++++
>  11 files changed, 329 insertions(+), 8 deletions(-)
>  create mode 100644 sysdeps/loongarch/Versions
>  create mode 100644 sysdeps/loongarch/cpu-tunables.c
>  create mode 100644 sysdeps/loongarch/dl-get-cpu-features.c
>  create mode 100644 sysdeps/loongarch/dl-tunables.list
>  create mode 100644 sysdeps/unix/sysv/linux/loongarch/cpu-features.c
>  create mode 100644 sysdeps/unix/sysv/linux/loongarch/dl-procinfo.c
>  create mode 100644 sysdeps/unix/sysv/linux/loongarch/dl-sysdep.c
>  create mode 100644 sysdeps/unix/sysv/linux/loongarch/libc-start.c
> 
> diff --git a/sysdeps/loongarch/Makefile b/sysdeps/loongarch/Makefile
> index 43d2f583cd..30a1f4a802 100644
> --- a/sysdeps/loongarch/Makefile
> +++ b/sysdeps/loongarch/Makefile
> @@ -6,6 +6,10 @@ ifeq ($(subdir),elf)
>  gen-as-const-headers += dl-link.sym
>  endif
>  
> +ifeq ($(subdir),elf)
> +  sysdep-dl-routines += dl-get-cpu-features

No need of double-space and move the entry to a new line:

sysdep-dl-routines += \
  dl-get-cpu-features \
  # sysdep-dl-routines

> +endif
> +
>  # LoongArch's assembler also needs to know about PIC as it changes the
>  # definition of some assembler macros.
>  ASFLAGS-.os += $(pic-ccflag)
> diff --git a/sysdeps/loongarch/Versions b/sysdeps/loongarch/Versions
> new file mode 100644
> index 0000000000..33ae2cc079
> --- /dev/null
> +++ b/sysdeps/loongarch/Versions
> @@ -0,0 +1,5 @@
> +ld {
> +  GLIBC_PRIVATE {
> +    _dl_larch_get_cpu_features;
> +  }
> +}

This file is not need, libc.so does not reference _dl_larch_get_cpu_features.

> diff --git a/sysdeps/loongarch/cpu-tunables.c b/sysdeps/loongarch/cpu-tunables.c
> new file mode 100644
> index 0000000000..8e9fab938b
> --- /dev/null
> +++ b/sysdeps/loongarch/cpu-tunables.c
> @@ -0,0 +1,89 @@
> +/* LoongArch CPU feature tuning.
> +   This file is part of the GNU C Library.
> +   Copyright (C) 2023 Free Software Foundation, Inc.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library; if not, see
> +   <http://www.gnu.org/licenses/>.  */
> +
> +# include <stdbool.h>
> +# include <stdint.h>
> +# include <unistd.h>		/* Get STDOUT_FILENO for _dl_printf.  */
> +# include <elf/dl-tunables.h>
> +# include <string.h>
> +# include <cpu-features.h>
> +# include <ldsodefs.h>
> +# include <sys/auxv.h>
> +
> +# define HWCAP_LOONGARCH_IFUNC \
> +  (HWCAP_LOONGARCH_UAL | HWCAP_LOONGARCH_LSX | HWCAP_LOONGARCH_LASX)
> +
> +# define CHECK_GLIBC_IFUNC_CPU_OFF(f, name, len)			\
> +  _Static_assert (sizeof (#name) - 1 == len, #name " != " #len);	\
> +  if (!memcmp (f, #name, len) &&					\

Use memcmp (...) == 0.

> +      (GLRO (dl_hwcap) & HWCAP_LOONGARCH_##name))			\
> +    {									\
> +      hwcap |= (HWCAP_LOONGARCH_##name | (~HWCAP_LOONGARCH_IFUNC));	\
> +      break;								\
> +    }									\
> +
> +attribute_hidden
> +void
> +TUNABLE_CALLBACK (set_hwcaps) (tunable_val_t *valp)
> +{

Maybe add a comment, similar to s390 and x86_64, on how the GLIBC_TUNABLES
should behave regarding parsing here.  The powerpc and s390 allows the
setup of disable a hwcap tunable by appending '-', as:

  GLIBC_TUNABLES=glibc.cpu.hwcaps=-xxx,yyy,zzz,....

And it not clear how loongarch will handle.  If I understand correclty,
setting:

  GLIBC_TUNABLES=glibc.cpu.hwcaps=LSX

will set the 'hwcap' to HWCAP_LOONGARCH_UAL | HWCAP_LOONGARCH_LSX | HWCAP_LOONGARCH_LASX)
because CHECK_GLIBC_IFUNC_CPU_OFF 'or' everything (which does not seem
correct).

So I would expect that it would follow what powerpc/s390 does, so
we could eventually consolidate this code.

> +  const char *p = valp->strval;
> +  size_t len;
> +  unsigned long hwcap = 0;
> +  const char *c;
> +
> +  do {

Put the bracet on a newline.

> +      for (c = p; *c != ','; c++)
> +	if (*c == '\0')
> +	  break;
> +
> +      len = c - p;
> +
> +      switch(len)

Space after 'switch'. 

> +      {
> +	default:
> +	  _dl_fatal_printf (
> +	    "The valid values of glibc.cpu.hwcaps is UAL, LASX, LSX!!\n"
> +			    );

I think the ');' should be on previou sline.

> +	  break;
> +	case 3:
> +	  {
> +	    CHECK_GLIBC_IFUNC_CPU_OFF (p, LSX, 3);
> +	    CHECK_GLIBC_IFUNC_CPU_OFF (p, UAL, 3);
> +	    _dl_fatal_printf (
> +		"Some features are invalid or not supported on this machine!!\n"
> +		"The valid values of glibc.cpu.hwcaps is UAL, LASX, LSX!!\n"
> +                       );
> +	  }
> +	  break;
> +	case 4:
> +	  {
> +	    CHECK_GLIBC_IFUNC_CPU_OFF (p, LASX, 4);
> +	    _dl_fatal_printf (
> +		"Some features are invalid or not supported on this machine!!\n"
> +		"The valid values of glibc.cpu.hwcaps is UAL, LASX, LSX!!\n"
> +                       );
> +	  }
> +	  break;
> +      }
> +
> +      p += len + 1;
> +    }
> +  while (*c != '\0');
> +
> +  GLRO (dl_larch_cpu_features).hwcap &= hwcap;
> +}
> diff --git a/sysdeps/loongarch/dl-get-cpu-features.c b/sysdeps/loongarch/dl-get-cpu-features.c
> new file mode 100644
> index 0000000000..7cd9bc15c3
> --- /dev/null
> +++ b/sysdeps/loongarch/dl-get-cpu-features.c
> @@ -0,0 +1,25 @@
> +/* Define _dl_larch_get_cpu_features.
> +   Copyright (C) 2023 Free Software Foundation, Inc.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library; if not, see
> +   <https://www.gnu.org/licenses/>.  */
> +
> +
> +#include <ldsodefs.h>
> +
> +const struct cpu_features *
> +_dl_larch_get_cpu_features (void)
> +{
> +  return &GLRO(dl_larch_cpu_features);
> +}
> diff --git a/sysdeps/loongarch/dl-machine.h b/sysdeps/loongarch/dl-machine.h
> index 57913cefaa..b395a9283e 100644
> --- a/sysdeps/loongarch/dl-machine.h
> +++ b/sysdeps/loongarch/dl-machine.h
> @@ -29,6 +29,8 @@
>  #include <dl-static-tls.h>
>  #include <dl-machine-rel.h>
>  
> +#include <cpu-features.c>
> +
>  #ifndef _RTLD_PROLOGUE
>  # define _RTLD_PROLOGUE(entry)					\
>  	".globl\t" __STRING (entry) "\n\t"			\
> @@ -53,6 +55,23 @@
>  #define ELF_MACHINE_NO_REL 1
>  #define ELF_MACHINE_NO_RELA 0
>  
> +#define DL_PLATFORM_INIT dl_platform_init ()
> +
> +static inline void __attribute__ ((unused))
> +dl_platform_init (void)
> +{
> +  if (GLRO(dl_platform) != NULL && *GLRO(dl_platform) == '\0')
> +    /* Avoid an empty string which would disturb us.  */
> +    GLRO(dl_platform) = NULL;
> +
> +#ifdef SHARED
> +  /* init_cpu_features has been called early from __libc_start_main in
> +     static executable.  */
> +  init_cpu_features (&GLRO(dl_larch_cpu_features));
> +#endif
> +}
> +
> +
>  /* Return nonzero iff ELF header is compatible with the running host.  */
>  static inline int
>  elf_machine_matches_host (const ElfW (Ehdr) *ehdr)
> @@ -290,9 +309,9 @@ elf_machine_runtime_setup (struct link_map *l, struct r_scope_elem *scope[],
>        if (profile != 0)
>  	{
>  #if !defined __loongarch_soft_float
> -	  if (SUPPORT_LASX)
> +	  if (RTLD_SUPPORT_LASX)
>  	    gotplt[0] = (ElfW(Addr)) &_dl_runtime_profile_lasx;
> -	  else if (SUPPORT_LSX)
> +	  else if (RTLD_SUPPORT_LSX)
>  	    gotplt[0] = (ElfW(Addr)) &_dl_runtime_profile_lsx;
>  	  else
>  #endif
> @@ -310,9 +329,9 @@ elf_machine_runtime_setup (struct link_map *l, struct r_scope_elem *scope[],
>  	     indicated by the offset on the stack, and then jump to
>  	     the resolved address.  */
>  #if !defined __loongarch_soft_float
> -	  if (SUPPORT_LASX)
> +	  if (RTLD_SUPPORT_LASX)
>  	    gotplt[0] = (ElfW(Addr)) &_dl_runtime_resolve_lasx;
> -	  else if (SUPPORT_LSX)
> +	  else if (RTLD_SUPPORT_LSX)
>  	    gotplt[0] = (ElfW(Addr)) &_dl_runtime_resolve_lsx;
>  	  else
>  #endif
> diff --git a/sysdeps/loongarch/dl-tunables.list b/sysdeps/loongarch/dl-tunables.list
> new file mode 100644
> index 0000000000..66b3427516
> --- /dev/null
> +++ b/sysdeps/loongarch/dl-tunables.list
> @@ -0,0 +1,25 @@
> +# LoongArch specific tunables.
> +# Copyright (C) 2023 Free Software Foundation, Inc.
> +# This file is part of the GNU C Library.
> +
> +# The GNU C Library is free software; you can redistribute it and/or
> +# modify it under the terms of the GNU Lesser General Public
> +# License as published by the Free Software Foundation; either
> +# version 2.1 of the License, or (at your option) any later version.
> +
> +# The GNU C Library is distributed in the hope that it will be useful,
> +# but WITHOUT ANY WARRANTY; without even the implied warranty of
> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +# Lesser General Public License for more details.
> +
> +# You should have received a copy of the GNU Lesser General Public
> +# License along with the GNU C Library; if not, see
> +# <http://www.gnu.org/licenses/>.
> +
> +glibc {
> +  cpu {
> +    hwcaps {
> +      type: STRING
> +    }
> +  }
> +}
> diff --git a/sysdeps/unix/sysv/linux/loongarch/cpu-features.c b/sysdeps/unix/sysv/linux/loongarch/cpu-features.c
> new file mode 100644
> index 0000000000..1290c4ce9f
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/loongarch/cpu-features.c
> @@ -0,0 +1,29 @@
> +/* Initialize CPU feature data.  LoongArch64 version.
> +   This file is part of the GNU C Library.
> +   Copyright (C) 2023 Free Software Foundation, Inc.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library; if not, see
> +   <http://www.gnu.org/licenses/>.  */
> +
> +#include <cpu-features.h>
> +#include <elf/dl-hwcaps.h>
> +#include <elf/dl-tunables.h>
> +extern void TUNABLE_CALLBACK (set_hwcaps) (tunable_val_t *) attribute_hidden;
> +
> +static inline void
> +init_cpu_features (struct cpu_features *cpu_features)
> +{
> +    GLRO (dl_larch_cpu_features).hwcap = GLRO (dl_hwcap);
> +    TUNABLE_GET (glibc, cpu, hwcaps, tunable_val_t *, TUNABLE_CALLBACK (set_hwcaps));

The initial space number seems odd here.

> +}
> diff --git a/sysdeps/unix/sysv/linux/loongarch/cpu-features.h b/sysdeps/unix/sysv/linux/loongarch/cpu-features.h
> index d1a280a5ee..450963cebc 100644
> --- a/sysdeps/unix/sysv/linux/loongarch/cpu-features.h
> +++ b/sysdeps/unix/sysv/linux/loongarch/cpu-features.h
> @@ -19,13 +19,23 @@
>  #ifndef _CPU_FEATURES_LOONGARCH64_H
>  #define _CPU_FEATURES_LOONGARCH64_H
>  
> +#include <stdint.h>
>  #include <sys/auxv.h>
>  
> -#define SUPPORT_UAL (GLRO (dl_hwcap) & HWCAP_LOONGARCH_UAL)
> -#define SUPPORT_LSX (GLRO (dl_hwcap) & HWCAP_LOONGARCH_LSX)
> -#define SUPPORT_LASX (GLRO (dl_hwcap) & HWCAP_LOONGARCH_LASX)
> +struct cpu_features
> + {
> +    uint64_t hwcap;
> + };

The indentation seems off here.

>  
> +/* Get a pointer to the CPU features structure.  */
> +extern const struct cpu_features *_dl_larch_get_cpu_features (void)
> +     __attribute__ ((pure));
> +
> +#define SUPPORT_UAL (GLRO (dl_larch_cpu_features).hwcap & HWCAP_LOONGARCH_UAL)
> +#define SUPPORT_LSX (GLRO (dl_larch_cpu_features).hwcap & HWCAP_LOONGARCH_LSX)
> +#define SUPPORT_LASX (GLRO (dl_larch_cpu_features).hwcap & HWCAP_LOONGARCH_LASX)
> +#define RTLD_SUPPORT_LSX (GLRO (dl_hwcap) & HWCAP_LOONGARCH_LSX)
> +#define RTLD_SUPPORT_LASX (GLRO (dl_hwcap) & HWCAP_LOONGARCH_LASX)

For GLRO, it is considered a variable access to there is no need of space.

>  #define INIT_ARCH()
>  
>  #endif /* _CPU_FEATURES_LOONGARCH64_H  */
> -
> diff --git a/sysdeps/unix/sysv/linux/loongarch/dl-procinfo.c b/sysdeps/unix/sysv/linux/loongarch/dl-procinfo.c
> new file mode 100644
> index 0000000000..6217fda983
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/loongarch/dl-procinfo.c
> @@ -0,0 +1,60 @@
> +/* Data for LoongArch64 version of processor capability information.
> +   Linux version.
> +   Copyright (C) 2023 Free Software Foundation, Inc.
> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library; if not, see
> +   <http://www.gnu.org/licenses/>.  */
> +
> +/* If anything should be added here check whether the size of each string
> +   is still ok with the given array size.
> +
> +   All the #ifdefs in the definitions are quite irritating but
> +   necessary if we want to avoid duplicating the information.  There
> +   are three different modes:
> +
> +   - PROCINFO_DECL is defined.  This means we are only interested in
> +     declarations.
> +
> +   - PROCINFO_DECL is not defined:
> +
> +     + if SHARED is defined the file is included in an array
> +       initializer.  The .element = { ... } syntax is needed.
> +
> +     + if SHARED is not defined a normal array initialization is
> +       needed.
> +  */
> +
> +#ifndef PROCINFO_CLASS
> +# define PROCINFO_CLASS
> +#endif
> +
> +#if !IS_IN (ldconfig)
> +# if !defined PROCINFO_DECL && defined SHARED
> +  ._dl_larch_cpu_features
> +# else
> +PROCINFO_CLASS struct cpu_features _dl_larch_cpu_features
> +# endif
> +# ifndef PROCINFO_DECL
> += { }
> +# endif
> +# if !defined SHARED || defined PROCINFO_DECL
> +;
> +# else
> +,
> +# endif
> +#endif
> +
> +#undef PROCINFO_DECL
> +#undef PROCINFO_CLASS
> diff --git a/sysdeps/unix/sysv/linux/loongarch/dl-sysdep.c b/sysdeps/unix/sysv/linux/loongarch/dl-sysdep.c
> new file mode 100644
> index 0000000000..455fd71abc
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/loongarch/dl-sysdep.c
> @@ -0,0 +1,21 @@
> +/* Operating system support for run-time dynamic linker.  LoongArch version.
> +   Copyright (C) 2023 Free Software Foundation, Inc.
> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library; if not, see
> +   <http://www.gnu.org/licenses/>.  */
> +
> +#include <config.h>
> +#include <sysdeps/loongarch/cpu-tunables.c>
> +#include <sysdeps/unix/sysv/linux/dl-sysdep.c>
> diff --git a/sysdeps/unix/sysv/linux/loongarch/libc-start.c b/sysdeps/unix/sysv/linux/loongarch/libc-start.c
> new file mode 100644
> index 0000000000..f1346ece0a
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/loongarch/libc-start.c
> @@ -0,0 +1,34 @@
> +/* Override csu/libc-start.c on LoongArch64.
> +   Copyright (C) 2023 Free Software Foundation, Inc.
> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library; if not, see
> +   <http://www.gnu.org/licenses/>.  */
> +
> +#ifndef SHARED
> +
> +/* Mark symbols hidden in static PIE for early self relocation to work.  */
> +# if BUILD_PIE_DEFAULT
> +#  pragma GCC visibility push(hidden)
> +# endif
> +
> +# include <ldsodefs.h>
> +# include <cpu-features.c>
> +
> +extern struct cpu_features _dl_larch_cpu_features;
> +
> +# define ARCH_INIT_CPU_FEATURES() init_cpu_features (&_dl_larch_cpu_features)
> +
> +#endif
> +#include <csu/libc-start.c>

I think this patch misses a proper testcase, similar to one I suggested
when powerpc added a similar support (check 21841f0d562f0e944c4d267a28cc3ebd19c847e9).
Check sysdeps/unix/sysv/linux/powerpc/tst-hwcap-tunables.c on a way to
proper check it.
  
Xi Ruoyao Sept. 19, 2023, 10:11 a.m. UTC | #2
By the way, GCC maintainers told me there may be future CPU models with
LSX/LASX but without UAL.  And if I read our string functions correctly,
the LSX/LASX ifuncs require UAL as well.  So we should only enable LSX
and LASX if UAL is also available, or make these string functions depend
on both LSX (LASX) and UAL.  Is this properly implemented now?

On Sun, 2023-09-17 at 17:48 +0800, caiyinyu wrote:
> Key Points:
> 1. On lasx & lsx platforms, We must use _dl_runtime_{profile, resolve}_{lsx, lasx}
>    to save vector registers.
> 2. Via "tunables", users can choose str/mem_{lasx,lsx,unaligned} functions with
>    `export GLIBC_TUNABLES=glibc.cpu.hwcaps=LASX,...`.
>    Note: glibc.cpu.hwcaps doesn't affect _dl_runtime_{profile, resolve}_{lsx, lasx}
>    selection.
> 
> Usage Notes:
> 1. Only valid inputs: LASX, LSX, UAL. Case-sensitive, comma-separated, no spaces.
> 2. Example: `export GLIBC_TUNABLES=glibc.cpu.hwcaps=LASX,UAL` turns on LASX & UAL.
>    Unmentioned features turn off. With default ifunc: lasx > lsx > unaligned >
>    aligned > generic, effect is: lasx > unaligned > aligned > generic; lsx off.
> 3. Incorrect GLIBC_TUNABLES settings will show error messages.
>    For example: On lsx platforms, you cannot enable lasx features. If you do
>    that, you will get error messages.
> 4. Valid input examples:
>    - GLIBC_TUNABLES=glibc.cpu.hwcaps=LASX: lasx > aligned > generic.
>    - GLIBC_TUNABLES=glibc.cpu.hwcaps=LSX,UAL: lsx > unaligned > aligned > generic.
>    - GLIBC_TUNABLES=glibc.cpu.hwcaps=LASX,UAL,LASX,UAL,LSX,LASX,UAL: Repetitions
>      allowed but not recommended. Results in: lasx > lsx > unaligned > aligned >
>      generic.
> ---
>  sysdeps/loongarch/Makefile                    |  4 +
>  sysdeps/loongarch/Versions                    |  5 ++
>  sysdeps/loongarch/cpu-tunables.c              | 89 +++++++++++++++++++
>  sysdeps/loongarch/dl-get-cpu-features.c       | 25 ++++++
>  sysdeps/loongarch/dl-machine.h                | 27 +++++-
>  sysdeps/loongarch/dl-tunables.list            | 25 ++++++
>  .../unix/sysv/linux/loongarch/cpu-features.c  | 29 ++++++
>  .../unix/sysv/linux/loongarch/cpu-features.h  | 18 +++-
>  .../unix/sysv/linux/loongarch/dl-procinfo.c   | 60 +++++++++++++
>  sysdeps/unix/sysv/linux/loongarch/dl-sysdep.c | 21 +++++
>  .../unix/sysv/linux/loongarch/libc-start.c    | 34 +++++++
>  11 files changed, 329 insertions(+), 8 deletions(-)
>  create mode 100644 sysdeps/loongarch/Versions
>  create mode 100644 sysdeps/loongarch/cpu-tunables.c
>  create mode 100644 sysdeps/loongarch/dl-get-cpu-features.c
>  create mode 100644 sysdeps/loongarch/dl-tunables.list
>  create mode 100644 sysdeps/unix/sysv/linux/loongarch/cpu-features.c
>  create mode 100644 sysdeps/unix/sysv/linux/loongarch/dl-procinfo.c
>  create mode 100644 sysdeps/unix/sysv/linux/loongarch/dl-sysdep.c
>  create mode 100644 sysdeps/unix/sysv/linux/loongarch/libc-start.c
> 
> diff --git a/sysdeps/loongarch/Makefile b/sysdeps/loongarch/Makefile
> index 43d2f583cd..30a1f4a802 100644
> --- a/sysdeps/loongarch/Makefile
> +++ b/sysdeps/loongarch/Makefile
> @@ -6,6 +6,10 @@ ifeq ($(subdir),elf)
>  gen-as-const-headers += dl-link.sym
>  endif
>  
> +ifeq ($(subdir),elf)
> +  sysdep-dl-routines += dl-get-cpu-features
> +endif
> +
>  # LoongArch's assembler also needs to know about PIC as it changes the
>  # definition of some assembler macros.
>  ASFLAGS-.os += $(pic-ccflag)
> diff --git a/sysdeps/loongarch/Versions b/sysdeps/loongarch/Versions
> new file mode 100644
> index 0000000000..33ae2cc079
> --- /dev/null
> +++ b/sysdeps/loongarch/Versions
> @@ -0,0 +1,5 @@
> +ld {
> +  GLIBC_PRIVATE {
> +    _dl_larch_get_cpu_features;
> +  }
> +}
> diff --git a/sysdeps/loongarch/cpu-tunables.c b/sysdeps/loongarch/cpu-tunables.c
> new file mode 100644
> index 0000000000..8e9fab938b
> --- /dev/null
> +++ b/sysdeps/loongarch/cpu-tunables.c
> @@ -0,0 +1,89 @@
> +/* LoongArch CPU feature tuning.
> +   This file is part of the GNU C Library.
> +   Copyright (C) 2023 Free Software Foundation, Inc.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library; if not, see
> +   <http://www.gnu.org/licenses/>.  */
> +
> +# include <stdbool.h>
> +# include <stdint.h>
> +# include <unistd.h>		/* Get STDOUT_FILENO for _dl_printf.  */
> +# include <elf/dl-tunables.h>
> +# include <string.h>
> +# include <cpu-features.h>
> +# include <ldsodefs.h>
> +# include <sys/auxv.h>
> +
> +# define HWCAP_LOONGARCH_IFUNC \
> +  (HWCAP_LOONGARCH_UAL | HWCAP_LOONGARCH_LSX | HWCAP_LOONGARCH_LASX)
> +
> +# define CHECK_GLIBC_IFUNC_CPU_OFF(f, name, len)			\
> +  _Static_assert (sizeof (#name) - 1 == len, #name " != " #len);	\
> +  if (!memcmp (f, #name, len) &&					\
> +      (GLRO (dl_hwcap) & HWCAP_LOONGARCH_##name))			\
> +    {									\
> +      hwcap |= (HWCAP_LOONGARCH_##name | (~HWCAP_LOONGARCH_IFUNC));	\
> +      break;								\
> +    }									\
> +
> +attribute_hidden
> +void
> +TUNABLE_CALLBACK (set_hwcaps) (tunable_val_t *valp)
> +{
> +  const char *p = valp->strval;
> +  size_t len;
> +  unsigned long hwcap = 0;
> +  const char *c;
> +
> +  do {
> +      for (c = p; *c != ','; c++)
> +	if (*c == '\0')
> +	  break;
> +
> +      len = c - p;
> +
> +      switch(len)
> +      {
> +	default:
> +	  _dl_fatal_printf (
> +	    "The valid values of glibc.cpu.hwcaps is UAL, LASX, LSX!!\n"
> +			    );
> +	  break;
> +	case 3:
> +	  {
> +	    CHECK_GLIBC_IFUNC_CPU_OFF (p, LSX, 3);
> +	    CHECK_GLIBC_IFUNC_CPU_OFF (p, UAL, 3);
> +	    _dl_fatal_printf (
> +		"Some features are invalid or not supported on this machine!!\n"
> +		"The valid values of glibc.cpu.hwcaps is UAL, LASX, LSX!!\n"
> +                       );
> +	  }
> +	  break;
> +	case 4:
> +	  {
> +	    CHECK_GLIBC_IFUNC_CPU_OFF (p, LASX, 4);
> +	    _dl_fatal_printf (
> +		"Some features are invalid or not supported on this machine!!\n"
> +		"The valid values of glibc.cpu.hwcaps is UAL, LASX, LSX!!\n"
> +                       );
> +	  }
> +	  break;
> +      }
> +
> +      p += len + 1;
> +    }
> +  while (*c != '\0');
> +
> +  GLRO (dl_larch_cpu_features).hwcap &= hwcap;
> +}
> diff --git a/sysdeps/loongarch/dl-get-cpu-features.c b/sysdeps/loongarch/dl-get-cpu-features.c
> new file mode 100644
> index 0000000000..7cd9bc15c3
> --- /dev/null
> +++ b/sysdeps/loongarch/dl-get-cpu-features.c
> @@ -0,0 +1,25 @@
> +/* Define _dl_larch_get_cpu_features.
> +   Copyright (C) 2023 Free Software Foundation, Inc.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library; if not, see
> +   <https://www.gnu.org/licenses/>.  */
> +
> +
> +#include <ldsodefs.h>
> +
> +const struct cpu_features *
> +_dl_larch_get_cpu_features (void)
> +{
> +  return &GLRO(dl_larch_cpu_features);
> +}
> diff --git a/sysdeps/loongarch/dl-machine.h b/sysdeps/loongarch/dl-machine.h
> index 57913cefaa..b395a9283e 100644
> --- a/sysdeps/loongarch/dl-machine.h
> +++ b/sysdeps/loongarch/dl-machine.h
> @@ -29,6 +29,8 @@
>  #include <dl-static-tls.h>
>  #include <dl-machine-rel.h>
>  
> +#include <cpu-features.c>
> +
>  #ifndef _RTLD_PROLOGUE
>  # define _RTLD_PROLOGUE(entry)					\
>  	".globl\t" __STRING (entry) "\n\t"			\
> @@ -53,6 +55,23 @@
>  #define ELF_MACHINE_NO_REL 1
>  #define ELF_MACHINE_NO_RELA 0
>  
> +#define DL_PLATFORM_INIT dl_platform_init ()
> +
> +static inline void __attribute__ ((unused))
> +dl_platform_init (void)
> +{
> +  if (GLRO(dl_platform) != NULL && *GLRO(dl_platform) == '\0')
> +    /* Avoid an empty string which would disturb us.  */
> +    GLRO(dl_platform) = NULL;
> +
> +#ifdef SHARED
> +  /* init_cpu_features has been called early from __libc_start_main in
> +     static executable.  */
> +  init_cpu_features (&GLRO(dl_larch_cpu_features));
> +#endif
> +}
> +
> +
>  /* Return nonzero iff ELF header is compatible with the running host.  */
>  static inline int
>  elf_machine_matches_host (const ElfW (Ehdr) *ehdr)
> @@ -290,9 +309,9 @@ elf_machine_runtime_setup (struct link_map *l, struct r_scope_elem *scope[],
>        if (profile != 0)
>  	{
>  #if !defined __loongarch_soft_float
> -	  if (SUPPORT_LASX)
> +	  if (RTLD_SUPPORT_LASX)
>  	    gotplt[0] = (ElfW(Addr)) &_dl_runtime_profile_lasx;
> -	  else if (SUPPORT_LSX)
> +	  else if (RTLD_SUPPORT_LSX)
>  	    gotplt[0] = (ElfW(Addr)) &_dl_runtime_profile_lsx;
>  	  else
>  #endif
> @@ -310,9 +329,9 @@ elf_machine_runtime_setup (struct link_map *l, struct r_scope_elem *scope[],
>  	     indicated by the offset on the stack, and then jump to
>  	     the resolved address.  */
>  #if !defined __loongarch_soft_float
> -	  if (SUPPORT_LASX)
> +	  if (RTLD_SUPPORT_LASX)
>  	    gotplt[0] = (ElfW(Addr)) &_dl_runtime_resolve_lasx;
> -	  else if (SUPPORT_LSX)
> +	  else if (RTLD_SUPPORT_LSX)
>  	    gotplt[0] = (ElfW(Addr)) &_dl_runtime_resolve_lsx;
>  	  else
>  #endif
> diff --git a/sysdeps/loongarch/dl-tunables.list b/sysdeps/loongarch/dl-tunables.list
> new file mode 100644
> index 0000000000..66b3427516
> --- /dev/null
> +++ b/sysdeps/loongarch/dl-tunables.list
> @@ -0,0 +1,25 @@
> +# LoongArch specific tunables.
> +# Copyright (C) 2023 Free Software Foundation, Inc.
> +# This file is part of the GNU C Library.
> +
> +# The GNU C Library is free software; you can redistribute it and/or
> +# modify it under the terms of the GNU Lesser General Public
> +# License as published by the Free Software Foundation; either
> +# version 2.1 of the License, or (at your option) any later version.
> +
> +# The GNU C Library is distributed in the hope that it will be useful,
> +# but WITHOUT ANY WARRANTY; without even the implied warranty of
> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +# Lesser General Public License for more details.
> +
> +# You should have received a copy of the GNU Lesser General Public
> +# License along with the GNU C Library; if not, see
> +# <http://www.gnu.org/licenses/>.
> +
> +glibc {
> +  cpu {
> +    hwcaps {
> +      type: STRING
> +    }
> +  }
> +}
> diff --git a/sysdeps/unix/sysv/linux/loongarch/cpu-features.c b/sysdeps/unix/sysv/linux/loongarch/cpu-features.c
> new file mode 100644
> index 0000000000..1290c4ce9f
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/loongarch/cpu-features.c
> @@ -0,0 +1,29 @@
> +/* Initialize CPU feature data.  LoongArch64 version.
> +   This file is part of the GNU C Library.
> +   Copyright (C) 2023 Free Software Foundation, Inc.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library; if not, see
> +   <http://www.gnu.org/licenses/>.  */
> +
> +#include <cpu-features.h>
> +#include <elf/dl-hwcaps.h>
> +#include <elf/dl-tunables.h>
> +extern void TUNABLE_CALLBACK (set_hwcaps) (tunable_val_t *) attribute_hidden;
> +
> +static inline void
> +init_cpu_features (struct cpu_features *cpu_features)
> +{
> +    GLRO (dl_larch_cpu_features).hwcap = GLRO (dl_hwcap);
> +    TUNABLE_GET (glibc, cpu, hwcaps, tunable_val_t *, TUNABLE_CALLBACK (set_hwcaps));
> +}
> diff --git a/sysdeps/unix/sysv/linux/loongarch/cpu-features.h b/sysdeps/unix/sysv/linux/loongarch/cpu-features.h
> index d1a280a5ee..450963cebc 100644
> --- a/sysdeps/unix/sysv/linux/loongarch/cpu-features.h
> +++ b/sysdeps/unix/sysv/linux/loongarch/cpu-features.h
> @@ -19,13 +19,23 @@
>  #ifndef _CPU_FEATURES_LOONGARCH64_H
>  #define _CPU_FEATURES_LOONGARCH64_H
>  
> +#include <stdint.h>
>  #include <sys/auxv.h>
>  
> -#define SUPPORT_UAL (GLRO (dl_hwcap) & HWCAP_LOONGARCH_UAL)
> -#define SUPPORT_LSX (GLRO (dl_hwcap) & HWCAP_LOONGARCH_LSX)
> -#define SUPPORT_LASX (GLRO (dl_hwcap) & HWCAP_LOONGARCH_LASX)
> +struct cpu_features
> + {
> +    uint64_t hwcap;
> + };
>  
> +/* Get a pointer to the CPU features structure.  */
> +extern const struct cpu_features *_dl_larch_get_cpu_features (void)
> +     __attribute__ ((pure));
> +
> +#define SUPPORT_UAL (GLRO (dl_larch_cpu_features).hwcap & HWCAP_LOONGARCH_UAL)
> +#define SUPPORT_LSX (GLRO (dl_larch_cpu_features).hwcap & HWCAP_LOONGARCH_LSX)
> +#define SUPPORT_LASX (GLRO (dl_larch_cpu_features).hwcap & HWCAP_LOONGARCH_LASX)
> +#define RTLD_SUPPORT_LSX (GLRO (dl_hwcap) & HWCAP_LOONGARCH_LSX)
> +#define RTLD_SUPPORT_LASX (GLRO (dl_hwcap) & HWCAP_LOONGARCH_LASX)
>  #define INIT_ARCH()
>  
>  #endif /* _CPU_FEATURES_LOONGARCH64_H  */
> -
> diff --git a/sysdeps/unix/sysv/linux/loongarch/dl-procinfo.c b/sysdeps/unix/sysv/linux/loongarch/dl-procinfo.c
> new file mode 100644
> index 0000000000..6217fda983
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/loongarch/dl-procinfo.c
> @@ -0,0 +1,60 @@
> +/* Data for LoongArch64 version of processor capability information.
> +   Linux version.
> +   Copyright (C) 2023 Free Software Foundation, Inc.
> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library; if not, see
> +   <http://www.gnu.org/licenses/>.  */
> +
> +/* If anything should be added here check whether the size of each string
> +   is still ok with the given array size.
> +
> +   All the #ifdefs in the definitions are quite irritating but
> +   necessary if we want to avoid duplicating the information.  There
> +   are three different modes:
> +
> +   - PROCINFO_DECL is defined.  This means we are only interested in
> +     declarations.
> +
> +   - PROCINFO_DECL is not defined:
> +
> +     + if SHARED is defined the file is included in an array
> +       initializer.  The .element = { ... } syntax is needed.
> +
> +     + if SHARED is not defined a normal array initialization is
> +       needed.
> +  */
> +
> +#ifndef PROCINFO_CLASS
> +# define PROCINFO_CLASS
> +#endif
> +
> +#if !IS_IN (ldconfig)
> +# if !defined PROCINFO_DECL && defined SHARED
> +  ._dl_larch_cpu_features
> +# else
> +PROCINFO_CLASS struct cpu_features _dl_larch_cpu_features
> +# endif
> +# ifndef PROCINFO_DECL
> += { }
> +# endif
> +# if !defined SHARED || defined PROCINFO_DECL
> +;
> +# else
> +,
> +# endif
> +#endif
> +
> +#undef PROCINFO_DECL
> +#undef PROCINFO_CLASS
> diff --git a/sysdeps/unix/sysv/linux/loongarch/dl-sysdep.c b/sysdeps/unix/sysv/linux/loongarch/dl-sysdep.c
> new file mode 100644
> index 0000000000..455fd71abc
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/loongarch/dl-sysdep.c
> @@ -0,0 +1,21 @@
> +/* Operating system support for run-time dynamic linker.  LoongArch version.
> +   Copyright (C) 2023 Free Software Foundation, Inc.
> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library; if not, see
> +   <http://www.gnu.org/licenses/>.  */
> +
> +#include <config.h>
> +#include <sysdeps/loongarch/cpu-tunables.c>
> +#include <sysdeps/unix/sysv/linux/dl-sysdep.c>
> diff --git a/sysdeps/unix/sysv/linux/loongarch/libc-start.c b/sysdeps/unix/sysv/linux/loongarch/libc-start.c
> new file mode 100644
> index 0000000000..f1346ece0a
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/loongarch/libc-start.c
> @@ -0,0 +1,34 @@
> +/* Override csu/libc-start.c on LoongArch64.
> +   Copyright (C) 2023 Free Software Foundation, Inc.
> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library; if not, see
> +   <http://www.gnu.org/licenses/>.  */
> +
> +#ifndef SHARED
> +
> +/* Mark symbols hidden in static PIE for early self relocation to work.  */
> +# if BUILD_PIE_DEFAULT
> +#  pragma GCC visibility push(hidden)
> +# endif
> +
> +# include <ldsodefs.h>
> +# include <cpu-features.c>
> +
> +extern struct cpu_features _dl_larch_cpu_features;
> +
> +# define ARCH_INIT_CPU_FEATURES() init_cpu_features (&_dl_larch_cpu_features)
> +
> +#endif
> +#include <csu/libc-start.c>
  
caiyinyu Sept. 20, 2023, 10:15 a.m. UTC | #3
在 2023/9/19 下午5:33, Adhemerval Zanella Netto 写道:
>
> On 17/09/23 06:48, caiyinyu wrote:
>> Key Points:
>> 1. On lasx & lsx platforms, We must use _dl_runtime_{profile, resolve}_{lsx, lasx}
>>     to save vector registers.
>> 2. Via "tunables", users can choose str/mem_{lasx,lsx,unaligned} functions with
>>     `export GLIBC_TUNABLES=glibc.cpu.hwcaps=LASX,...`.
>>     Note: glibc.cpu.hwcaps doesn't affect _dl_runtime_{profile, resolve}_{lsx, lasx}
>>     selection.
>>
>> Usage Notes:
>> 1. Only valid inputs: LASX, LSX, UAL. Case-sensitive, comma-separated, no spaces.
>> 2. Example: `export GLIBC_TUNABLES=glibc.cpu.hwcaps=LASX,UAL` turns on LASX & UAL.
>>     Unmentioned features turn off. With default ifunc: lasx > lsx > unaligned >
>>     aligned > generic, effect is: lasx > unaligned > aligned > generic; lsx off.
>> 3. Incorrect GLIBC_TUNABLES settings will show error messages.
>>     For example: On lsx platforms, you cannot enable lasx features. If you do
>>     that, you will get error messages.
>> 4. Valid input examples:
>>     - GLIBC_TUNABLES=glibc.cpu.hwcaps=LASX: lasx > aligned > generic.
>>     - GLIBC_TUNABLES=glibc.cpu.hwcaps=LSX,UAL: lsx > unaligned > aligned > generic.
>>     - GLIBC_TUNABLES=glibc.cpu.hwcaps=LASX,UAL,LASX,UAL,LSX,LASX,UAL: Repetitions
>>       allowed but not recommended. Results in: lasx > lsx > unaligned > aligned >
>>       generic.
> This patch and a bunch other for Loongarch landed without any sort of
> review. I know that this mostly touch arch-specific code and in the end
> it would up to arch-maintaners to actually review and install this; but
> I also would be good to have at some some of minimum review from another
> loongarch maintaner.
>
> Below some comments, which should be catch by a proper review.

Thank you for the reminder. I will address these issues in the upcoming 
patch.

(More responses to follow.)

>
>> ---
>>   sysdeps/loongarch/Makefile                    |  4 +
>>   sysdeps/loongarch/Versions                    |  5 ++
>>   sysdeps/loongarch/cpu-tunables.c              | 89 +++++++++++++++++++
>>   sysdeps/loongarch/dl-get-cpu-features.c       | 25 ++++++
>>   sysdeps/loongarch/dl-machine.h                | 27 +++++-
>>   sysdeps/loongarch/dl-tunables.list            | 25 ++++++
>>   .../unix/sysv/linux/loongarch/cpu-features.c  | 29 ++++++
>>   .../unix/sysv/linux/loongarch/cpu-features.h  | 18 +++-
>>   .../unix/sysv/linux/loongarch/dl-procinfo.c   | 60 +++++++++++++
>>   sysdeps/unix/sysv/linux/loongarch/dl-sysdep.c | 21 +++++
>>   .../unix/sysv/linux/loongarch/libc-start.c    | 34 +++++++
>>   11 files changed, 329 insertions(+), 8 deletions(-)
>>   create mode 100644 sysdeps/loongarch/Versions
>>   create mode 100644 sysdeps/loongarch/cpu-tunables.c
>>   create mode 100644 sysdeps/loongarch/dl-get-cpu-features.c
>>   create mode 100644 sysdeps/loongarch/dl-tunables.list
>>   create mode 100644 sysdeps/unix/sysv/linux/loongarch/cpu-features.c
>>   create mode 100644 sysdeps/unix/sysv/linux/loongarch/dl-procinfo.c
>>   create mode 100644 sysdeps/unix/sysv/linux/loongarch/dl-sysdep.c
>>   create mode 100644 sysdeps/unix/sysv/linux/loongarch/libc-start.c
>>
>> diff --git a/sysdeps/loongarch/Makefile b/sysdeps/loongarch/Makefile
>> index 43d2f583cd..30a1f4a802 100644
>> --- a/sysdeps/loongarch/Makefile
>> +++ b/sysdeps/loongarch/Makefile
>> @@ -6,6 +6,10 @@ ifeq ($(subdir),elf)
>>   gen-as-const-headers += dl-link.sym
>>   endif
>>   
>> +ifeq ($(subdir),elf)
>> +  sysdep-dl-routines += dl-get-cpu-features
> No need of double-space and move the entry to a new line:
>
> sysdep-dl-routines += \
>    dl-get-cpu-features \
>    # sysdep-dl-routines
>
>> +endif
>> +
>>   # LoongArch's assembler also needs to know about PIC as it changes the
>>   # definition of some assembler macros.
>>   ASFLAGS-.os += $(pic-ccflag)
>> diff --git a/sysdeps/loongarch/Versions b/sysdeps/loongarch/Versions
>> new file mode 100644
>> index 0000000000..33ae2cc079
>> --- /dev/null
>> +++ b/sysdeps/loongarch/Versions
>> @@ -0,0 +1,5 @@
>> +ld {
>> +  GLIBC_PRIVATE {
>> +    _dl_larch_get_cpu_features;
>> +  }
>> +}
> This file is not need, libc.so does not reference _dl_larch_get_cpu_features.
>
>> diff --git a/sysdeps/loongarch/cpu-tunables.c b/sysdeps/loongarch/cpu-tunables.c
>> new file mode 100644
>> index 0000000000..8e9fab938b
>> --- /dev/null
>> +++ b/sysdeps/loongarch/cpu-tunables.c
>> @@ -0,0 +1,89 @@
>> +/* LoongArch CPU feature tuning.
>> +   This file is part of the GNU C Library.
>> +   Copyright (C) 2023 Free Software Foundation, Inc.
>> +
>> +   The GNU C Library is free software; you can redistribute it and/or
>> +   modify it under the terms of the GNU Lesser General Public
>> +   License as published by the Free Software Foundation; either
>> +   version 2.1 of the License, or (at your option) any later version.
>> +
>> +   The GNU C Library is distributed in the hope that it will be useful,
>> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
>> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>> +   Lesser General Public License for more details.
>> +
>> +   You should have received a copy of the GNU Lesser General Public
>> +   License along with the GNU C Library; if not, see
>> +   <http://www.gnu.org/licenses/>.  */
>> +
>> +# include <stdbool.h>
>> +# include <stdint.h>
>> +# include <unistd.h>		/* Get STDOUT_FILENO for _dl_printf.  */
>> +# include <elf/dl-tunables.h>
>> +# include <string.h>
>> +# include <cpu-features.h>
>> +# include <ldsodefs.h>
>> +# include <sys/auxv.h>
>> +
>> +# define HWCAP_LOONGARCH_IFUNC \
>> +  (HWCAP_LOONGARCH_UAL | HWCAP_LOONGARCH_LSX | HWCAP_LOONGARCH_LASX)
>> +
>> +# define CHECK_GLIBC_IFUNC_CPU_OFF(f, name, len)			\
>> +  _Static_assert (sizeof (#name) - 1 == len, #name " != " #len);	\
>> +  if (!memcmp (f, #name, len) &&					\
> Use memcmp (...) == 0.
>
>> +      (GLRO (dl_hwcap) & HWCAP_LOONGARCH_##name))			\
>> +    {									\
>> +      hwcap |= (HWCAP_LOONGARCH_##name | (~HWCAP_LOONGARCH_IFUNC));	\
>> +      break;								\
>> +    }									\
>> +
>> +attribute_hidden
>> +void
>> +TUNABLE_CALLBACK (set_hwcaps) (tunable_val_t *valp)
>> +{
> Maybe add a comment, similar to s390 and x86_64, on how the GLIBC_TUNABLES
> should behave regarding parsing here.  The powerpc and s390 allows the
> setup of disable a hwcap tunable by appending '-', as:
>
>    GLIBC_TUNABLES=glibc.cpu.hwcaps=-xxx,yyy,zzz,....

The only valid input of " glibc.cpu.hwcaps " are: LASX LSX UAL which i 
mentioned in

comimt message "Usage Notes" parts. "-" and "+" are not allowed.

If you set GLIBC_TUNABLES=glibc.cpu.hwcaps=UAL on the lasx platform,

which supports all three features, the other features will be disabled.

     Usage Notes:
     1. Only valid inputs: LASX, LSX, UAL. Case-sensitive, 
comma-separated, no spaces.
     2. Example: `export GLIBC_TUNABLES=glibc.cpu.hwcaps=LASX,UAL` turns 
on LASX & UAL.
*Unmentioned features turn off.* With default ifunc: lasx > lsx > 
unaligned >
        aligned > generic, effect is: lasx > unaligned > aligned > 
generic; lsx off.
     3. Incorrect GLIBC_TUNABLES settings will show error messages.
        For example: On lsx platforms, you cannot enable lasx features. 
If you do
        that, you will get error messages.
     4. Valid input examples:
        - GLIBC_TUNABLES=glibc.cpu.hwcaps=LASX:  lasx > aligned > generic.
        - GLIBC_TUNABLES=glibc.cpu.hwcaps=LSX,UAL:  lsx > unaligned > 
aligned > generic.
        - 
GLIBC_TUNABLES=glibc.cpu.hwcaps=LASX,UAL,LASX,UAL,LSX,LASX,UAL: Repetitions
          allowed but not recommended. Results in:  lasx > lsx > 
unaligned > aligned >
          generic.


>
> And it not clear how loongarch will handle.  If I understand correclty,
> setting:
>
>    GLIBC_TUNABLES=glibc.cpu.hwcaps=LSX
>
> will set the 'hwcap' to HWCAP_LOONGARCH_UAL | HWCAP_LOONGARCH_LSX | HWCAP_LOONGARCH_LASX)
> because CHECK_GLIBC_IFUNC_CPU_OFF 'or' everything (which does not seem
> correct).

hwcap is just an intermediate temporary variable used to validate the 
input and collect valid features from it.

Note the following:

+
+      p += len + 1;
+    }
+  while (*c != '\0');
+
+  GLRO (dl_larch_cpu_features).hwcap &= hwcap;
+}


>
> So I would expect that it would follow what powerpc/s390 does, so
> we could eventually consolidate this code.
>
>> +  const char *p = valp->strval;
>> +  size_t len;
>> +  unsigned long hwcap = 0;
>> +  const char *c;
>> +
>> +  do {
> Put the bracet on a newline.
>
>> +      for (c = p; *c != ','; c++)
>> +	if (*c == '\0')
>> +	  break;
>> +
>> +      len = c - p;
>> +
>> +      switch(len)
> Space after 'switch'.
>
>> +      {
>> +	default:
>> +	  _dl_fatal_printf (
>> +	    "The valid values of glibc.cpu.hwcaps is UAL, LASX, LSX!!\n"
>> +			    );
> I think the ');' should be on previou sline.
>
>> +	  break;
>> +	case 3:
>> +	  {
>> +	    CHECK_GLIBC_IFUNC_CPU_OFF (p, LSX, 3);
>> +	    CHECK_GLIBC_IFUNC_CPU_OFF (p, UAL, 3);
>> +	    _dl_fatal_printf (
>> +		"Some features are invalid or not supported on this machine!!\n"
>> +		"The valid values of glibc.cpu.hwcaps is UAL, LASX, LSX!!\n"
>> +                       );
>> +	  }
>> +	  break;
>> +	case 4:
>> +	  {
>> +	    CHECK_GLIBC_IFUNC_CPU_OFF (p, LASX, 4);
>> +	    _dl_fatal_printf (
>> +		"Some features are invalid or not supported on this machine!!\n"
>> +		"The valid values of glibc.cpu.hwcaps is UAL, LASX, LSX!!\n"
>> +                       );
>> +	  }
>> +	  break;
>> +      }
>> +
>> +      p += len + 1;
>> +    }
>> +  while (*c != '\0');
>> +
>> +  GLRO (dl_larch_cpu_features).hwcap &= hwcap;
>> +}
>> diff --git a/sysdeps/loongarch/dl-get-cpu-features.c b/sysdeps/loongarch/dl-get-cpu-features.c
>> new file mode 100644
>> index 0000000000..7cd9bc15c3
>> --- /dev/null
>> +++ b/sysdeps/loongarch/dl-get-cpu-features.c
>> @@ -0,0 +1,25 @@
>> +/* Define _dl_larch_get_cpu_features.
>> +   Copyright (C) 2023 Free Software Foundation, Inc.
>> +
>> +   The GNU C Library is free software; you can redistribute it and/or
>> +   modify it under the terms of the GNU Lesser General Public
>> +   License as published by the Free Software Foundation; either
>> +   version 2.1 of the License, or (at your option) any later version.
>> +
>> +   The GNU C Library is distributed in the hope that it will be useful,
>> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
>> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>> +   Lesser General Public License for more details.
>> +
>> +   You should have received a copy of the GNU Lesser General Public
>> +   License along with the GNU C Library; if not, see
>> +   <https://www.gnu.org/licenses/>.  */
>> +
>> +
>> +#include <ldsodefs.h>
>> +
>> +const struct cpu_features *
>> +_dl_larch_get_cpu_features (void)
>> +{
>> +  return &GLRO(dl_larch_cpu_features);
>> +}
>> diff --git a/sysdeps/loongarch/dl-machine.h b/sysdeps/loongarch/dl-machine.h
>> index 57913cefaa..b395a9283e 100644
>> --- a/sysdeps/loongarch/dl-machine.h
>> +++ b/sysdeps/loongarch/dl-machine.h
>> @@ -29,6 +29,8 @@
>>   #include <dl-static-tls.h>
>>   #include <dl-machine-rel.h>
>>   
>> +#include <cpu-features.c>
>> +
>>   #ifndef _RTLD_PROLOGUE
>>   # define _RTLD_PROLOGUE(entry)					\
>>   	".globl\t" __STRING (entry) "\n\t"			\
>> @@ -53,6 +55,23 @@
>>   #define ELF_MACHINE_NO_REL 1
>>   #define ELF_MACHINE_NO_RELA 0
>>   
>> +#define DL_PLATFORM_INIT dl_platform_init ()
>> +
>> +static inline void __attribute__ ((unused))
>> +dl_platform_init (void)
>> +{
>> +  if (GLRO(dl_platform) != NULL && *GLRO(dl_platform) == '\0')
>> +    /* Avoid an empty string which would disturb us.  */
>> +    GLRO(dl_platform) = NULL;
>> +
>> +#ifdef SHARED
>> +  /* init_cpu_features has been called early from __libc_start_main in
>> +     static executable.  */
>> +  init_cpu_features (&GLRO(dl_larch_cpu_features));
>> +#endif
>> +}
>> +
>> +
>>   /* Return nonzero iff ELF header is compatible with the running host.  */
>>   static inline int
>>   elf_machine_matches_host (const ElfW (Ehdr) *ehdr)
>> @@ -290,9 +309,9 @@ elf_machine_runtime_setup (struct link_map *l, struct r_scope_elem *scope[],
>>         if (profile != 0)
>>   	{
>>   #if !defined __loongarch_soft_float
>> -	  if (SUPPORT_LASX)
>> +	  if (RTLD_SUPPORT_LASX)
>>   	    gotplt[0] = (ElfW(Addr)) &_dl_runtime_profile_lasx;
>> -	  else if (SUPPORT_LSX)
>> +	  else if (RTLD_SUPPORT_LSX)
>>   	    gotplt[0] = (ElfW(Addr)) &_dl_runtime_profile_lsx;
>>   	  else
>>   #endif
>> @@ -310,9 +329,9 @@ elf_machine_runtime_setup (struct link_map *l, struct r_scope_elem *scope[],
>>   	     indicated by the offset on the stack, and then jump to
>>   	     the resolved address.  */
>>   #if !defined __loongarch_soft_float
>> -	  if (SUPPORT_LASX)
>> +	  if (RTLD_SUPPORT_LASX)
>>   	    gotplt[0] = (ElfW(Addr)) &_dl_runtime_resolve_lasx;
>> -	  else if (SUPPORT_LSX)
>> +	  else if (RTLD_SUPPORT_LSX)
>>   	    gotplt[0] = (ElfW(Addr)) &_dl_runtime_resolve_lsx;
>>   	  else
>>   #endif
>> diff --git a/sysdeps/loongarch/dl-tunables.list b/sysdeps/loongarch/dl-tunables.list
>> new file mode 100644
>> index 0000000000..66b3427516
>> --- /dev/null
>> +++ b/sysdeps/loongarch/dl-tunables.list
>> @@ -0,0 +1,25 @@
>> +# LoongArch specific tunables.
>> +# Copyright (C) 2023 Free Software Foundation, Inc.
>> +# This file is part of the GNU C Library.
>> +
>> +# The GNU C Library is free software; you can redistribute it and/or
>> +# modify it under the terms of the GNU Lesser General Public
>> +# License as published by the Free Software Foundation; either
>> +# version 2.1 of the License, or (at your option) any later version.
>> +
>> +# The GNU C Library is distributed in the hope that it will be useful,
>> +# but WITHOUT ANY WARRANTY; without even the implied warranty of
>> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>> +# Lesser General Public License for more details.
>> +
>> +# You should have received a copy of the GNU Lesser General Public
>> +# License along with the GNU C Library; if not, see
>> +# <http://www.gnu.org/licenses/>.
>> +
>> +glibc {
>> +  cpu {
>> +    hwcaps {
>> +      type: STRING
>> +    }
>> +  }
>> +}
>> diff --git a/sysdeps/unix/sysv/linux/loongarch/cpu-features.c b/sysdeps/unix/sysv/linux/loongarch/cpu-features.c
>> new file mode 100644
>> index 0000000000..1290c4ce9f
>> --- /dev/null
>> +++ b/sysdeps/unix/sysv/linux/loongarch/cpu-features.c
>> @@ -0,0 +1,29 @@
>> +/* Initialize CPU feature data.  LoongArch64 version.
>> +   This file is part of the GNU C Library.
>> +   Copyright (C) 2023 Free Software Foundation, Inc.
>> +
>> +   The GNU C Library is free software; you can redistribute it and/or
>> +   modify it under the terms of the GNU Lesser General Public
>> +   License as published by the Free Software Foundation; either
>> +   version 2.1 of the License, or (at your option) any later version.
>> +
>> +   The GNU C Library is distributed in the hope that it will be useful,
>> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
>> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>> +   Lesser General Public License for more details.
>> +
>> +   You should have received a copy of the GNU Lesser General Public
>> +   License along with the GNU C Library; if not, see
>> +   <http://www.gnu.org/licenses/>.  */
>> +
>> +#include <cpu-features.h>
>> +#include <elf/dl-hwcaps.h>
>> +#include <elf/dl-tunables.h>
>> +extern void TUNABLE_CALLBACK (set_hwcaps) (tunable_val_t *) attribute_hidden;
>> +
>> +static inline void
>> +init_cpu_features (struct cpu_features *cpu_features)
>> +{
>> +    GLRO (dl_larch_cpu_features).hwcap = GLRO (dl_hwcap);
>> +    TUNABLE_GET (glibc, cpu, hwcaps, tunable_val_t *, TUNABLE_CALLBACK (set_hwcaps));
> The initial space number seems odd here.
>
>> +}
>> diff --git a/sysdeps/unix/sysv/linux/loongarch/cpu-features.h b/sysdeps/unix/sysv/linux/loongarch/cpu-features.h
>> index d1a280a5ee..450963cebc 100644
>> --- a/sysdeps/unix/sysv/linux/loongarch/cpu-features.h
>> +++ b/sysdeps/unix/sysv/linux/loongarch/cpu-features.h
>> @@ -19,13 +19,23 @@
>>   #ifndef _CPU_FEATURES_LOONGARCH64_H
>>   #define _CPU_FEATURES_LOONGARCH64_H
>>   
>> +#include <stdint.h>
>>   #include <sys/auxv.h>
>>   
>> -#define SUPPORT_UAL (GLRO (dl_hwcap) & HWCAP_LOONGARCH_UAL)
>> -#define SUPPORT_LSX (GLRO (dl_hwcap) & HWCAP_LOONGARCH_LSX)
>> -#define SUPPORT_LASX (GLRO (dl_hwcap) & HWCAP_LOONGARCH_LASX)
>> +struct cpu_features
>> + {
>> +    uint64_t hwcap;
>> + };
> The indentation seems off here.
>
>>   
>> +/* Get a pointer to the CPU features structure.  */
>> +extern const struct cpu_features *_dl_larch_get_cpu_features (void)
>> +     __attribute__ ((pure));
>> +
>> +#define SUPPORT_UAL (GLRO (dl_larch_cpu_features).hwcap & HWCAP_LOONGARCH_UAL)
>> +#define SUPPORT_LSX (GLRO (dl_larch_cpu_features).hwcap & HWCAP_LOONGARCH_LSX)
>> +#define SUPPORT_LASX (GLRO (dl_larch_cpu_features).hwcap & HWCAP_LOONGARCH_LASX)
>> +#define RTLD_SUPPORT_LSX (GLRO (dl_hwcap) & HWCAP_LOONGARCH_LSX)
>> +#define RTLD_SUPPORT_LASX (GLRO (dl_hwcap) & HWCAP_LOONGARCH_LASX)
> For GLRO, it is considered a variable access to there is no need of space.
>
>>   #define INIT_ARCH()
>>   
>>   #endif /* _CPU_FEATURES_LOONGARCH64_H  */
>> -
>> diff --git a/sysdeps/unix/sysv/linux/loongarch/dl-procinfo.c b/sysdeps/unix/sysv/linux/loongarch/dl-procinfo.c
>> new file mode 100644
>> index 0000000000..6217fda983
>> --- /dev/null
>> +++ b/sysdeps/unix/sysv/linux/loongarch/dl-procinfo.c
>> @@ -0,0 +1,60 @@
>> +/* Data for LoongArch64 version of processor capability information.
>> +   Linux version.
>> +   Copyright (C) 2023 Free Software Foundation, Inc.
>> +   This file is part of the GNU C Library.
>> +
>> +   The GNU C Library is free software; you can redistribute it and/or
>> +   modify it under the terms of the GNU Lesser General Public
>> +   License as published by the Free Software Foundation; either
>> +   version 2.1 of the License, or (at your option) any later version.
>> +
>> +   The GNU C Library is distributed in the hope that it will be useful,
>> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
>> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>> +   Lesser General Public License for more details.
>> +
>> +   You should have received a copy of the GNU Lesser General Public
>> +   License along with the GNU C Library; if not, see
>> +   <http://www.gnu.org/licenses/>.  */
>> +
>> +/* If anything should be added here check whether the size of each string
>> +   is still ok with the given array size.
>> +
>> +   All the #ifdefs in the definitions are quite irritating but
>> +   necessary if we want to avoid duplicating the information.  There
>> +   are three different modes:
>> +
>> +   - PROCINFO_DECL is defined.  This means we are only interested in
>> +     declarations.
>> +
>> +   - PROCINFO_DECL is not defined:
>> +
>> +     + if SHARED is defined the file is included in an array
>> +       initializer.  The .element = { ... } syntax is needed.
>> +
>> +     + if SHARED is not defined a normal array initialization is
>> +       needed.
>> +  */
>> +
>> +#ifndef PROCINFO_CLASS
>> +# define PROCINFO_CLASS
>> +#endif
>> +
>> +#if !IS_IN (ldconfig)
>> +# if !defined PROCINFO_DECL && defined SHARED
>> +  ._dl_larch_cpu_features
>> +# else
>> +PROCINFO_CLASS struct cpu_features _dl_larch_cpu_features
>> +# endif
>> +# ifndef PROCINFO_DECL
>> += { }
>> +# endif
>> +# if !defined SHARED || defined PROCINFO_DECL
>> +;
>> +# else
>> +,
>> +# endif
>> +#endif
>> +
>> +#undef PROCINFO_DECL
>> +#undef PROCINFO_CLASS
>> diff --git a/sysdeps/unix/sysv/linux/loongarch/dl-sysdep.c b/sysdeps/unix/sysv/linux/loongarch/dl-sysdep.c
>> new file mode 100644
>> index 0000000000..455fd71abc
>> --- /dev/null
>> +++ b/sysdeps/unix/sysv/linux/loongarch/dl-sysdep.c
>> @@ -0,0 +1,21 @@
>> +/* Operating system support for run-time dynamic linker.  LoongArch version.
>> +   Copyright (C) 2023 Free Software Foundation, Inc.
>> +   This file is part of the GNU C Library.
>> +
>> +   The GNU C Library is free software; you can redistribute it and/or
>> +   modify it under the terms of the GNU Lesser General Public
>> +   License as published by the Free Software Foundation; either
>> +   version 2.1 of the License, or (at your option) any later version.
>> +
>> +   The GNU C Library is distributed in the hope that it will be useful,
>> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
>> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>> +   Lesser General Public License for more details.
>> +
>> +   You should have received a copy of the GNU Lesser General Public
>> +   License along with the GNU C Library; if not, see
>> +   <http://www.gnu.org/licenses/>.  */
>> +
>> +#include <config.h>
>> +#include <sysdeps/loongarch/cpu-tunables.c>
>> +#include <sysdeps/unix/sysv/linux/dl-sysdep.c>
>> diff --git a/sysdeps/unix/sysv/linux/loongarch/libc-start.c b/sysdeps/unix/sysv/linux/loongarch/libc-start.c
>> new file mode 100644
>> index 0000000000..f1346ece0a
>> --- /dev/null
>> +++ b/sysdeps/unix/sysv/linux/loongarch/libc-start.c
>> @@ -0,0 +1,34 @@
>> +/* Override csu/libc-start.c on LoongArch64.
>> +   Copyright (C) 2023 Free Software Foundation, Inc.
>> +   This file is part of the GNU C Library.
>> +
>> +   The GNU C Library is free software; you can redistribute it and/or
>> +   modify it under the terms of the GNU Lesser General Public
>> +   License as published by the Free Software Foundation; either
>> +   version 2.1 of the License, or (at your option) any later version.
>> +
>> +   The GNU C Library is distributed in the hope that it will be useful,
>> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
>> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>> +   Lesser General Public License for more details.
>> +
>> +   You should have received a copy of the GNU Lesser General Public
>> +   License along with the GNU C Library; if not, see
>> +   <http://www.gnu.org/licenses/>.  */
>> +
>> +#ifndef SHARED
>> +
>> +/* Mark symbols hidden in static PIE for early self relocation to work.  */
>> +# if BUILD_PIE_DEFAULT
>> +#  pragma GCC visibility push(hidden)
>> +# endif
>> +
>> +# include <ldsodefs.h>
>> +# include <cpu-features.c>
>> +
>> +extern struct cpu_features _dl_larch_cpu_features;
>> +
>> +# define ARCH_INIT_CPU_FEATURES() init_cpu_features (&_dl_larch_cpu_features)
>> +
>> +#endif
>> +#include <csu/libc-start.c>
> I think this patch misses a proper testcase, similar to one I suggested
> when powerpc added a similar support (check 21841f0d562f0e944c4d267a28cc3ebd19c847e9).
> Check sysdeps/unix/sysv/linux/powerpc/tst-hwcap-tunables.c on a way to
> proper check it.
I will add a proper testcase in the upcoming patch.
  
caiyinyu Sept. 20, 2023, 10:51 a.m. UTC | #4
在 2023/9/19 下午6:11, Xi Ruoyao 写道:
> By the way, GCC maintainers told me there may be future CPU models with
> LSX/LASX but without UAL.
Yes.
> And if I read our string functions correctly,
> the LSX/LASX ifuncs require UAL as well.
Yes.
> So we should only enable LSX
> and LASX if UAL is also available, or make these string functions depend
> on both LSX (LASX) and UAL.  Is this properly implemented now?

All lasx/lsx str/mem functions currently have only one assembly 
implementation.

Therefore, when you enable lasx/lsx, there is only one lasx/lsx option 
available, regardless of whether UAL is enabled or not.

However, we do not rule out the possibility of future alternative 
implementations for lasx/lsx.

At that time, a combination of other features may be required.

For example, both lasx and UAL would need to be enabled to select this 
new implementation.

We hope to meet the selection criteria for different function 
implementations through various combinations of these options.

>
> On Sun, 2023-09-17 at 17:48 +0800, caiyinyu wrote:
>> Key Points:
>> 1. On lasx & lsx platforms, We must use _dl_runtime_{profile, resolve}_{lsx, lasx}
>>     to save vector registers.
>> 2. Via "tunables", users can choose str/mem_{lasx,lsx,unaligned} functions with
>>     `export GLIBC_TUNABLES=glibc.cpu.hwcaps=LASX,...`.
>>     Note: glibc.cpu.hwcaps doesn't affect _dl_runtime_{profile, resolve}_{lsx, lasx}
>>     selection.
>>
>> Usage Notes:
>> 1. Only valid inputs: LASX, LSX, UAL. Case-sensitive, comma-separated, no spaces.
>> 2. Example: `export GLIBC_TUNABLES=glibc.cpu.hwcaps=LASX,UAL` turns on LASX & UAL.
>>     Unmentioned features turn off. With default ifunc: lasx > lsx > unaligned >
>>     aligned > generic, effect is: lasx > unaligned > aligned > generic; lsx off.
>> 3. Incorrect GLIBC_TUNABLES settings will show error messages.
>>     For example: On lsx platforms, you cannot enable lasx features. If you do
>>     that, you will get error messages.
>> 4. Valid input examples:
>>     - GLIBC_TUNABLES=glibc.cpu.hwcaps=LASX: lasx > aligned > generic.
>>     - GLIBC_TUNABLES=glibc.cpu.hwcaps=LSX,UAL: lsx > unaligned > aligned > generic.
>>     - GLIBC_TUNABLES=glibc.cpu.hwcaps=LASX,UAL,LASX,UAL,LSX,LASX,UAL: Repetitions
>>       allowed but not recommended. Results in: lasx > lsx > unaligned > aligned >
>>       generic.
>> ---
>>   sysdeps/loongarch/Makefile                    |  4 +
>>   sysdeps/loongarch/Versions                    |  5 ++
>>   sysdeps/loongarch/cpu-tunables.c              | 89 +++++++++++++++++++
>>   sysdeps/loongarch/dl-get-cpu-features.c       | 25 ++++++
>>   sysdeps/loongarch/dl-machine.h                | 27 +++++-
>>   sysdeps/loongarch/dl-tunables.list            | 25 ++++++
>>   .../unix/sysv/linux/loongarch/cpu-features.c  | 29 ++++++
>>   .../unix/sysv/linux/loongarch/cpu-features.h  | 18 +++-
>>   .../unix/sysv/linux/loongarch/dl-procinfo.c   | 60 +++++++++++++
>>   sysdeps/unix/sysv/linux/loongarch/dl-sysdep.c | 21 +++++
>>   .../unix/sysv/linux/loongarch/libc-start.c    | 34 +++++++
>>   11 files changed, 329 insertions(+), 8 deletions(-)
>>   create mode 100644 sysdeps/loongarch/Versions
>>   create mode 100644 sysdeps/loongarch/cpu-tunables.c
>>   create mode 100644 sysdeps/loongarch/dl-get-cpu-features.c
>>   create mode 100644 sysdeps/loongarch/dl-tunables.list
>>   create mode 100644 sysdeps/unix/sysv/linux/loongarch/cpu-features.c
>>   create mode 100644 sysdeps/unix/sysv/linux/loongarch/dl-procinfo.c
>>   create mode 100644 sysdeps/unix/sysv/linux/loongarch/dl-sysdep.c
>>   create mode 100644 sysdeps/unix/sysv/linux/loongarch/libc-start.c
>>
>> diff --git a/sysdeps/loongarch/Makefile b/sysdeps/loongarch/Makefile
>> index 43d2f583cd..30a1f4a802 100644
>> --- a/sysdeps/loongarch/Makefile
>> +++ b/sysdeps/loongarch/Makefile
>> @@ -6,6 +6,10 @@ ifeq ($(subdir),elf)
>>   gen-as-const-headers += dl-link.sym
>>   endif
>>   
>> +ifeq ($(subdir),elf)
>> +  sysdep-dl-routines += dl-get-cpu-features
>> +endif
>> +
>>   # LoongArch's assembler also needs to know about PIC as it changes the
>>   # definition of some assembler macros.
>>   ASFLAGS-.os += $(pic-ccflag)
>> diff --git a/sysdeps/loongarch/Versions b/sysdeps/loongarch/Versions
>> new file mode 100644
>> index 0000000000..33ae2cc079
>> --- /dev/null
>> +++ b/sysdeps/loongarch/Versions
>> @@ -0,0 +1,5 @@
>> +ld {
>> +  GLIBC_PRIVATE {
>> +    _dl_larch_get_cpu_features;
>> +  }
>> +}
>> diff --git a/sysdeps/loongarch/cpu-tunables.c b/sysdeps/loongarch/cpu-tunables.c
>> new file mode 100644
>> index 0000000000..8e9fab938b
>> --- /dev/null
>> +++ b/sysdeps/loongarch/cpu-tunables.c
>> @@ -0,0 +1,89 @@
>> +/* LoongArch CPU feature tuning.
>> +   This file is part of the GNU C Library.
>> +   Copyright (C) 2023 Free Software Foundation, Inc.
>> +
>> +   The GNU C Library is free software; you can redistribute it and/or
>> +   modify it under the terms of the GNU Lesser General Public
>> +   License as published by the Free Software Foundation; either
>> +   version 2.1 of the License, or (at your option) any later version.
>> +
>> +   The GNU C Library is distributed in the hope that it will be useful,
>> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
>> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>> +   Lesser General Public License for more details.
>> +
>> +   You should have received a copy of the GNU Lesser General Public
>> +   License along with the GNU C Library; if not, see
>> +   <http://www.gnu.org/licenses/>.  */
>> +
>> +# include <stdbool.h>
>> +# include <stdint.h>
>> +# include <unistd.h>		/* Get STDOUT_FILENO for _dl_printf.  */
>> +# include <elf/dl-tunables.h>
>> +# include <string.h>
>> +# include <cpu-features.h>
>> +# include <ldsodefs.h>
>> +# include <sys/auxv.h>
>> +
>> +# define HWCAP_LOONGARCH_IFUNC \
>> +  (HWCAP_LOONGARCH_UAL | HWCAP_LOONGARCH_LSX | HWCAP_LOONGARCH_LASX)
>> +
>> +# define CHECK_GLIBC_IFUNC_CPU_OFF(f, name, len)			\
>> +  _Static_assert (sizeof (#name) - 1 == len, #name " != " #len);	\
>> +  if (!memcmp (f, #name, len) &&					\
>> +      (GLRO (dl_hwcap) & HWCAP_LOONGARCH_##name))			\
>> +    {									\
>> +      hwcap |= (HWCAP_LOONGARCH_##name | (~HWCAP_LOONGARCH_IFUNC));	\
>> +      break;								\
>> +    }									\
>> +
>> +attribute_hidden
>> +void
>> +TUNABLE_CALLBACK (set_hwcaps) (tunable_val_t *valp)
>> +{
>> +  const char *p = valp->strval;
>> +  size_t len;
>> +  unsigned long hwcap = 0;
>> +  const char *c;
>> +
>> +  do {
>> +      for (c = p; *c != ','; c++)
>> +	if (*c == '\0')
>> +	  break;
>> +
>> +      len = c - p;
>> +
>> +      switch(len)
>> +      {
>> +	default:
>> +	  _dl_fatal_printf (
>> +	    "The valid values of glibc.cpu.hwcaps is UAL, LASX, LSX!!\n"
>> +			    );
>> +	  break;
>> +	case 3:
>> +	  {
>> +	    CHECK_GLIBC_IFUNC_CPU_OFF (p, LSX, 3);
>> +	    CHECK_GLIBC_IFUNC_CPU_OFF (p, UAL, 3);
>> +	    _dl_fatal_printf (
>> +		"Some features are invalid or not supported on this machine!!\n"
>> +		"The valid values of glibc.cpu.hwcaps is UAL, LASX, LSX!!\n"
>> +                       );
>> +	  }
>> +	  break;
>> +	case 4:
>> +	  {
>> +	    CHECK_GLIBC_IFUNC_CPU_OFF (p, LASX, 4);
>> +	    _dl_fatal_printf (
>> +		"Some features are invalid or not supported on this machine!!\n"
>> +		"The valid values of glibc.cpu.hwcaps is UAL, LASX, LSX!!\n"
>> +                       );
>> +	  }
>> +	  break;
>> +      }
>> +
>> +      p += len + 1;
>> +    }
>> +  while (*c != '\0');
>> +
>> +  GLRO (dl_larch_cpu_features).hwcap &= hwcap;
>> +}
>> diff --git a/sysdeps/loongarch/dl-get-cpu-features.c b/sysdeps/loongarch/dl-get-cpu-features.c
>> new file mode 100644
>> index 0000000000..7cd9bc15c3
>> --- /dev/null
>> +++ b/sysdeps/loongarch/dl-get-cpu-features.c
>> @@ -0,0 +1,25 @@
>> +/* Define _dl_larch_get_cpu_features.
>> +   Copyright (C) 2023 Free Software Foundation, Inc.
>> +
>> +   The GNU C Library is free software; you can redistribute it and/or
>> +   modify it under the terms of the GNU Lesser General Public
>> +   License as published by the Free Software Foundation; either
>> +   version 2.1 of the License, or (at your option) any later version.
>> +
>> +   The GNU C Library is distributed in the hope that it will be useful,
>> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
>> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>> +   Lesser General Public License for more details.
>> +
>> +   You should have received a copy of the GNU Lesser General Public
>> +   License along with the GNU C Library; if not, see
>> +   <https://www.gnu.org/licenses/>.  */
>> +
>> +
>> +#include <ldsodefs.h>
>> +
>> +const struct cpu_features *
>> +_dl_larch_get_cpu_features (void)
>> +{
>> +  return &GLRO(dl_larch_cpu_features);
>> +}
>> diff --git a/sysdeps/loongarch/dl-machine.h b/sysdeps/loongarch/dl-machine.h
>> index 57913cefaa..b395a9283e 100644
>> --- a/sysdeps/loongarch/dl-machine.h
>> +++ b/sysdeps/loongarch/dl-machine.h
>> @@ -29,6 +29,8 @@
>>   #include <dl-static-tls.h>
>>   #include <dl-machine-rel.h>
>>   
>> +#include <cpu-features.c>
>> +
>>   #ifndef _RTLD_PROLOGUE
>>   # define _RTLD_PROLOGUE(entry)					\
>>   	".globl\t" __STRING (entry) "\n\t"			\
>> @@ -53,6 +55,23 @@
>>   #define ELF_MACHINE_NO_REL 1
>>   #define ELF_MACHINE_NO_RELA 0
>>   
>> +#define DL_PLATFORM_INIT dl_platform_init ()
>> +
>> +static inline void __attribute__ ((unused))
>> +dl_platform_init (void)
>> +{
>> +  if (GLRO(dl_platform) != NULL && *GLRO(dl_platform) == '\0')
>> +    /* Avoid an empty string which would disturb us.  */
>> +    GLRO(dl_platform) = NULL;
>> +
>> +#ifdef SHARED
>> +  /* init_cpu_features has been called early from __libc_start_main in
>> +     static executable.  */
>> +  init_cpu_features (&GLRO(dl_larch_cpu_features));
>> +#endif
>> +}
>> +
>> +
>>   /* Return nonzero iff ELF header is compatible with the running host.  */
>>   static inline int
>>   elf_machine_matches_host (const ElfW (Ehdr) *ehdr)
>> @@ -290,9 +309,9 @@ elf_machine_runtime_setup (struct link_map *l, struct r_scope_elem *scope[],
>>         if (profile != 0)
>>   	{
>>   #if !defined __loongarch_soft_float
>> -	  if (SUPPORT_LASX)
>> +	  if (RTLD_SUPPORT_LASX)
>>   	    gotplt[0] = (ElfW(Addr)) &_dl_runtime_profile_lasx;
>> -	  else if (SUPPORT_LSX)
>> +	  else if (RTLD_SUPPORT_LSX)
>>   	    gotplt[0] = (ElfW(Addr)) &_dl_runtime_profile_lsx;
>>   	  else
>>   #endif
>> @@ -310,9 +329,9 @@ elf_machine_runtime_setup (struct link_map *l, struct r_scope_elem *scope[],
>>   	     indicated by the offset on the stack, and then jump to
>>   	     the resolved address.  */
>>   #if !defined __loongarch_soft_float
>> -	  if (SUPPORT_LASX)
>> +	  if (RTLD_SUPPORT_LASX)
>>   	    gotplt[0] = (ElfW(Addr)) &_dl_runtime_resolve_lasx;
>> -	  else if (SUPPORT_LSX)
>> +	  else if (RTLD_SUPPORT_LSX)
>>   	    gotplt[0] = (ElfW(Addr)) &_dl_runtime_resolve_lsx;
>>   	  else
>>   #endif
>> diff --git a/sysdeps/loongarch/dl-tunables.list b/sysdeps/loongarch/dl-tunables.list
>> new file mode 100644
>> index 0000000000..66b3427516
>> --- /dev/null
>> +++ b/sysdeps/loongarch/dl-tunables.list
>> @@ -0,0 +1,25 @@
>> +# LoongArch specific tunables.
>> +# Copyright (C) 2023 Free Software Foundation, Inc.
>> +# This file is part of the GNU C Library.
>> +
>> +# The GNU C Library is free software; you can redistribute it and/or
>> +# modify it under the terms of the GNU Lesser General Public
>> +# License as published by the Free Software Foundation; either
>> +# version 2.1 of the License, or (at your option) any later version.
>> +
>> +# The GNU C Library is distributed in the hope that it will be useful,
>> +# but WITHOUT ANY WARRANTY; without even the implied warranty of
>> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>> +# Lesser General Public License for more details.
>> +
>> +# You should have received a copy of the GNU Lesser General Public
>> +# License along with the GNU C Library; if not, see
>> +# <http://www.gnu.org/licenses/>.
>> +
>> +glibc {
>> +  cpu {
>> +    hwcaps {
>> +      type: STRING
>> +    }
>> +  }
>> +}
>> diff --git a/sysdeps/unix/sysv/linux/loongarch/cpu-features.c b/sysdeps/unix/sysv/linux/loongarch/cpu-features.c
>> new file mode 100644
>> index 0000000000..1290c4ce9f
>> --- /dev/null
>> +++ b/sysdeps/unix/sysv/linux/loongarch/cpu-features.c
>> @@ -0,0 +1,29 @@
>> +/* Initialize CPU feature data.  LoongArch64 version.
>> +   This file is part of the GNU C Library.
>> +   Copyright (C) 2023 Free Software Foundation, Inc.
>> +
>> +   The GNU C Library is free software; you can redistribute it and/or
>> +   modify it under the terms of the GNU Lesser General Public
>> +   License as published by the Free Software Foundation; either
>> +   version 2.1 of the License, or (at your option) any later version.
>> +
>> +   The GNU C Library is distributed in the hope that it will be useful,
>> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
>> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>> +   Lesser General Public License for more details.
>> +
>> +   You should have received a copy of the GNU Lesser General Public
>> +   License along with the GNU C Library; if not, see
>> +   <http://www.gnu.org/licenses/>.  */
>> +
>> +#include <cpu-features.h>
>> +#include <elf/dl-hwcaps.h>
>> +#include <elf/dl-tunables.h>
>> +extern void TUNABLE_CALLBACK (set_hwcaps) (tunable_val_t *) attribute_hidden;
>> +
>> +static inline void
>> +init_cpu_features (struct cpu_features *cpu_features)
>> +{
>> +    GLRO (dl_larch_cpu_features).hwcap = GLRO (dl_hwcap);
>> +    TUNABLE_GET (glibc, cpu, hwcaps, tunable_val_t *, TUNABLE_CALLBACK (set_hwcaps));
>> +}
>> diff --git a/sysdeps/unix/sysv/linux/loongarch/cpu-features.h b/sysdeps/unix/sysv/linux/loongarch/cpu-features.h
>> index d1a280a5ee..450963cebc 100644
>> --- a/sysdeps/unix/sysv/linux/loongarch/cpu-features.h
>> +++ b/sysdeps/unix/sysv/linux/loongarch/cpu-features.h
>> @@ -19,13 +19,23 @@
>>   #ifndef _CPU_FEATURES_LOONGARCH64_H
>>   #define _CPU_FEATURES_LOONGARCH64_H
>>   
>> +#include <stdint.h>
>>   #include <sys/auxv.h>
>>   
>> -#define SUPPORT_UAL (GLRO (dl_hwcap) & HWCAP_LOONGARCH_UAL)
>> -#define SUPPORT_LSX (GLRO (dl_hwcap) & HWCAP_LOONGARCH_LSX)
>> -#define SUPPORT_LASX (GLRO (dl_hwcap) & HWCAP_LOONGARCH_LASX)
>> +struct cpu_features
>> + {
>> +    uint64_t hwcap;
>> + };
>>   
>> +/* Get a pointer to the CPU features structure.  */
>> +extern const struct cpu_features *_dl_larch_get_cpu_features (void)
>> +     __attribute__ ((pure));
>> +
>> +#define SUPPORT_UAL (GLRO (dl_larch_cpu_features).hwcap & HWCAP_LOONGARCH_UAL)
>> +#define SUPPORT_LSX (GLRO (dl_larch_cpu_features).hwcap & HWCAP_LOONGARCH_LSX)
>> +#define SUPPORT_LASX (GLRO (dl_larch_cpu_features).hwcap & HWCAP_LOONGARCH_LASX)
>> +#define RTLD_SUPPORT_LSX (GLRO (dl_hwcap) & HWCAP_LOONGARCH_LSX)
>> +#define RTLD_SUPPORT_LASX (GLRO (dl_hwcap) & HWCAP_LOONGARCH_LASX)
>>   #define INIT_ARCH()
>>   
>>   #endif /* _CPU_FEATURES_LOONGARCH64_H  */
>> -
>> diff --git a/sysdeps/unix/sysv/linux/loongarch/dl-procinfo.c b/sysdeps/unix/sysv/linux/loongarch/dl-procinfo.c
>> new file mode 100644
>> index 0000000000..6217fda983
>> --- /dev/null
>> +++ b/sysdeps/unix/sysv/linux/loongarch/dl-procinfo.c
>> @@ -0,0 +1,60 @@
>> +/* Data for LoongArch64 version of processor capability information.
>> +   Linux version.
>> +   Copyright (C) 2023 Free Software Foundation, Inc.
>> +   This file is part of the GNU C Library.
>> +
>> +   The GNU C Library is free software; you can redistribute it and/or
>> +   modify it under the terms of the GNU Lesser General Public
>> +   License as published by the Free Software Foundation; either
>> +   version 2.1 of the License, or (at your option) any later version.
>> +
>> +   The GNU C Library is distributed in the hope that it will be useful,
>> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
>> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>> +   Lesser General Public License for more details.
>> +
>> +   You should have received a copy of the GNU Lesser General Public
>> +   License along with the GNU C Library; if not, see
>> +   <http://www.gnu.org/licenses/>.  */
>> +
>> +/* If anything should be added here check whether the size of each string
>> +   is still ok with the given array size.
>> +
>> +   All the #ifdefs in the definitions are quite irritating but
>> +   necessary if we want to avoid duplicating the information.  There
>> +   are three different modes:
>> +
>> +   - PROCINFO_DECL is defined.  This means we are only interested in
>> +     declarations.
>> +
>> +   - PROCINFO_DECL is not defined:
>> +
>> +     + if SHARED is defined the file is included in an array
>> +       initializer.  The .element = { ... } syntax is needed.
>> +
>> +     + if SHARED is not defined a normal array initialization is
>> +       needed.
>> +  */
>> +
>> +#ifndef PROCINFO_CLASS
>> +# define PROCINFO_CLASS
>> +#endif
>> +
>> +#if !IS_IN (ldconfig)
>> +# if !defined PROCINFO_DECL && defined SHARED
>> +  ._dl_larch_cpu_features
>> +# else
>> +PROCINFO_CLASS struct cpu_features _dl_larch_cpu_features
>> +# endif
>> +# ifndef PROCINFO_DECL
>> += { }
>> +# endif
>> +# if !defined SHARED || defined PROCINFO_DECL
>> +;
>> +# else
>> +,
>> +# endif
>> +#endif
>> +
>> +#undef PROCINFO_DECL
>> +#undef PROCINFO_CLASS
>> diff --git a/sysdeps/unix/sysv/linux/loongarch/dl-sysdep.c b/sysdeps/unix/sysv/linux/loongarch/dl-sysdep.c
>> new file mode 100644
>> index 0000000000..455fd71abc
>> --- /dev/null
>> +++ b/sysdeps/unix/sysv/linux/loongarch/dl-sysdep.c
>> @@ -0,0 +1,21 @@
>> +/* Operating system support for run-time dynamic linker.  LoongArch version.
>> +   Copyright (C) 2023 Free Software Foundation, Inc.
>> +   This file is part of the GNU C Library.
>> +
>> +   The GNU C Library is free software; you can redistribute it and/or
>> +   modify it under the terms of the GNU Lesser General Public
>> +   License as published by the Free Software Foundation; either
>> +   version 2.1 of the License, or (at your option) any later version.
>> +
>> +   The GNU C Library is distributed in the hope that it will be useful,
>> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
>> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>> +   Lesser General Public License for more details.
>> +
>> +   You should have received a copy of the GNU Lesser General Public
>> +   License along with the GNU C Library; if not, see
>> +   <http://www.gnu.org/licenses/>.  */
>> +
>> +#include <config.h>
>> +#include <sysdeps/loongarch/cpu-tunables.c>
>> +#include <sysdeps/unix/sysv/linux/dl-sysdep.c>
>> diff --git a/sysdeps/unix/sysv/linux/loongarch/libc-start.c b/sysdeps/unix/sysv/linux/loongarch/libc-start.c
>> new file mode 100644
>> index 0000000000..f1346ece0a
>> --- /dev/null
>> +++ b/sysdeps/unix/sysv/linux/loongarch/libc-start.c
>> @@ -0,0 +1,34 @@
>> +/* Override csu/libc-start.c on LoongArch64.
>> +   Copyright (C) 2023 Free Software Foundation, Inc.
>> +   This file is part of the GNU C Library.
>> +
>> +   The GNU C Library is free software; you can redistribute it and/or
>> +   modify it under the terms of the GNU Lesser General Public
>> +   License as published by the Free Software Foundation; either
>> +   version 2.1 of the License, or (at your option) any later version.
>> +
>> +   The GNU C Library is distributed in the hope that it will be useful,
>> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
>> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>> +   Lesser General Public License for more details.
>> +
>> +   You should have received a copy of the GNU Lesser General Public
>> +   License along with the GNU C Library; if not, see
>> +   <http://www.gnu.org/licenses/>.  */
>> +
>> +#ifndef SHARED
>> +
>> +/* Mark symbols hidden in static PIE for early self relocation to work.  */
>> +# if BUILD_PIE_DEFAULT
>> +#  pragma GCC visibility push(hidden)
>> +# endif
>> +
>> +# include <ldsodefs.h>
>> +# include <cpu-features.c>
>> +
>> +extern struct cpu_features _dl_larch_cpu_features;
>> +
>> +# define ARCH_INIT_CPU_FEATURES() init_cpu_features (&_dl_larch_cpu_features)
>> +
>> +#endif
>> +#include <csu/libc-start.c>
  
caiyinyu Sept. 20, 2023, 11:53 a.m. UTC | #5
在 2023/9/20 下午6:51, caiyinyu 写道:
>
> 在 2023/9/19 下午6:11, Xi Ruoyao 写道:
>> By the way, GCC maintainers told me there may be future CPU models with
>> LSX/LASX but without UAL.
> Yes.
>> And if I read our string functions correctly,
>> the LSX/LASX ifuncs require UAL as well.
> Yes.
>> So we should only enable LSX
>> and LASX if UAL is also available, or make these string functions depend
>> on both LSX (LASX) and UAL.  Is this properly implemented now?
>
> All lasx/lsx str/mem functions currently have only one assembly 
> implementation.
>
> Therefore, when you enable lasx/lsx, there is only one lasx/lsx option 
> available, regardless of whether UAL is enabled or not.
>
> However, we do not rule out the possibility of future alternative 
> implementations for lasx/lsx.
>
> At that time, a combination of other features may be required.
>
> For example, both lasx and UAL would need to be enabled to select this 
> new implementation.

My mistake here. What I mean is we need various combinations of these 
options to select the new implementation in future.

Therefore, the current implementation meets the criteria and allows for 
the addition of new function implementations.

As for "And if I read our string functions correctly, the LSX/LASX 
ifuncs require UAL as well." See:

...

diff --git a/sysdeps/loongarch/lp64/multiarch/ifunc-lasx.h 
b/sysdeps/loongarch/lp64/multiarch/ifunc-lasx.h
index 3be67da611..a496ff505d 100644
--- a/sysdeps/loongarch/lp64/multiarch/ifunc-lasx.h
+++ b/sysdeps/loongarch/lp64/multiarch/ifunc-lasx.h
@@ -32,7 +32,7 @@ static inline void *
  IFUNC_SELECTOR (void)
  {
  #if !defined __loongarch_soft_float
-  if (SUPPORT_LASX)
+  if (SUPPORT_LASX && SUPPORT_UAL)
      return OPTIMIZE (lasx);
    else if (SUPPORT_LSX)
      return OPTIMIZE (lsx);

....

>
> We hope to meet the selection criteria for different function 
> implementations through various combinations of these options.
>
>>
>> On Sun, 2023-09-17 at 17:48 +0800, caiyinyu wrote:
>>> Key Points:
>>> 1. On lasx & lsx platforms, We must use _dl_runtime_{profile, 
>>> resolve}_{lsx, lasx}
>>>     to save vector registers.
>>> 2. Via "tunables", users can choose str/mem_{lasx,lsx,unaligned} 
>>> functions with
>>>     `export GLIBC_TUNABLES=glibc.cpu.hwcaps=LASX,...`.
>>>     Note: glibc.cpu.hwcaps doesn't affect _dl_runtime_{profile, 
>>> resolve}_{lsx, lasx}
>>>     selection.
>>>
>>> Usage Notes:
>>> 1. Only valid inputs: LASX, LSX, UAL. Case-sensitive, 
>>> comma-separated, no spaces.
>>> 2. Example: `export GLIBC_TUNABLES=glibc.cpu.hwcaps=LASX,UAL` turns 
>>> on LASX & UAL.
>>>     Unmentioned features turn off. With default ifunc: lasx > lsx > 
>>> unaligned >
>>>     aligned > generic, effect is: lasx > unaligned > aligned > 
>>> generic; lsx off.
>>> 3. Incorrect GLIBC_TUNABLES settings will show error messages.
>>>     For example: On lsx platforms, you cannot enable lasx features. 
>>> If you do
>>>     that, you will get error messages.
>>> 4. Valid input examples:
>>>     - GLIBC_TUNABLES=glibc.cpu.hwcaps=LASX: lasx > aligned > generic.
>>>     - GLIBC_TUNABLES=glibc.cpu.hwcaps=LSX,UAL: lsx > unaligned > 
>>> aligned > generic.
>>>     - 
>>> GLIBC_TUNABLES=glibc.cpu.hwcaps=LASX,UAL,LASX,UAL,LSX,LASX,UAL: 
>>> Repetitions
>>>       allowed but not recommended. Results in: lasx > lsx > 
>>> unaligned > aligned >
>>>       generic.
>>> ---
>>>   sysdeps/loongarch/Makefile                    |  4 +
>>>   sysdeps/loongarch/Versions                    |  5 ++
>>>   sysdeps/loongarch/cpu-tunables.c              | 89 
>>> +++++++++++++++++++
>>>   sysdeps/loongarch/dl-get-cpu-features.c       | 25 ++++++
>>>   sysdeps/loongarch/dl-machine.h                | 27 +++++-
>>>   sysdeps/loongarch/dl-tunables.list            | 25 ++++++
>>>   .../unix/sysv/linux/loongarch/cpu-features.c  | 29 ++++++
>>>   .../unix/sysv/linux/loongarch/cpu-features.h  | 18 +++-
>>>   .../unix/sysv/linux/loongarch/dl-procinfo.c   | 60 +++++++++++++
>>>   sysdeps/unix/sysv/linux/loongarch/dl-sysdep.c | 21 +++++
>>>   .../unix/sysv/linux/loongarch/libc-start.c    | 34 +++++++
>>>   11 files changed, 329 insertions(+), 8 deletions(-)
>>>   create mode 100644 sysdeps/loongarch/Versions
>>>   create mode 100644 sysdeps/loongarch/cpu-tunables.c
>>>   create mode 100644 sysdeps/loongarch/dl-get-cpu-features.c
>>>   create mode 100644 sysdeps/loongarch/dl-tunables.list
>>>   create mode 100644 sysdeps/unix/sysv/linux/loongarch/cpu-features.c
>>>   create mode 100644 sysdeps/unix/sysv/linux/loongarch/dl-procinfo.c
>>>   create mode 100644 sysdeps/unix/sysv/linux/loongarch/dl-sysdep.c
>>>   create mode 100644 sysdeps/unix/sysv/linux/loongarch/libc-start.c
>>>
>>> diff --git a/sysdeps/loongarch/Makefile b/sysdeps/loongarch/Makefile
>>> index 43d2f583cd..30a1f4a802 100644
>>> --- a/sysdeps/loongarch/Makefile
>>> +++ b/sysdeps/loongarch/Makefile
>>> @@ -6,6 +6,10 @@ ifeq ($(subdir),elf)
>>>   gen-as-const-headers += dl-link.sym
>>>   endif
>>>   +ifeq ($(subdir),elf)
>>> +  sysdep-dl-routines += dl-get-cpu-features
>>> +endif
>>> +
>>>   # LoongArch's assembler also needs to know about PIC as it changes 
>>> the
>>>   # definition of some assembler macros.
>>>   ASFLAGS-.os += $(pic-ccflag)
>>> diff --git a/sysdeps/loongarch/Versions b/sysdeps/loongarch/Versions
>>> new file mode 100644
>>> index 0000000000..33ae2cc079
>>> --- /dev/null
>>> +++ b/sysdeps/loongarch/Versions
>>> @@ -0,0 +1,5 @@
>>> +ld {
>>> +  GLIBC_PRIVATE {
>>> +    _dl_larch_get_cpu_features;
>>> +  }
>>> +}
>>> diff --git a/sysdeps/loongarch/cpu-tunables.c 
>>> b/sysdeps/loongarch/cpu-tunables.c
>>> new file mode 100644
>>> index 0000000000..8e9fab938b
>>> --- /dev/null
>>> +++ b/sysdeps/loongarch/cpu-tunables.c
>>> @@ -0,0 +1,89 @@
>>> +/* LoongArch CPU feature tuning.
>>> +   This file is part of the GNU C Library.
>>> +   Copyright (C) 2023 Free Software Foundation, Inc.
>>> +
>>> +   The GNU C Library is free software; you can redistribute it and/or
>>> +   modify it under the terms of the GNU Lesser General Public
>>> +   License as published by the Free Software Foundation; either
>>> +   version 2.1 of the License, or (at your option) any later version.
>>> +
>>> +   The GNU C Library is distributed in the hope that it will be 
>>> useful,
>>> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
>>> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>>> +   Lesser General Public License for more details.
>>> +
>>> +   You should have received a copy of the GNU Lesser General Public
>>> +   License along with the GNU C Library; if not, see
>>> +   <http://www.gnu.org/licenses/>.  */
>>> +
>>> +# include <stdbool.h>
>>> +# include <stdint.h>
>>> +# include <unistd.h>        /* Get STDOUT_FILENO for _dl_printf.  */
>>> +# include <elf/dl-tunables.h>
>>> +# include <string.h>
>>> +# include <cpu-features.h>
>>> +# include <ldsodefs.h>
>>> +# include <sys/auxv.h>
>>> +
>>> +# define HWCAP_LOONGARCH_IFUNC \
>>> +  (HWCAP_LOONGARCH_UAL | HWCAP_LOONGARCH_LSX | HWCAP_LOONGARCH_LASX)
>>> +
>>> +# define CHECK_GLIBC_IFUNC_CPU_OFF(f, name, len)            \
>>> +  _Static_assert (sizeof (#name) - 1 == len, #name " != " #len);    \
>>> +  if (!memcmp (f, #name, len) &&                    \
>>> +      (GLRO (dl_hwcap) & HWCAP_LOONGARCH_##name))            \
>>> +    {                                    \
>>> +      hwcap |= (HWCAP_LOONGARCH_##name | 
>>> (~HWCAP_LOONGARCH_IFUNC));    \
>>> +      break;                                \
>>> +    }                                    \
>>> +
>>> +attribute_hidden
>>> +void
>>> +TUNABLE_CALLBACK (set_hwcaps) (tunable_val_t *valp)
>>> +{
>>> +  const char *p = valp->strval;
>>> +  size_t len;
>>> +  unsigned long hwcap = 0;
>>> +  const char *c;
>>> +
>>> +  do {
>>> +      for (c = p; *c != ','; c++)
>>> +    if (*c == '\0')
>>> +      break;
>>> +
>>> +      len = c - p;
>>> +
>>> +      switch(len)
>>> +      {
>>> +    default:
>>> +      _dl_fatal_printf (
>>> +        "The valid values of glibc.cpu.hwcaps is UAL, LASX, LSX!!\n"
>>> +                );
>>> +      break;
>>> +    case 3:
>>> +      {
>>> +        CHECK_GLIBC_IFUNC_CPU_OFF (p, LSX, 3);
>>> +        CHECK_GLIBC_IFUNC_CPU_OFF (p, UAL, 3);
>>> +        _dl_fatal_printf (
>>> +        "Some features are invalid or not supported on this 
>>> machine!!\n"
>>> +        "The valid values of glibc.cpu.hwcaps is UAL, LASX, LSX!!\n"
>>> +                       );
>>> +      }
>>> +      break;
>>> +    case 4:
>>> +      {
>>> +        CHECK_GLIBC_IFUNC_CPU_OFF (p, LASX, 4);
>>> +        _dl_fatal_printf (
>>> +        "Some features are invalid or not supported on this 
>>> machine!!\n"
>>> +        "The valid values of glibc.cpu.hwcaps is UAL, LASX, LSX!!\n"
>>> +                       );
>>> +      }
>>> +      break;
>>> +      }
>>> +
>>> +      p += len + 1;
>>> +    }
>>> +  while (*c != '\0');
>>> +
>>> +  GLRO (dl_larch_cpu_features).hwcap &= hwcap;
>>> +}
>>> diff --git a/sysdeps/loongarch/dl-get-cpu-features.c 
>>> b/sysdeps/loongarch/dl-get-cpu-features.c
>>> new file mode 100644
>>> index 0000000000..7cd9bc15c3
>>> --- /dev/null
>>> +++ b/sysdeps/loongarch/dl-get-cpu-features.c
>>> @@ -0,0 +1,25 @@
>>> +/* Define _dl_larch_get_cpu_features.
>>> +   Copyright (C) 2023 Free Software Foundation, Inc.
>>> +
>>> +   The GNU C Library is free software; you can redistribute it and/or
>>> +   modify it under the terms of the GNU Lesser General Public
>>> +   License as published by the Free Software Foundation; either
>>> +   version 2.1 of the License, or (at your option) any later version.
>>> +
>>> +   The GNU C Library is distributed in the hope that it will be 
>>> useful,
>>> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
>>> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>>> +   Lesser General Public License for more details.
>>> +
>>> +   You should have received a copy of the GNU Lesser General Public
>>> +   License along with the GNU C Library; if not, see
>>> +   <https://www.gnu.org/licenses/>.  */
>>> +
>>> +
>>> +#include <ldsodefs.h>
>>> +
>>> +const struct cpu_features *
>>> +_dl_larch_get_cpu_features (void)
>>> +{
>>> +  return &GLRO(dl_larch_cpu_features);
>>> +}
>>> diff --git a/sysdeps/loongarch/dl-machine.h 
>>> b/sysdeps/loongarch/dl-machine.h
>>> index 57913cefaa..b395a9283e 100644
>>> --- a/sysdeps/loongarch/dl-machine.h
>>> +++ b/sysdeps/loongarch/dl-machine.h
>>> @@ -29,6 +29,8 @@
>>>   #include <dl-static-tls.h>
>>>   #include <dl-machine-rel.h>
>>>   +#include <cpu-features.c>
>>> +
>>>   #ifndef _RTLD_PROLOGUE
>>>   # define _RTLD_PROLOGUE(entry)                    \
>>>       ".globl\t" __STRING (entry) "\n\t"            \
>>> @@ -53,6 +55,23 @@
>>>   #define ELF_MACHINE_NO_REL 1
>>>   #define ELF_MACHINE_NO_RELA 0
>>>   +#define DL_PLATFORM_INIT dl_platform_init ()
>>> +
>>> +static inline void __attribute__ ((unused))
>>> +dl_platform_init (void)
>>> +{
>>> +  if (GLRO(dl_platform) != NULL && *GLRO(dl_platform) == '\0')
>>> +    /* Avoid an empty string which would disturb us.  */
>>> +    GLRO(dl_platform) = NULL;
>>> +
>>> +#ifdef SHARED
>>> +  /* init_cpu_features has been called early from __libc_start_main in
>>> +     static executable.  */
>>> +  init_cpu_features (&GLRO(dl_larch_cpu_features));
>>> +#endif
>>> +}
>>> +
>>> +
>>>   /* Return nonzero iff ELF header is compatible with the running 
>>> host.  */
>>>   static inline int
>>>   elf_machine_matches_host (const ElfW (Ehdr) *ehdr)
>>> @@ -290,9 +309,9 @@ elf_machine_runtime_setup (struct link_map *l, 
>>> struct r_scope_elem *scope[],
>>>         if (profile != 0)
>>>       {
>>>   #if !defined __loongarch_soft_float
>>> -      if (SUPPORT_LASX)
>>> +      if (RTLD_SUPPORT_LASX)
>>>           gotplt[0] = (ElfW(Addr)) &_dl_runtime_profile_lasx;
>>> -      else if (SUPPORT_LSX)
>>> +      else if (RTLD_SUPPORT_LSX)
>>>           gotplt[0] = (ElfW(Addr)) &_dl_runtime_profile_lsx;
>>>         else
>>>   #endif
>>> @@ -310,9 +329,9 @@ elf_machine_runtime_setup (struct link_map *l, 
>>> struct r_scope_elem *scope[],
>>>            indicated by the offset on the stack, and then jump to
>>>            the resolved address.  */
>>>   #if !defined __loongarch_soft_float
>>> -      if (SUPPORT_LASX)
>>> +      if (RTLD_SUPPORT_LASX)
>>>           gotplt[0] = (ElfW(Addr)) &_dl_runtime_resolve_lasx;
>>> -      else if (SUPPORT_LSX)
>>> +      else if (RTLD_SUPPORT_LSX)
>>>           gotplt[0] = (ElfW(Addr)) &_dl_runtime_resolve_lsx;
>>>         else
>>>   #endif
>>> diff --git a/sysdeps/loongarch/dl-tunables.list 
>>> b/sysdeps/loongarch/dl-tunables.list
>>> new file mode 100644
>>> index 0000000000..66b3427516
>>> --- /dev/null
>>> +++ b/sysdeps/loongarch/dl-tunables.list
>>> @@ -0,0 +1,25 @@
>>> +# LoongArch specific tunables.
>>> +# Copyright (C) 2023 Free Software Foundation, Inc.
>>> +# This file is part of the GNU C Library.
>>> +
>>> +# The GNU C Library is free software; you can redistribute it and/or
>>> +# modify it under the terms of the GNU Lesser General Public
>>> +# License as published by the Free Software Foundation; either
>>> +# version 2.1 of the License, or (at your option) any later version.
>>> +
>>> +# The GNU C Library is distributed in the hope that it will be useful,
>>> +# but WITHOUT ANY WARRANTY; without even the implied warranty of
>>> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>>> +# Lesser General Public License for more details.
>>> +
>>> +# You should have received a copy of the GNU Lesser General Public
>>> +# License along with the GNU C Library; if not, see
>>> +# <http://www.gnu.org/licenses/>.
>>> +
>>> +glibc {
>>> +  cpu {
>>> +    hwcaps {
>>> +      type: STRING
>>> +    }
>>> +  }
>>> +}
>>> diff --git a/sysdeps/unix/sysv/linux/loongarch/cpu-features.c 
>>> b/sysdeps/unix/sysv/linux/loongarch/cpu-features.c
>>> new file mode 100644
>>> index 0000000000..1290c4ce9f
>>> --- /dev/null
>>> +++ b/sysdeps/unix/sysv/linux/loongarch/cpu-features.c
>>> @@ -0,0 +1,29 @@
>>> +/* Initialize CPU feature data.  LoongArch64 version.
>>> +   This file is part of the GNU C Library.
>>> +   Copyright (C) 2023 Free Software Foundation, Inc.
>>> +
>>> +   The GNU C Library is free software; you can redistribute it and/or
>>> +   modify it under the terms of the GNU Lesser General Public
>>> +   License as published by the Free Software Foundation; either
>>> +   version 2.1 of the License, or (at your option) any later version.
>>> +
>>> +   The GNU C Library is distributed in the hope that it will be 
>>> useful,
>>> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
>>> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>>> +   Lesser General Public License for more details.
>>> +
>>> +   You should have received a copy of the GNU Lesser General Public
>>> +   License along with the GNU C Library; if not, see
>>> +   <http://www.gnu.org/licenses/>.  */
>>> +
>>> +#include <cpu-features.h>
>>> +#include <elf/dl-hwcaps.h>
>>> +#include <elf/dl-tunables.h>
>>> +extern void TUNABLE_CALLBACK (set_hwcaps) (tunable_val_t *) 
>>> attribute_hidden;
>>> +
>>> +static inline void
>>> +init_cpu_features (struct cpu_features *cpu_features)
>>> +{
>>> +    GLRO (dl_larch_cpu_features).hwcap = GLRO (dl_hwcap);
>>> +    TUNABLE_GET (glibc, cpu, hwcaps, tunable_val_t *, 
>>> TUNABLE_CALLBACK (set_hwcaps));
>>> +}
>>> diff --git a/sysdeps/unix/sysv/linux/loongarch/cpu-features.h 
>>> b/sysdeps/unix/sysv/linux/loongarch/cpu-features.h
>>> index d1a280a5ee..450963cebc 100644
>>> --- a/sysdeps/unix/sysv/linux/loongarch/cpu-features.h
>>> +++ b/sysdeps/unix/sysv/linux/loongarch/cpu-features.h
>>> @@ -19,13 +19,23 @@
>>>   #ifndef _CPU_FEATURES_LOONGARCH64_H
>>>   #define _CPU_FEATURES_LOONGARCH64_H
>>>   +#include <stdint.h>
>>>   #include <sys/auxv.h>
>>>   -#define SUPPORT_UAL (GLRO (dl_hwcap) & HWCAP_LOONGARCH_UAL)
>>> -#define SUPPORT_LSX (GLRO (dl_hwcap) & HWCAP_LOONGARCH_LSX)
>>> -#define SUPPORT_LASX (GLRO (dl_hwcap) & HWCAP_LOONGARCH_LASX)
>>> +struct cpu_features
>>> + {
>>> +    uint64_t hwcap;
>>> + };
>>>   +/* Get a pointer to the CPU features structure.  */
>>> +extern const struct cpu_features *_dl_larch_get_cpu_features (void)
>>> +     __attribute__ ((pure));
>>> +
>>> +#define SUPPORT_UAL (GLRO (dl_larch_cpu_features).hwcap & 
>>> HWCAP_LOONGARCH_UAL)
>>> +#define SUPPORT_LSX (GLRO (dl_larch_cpu_features).hwcap & 
>>> HWCAP_LOONGARCH_LSX)
>>> +#define SUPPORT_LASX (GLRO (dl_larch_cpu_features).hwcap & 
>>> HWCAP_LOONGARCH_LASX)
>>> +#define RTLD_SUPPORT_LSX (GLRO (dl_hwcap) & HWCAP_LOONGARCH_LSX)
>>> +#define RTLD_SUPPORT_LASX (GLRO (dl_hwcap) & HWCAP_LOONGARCH_LASX)
>>>   #define INIT_ARCH()
>>>     #endif /* _CPU_FEATURES_LOONGARCH64_H  */
>>> -
>>> diff --git a/sysdeps/unix/sysv/linux/loongarch/dl-procinfo.c 
>>> b/sysdeps/unix/sysv/linux/loongarch/dl-procinfo.c
>>> new file mode 100644
>>> index 0000000000..6217fda983
>>> --- /dev/null
>>> +++ b/sysdeps/unix/sysv/linux/loongarch/dl-procinfo.c
>>> @@ -0,0 +1,60 @@
>>> +/* Data for LoongArch64 version of processor capability information.
>>> +   Linux version.
>>> +   Copyright (C) 2023 Free Software Foundation, Inc.
>>> +   This file is part of the GNU C Library.
>>> +
>>> +   The GNU C Library is free software; you can redistribute it and/or
>>> +   modify it under the terms of the GNU Lesser General Public
>>> +   License as published by the Free Software Foundation; either
>>> +   version 2.1 of the License, or (at your option) any later version.
>>> +
>>> +   The GNU C Library is distributed in the hope that it will be 
>>> useful,
>>> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
>>> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>>> +   Lesser General Public License for more details.
>>> +
>>> +   You should have received a copy of the GNU Lesser General Public
>>> +   License along with the GNU C Library; if not, see
>>> +   <http://www.gnu.org/licenses/>.  */
>>> +
>>> +/* If anything should be added here check whether the size of each 
>>> string
>>> +   is still ok with the given array size.
>>> +
>>> +   All the #ifdefs in the definitions are quite irritating but
>>> +   necessary if we want to avoid duplicating the information.  There
>>> +   are three different modes:
>>> +
>>> +   - PROCINFO_DECL is defined.  This means we are only interested in
>>> +     declarations.
>>> +
>>> +   - PROCINFO_DECL is not defined:
>>> +
>>> +     + if SHARED is defined the file is included in an array
>>> +       initializer.  The .element = { ... } syntax is needed.
>>> +
>>> +     + if SHARED is not defined a normal array initialization is
>>> +       needed.
>>> +  */
>>> +
>>> +#ifndef PROCINFO_CLASS
>>> +# define PROCINFO_CLASS
>>> +#endif
>>> +
>>> +#if !IS_IN (ldconfig)
>>> +# if !defined PROCINFO_DECL && defined SHARED
>>> +  ._dl_larch_cpu_features
>>> +# else
>>> +PROCINFO_CLASS struct cpu_features _dl_larch_cpu_features
>>> +# endif
>>> +# ifndef PROCINFO_DECL
>>> += { }
>>> +# endif
>>> +# if !defined SHARED || defined PROCINFO_DECL
>>> +;
>>> +# else
>>> +,
>>> +# endif
>>> +#endif
>>> +
>>> +#undef PROCINFO_DECL
>>> +#undef PROCINFO_CLASS
>>> diff --git a/sysdeps/unix/sysv/linux/loongarch/dl-sysdep.c 
>>> b/sysdeps/unix/sysv/linux/loongarch/dl-sysdep.c
>>> new file mode 100644
>>> index 0000000000..455fd71abc
>>> --- /dev/null
>>> +++ b/sysdeps/unix/sysv/linux/loongarch/dl-sysdep.c
>>> @@ -0,0 +1,21 @@
>>> +/* Operating system support for run-time dynamic linker. LoongArch 
>>> version.
>>> +   Copyright (C) 2023 Free Software Foundation, Inc.
>>> +   This file is part of the GNU C Library.
>>> +
>>> +   The GNU C Library is free software; you can redistribute it and/or
>>> +   modify it under the terms of the GNU Lesser General Public
>>> +   License as published by the Free Software Foundation; either
>>> +   version 2.1 of the License, or (at your option) any later version.
>>> +
>>> +   The GNU C Library is distributed in the hope that it will be 
>>> useful,
>>> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
>>> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>>> +   Lesser General Public License for more details.
>>> +
>>> +   You should have received a copy of the GNU Lesser General Public
>>> +   License along with the GNU C Library; if not, see
>>> +   <http://www.gnu.org/licenses/>.  */
>>> +
>>> +#include <config.h>
>>> +#include <sysdeps/loongarch/cpu-tunables.c>
>>> +#include <sysdeps/unix/sysv/linux/dl-sysdep.c>
>>> diff --git a/sysdeps/unix/sysv/linux/loongarch/libc-start.c 
>>> b/sysdeps/unix/sysv/linux/loongarch/libc-start.c
>>> new file mode 100644
>>> index 0000000000..f1346ece0a
>>> --- /dev/null
>>> +++ b/sysdeps/unix/sysv/linux/loongarch/libc-start.c
>>> @@ -0,0 +1,34 @@
>>> +/* Override csu/libc-start.c on LoongArch64.
>>> +   Copyright (C) 2023 Free Software Foundation, Inc.
>>> +   This file is part of the GNU C Library.
>>> +
>>> +   The GNU C Library is free software; you can redistribute it and/or
>>> +   modify it under the terms of the GNU Lesser General Public
>>> +   License as published by the Free Software Foundation; either
>>> +   version 2.1 of the License, or (at your option) any later version.
>>> +
>>> +   The GNU C Library is distributed in the hope that it will be 
>>> useful,
>>> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
>>> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>>> +   Lesser General Public License for more details.
>>> +
>>> +   You should have received a copy of the GNU Lesser General Public
>>> +   License along with the GNU C Library; if not, see
>>> +   <http://www.gnu.org/licenses/>.  */
>>> +
>>> +#ifndef SHARED
>>> +
>>> +/* Mark symbols hidden in static PIE for early self relocation to 
>>> work.  */
>>> +# if BUILD_PIE_DEFAULT
>>> +#  pragma GCC visibility push(hidden)
>>> +# endif
>>> +
>>> +# include <ldsodefs.h>
>>> +# include <cpu-features.c>
>>> +
>>> +extern struct cpu_features _dl_larch_cpu_features;
>>> +
>>> +# define ARCH_INIT_CPU_FEATURES() init_cpu_features 
>>> (&_dl_larch_cpu_features)
>>> +
>>> +#endif
>>> +#include <csu/libc-start.c>
  
Adhemerval Zanella Netto Sept. 20, 2023, 12:49 p.m. UTC | #6
On 20/09/23 07:15, caiyinyu wrote:

>> Maybe add a comment, similar to s390 and x86_64, on how the GLIBC_TUNABLES
>> should behave regarding parsing here.  The powerpc and s390 allows the
>> setup of disable a hwcap tunable by appending '-', as:
>>
>>   GLIBC_TUNABLES=glibc.cpu.hwcaps=-xxx,yyy,zzz,....
> 
> The only valid input of " glibc.cpu.hwcaps " are: LASX LSX UAL which i mentioned in
> 
> comimt message "Usage Notes" parts. "-" and "+" are not allowed. 
> 
> If you set GLIBC_TUNABLES=glibc.cpu.hwcaps=UAL on the lasx platform,
> 
> which supports all three features, the other features will be disabled.
> 
>     Usage Notes:
>     1. Only valid inputs: LASX, LSX, UAL. Case-sensitive, comma-separated, no spaces.
>     2. Example: `export GLIBC_TUNABLES=glibc.cpu.hwcaps=LASX,UAL` turns on LASX & UAL.
>        *Unmentioned features turn off.* With default ifunc: lasx > lsx > unaligned >
>        aligned > generic, effect is: lasx > unaligned > aligned > generic; lsx off.
>     3. Incorrect GLIBC_TUNABLES settings will show error messages.
>        For example: On lsx platforms, you cannot enable lasx features. If you do
>        that, you will get error messages.
>     4. Valid input examples:
>        - GLIBC_TUNABLES=glibc.cpu.hwcaps=LASX:  lasx > aligned > generic.
>        - GLIBC_TUNABLES=glibc.cpu.hwcaps=LSX,UAL:  lsx > unaligned > aligned > generic.
>        - GLIBC_TUNABLES=glibc.cpu.hwcaps=LASX,UAL,LASX,UAL,LSX,LASX,UAL: Repetitions
>          allowed but not recommended. Results in:  lasx > lsx > unaligned > aligned >
>          generic.
> 

I still don't see why loongarch should be different than x86, s390x,
and powerpc for the glibc.cpu.hwcap.  The current documentation
(manual/tunables.texi) specify that tunable allows the user enable
and disable each feature; so it means that we will need to update it
with the loongarch exception.

So I think it would be better to follow current pratice, add support
for disable a ifunc selection hwcap, and also update the documentation
to cite loongarch and the supported hwcaps.

> 
>> And it not clear how loongarch will handle.  If I understand correclty,
>> setting:
>>
>>   GLIBC_TUNABLES=glibc.cpu.hwcaps=LSX
>>
>> will set the 'hwcap' to HWCAP_LOONGARCH_UAL | HWCAP_LOONGARCH_LSX | HWCAP_LOONGARCH_LASX)
>> because CHECK_GLIBC_IFUNC_CPU_OFF 'or' everything (which does not seem
>> correct).
> 
> hwcap is just an intermediate temporary variable used to validate the input and collect valid features from it.
> 
> Note the following:
> 
> +
> +      p += len + 1;
> +    }
> +  while (*c != '\0');
> +
> +  GLRO (dl_larch_cpu_features).hwcap &= hwcap;
> +}
> 

Because the way you added the hwcap support is totally redundant, since
it always assumes ual, lsx, and lasx.  So GLIBC_TUNABLES=glibc.cpu.hwcaps=UAL
has absolute no effect, since either the machine already support UAL
or it will _dl_fatal_printf.  Same for LSX and LASX.

Also, I do not think it is a good idea to abort the execution on
TUNABLE_CALLBACK (set_hwcaps).  On s390x and powerpc, if the hwcap 
is not supported at runtime it would just not set the selection.

> 
>> So I would expect that it would follow what powerpc/s390 does, so
>> we could eventually consolidate this code.
>>
>>> +  const char *p = valp->strval;
>>> +  size_t len;
>>> +  unsigned long hwcap = 0;
>>> +  const char *c;
>>> +
>>> +  do {
>> Put the bracet on a newline.
>>
>>> +      for (c = p; *c != ','; c++)
>>> +	if (*c == '\0')
>>> +	  break;
>>> +
>>> +      len = c - p;
>>> +
>>> +      switch(len)
>> Space after 'switch'. 
>>
>>> +      {
>>> +	default:
>>> +	  _dl_fatal_printf (
>>> +	    "The valid values of glibc.cpu.hwcaps is UAL, LASX, LSX!!\n"
>>> +			    );
>> I think the ');' should be on previou sline.
>>
>>> +	  break;
>>> +	case 3:
>>> +	  {
>>> +	    CHECK_GLIBC_IFUNC_CPU_OFF (p, LSX, 3);
>>> +	    CHECK_GLIBC_IFUNC_CPU_OFF (p, UAL, 3);
>>> +	    _dl_fatal_printf (
>>> +		"Some features are invalid or not supported on this machine!!\n"
>>> +		"The valid values of glibc.cpu.hwcaps is UAL, LASX, LSX!!\n"
>>> +                       );
>>> +	  }
>>> +	  break;
>>> +	case 4:
>>> +	  {
>>> +	    CHECK_GLIBC_IFUNC_CPU_OFF (p, LASX, 4);
>>> +	    _dl_fatal_printf (
>>> +		"Some features are invalid or not supported on this machine!!\n"
>>> +		"The valid values of glibc.cpu.hwcaps is UAL, LASX, LSX!!\n"
>>> +                       );
>>> +	  }
>>> +	  break;
>>> +      }
>>> +
>>> +      p += len + 1;
>>> +    }
>>> +  while (*c != '\0');
>>> +
>>> +  GLRO (dl_larch_cpu_features).hwcap &= hwcap;
>>> +}
>>> diff --git a/sysdeps/loongarch/dl-get-cpu-features.c b/sysdeps/loongarch/dl-get-cpu-features.c
>>> new file mode 100644
>>> index 0000000000..7cd9bc15c3
>>> --- /dev/null
>>> +++ b/sysdeps/loongarch/dl-get-cpu-features.c
>>> @@ -0,0 +1,25 @@
>>> +/* Define _dl_larch_get_cpu_features.
>>> +   Copyright (C) 2023 Free Software Foundation, Inc.
>>> +
>>> +   The GNU C Library is free software; you can redistribute it and/or
>>> +   modify it under the terms of the GNU Lesser General Public
>>> +   License as published by the Free Software Foundation; either
>>> +   version 2.1 of the License, or (at your option) any later version.
>>> +
>>> +   The GNU C Library is distributed in the hope that it will be useful,
>>> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
>>> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>>> +   Lesser General Public License for more details.
>>> +
>>> +   You should have received a copy of the GNU Lesser General Public
>>> +   License along with the GNU C Library; if not, see
>>> +   <https://www.gnu.org/licenses/>.  */
>>> +
>>> +
>>> +#include <ldsodefs.h>
>>> +
>>> +const struct cpu_features *
>>> +_dl_larch_get_cpu_features (void)
>>> +{
>>> +  return &GLRO(dl_larch_cpu_features);
>>> +}
>>> diff --git a/sysdeps/loongarch/dl-machine.h b/sysdeps/loongarch/dl-machine.h
>>> index 57913cefaa..b395a9283e 100644
>>> --- a/sysdeps/loongarch/dl-machine.h
>>> +++ b/sysdeps/loongarch/dl-machine.h
>>> @@ -29,6 +29,8 @@
>>>  #include <dl-static-tls.h>
>>>  #include <dl-machine-rel.h>
>>>  
>>> +#include <cpu-features.c>
>>> +
>>>  #ifndef _RTLD_PROLOGUE
>>>  # define _RTLD_PROLOGUE(entry)					\
>>>  	".globl\t" __STRING (entry) "\n\t"			\
>>> @@ -53,6 +55,23 @@
>>>  #define ELF_MACHINE_NO_REL 1
>>>  #define ELF_MACHINE_NO_RELA 0
>>>  
>>> +#define DL_PLATFORM_INIT dl_platform_init ()
>>> +
>>> +static inline void __attribute__ ((unused))
>>> +dl_platform_init (void)
>>> +{
>>> +  if (GLRO(dl_platform) != NULL && *GLRO(dl_platform) == '\0')
>>> +    /* Avoid an empty string which would disturb us.  */
>>> +    GLRO(dl_platform) = NULL;
>>> +
>>> +#ifdef SHARED
>>> +  /* init_cpu_features has been called early from __libc_start_main in
>>> +     static executable.  */
>>> +  init_cpu_features (&GLRO(dl_larch_cpu_features));
>>> +#endif
>>> +}
>>> +
>>> +
>>>  /* Return nonzero iff ELF header is compatible with the running host.  */
>>>  static inline int
>>>  elf_machine_matches_host (const ElfW (Ehdr) *ehdr)
>>> @@ -290,9 +309,9 @@ elf_machine_runtime_setup (struct link_map *l, struct r_scope_elem *scope[],
>>>        if (profile != 0)
>>>  	{
>>>  #if !defined __loongarch_soft_float
>>> -	  if (SUPPORT_LASX)
>>> +	  if (RTLD_SUPPORT_LASX)
>>>  	    gotplt[0] = (ElfW(Addr)) &_dl_runtime_profile_lasx;
>>> -	  else if (SUPPORT_LSX)
>>> +	  else if (RTLD_SUPPORT_LSX)
>>>  	    gotplt[0] = (ElfW(Addr)) &_dl_runtime_profile_lsx;
>>>  	  else
>>>  #endif
>>> @@ -310,9 +329,9 @@ elf_machine_runtime_setup (struct link_map *l, struct r_scope_elem *scope[],
>>>  	     indicated by the offset on the stack, and then jump to
>>>  	     the resolved address.  */
>>>  #if !defined __loongarch_soft_float
>>> -	  if (SUPPORT_LASX)
>>> +	  if (RTLD_SUPPORT_LASX)
>>>  	    gotplt[0] = (ElfW(Addr)) &_dl_runtime_resolve_lasx;
>>> -	  else if (SUPPORT_LSX)
>>> +	  else if (RTLD_SUPPORT_LSX)
>>>  	    gotplt[0] = (ElfW(Addr)) &_dl_runtime_resolve_lsx;
>>>  	  else
>>>  #endif
>>> diff --git a/sysdeps/loongarch/dl-tunables.list b/sysdeps/loongarch/dl-tunables.list
>>> new file mode 100644
>>> index 0000000000..66b3427516
>>> --- /dev/null
>>> +++ b/sysdeps/loongarch/dl-tunables.list
>>> @@ -0,0 +1,25 @@
>>> +# LoongArch specific tunables.
>>> +# Copyright (C) 2023 Free Software Foundation, Inc.
>>> +# This file is part of the GNU C Library.
>>> +
>>> +# The GNU C Library is free software; you can redistribute it and/or
>>> +# modify it under the terms of the GNU Lesser General Public
>>> +# License as published by the Free Software Foundation; either
>>> +# version 2.1 of the License, or (at your option) any later version.
>>> +
>>> +# The GNU C Library is distributed in the hope that it will be useful,
>>> +# but WITHOUT ANY WARRANTY; without even the implied warranty of
>>> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>>> +# Lesser General Public License for more details.
>>> +
>>> +# You should have received a copy of the GNU Lesser General Public
>>> +# License along with the GNU C Library; if not, see
>>> +# <http://www.gnu.org/licenses/>.
>>> +
>>> +glibc {
>>> +  cpu {
>>> +    hwcaps {
>>> +      type: STRING
>>> +    }
>>> +  }
>>> +}
>>> diff --git a/sysdeps/unix/sysv/linux/loongarch/cpu-features.c b/sysdeps/unix/sysv/linux/loongarch/cpu-features.c
>>> new file mode 100644
>>> index 0000000000..1290c4ce9f
>>> --- /dev/null
>>> +++ b/sysdeps/unix/sysv/linux/loongarch/cpu-features.c
>>> @@ -0,0 +1,29 @@
>>> +/* Initialize CPU feature data.  LoongArch64 version.
>>> +   This file is part of the GNU C Library.
>>> +   Copyright (C) 2023 Free Software Foundation, Inc.
>>> +
>>> +   The GNU C Library is free software; you can redistribute it and/or
>>> +   modify it under the terms of the GNU Lesser General Public
>>> +   License as published by the Free Software Foundation; either
>>> +   version 2.1 of the License, or (at your option) any later version.
>>> +
>>> +   The GNU C Library is distributed in the hope that it will be useful,
>>> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
>>> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>>> +   Lesser General Public License for more details.
>>> +
>>> +   You should have received a copy of the GNU Lesser General Public
>>> +   License along with the GNU C Library; if not, see
>>> +   <http://www.gnu.org/licenses/>.  */
>>> +
>>> +#include <cpu-features.h>
>>> +#include <elf/dl-hwcaps.h>
>>> +#include <elf/dl-tunables.h>
>>> +extern void TUNABLE_CALLBACK (set_hwcaps) (tunable_val_t *) attribute_hidden;
>>> +
>>> +static inline void
>>> +init_cpu_features (struct cpu_features *cpu_features)
>>> +{
>>> +    GLRO (dl_larch_cpu_features).hwcap = GLRO (dl_hwcap);
>>> +    TUNABLE_GET (glibc, cpu, hwcaps, tunable_val_t *, TUNABLE_CALLBACK (set_hwcaps));
>> The initial space number seems odd here.
>>
>>> +}
>>> diff --git a/sysdeps/unix/sysv/linux/loongarch/cpu-features.h b/sysdeps/unix/sysv/linux/loongarch/cpu-features.h
>>> index d1a280a5ee..450963cebc 100644
>>> --- a/sysdeps/unix/sysv/linux/loongarch/cpu-features.h
>>> +++ b/sysdeps/unix/sysv/linux/loongarch/cpu-features.h
>>> @@ -19,13 +19,23 @@
>>>  #ifndef _CPU_FEATURES_LOONGARCH64_H
>>>  #define _CPU_FEATURES_LOONGARCH64_H
>>>  
>>> +#include <stdint.h>
>>>  #include <sys/auxv.h>
>>>  
>>> -#define SUPPORT_UAL (GLRO (dl_hwcap) & HWCAP_LOONGARCH_UAL)
>>> -#define SUPPORT_LSX (GLRO (dl_hwcap) & HWCAP_LOONGARCH_LSX)
>>> -#define SUPPORT_LASX (GLRO (dl_hwcap) & HWCAP_LOONGARCH_LASX)
>>> +struct cpu_features
>>> + {
>>> +    uint64_t hwcap;
>>> + };
>> The indentation seems off here.
>>
>>>  
>>> +/* Get a pointer to the CPU features structure.  */
>>> +extern const struct cpu_features *_dl_larch_get_cpu_features (void)
>>> +     __attribute__ ((pure));
>>> +
>>> +#define SUPPORT_UAL (GLRO (dl_larch_cpu_features).hwcap & HWCAP_LOONGARCH_UAL)
>>> +#define SUPPORT_LSX (GLRO (dl_larch_cpu_features).hwcap & HWCAP_LOONGARCH_LSX)
>>> +#define SUPPORT_LASX (GLRO (dl_larch_cpu_features).hwcap & HWCAP_LOONGARCH_LASX)
>>> +#define RTLD_SUPPORT_LSX (GLRO (dl_hwcap) & HWCAP_LOONGARCH_LSX)
>>> +#define RTLD_SUPPORT_LASX (GLRO (dl_hwcap) & HWCAP_LOONGARCH_LASX)
>> For GLRO, it is considered a variable access to there is no need of space.
>>
>>>  #define INIT_ARCH()
>>>  
>>>  #endif /* _CPU_FEATURES_LOONGARCH64_H  */
>>> -
>>> diff --git a/sysdeps/unix/sysv/linux/loongarch/dl-procinfo.c b/sysdeps/unix/sysv/linux/loongarch/dl-procinfo.c
>>> new file mode 100644
>>> index 0000000000..6217fda983
>>> --- /dev/null
>>> +++ b/sysdeps/unix/sysv/linux/loongarch/dl-procinfo.c
>>> @@ -0,0 +1,60 @@
>>> +/* Data for LoongArch64 version of processor capability information.
>>> +   Linux version.
>>> +   Copyright (C) 2023 Free Software Foundation, Inc.
>>> +   This file is part of the GNU C Library.
>>> +
>>> +   The GNU C Library is free software; you can redistribute it and/or
>>> +   modify it under the terms of the GNU Lesser General Public
>>> +   License as published by the Free Software Foundation; either
>>> +   version 2.1 of the License, or (at your option) any later version.
>>> +
>>> +   The GNU C Library is distributed in the hope that it will be useful,
>>> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
>>> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>>> +   Lesser General Public License for more details.
>>> +
>>> +   You should have received a copy of the GNU Lesser General Public
>>> +   License along with the GNU C Library; if not, see
>>> +   <http://www.gnu.org/licenses/>.  */
>>> +
>>> +/* If anything should be added here check whether the size of each string
>>> +   is still ok with the given array size.
>>> +
>>> +   All the #ifdefs in the definitions are quite irritating but
>>> +   necessary if we want to avoid duplicating the information.  There
>>> +   are three different modes:
>>> +
>>> +   - PROCINFO_DECL is defined.  This means we are only interested in
>>> +     declarations.
>>> +
>>> +   - PROCINFO_DECL is not defined:
>>> +
>>> +     + if SHARED is defined the file is included in an array
>>> +       initializer.  The .element = { ... } syntax is needed.
>>> +
>>> +     + if SHARED is not defined a normal array initialization is
>>> +       needed.
>>> +  */
>>> +
>>> +#ifndef PROCINFO_CLASS
>>> +# define PROCINFO_CLASS
>>> +#endif
>>> +
>>> +#if !IS_IN (ldconfig)
>>> +# if !defined PROCINFO_DECL && defined SHARED
>>> +  ._dl_larch_cpu_features
>>> +# else
>>> +PROCINFO_CLASS struct cpu_features _dl_larch_cpu_features
>>> +# endif
>>> +# ifndef PROCINFO_DECL
>>> += { }
>>> +# endif
>>> +# if !defined SHARED || defined PROCINFO_DECL
>>> +;
>>> +# else
>>> +,
>>> +# endif
>>> +#endif
>>> +
>>> +#undef PROCINFO_DECL
>>> +#undef PROCINFO_CLASS
>>> diff --git a/sysdeps/unix/sysv/linux/loongarch/dl-sysdep.c b/sysdeps/unix/sysv/linux/loongarch/dl-sysdep.c
>>> new file mode 100644
>>> index 0000000000..455fd71abc
>>> --- /dev/null
>>> +++ b/sysdeps/unix/sysv/linux/loongarch/dl-sysdep.c
>>> @@ -0,0 +1,21 @@
>>> +/* Operating system support for run-time dynamic linker.  LoongArch version.
>>> +   Copyright (C) 2023 Free Software Foundation, Inc.
>>> +   This file is part of the GNU C Library.
>>> +
>>> +   The GNU C Library is free software; you can redistribute it and/or
>>> +   modify it under the terms of the GNU Lesser General Public
>>> +   License as published by the Free Software Foundation; either
>>> +   version 2.1 of the License, or (at your option) any later version.
>>> +
>>> +   The GNU C Library is distributed in the hope that it will be useful,
>>> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
>>> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>>> +   Lesser General Public License for more details.
>>> +
>>> +   You should have received a copy of the GNU Lesser General Public
>>> +   License along with the GNU C Library; if not, see
>>> +   <http://www.gnu.org/licenses/>.  */
>>> +
>>> +#include <config.h>
>>> +#include <sysdeps/loongarch/cpu-tunables.c>
>>> +#include <sysdeps/unix/sysv/linux/dl-sysdep.c>
>>> diff --git a/sysdeps/unix/sysv/linux/loongarch/libc-start.c b/sysdeps/unix/sysv/linux/loongarch/libc-start.c
>>> new file mode 100644
>>> index 0000000000..f1346ece0a
>>> --- /dev/null
>>> +++ b/sysdeps/unix/sysv/linux/loongarch/libc-start.c
>>> @@ -0,0 +1,34 @@
>>> +/* Override csu/libc-start.c on LoongArch64.
>>> +   Copyright (C) 2023 Free Software Foundation, Inc.
>>> +   This file is part of the GNU C Library.
>>> +
>>> +   The GNU C Library is free software; you can redistribute it and/or
>>> +   modify it under the terms of the GNU Lesser General Public
>>> +   License as published by the Free Software Foundation; either
>>> +   version 2.1 of the License, or (at your option) any later version.
>>> +
>>> +   The GNU C Library is distributed in the hope that it will be useful,
>>> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
>>> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>>> +   Lesser General Public License for more details.
>>> +
>>> +   You should have received a copy of the GNU Lesser General Public
>>> +   License along with the GNU C Library; if not, see
>>> +   <http://www.gnu.org/licenses/>.  */
>>> +
>>> +#ifndef SHARED
>>> +
>>> +/* Mark symbols hidden in static PIE for early self relocation to work.  */
>>> +# if BUILD_PIE_DEFAULT
>>> +#  pragma GCC visibility push(hidden)
>>> +# endif
>>> +
>>> +# include <ldsodefs.h>
>>> +# include <cpu-features.c>
>>> +
>>> +extern struct cpu_features _dl_larch_cpu_features;
>>> +
>>> +# define ARCH_INIT_CPU_FEATURES() init_cpu_features (&_dl_larch_cpu_features)
>>> +
>>> +#endif
>>> +#include <csu/libc-start.c>
>> I think this patch misses a proper testcase, similar to one I suggested
>> when powerpc added a similar support (check 21841f0d562f0e944c4d267a28cc3ebd19c847e9).
>> Check sysdeps/unix/sysv/linux/powerpc/tst-hwcap-tunables.c on a way to
>> proper check it.
> I will add a proper testcase in the upcoming patch.
  
caiyinyu Sept. 20, 2023, 1:20 p.m. UTC | #7
在 2023/9/20 下午8:49, Adhemerval Zanella Netto 写道:
>
> On 20/09/23 07:15, caiyinyu wrote:
>
>>> Maybe add a comment, similar to s390 and x86_64, on how the GLIBC_TUNABLES
>>> should behave regarding parsing here.  The powerpc and s390 allows the
>>> setup of disable a hwcap tunable by appending '-', as:
>>>
>>>    GLIBC_TUNABLES=glibc.cpu.hwcaps=-xxx,yyy,zzz,....
>> The only valid input of " glibc.cpu.hwcaps " are: LASX LSX UAL which i mentioned in
>>
>> comimt message "Usage Notes" parts. "-" and "+" are not allowed.
>>
>> If you set GLIBC_TUNABLES=glibc.cpu.hwcaps=UAL on the lasx platform,
>>
>> which supports all three features, the other features will be disabled.
>>
>>      Usage Notes:
>>      1. Only valid inputs: LASX, LSX, UAL. Case-sensitive, comma-separated, no spaces.
>>      2. Example: `export GLIBC_TUNABLES=glibc.cpu.hwcaps=LASX,UAL` turns on LASX & UAL.
>>         *Unmentioned features turn off.* With default ifunc: lasx > lsx > unaligned >
>>         aligned > generic, effect is: lasx > unaligned > aligned > generic; lsx off.
>>      3. Incorrect GLIBC_TUNABLES settings will show error messages.
>>         For example: On lsx platforms, you cannot enable lasx features. If you do
>>         that, you will get error messages.
>>      4. Valid input examples:
>>         - GLIBC_TUNABLES=glibc.cpu.hwcaps=LASX:  lasx > aligned > generic.
>>         - GLIBC_TUNABLES=glibc.cpu.hwcaps=LSX,UAL:  lsx > unaligned > aligned > generic.
>>         - GLIBC_TUNABLES=glibc.cpu.hwcaps=LASX,UAL,LASX,UAL,LSX,LASX,UAL: Repetitions
>>           allowed but not recommended. Results in:  lasx > lsx > unaligned > aligned >
>>           generic.
>>
> I still don't see why loongarch should be different than x86, s390x,
> and powerpc for the glibc.cpu.hwcap.  The current documentation
> (manual/tunables.texi) specify that tunable allows the user enable
> and disable each feature; so it means that we will need to update it
> with the loongarch exception.
>
> So I think it would be better to follow current pratice, add support
> for disable a ifunc selection hwcap, and also update the documentation
> to cite loongarch and the supported hwcaps.
Alright, I will revert this commit first.


>
>>> And it not clear how loongarch will handle.  If I understand correclty,
>>> setting:
>>>
>>>    GLIBC_TUNABLES=glibc.cpu.hwcaps=LSX
>>>
>>> will set the 'hwcap' to HWCAP_LOONGARCH_UAL | HWCAP_LOONGARCH_LSX | HWCAP_LOONGARCH_LASX)
>>> because CHECK_GLIBC_IFUNC_CPU_OFF 'or' everything (which does not seem
>>> correct).
>> hwcap is just an intermediate temporary variable used to validate the input and collect valid features from it.
>>
>> Note the following:
>>
>> +
>> +      p += len + 1;
>> +    }
>> +  while (*c != '\0');
>> +
>> +  GLRO (dl_larch_cpu_features).hwcap &= hwcap;
>> +}
>>
> Because the way you added the hwcap support is totally redundant, since
> it always assumes ual, lsx, and lasx.  So GLIBC_TUNABLES=glibc.cpu.hwcaps=UAL
> has absolute no effect, since either the machine already support UAL
> or it will _dl_fatal_printf.  Same for LSX and LASX.
>
> Also, I do not think it is a good idea to abort the execution on
> TUNABLE_CALLBACK (set_hwcaps).  On s390x and powerpc, if the hwcap
> is not supported at runtime it would just not set the selection.
>
>>> So I would expect that it would follow what powerpc/s390 does, so
>>> we could eventually consolidate this code.
>>>
>>>> +  const char *p = valp->strval;
>>>> +  size_t len;
>>>> +  unsigned long hwcap = 0;
>>>> +  const char *c;
>>>> +
>>>> +  do {
>>> Put the bracet on a newline.
>>>
>>>> +      for (c = p; *c != ','; c++)
>>>> +	if (*c == '\0')
>>>> +	  break;
>>>> +
>>>> +      len = c - p;
>>>> +
>>>> +      switch(len)
>>> Space after 'switch'.
>>>
>>>> +      {
>>>> +	default:
>>>> +	  _dl_fatal_printf (
>>>> +	    "The valid values of glibc.cpu.hwcaps is UAL, LASX, LSX!!\n"
>>>> +			    );
>>> I think the ');' should be on previou sline.
>>>
>>>> +	  break;
>>>> +	case 3:
>>>> +	  {
>>>> +	    CHECK_GLIBC_IFUNC_CPU_OFF (p, LSX, 3);
>>>> +	    CHECK_GLIBC_IFUNC_CPU_OFF (p, UAL, 3);
>>>> +	    _dl_fatal_printf (
>>>> +		"Some features are invalid or not supported on this machine!!\n"
>>>> +		"The valid values of glibc.cpu.hwcaps is UAL, LASX, LSX!!\n"
>>>> +                       );
>>>> +	  }
>>>> +	  break;
>>>> +	case 4:
>>>> +	  {
>>>> +	    CHECK_GLIBC_IFUNC_CPU_OFF (p, LASX, 4);
>>>> +	    _dl_fatal_printf (
>>>> +		"Some features are invalid or not supported on this machine!!\n"
>>>> +		"The valid values of glibc.cpu.hwcaps is UAL, LASX, LSX!!\n"
>>>> +                       );
>>>> +	  }
>>>> +	  break;
>>>> +      }
>>>> +
>>>> +      p += len + 1;
>>>> +    }
>>>> +  while (*c != '\0');
>>>> +
>>>> +  GLRO (dl_larch_cpu_features).hwcap &= hwcap;
>>>> +}
>>>> diff --git a/sysdeps/loongarch/dl-get-cpu-features.c b/sysdeps/loongarch/dl-get-cpu-features.c
>>>> new file mode 100644
>>>> index 0000000000..7cd9bc15c3
>>>> --- /dev/null
>>>> +++ b/sysdeps/loongarch/dl-get-cpu-features.c
>>>> @@ -0,0 +1,25 @@
>>>> +/* Define _dl_larch_get_cpu_features.
>>>> +   Copyright (C) 2023 Free Software Foundation, Inc.
>>>> +
>>>> +   The GNU C Library is free software; you can redistribute it and/or
>>>> +   modify it under the terms of the GNU Lesser General Public
>>>> +   License as published by the Free Software Foundation; either
>>>> +   version 2.1 of the License, or (at your option) any later version.
>>>> +
>>>> +   The GNU C Library is distributed in the hope that it will be useful,
>>>> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
>>>> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>>>> +   Lesser General Public License for more details.
>>>> +
>>>> +   You should have received a copy of the GNU Lesser General Public
>>>> +   License along with the GNU C Library; if not, see
>>>> +   <https://www.gnu.org/licenses/>.  */
>>>> +
>>>> +
>>>> +#include <ldsodefs.h>
>>>> +
>>>> +const struct cpu_features *
>>>> +_dl_larch_get_cpu_features (void)
>>>> +{
>>>> +  return &GLRO(dl_larch_cpu_features);
>>>> +}
>>>> diff --git a/sysdeps/loongarch/dl-machine.h b/sysdeps/loongarch/dl-machine.h
>>>> index 57913cefaa..b395a9283e 100644
>>>> --- a/sysdeps/loongarch/dl-machine.h
>>>> +++ b/sysdeps/loongarch/dl-machine.h
>>>> @@ -29,6 +29,8 @@
>>>>   #include <dl-static-tls.h>
>>>>   #include <dl-machine-rel.h>
>>>>   
>>>> +#include <cpu-features.c>
>>>> +
>>>>   #ifndef _RTLD_PROLOGUE
>>>>   # define _RTLD_PROLOGUE(entry)					\
>>>>   	".globl\t" __STRING (entry) "\n\t"			\
>>>> @@ -53,6 +55,23 @@
>>>>   #define ELF_MACHINE_NO_REL 1
>>>>   #define ELF_MACHINE_NO_RELA 0
>>>>   
>>>> +#define DL_PLATFORM_INIT dl_platform_init ()
>>>> +
>>>> +static inline void __attribute__ ((unused))
>>>> +dl_platform_init (void)
>>>> +{
>>>> +  if (GLRO(dl_platform) != NULL && *GLRO(dl_platform) == '\0')
>>>> +    /* Avoid an empty string which would disturb us.  */
>>>> +    GLRO(dl_platform) = NULL;
>>>> +
>>>> +#ifdef SHARED
>>>> +  /* init_cpu_features has been called early from __libc_start_main in
>>>> +     static executable.  */
>>>> +  init_cpu_features (&GLRO(dl_larch_cpu_features));
>>>> +#endif
>>>> +}
>>>> +
>>>> +
>>>>   /* Return nonzero iff ELF header is compatible with the running host.  */
>>>>   static inline int
>>>>   elf_machine_matches_host (const ElfW (Ehdr) *ehdr)
>>>> @@ -290,9 +309,9 @@ elf_machine_runtime_setup (struct link_map *l, struct r_scope_elem *scope[],
>>>>         if (profile != 0)
>>>>   	{
>>>>   #if !defined __loongarch_soft_float
>>>> -	  if (SUPPORT_LASX)
>>>> +	  if (RTLD_SUPPORT_LASX)
>>>>   	    gotplt[0] = (ElfW(Addr)) &_dl_runtime_profile_lasx;
>>>> -	  else if (SUPPORT_LSX)
>>>> +	  else if (RTLD_SUPPORT_LSX)
>>>>   	    gotplt[0] = (ElfW(Addr)) &_dl_runtime_profile_lsx;
>>>>   	  else
>>>>   #endif
>>>> @@ -310,9 +329,9 @@ elf_machine_runtime_setup (struct link_map *l, struct r_scope_elem *scope[],
>>>>   	     indicated by the offset on the stack, and then jump to
>>>>   	     the resolved address.  */
>>>>   #if !defined __loongarch_soft_float
>>>> -	  if (SUPPORT_LASX)
>>>> +	  if (RTLD_SUPPORT_LASX)
>>>>   	    gotplt[0] = (ElfW(Addr)) &_dl_runtime_resolve_lasx;
>>>> -	  else if (SUPPORT_LSX)
>>>> +	  else if (RTLD_SUPPORT_LSX)
>>>>   	    gotplt[0] = (ElfW(Addr)) &_dl_runtime_resolve_lsx;
>>>>   	  else
>>>>   #endif
>>>> diff --git a/sysdeps/loongarch/dl-tunables.list b/sysdeps/loongarch/dl-tunables.list
>>>> new file mode 100644
>>>> index 0000000000..66b3427516
>>>> --- /dev/null
>>>> +++ b/sysdeps/loongarch/dl-tunables.list
>>>> @@ -0,0 +1,25 @@
>>>> +# LoongArch specific tunables.
>>>> +# Copyright (C) 2023 Free Software Foundation, Inc.
>>>> +# This file is part of the GNU C Library.
>>>> +
>>>> +# The GNU C Library is free software; you can redistribute it and/or
>>>> +# modify it under the terms of the GNU Lesser General Public
>>>> +# License as published by the Free Software Foundation; either
>>>> +# version 2.1 of the License, or (at your option) any later version.
>>>> +
>>>> +# The GNU C Library is distributed in the hope that it will be useful,
>>>> +# but WITHOUT ANY WARRANTY; without even the implied warranty of
>>>> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>>>> +# Lesser General Public License for more details.
>>>> +
>>>> +# You should have received a copy of the GNU Lesser General Public
>>>> +# License along with the GNU C Library; if not, see
>>>> +# <http://www.gnu.org/licenses/>.
>>>> +
>>>> +glibc {
>>>> +  cpu {
>>>> +    hwcaps {
>>>> +      type: STRING
>>>> +    }
>>>> +  }
>>>> +}
>>>> diff --git a/sysdeps/unix/sysv/linux/loongarch/cpu-features.c b/sysdeps/unix/sysv/linux/loongarch/cpu-features.c
>>>> new file mode 100644
>>>> index 0000000000..1290c4ce9f
>>>> --- /dev/null
>>>> +++ b/sysdeps/unix/sysv/linux/loongarch/cpu-features.c
>>>> @@ -0,0 +1,29 @@
>>>> +/* Initialize CPU feature data.  LoongArch64 version.
>>>> +   This file is part of the GNU C Library.
>>>> +   Copyright (C) 2023 Free Software Foundation, Inc.
>>>> +
>>>> +   The GNU C Library is free software; you can redistribute it and/or
>>>> +   modify it under the terms of the GNU Lesser General Public
>>>> +   License as published by the Free Software Foundation; either
>>>> +   version 2.1 of the License, or (at your option) any later version.
>>>> +
>>>> +   The GNU C Library is distributed in the hope that it will be useful,
>>>> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
>>>> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>>>> +   Lesser General Public License for more details.
>>>> +
>>>> +   You should have received a copy of the GNU Lesser General Public
>>>> +   License along with the GNU C Library; if not, see
>>>> +   <http://www.gnu.org/licenses/>.  */
>>>> +
>>>> +#include <cpu-features.h>
>>>> +#include <elf/dl-hwcaps.h>
>>>> +#include <elf/dl-tunables.h>
>>>> +extern void TUNABLE_CALLBACK (set_hwcaps) (tunable_val_t *) attribute_hidden;
>>>> +
>>>> +static inline void
>>>> +init_cpu_features (struct cpu_features *cpu_features)
>>>> +{
>>>> +    GLRO (dl_larch_cpu_features).hwcap = GLRO (dl_hwcap);
>>>> +    TUNABLE_GET (glibc, cpu, hwcaps, tunable_val_t *, TUNABLE_CALLBACK (set_hwcaps));
>>> The initial space number seems odd here.
>>>
>>>> +}
>>>> diff --git a/sysdeps/unix/sysv/linux/loongarch/cpu-features.h b/sysdeps/unix/sysv/linux/loongarch/cpu-features.h
>>>> index d1a280a5ee..450963cebc 100644
>>>> --- a/sysdeps/unix/sysv/linux/loongarch/cpu-features.h
>>>> +++ b/sysdeps/unix/sysv/linux/loongarch/cpu-features.h
>>>> @@ -19,13 +19,23 @@
>>>>   #ifndef _CPU_FEATURES_LOONGARCH64_H
>>>>   #define _CPU_FEATURES_LOONGARCH64_H
>>>>   
>>>> +#include <stdint.h>
>>>>   #include <sys/auxv.h>
>>>>   
>>>> -#define SUPPORT_UAL (GLRO (dl_hwcap) & HWCAP_LOONGARCH_UAL)
>>>> -#define SUPPORT_LSX (GLRO (dl_hwcap) & HWCAP_LOONGARCH_LSX)
>>>> -#define SUPPORT_LASX (GLRO (dl_hwcap) & HWCAP_LOONGARCH_LASX)
>>>> +struct cpu_features
>>>> + {
>>>> +    uint64_t hwcap;
>>>> + };
>>> The indentation seems off here.
>>>
>>>>   
>>>> +/* Get a pointer to the CPU features structure.  */
>>>> +extern const struct cpu_features *_dl_larch_get_cpu_features (void)
>>>> +     __attribute__ ((pure));
>>>> +
>>>> +#define SUPPORT_UAL (GLRO (dl_larch_cpu_features).hwcap & HWCAP_LOONGARCH_UAL)
>>>> +#define SUPPORT_LSX (GLRO (dl_larch_cpu_features).hwcap & HWCAP_LOONGARCH_LSX)
>>>> +#define SUPPORT_LASX (GLRO (dl_larch_cpu_features).hwcap & HWCAP_LOONGARCH_LASX)
>>>> +#define RTLD_SUPPORT_LSX (GLRO (dl_hwcap) & HWCAP_LOONGARCH_LSX)
>>>> +#define RTLD_SUPPORT_LASX (GLRO (dl_hwcap) & HWCAP_LOONGARCH_LASX)
>>> For GLRO, it is considered a variable access to there is no need of space.
>>>
>>>>   #define INIT_ARCH()
>>>>   
>>>>   #endif /* _CPU_FEATURES_LOONGARCH64_H  */
>>>> -
>>>> diff --git a/sysdeps/unix/sysv/linux/loongarch/dl-procinfo.c b/sysdeps/unix/sysv/linux/loongarch/dl-procinfo.c
>>>> new file mode 100644
>>>> index 0000000000..6217fda983
>>>> --- /dev/null
>>>> +++ b/sysdeps/unix/sysv/linux/loongarch/dl-procinfo.c
>>>> @@ -0,0 +1,60 @@
>>>> +/* Data for LoongArch64 version of processor capability information.
>>>> +   Linux version.
>>>> +   Copyright (C) 2023 Free Software Foundation, Inc.
>>>> +   This file is part of the GNU C Library.
>>>> +
>>>> +   The GNU C Library is free software; you can redistribute it and/or
>>>> +   modify it under the terms of the GNU Lesser General Public
>>>> +   License as published by the Free Software Foundation; either
>>>> +   version 2.1 of the License, or (at your option) any later version.
>>>> +
>>>> +   The GNU C Library is distributed in the hope that it will be useful,
>>>> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
>>>> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>>>> +   Lesser General Public License for more details.
>>>> +
>>>> +   You should have received a copy of the GNU Lesser General Public
>>>> +   License along with the GNU C Library; if not, see
>>>> +   <http://www.gnu.org/licenses/>.  */
>>>> +
>>>> +/* If anything should be added here check whether the size of each string
>>>> +   is still ok with the given array size.
>>>> +
>>>> +   All the #ifdefs in the definitions are quite irritating but
>>>> +   necessary if we want to avoid duplicating the information.  There
>>>> +   are three different modes:
>>>> +
>>>> +   - PROCINFO_DECL is defined.  This means we are only interested in
>>>> +     declarations.
>>>> +
>>>> +   - PROCINFO_DECL is not defined:
>>>> +
>>>> +     + if SHARED is defined the file is included in an array
>>>> +       initializer.  The .element = { ... } syntax is needed.
>>>> +
>>>> +     + if SHARED is not defined a normal array initialization is
>>>> +       needed.
>>>> +  */
>>>> +
>>>> +#ifndef PROCINFO_CLASS
>>>> +# define PROCINFO_CLASS
>>>> +#endif
>>>> +
>>>> +#if !IS_IN (ldconfig)
>>>> +# if !defined PROCINFO_DECL && defined SHARED
>>>> +  ._dl_larch_cpu_features
>>>> +# else
>>>> +PROCINFO_CLASS struct cpu_features _dl_larch_cpu_features
>>>> +# endif
>>>> +# ifndef PROCINFO_DECL
>>>> += { }
>>>> +# endif
>>>> +# if !defined SHARED || defined PROCINFO_DECL
>>>> +;
>>>> +# else
>>>> +,
>>>> +# endif
>>>> +#endif
>>>> +
>>>> +#undef PROCINFO_DECL
>>>> +#undef PROCINFO_CLASS
>>>> diff --git a/sysdeps/unix/sysv/linux/loongarch/dl-sysdep.c b/sysdeps/unix/sysv/linux/loongarch/dl-sysdep.c
>>>> new file mode 100644
>>>> index 0000000000..455fd71abc
>>>> --- /dev/null
>>>> +++ b/sysdeps/unix/sysv/linux/loongarch/dl-sysdep.c
>>>> @@ -0,0 +1,21 @@
>>>> +/* Operating system support for run-time dynamic linker.  LoongArch version.
>>>> +   Copyright (C) 2023 Free Software Foundation, Inc.
>>>> +   This file is part of the GNU C Library.
>>>> +
>>>> +   The GNU C Library is free software; you can redistribute it and/or
>>>> +   modify it under the terms of the GNU Lesser General Public
>>>> +   License as published by the Free Software Foundation; either
>>>> +   version 2.1 of the License, or (at your option) any later version.
>>>> +
>>>> +   The GNU C Library is distributed in the hope that it will be useful,
>>>> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
>>>> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>>>> +   Lesser General Public License for more details.
>>>> +
>>>> +   You should have received a copy of the GNU Lesser General Public
>>>> +   License along with the GNU C Library; if not, see
>>>> +   <http://www.gnu.org/licenses/>.  */
>>>> +
>>>> +#include <config.h>
>>>> +#include <sysdeps/loongarch/cpu-tunables.c>
>>>> +#include <sysdeps/unix/sysv/linux/dl-sysdep.c>
>>>> diff --git a/sysdeps/unix/sysv/linux/loongarch/libc-start.c b/sysdeps/unix/sysv/linux/loongarch/libc-start.c
>>>> new file mode 100644
>>>> index 0000000000..f1346ece0a
>>>> --- /dev/null
>>>> +++ b/sysdeps/unix/sysv/linux/loongarch/libc-start.c
>>>> @@ -0,0 +1,34 @@
>>>> +/* Override csu/libc-start.c on LoongArch64.
>>>> +   Copyright (C) 2023 Free Software Foundation, Inc.
>>>> +   This file is part of the GNU C Library.
>>>> +
>>>> +   The GNU C Library is free software; you can redistribute it and/or
>>>> +   modify it under the terms of the GNU Lesser General Public
>>>> +   License as published by the Free Software Foundation; either
>>>> +   version 2.1 of the License, or (at your option) any later version.
>>>> +
>>>> +   The GNU C Library is distributed in the hope that it will be useful,
>>>> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
>>>> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>>>> +   Lesser General Public License for more details.
>>>> +
>>>> +   You should have received a copy of the GNU Lesser General Public
>>>> +   License along with the GNU C Library; if not, see
>>>> +   <http://www.gnu.org/licenses/>.  */
>>>> +
>>>> +#ifndef SHARED
>>>> +
>>>> +/* Mark symbols hidden in static PIE for early self relocation to work.  */
>>>> +# if BUILD_PIE_DEFAULT
>>>> +#  pragma GCC visibility push(hidden)
>>>> +# endif
>>>> +
>>>> +# include <ldsodefs.h>
>>>> +# include <cpu-features.c>
>>>> +
>>>> +extern struct cpu_features _dl_larch_cpu_features;
>>>> +
>>>> +# define ARCH_INIT_CPU_FEATURES() init_cpu_features (&_dl_larch_cpu_features)
>>>> +
>>>> +#endif
>>>> +#include <csu/libc-start.c>
>>> I think this patch misses a proper testcase, similar to one I suggested
>>> when powerpc added a similar support (check 21841f0d562f0e944c4d267a28cc3ebd19c847e9).
>>> Check sysdeps/unix/sysv/linux/powerpc/tst-hwcap-tunables.c on a way to
>>> proper check it.
>> I will add a proper testcase in the upcoming patch.
  

Patch

diff --git a/sysdeps/loongarch/Makefile b/sysdeps/loongarch/Makefile
index 43d2f583cd..30a1f4a802 100644
--- a/sysdeps/loongarch/Makefile
+++ b/sysdeps/loongarch/Makefile
@@ -6,6 +6,10 @@  ifeq ($(subdir),elf)
 gen-as-const-headers += dl-link.sym
 endif
 
+ifeq ($(subdir),elf)
+  sysdep-dl-routines += dl-get-cpu-features
+endif
+
 # LoongArch's assembler also needs to know about PIC as it changes the
 # definition of some assembler macros.
 ASFLAGS-.os += $(pic-ccflag)
diff --git a/sysdeps/loongarch/Versions b/sysdeps/loongarch/Versions
new file mode 100644
index 0000000000..33ae2cc079
--- /dev/null
+++ b/sysdeps/loongarch/Versions
@@ -0,0 +1,5 @@ 
+ld {
+  GLIBC_PRIVATE {
+    _dl_larch_get_cpu_features;
+  }
+}
diff --git a/sysdeps/loongarch/cpu-tunables.c b/sysdeps/loongarch/cpu-tunables.c
new file mode 100644
index 0000000000..8e9fab938b
--- /dev/null
+++ b/sysdeps/loongarch/cpu-tunables.c
@@ -0,0 +1,89 @@ 
+/* LoongArch CPU feature tuning.
+   This file is part of the GNU C Library.
+   Copyright (C) 2023 Free Software Foundation, Inc.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+# include <stdbool.h>
+# include <stdint.h>
+# include <unistd.h>		/* Get STDOUT_FILENO for _dl_printf.  */
+# include <elf/dl-tunables.h>
+# include <string.h>
+# include <cpu-features.h>
+# include <ldsodefs.h>
+# include <sys/auxv.h>
+
+# define HWCAP_LOONGARCH_IFUNC \
+  (HWCAP_LOONGARCH_UAL | HWCAP_LOONGARCH_LSX | HWCAP_LOONGARCH_LASX)
+
+# define CHECK_GLIBC_IFUNC_CPU_OFF(f, name, len)			\
+  _Static_assert (sizeof (#name) - 1 == len, #name " != " #len);	\
+  if (!memcmp (f, #name, len) &&					\
+      (GLRO (dl_hwcap) & HWCAP_LOONGARCH_##name))			\
+    {									\
+      hwcap |= (HWCAP_LOONGARCH_##name | (~HWCAP_LOONGARCH_IFUNC));	\
+      break;								\
+    }									\
+
+attribute_hidden
+void
+TUNABLE_CALLBACK (set_hwcaps) (tunable_val_t *valp)
+{
+  const char *p = valp->strval;
+  size_t len;
+  unsigned long hwcap = 0;
+  const char *c;
+
+  do {
+      for (c = p; *c != ','; c++)
+	if (*c == '\0')
+	  break;
+
+      len = c - p;
+
+      switch(len)
+      {
+	default:
+	  _dl_fatal_printf (
+	    "The valid values of glibc.cpu.hwcaps is UAL, LASX, LSX!!\n"
+			    );
+	  break;
+	case 3:
+	  {
+	    CHECK_GLIBC_IFUNC_CPU_OFF (p, LSX, 3);
+	    CHECK_GLIBC_IFUNC_CPU_OFF (p, UAL, 3);
+	    _dl_fatal_printf (
+		"Some features are invalid or not supported on this machine!!\n"
+		"The valid values of glibc.cpu.hwcaps is UAL, LASX, LSX!!\n"
+                       );
+	  }
+	  break;
+	case 4:
+	  {
+	    CHECK_GLIBC_IFUNC_CPU_OFF (p, LASX, 4);
+	    _dl_fatal_printf (
+		"Some features are invalid or not supported on this machine!!\n"
+		"The valid values of glibc.cpu.hwcaps is UAL, LASX, LSX!!\n"
+                       );
+	  }
+	  break;
+      }
+
+      p += len + 1;
+    }
+  while (*c != '\0');
+
+  GLRO (dl_larch_cpu_features).hwcap &= hwcap;
+}
diff --git a/sysdeps/loongarch/dl-get-cpu-features.c b/sysdeps/loongarch/dl-get-cpu-features.c
new file mode 100644
index 0000000000..7cd9bc15c3
--- /dev/null
+++ b/sysdeps/loongarch/dl-get-cpu-features.c
@@ -0,0 +1,25 @@ 
+/* Define _dl_larch_get_cpu_features.
+   Copyright (C) 2023 Free Software Foundation, Inc.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+
+#include <ldsodefs.h>
+
+const struct cpu_features *
+_dl_larch_get_cpu_features (void)
+{
+  return &GLRO(dl_larch_cpu_features);
+}
diff --git a/sysdeps/loongarch/dl-machine.h b/sysdeps/loongarch/dl-machine.h
index 57913cefaa..b395a9283e 100644
--- a/sysdeps/loongarch/dl-machine.h
+++ b/sysdeps/loongarch/dl-machine.h
@@ -29,6 +29,8 @@ 
 #include <dl-static-tls.h>
 #include <dl-machine-rel.h>
 
+#include <cpu-features.c>
+
 #ifndef _RTLD_PROLOGUE
 # define _RTLD_PROLOGUE(entry)					\
 	".globl\t" __STRING (entry) "\n\t"			\
@@ -53,6 +55,23 @@ 
 #define ELF_MACHINE_NO_REL 1
 #define ELF_MACHINE_NO_RELA 0
 
+#define DL_PLATFORM_INIT dl_platform_init ()
+
+static inline void __attribute__ ((unused))
+dl_platform_init (void)
+{
+  if (GLRO(dl_platform) != NULL && *GLRO(dl_platform) == '\0')
+    /* Avoid an empty string which would disturb us.  */
+    GLRO(dl_platform) = NULL;
+
+#ifdef SHARED
+  /* init_cpu_features has been called early from __libc_start_main in
+     static executable.  */
+  init_cpu_features (&GLRO(dl_larch_cpu_features));
+#endif
+}
+
+
 /* Return nonzero iff ELF header is compatible with the running host.  */
 static inline int
 elf_machine_matches_host (const ElfW (Ehdr) *ehdr)
@@ -290,9 +309,9 @@  elf_machine_runtime_setup (struct link_map *l, struct r_scope_elem *scope[],
       if (profile != 0)
 	{
 #if !defined __loongarch_soft_float
-	  if (SUPPORT_LASX)
+	  if (RTLD_SUPPORT_LASX)
 	    gotplt[0] = (ElfW(Addr)) &_dl_runtime_profile_lasx;
-	  else if (SUPPORT_LSX)
+	  else if (RTLD_SUPPORT_LSX)
 	    gotplt[0] = (ElfW(Addr)) &_dl_runtime_profile_lsx;
 	  else
 #endif
@@ -310,9 +329,9 @@  elf_machine_runtime_setup (struct link_map *l, struct r_scope_elem *scope[],
 	     indicated by the offset on the stack, and then jump to
 	     the resolved address.  */
 #if !defined __loongarch_soft_float
-	  if (SUPPORT_LASX)
+	  if (RTLD_SUPPORT_LASX)
 	    gotplt[0] = (ElfW(Addr)) &_dl_runtime_resolve_lasx;
-	  else if (SUPPORT_LSX)
+	  else if (RTLD_SUPPORT_LSX)
 	    gotplt[0] = (ElfW(Addr)) &_dl_runtime_resolve_lsx;
 	  else
 #endif
diff --git a/sysdeps/loongarch/dl-tunables.list b/sysdeps/loongarch/dl-tunables.list
new file mode 100644
index 0000000000..66b3427516
--- /dev/null
+++ b/sysdeps/loongarch/dl-tunables.list
@@ -0,0 +1,25 @@ 
+# LoongArch specific tunables.
+# Copyright (C) 2023 Free Software Foundation, Inc.
+# This file is part of the GNU C Library.
+
+# The GNU C Library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+
+# The GNU C Library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+
+# You should have received a copy of the GNU Lesser General Public
+# License along with the GNU C Library; if not, see
+# <http://www.gnu.org/licenses/>.
+
+glibc {
+  cpu {
+    hwcaps {
+      type: STRING
+    }
+  }
+}
diff --git a/sysdeps/unix/sysv/linux/loongarch/cpu-features.c b/sysdeps/unix/sysv/linux/loongarch/cpu-features.c
new file mode 100644
index 0000000000..1290c4ce9f
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/loongarch/cpu-features.c
@@ -0,0 +1,29 @@ 
+/* Initialize CPU feature data.  LoongArch64 version.
+   This file is part of the GNU C Library.
+   Copyright (C) 2023 Free Software Foundation, Inc.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <cpu-features.h>
+#include <elf/dl-hwcaps.h>
+#include <elf/dl-tunables.h>
+extern void TUNABLE_CALLBACK (set_hwcaps) (tunable_val_t *) attribute_hidden;
+
+static inline void
+init_cpu_features (struct cpu_features *cpu_features)
+{
+    GLRO (dl_larch_cpu_features).hwcap = GLRO (dl_hwcap);
+    TUNABLE_GET (glibc, cpu, hwcaps, tunable_val_t *, TUNABLE_CALLBACK (set_hwcaps));
+}
diff --git a/sysdeps/unix/sysv/linux/loongarch/cpu-features.h b/sysdeps/unix/sysv/linux/loongarch/cpu-features.h
index d1a280a5ee..450963cebc 100644
--- a/sysdeps/unix/sysv/linux/loongarch/cpu-features.h
+++ b/sysdeps/unix/sysv/linux/loongarch/cpu-features.h
@@ -19,13 +19,23 @@ 
 #ifndef _CPU_FEATURES_LOONGARCH64_H
 #define _CPU_FEATURES_LOONGARCH64_H
 
+#include <stdint.h>
 #include <sys/auxv.h>
 
-#define SUPPORT_UAL (GLRO (dl_hwcap) & HWCAP_LOONGARCH_UAL)
-#define SUPPORT_LSX (GLRO (dl_hwcap) & HWCAP_LOONGARCH_LSX)
-#define SUPPORT_LASX (GLRO (dl_hwcap) & HWCAP_LOONGARCH_LASX)
+struct cpu_features
+ {
+    uint64_t hwcap;
+ };
 
+/* Get a pointer to the CPU features structure.  */
+extern const struct cpu_features *_dl_larch_get_cpu_features (void)
+     __attribute__ ((pure));
+
+#define SUPPORT_UAL (GLRO (dl_larch_cpu_features).hwcap & HWCAP_LOONGARCH_UAL)
+#define SUPPORT_LSX (GLRO (dl_larch_cpu_features).hwcap & HWCAP_LOONGARCH_LSX)
+#define SUPPORT_LASX (GLRO (dl_larch_cpu_features).hwcap & HWCAP_LOONGARCH_LASX)
+#define RTLD_SUPPORT_LSX (GLRO (dl_hwcap) & HWCAP_LOONGARCH_LSX)
+#define RTLD_SUPPORT_LASX (GLRO (dl_hwcap) & HWCAP_LOONGARCH_LASX)
 #define INIT_ARCH()
 
 #endif /* _CPU_FEATURES_LOONGARCH64_H  */
-
diff --git a/sysdeps/unix/sysv/linux/loongarch/dl-procinfo.c b/sysdeps/unix/sysv/linux/loongarch/dl-procinfo.c
new file mode 100644
index 0000000000..6217fda983
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/loongarch/dl-procinfo.c
@@ -0,0 +1,60 @@ 
+/* Data for LoongArch64 version of processor capability information.
+   Linux version.
+   Copyright (C) 2023 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+/* If anything should be added here check whether the size of each string
+   is still ok with the given array size.
+
+   All the #ifdefs in the definitions are quite irritating but
+   necessary if we want to avoid duplicating the information.  There
+   are three different modes:
+
+   - PROCINFO_DECL is defined.  This means we are only interested in
+     declarations.
+
+   - PROCINFO_DECL is not defined:
+
+     + if SHARED is defined the file is included in an array
+       initializer.  The .element = { ... } syntax is needed.
+
+     + if SHARED is not defined a normal array initialization is
+       needed.
+  */
+
+#ifndef PROCINFO_CLASS
+# define PROCINFO_CLASS
+#endif
+
+#if !IS_IN (ldconfig)
+# if !defined PROCINFO_DECL && defined SHARED
+  ._dl_larch_cpu_features
+# else
+PROCINFO_CLASS struct cpu_features _dl_larch_cpu_features
+# endif
+# ifndef PROCINFO_DECL
+= { }
+# endif
+# if !defined SHARED || defined PROCINFO_DECL
+;
+# else
+,
+# endif
+#endif
+
+#undef PROCINFO_DECL
+#undef PROCINFO_CLASS
diff --git a/sysdeps/unix/sysv/linux/loongarch/dl-sysdep.c b/sysdeps/unix/sysv/linux/loongarch/dl-sysdep.c
new file mode 100644
index 0000000000..455fd71abc
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/loongarch/dl-sysdep.c
@@ -0,0 +1,21 @@ 
+/* Operating system support for run-time dynamic linker.  LoongArch version.
+   Copyright (C) 2023 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+#include <sysdeps/loongarch/cpu-tunables.c>
+#include <sysdeps/unix/sysv/linux/dl-sysdep.c>
diff --git a/sysdeps/unix/sysv/linux/loongarch/libc-start.c b/sysdeps/unix/sysv/linux/loongarch/libc-start.c
new file mode 100644
index 0000000000..f1346ece0a
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/loongarch/libc-start.c
@@ -0,0 +1,34 @@ 
+/* Override csu/libc-start.c on LoongArch64.
+   Copyright (C) 2023 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef SHARED
+
+/* Mark symbols hidden in static PIE for early self relocation to work.  */
+# if BUILD_PIE_DEFAULT
+#  pragma GCC visibility push(hidden)
+# endif
+
+# include <ldsodefs.h>
+# include <cpu-features.c>
+
+extern struct cpu_features _dl_larch_cpu_features;
+
+# define ARCH_INIT_CPU_FEATURES() init_cpu_features (&_dl_larch_cpu_features)
+
+#endif
+#include <csu/libc-start.c>