[PATCH v3 2/2] x86: Use separate variable for TLSDESC XSAVE/XSAVEC state size (bug 32810)
H.J. Lu
hjl.tools@gmail.com
Fri Mar 28 17:27:42 GMT 2025
On Fri, Mar 28, 2025 at 1:27 AM Florian Weimer <fweimer@redhat.com> wrote:
>
> Previously, the initialization code reused the xsave_state_full_size
> member of struct cpu_features for the TLSDESC state size. However,
> the tunable processing code assumes that this member has the
> original XSAVE (non-compact) state size, so that it can use its
> value if XSAVEC is disabled via tunable.
>
> This change uses a separate variable and not a struct member because
> the value is only needed in ld.so and the static libc, but not in
> libc.so. As a result, struct cpu_features layout does not change,
> helping a future backport of this change.
>
> Fixes commit 9b7091415af47082664717210ac49d51551456ab ("x86-64:
> Update _dl_tlsdesc_dynamic to preserve AMX registers").
> ---
> v3: No real change, H.J.'s review comment is addressed in first patch.
>
> sysdeps/x86/Makefile | 19 +++++++++++++++++++
> sysdeps/x86/cpu-features.c | 11 ++++++-----
> sysdeps/x86/cpu-tunables.c | 2 ++
> sysdeps/x86/dl-diagnostics-cpu.c | 2 ++
> sysdeps/x86/include/cpu-features.h | 9 +++++++--
> sysdeps/x86/tst-gnu2-tls2-x86-noxsave.c | 1 +
> sysdeps/x86/tst-gnu2-tls2-x86-noxsavec.c | 1 +
> sysdeps/x86/tst-gnu2-tls2-x86-noxsavexsavec.c | 1 +
> sysdeps/x86_64/dl-tlsdesc-dynamic.h | 2 +-
> 9 files changed, 40 insertions(+), 8 deletions(-)
> create mode 100644 sysdeps/x86/tst-gnu2-tls2-x86-noxsave.c
> create mode 100644 sysdeps/x86/tst-gnu2-tls2-x86-noxsavec.c
> create mode 100644 sysdeps/x86/tst-gnu2-tls2-x86-noxsavexsavec.c
>
> diff --git a/sysdeps/x86/Makefile b/sysdeps/x86/Makefile
> index 5311b594af..8819fba1b7 100644
> --- a/sysdeps/x86/Makefile
> +++ b/sysdeps/x86/Makefile
> @@ -21,6 +21,9 @@ tests += \
> tst-cpu-features-supports-static \
> tst-get-cpu-features \
> tst-get-cpu-features-static \
> + tst-gnu2-tls2-x86-noxsave \
> + tst-gnu2-tls2-x86-noxsavec \
> + tst-gnu2-tls2-x86-noxsavexsavec \
> tst-hwcap-tunables \
> # tests
> tests-static += \
> @@ -91,6 +94,22 @@ CFLAGS-tst-gnu2-tls2.c += -msse
> CFLAGS-tst-gnu2-tls2mod0.c += -msse2 -mtune=haswell
> CFLAGS-tst-gnu2-tls2mod1.c += -msse2 -mtune=haswell
> CFLAGS-tst-gnu2-tls2mod2.c += -msse2 -mtune=haswell
> +
> +LDFLAGS-tst-gnu2-tls2-x86-noxsave += -Wl,-z,lazy
> +LDFLAGS-tst-gnu2-tls2-x86-noxsavec += -Wl,-z,lazy
> +LDFLAGS-tst-gnu2-tls2-x86-noxsavexsavec += -Wl,-z,lazy
> +
> +# Test for bug 32810: incorrect XSAVE state size if XSAVEC is disabled
> +# via tunable.
> +tst-gnu2-tls2-x86-noxsave-ENV = GLIBC_TUNABLES=glibc.cpu.hwcaps=-XSAVE
> +tst-gnu2-tls2-x86-noxsavec-ENV = GLIBC_TUNABLES=glibc.cpu.hwcaps=-XSAVEC
> +tst-gnu2-tls2-x86-noxsavexsavec-ENV = GLIBC_TUNABLES=glibc.cpu.hwcaps=-XSAVE,-XSAVEC
> +$(objpfx)tst-gnu2-tls2-x86-noxsave.out \
> +$(objpfx)tst-gnu2-tls2-x86-noxsavec.out \
> +$(objpfx)tst-gnu2-tls2-x86-noxsavexsavec.out: \
> + $(objpfx)tst-gnu2-tls2mod0.so \
> + $(objpfx)tst-gnu2-tls2mod1.so \
> + $(objpfx)tst-gnu2-tls2mod2.so
> endif
>
> ifeq ($(subdir),math)
> diff --git a/sysdeps/x86/cpu-features.c b/sysdeps/x86/cpu-features.c
> index 6dfb112038..6cf7e4caf1 100644
> --- a/sysdeps/x86/cpu-features.c
> +++ b/sysdeps/x86/cpu-features.c
> @@ -84,6 +84,8 @@ extern void TUNABLE_CALLBACK (set_x86_shstk) (tunable_val_t *)
> # include <dl-cet.h>
> #endif
>
> +unsigned long int _dl_x86_features_tlsdesc_state_size;
> +
> static void
> update_active (struct cpu_features *cpu_features)
> {
> @@ -318,6 +320,7 @@ update_active (struct cpu_features *cpu_features)
> = xsave_state_full_size;
> cpu_features->xsave_state_full_size
> = xsave_state_full_size;
> + _dl_x86_features_tlsdesc_state_size = xsave_state_full_size;
>
> /* Check if XSAVEC is available. */
> if (CPU_FEATURES_CPU_P (cpu_features, XSAVEC))
> @@ -406,11 +409,9 @@ update_active (struct cpu_features *cpu_features)
> = ALIGN_UP ((amx_size
> + TLSDESC_CALL_REGISTER_SAVE_AREA),
> 64);
> - /* Set xsave_state_full_size to the compact AMX
> - state size for XSAVEC. NB: xsave_state_full_size
> - is only used in _dl_tlsdesc_dynamic_xsave and
> - _dl_tlsdesc_dynamic_xsavec. */
> - cpu_features->xsave_state_full_size = amx_size;
> + /* Set TLSDESC state size to the compact AMX
> + state size for XSAVEC. */
> + _dl_x86_features_tlsdesc_state_size = amx_size;
> #endif
> cpu_features->xsave_state_size
> = ALIGN_UP (size + TLSDESC_CALL_REGISTER_SAVE_AREA,
> diff --git a/sysdeps/x86/cpu-tunables.c b/sysdeps/x86/cpu-tunables.c
> index 3423176802..d692e0e0de 100644
> --- a/sysdeps/x86/cpu-tunables.c
> +++ b/sysdeps/x86/cpu-tunables.c
> @@ -164,6 +164,8 @@ TUNABLE_CALLBACK (set_hwcaps) (tunable_val_t *valp)
> /* Update xsave_state_size to XSAVE state size. */
> cpu_features->xsave_state_size
> = cpu_features->xsave_state_full_size;
> + _dl_x86_features_tlsdesc_state_size
> + = cpu_features->xsave_state_full_size;
> CPU_FEATURE_UNSET (cpu_features, XSAVEC);
> }
> }
> diff --git a/sysdeps/x86/dl-diagnostics-cpu.c b/sysdeps/x86/dl-diagnostics-cpu.c
> index 7d0373602d..870b1268db 100644
> --- a/sysdeps/x86/dl-diagnostics-cpu.c
> +++ b/sysdeps/x86/dl-diagnostics-cpu.c
> @@ -89,6 +89,8 @@ _dl_diagnostics_cpu (void)
> cpu_features->xsave_state_size);
> print_cpu_features_value ("xsave_state_full_size",
> cpu_features->xsave_state_full_size);
> + print_cpu_features_value ("tlsdesc_state_full_size",
> + _dl_x86_features_tlsdesc_state_size);
> print_cpu_features_value ("data_cache_size", cpu_features->data_cache_size);
> print_cpu_features_value ("shared_cache_size",
> cpu_features->shared_cache_size);
> diff --git a/sysdeps/x86/include/cpu-features.h b/sysdeps/x86/include/cpu-features.h
> index 9c485d38ef..fbf1b89110 100644
> --- a/sysdeps/x86/include/cpu-features.h
> +++ b/sysdeps/x86/include/cpu-features.h
> @@ -935,8 +935,6 @@ struct cpu_features
> /* The full state size for XSAVE when XSAVEC is disabled by
>
> GLIBC_TUNABLES=glibc.cpu.hwcaps=-XSAVEC
> -
> - and the AMX state size when XSAVEC is available.
> */
> unsigned int xsave_state_full_size;
> /* Data cache size for use in memory and string routines, typically
> @@ -990,6 +988,13 @@ extern const struct cpu_features *_dl_x86_get_cpu_features (void)
>
> #define __get_cpu_features() _dl_x86_get_cpu_features()
>
> +#if IS_IN (rtld) || IS_IN (libc)
> +/* XSAVE/XSAVEC state size used by TLS descriptors. Compared to
> + xsave_state_size from struct cpu_features, this includes additional
> + registers. */
> +extern unsigned long int _dl_x86_features_tlsdesc_state_size attribute_hidden;
> +#endif
> +
> #if defined (_LIBC) && !IS_IN (nonlib)
> /* Unused for x86. */
> # define INIT_ARCH()
> diff --git a/sysdeps/x86/tst-gnu2-tls2-x86-noxsave.c b/sysdeps/x86/tst-gnu2-tls2-x86-noxsave.c
> new file mode 100644
> index 0000000000..f0024c143d
> --- /dev/null
> +++ b/sysdeps/x86/tst-gnu2-tls2-x86-noxsave.c
> @@ -0,0 +1 @@
> +#include <elf/tst-gnu2-tls2.c>
> diff --git a/sysdeps/x86/tst-gnu2-tls2-x86-noxsavec.c b/sysdeps/x86/tst-gnu2-tls2-x86-noxsavec.c
> new file mode 100644
> index 0000000000..f0024c143d
> --- /dev/null
> +++ b/sysdeps/x86/tst-gnu2-tls2-x86-noxsavec.c
> @@ -0,0 +1 @@
> +#include <elf/tst-gnu2-tls2.c>
> diff --git a/sysdeps/x86/tst-gnu2-tls2-x86-noxsavexsavec.c b/sysdeps/x86/tst-gnu2-tls2-x86-noxsavexsavec.c
> new file mode 100644
> index 0000000000..f0024c143d
> --- /dev/null
> +++ b/sysdeps/x86/tst-gnu2-tls2-x86-noxsavexsavec.c
> @@ -0,0 +1 @@
> +#include <elf/tst-gnu2-tls2.c>
> diff --git a/sysdeps/x86_64/dl-tlsdesc-dynamic.h b/sysdeps/x86_64/dl-tlsdesc-dynamic.h
> index 9965ddd2c0..4f496de8c8 100644
> --- a/sysdeps/x86_64/dl-tlsdesc-dynamic.h
> +++ b/sysdeps/x86_64/dl-tlsdesc-dynamic.h
> @@ -99,7 +99,7 @@ _dl_tlsdesc_dynamic:
> # endif
> #else
> /* Allocate stack space of the required size to save the state. */
> - sub _rtld_local_ro+RTLD_GLOBAL_RO_DL_X86_CPU_FEATURES_OFFSET+XSAVE_STATE_FULL_SIZE_OFFSET(%rip), %RSP_LP
> + sub _dl_x86_features_tlsdesc_state_size(%rip), %RSP_LP
> #endif
> /* Besides rdi and rsi, saved above, save rcx, rdx, r8, r9,
> r10 and r11. */
> --
> 2.48.1
>
LGTM.
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
Thanks.
--
H.J.
More information about the Libc-alpha
mailing list