1 /* Initialize cpu feature data. PowerPC version.
2 Copyright (C) 2017-2023 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <https://www.gnu.org/licenses/>. */
19 #include <array_length.h>
21 #include <cpu-features.h>
22 #include <elf/dl-tunables.h>
27 TUNABLE_CALLBACK (set_hwcaps
) (tunable_val_t
*valp
)
29 /* The current IFUNC selection is always using the most recent
30 features which are available via AT_HWCAP or AT_HWCAP2. But in
31 some scenarios it is useful to adjust this selection.
33 The environment variable:
35 GLIBC_TUNABLES=glibc.cpu.hwcaps=-xxx,yyy,....
37 Can be used to enable HWCAP/HWCAP2 feature yyy, disable HWCAP/HWCAP2
38 feature xxx, where the feature name is case-sensitive and has to match
39 the ones mentioned in the file{sysdeps/powerpc/dl-procinfo.c}. */
41 /* Copy the features from dl_powerpc_cpu_features, which contains the
42 features provided by AT_HWCAP and AT_HWCAP2. */
43 struct cpu_features
*cpu_features
= &GLRO(dl_powerpc_cpu_features
);
44 unsigned long int tcbv_hwcap
= cpu_features
->hwcap
;
45 unsigned long int tcbv_hwcap2
= cpu_features
->hwcap2
;
46 const char *token
= valp
->strval
;
49 const char *token_end
, *feature
;
51 size_t token_len
, i
, feature_len
, offset
= 0;
52 /* Find token separator or end of string. */
53 for (token_end
= token
; *token_end
!= ','; token_end
++)
54 if (*token_end
== '\0')
57 /* Determine feature. */
58 token_len
= token_end
- token
;
63 feature_len
= token_len
- 1;
69 feature_len
= token_len
;
71 for (i
= 0; i
< array_length (hwcap_tunables
); ++i
)
73 const char *hwcap_name
= hwcap_names
+ offset
;
74 size_t hwcap_name_len
= strlen (hwcap_name
);
75 /* Check the tunable name on the supported list. */
76 if (hwcap_name_len
== feature_len
77 && memcmp (feature
, hwcap_name
, feature_len
) == 0)
79 /* Update the hwcap and hwcap2 bits. */
82 /* Id is 1 for hwcap2 tunable. */
83 if (hwcap_tunables
[i
].id
)
84 cpu_features
->hwcap2
&= ~(hwcap_tunables
[i
].mask
);
86 cpu_features
->hwcap
&= ~(hwcap_tunables
[i
].mask
);
90 /* Enable the features and also check that no unsupported
91 features were enabled by user. */
92 if (hwcap_tunables
[i
].id
)
93 cpu_features
->hwcap2
|= (tcbv_hwcap2
& hwcap_tunables
[i
].mask
);
95 cpu_features
->hwcap
|= (tcbv_hwcap
& hwcap_tunables
[i
].mask
);
99 offset
+= hwcap_name_len
+ 1;
102 /* ... and skip token separator for next round. */
106 while (*token
!= '\0');
110 init_cpu_features (struct cpu_features
*cpu_features
, uint64_t hwcaps
[])
112 /* Fill the cpu_features with the supported hwcaps
113 which are set by __tcb_parse_hwcap_and_convert_at_platform. */
114 cpu_features
->hwcap
= hwcaps
[0];
115 cpu_features
->hwcap2
= hwcaps
[1];
116 /* Default is to use aligned memory access on optimized function unless
117 tunables is enable, since for this case user can explicit disable
118 unaligned optimizations. */
119 int32_t cached_memfunc
= TUNABLE_GET (glibc
, cpu
, cached_memopt
, int32_t,
121 cpu_features
->use_cached_memopt
= (cached_memfunc
> 0);
122 TUNABLE_GET (glibc
, cpu
, hwcaps
, tunable_val_t
*,
123 TUNABLE_CALLBACK (set_hwcaps
));