diff options
author | CoprDistGit <infra@openeuler.org> | 2024-10-09 03:36:26 +0000 |
---|---|---|
committer | CoprDistGit <infra@openeuler.org> | 2024-10-09 03:36:26 +0000 |
commit | db43dfdfa8bc2b938582aef3d87e43594c13ee50 (patch) | |
tree | 47b95b2f6ac8d8b7e6fa373a5bd7d661bf7234df /0012-AArch64-Check-kernel-version-for-SVE-ifuncs.patch | |
parent | b933872de72b006230559f77acc3ccfb38a1f343 (diff) |
automatic import of glibcopeneuler20.03
Diffstat (limited to '0012-AArch64-Check-kernel-version-for-SVE-ifuncs.patch')
-rw-r--r-- | 0012-AArch64-Check-kernel-version-for-SVE-ifuncs.patch | 153 |
1 files changed, 153 insertions, 0 deletions
diff --git a/0012-AArch64-Check-kernel-version-for-SVE-ifuncs.patch b/0012-AArch64-Check-kernel-version-for-SVE-ifuncs.patch new file mode 100644 index 0000000..687c821 --- /dev/null +++ b/0012-AArch64-Check-kernel-version-for-SVE-ifuncs.patch @@ -0,0 +1,153 @@ +From 92da7c2cfeeea36d651142f47e570dd5076bc166 Mon Sep 17 00:00:00 2001 +From: Wilco Dijkstra <wilco.dijkstra@arm.com> +Date: Thu, 21 Mar 2024 16:48:33 +0000 +Subject: [PATCH 12/26] AArch64: Check kernel version for SVE ifuncs + +Old Linux kernels disable SVE after every system call. Calling the +SVE-optimized memcpy afterwards will then cause a trap to reenable SVE. +As a result, applications with a high use of syscalls may run slower with +the SVE memcpy. This is true for kernels between 4.15.0 and before 6.2.0, +except for 5.14.0 which was patched. Avoid this by checking the kernel +version and selecting the SVE ifunc on modern kernels. + +Parse the kernel version reported by uname() into a 24-bit kernel.major.minor +value without calling any library functions. If uname() is not supported or +if the version format is not recognized, assume the kernel is modern. + +Tested-by: Florian Weimer <fweimer@redhat.com> +Reviewed-by: Szabolcs Nagy <szabolcs.nagy@arm.com> +(cherry picked from commit 2e94e2f5d2bf2de124c8ad7da85463355e54ccb2) +--- + sysdeps/aarch64/multiarch/init-arch.h | 2 + + sysdeps/aarch64/multiarch/memcpy.c | 2 +- + sysdeps/aarch64/multiarch/memmove.c | 2 +- + .../unix/sysv/linux/aarch64/cpu-features.c | 48 +++++++++++++++++++ + .../unix/sysv/linux/aarch64/cpu-features.h | 1 + + 5 files changed, 53 insertions(+), 2 deletions(-) + +diff --git a/sysdeps/aarch64/multiarch/init-arch.h b/sysdeps/aarch64/multiarch/init-arch.h +index e23e6ff290..daef631e04 100644 +--- a/sysdeps/aarch64/multiarch/init-arch.h ++++ b/sysdeps/aarch64/multiarch/init-arch.h +@@ -36,5 +36,7 @@ + MTE_ENABLED (); \ + bool __attribute__((unused)) sve = \ + GLRO(dl_aarch64_cpu_features).sve; \ ++ bool __attribute__((unused)) prefer_sve_ifuncs = \ ++ GLRO(dl_aarch64_cpu_features).prefer_sve_ifuncs; \ + bool __attribute__((unused)) mops = \ + GLRO(dl_aarch64_cpu_features).mops; +diff --git a/sysdeps/aarch64/multiarch/memcpy.c b/sysdeps/aarch64/multiarch/memcpy.c +index 6471fe82e3..e7c7795db6 100644 +--- a/sysdeps/aarch64/multiarch/memcpy.c ++++ b/sysdeps/aarch64/multiarch/memcpy.c +@@ -47,7 +47,7 @@ select_memcpy_ifunc (void) + { + if (IS_A64FX (midr)) + return __memcpy_a64fx; +- return __memcpy_sve; ++ return prefer_sve_ifuncs ? __memcpy_sve : __memcpy_generic; + } + + if (IS_THUNDERX (midr)) +diff --git a/sysdeps/aarch64/multiarch/memmove.c b/sysdeps/aarch64/multiarch/memmove.c +index 7602a5d57d..6b77166851 100644 +--- a/sysdeps/aarch64/multiarch/memmove.c ++++ b/sysdeps/aarch64/multiarch/memmove.c +@@ -47,7 +47,7 @@ select_memmove_ifunc (void) + { + if (IS_A64FX (midr)) + return __memmove_a64fx; +- return __memmove_sve; ++ return prefer_sve_ifuncs ? __memmove_sve : __memmove_generic; + } + + if (IS_THUNDERX (midr)) +diff --git a/sysdeps/unix/sysv/linux/aarch64/cpu-features.c b/sysdeps/unix/sysv/linux/aarch64/cpu-features.c +index a11a86efab..4a205a6b35 100644 +--- a/sysdeps/unix/sysv/linux/aarch64/cpu-features.c ++++ b/sysdeps/unix/sysv/linux/aarch64/cpu-features.c +@@ -20,6 +20,7 @@ + #include <sys/auxv.h> + #include <elf/dl-hwcaps.h> + #include <sys/prctl.h> ++#include <sys/utsname.h> + + #define DCZID_DZP_MASK (1 << 4) + #define DCZID_BS_MASK (0xf) +@@ -57,6 +58,46 @@ get_midr_from_mcpu (const char *mcpu) + return UINT64_MAX; + } + ++#if __LINUX_KERNEL_VERSION < 0x060200 ++ ++/* Return true if we prefer using SVE in string ifuncs. Old kernels disable ++ SVE after every system call which results in unnecessary traps if memcpy ++ uses SVE. This is true for kernels between 4.15.0 and before 6.2.0, except ++ for 5.14.0 which was patched. For these versions return false to avoid using ++ SVE ifuncs. ++ Parse the kernel version into a 24-bit kernel.major.minor value without ++ calling any library functions. If uname() is not supported or if the version ++ format is not recognized, assume the kernel is modern and return true. */ ++ ++static inline bool ++prefer_sve_ifuncs (void) ++{ ++ struct utsname buf; ++ const char *p = &buf.release[0]; ++ int kernel = 0; ++ int val; ++ ++ if (__uname (&buf) < 0) ++ return true; ++ ++ for (int shift = 16; shift >= 0; shift -= 8) ++ { ++ for (val = 0; *p >= '0' && *p <= '9'; p++) ++ val = val * 10 + *p - '0'; ++ kernel |= (val & 255) << shift; ++ if (*p++ != '.') ++ break; ++ } ++ ++ if (kernel >= 0x060200 || kernel == 0x050e00) ++ return true; ++ if (kernel >= 0x040f00) ++ return false; ++ return true; ++} ++ ++#endif ++ + static inline void + init_cpu_features (struct cpu_features *cpu_features) + { +@@ -119,6 +160,13 @@ init_cpu_features (struct cpu_features *cpu_features) + /* Check if SVE is supported. */ + cpu_features->sve = GLRO (dl_hwcap) & HWCAP_SVE; + ++ cpu_features->prefer_sve_ifuncs = cpu_features->sve; ++ ++#if __LINUX_KERNEL_VERSION < 0x060200 ++ if (cpu_features->sve) ++ cpu_features->prefer_sve_ifuncs = prefer_sve_ifuncs (); ++#endif ++ + /* Check if MOPS is supported. */ + cpu_features->mops = GLRO (dl_hwcap2) & HWCAP2_MOPS; + } +diff --git a/sysdeps/unix/sysv/linux/aarch64/cpu-features.h b/sysdeps/unix/sysv/linux/aarch64/cpu-features.h +index 2cf745cd19..351a619dcb 100644 +--- a/sysdeps/unix/sysv/linux/aarch64/cpu-features.h ++++ b/sysdeps/unix/sysv/linux/aarch64/cpu-features.h +@@ -71,6 +71,7 @@ struct cpu_features + /* Currently, the GLIBC memory tagging tunable only defines 8 bits. */ + uint8_t mte_state; + bool sve; ++ bool prefer_sve_ifuncs; + bool mops; + }; + +-- +2.33.0 + |