aboutsummaryrefslogtreecommitdiff
path: root/sysdeps/s390/cpu-features.c
diff options
context:
space:
mode:
authorAdhemerval Zanella <adhemerval.zanella@linaro.org>2023-12-06 10:24:01 -0300
committerAdhemerval Zanella <adhemerval.zanella@linaro.org>2023-12-19 13:25:45 -0300
commit2a969b53c0b02fed7e43473a92f219d737fd217a (patch)
treeb55eda5dc496c260e9757a5fc3856838d85b38fd /sysdeps/s390/cpu-features.c
parent5275fc784c8113c84c85ca028ce621f68fe6642b (diff)
downloadglibc-2a969b53c0b02fed7e43473a92f219d737fd217a.tar
glibc-2a969b53c0b02fed7e43473a92f219d737fd217a.tar.gz
glibc-2a969b53c0b02fed7e43473a92f219d737fd217a.tar.bz2
glibc-2a969b53c0b02fed7e43473a92f219d737fd217a.zip
elf: Do not duplicate the GLIBC_TUNABLES string
The tunable parsing duplicates the tunable environment variable so it null-terminates each one since it simplifies the later parsing. It has the drawback of adding another point of failure (__minimal_malloc failing), and the memory copy requires tuning the compiler to avoid mem operations calls. The parsing now tracks the tunable start and its size. The dl-tunable-parse.h adds helper functions to help parsing, like a strcmp that also checks for size and an iterator for suboptions that are comma-separated (used on hwcap parsing by x86, powerpc, and s390x). Since the environment variable is allocated on the stack by the kernel, it is safe to keep the references to the suboptions for later parsing of string tunables (as done by set_hwcaps by multiple architectures). Checked on x86_64-linux-gnu, powerpc64le-linux-gnu, and aarch64-linux-gnu. Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
Diffstat (limited to 'sysdeps/s390/cpu-features.c')
-rw-r--r--sysdeps/s390/cpu-features.c165
1 files changed, 59 insertions, 106 deletions
diff --git a/sysdeps/s390/cpu-features.c b/sysdeps/s390/cpu-features.c
index 55449ba07f..06c1cab0fd 100644
--- a/sysdeps/s390/cpu-features.c
+++ b/sysdeps/s390/cpu-features.c
@@ -22,6 +22,7 @@
#include <ifunc-memcmp.h>
#include <string.h>
#include <dl-symbol-redir-ifunc.h>
+#include <dl-tunables-parse.h>
#define S390_COPY_CPU_FEATURES(SRC_PTR, DEST_PTR) \
(DEST_PTR)->hwcap = (SRC_PTR)->hwcap; \
@@ -51,33 +52,14 @@ TUNABLE_CALLBACK (set_hwcaps) (tunable_val_t *valp)
struct cpu_features cpu_features_curr;
S390_COPY_CPU_FEATURES (cpu_features, &cpu_features_curr);
- const char *token = valp->strval;
- do
+ struct tunable_str_comma_state_t ts;
+ tunable_str_comma_init (&ts, valp);
+
+ struct tunable_str_comma_t t;
+ while (tunable_str_comma_next (&ts, &t))
{
- const char *token_end, *feature;
- bool disable;
- size_t token_len;
- size_t feature_len;
-
- /* 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;
- }
+ if (t.len == 0)
+ continue;
/* Handle only the features here which are really used in the
IFUNC-resolvers. All others are ignored as the values are only used
@@ -85,86 +67,64 @@ TUNABLE_CALLBACK (set_hwcaps) (tunable_val_t *valp)
bool reset_features = false;
unsigned long int hwcap_mask = 0UL;
unsigned long long stfle_bits0_mask = 0ULL;
+ bool disable = t.disable;
- if ((*feature == 'z' || *feature == 'a'))
+ if (tunable_str_comma_strcmp_cte (&t, "zEC12")
+ || tunable_str_comma_strcmp_cte (&t, "arch10"))
+ {
+ reset_features = true;
+ disable = true;
+ hwcap_mask = HWCAP_S390_VXRS | HWCAP_S390_VXRS_EXT
+ | HWCAP_S390_VXRS_EXT2;
+ stfle_bits0_mask = S390_STFLE_MASK_ARCH13_MIE3;
+ }
+ else if (tunable_str_comma_strcmp_cte (&t, "z13")
+ || tunable_str_comma_strcmp_cte (&t, "arch11"))
+ {
+ reset_features = true;
+ disable = true;
+ hwcap_mask = HWCAP_S390_VXRS_EXT | HWCAP_S390_VXRS_EXT2;
+ stfle_bits0_mask = S390_STFLE_MASK_ARCH13_MIE3;
+ }
+ else if (tunable_str_comma_strcmp_cte (&t, "z14")
+ || tunable_str_comma_strcmp_cte (&t, "arch12"))
+ {
+ reset_features = true;
+ disable = true;
+ hwcap_mask = HWCAP_S390_VXRS_EXT2;
+ stfle_bits0_mask = S390_STFLE_MASK_ARCH13_MIE3;
+ }
+ else if (tunable_str_comma_strcmp_cte (&t, "z15")
+ || tunable_str_comma_strcmp_cte (&t, "z16")
+ || tunable_str_comma_strcmp_cte (&t, "arch13")
+ || tunable_str_comma_strcmp_cte (&t, "arch14"))
{
- if ((feature_len == 5 && *feature == 'z'
- && memcmp (feature, "zEC12", 5) == 0)
- || (feature_len == 6 && *feature == 'a'
- && memcmp (feature, "arch10", 6) == 0))
- {
- reset_features = true;
- disable = true;
- hwcap_mask = HWCAP_S390_VXRS | HWCAP_S390_VXRS_EXT
- | HWCAP_S390_VXRS_EXT2;
- stfle_bits0_mask = S390_STFLE_MASK_ARCH13_MIE3;
- }
- else if ((feature_len == 3 && *feature == 'z'
- && memcmp (feature, "z13", 3) == 0)
- || (feature_len == 6 && *feature == 'a'
- && memcmp (feature, "arch11", 6) == 0))
- {
- reset_features = true;
- disable = true;
- hwcap_mask = HWCAP_S390_VXRS_EXT | HWCAP_S390_VXRS_EXT2;
- stfle_bits0_mask = S390_STFLE_MASK_ARCH13_MIE3;
- }
- else if ((feature_len == 3 && *feature == 'z'
- && memcmp (feature, "z14", 3) == 0)
- || (feature_len == 6 && *feature == 'a'
- && memcmp (feature, "arch12", 6) == 0))
- {
- reset_features = true;
- disable = true;
- hwcap_mask = HWCAP_S390_VXRS_EXT2;
- stfle_bits0_mask = S390_STFLE_MASK_ARCH13_MIE3;
- }
- else if ((feature_len == 3 && *feature == 'z'
- && (memcmp (feature, "z15", 3) == 0
- || memcmp (feature, "z16", 3) == 0))
- || (feature_len == 6
- && (memcmp (feature, "arch13", 6) == 0
- || memcmp (feature, "arch14", 6) == 0)))
- {
- /* For z15 or newer we don't have to disable something,
- but we have to reset to the original values. */
- reset_features = true;
- }
+ /* For z15 or newer we don't have to disable something, but we have
+ to reset to the original values. */
+ reset_features = true;
}
- else if (*feature == 'H')
+ else if (tunable_str_comma_strcmp_cte (&t, "HWCAP_S390_VXRS"))
{
- if (feature_len == 15
- && memcmp (feature, "HWCAP_S390_VXRS", 15) == 0)
- {
- hwcap_mask = HWCAP_S390_VXRS;
- if (disable)
- hwcap_mask |= HWCAP_S390_VXRS_EXT | HWCAP_S390_VXRS_EXT2;
- }
- else if (feature_len == 19
- && memcmp (feature, "HWCAP_S390_VXRS_EXT", 19) == 0)
- {
- hwcap_mask = HWCAP_S390_VXRS_EXT;
- if (disable)
- hwcap_mask |= HWCAP_S390_VXRS_EXT2;
- else
- hwcap_mask |= HWCAP_S390_VXRS;
- }
- else if (feature_len == 20
- && memcmp (feature, "HWCAP_S390_VXRS_EXT2", 20) == 0)
- {
- hwcap_mask = HWCAP_S390_VXRS_EXT2;
- if (!disable)
- hwcap_mask |= HWCAP_S390_VXRS | HWCAP_S390_VXRS_EXT;
- }
+ hwcap_mask = HWCAP_S390_VXRS;
+ if (t.disable)
+ hwcap_mask |= HWCAP_S390_VXRS_EXT | HWCAP_S390_VXRS_EXT2;
}
- else if (*feature == 'S')
+ else if (tunable_str_comma_strcmp_cte (&t, "HWCAP_S390_VXRS_EXT"))
{
- if (feature_len == 10
- && memcmp (feature, "STFLE_MIE3", 10) == 0)
- {
- stfle_bits0_mask = S390_STFLE_MASK_ARCH13_MIE3;
- }
+ hwcap_mask = HWCAP_S390_VXRS_EXT;
+ if (t.disable)
+ hwcap_mask |= HWCAP_S390_VXRS_EXT2;
+ else
+ hwcap_mask |= HWCAP_S390_VXRS;
+ }
+ else if (tunable_str_comma_strcmp_cte (&t, "HWCAP_S390_VXRS_EXT2"))
+ {
+ hwcap_mask = HWCAP_S390_VXRS_EXT2;
+ if (!t.disable)
+ 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;
/* Perform the actions determined above. */
if (reset_features)
@@ -187,14 +147,7 @@ TUNABLE_CALLBACK (set_hwcaps) (tunable_val_t *valp)
else
cpu_features_curr.stfle_bits[0] |= stfle_bits0_mask;
}
-
- /* Jump over current token ... */
- token += token_len;
-
- /* ... and skip token separator for next round. */
- if (*token == ',') token++;
}
- while (*token != '\0');
/* Copy back the features after checking that no unsupported features were
enabled by user. */