[PATCH v2] S390: Add new s390 platform z17.

Stefan Liebler stli@linux.ibm.com
Mon May 5 08:35:47 GMT 2025


Hi,

I've just committed the patch.

For the records regarding:
linaro-tcwg-bot/tcwg_glibc_check--master-arm fail

https://lists.linaro.org/archives/list/linaro-toolchain@lists.linaro.org/thread/N5NFKJW3MQ2X4MCCGZ6WSE2ARNOFH5JS/

Bye,
Stefan

On 4/29/25 13:28, Stefan Liebler wrote:
> Hi,
> need a V2: stfle_bits on stack in init_cpu_features_no_tunables() needs to be
> zeroed before usage.  If there is no more feedback, I will commit this patch shortly.
> Bye,
> Stefan
> 
> The glibc-hwcaps subdirectories are extended by "z17".  Libraries are loaded if
> the z17 facility bits are active:
> - Miscellaneous-instruction-extensions facility 4
> - Vector-enhancements-facility 3
> - Vector-Packed-Decimal-Enhancement Facility 3
> - CPU: Concurrent-Functions Facility
> 
> tst-glibc-hwcaps.c is extended in order to test z17 via new marker6.
> In case of running on a z17 with a kernel not recognizing z17 yet,
> AT_PLATFORM will be z900 but vector-bit in AT_HWCAP is set.  This situation
> is now recognized and this testcase does not fail.
> 
> A fatal glibc error is dumped if glibc was build with architecture
> level set for z17, but run on an older machine (See dl-hwcap-check.h).
> Note, you might get an SIGILL before this check if you don't use:
> configure --with-rtld-early-cflags=-march=<older-machine>
> 
> ld.so --list-diagnostics now also dumps information about s390.cpu_features.
> 
> Independent from z17, the s390x kernel won't introduce new HWCAP-Bits if there
> is no special handling needed in kernel itself.  For z17, we don't have new
> HWCAP flags, but have to check the facility bits retrieved by
> stfle-instruction.
> 
> Instead of storing all the stfle-bits (currently four 64bit values) in the
> cpu_features struct, we now only store those bits, which are needed within
> glibc itself.  Note that we have this list twice, one with original values and
> the other one which can be filtered with GLIBC_TUNABLES=glibc.cpu.hwcaps.
> Those new fields are stored in so far reserved space in cpu_features struct.
> Thus processes started in between the update of glibc package and we e.g. have
> a new ld.so and an old libc.so, won't crash. The glibc internal ifunc-resolvers
> would not select the best optimized variant.
> 
> The users of stfle-bits are also updated:
> - parsing of GLIBC_TUNABLES=glibc.cpu.hwcaps
> - glibc internal ifunc-resolvers
> - __libc_ifunc_impl_list
> - sysconf
> ---
>  elf/Makefile                             |  9 +++
>  elf/tst-glibc-hwcaps-cache.script        |  7 +++
>  sysdeps/s390/cpu-features.c              | 77 ++++++++++++++++++------
>  sysdeps/s390/cpu-features.h              | 55 +++++++++++++----
>  sysdeps/s390/dl-diagnostics-cpu.c        | 37 ++++++++++++
>  sysdeps/s390/multiarch/ifunc-impl-list.c |  4 +-
>  sysdeps/s390/multiarch/ifunc-resolve.h   |  2 +-
>  sysdeps/s390/s390-64/Makefile            | 27 ++++++++-
>  sysdeps/s390/s390-64/dl-hwcap-check.h    | 21 ++++++-
>  sysdeps/s390/s390-64/dl-hwcaps-subdirs.c | 12 +++-
>  sysdeps/s390/s390-64/tst-glibc-hwcaps.c  | 52 +++++++++++-----
>  sysdeps/unix/sysv/linux/s390/sysconf.c   |  2 +-
>  12 files changed, 249 insertions(+), 56 deletions(-)
>  create mode 100644 sysdeps/s390/dl-diagnostics-cpu.c
> 
> diff --git a/elf/Makefile b/elf/Makefile
> index c3864ca350..ed1b0223da 100644
> --- a/elf/Makefile
> +++ b/elf/Makefile
> @@ -768,6 +768,12 @@ modules-names += \
>    libmarkermod5-3 \
>    libmarkermod5-4 \
>    libmarkermod5-5 \
> +  libmarkermod6-1 \
> +  libmarkermod6-2 \
> +  libmarkermod6-3 \
> +  libmarkermod6-4 \
> +  libmarkermod6-5 \
> +  libmarkermod6-6 \
>    liborigin-mod \
>    libtracemod1-1 \
>    libtracemod2-1 \
> @@ -2866,6 +2872,7 @@ LDFLAGS-libmarkermod2-1.so += -Wl,-soname,libmarkermod2.so
>  LDFLAGS-libmarkermod3-1.so += -Wl,-soname,libmarkermod3.so
>  LDFLAGS-libmarkermod4-1.so += -Wl,-soname,libmarkermod4.so
>  LDFLAGS-libmarkermod5-1.so += -Wl,-soname,libmarkermod5.so
> +LDFLAGS-libmarkermod6-1.so += -Wl,-soname,libmarkermod6.so
>  $(objpfx)libmarkermod%.os : markermodMARKER-VALUE.c
>  	$(compile-command.c) \
>  	  -DMARKER=marker$(firstword $(subst -, ,$*)) \
> @@ -2880,6 +2887,8 @@ $(objpfx)libmarkermod4.so: $(objpfx)libmarkermod4-1.so
>  	cp $< $@
>  $(objpfx)libmarkermod5.so: $(objpfx)libmarkermod5-1.so
>  	cp $< $@
> +$(objpfx)libmarkermod6.so: $(objpfx)libmarkermod6-1.so
> +	cp $< $@
>  
>  # tst-glibc-hwcaps-prepend checks that --glibc-hwcaps-prepend is
>  # preferred over auto-detected subdirectories.
> diff --git a/elf/tst-glibc-hwcaps-cache.script b/elf/tst-glibc-hwcaps-cache.script
> index d58fc8c5de..af89e9c6f8 100644
> --- a/elf/tst-glibc-hwcaps-cache.script
> +++ b/elf/tst-glibc-hwcaps-cache.script
> @@ -5,6 +5,7 @@ cp $B/elf/libmarkermod2-1.so $L/libmarkermod2.so
>  cp $B/elf/libmarkermod3-1.so $L/libmarkermod3.so
>  cp $B/elf/libmarkermod4-1.so $L/libmarkermod4.so
>  cp $B/elf/libmarkermod5-1.so $L/libmarkermod5.so
> +cp $B/elf/libmarkermod6-1.so $L/libmarkermod6.so
>  
>  mkdirp 0770 $L/glibc-hwcaps/power9
>  cp $B/elf/libmarkermod2-2.so $L/glibc-hwcaps/power9/libmarkermod2.so
> @@ -26,6 +27,12 @@ cp $B/elf/libmarkermod5-2.so $L/glibc-hwcaps/z13/libmarkermod5.so
>  cp $B/elf/libmarkermod5-3.so $L/glibc-hwcaps/z14/libmarkermod5.so
>  cp $B/elf/libmarkermod5-4.so $L/glibc-hwcaps/z15/libmarkermod5.so
>  cp $B/elf/libmarkermod5-5.so $L/glibc-hwcaps/z16/libmarkermod5.so
> +mkdirp 0770 $L/glibc-hwcaps/z17
> +cp $B/elf/libmarkermod6-2.so $L/glibc-hwcaps/z13/libmarkermod6.so
> +cp $B/elf/libmarkermod6-3.so $L/glibc-hwcaps/z14/libmarkermod6.so
> +cp $B/elf/libmarkermod6-4.so $L/glibc-hwcaps/z15/libmarkermod6.so
> +cp $B/elf/libmarkermod6-5.so $L/glibc-hwcaps/z16/libmarkermod6.so
> +cp $B/elf/libmarkermod6-6.so $L/glibc-hwcaps/z17/libmarkermod6.so
>  
>  mkdirp 0770 $L/glibc-hwcaps/x86-64-v2
>  cp $B/elf/libmarkermod2-2.so $L/glibc-hwcaps/x86-64-v2/libmarkermod2.so
> diff --git a/sysdeps/s390/cpu-features.c b/sysdeps/s390/cpu-features.c
> index 31a1f4d600..106874b2f8 100644
> --- a/sysdeps/s390/cpu-features.c
> +++ b/sysdeps/s390/cpu-features.c
> @@ -27,7 +27,7 @@
>  
>  #define S390_COPY_CPU_FEATURES(SRC_PTR, DEST_PTR)	\
>    (DEST_PTR)->hwcap = (SRC_PTR)->hwcap;			\
> -  (DEST_PTR)->stfle_bits[0] = (SRC_PTR)->stfle_bits[0];
> +  (DEST_PTR)->stfle_filtered = (SRC_PTR)->stfle_filtered;
>  
>  static void
>  TUNABLE_CALLBACK (set_hwcaps) (tunable_val_t *valp)
> @@ -77,7 +77,7 @@ TUNABLE_CALLBACK (set_hwcaps) (tunable_val_t *valp)
>  	  disable = true;
>  	  hwcap_mask = HWCAP_S390_VXRS | HWCAP_S390_VXRS_EXT
>  	    | HWCAP_S390_VXRS_EXT2;
> -	  stfle_bits0_mask = S390_STFLE_MASK_ARCH13_MIE3;
> +	  stfle_bits0_mask = S390_STFLE_BIT61_ARCH13_MIE3;
>  	}
>        else if (tunable_str_comma_strcmp_cte (&t, "z13")
>  	       || tunable_str_comma_strcmp_cte (&t, "arch11"))
> @@ -85,7 +85,7 @@ TUNABLE_CALLBACK (set_hwcaps) (tunable_val_t *valp)
>  	  reset_features = true;
>  	  disable = true;
>  	  hwcap_mask = HWCAP_S390_VXRS_EXT | HWCAP_S390_VXRS_EXT2;
> -	  stfle_bits0_mask = S390_STFLE_MASK_ARCH13_MIE3;
> +	  stfle_bits0_mask = S390_STFLE_BIT61_ARCH13_MIE3;
>  	}
>        else if (tunable_str_comma_strcmp_cte (&t, "z14")
>  	       || tunable_str_comma_strcmp_cte (&t, "arch12"))
> @@ -93,12 +93,14 @@ TUNABLE_CALLBACK (set_hwcaps) (tunable_val_t *valp)
>  	  reset_features = true;
>  	  disable = true;
>  	  hwcap_mask = HWCAP_S390_VXRS_EXT2;
> -	  stfle_bits0_mask = S390_STFLE_MASK_ARCH13_MIE3;
> +	  stfle_bits0_mask = S390_STFLE_BIT61_ARCH13_MIE3;
>  	}
>        else if (tunable_str_comma_strcmp_cte (&t, "z15")
>  	       || tunable_str_comma_strcmp_cte (&t, "z16")
> +	       || tunable_str_comma_strcmp_cte (&t, "z17")
>  	       || tunable_str_comma_strcmp_cte (&t, "arch13")
> -	       || tunable_str_comma_strcmp_cte (&t, "arch14"))
> +	       || tunable_str_comma_strcmp_cte (&t, "arch14")
> +	       || tunable_str_comma_strcmp_cte (&t, "arch15"))
>  	{
>  	  /* For z15 or newer we don't have to disable something, but we have
>  	     to reset to the original values.  */
> @@ -125,7 +127,7 @@ TUNABLE_CALLBACK (set_hwcaps) (tunable_val_t *valp)
>  	    hwcap_mask |= HWCAP_S390_VXRS | HWCAP_S390_VXRS_EXT;
>  	}
>        else if (tunable_str_comma_strcmp_cte (&t, "STFLE_MIE3"))
> -	stfle_bits0_mask = S390_STFLE_MASK_ARCH13_MIE3;
> +	stfle_bits0_mask = S390_STFLE_BIT61_ARCH13_MIE3;
>  
>        /* Perform the actions determined above.  */
>        if (reset_features)
> @@ -144,22 +146,26 @@ TUNABLE_CALLBACK (set_hwcaps) (tunable_val_t *valp)
>        if (stfle_bits0_mask != 0ULL)
>  	{
>  	  if (disable)
> -	    cpu_features_curr.stfle_bits[0] &= ~stfle_bits0_mask;
> +	    cpu_features_curr.stfle_filtered &= ~stfle_bits0_mask;
>  	  else
> -	    cpu_features_curr.stfle_bits[0] |= stfle_bits0_mask;
> +	    cpu_features_curr.stfle_filtered |= stfle_bits0_mask;
>  	}
>      }
>  
>    /* Copy back the features after checking that no unsupported features were
>       enabled by user.  */
>    cpu_features->hwcap = cpu_features_curr.hwcap & cpu_features_orig.hwcap;
> -  cpu_features->stfle_bits[0] = cpu_features_curr.stfle_bits[0]
> -    & cpu_features_orig.stfle_bits[0];
> +  cpu_features->stfle_filtered = cpu_features_curr.stfle_filtered
> +    & cpu_features_orig.stfle_filtered;
>  }
>  
>  static inline void
> -init_cpu_features (struct cpu_features *cpu_features)
> +init_cpu_features_no_tunables (struct cpu_features *cpu_features)
>  {
> +  /* Only initialize once.  */
> +  if (cpu_features->hwcap != 0)
> +    return;
> +
>    /* Fill cpu_features as passed by kernel and machine.  */
>    cpu_features->hwcap = GLRO(dl_hwcap);
>  
> @@ -168,20 +174,57 @@ init_cpu_features (struct cpu_features *cpu_features)
>  		      && (cpu_features->hwcap & HWCAP_S390_ZARCH)
>  		      && (cpu_features->hwcap & HWCAP_S390_HIGH_GPRS)))
>      {
> -      register unsigned long reg0 __asm__("0") = 0;
> +      unsigned long long stfle_bits[4] = { 0 };
> +      register unsigned long reg0 __asm__("0") = 3;
>        __asm__ __volatile__(".machine push"        "\n\t"
>  			   ".machine \"z9-109\""  "\n\t"
>  			   ".machinemode \"zarch_nohighgprs\"\n\t"
>  			   "stfle %0"             "\n\t"
>  			   ".machine pop"         "\n"
> -			   : "=QS" (cpu_features->stfle_bits[0]),
> +			   : "=QS" (stfle_bits[0]),
>  			     "+d" (reg0)
>  			   : : "cc");
> +
> +      unsigned long long internal_stfle_bits = 0;
> +
> +      /* Facility bit 34: z10: General instructions extension.  */
> +      if ((stfle_bits[0] & (1ULL << (63 - 34))) != 0)
> +	internal_stfle_bits |= S390_STFLE_BIT34_Z10;
> +
> +      /* Facility bit 45: z196: Distinct operands, popcount, ...  */
> +      if ((stfle_bits[0] & (1ULL << (63 - 45))) != 0)
> +	internal_stfle_bits |= S390_STFLE_BIT45_Z196;
> +
> +      /* Facility bit 61: arch13/z15: Miscellaneous-Instruction-Extensions
> +	 Facility 3, e.g. mvcrl.  */
> +      if ((stfle_bits[0] & (1ULL << (63 - 61))) != 0)
> +	internal_stfle_bits |= S390_STFLE_BIT61_ARCH13_MIE3;
> +
> +      /* Facility bit 84: arch15/z17: Miscellaneous-instruction-extensions 4  */
> +      if ((stfle_bits[1] & (1ULL << (127 - 84))) != 0)
> +	internal_stfle_bits |= S390_STFLE_BIT84_ARCH15_MIE4;
> +
> +      /* Facility bit 198: arch15/z17: Vector-enhancements-facility 3  */
> +      if ((stfle_bits[3] & (1ULL << (255 - 198))) != 0)
> +	internal_stfle_bits |= S390_STFLE_BIT198_ARCH15_VXRS_EXT3;
> +
> +      /* Facility bit 199: arch15/z17: Vector-Packed-Decimal-Enhancement 3  */
> +      if ((stfle_bits[3] & (1ULL << (255 - 199))) != 0)
> +	internal_stfle_bits |= S390_STFLE_BIT199_ARCH15_VXRS_PDE3;
> +
> +      /* Facility bit 201: arch15/z17: CPU: Concurrent-Functions Facility  */
> +      if ((stfle_bits[3] & (1ULL << (255 - 201))) != 0)
> +	internal_stfle_bits |= S390_STFLE_BIT201_ARCH15_CON;
> +
> +      cpu_features->stfle_orig = internal_stfle_bits;
> +      cpu_features->stfle_filtered = internal_stfle_bits;
>      }
> -  else
> -    {
> -      cpu_features->stfle_bits[0] = 0ULL;
> -    }
> +}
> +
> +static inline void
> +init_cpu_features (struct cpu_features *cpu_features)
> +{
> +  init_cpu_features_no_tunables (cpu_features);
>  
>    TUNABLE_GET (glibc, cpu, hwcaps, tunable_val_t *, TUNABLE_CALLBACK (set_hwcaps));
>  }
> diff --git a/sysdeps/s390/cpu-features.h b/sysdeps/s390/cpu-features.h
> index 4ff442161a..2441b27f3a 100644
> --- a/sysdeps/s390/cpu-features.h
> +++ b/sysdeps/s390/cpu-features.h
> @@ -18,29 +18,58 @@
>  #ifndef __CPU_FEATURES_S390X_H
>  # define __CPU_FEATURES_S390X_H
>  
> -#define S390_STFLE_BITS_Z10  34 /* General instructions extension */
> -#define S390_STFLE_BITS_Z196 45 /* Distinct operands, pop ... */
> -#define S390_STFLE_BITS_ARCH13_MIE3 61 /* Miscellaneous-Instruction-Extensions
> -					  Facility 3, e.g. mvcrl.  */
> +/* The following stfle bit definitions are intended to be used for the
> +   glibc internal stfle_orig and stfle_filtered fields in cpu_features
> +   struct.  They can't be used on the double words retrieved by the
> +   stfle-instruction.  */
>  
> -#define S390_STFLE_MASK_ARCH13_MIE3 (1ULL << (63 - S390_STFLE_BITS_ARCH13_MIE3))
> +/* Facility bit 34: z10: General instructions extension.  */
> +#define S390_STFLE_BIT34_Z10 (1ULL << 0)
>  
> +/* Facility bit 45: z196: Distinct operands, popcount, ...  */
> +#define S390_STFLE_BIT45_Z196 (1ULL << 1)
>  
> -#define S390_IS_ARCH13_MIE3(STFLE_BITS_ARRAY)			\
> -  (((STFLE_BITS_ARRAY)[0] & S390_STFLE_MASK_ARCH13_MIE3) != 0)
> +/* Facility bit 61: arch13/z15: Miscellaneous-Instruction-Extensions
> +   Facility 3, e.g. mvcrl.  */
> +#define S390_STFLE_BIT61_ARCH13_MIE3 (1ULL << 2)
>  
> -#define S390_IS_Z196(STFLE_BITS_ARRAY)			\
> -  (((STFLE_BITS_ARRAY)[0] & (1ULL << (63 - S390_STFLE_BITS_Z196))) != 0)
> +/* Facility bit 84: arch15/z17: Miscellaneous-instruction-extensions
> +   facility 4  */
> +#define S390_STFLE_BIT84_ARCH15_MIE4 (1ULL << 3)
>  
> -#define S390_IS_Z10(STFLE_BITS_ARRAY)				\
> -  (((STFLE_BITS_ARRAY)[0] & (1ULL << (63 - S390_STFLE_BITS_Z10))) != 0)
> +/* Facility bit 198: arch15/z17: Vector-enhancements-facility 3  */
> +#define S390_STFLE_BIT198_ARCH15_VXRS_EXT3 (1ULL << 4)
> +
> +/* Facility bit 199: arch15/z17: Vector-Packed-Decimal-Enhancement
> +   Facility 3  */
> +#define S390_STFLE_BIT199_ARCH15_VXRS_PDE3 (1ULL << 5)
> +
> +/* Facility bit 201: arch15/z17: CPU: Concurrent-Functions Facility  */
> +#define S390_STFLE_BIT201_ARCH15_CON (1ULL << 6)
> +
> +#define S390_IS_ARCH15(STFLE_BITS)					\
> +  ((((STFLE_BITS) & S390_STFLE_BIT84_ARCH15_MIE4) != 0)			\
> +   && (((STFLE_BITS) & S390_STFLE_BIT198_ARCH15_VXRS_EXT3) != 0)	\
> +   && (((STFLE_BITS) & S390_STFLE_BIT199_ARCH15_VXRS_PDE3) != 0)	\
> +   && (((STFLE_BITS) & S390_STFLE_BIT201_ARCH15_CON) != 0))
> +
> +#define S390_IS_ARCH13_MIE3(STFLE_BITS)			\
> +  (((STFLE_BITS) & S390_STFLE_BIT61_ARCH13_MIE3) != 0)
> +
> +#define S390_IS_Z196(STFLE_BITS)		\
> +  (((STFLE_BITS) & S390_STFLE_BIT45_Z196) != 0)
> +
> +#define S390_IS_Z10(STFLE_BITS)			\
> +  (((STFLE_BITS) & S390_STFLE_BIT34_Z10) != 0)
>  
>  struct cpu_features
>  {
>    unsigned long int hwcap;
>    unsigned long int __reserved_hwcap2;
> -  unsigned long long stfle_bits[3];
> -  unsigned long long __reserved[11];
> +  unsigned long long __reserved;
> +  unsigned long long stfle_orig;
> +  unsigned long long stfle_filtered;
> +  unsigned long long __reserved2[11];
>  };
>  
>  #endif /* __CPU_FEATURES_S390X_H  */
> diff --git a/sysdeps/s390/dl-diagnostics-cpu.c b/sysdeps/s390/dl-diagnostics-cpu.c
> new file mode 100644
> index 0000000000..426af2df7a
> --- /dev/null
> +++ b/sysdeps/s390/dl-diagnostics-cpu.c
> @@ -0,0 +1,37 @@
> +/* Print CPU diagnostics data in ld.so.  s390 version.
> +   Copyright (C) 2025 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
> +   <https://www.gnu.org/licenses/>.  */
> +
> +#include <dl-diagnostics.h>
> +#include <ldsodefs.h>
> +#include <cpu-features.h>
> +
> +static void
> +print_cpu_features_value (const char *label, uint64_t value)
> +{
> +  _dl_printf ("s390.cpu_features.");
> +  _dl_diagnostics_print_labeled_value (label, value);
> +}
> +
> +void
> +_dl_diagnostics_cpu (void)
> +{
> +  const struct cpu_features *cpu_features = &GLRO(dl_s390_cpu_features);
> +  print_cpu_features_value ("hwcap", cpu_features->hwcap);
> +  print_cpu_features_value ("stfle_orig", cpu_features->stfle_orig);
> +  print_cpu_features_value ("stfle_filtered", cpu_features->stfle_filtered);
> +}
> diff --git a/sysdeps/s390/multiarch/ifunc-impl-list.c b/sysdeps/s390/multiarch/ifunc-impl-list.c
> index 48c8ce13e7..14b1f7639c 100644
> --- a/sysdeps/s390/multiarch/ifunc-impl-list.c
> +++ b/sysdeps/s390/multiarch/ifunc-impl-list.c
> @@ -81,8 +81,8 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
>    /* Get hardware information.  */
>    const struct cpu_features *features = &GLRO(dl_s390_cpu_features);
>    unsigned long int dl_hwcap __attribute__ ((unused)) = features->hwcap;
> -  const unsigned long long * __attribute__((unused)) stfle_bits
> -    = features->stfle_bits;
> +  const unsigned long long __attribute__((unused)) stfle_bits
> +    = features->stfle_filtered;
>  
>  #if HAVE_MEMSET_IFUNC
>    IFUNC_IMPL (i, name, memset,
> diff --git a/sysdeps/s390/multiarch/ifunc-resolve.h b/sysdeps/s390/multiarch/ifunc-resolve.h
> index 34f3b0d8d2..b28c503e31 100644
> --- a/sysdeps/s390/multiarch/ifunc-resolve.h
> +++ b/sysdeps/s390/multiarch/ifunc-resolve.h
> @@ -23,7 +23,7 @@
>  #include <sys/auxv.h>
>  
>  #define s390_libc_ifunc_expr_stfle_init()				\
> -  const unsigned long long *stfle_bits = features->stfle_bits;
> +  const unsigned long long stfle_bits = features->stfle_filtered;
>  
>  #define s390_libc_ifunc_expr_init()					\
>    const struct cpu_features *features = &GLRO(dl_s390_cpu_features);	\
> diff --git a/sysdeps/s390/s390-64/Makefile b/sysdeps/s390/s390-64/Makefile
> index 66ed844e68..991025cd2a 100644
> --- a/sysdeps/s390/s390-64/Makefile
> +++ b/sysdeps/s390/s390-64/Makefile
> @@ -11,7 +11,8 @@ $(objpfx)tst-glibc-hwcaps: \
>    $(objpfx)libmarkermod2-1.so \
>    $(objpfx)libmarkermod3-1.so \
>    $(objpfx)libmarkermod4-1.so \
> -  $(objpfx)libmarkermod5-1.so
> +  $(objpfx)libmarkermod5-1.so \
> +  $(objpfx)libmarkermod6-1.so
>  $(objpfx)tst-glibc-hwcaps.out: \
>    $(objpfx)libmarkermod2.so \
>      $(objpfx)glibc-hwcaps/z13/libmarkermod2.so \
> @@ -26,7 +27,14 @@ $(objpfx)tst-glibc-hwcaps.out: \
>      $(objpfx)glibc-hwcaps/z13/libmarkermod5.so \
>      $(objpfx)glibc-hwcaps/z14/libmarkermod5.so \
>      $(objpfx)glibc-hwcaps/z15/libmarkermod5.so \
> -    $(objpfx)glibc-hwcaps/z16/libmarkermod5.so
> +    $(objpfx)glibc-hwcaps/z16/libmarkermod5.so \
> +  $(objpfx)libmarkermod6.so \
> +    $(objpfx)glibc-hwcaps/z13/libmarkermod6.so \
> +    $(objpfx)glibc-hwcaps/z14/libmarkermod6.so \
> +    $(objpfx)glibc-hwcaps/z15/libmarkermod6.so \
> +    $(objpfx)glibc-hwcaps/z16/libmarkermod6.so \
> +    $(objpfx)glibc-hwcaps/z17/libmarkermod6.so
> +
>  
>  $(objpfx)glibc-hwcaps/z13/libmarkermod2.so: $(objpfx)libmarkermod2-2.so
>  	$(make-target-directory)
> @@ -58,6 +66,21 @@ $(objpfx)glibc-hwcaps/z15/libmarkermod5.so: $(objpfx)libmarkermod5-4.so
>  $(objpfx)glibc-hwcaps/z16/libmarkermod5.so: $(objpfx)libmarkermod5-5.so
>  	$(make-target-directory)
>  	cp $< $@
> +$(objpfx)glibc-hwcaps/z13/libmarkermod6.so: $(objpfx)libmarkermod6-2.so
> +	$(make-target-directory)
> +	cp $< $@
> +$(objpfx)glibc-hwcaps/z14/libmarkermod6.so: $(objpfx)libmarkermod6-3.so
> +	$(make-target-directory)
> +	cp $< $@
> +$(objpfx)glibc-hwcaps/z15/libmarkermod6.so: $(objpfx)libmarkermod6-4.so
> +	$(make-target-directory)
> +	cp $< $@
> +$(objpfx)glibc-hwcaps/z16/libmarkermod6.so: $(objpfx)libmarkermod6-5.so
> +	$(make-target-directory)
> +	cp $< $@
> +$(objpfx)glibc-hwcaps/z17/libmarkermod6.so: $(objpfx)libmarkermod6-6.so
> +	$(make-target-directory)
> +	cp $< $@
>  
>  
>  ifeq (no,$(build-hardcoded-path-in-tests))
> diff --git a/sysdeps/s390/s390-64/dl-hwcap-check.h b/sysdeps/s390/s390-64/dl-hwcap-check.h
> index 815cf3e605..736e654474 100644
> --- a/sysdeps/s390/s390-64/dl-hwcap-check.h
> +++ b/sysdeps/s390/s390-64/dl-hwcap-check.h
> @@ -25,8 +25,23 @@
>  static inline void
>  dl_hwcap_check (void)
>  {
> -#if defined __ARCH__
> -# if GCCMACRO__ARCH__ >= 14
> +  /* Note: The s390x kernel won't introduce new HWCAP-Bits if there is
> +     no special handling needed in kernel itself.  Thus we have have
> +     to check the facility-list retrieved with the stfle instruction.
> +     We already have a common storage of this list in cpu-features.c.
> +     This dl-hwcap-check.h file is included in
> +     sysdeps/unix/sysv/linux/dl-sysdep.c, where also dl-machine.h and
> +     cpu-features.c is included.  Therefore we don't have a special
> +     include here.  */
> +
> +#if defined GCCMACRO__ARCH__
> +# if GCCMACRO__ARCH__ >= 15
> +  init_cpu_features_no_tunables (&GLRO(dl_s390_cpu_features));
> +  if (!(S390_IS_ARCH15 (GLRO(dl_s390_cpu_features).stfle_orig)))
> +    _dl_fatal_printf ("\
> +Fatal glibc error: CPU lacks VXRS_EXT3/VXRS_PDE3/MIE4/Concurrent-functions \
> +support (z17 or later required)\n");
> +# elif GCCMACRO__ARCH__ >= 14
>    if (!(GLRO(dl_hwcap) & HWCAP_S390_VXRS_PDE2))
>      _dl_fatal_printf ("\
>  Fatal glibc error: CPU lacks VXRS_PDE2 support (z16 or later required)\n");
> @@ -39,7 +54,7 @@ Fatal glibc error: CPU lacks VXRS_EXT2 support (z15 or later required)\n");
>      _dl_fatal_printf ("\
>  Fatal glibc error: CPU lacks VXE support (z14 or later required)\n");
>  # endif
> -#endif /* __ARCH__ */
> +#endif /* GCCMACRO__ARCH__ */
>  }
>  
>  #endif /* _DL_HWCAP_CHECK_H */
> diff --git a/sysdeps/s390/s390-64/dl-hwcaps-subdirs.c b/sysdeps/s390/s390-64/dl-hwcaps-subdirs.c
> index 32fdabdb00..1ae9fdd098 100644
> --- a/sysdeps/s390/s390-64/dl-hwcaps-subdirs.c
> +++ b/sysdeps/s390/s390-64/dl-hwcaps-subdirs.c
> @@ -19,9 +19,10 @@
>  #include <dl-hwcaps.h>
>  #include <ldsodefs.h>
>  #include <sys/auxv.h>
> +#include <cpu-features.h>
>  
> -const char _dl_hwcaps_subdirs[] = "z16:z15:z14:z13";
> -enum { subdirs_count = 4 }; /* Number of components in _dl_hwcaps_subdirs.  */
> +const char _dl_hwcaps_subdirs[] = "z17:z16:z15:z14:z13";
> +enum { subdirs_count = 5 }; /* Number of components in _dl_hwcaps_subdirs.  */
>  
>  uint32_t
>  _dl_hwcaps_subdirs_active (void)
> @@ -58,5 +59,12 @@ _dl_hwcaps_subdirs_active (void)
>      return _dl_hwcaps_subdirs_build_bitmask (subdirs_count, active);
>    ++active;
>  
> +  /* z17.
> +     Note: The kernel has not introduced new HWCAP bits as the new facilities do
> +     not require kernel interaction.  Thus we check the features via stfle.  */
> +  if (!(S390_IS_ARCH15 (GLRO(dl_s390_cpu_features).stfle_orig)))
> +    return _dl_hwcaps_subdirs_build_bitmask (subdirs_count, active);
> +  ++active;
> +
>    return _dl_hwcaps_subdirs_build_bitmask (subdirs_count, active);
>  }
> diff --git a/sysdeps/s390/s390-64/tst-glibc-hwcaps.c b/sysdeps/s390/s390-64/tst-glibc-hwcaps.c
> index 1652bd7c63..b9d8781dc3 100644
> --- a/sysdeps/s390/s390-64/tst-glibc-hwcaps.c
> +++ b/sysdeps/s390/s390-64/tst-glibc-hwcaps.c
> @@ -26,35 +26,53 @@ extern int marker2 (void);
>  extern int marker3 (void);
>  extern int marker4 (void);
>  extern int marker5 (void);
> +extern int marker6 (void);
>  
>  /* Return the arch level, 10 for the baseline libmarkermod*.so's.  */
>  static int
>  compute_level (void)
>  {
>    const char *platform = (const char *) getauxval (AT_PLATFORM);
> +  const unsigned long int hwcap = getauxval (AT_HWCAP);
> +  const int latest_level = 15;
>  
>    /* The arch* versions refer to the edition of the Principles of
>       Operation, and they are off by two when compared with the recent
>       product names.  (The code below should not be considered an
>       accurate mapping to Principles of Operation editions for earlier
>       AT_PLATFORM strings).  */
> -  if (strcmp (platform, "z900") == 0)
> -    return 10;
> -  if (strcmp (platform, "z990") == 0)
> -    return 10;
> -  if (strcmp (platform, "z9-109") == 0)
> -    return 10;
> -  if (strcmp (platform, "z10") == 0)
> -    return 10;
> -  if (strcmp (platform, "z196") == 0)
> -    return 10;
> -  if (strcmp (platform, "zEC12") == 0)
> -    return 10;
> +  if ((strcmp (platform, "z900") == 0)
> +      || (strcmp (platform, "z990") == 0)
> +      || (strcmp (platform, "z9-109") == 0)
> +      || (strcmp (platform, "z10") == 0)
> +      || (strcmp (platform, "z196") == 0)
> +      || (strcmp (platform, "zEC12") == 0))
> +    {
> +      if ((hwcap & HWCAP_S390_VX) == 0)
> +	{
> +	  /* As vector-support was introduced with the newer z13
> +	     architecture, we are really on one of the tested older
> +	     architectures.  */
> +	  return 10;
> +	}
> +      else
> +	{
> +	  /* According to AT_PLATFORM we are on an older architecture
> +	     without vector-support, but according to HWCAPs vector
> +	     registers are supported.  This means we are running on a
> +	     new architecture which is not yet known by the kernel.
> +	     Thus the default AT_PLATFORM string is used, which is the
> +	     oldest supported one.  For this test, assume we are on
> +	     the latest known architecture.  See
> +	     <kernel>/arch/s390/kernel/processor.c:setup_elf_platform().
> +	  */
> +	  return latest_level;
> +	}
> +    }
>  
>    /* If we are running on z13 or newer and the kernel was booted with novx,
>       then AT_PLATFORM is z13 or newer, but _dl_hwcaps_subdirs_active will
>       return zero and the _dl_hwcaps_subdirs are not searched.  */
> -  const unsigned long int hwcap = getauxval (AT_HWCAP);
>    if ((hwcap & HWCAP_S390_VX) == 0)
>      return 10;
>  
> @@ -66,9 +84,12 @@ compute_level (void)
>      return 13;
>    if (strcmp (platform, "z16") == 0)
>      return 14;
> +  if (strcmp (platform, "z17") == 0)
> +    return latest_level;
> +
>    printf ("warning: unrecognized AT_PLATFORM value: %s\n", platform);
> -  /* Assume that the new platform supports z16.  */
> -  return 14;
> +  /* Assume that the new platform supports the latest known architecture.  */
> +  return latest_level;
>  }
>  
>  static int
> @@ -80,6 +101,7 @@ do_test (void)
>    TEST_COMPARE (marker3 (), MIN (level - 9, 3));
>    TEST_COMPARE (marker4 (), MIN (level - 9, 4));
>    TEST_COMPARE (marker5 (), MIN (level - 9, 5));
> +  TEST_COMPARE (marker6 (), MIN (level - 9, 6));
>    return 0;
>  }
>  
> diff --git a/sysdeps/unix/sysv/linux/s390/sysconf.c b/sysdeps/unix/sysv/linux/s390/sysconf.c
> index 8386523c96..dcb335adc5 100644
> --- a/sysdeps/unix/sysv/linux/s390/sysconf.c
> +++ b/sysdeps/unix/sysv/linux/s390/sysconf.c
> @@ -66,7 +66,7 @@ get_cache_info (int level, int attr, int type)
>  	return 0L;
>      }
>  
> -  if (!S390_IS_Z10 (features->stfle_bits))
> +  if (!S390_IS_Z10 (features->stfle_orig))
>      {
>        /* We are at least on a z9 machine.
>  	 Return 256byte for LINESIZE for L1 d/i-cache,



More information about the Libc-alpha mailing list