public inbox for libc-alpha@sourceware.org
 help / color / mirror / Atom feed
* [PATCH] LoongArch: Add glibc.cpu.hwcap support.
@ 2024-04-23 12:48 caiyinyu
  2024-04-23 20:10 ` Adhemerval Zanella Netto
  0 siblings, 1 reply; 10+ messages in thread
From: caiyinyu @ 2024-04-23 12:48 UTC (permalink / raw)
  To: libc-alpha; +Cc: adhemerval.zanella, xry111, caiyinyu

The current IFUNC selection is always using the most recent
features which are available via AT_HWCAP.  But in
some scenarios it is useful to adjust this selection.

The environment variable:

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

can be used to enable HWCAP feature yyy, disable HWCAP feature xxx,
where the feature name is case-sensitive and has to match the ones
used in sysdeps/loongarch/cpu-tunables.c.
---
 manual/tunables.texi                          |   5 +-
 sysdeps/loongarch/Makefile                    |  12 ++
 sysdeps/loongarch/cpu-tunables.c              |  87 +++++++++++
 sysdeps/loongarch/dl-get-cpu-features.c       |  25 ++++
 sysdeps/loongarch/dl-machine.h                |  29 +++-
 sysdeps/loongarch/dl-tunables.list            |  25 ++++
 .../lp64/multiarch/dl-symbol-redir-ifunc.h    |   3 +
 sysdeps/loongarch/tst-hwcap-tunables.c        | 136 ++++++++++++++++++
 .../unix/sysv/linux/loongarch/cpu-features.c  |  30 ++++
 .../unix/sysv/linux/loongarch/cpu-features.h  |  17 ++-
 .../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 +++++
 13 files changed, 475 insertions(+), 9 deletions(-)
 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/loongarch/tst-hwcap-tunables.c
 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/manual/tunables.texi b/manual/tunables.texi
index 4a7d04dc0d..baaf751721 100644
--- a/manual/tunables.texi
+++ b/manual/tunables.texi
@@ -525,7 +525,10 @@ a CPU arch-level like @code{z13} instead of single HWCAP and STFLE features.
 On powerpc, the supported HWCAP and HWCAP2 features can be found in
 @code{sysdeps/powerpc/dl-procinfo.c}.
 
-This tunable is specific to i386, x86-64, s390x and powerpc.
+On loongarch, the supported HWCAP features can be found in
+@code{sysdeps/loongarch/cpu-tunables.c}.
+
+This tunable is specific to i386, x86-64, s390x, powerpc and loongarch.
 @end deftp
 
 @deftp Tunable glibc.cpu.cached_memopt
diff --git a/sysdeps/loongarch/Makefile b/sysdeps/loongarch/Makefile
index 43d2f583cd..965daae571 100644
--- a/sysdeps/loongarch/Makefile
+++ b/sysdeps/loongarch/Makefile
@@ -1,11 +1,23 @@
 ifeq ($(subdir),misc)
 sysdep_headers += sys/asm.h
+
+tests += \
+	tst-hwcap-tunables \
+	# tests
+
+tst-hwcap-tunables-ARGS = -- $(host-test-program-cmd)
 endif
 
 ifeq ($(subdir),elf)
 gen-as-const-headers += dl-link.sym
 endif
 
+ifeq ($(subdir),elf)
+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/cpu-tunables.c b/sysdeps/loongarch/cpu-tunables.c
new file mode 100644
index 0000000000..e274e993c1
--- /dev/null
+++ b/sysdeps/loongarch/cpu-tunables.c
@@ -0,0 +1,87 @@
+/* LoongArch CPU feature tuning.
+   This file is part of the GNU C Library.
+   Copyright (C) 2024 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>
+#include <dl-tunables-parse.h>
+#include <dl-symbol-redir-ifunc.h>
+
+#define CHECK_GLIBC_IFUNC_CPU(f, name, len)			\
+  _Static_assert (sizeof (#name) - 1 == len, #name " != " #len);	\
+  if (tunable_str_comma_strcmp_cte (&f, #name))				\
+    {									\
+      if (f.disable)							\
+	GLRO(dl_larch_cpu_features).hwcap &= (~HWCAP_LOONGARCH_##name);	\
+      else								\
+	GLRO(dl_larch_cpu_features).hwcap |= HWCAP_LOONGARCH_##name;	\
+      break;								\
+    }
+
+attribute_hidden void
+TUNABLE_CALLBACK (set_hwcaps) (tunable_val_t *valp)
+{
+  /* The current IFUNC selection is based on microbenchmarks in glibc.
+     It should give the best performance for most workloads.  But other
+     choices may have better performance for a particular workload or on
+     the hardware which wasn't available when the selection was made.
+     The environment variable:
+
+     GLIBC_TUNABLES=glibc.cpu.hwcaps=-xxx,yyy,-zzz,....
+
+     can be used to enable CPU/ARCH feature yyy, disable CPU/ARCH feature
+     yyy and zzz, where the feature name is case-sensitive and has to
+     match the ones in cpu-features.h.  It can be used by glibc developers
+     to tune for a new processor or override the IFUNC selection to
+     improve performance for a particular workload.
+
+     NOTE: the IFUNC selection may change over time.  Please check all
+     multiarch implementations when experimenting.  */
+
+  struct tunable_str_comma_state_t ts;
+  tunable_str_comma_init (&ts, valp);
+
+  struct tunable_str_comma_t n;
+  while (tunable_str_comma_next (&ts, &n))
+    {
+      switch (n.len)
+	{
+	default:
+	  break;
+	case 3:
+	  {
+	    CHECK_GLIBC_IFUNC_CPU (n, LSX, 3);
+	    CHECK_GLIBC_IFUNC_CPU (n, UAL, 3);
+	  }
+	  break;
+	case 4:
+	  {
+	    CHECK_GLIBC_IFUNC_CPU (n, LASX, 4);
+	  }
+	  break;
+	}
+    }
+
+  /* Ensure that the user has not enabled any unsupported features.  */
+  GLRO(dl_larch_cpu_features).hwcap &= GLRO(dl_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..3dcecefbcd
--- /dev/null
+++ b/sysdeps/loongarch/dl-get-cpu-features.c
@@ -0,0 +1,25 @@
+/* Define _dl_larch_get_cpu_features.
+   Copyright (C) 2024 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 ab81b82d95..6baf0e600a 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,10 +309,10 @@ elf_machine_runtime_setup (struct link_map *l, struct r_scope_elem *scope[],
 #ifdef SHARED
       if (profile != 0)
 	{
-# if !defined __loongarch_soft_float
-	  if (SUPPORT_LASX)
+#if !defined __loongarch_soft_float
+	  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
@@ -312,9 +331,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..00869a9fad
--- /dev/null
+++ b/sysdeps/loongarch/dl-tunables.list
@@ -0,0 +1,25 @@
+# LoongArch specific tunables.
+# Copyright (C) 2024 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/loongarch/lp64/multiarch/dl-symbol-redir-ifunc.h b/sysdeps/loongarch/lp64/multiarch/dl-symbol-redir-ifunc.h
index cb640d77b7..a73390b12f 100644
--- a/sysdeps/loongarch/lp64/multiarch/dl-symbol-redir-ifunc.h
+++ b/sysdeps/loongarch/lp64/multiarch/dl-symbol-redir-ifunc.h
@@ -19,6 +19,9 @@
 #ifndef _DL_IFUNC_GENERIC_H
 #define _DL_IFUNC_GENERIC_H
 
+#ifndef SHARED
 asm ("memset = __memset_aligned");
+asm ("memcmp = __memcmp_aligned");
+#endif
 
 #endif
diff --git a/sysdeps/loongarch/tst-hwcap-tunables.c b/sysdeps/loongarch/tst-hwcap-tunables.c
new file mode 100644
index 0000000000..e6856ad042
--- /dev/null
+++ b/sysdeps/loongarch/tst-hwcap-tunables.c
@@ -0,0 +1,136 @@
+/* Tests for powerpc GLIBC_TUNABLES=glibc.cpu.hwcaps filter.
+   Copyright (C) 2024 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 <array_length.h>
+#include <getopt.h>
+#include <ifunc-impl-list.h>
+#include <spawn.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <support/check.h>
+#include <support/support.h>
+#include <support/xunistd.h>
+#include <sys/auxv.h>
+#include <sys/wait.h>
+
+/* Nonzero if the program gets called via `exec'.  */
+#define CMDLINE_OPTIONS \
+  { "restart", no_argument, &restart, 1 }, \
+  { "enable", no_argument, &enable, 1 },
+static int restart;
+static int enable;
+
+/* Hold the four initial argument used to respawn the process, plus the extra
+   '--direct', '--restart', and the function to check.  */
+static char *spargs[9];
+static int fc;
+
+/* Called on process re-execution.  */
+_Noreturn static void
+handle_restart (int argc, char *argv[])
+{
+  TEST_VERIFY_EXIT (argc == 1);
+  const char *funcname = argv[0];
+
+  struct libc_ifunc_impl impls[32];
+  int cnt = __libc_ifunc_impl_list ("memcpy", impls, array_length (impls));
+  if (cnt == 0)
+    _exit (EXIT_SUCCESS);
+  TEST_VERIFY_EXIT (cnt >= 1);
+  for (int i = 0; i < cnt; i++)
+  {
+    if (strcmp (impls[i].name, funcname) == 0)
+      {
+	if (enable && impls[i].usable != true)
+	  FAIL_EXIT1 ("FAIL: %s ifunc selection is not enabled.\n", funcname);
+	else if (!enable && impls[i].usable != false)
+	  FAIL_EXIT1 ("FAIL: %s ifunc selection is not disabled.\n", funcname);
+	break;
+      }
+  }
+
+  _exit (EXIT_SUCCESS);
+}
+
+static void
+run_test (const char *filter, const char *funcname, int disable)
+{
+  if (disable)
+    printf ("info: checking filter %s (expect %s ifunc "
+	    "selection to be disabled)\n", filter, funcname);
+  else
+    {
+      printf ("info: checking filter %s (expect %s ifunc "
+	      "selection to be enabled)\n", filter, funcname);
+      spargs[fc++] = (char *) "--enable";
+    }
+
+  char *tunable = xasprintf ("GLIBC_TUNABLES=glibc.cpu.hwcaps=%s", filter);
+  char *const newenvs[] = { (char*) tunable, NULL };
+  spargs[fc] = (char *) funcname;
+
+  pid_t pid;
+  TEST_COMPARE (posix_spawn (&pid, spargs[0], NULL, NULL, spargs, newenvs), 0);
+  int status;
+  TEST_COMPARE (xwaitpid (pid, &status, 0), pid);
+  TEST_VERIFY (WIFEXITED (status));
+  TEST_VERIFY (!WIFSIGNALED (status));
+  TEST_COMPARE (WEXITSTATUS (status), 0);
+
+  if (!disable)
+    fc--;
+  free (tunable);
+}
+
+static int
+do_test (int argc, char *argv[])
+{
+  if (restart)
+    handle_restart (argc - 1, &argv[1]);
+
+  TEST_VERIFY_EXIT (argc == 2 || argc == 5);
+
+  int i;
+  for (i = 0; i < argc - 1; i++)
+    spargs[i] = argv[i + 1];
+  spargs[i++] = (char *) "--direct";
+  spargs[i++] = (char *) "--restart";
+  fc = i++;
+  spargs[i] = NULL;
+
+  unsigned long int hwcap = getauxval (AT_HWCAP);
+
+  if (hwcap & HWCAP_LOONGARCH_LASX)
+    run_test ("-LASX", "__memcpy_lasx", 1);
+  if (hwcap & HWCAP_LOONGARCH_LSX)
+    run_test ("-LSX", "__memcpy_lsx", 1);
+  if (hwcap & HWCAP_LOONGARCH_UAL)
+    run_test ("-UAL", "__memcpy_unaligned", 1);
+
+  /* __memcpy_aligned is the default ifunc selection and will be
+   * always enabled.  */
+  run_test ("-LASX,-LSX,-UAL", "__memcpy_aligned", 0);
+  run_test ("-LASX,-LSX", "__memcpy_aligned", 0);
+  run_test ("-LASX", "__memcpy_aligned", 0);
+
+  return 0;
+}
+
+#define TEST_FUNCTION_ARGV do_test
+#include <support/test-driver.c>
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..9c526516d8
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/loongarch/cpu-features.c
@@ -0,0 +1,30 @@
+/* Initialize CPU feature data.  LoongArch64 version.
+   This file is part of the GNU C Library.
+   Copyright (C) 2024 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 4e863c7469..eec51956a9 100644
--- a/sysdeps/unix/sysv/linux/loongarch/cpu-features.h
+++ b/sysdeps/unix/sysv/linux/loongarch/cpu-features.h
@@ -19,12 +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..5e056a1923
--- /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) 2024 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..30b84f1911
--- /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) 2024 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..e545f7f1d7
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/loongarch/libc-start.c
@@ -0,0 +1,34 @@
+/* Override csu/libc-start.c on LoongArch64.
+   Copyright (C) 2024 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>
-- 
2.43.0


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] LoongArch: Add glibc.cpu.hwcap support.
  2024-04-23 12:48 [PATCH] LoongArch: Add glibc.cpu.hwcap support caiyinyu
@ 2024-04-23 20:10 ` Adhemerval Zanella Netto
  0 siblings, 0 replies; 10+ messages in thread
From: Adhemerval Zanella Netto @ 2024-04-23 20:10 UTC (permalink / raw)
  To: caiyinyu, libc-alpha; +Cc: xry111



On 23/04/24 09:48, caiyinyu wrote:
> The current IFUNC selection is always using the most recent
> features which are available via AT_HWCAP.  But in
> some scenarios it is useful to adjust this selection.
> 
> The environment variable:
> 
> GLIBC_TUNABLES=glibc.cpu.hwcaps=-xxx,yyy,zzz,....
> 
> can be used to enable HWCAP feature yyy, disable HWCAP feature xxx,
> where the feature name is case-sensitive and has to match the ones
> used in sysdeps/loongarch/cpu-tunables.c.

The patch looks good, just two minor style issues below.

> ---
>  manual/tunables.texi                          |   5 +-
>  sysdeps/loongarch/Makefile                    |  12 ++
>  sysdeps/loongarch/cpu-tunables.c              |  87 +++++++++++
>  sysdeps/loongarch/dl-get-cpu-features.c       |  25 ++++
>  sysdeps/loongarch/dl-machine.h                |  29 +++-
>  sysdeps/loongarch/dl-tunables.list            |  25 ++++
>  .../lp64/multiarch/dl-symbol-redir-ifunc.h    |   3 +
>  sysdeps/loongarch/tst-hwcap-tunables.c        | 136 ++++++++++++++++++
>  .../unix/sysv/linux/loongarch/cpu-features.c  |  30 ++++
>  .../unix/sysv/linux/loongarch/cpu-features.h  |  17 ++-
>  .../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 +++++
>  13 files changed, 475 insertions(+), 9 deletions(-)
>  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/loongarch/tst-hwcap-tunables.c
>  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/manual/tunables.texi b/manual/tunables.texi
> index 4a7d04dc0d..baaf751721 100644
> --- a/manual/tunables.texi
> +++ b/manual/tunables.texi
> @@ -525,7 +525,10 @@ a CPU arch-level like @code{z13} instead of single HWCAP and STFLE features.
>  On powerpc, the supported HWCAP and HWCAP2 features can be found in
>  @code{sysdeps/powerpc/dl-procinfo.c}.
>  
> -This tunable is specific to i386, x86-64, s390x and powerpc.
> +On loongarch, the supported HWCAP features can be found in
> +@code{sysdeps/loongarch/cpu-tunables.c}.
> +
> +This tunable is specific to i386, x86-64, s390x, powerpc and loongarch.
>  @end deftp
>  
>  @deftp Tunable glibc.cpu.cached_memopt

Ok.  As a side note, from a recent BZ report [1] I think maybe we should
start to proper document the supported HWCAP for ifunc selection instead
of reference a source file.

[1] https://sourceware.org/bugzilla/show_bug.cgi?id=31675

> diff --git a/sysdeps/loongarch/Makefile b/sysdeps/loongarch/Makefile
> index 43d2f583cd..965daae571 100644
> --- a/sysdeps/loongarch/Makefile
> +++ b/sysdeps/loongarch/Makefile
> @@ -1,11 +1,23 @@
>  ifeq ($(subdir),misc)
>  sysdep_headers += sys/asm.h
> +
> +tests += \
> +	tst-hwcap-tunables \
> +	# tests
> +
> +tst-hwcap-tunables-ARGS = -- $(host-test-program-cmd)
>  endif
>  
>  ifeq ($(subdir),elf)
>  gen-as-const-headers += dl-link.sym
>  endif
>  
> +ifeq ($(subdir),elf)
> +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)

Minor nit, other files use a double space instead of tab for each new entry.

> diff --git a/sysdeps/loongarch/cpu-tunables.c b/sysdeps/loongarch/cpu-tunables.c
> new file mode 100644
> index 0000000000..e274e993c1
> --- /dev/null
> +++ b/sysdeps/loongarch/cpu-tunables.c
> @@ -0,0 +1,87 @@
> +/* LoongArch CPU feature tuning.
> +   This file is part of the GNU C Library.
> +   Copyright (C) 2024 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>
> +#include <dl-tunables-parse.h>
> +#include <dl-symbol-redir-ifunc.h>
> +
> +#define CHECK_GLIBC_IFUNC_CPU(f, name, len)			\
> +  _Static_assert (sizeof (#name) - 1 == len, #name " != " #len);	\
> +  if (tunable_str_comma_strcmp_cte (&f, #name))				\
> +    {									\
> +      if (f.disable)							\
> +	GLRO(dl_larch_cpu_features).hwcap &= (~HWCAP_LOONGARCH_##name);	\
> +      else								\
> +	GLRO(dl_larch_cpu_features).hwcap |= HWCAP_LOONGARCH_##name;	\
> +      break;								\
> +    }
> +
> +attribute_hidden void
> +TUNABLE_CALLBACK (set_hwcaps) (tunable_val_t *valp)
> +{
> +  /* The current IFUNC selection is based on microbenchmarks in glibc.
> +     It should give the best performance for most workloads.  But other
> +     choices may have better performance for a particular workload or on
> +     the hardware which wasn't available when the selection was made.
> +     The environment variable:
> +
> +     GLIBC_TUNABLES=glibc.cpu.hwcaps=-xxx,yyy,-zzz,....
> +
> +     can be used to enable CPU/ARCH feature yyy, disable CPU/ARCH feature
> +     yyy and zzz, where the feature name is case-sensitive and has to
> +     match the ones in cpu-features.h.  It can be used by glibc developers
> +     to tune for a new processor or override the IFUNC selection to
> +     improve performance for a particular workload.
> +
> +     NOTE: the IFUNC selection may change over time.  Please check all
> +     multiarch implementations when experimenting.  */
> +
> +  struct tunable_str_comma_state_t ts;
> +  tunable_str_comma_init (&ts, valp);
> +
> +  struct tunable_str_comma_t n;
> +  while (tunable_str_comma_next (&ts, &n))
> +    {
> +      switch (n.len)
> +	{
> +	default:
> +	  break;
> +	case 3:
> +	  {
> +	    CHECK_GLIBC_IFUNC_CPU (n, LSX, 3);
> +	    CHECK_GLIBC_IFUNC_CPU (n, UAL, 3);
> +	  }
> +	  break;
> +	case 4:
> +	  {
> +	    CHECK_GLIBC_IFUNC_CPU (n, LASX, 4);
> +	  }
> +	  break;
> +	}
> +    }
> +
> +  /* Ensure that the user has not enabled any unsupported features.  */
> +  GLRO(dl_larch_cpu_features).hwcap &= GLRO(dl_hwcap);
> +}

Ok.

> diff --git a/sysdeps/loongarch/dl-get-cpu-features.c b/sysdeps/loongarch/dl-get-cpu-features.c
> new file mode 100644
> index 0000000000..3dcecefbcd
> --- /dev/null
> +++ b/sysdeps/loongarch/dl-get-cpu-features.c
> @@ -0,0 +1,25 @@
> +/* Define _dl_larch_get_cpu_features.
> +   Copyright (C) 2024 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);
> +}

Ok.

> diff --git a/sysdeps/loongarch/dl-machine.h b/sysdeps/loongarch/dl-machine.h
> index ab81b82d95..6baf0e600a 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,10 +309,10 @@ elf_machine_runtime_setup (struct link_map *l, struct r_scope_elem *scope[],
>  #ifdef SHARED
>        if (profile != 0)
>  	{
> -# if !defined __loongarch_soft_float
> -	  if (SUPPORT_LASX)
> +#if !defined __loongarch_soft_float
> +	  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
> @@ -312,9 +331,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

Ok, lazy resolvers should not depend of the glibc.cpu.hwcap value.

> diff --git a/sysdeps/loongarch/dl-tunables.list b/sysdeps/loongarch/dl-tunables.list
> new file mode 100644
> index 0000000000..00869a9fad
> --- /dev/null
> +++ b/sysdeps/loongarch/dl-tunables.list
> @@ -0,0 +1,25 @@
> +# LoongArch specific tunables.
> +# Copyright (C) 2024 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
> +    }
> +  }
> +}

Ok.

> diff --git a/sysdeps/loongarch/lp64/multiarch/dl-symbol-redir-ifunc.h b/sysdeps/loongarch/lp64/multiarch/dl-symbol-redir-ifunc.h
> index cb640d77b7..a73390b12f 100644
> --- a/sysdeps/loongarch/lp64/multiarch/dl-symbol-redir-ifunc.h
> +++ b/sysdeps/loongarch/lp64/multiarch/dl-symbol-redir-ifunc.h
> @@ -19,6 +19,9 @@
>  #ifndef _DL_IFUNC_GENERIC_H
>  #define _DL_IFUNC_GENERIC_H
>  
> +#ifndef SHARED
>  asm ("memset = __memset_aligned");
> +asm ("memcmp = __memcmp_aligned");
> +#endif
>  
>  #endif

Ok.

> diff --git a/sysdeps/loongarch/tst-hwcap-tunables.c b/sysdeps/loongarch/tst-hwcap-tunables.c
> new file mode 100644
> index 0000000000..e6856ad042
> --- /dev/null
> +++ b/sysdeps/loongarch/tst-hwcap-tunables.c
> @@ -0,0 +1,136 @@
> +/* Tests for powerpc GLIBC_TUNABLES=glibc.cpu.hwcaps filter.
> +   Copyright (C) 2024 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 <array_length.h>
> +#include <getopt.h>
> +#include <ifunc-impl-list.h>
> +#include <spawn.h>
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <string.h>
> +#include <support/check.h>
> +#include <support/support.h>
> +#include <support/xunistd.h>
> +#include <sys/auxv.h>
> +#include <sys/wait.h>
> +
> +/* Nonzero if the program gets called via `exec'.  */
> +#define CMDLINE_OPTIONS \
> +  { "restart", no_argument, &restart, 1 }, \
> +  { "enable", no_argument, &enable, 1 },
> +static int restart;
> +static int enable;
> +
> +/* Hold the four initial argument used to respawn the process, plus the extra
> +   '--direct', '--restart', and the function to check.  */
> +static char *spargs[9];
> +static int fc;
> +
> +/* Called on process re-execution.  */
> +_Noreturn static void
> +handle_restart (int argc, char *argv[])
> +{
> +  TEST_VERIFY_EXIT (argc == 1);
> +  const char *funcname = argv[0];
> +
> +  struct libc_ifunc_impl impls[32];
> +  int cnt = __libc_ifunc_impl_list ("memcpy", impls, array_length (impls));
> +  if (cnt == 0)
> +    _exit (EXIT_SUCCESS);
> +  TEST_VERIFY_EXIT (cnt >= 1);
> +  for (int i = 0; i < cnt; i++)
> +  {
> +    if (strcmp (impls[i].name, funcname) == 0)
> +      {
> +	if (enable && impls[i].usable != true)
> +	  FAIL_EXIT1 ("FAIL: %s ifunc selection is not enabled.\n", funcname);
> +	else if (!enable && impls[i].usable != false)
> +	  FAIL_EXIT1 ("FAIL: %s ifunc selection is not disabled.\n", funcname);
> +	break;
> +      }
> +  }
> +
> +  _exit (EXIT_SUCCESS);
> +}
> +
> +static void
> +run_test (const char *filter, const char *funcname, int disable)
> +{
> +  if (disable)
> +    printf ("info: checking filter %s (expect %s ifunc "
> +	    "selection to be disabled)\n", filter, funcname);
> +  else
> +    {
> +      printf ("info: checking filter %s (expect %s ifunc "
> +	      "selection to be enabled)\n", filter, funcname);
> +      spargs[fc++] = (char *) "--enable";
> +    }
> +
> +  char *tunable = xasprintf ("GLIBC_TUNABLES=glibc.cpu.hwcaps=%s", filter);
> +  char *const newenvs[] = { (char*) tunable, NULL };
> +  spargs[fc] = (char *) funcname;
> +
> +  pid_t pid;
> +  TEST_COMPARE (posix_spawn (&pid, spargs[0], NULL, NULL, spargs, newenvs), 0);
> +  int status;
> +  TEST_COMPARE (xwaitpid (pid, &status, 0), pid);
> +  TEST_VERIFY (WIFEXITED (status));
> +  TEST_VERIFY (!WIFSIGNALED (status));
> +  TEST_COMPARE (WEXITSTATUS (status), 0);
> +
> +  if (!disable)
> +    fc--;
> +  free (tunable);
> +}
> +
> +static int
> +do_test (int argc, char *argv[])
> +{
> +  if (restart)
> +    handle_restart (argc - 1, &argv[1]);
> +
> +  TEST_VERIFY_EXIT (argc == 2 || argc == 5);
> +
> +  int i;
> +  for (i = 0; i < argc - 1; i++)
> +    spargs[i] = argv[i + 1];
> +  spargs[i++] = (char *) "--direct";
> +  spargs[i++] = (char *) "--restart";
> +  fc = i++;
> +  spargs[i] = NULL;
> +
> +  unsigned long int hwcap = getauxval (AT_HWCAP);
> +
> +  if (hwcap & HWCAP_LOONGARCH_LASX)
> +    run_test ("-LASX", "__memcpy_lasx", 1);
> +  if (hwcap & HWCAP_LOONGARCH_LSX)
> +    run_test ("-LSX", "__memcpy_lsx", 1);
> +  if (hwcap & HWCAP_LOONGARCH_UAL)
> +    run_test ("-UAL", "__memcpy_unaligned", 1);
> +
> +  /* __memcpy_aligned is the default ifunc selection and will be
> +   * always enabled.  */
> +  run_test ("-LASX,-LSX,-UAL", "__memcpy_aligned", 0);
> +  run_test ("-LASX,-LSX", "__memcpy_aligned", 0);
> +  run_test ("-LASX", "__memcpy_aligned", 0);
> +
> +  return 0;
> +}
> +
> +#define TEST_FUNCTION_ARGV do_test
> +#include <support/test-driver.c>

Ok.

> 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..9c526516d8
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/loongarch/cpu-features.c
> @@ -0,0 +1,30 @@
> +/* Initialize CPU feature data.  LoongArch64 version.
> +   This file is part of the GNU C Library.
> +   Copyright (C) 2024 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));
> +}

Minor nit, the indentation should use double space.

> diff --git a/sysdeps/unix/sysv/linux/loongarch/cpu-features.h b/sysdeps/unix/sysv/linux/loongarch/cpu-features.h
> index 4e863c7469..eec51956a9 100644
> --- a/sysdeps/unix/sysv/linux/loongarch/cpu-features.h
> +++ b/sysdeps/unix/sysv/linux/loongarch/cpu-features.h
> @@ -19,12 +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  */

Ok.

> 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..5e056a1923
> --- /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) 2024 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

Ok.

> 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..30b84f1911
> --- /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) 2024 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>

Ok.

> 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..e545f7f1d7
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/loongarch/libc-start.c
> @@ -0,0 +1,34 @@
> +/* Override csu/libc-start.c on LoongArch64.
> +   Copyright (C) 2024 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>


OK.

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] LoongArch: Add glibc.cpu.hwcap support.
  2023-09-20 12:49     ` Adhemerval Zanella Netto
@ 2023-09-20 13:20       ` caiyinyu
  0 siblings, 0 replies; 10+ messages in thread
From: caiyinyu @ 2023-09-20 13:20 UTC (permalink / raw)
  To: Adhemerval Zanella Netto, libc-alpha; +Cc: xry111


在 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.


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] LoongArch: Add glibc.cpu.hwcap support.
  2023-09-20 10:15   ` caiyinyu
@ 2023-09-20 12:49     ` Adhemerval Zanella Netto
  2023-09-20 13:20       ` caiyinyu
  0 siblings, 1 reply; 10+ messages in thread
From: Adhemerval Zanella Netto @ 2023-09-20 12:49 UTC (permalink / raw)
  To: caiyinyu, libc-alpha; +Cc: xry111



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.

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] LoongArch: Add glibc.cpu.hwcap support.
  2023-09-20 10:51   ` caiyinyu
@ 2023-09-20 11:53     ` caiyinyu
  0 siblings, 0 replies; 10+ messages in thread
From: caiyinyu @ 2023-09-20 11:53 UTC (permalink / raw)
  To: Xi Ruoyao, libc-alpha; +Cc: adhemerval.zanella


在 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>


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] LoongArch: Add glibc.cpu.hwcap support.
  2023-09-19 10:11 ` Xi Ruoyao
@ 2023-09-20 10:51   ` caiyinyu
  2023-09-20 11:53     ` caiyinyu
  0 siblings, 1 reply; 10+ messages in thread
From: caiyinyu @ 2023-09-20 10:51 UTC (permalink / raw)
  To: Xi Ruoyao, libc-alpha; +Cc: adhemerval.zanella


在 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>


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] LoongArch: Add glibc.cpu.hwcap support.
  2023-09-19  9:33 ` Adhemerval Zanella Netto
@ 2023-09-20 10:15   ` caiyinyu
  2023-09-20 12:49     ` Adhemerval Zanella Netto
  0 siblings, 1 reply; 10+ messages in thread
From: caiyinyu @ 2023-09-20 10:15 UTC (permalink / raw)
  To: Adhemerval Zanella Netto, libc-alpha; +Cc: xry111

[-- Attachment #1: Type: text/plain, Size: 23017 bytes --]


在 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.

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] LoongArch: Add glibc.cpu.hwcap support.
  2023-09-17  9:48 caiyinyu
  2023-09-19  9:33 ` Adhemerval Zanella Netto
@ 2023-09-19 10:11 ` Xi Ruoyao
  2023-09-20 10:51   ` caiyinyu
  1 sibling, 1 reply; 10+ messages in thread
From: Xi Ruoyao @ 2023-09-19 10:11 UTC (permalink / raw)
  To: caiyinyu, libc-alpha; +Cc: adhemerval.zanella

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>

-- 
Xi Ruoyao <xry111@xry111.site>
School of Aerospace Science and Technology, Xidian University

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] LoongArch: Add glibc.cpu.hwcap support.
  2023-09-17  9:48 caiyinyu
@ 2023-09-19  9:33 ` Adhemerval Zanella Netto
  2023-09-20 10:15   ` caiyinyu
  2023-09-19 10:11 ` Xi Ruoyao
  1 sibling, 1 reply; 10+ messages in thread
From: Adhemerval Zanella Netto @ 2023-09-19  9:33 UTC (permalink / raw)
  To: caiyinyu, libc-alpha; +Cc: xry111



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.

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH] LoongArch: Add glibc.cpu.hwcap support.
@ 2023-09-17  9:48 caiyinyu
  2023-09-19  9:33 ` Adhemerval Zanella Netto
  2023-09-19 10:11 ` Xi Ruoyao
  0 siblings, 2 replies; 10+ messages in thread
From: caiyinyu @ 2023-09-17  9:48 UTC (permalink / raw)
  To: libc-alpha; +Cc: adhemerval.zanella, xry111, caiyinyu

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>
-- 
2.31.1


^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2024-04-23 20:10 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-04-23 12:48 [PATCH] LoongArch: Add glibc.cpu.hwcap support caiyinyu
2024-04-23 20:10 ` Adhemerval Zanella Netto
  -- strict thread matches above, loose matches on Subject: below --
2023-09-17  9:48 caiyinyu
2023-09-19  9:33 ` Adhemerval Zanella Netto
2023-09-20 10:15   ` caiyinyu
2023-09-20 12:49     ` Adhemerval Zanella Netto
2023-09-20 13:20       ` caiyinyu
2023-09-19 10:11 ` Xi Ruoyao
2023-09-20 10:51   ` caiyinyu
2023-09-20 11:53     ` caiyinyu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).