From 21841f0d562f0e944c4d267a28cc3ebd19c847e9 Mon Sep 17 00:00:00 2001 From: Mahesh Bodapati Date: Tue, 1 Aug 2023 07:41:17 -0500 Subject: PowerPC: Influence cpu/arch hwcap features via GLIBC_TUNABLES This patch enables the option to influence hwcaps used by PowerPC. The environment variable, GLIBC_TUNABLES=glibc.cpu.hwcaps=-xxx,yyy,-zzz...., can be used to enable CPU/ARCH feature yyy, disable CPU/ARCH feature xxx and zzz, where the feature name is case-sensitive and has to match the ones mentioned in the file{sysdeps/powerpc/dl-procinfo.c}. Note that the hwcap tunables only used in the IFUNC selection. Reviewed-by: Adhemerval Zanella [rebased to c9s by DJ] diff -rupN a/manual/tunables.texi b/manual/tunables.texi --- a/manual/tunables.texi 2023-09-13 01:16:19.979884270 -0400 +++ b/manual/tunables.texi 2023-09-13 01:17:19.217179994 -0400 @@ -476,7 +476,10 @@ On s390x, the supported HWCAP and STFLE @code{sysdeps/s390/cpu-features.c}. In addition the user can also set a CPU arch-level like @code{z13} instead of single HWCAP and STFLE features. -This tunable is specific to i386, x86-64 and s390x. +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. @end deftp @deftp Tunable glibc.cpu.cached_memopt diff -rupN a/sysdeps/powerpc/cpu-features.c b/sysdeps/powerpc/cpu-features.c --- a/sysdeps/powerpc/cpu-features.c 2021-08-01 21:33:43.000000000 -0400 +++ b/sysdeps/powerpc/cpu-features.c 1969-12-31 19:00:00.000000000 -0500 @@ -1,39 +0,0 @@ -/* Initialize cpu feature data. PowerPC version. - Copyright (C) 2017-2021 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 - . */ - -#include -#include - -#if HAVE_TUNABLES -# include -#endif - -static inline void -init_cpu_features (struct cpu_features *cpu_features) -{ - /* Default is to use aligned memory access on optimized function unless - tunables is enable, since for this case user can explicit disable - unaligned optimizations. */ -#if HAVE_TUNABLES - int32_t cached_memfunc = TUNABLE_GET (glibc, cpu, cached_memopt, int32_t, - NULL); - cpu_features->use_cached_memopt = (cached_memfunc > 0); -#else - cpu_features->use_cached_memopt = false; -#endif -} diff -rupN a/sysdeps/powerpc/cpu-features.h b/sysdeps/powerpc/cpu-features.h --- a/sysdeps/powerpc/cpu-features.h 2021-08-01 21:33:43.000000000 -0400 +++ b/sysdeps/powerpc/cpu-features.h 1969-12-31 19:00:00.000000000 -0500 @@ -1,28 +0,0 @@ -/* Initialize cpu feature data. PowerPC version. - Copyright (C) 2017-2021 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 - . */ - -#ifndef __CPU_FEATURES_POWERPC_H -# define __CPU_FEATURES_POWERPC_H - -#include - -struct cpu_features -{ - bool use_cached_memopt; -}; - -#endif /* __CPU_FEATURES_H */ diff -rupN a/sysdeps/powerpc/dl-tunables.list b/sysdeps/powerpc/dl-tunables.list --- a/sysdeps/powerpc/dl-tunables.list 2021-08-01 21:33:43.000000000 -0400 +++ b/sysdeps/powerpc/dl-tunables.list 2023-09-13 01:17:19.226180343 -0400 @@ -24,5 +24,8 @@ glibc { maxval: 1 default: 0 } + hwcaps { + type: STRING + } } } diff -rupN a/sysdeps/powerpc/hwcapinfo.c b/sysdeps/powerpc/hwcapinfo.c --- a/sysdeps/powerpc/hwcapinfo.c 2021-08-01 21:33:43.000000000 -0400 +++ b/sysdeps/powerpc/hwcapinfo.c 2023-09-13 01:17:19.229180459 -0400 @@ -19,6 +19,7 @@ #include #include #include +#include uint64_t __tcb_hwcap __attribute__ ((visibility ("hidden"))); uint32_t __tcb_platform __attribute__ ((visibility ("hidden"))); @@ -64,6 +65,9 @@ __tcb_parse_hwcap_and_convert_at_platfor else if (h1 & PPC_FEATURE_POWER5) h1 |= PPC_FEATURE_POWER4; + uint64_t array_hwcaps[] = { h1, h2 }; + init_cpu_features (&GLRO(dl_powerpc_cpu_features), array_hwcaps); + /* Consolidate both HWCAP and HWCAP2 into a single doubleword so that we can read both in a single load later. */ __tcb_hwcap = h2; diff -rupN a/sysdeps/powerpc/powerpc32/power4/multiarch/ifunc-impl-list.c b/sysdeps/powerpc/powerpc32/power4/multiarch/ifunc-impl-list.c --- a/sysdeps/powerpc/powerpc32/power4/multiarch/ifunc-impl-list.c 2021-08-01 21:33:43.000000000 -0400 +++ b/sysdeps/powerpc/powerpc32/power4/multiarch/ifunc-impl-list.c 2023-09-13 01:17:19.232180575 -0400 @@ -21,6 +21,7 @@ #include #include #include +#include /* Maximum number of IFUNC implementations. */ #define MAX_IFUNC 6 @@ -33,7 +34,8 @@ __libc_ifunc_impl_list (const char *name size_t i = 0; - unsigned long int hwcap = GLRO(dl_hwcap); + const struct cpu_features *features = &GLRO(dl_powerpc_cpu_features); + unsigned long int hwcap = features->hwcap; /* hwcap contains only the latest supported ISA, the code checks which is and fills the previous supported ones. */ if (hwcap & PPC_FEATURE_ARCH_2_06) diff -rupN a/sysdeps/powerpc/powerpc32/power4/multiarch/init-arch.h b/sysdeps/powerpc/powerpc32/power4/multiarch/init-arch.h --- a/sysdeps/powerpc/powerpc32/power4/multiarch/init-arch.h 2021-08-01 21:33:43.000000000 -0400 +++ b/sysdeps/powerpc/powerpc32/power4/multiarch/init-arch.h 2023-09-13 01:17:19.232180575 -0400 @@ -16,6 +16,7 @@ . */ #include +#include /* The code checks if _rtld_global_ro was realocated before trying to access the dl_hwcap field. The assembly is to make the compiler not optimize the @@ -32,11 +33,12 @@ # define __GLRO(value) GLRO(value) #endif -/* dl_hwcap contains only the latest supported ISA, the macro checks which is - and fills the previous ones. */ +/* Get the hardware information post the tunables set, the macro checks + it and fills the previous ones. */ #define INIT_ARCH() \ - unsigned long int hwcap = __GLRO(dl_hwcap); \ - unsigned long int __attribute__((unused)) hwcap2 = __GLRO(dl_hwcap2); \ + const struct cpu_features *features = &GLRO(dl_powerpc_cpu_features); \ + unsigned long int hwcap = features->hwcap; \ + unsigned long int __attribute__((unused)) hwcap2 = features->hwcap2; \ bool __attribute__((unused)) use_cached_memopt = \ __GLRO(dl_powerpc_cpu_features.use_cached_memopt); \ if (hwcap & PPC_FEATURE_ARCH_2_06) \ diff -rupN a/sysdeps/powerpc/powerpc64/dl-machine.h b/sysdeps/powerpc/powerpc64/dl-machine.h --- a/sysdeps/powerpc/powerpc64/dl-machine.h 2023-09-13 01:16:17.582791395 -0400 +++ b/sysdeps/powerpc/powerpc64/dl-machine.h 2023-09-13 01:17:19.236180730 -0400 @@ -27,7 +27,6 @@ #include #include #include -#include #include #include #include @@ -293,7 +292,6 @@ static inline void __attribute__ ((unuse dl_platform_init (void) { __tcb_parse_hwcap_and_convert_at_platform (); - init_cpu_features (&GLRO(dl_powerpc_cpu_features)); } #endif diff -rupN a/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c b/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c --- a/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c 2023-09-13 01:16:20.219893569 -0400 +++ b/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c 2023-09-13 01:19:17.169756083 -0400 @@ -17,6 +17,7 @@ . */ #include +#include #include #include #include @@ -32,9 +33,9 @@ __libc_ifunc_impl_list (const char *name assert (max >= MAX_IFUNC); size_t i = 0; - - unsigned long int hwcap = GLRO(dl_hwcap); - unsigned long int hwcap2 = GLRO(dl_hwcap2); + const struct cpu_features *features = &GLRO(dl_powerpc_cpu_features); + unsigned long int hwcap = features->hwcap; + unsigned long int hwcap2 = features->hwcap2; #ifdef SHARED int cacheline_size = GLRO(dl_cache_line_size); #endif diff -rupN a/sysdeps/unix/sysv/linux/powerpc/Makefile b/sysdeps/unix/sysv/linux/powerpc/Makefile --- a/sysdeps/unix/sysv/linux/powerpc/Makefile 2021-08-01 21:33:43.000000000 -0400 +++ b/sysdeps/unix/sysv/linux/powerpc/Makefile 2023-09-13 01:17:19.243181002 -0400 @@ -21,7 +21,12 @@ ifeq ($(subdir),misc) sysdep_headers += bits/ppc.h sysdep_routines += get_timebase_freq tests-static += test-gettimebasefreq-static -tests += $(tests-static) -tests += test-gettimebasefreq -tests += test-powerpc-linux-sysconf +tests += \ + $(tests-static) \ + test-gettimebasefreq \ + test-powerpc-linux-sysconf \ + tst-hwcap-tunables \ + # tests + +tst-hwcap-tunables-ARGS = -- $(host-test-program-cmd) endif diff -rupN a/sysdeps/unix/sysv/linux/powerpc/cpu-features.c b/sysdeps/unix/sysv/linux/powerpc/cpu-features.c --- a/sysdeps/unix/sysv/linux/powerpc/cpu-features.c 1969-12-31 19:00:00.000000000 -0500 +++ b/sysdeps/unix/sysv/linux/powerpc/cpu-features.c 2023-09-13 01:17:19.247181157 -0400 @@ -0,0 +1,124 @@ +/* Initialize cpu feature data. PowerPC version. + Copyright (C) 2017-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 + . */ + +#include +#include +#include +#include +#include +#include + +static void +TUNABLE_CALLBACK (set_hwcaps) (tunable_val_t *valp) +{ + /* The current IFUNC selection is always using the most recent + features which are available via AT_HWCAP or AT_HWCAP2. But in + some scenarios it is useful to adjust this selection. + + The environment variable: + + GLIBC_TUNABLES=glibc.cpu.hwcaps=-xxx,yyy,.... + + Can be used to enable HWCAP/HWCAP2 feature yyy, disable HWCAP/HWCAP2 + feature xxx, where the feature name is case-sensitive and has to match + the ones mentioned in the file{sysdeps/powerpc/dl-procinfo.c}. */ + + /* Copy the features from dl_powerpc_cpu_features, which contains the + features provided by AT_HWCAP and AT_HWCAP2. */ + struct cpu_features *cpu_features = &GLRO(dl_powerpc_cpu_features); + unsigned long int tcbv_hwcap = cpu_features->hwcap; + unsigned long int tcbv_hwcap2 = cpu_features->hwcap2; + const char *token = valp->strval; + do + { + const char *token_end, *feature; + bool disable; + size_t token_len, i, feature_len, offset = 0; + /* Find token separator or end of string. */ + for (token_end = token; *token_end != ','; token_end++) + if (*token_end == '\0') + break; + + /* Determine feature. */ + token_len = token_end - token; + if (*token == '-') + { + disable = true; + feature = token + 1; + feature_len = token_len - 1; + } + else + { + disable = false; + feature = token; + feature_len = token_len; + } + for (i = 0; i < array_length (hwcap_tunables); ++i) + { + const char *hwcap_name = hwcap_names + offset; + size_t hwcap_name_len = strlen (hwcap_name); + /* Check the tunable name on the supported list. */ + if (hwcap_name_len == feature_len + && memcmp (feature, hwcap_name, feature_len) == 0) + { + /* Update the hwcap and hwcap2 bits. */ + if (disable) + { + /* Id is 1 for hwcap2 tunable. */ + if (hwcap_tunables[i].id) + cpu_features->hwcap2 &= ~(hwcap_tunables[i].mask); + else + cpu_features->hwcap &= ~(hwcap_tunables[i].mask); + } + else + { + /* Enable the features and also check that no unsupported + features were enabled by user. */ + if (hwcap_tunables[i].id) + cpu_features->hwcap2 |= (tcbv_hwcap2 & hwcap_tunables[i].mask); + else + cpu_features->hwcap |= (tcbv_hwcap & hwcap_tunables[i].mask); + } + break; + } + offset += hwcap_name_len + 1; + } + token += token_len; + /* ... and skip token separator for next round. */ + if (*token == ',') + token++; + } + while (*token != '\0'); +} + +static inline void +init_cpu_features (struct cpu_features *cpu_features, uint64_t hwcaps[]) +{ + /* Fill the cpu_features with the supported hwcaps + which are set by __tcb_parse_hwcap_and_convert_at_platform. */ + cpu_features->hwcap = hwcaps[0]; + cpu_features->hwcap2 = hwcaps[1]; + /* Default is to use aligned memory access on optimized function unless + tunables is enable, since for this case user can explicit disable + unaligned optimizations. */ + int32_t cached_memfunc = TUNABLE_GET (glibc, cpu, cached_memopt, int32_t, + NULL); + cpu_features->use_cached_memopt = (cached_memfunc > 0); + TUNABLE_GET (glibc, cpu, hwcaps, tunable_val_t *, + TUNABLE_CALLBACK (set_hwcaps)); +} diff -rupN a/sysdeps/unix/sysv/linux/powerpc/cpu-features.h b/sysdeps/unix/sysv/linux/powerpc/cpu-features.h --- a/sysdeps/unix/sysv/linux/powerpc/cpu-features.h 1969-12-31 19:00:00.000000000 -0500 +++ b/sysdeps/unix/sysv/linux/powerpc/cpu-features.h 2023-09-13 01:17:19.251181312 -0400 @@ -0,0 +1,130 @@ +/* Initialize cpu feature data. PowerPC version. + Copyright (C) 2017-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 + . */ + +#ifndef __CPU_FEATURES_POWERPC_H +# define __CPU_FEATURES_POWERPC_H + +#include +#include + +struct cpu_features +{ + bool use_cached_memopt; + unsigned long int hwcap; + unsigned long int hwcap2; +}; + +static const char hwcap_names[] = { + "4xxmac\0" + "altivec\0" + "arch_2_05\0" + "arch_2_06\0" + "archpmu\0" + "booke\0" + "cellbe\0" + "dfp\0" + "efpdouble\0" + "efpsingle\0" + "fpu\0" + "ic_snoop\0" + "mmu\0" + "notb\0" + "pa6t\0" + "power4\0" + "power5\0" + "power5+\0" + "power6x\0" + "ppc32\0" + "ppc601\0" + "ppc64\0" + "ppcle\0" + "smt\0" + "spe\0" + "true_le\0" + "ucache\0" + "vsx\0" + "arch_2_07\0" + "dscr\0" + "ebb\0" + "htm\0" + "htm-nosc\0" + "htm-no-suspend\0" + "isel\0" + "tar\0" + "vcrypto\0" + "arch_3_00\0" + "ieee128\0" + "darn\0" + "scv\0" + "arch_3_1\0" + "mma\0" +}; + +static const struct +{ + unsigned int mask; + bool id; +} hwcap_tunables[] = { + /* AT_HWCAP tunable masks. */ + { PPC_FEATURE_HAS_4xxMAC, 0 }, + { PPC_FEATURE_HAS_ALTIVEC, 0 }, + { PPC_FEATURE_ARCH_2_05, 0 }, + { PPC_FEATURE_ARCH_2_06, 0 }, + { PPC_FEATURE_PSERIES_PERFMON_COMPAT, 0 }, + { PPC_FEATURE_BOOKE, 0 }, + { PPC_FEATURE_CELL_BE, 0 }, + { PPC_FEATURE_HAS_DFP, 0 }, + { PPC_FEATURE_HAS_EFP_DOUBLE, 0 }, + { PPC_FEATURE_HAS_EFP_SINGLE, 0 }, + { PPC_FEATURE_HAS_FPU, 0 }, + { PPC_FEATURE_ICACHE_SNOOP, 0 }, + { PPC_FEATURE_HAS_MMU, 0 }, + { PPC_FEATURE_NO_TB, 0 }, + { PPC_FEATURE_PA6T, 0 }, + { PPC_FEATURE_POWER4, 0 }, + { PPC_FEATURE_POWER5, 0 }, + { PPC_FEATURE_POWER5_PLUS, 0 }, + { PPC_FEATURE_POWER6_EXT, 0 }, + { PPC_FEATURE_32, 0 }, + { PPC_FEATURE_601_INSTR, 0 }, + { PPC_FEATURE_64, 0 }, + { PPC_FEATURE_PPC_LE, 0 }, + { PPC_FEATURE_SMT, 0 }, + { PPC_FEATURE_HAS_SPE, 0 }, + { PPC_FEATURE_TRUE_LE, 0 }, + { PPC_FEATURE_UNIFIED_CACHE, 0 }, + { PPC_FEATURE_HAS_VSX, 0 }, + + /* AT_HWCAP2 tunable masks. */ + { PPC_FEATURE2_ARCH_2_07, 1 }, + { PPC_FEATURE2_HAS_DSCR, 1 }, + { PPC_FEATURE2_HAS_EBB, 1 }, + { PPC_FEATURE2_HAS_HTM, 1 }, + { PPC_FEATURE2_HTM_NOSC, 1 }, + { PPC_FEATURE2_HTM_NO_SUSPEND, 1 }, + { PPC_FEATURE2_HAS_ISEL, 1 }, + { PPC_FEATURE2_HAS_TAR, 1 }, + { PPC_FEATURE2_HAS_VEC_CRYPTO, 1 }, + { PPC_FEATURE2_ARCH_3_00, 1 }, + { PPC_FEATURE2_HAS_IEEE128, 1 }, + { PPC_FEATURE2_DARN, 1 }, + { PPC_FEATURE2_SCV, 1 }, + { PPC_FEATURE2_ARCH_3_1, 1 }, + { PPC_FEATURE2_MMA, 1 }, +}; + +#endif /* __CPU_FEATURES_H */ diff -rupN a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/dl-tunables.list b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/dl-tunables.list --- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/dl-tunables.list 2023-09-13 01:16:19.989884657 -0400 +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/dl-tunables.list 2023-09-13 01:17:19.254181428 -0400 @@ -28,3 +28,4 @@ @order glibc.malloc.check @order glibc.gmon.minarcs @order glibc.gmon.maxarcs +@order glibc.cpu.hwcaps diff -rupN a/sysdeps/unix/sysv/linux/powerpc/tst-hwcap-tunables.c b/sysdeps/unix/sysv/linux/powerpc/tst-hwcap-tunables.c --- a/sysdeps/unix/sysv/linux/powerpc/tst-hwcap-tunables.c 1969-12-31 19:00:00.000000000 -0500 +++ b/sysdeps/unix/sysv/linux/powerpc/tst-hwcap-tunables.c 2023-09-13 01:17:19.258181583 -0400 @@ -0,0 +1,128 @@ +/* Tests for powerpc GLIBC_TUNABLES=glibc.cpu.hwcaps filter. + 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 + . */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Nonzero if the program gets called via `exec'. */ +#define CMDLINE_OPTIONS \ + { "restart", no_argument, &restart, 1 }, +static int restart; + +/* Hold the four initial argument used to respawn the process, plus the extra + '--direct', '--restart', and the function to check */ +static char *spargs[8]; +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) + { + TEST_COMPARE (impls[i].usable, false); + break; + } + } + + _exit (EXIT_SUCCESS); +} + +static void +run_test (const char *filter, const char *funcname) +{ + printf ("info: checking filter %s (expect %s ifunc selection to be removed)\n", + filter, funcname); + 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); + + 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); + unsigned long int hwcap2 = getauxval (AT_HWCAP2); + if (__WORDSIZE == 64) + { + if (hwcap2 & PPC_FEATURE2_ARCH_3_1) + run_test ("-arch_3_1", "__memcpy_power10"); + if (hwcap2 & PPC_FEATURE2_ARCH_2_07) + run_test ("-arch_2_07", "__memcpy_power8_cached"); + if (hwcap & PPC_FEATURE_ARCH_2_06) + run_test ("-arch_2_06", "__memcpy_power7"); + if (hwcap & PPC_FEATURE_ARCH_2_05) + run_test ("-arch_2_06,-arch_2_05","__memcpy_power6"); + run_test ("-arch_2_06,-arch_2_05,-power5+,-power5,-power4", "__memcpy_power4"); + } + else + { + if (hwcap & PPC_FEATURE_HAS_VSX) + run_test ("-vsx", "__memcpy_power7"); + if (hwcap & PPC_FEATURE_ARCH_2_06) + run_test ("-arch_2_06", "__memcpy_a2"); + if (hwcap & PPC_FEATURE_ARCH_2_05) + run_test ("-arch_2_05", "__memcpy_power6"); + } + return 0; +} + +#define TEST_FUNCTION_ARGV do_test +#include