[PATCH] x86: Use separate variable for TLSDESC XSAVE/XSAVEC state size (bug 32810)

H.J. Lu hjl.tools@gmail.com
Thu Mar 27 15:45:17 GMT 2025


On Thu, Mar 27, 2025 at 8:37 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").
>
> ---
>  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_64/dl-tlsdesc-dynamic.h |  2 +-
>  5 files changed, 18 insertions(+), 8 deletions(-)
>
> diff --git a/sysdeps/x86/cpu-features.c b/sysdeps/x86/cpu-features.c
> index 27abaca8b7..0a715c1c04 100644
> --- a/sysdeps/x86/cpu-features.c
> +++ b/sysdeps/x86/cpu-features.c
> @@ -83,6 +83,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)
>  {
> @@ -317,6 +319,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))
> @@ -405,11 +408,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_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.  */
>
> base-commit: be61b9493d38032519e596f282f9695667402c8d
>

Can we add a glibc test?

-- 
H.J.


More information about the Libc-alpha mailing list