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

Florian Weimer fweimer@redhat.com
Thu Mar 27 15:36:53 GMT 2025


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



More information about the Libc-alpha mailing list