diff --git a/glibc-rh2024347-1.patch b/glibc-rh2024347-1.patch new file mode 100644 index 0000000..1c18bfa --- /dev/null +++ b/glibc-rh2024347-1.patch @@ -0,0 +1,98 @@ +commit 84a7eb1f87c1d01b58ad887a0ab5d87abbc1c772 +Author: H.J. Lu +Date: Fri Jul 30 19:07:30 2021 -0700 + + Use __executable_start as the lowest address for profiling [BZ #28153] + + Glibc assumes that ENTRY_POINT is the lowest address for which we need + to keep profiling records and BFD linker uses a linker script to place + the input sections. + + Starting from GCC 4.6, the main function is placed in .text.startup + section and starting from binutils 2.22, BFD linker with + + commit add44f8d5c5c05e08b11e033127a744d61c26aee + Author: Alan Modra + Date: Thu Nov 25 03:03:02 2010 +0000 + + * scripttempl/elf.sc: Group .text.exit, text.startup and .text.hot + sections. + + places .text.startup section before .text section, which leave the main + function out of profiling records. + + Starting from binutils 2.15, linker provides __executable_start to mark + the lowest address of the executable. Use __executable_start as the + lowest address to keep the main function in profiling records. This fixes + [BZ #28153]. + + Tested on Linux/x86-64, Linux/x32 and Linux/i686 as well as with + build-many-glibcs.py. + +diff --git a/csu/gmon-start.c b/csu/gmon-start.c +index b3432885b39071cc..344606a676c188d4 100644 +--- a/csu/gmon-start.c ++++ b/csu/gmon-start.c +@@ -52,6 +52,11 @@ extern char ENTRY_POINT[]; + #endif + extern char etext[]; + ++/* Use __executable_start as the lowest address to keep profiling records ++ if it provided by the linker. */ ++extern const char executable_start[] asm ("__executable_start") ++ __attribute__ ((weak, visibility ("hidden"))); ++ + #ifndef TEXT_START + # ifdef ENTRY_POINT_DECL + # define TEXT_START ENTRY_POINT +@@ -92,7 +97,10 @@ __gmon_start__ (void) + called = 1; + + /* Start keeping profiling records. */ +- __monstartup ((u_long) TEXT_START, (u_long) &etext); ++ if (&executable_start != NULL) ++ __monstartup ((u_long) &executable_start, (u_long) &etext); ++ else ++ __monstartup ((u_long) TEXT_START, (u_long) &etext); + + /* Call _mcleanup before exiting; it will write out gmon.out from the + collected data. */ +diff --git a/gmon/tst-gmon-gprof.sh b/gmon/tst-gmon-gprof.sh +index 9d371582b99677fa..dc0be021104f725d 100644 +--- a/gmon/tst-gmon-gprof.sh ++++ b/gmon/tst-gmon-gprof.sh +@@ -39,12 +39,14 @@ trap cleanup 0 + cat > "$expected" < "$expected_dot" < "$expected" < "$expected_dot" < +Date: Thu Dec 9 09:49:32 2021 +0100 + + nptl: rseq failure after registration on main thread is fatal + + This simplifies the application programming model. + + Browser sandboxes have already been fixed: + + Sandbox is incompatible with rseq registration + + + Allow rseq in the Linux sandboxes. r=gcp + + + Sandbox needs to support rseq system call + + + Linux sandbox: Allow rseq(2) + + + Reviewed-by: Szabolcs Nagy + +diff --git a/nptl/pthread_create.c b/nptl/pthread_create.c +index f405fa356c2955ce..109c5e3dc78c9aa2 100644 +--- a/nptl/pthread_create.c ++++ b/nptl/pthread_create.c +@@ -371,7 +371,8 @@ start_thread (void *arg) + /* Register rseq TLS to the kernel. */ + { + bool do_rseq = THREAD_GETMEM (pd, flags) & ATTR_FLAG_DO_RSEQ; +- rseq_register_current_thread (pd, do_rseq); ++ if (!rseq_register_current_thread (pd, do_rseq) && do_rseq) ++ __libc_fatal ("Fatal glibc error: rseq registration failed\n"); + } + + #ifndef __ASSUME_SET_ROBUST_LIST +diff --git a/sysdeps/unix/sysv/linux/rseq-internal.h b/sysdeps/unix/sysv/linux/rseq-internal.h +index 15bc7ffd6eda632d..6a3441f2cc49e7c4 100644 +--- a/sysdeps/unix/sysv/linux/rseq-internal.h ++++ b/sysdeps/unix/sysv/linux/rseq-internal.h +@@ -26,7 +26,7 @@ + #include + + #ifdef RSEQ_SIG +-static inline void ++static inline bool + rseq_register_current_thread (struct pthread *self, bool do_rseq) + { + if (do_rseq) +@@ -35,15 +35,17 @@ rseq_register_current_thread (struct pthread *self, bool do_rseq) + sizeof (self->rseq_area), + 0, RSEQ_SIG); + if (!INTERNAL_SYSCALL_ERROR_P (ret)) +- return; ++ return true; + } + THREAD_SETMEM (self, rseq_area.cpu_id, RSEQ_CPU_ID_REGISTRATION_FAILED); ++ return false; + } + #else /* RSEQ_SIG */ + static inline void + rseq_register_current_thread (struct pthread *self, bool do_rseq) + { + THREAD_SETMEM (self, rseq_area.cpu_id, RSEQ_CPU_ID_REGISTRATION_FAILED); ++ return false; + } + #endif /* RSEQ_SIG */ + diff --git a/glibc-rh2024347-11.patch b/glibc-rh2024347-11.patch new file mode 100644 index 0000000..3060a51 --- /dev/null +++ b/glibc-rh2024347-11.patch @@ -0,0 +1,592 @@ +commit 627f5ede70d70c77bdaf857db07404e8bf7f60af +Author: Florian Weimer +Date: Thu Dec 9 17:57:11 2021 +0100 + + Remove TLS_TCB_ALIGN and TLS_INIT_TCB_ALIGN + + TLS_INIT_TCB_ALIGN is not actually used. TLS_TCB_ALIGN was likely + introduced to support a configuration where the thread pointer + has not the same alignment as THREAD_SELF. Only ia64 seems to use + that, but for the stack/pointer guard, not for storing tcbhead_t. + Some ports use TLS_TCB_OFFSET and TLS_PRE_TCB_SIZE to shift + the thread pointer, potentially landing in a different residue class + modulo the alignment, but the changes should not impact that. + + In general, given that TLS variables have their own alignment + requirements, having different alignment for the (unshifted) thread + pointer and struct pthread would potentially result in dynamic + offsets, leading to more complexity. + + hppa had different values before: __alignof__ (tcbhead_t), which + seems to be 4, and __alignof__ (struct pthread), which was 8 + (old default) and is now 32. However, it defines THREAD_SELF as: + + /* Return the thread descriptor for the current thread. */ + # define THREAD_SELF \ + ({ struct pthread *__self; \ + __self = __get_cr27(); \ + __self - 1; \ + }) + + So the thread pointer points after struct pthread (hence __self - 1), + and they have to have the same alignment on hppa as well. + + Similarly, on ia64, the definitions were different. We have: + + # define TLS_PRE_TCB_SIZE \ + (sizeof (struct pthread) \ + + (PTHREAD_STRUCT_END_PADDING < 2 * sizeof (uintptr_t) \ + ? ((2 * sizeof (uintptr_t) + __alignof__ (struct pthread) - 1) \ + & ~(__alignof__ (struct pthread) - 1)) \ + : 0)) + # define THREAD_SELF \ + ((struct pthread *) ((char *) __thread_self - TLS_PRE_TCB_SIZE)) + + And TLS_PRE_TCB_SIZE is a multiple of the struct pthread alignment + (confirmed by the new _Static_assert in sysdeps/ia64/libc-tls.c). + + On m68k, we have a larger gap between tcbhead_t and struct pthread. + But as far as I can tell, the port is fine with that. The definition + of TCB_OFFSET is sufficient to handle the shifted TCB scenario. + + This fixes commit 23c77f60181eb549f11ec2f913b4270af29eee38 + ("nptl: Increase default TCB alignment to 32"). + + Reviewed-by: H.J. Lu + +diff --git a/csu/libc-tls.c b/csu/libc-tls.c +index 5515204863218163..d83e69f6257ae981 100644 +--- a/csu/libc-tls.c ++++ b/csu/libc-tls.c +@@ -24,6 +24,7 @@ + #include + #include + #include ++#include + + #ifdef SHARED + #error makefile bug, this file is for static only +@@ -89,7 +90,7 @@ init_static_tls (size_t memsz, size_t align) + { + /* That is the size of the TLS memory for this object. */ + GL(dl_tls_static_size) = roundup (memsz + GLRO(dl_tls_static_surplus), +- TLS_TCB_ALIGN); ++ TCB_ALIGNMENT); + #if TLS_TCB_AT_TP + GL(dl_tls_static_size) += TLS_TCB_SIZE; + #endif +@@ -214,5 +215,5 @@ __libc_setup_tls (void) + memsz += tcb_offset; + #endif + +- init_static_tls (memsz, MAX (TLS_TCB_ALIGN, max_align)); ++ init_static_tls (memsz, MAX (TCB_ALIGNMENT, max_align)); + } +diff --git a/elf/dl-tls.c b/elf/dl-tls.c +index 40263cf586e74c64..e2012d0cd515103b 100644 +--- a/elf/dl-tls.c ++++ b/elf/dl-tls.c +@@ -219,7 +219,7 @@ _dl_count_modids (void) + void + _dl_determine_tlsoffset (void) + { +- size_t max_align = TLS_TCB_ALIGN; ++ size_t max_align = TCB_ALIGNMENT; + size_t freetop = 0; + size_t freebottom = 0; + +@@ -350,7 +350,7 @@ _dl_determine_tlsoffset (void) + + GL(dl_tls_static_used) = offset; + GLRO (dl_tls_static_size) = roundup (offset + GLRO(dl_tls_static_surplus), +- TLS_TCB_ALIGN); ++ TCB_ALIGNMENT); + #else + # error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined" + #endif +diff --git a/sysdeps/aarch64/nptl/tls.h b/sysdeps/aarch64/nptl/tls.h +index cd9abb5d1d073593..75c469d51b532a89 100644 +--- a/sysdeps/aarch64/nptl/tls.h ++++ b/sysdeps/aarch64/nptl/tls.h +@@ -52,18 +52,12 @@ typedef struct + /* This is the size of the initial TCB. */ + # define TLS_INIT_TCB_SIZE sizeof (tcbhead_t) + +-/* Alignment requirements for the initial TCB. */ +-# define TLS_INIT_TCB_ALIGN __alignof__ (struct pthread) +- + /* This is the size of the TCB. */ + # define TLS_TCB_SIZE sizeof (tcbhead_t) + + /* This is the size we need before TCB. */ + # define TLS_PRE_TCB_SIZE sizeof (struct pthread) + +-/* Alignment requirements for the TCB. */ +-# define TLS_TCB_ALIGN __alignof__ (struct pthread) +- + /* Install the dtv pointer. The pointer passed is to the element with + index -1 which contain the length. */ + # define INSTALL_DTV(tcbp, dtvp) \ +diff --git a/sysdeps/alpha/nptl/tls.h b/sysdeps/alpha/nptl/tls.h +index 5f4843b28e7f1ad1..c0b6c93891546480 100644 +--- a/sysdeps/alpha/nptl/tls.h ++++ b/sysdeps/alpha/nptl/tls.h +@@ -46,18 +46,12 @@ typedef struct + /* This is the size of the initial TCB. */ + # define TLS_INIT_TCB_SIZE sizeof (tcbhead_t) + +-/* Alignment requirements for the initial TCB. */ +-# define TLS_INIT_TCB_ALIGN 16 +- + /* This is the size of the TCB. */ + # define TLS_TCB_SIZE sizeof (tcbhead_t) + + /* This is the size we need before TCB. */ + # define TLS_PRE_TCB_SIZE sizeof (struct pthread) + +-/* Alignment requirements for the TCB. */ +-# define TLS_TCB_ALIGN 16 +- + /* Install the dtv pointer. The pointer passed is to the element with + index -1 which contain the length. */ + # define INSTALL_DTV(tcbp, dtvp) \ +diff --git a/sysdeps/arc/nptl/tls.h b/sysdeps/arc/nptl/tls.h +index d9ada2f38089e6cd..d5d282297d12ec98 100644 +--- a/sysdeps/arc/nptl/tls.h ++++ b/sysdeps/arc/nptl/tls.h +@@ -48,17 +48,11 @@ typedef struct + /* This is the size of the initial TCB. */ + # define TLS_INIT_TCB_SIZE sizeof (tcbhead_t) + +-/* Alignment requirements for the initial TCB. */ +-# define TLS_INIT_TCB_ALIGN __alignof__ (struct pthread) +- + /* This is the size of the TCB. */ + #ifndef TLS_TCB_SIZE + # define TLS_TCB_SIZE sizeof (tcbhead_t) + #endif + +-/* Alignment requirements for the TCB. */ +-# define TLS_TCB_ALIGN __alignof__ (struct pthread) +- + /* This is the size we need before TCB. */ + # define TLS_PRE_TCB_SIZE sizeof (struct pthread) + +diff --git a/sysdeps/arm/nptl/tls.h b/sysdeps/arm/nptl/tls.h +index 354aae3318291395..8475c66588f99cae 100644 +--- a/sysdeps/arm/nptl/tls.h ++++ b/sysdeps/arm/nptl/tls.h +@@ -50,18 +50,12 @@ typedef struct + /* This is the size of the initial TCB. */ + # define TLS_INIT_TCB_SIZE sizeof (tcbhead_t) + +-/* Alignment requirements for the initial TCB. */ +-# define TLS_INIT_TCB_ALIGN 16 +- + /* This is the size of the TCB. */ + # define TLS_TCB_SIZE sizeof (tcbhead_t) + + /* This is the size we need before TCB. */ + # define TLS_PRE_TCB_SIZE sizeof (struct pthread) + +-/* Alignment requirements for the TCB. */ +-# define TLS_TCB_ALIGN 16 +- + /* Install the dtv pointer. The pointer passed is to the element with + index -1 which contain the length. */ + # define INSTALL_DTV(tcbp, dtvp) \ +diff --git a/sysdeps/csky/nptl/tls.h b/sysdeps/csky/nptl/tls.h +index f3fa3fcb02748776..e81d4552d27e0378 100644 +--- a/sysdeps/csky/nptl/tls.h ++++ b/sysdeps/csky/nptl/tls.h +@@ -61,15 +61,9 @@ typedef struct + /* This is the size of the initial TCB. */ + # define TLS_INIT_TCB_SIZE sizeof (tcbhead_t) + +-/* Alignment requirements for the initial TCB. */ +-# define TLS_INIT_TCB_ALIGN 8 +- + /* This is the size of the TCB. */ + # define TLS_TCB_SIZE sizeof (tcbhead_t) + +-/* Alignment requirements for the TCB. */ +-# define TLS_TCB_ALIGN 8 +- + /* This is the size we need before TCB. */ + # define TLS_PRE_TCB_SIZE sizeof (struct pthread) + +diff --git a/sysdeps/generic/tls.h b/sysdeps/generic/tls.h +index e86d70e6cebba5c8..9214ed39b6383e8c 100644 +--- a/sysdeps/generic/tls.h ++++ b/sysdeps/generic/tls.h +@@ -19,6 +19,11 @@ + /* An architecture-specific version of this file has to defined a + number of symbols: + ++ TCB_ALIGNMENT ++ ++ Alignment of THREAD_SELF (struct pthread *) and the thread ++ pointer. ++ + TLS_TCB_AT_TP or TLS_DTV_AT_TP + + The presence of one of these symbols signals which variant of +@@ -43,15 +48,6 @@ + dynamic linker itself. There are no threads in use at that time. + + +- TLS_TCB_ALIGN +- +- Alignment requirements for the TCB structure. +- +- TLS_INIT_TCB_ALIGN +- +- Similarly, but for the structure used at startup time. +- +- + INSTALL_DTV(tcb, init_dtv) + + This macro must install the given initial DTV into the thread control +diff --git a/sysdeps/hppa/nptl/tls.h b/sysdeps/hppa/nptl/tls.h +index f0e274c45fb5e91e..88a6b902c0b7e2fd 100644 +--- a/sysdeps/hppa/nptl/tls.h ++++ b/sysdeps/hppa/nptl/tls.h +@@ -52,15 +52,9 @@ typedef struct + /* This is the size of the initial TCB. */ + # define TLS_INIT_TCB_SIZE sizeof (tcbhead_t) + +-/* Alignment requirements for the initial TCB. */ +-# define TLS_INIT_TCB_ALIGN __alignof__ (tcbhead_t) +- + /* This is the size of the TCB. */ + # define TLS_TCB_SIZE sizeof (tcbhead_t) + +-/* Alignment requirements for the TCB. */ +-# define TLS_TCB_ALIGN __alignof__ (struct pthread) +- + /* This is the size we need before TCB */ + # define TLS_PRE_TCB_SIZE sizeof (struct pthread) + +diff --git a/sysdeps/i386/nptl/tls.h b/sysdeps/i386/nptl/tls.h +index 111c9ee59df30bc3..06ab9784a5358b0b 100644 +--- a/sysdeps/i386/nptl/tls.h ++++ b/sysdeps/i386/nptl/tls.h +@@ -102,15 +102,9 @@ union user_desc_init + struct pthread even when not linked with -lpthread. */ + # define TLS_INIT_TCB_SIZE sizeof (struct pthread) + +-/* Alignment requirements for the initial TCB. */ +-# define TLS_INIT_TCB_ALIGN __alignof__ (struct pthread) +- + /* This is the size of the TCB. */ + # define TLS_TCB_SIZE sizeof (struct pthread) + +-/* Alignment requirements for the TCB. */ +-# define TLS_TCB_ALIGN __alignof__ (struct pthread) +- + /* The TCB can have any size and the memory following the address the + thread pointer points to is unspecified. Allocate the TCB there. */ + # define TLS_TCB_AT_TP 1 +diff --git a/sysdeps/ia64/libc-tls.c b/sysdeps/ia64/libc-tls.c +index a01edceab36d375e..ede1e8f463b135b4 100644 +--- a/sysdeps/ia64/libc-tls.c ++++ b/sysdeps/ia64/libc-tls.c +@@ -18,6 +18,9 @@ + + #include + ++_Static_assert (TLS_PRE_TCB_SIZE % __alignof (struct pthread) == 0, ++ "__thread_self and THREAD_SELF have same alignment"); ++ + /* On IA-64, as it lacks linker optimizations, __tls_get_addr can be + called even in statically linked binaries. + In this case module must be always 1 and PT_TLS segment +diff --git a/sysdeps/ia64/nptl/tls.h b/sysdeps/ia64/nptl/tls.h +index 26fe555cb4b5e164..ca8f1280aeeed3d5 100644 +--- a/sysdeps/ia64/nptl/tls.h ++++ b/sysdeps/ia64/nptl/tls.h +@@ -53,9 +53,6 @@ register struct pthread *__thread_self __asm__("r13"); + /* This is the size of the initial TCB. */ + # define TLS_INIT_TCB_SIZE sizeof (tcbhead_t) + +-/* Alignment requirements for the initial TCB. */ +-# define TLS_INIT_TCB_ALIGN __alignof__ (tcbhead_t) +- + /* This is the size of the TCB. */ + # define TLS_TCB_SIZE sizeof (tcbhead_t) + +@@ -70,9 +67,6 @@ register struct pthread *__thread_self __asm__("r13"); + & ~(__alignof__ (struct pthread) - 1)) \ + : 0)) + +-/* Alignment requirements for the TCB. */ +-# define TLS_TCB_ALIGN __alignof__ (struct pthread) +- + /* The DTV is allocated at the TP; the TCB is placed elsewhere. */ + # define TLS_DTV_AT_TP 1 + # define TLS_TCB_AT_TP 0 +diff --git a/sysdeps/m68k/nptl/tls.h b/sysdeps/m68k/nptl/tls.h +index 9f562c38288df200..b88ef0c9c74ae0b0 100644 +--- a/sysdeps/m68k/nptl/tls.h ++++ b/sysdeps/m68k/nptl/tls.h +@@ -54,20 +54,15 @@ typedef struct + pointer, we don't need this. */ + # define TLS_INIT_TCB_SIZE 0 + +-/* Alignment requirements for the initial TCB. */ +-# define TLS_INIT_TCB_ALIGN __alignof__ (struct pthread) +- + /* This is the size of the TCB. Because our TCB is before the thread + pointer, we don't need this. */ + # define TLS_TCB_SIZE 0 + +-/* Alignment requirements for the TCB. */ +-# define TLS_TCB_ALIGN __alignof__ (struct pthread) +- + /* This is the size we need before TCB - actually, it includes the TCB. */ + # define TLS_PRE_TCB_SIZE \ + (sizeof (struct pthread) \ +- + ((sizeof (tcbhead_t) + TLS_TCB_ALIGN - 1) & ~(TLS_TCB_ALIGN - 1))) ++ + ((sizeof (tcbhead_t) + __alignof (struct pthread) - 1) \ ++ & ~(__alignof (struct pthread) - 1))) + + /* The thread pointer (TP) points to the end of the + TCB + 0x7000, as for PowerPC and MIPS. This implies that TCB address is +diff --git a/sysdeps/mach/hurd/tls.h b/sysdeps/mach/hurd/tls.h +index f83956d3d7ca4f9f..773a2a0c36d5d57d 100644 +--- a/sysdeps/mach/hurd/tls.h ++++ b/sysdeps/mach/hurd/tls.h +@@ -29,20 +29,12 @@ + # include + # include + +- + /* This is the size of the initial TCB. */ + # define TLS_INIT_TCB_SIZE sizeof (tcbhead_t) + +-/* Alignment requirements for the initial TCB. */ +-# define TLS_INIT_TCB_ALIGN __alignof__ (tcbhead_t) +- + /* This is the size of the TCB. */ + # define TLS_TCB_SIZE TLS_INIT_TCB_SIZE /* XXX */ + +-/* Alignment requirements for the TCB. */ +-# define TLS_TCB_ALIGN TLS_INIT_TCB_ALIGN /* XXX */ +- +- + /* Install the dtv pointer. The pointer passed is to the element with + index -1 which contain the length. */ + # define INSTALL_DTV(descr, dtvp) \ +diff --git a/sysdeps/microblaze/nptl/tls.h b/sysdeps/microblaze/nptl/tls.h +index bfa6efa78049bb2d..b69d7b4f28f3b757 100644 +--- a/sysdeps/microblaze/nptl/tls.h ++++ b/sysdeps/microblaze/nptl/tls.h +@@ -56,18 +56,12 @@ typedef struct + /* This is the size of the initial TCB. */ + # define TLS_INIT_TCB_SIZE sizeof (tcbhead_t) + +-/* Alignment requirements for the initial TCB. */ +-# define TLS_INIT_TCB_ALIGN __alignof__ (tcbhead_t) +- + /* This is the size of the TCB. */ + # define TLS_TCB_SIZE sizeof (tcbhead_t) + + /* This is the size we need before TCB. */ + # define TLS_PRE_TCB_SIZE sizeof (struct pthread) + +-/* Alignment requirements for the TCB. */ +-# define TLS_TCB_ALIGN __alignof__ (struct pthread) +- + /* Install the dtv pointer. The pointer passed is to the element with + index -1 which contain the length. */ + # define INSTALL_DTV(tcbp, dtvp) \ +diff --git a/sysdeps/mips/nptl/tls.h b/sysdeps/mips/nptl/tls.h +index ef99aa646c898e76..6ccaf9804a68634a 100644 +--- a/sysdeps/mips/nptl/tls.h ++++ b/sysdeps/mips/nptl/tls.h +@@ -83,20 +83,15 @@ typedef struct + pointer, we don't need this. */ + # define TLS_INIT_TCB_SIZE 0 + +-/* Alignment requirements for the initial TCB. */ +-# define TLS_INIT_TCB_ALIGN __alignof__ (struct pthread) +- + /* This is the size of the TCB. Because our TCB is before the thread + pointer, we don't need this. */ + # define TLS_TCB_SIZE 0 + +-/* Alignment requirements for the TCB. */ +-# define TLS_TCB_ALIGN __alignof__ (struct pthread) +- + /* This is the size we need before TCB - actually, it includes the TCB. */ + # define TLS_PRE_TCB_SIZE \ + (sizeof (struct pthread) \ +- + ((sizeof (tcbhead_t) + TLS_TCB_ALIGN - 1) & ~(TLS_TCB_ALIGN - 1))) ++ + ((sizeof (tcbhead_t) + __alignof (struct pthread) - 1) \ ++ & ~(__alignof (struct pthread) - 1))) + + /* The thread pointer (in hardware register $29) points to the end of + the TCB + 0x7000, as for PowerPC. The pthread_descr structure is +diff --git a/sysdeps/nios2/nptl/tls.h b/sysdeps/nios2/nptl/tls.h +index 7110cfccad7131f4..6ab6bd27b00a70ee 100644 +--- a/sysdeps/nios2/nptl/tls.h ++++ b/sysdeps/nios2/nptl/tls.h +@@ -59,20 +59,15 @@ register struct pthread *__thread_self __asm__("r23"); + pointer, we don't need this. */ + # define TLS_INIT_TCB_SIZE 0 + +-/* Alignment requirements for the initial TCB. */ +-# define TLS_INIT_TCB_ALIGN __alignof__ (struct pthread) +- + /* This is the size of the TCB. Because our TCB is before the thread + pointer, we don't need this. */ + # define TLS_TCB_SIZE 0 + +-/* Alignment requirements for the TCB. */ +-# define TLS_TCB_ALIGN __alignof__ (struct pthread) +- + /* This is the size we need before TCB - actually, it includes the TCB. */ + # define TLS_PRE_TCB_SIZE \ + (sizeof (struct pthread) \ +- + ((sizeof (tcbhead_t) + TLS_TCB_ALIGN - 1) & ~(TLS_TCB_ALIGN - 1))) ++ + ((sizeof (tcbhead_t) + __alignof (struct pthread) - 1) \ ++ & ~(__alignof (struct pthread) - 1))) + + /* The thread pointer (in hardware register r23) points to the end of + the TCB + 0x7000, as for PowerPC and MIPS. */ +diff --git a/sysdeps/powerpc/nptl/tls.h b/sysdeps/powerpc/nptl/tls.h +index 110d085d30c86302..e194b334216eaa02 100644 +--- a/sysdeps/powerpc/nptl/tls.h ++++ b/sysdeps/powerpc/nptl/tls.h +@@ -108,19 +108,14 @@ typedef struct + /* This is the size of the initial TCB. */ + # define TLS_INIT_TCB_SIZE 0 + +-/* Alignment requirements for the initial TCB. */ +-# define TLS_INIT_TCB_ALIGN __alignof__ (struct pthread) +- + /* This is the size of the TCB. */ + # define TLS_TCB_SIZE 0 + +-/* Alignment requirements for the TCB. */ +-# define TLS_TCB_ALIGN __alignof__ (struct pthread) +- + /* This is the size we need before TCB. */ + # define TLS_PRE_TCB_SIZE \ + (sizeof (struct pthread) \ +- + ((sizeof (tcbhead_t) + TLS_TCB_ALIGN - 1) & ~(TLS_TCB_ALIGN - 1))) ++ + ((sizeof (tcbhead_t) + __alignof (struct pthread) - 1) \ ++ & ~(__alignof (struct pthread) - 1))) + + /* The following assumes that TP (R2 or R13) points to the end of the + TCB + 0x7000 (per the ABI). This implies that TCB address is +diff --git a/sysdeps/riscv/nptl/tls.h b/sysdeps/riscv/nptl/tls.h +index bdc0a3a6f91b51e8..8c12d8f971adeddb 100644 +--- a/sysdeps/riscv/nptl/tls.h ++++ b/sysdeps/riscv/nptl/tls.h +@@ -50,20 +50,15 @@ typedef struct + pointer, we don't need this. */ + # define TLS_INIT_TCB_SIZE 0 + +-/* Alignment requirements for the initial TCB. */ +-# define TLS_INIT_TCB_ALIGN __alignof__ (struct pthread) +- + /* This is the size of the TCB. Because our TCB is before the thread + pointer, we don't need this. */ + # define TLS_TCB_SIZE 0 + +-/* Alignment requirements for the TCB. */ +-# define TLS_TCB_ALIGN __alignof__ (struct pthread) +- + /* This is the size we need before TCB - actually, it includes the TCB. */ + # define TLS_PRE_TCB_SIZE \ + (sizeof (struct pthread) \ +- + ((sizeof (tcbhead_t) + TLS_TCB_ALIGN - 1) & ~(TLS_TCB_ALIGN - 1))) ++ + ((sizeof (tcbhead_t) + __alignof (struct pthread) - 1) \ ++ & ~(__alignof (struct pthread) - 1))) + + /* The thread pointer tp points to the end of the TCB. + The pthread_descr structure is immediately in front of the TCB. */ +diff --git a/sysdeps/s390/nptl/tls.h b/sysdeps/s390/nptl/tls.h +index 2cdd18eb2907c060..3b4c0ab32a9439a3 100644 +--- a/sysdeps/s390/nptl/tls.h ++++ b/sysdeps/s390/nptl/tls.h +@@ -66,15 +66,9 @@ typedef struct + struct pthread even when not linked with -lpthread. */ + # define TLS_INIT_TCB_SIZE sizeof (struct pthread) + +-/* Alignment requirements for the initial TCB. */ +-# define TLS_INIT_TCB_ALIGN __alignof__ (struct pthread) +- + /* This is the size of the TCB. */ + # define TLS_TCB_SIZE sizeof (struct pthread) + +-/* Alignment requirements for the TCB. */ +-# define TLS_TCB_ALIGN __alignof__ (struct pthread) +- + /* The TCB can have any size and the memory following the address the + thread pointer points to is unspecified. Allocate the TCB there. */ + # define TLS_TCB_AT_TP 1 +diff --git a/sysdeps/sh/nptl/tls.h b/sysdeps/sh/nptl/tls.h +index 390640020e45f716..3e4d480b35951253 100644 +--- a/sysdeps/sh/nptl/tls.h ++++ b/sysdeps/sh/nptl/tls.h +@@ -51,18 +51,12 @@ typedef struct + /* This is the size of the initial TCB. */ + # define TLS_INIT_TCB_SIZE sizeof (tcbhead_t) + +-/* Alignment requirements for the initial TCB. */ +-# define TLS_INIT_TCB_ALIGN __alignof__ (tcbhead_t) +- + /* This is the size of the TCB. */ + # define TLS_TCB_SIZE sizeof (tcbhead_t) + + /* This is the size we need before TCB. */ + # define TLS_PRE_TCB_SIZE sizeof (struct pthread) + +-/* Alignment requirements for the TCB. */ +-# define TLS_TCB_ALIGN __alignof__ (struct pthread) +- + /* The TLS blocks start right after the TCB. */ + # define TLS_DTV_AT_TP 1 + # define TLS_TCB_AT_TP 0 +diff --git a/sysdeps/sparc/nptl/tls.h b/sysdeps/sparc/nptl/tls.h +index 376d729989e35660..3fb4ce6e6dacf28c 100644 +--- a/sysdeps/sparc/nptl/tls.h ++++ b/sysdeps/sparc/nptl/tls.h +@@ -63,15 +63,9 @@ register struct pthread *__thread_self __asm__("%g7"); + struct pthread even when not linked with -lpthread. */ + # define TLS_INIT_TCB_SIZE sizeof (struct pthread) + +-/* Alignment requirements for the initial TCB. */ +-# define TLS_INIT_TCB_ALIGN __alignof__ (struct pthread) +- + /* This is the size of the TCB. */ + # define TLS_TCB_SIZE sizeof (struct pthread) + +-/* Alignment requirements for the TCB. */ +-# define TLS_TCB_ALIGN __alignof__ (struct pthread) +- + /* The TCB can have any size and the memory following the address the + thread pointer points to is unspecified. Allocate the TCB there. */ + # define TLS_TCB_AT_TP 1 +diff --git a/sysdeps/x86_64/nptl/tls.h b/sysdeps/x86_64/nptl/tls.h +index 3af1836e28b26fdb..50f7e8b544f9e6fc 100644 +--- a/sysdeps/x86_64/nptl/tls.h ++++ b/sysdeps/x86_64/nptl/tls.h +@@ -106,15 +106,9 @@ _Static_assert (offsetof (tcbhead_t, __glibc_unused2) == 0x80, + struct pthread even when not linked with -lpthread. */ + # define TLS_INIT_TCB_SIZE sizeof (struct pthread) + +-/* Alignment requirements for the initial TCB. */ +-# define TLS_INIT_TCB_ALIGN __alignof__ (struct pthread) +- + /* This is the size of the TCB. */ + # define TLS_TCB_SIZE sizeof (struct pthread) + +-/* Alignment requirements for the TCB. */ +-# define TLS_TCB_ALIGN __alignof__ (struct pthread) +- + /* The TCB can have any size and the memory following the address the + thread pointer points to is unspecified. Allocate the TCB there. */ + # define TLS_TCB_AT_TP 1 diff --git a/glibc-rh2024347-12.patch b/glibc-rh2024347-12.patch new file mode 100644 index 0000000..02a9cea --- /dev/null +++ b/glibc-rh2024347-12.patch @@ -0,0 +1,73 @@ +commit cb976fba4c51ede7bf8cee5035888527c308dfbc +Author: Florian Weimer +Date: Wed Dec 15 16:06:25 2021 +0100 + + powerpc: Use global register variable in + + A local register variable is merely a compiler hint, and so not + appropriate in this context. Move the global register variable into + and include it from , as there can only + be one global definition for one particular register. + + Fixes commit 8dbeb0561eeb876f557ac9eef5721912ec074ea5 + ("nptl: Add for defining __thread_pointer"). + + Reported-by: Mathieu Desnoyers + Reviewed-by: Raphael M Zinsly + +diff --git a/sysdeps/powerpc/nptl/thread_pointer.h b/sysdeps/powerpc/nptl/thread_pointer.h +index 8fd5ba671f6f5e64..4feba5961062cfaf 100644 +--- a/sysdeps/powerpc/nptl/thread_pointer.h ++++ b/sysdeps/powerpc/nptl/thread_pointer.h +@@ -19,15 +19,16 @@ + #ifndef _SYS_THREAD_POINTER_H + #define _SYS_THREAD_POINTER_H + +-static inline void * +-__thread_pointer (void) +-{ + #ifdef __powerpc64__ +- register void *__result asm ("r13"); ++register void *__thread_register asm ("r13"); + #else +- register void *__result asm ("r2"); ++register void *__thread_register asm ("r2"); + #endif +- return __result; ++ ++static inline void * ++__thread_pointer (void) ++{ ++ return __thread_register; + } + + #endif /* _SYS_THREAD_POINTER_H */ +diff --git a/sysdeps/powerpc/nptl/tls.h b/sysdeps/powerpc/nptl/tls.h +index e194b334216eaa02..050beb06a8f7de65 100644 +--- a/sysdeps/powerpc/nptl/tls.h ++++ b/sysdeps/powerpc/nptl/tls.h +@@ -26,6 +26,7 @@ + # include + # include + # include ++# include + + #else /* __ASSEMBLER__ */ + # include +@@ -36,16 +37,10 @@ + #ifndef __powerpc64__ + /* Register r2 (tp) is reserved by the ABI as "thread pointer". */ + # define PT_THREAD_POINTER PT_R2 +-# ifndef __ASSEMBLER__ +-register void *__thread_register __asm__ ("r2"); +-# endif + + #else /* __powerpc64__ */ + /* Register r13 (tp) is reserved by the ABI as "thread pointer". */ + # define PT_THREAD_POINTER PT_R13 +-# ifndef __ASSEMBLER__ +-register void *__thread_register __asm__ ("r13"); +-# endif + #endif /* __powerpc64__ */ + + #ifndef __ASSEMBLER__ diff --git a/glibc-rh2024347-13.patch b/glibc-rh2024347-13.patch new file mode 100644 index 0000000..f002a78 --- /dev/null +++ b/glibc-rh2024347-13.patch @@ -0,0 +1,42 @@ +Downstream-only patch to disable rseq by default. This is necessary +because CRIU does not yet support rseq: + + criu: Implement rseq support + + +diff --git a/manual/tunables.texi b/manual/tunables.texi +index 28ff502990c2a10f..f559c44dcec4624b 100644 +--- a/manual/tunables.texi ++++ b/manual/tunables.texi +@@ -425,11 +425,13 @@ The value is measured in bytes. The default is @samp{41943040} + @end deftp + + @deftp Tunable glibc.pthread.rseq +-The @code{glibc.pthread.rseq} tunable can be set to @samp{0}, to disable +-restartable sequences support in @theglibc{}. This enables applications +-to perform direct restartable sequence registration with the kernel. +-The default is @samp{1}, which means that @theglibc{} performs +-registration on behalf of the application. ++The @code{glibc.pthread.rseq} tunable can be set to @samp{1}, to enable ++restartable sequences support. @Theglibc{} uses this to optimize the ++@code{sched_getcpu} function. ++ ++The default is @samp{0}, which means that applications can perform ++restartable sequences registration, but @code{sched_getcpu} is not ++accelerated. + + Restartable sequences are a Linux-specific extension. + @end deftp +diff --git a/sysdeps/nptl/dl-tunables.list b/sysdeps/nptl/dl-tunables.list +index d24f4be0d08ba407..df2a39ce01858d3b 100644 +--- a/sysdeps/nptl/dl-tunables.list ++++ b/sysdeps/nptl/dl-tunables.list +@@ -31,7 +31,7 @@ glibc { + type: INT_32 + minval: 0 + maxval: 1 +- default: 1 ++ default: 0 + } + } + } diff --git a/glibc-rh2024347-2.patch b/glibc-rh2024347-2.patch new file mode 100644 index 0000000..71613f3 --- /dev/null +++ b/glibc-rh2024347-2.patch @@ -0,0 +1,259 @@ +commit 23c77f60181eb549f11ec2f913b4270af29eee38 +Author: Florian Weimer +Date: Fri Dec 3 16:28:07 2021 +0100 + + nptl: Increase default TCB alignment to 32 + + rseq support will use a 32-byte aligned field in struct pthread, + so the whole struct needs to have at least that alignment. + + nptl/tst-tls3mod.c uses TCB_ALIGNMENT, therefore include + to obtain the fallback definition. + + Reviewed-by: H.J. Lu + +diff --git a/nptl/descr.h b/nptl/descr.h +index 4de84138fb960fa4..57be5b4fef564b36 100644 +--- a/nptl/descr.h ++++ b/nptl/descr.h +@@ -37,7 +37,9 @@ + #include + + #ifndef TCB_ALIGNMENT +-# define TCB_ALIGNMENT sizeof (double) ++# define TCB_ALIGNMENT 32 ++#elif TCB_ALIGNMENT < 32 ++# error TCB_ALIGNMENT must be at least 32 + #endif + + +diff --git a/nptl/tst-tls3mod.c b/nptl/tst-tls3mod.c +index cfd13aace1affcd5..77dcc550fc3b5017 100644 +--- a/nptl/tst-tls3mod.c ++++ b/nptl/tst-tls3mod.c +@@ -24,6 +24,7 @@ + #include + #include + #include ++#include + + + extern pthread_barrier_t b; +diff --git a/sysdeps/aarch64/nptl/pthreaddef.h b/sysdeps/aarch64/nptl/pthreaddef.h +index 4d5ecf6661fd0fe6..8d9a10622d132a7a 100644 +--- a/sysdeps/aarch64/nptl/pthreaddef.h ++++ b/sysdeps/aarch64/nptl/pthreaddef.h +@@ -28,8 +28,5 @@ + /* Minimal stack size after allocating thread descriptor and guard size. */ + #define MINIMAL_REST_STACK 2048 + +-/* Alignment requirement for TCB. */ +-#define TCB_ALIGNMENT 16 +- + /* Location of current stack frame. */ + #define CURRENT_STACK_FRAME __builtin_frame_address (0) +diff --git a/sysdeps/alpha/nptl/pthreaddef.h b/sysdeps/alpha/nptl/pthreaddef.h +index 25edb5093e095548..660e5694a25ec60f 100644 +--- a/sysdeps/alpha/nptl/pthreaddef.h ++++ b/sysdeps/alpha/nptl/pthreaddef.h +@@ -27,8 +27,5 @@ + /* Minimal stack size after allocating thread descriptor and guard size. */ + #define MINIMAL_REST_STACK 4096 + +-/* Alignment requirement for TCB. */ +-#define TCB_ALIGNMENT 16 +- + /* Location of current stack frame. */ + #define CURRENT_STACK_FRAME __builtin_frame_address (0) +diff --git a/sysdeps/arc/nptl/pthreaddef.h b/sysdeps/arc/nptl/pthreaddef.h +index 873b9d149ac46a62..d4dbe9e079445353 100644 +--- a/sysdeps/arc/nptl/pthreaddef.h ++++ b/sysdeps/arc/nptl/pthreaddef.h +@@ -28,8 +28,5 @@ + /* Minimal stack size after allocating thread descriptor and guard size. */ + #define MINIMAL_REST_STACK 2048 + +-/* Alignment requirement for TCB. */ +-#define TCB_ALIGNMENT 4 +- + /* Location of current stack frame. */ + #define CURRENT_STACK_FRAME __builtin_frame_address (0) +diff --git a/sysdeps/arm/nptl/pthreaddef.h b/sysdeps/arm/nptl/pthreaddef.h +index 332f4079c4c3f2bf..13769f5ae270b0ca 100644 +--- a/sysdeps/arm/nptl/pthreaddef.h ++++ b/sysdeps/arm/nptl/pthreaddef.h +@@ -28,9 +28,6 @@ + /* Minimal stack size after allocating thread descriptor and guard size. */ + #define MINIMAL_REST_STACK 2048 + +-/* Alignment requirement for TCB. */ +-#define TCB_ALIGNMENT 16 +- + + /* Location of current stack frame. + +diff --git a/sysdeps/csky/nptl/pthreaddef.h b/sysdeps/csky/nptl/pthreaddef.h +index e78bc0016b43b450..7dde9131b9b1a6b0 100644 +--- a/sysdeps/csky/nptl/pthreaddef.h ++++ b/sysdeps/csky/nptl/pthreaddef.h +@@ -28,8 +28,5 @@ + /* Minimal stack size after allocating thread descriptor and guard size. */ + #define MINIMAL_REST_STACK 2048 + +-/* Alignment requirement for TCB. */ +-#define TCB_ALIGNMENT 8 +- + /* Location of current stack frame. */ + #define CURRENT_STACK_FRAME __builtin_frame_address (0) +diff --git a/sysdeps/ia64/nptl/pthreaddef.h b/sysdeps/ia64/nptl/pthreaddef.h +index 3a0f6daf9ad871aa..c7420fd1e4ee6081 100644 +--- a/sysdeps/ia64/nptl/pthreaddef.h ++++ b/sysdeps/ia64/nptl/pthreaddef.h +@@ -30,9 +30,6 @@ + /* Minimal stack size after allocating thread descriptor and guard size. */ + #define MINIMAL_REST_STACK 16384 + +-/* Alignment requirement for TCB. */ +-#define TCB_ALIGNMENT 16 +- + + /* Location of current stack frame. */ + #define CURRENT_STACK_FRAME __stack_pointer +diff --git a/sysdeps/m68k/nptl/pthreaddef.h b/sysdeps/m68k/nptl/pthreaddef.h +index 13e785a86bbf47b4..ce9511cb02da69fd 100644 +--- a/sysdeps/m68k/nptl/pthreaddef.h ++++ b/sysdeps/m68k/nptl/pthreaddef.h +@@ -28,9 +28,6 @@ + /* Minimal stack size after allocating thread descriptor and guard size. */ + #define MINIMAL_REST_STACK 2048 + +-/* Alignment requirement for TCB. */ +-#define TCB_ALIGNMENT 16 +- + + /* Location of current stack frame. */ + #define CURRENT_STACK_FRAME __builtin_frame_address (0) +diff --git a/sysdeps/microblaze/nptl/pthreaddef.h b/sysdeps/microblaze/nptl/pthreaddef.h +index 517157444da556ad..19d7235782afde53 100644 +--- a/sysdeps/microblaze/nptl/pthreaddef.h ++++ b/sysdeps/microblaze/nptl/pthreaddef.h +@@ -31,8 +31,5 @@ + /* Minimal stack size after allocating thread descriptor and guard size. */ + #define MINIMAL_REST_STACK 2048 + +-/* Alignment requirement for TCB. */ +-#define TCB_ALIGNMENT 16 +- + /* Location of current stack frame. */ + #define CURRENT_STACK_FRAME __builtin_frame_address (0) +diff --git a/sysdeps/mips/nptl/pthreaddef.h b/sysdeps/mips/nptl/pthreaddef.h +index a7bccef6e512438f..322591c293ce5e15 100644 +--- a/sysdeps/mips/nptl/pthreaddef.h ++++ b/sysdeps/mips/nptl/pthreaddef.h +@@ -27,9 +27,6 @@ + /* Minimal stack size after allocating thread descriptor and guard size. */ + #define MINIMAL_REST_STACK 2048 + +-/* Alignment requirement for TCB. */ +-#define TCB_ALIGNMENT 16 +- + + /* Location of current stack frame. */ + #define CURRENT_STACK_FRAME __builtin_frame_address (0) +diff --git a/sysdeps/nios2/nptl/pthreaddef.h b/sysdeps/nios2/nptl/pthreaddef.h +index e01a0e6df72c089a..aa0709d0dc69f251 100644 +--- a/sysdeps/nios2/nptl/pthreaddef.h ++++ b/sysdeps/nios2/nptl/pthreaddef.h +@@ -28,8 +28,5 @@ + /* Minimal stack size after allocating thread descriptor and guard size. */ + #define MINIMAL_REST_STACK 2048 + +-/* Alignment requirement for TCB. */ +-#define TCB_ALIGNMENT 4 +- + /* Location of current stack frame. */ + #define CURRENT_STACK_FRAME __builtin_frame_address (0) +diff --git a/sysdeps/powerpc/nptl/pthreaddef.h b/sysdeps/powerpc/nptl/pthreaddef.h +index ef5310e6315fde2c..117c35229ea68f48 100644 +--- a/sysdeps/powerpc/nptl/pthreaddef.h ++++ b/sysdeps/powerpc/nptl/pthreaddef.h +@@ -28,9 +28,6 @@ + /* Minimal stack size after allocating thread descriptor and guard size. */ + #define MINIMAL_REST_STACK 4096 + +-/* Alignment requirement for TCB. */ +-#define TCB_ALIGNMENT 16 +- + + /* Location of current stack frame. */ + #define CURRENT_STACK_FRAME __builtin_frame_address (0) +diff --git a/sysdeps/riscv/nptl/pthreaddef.h b/sysdeps/riscv/nptl/pthreaddef.h +index 7bf93d6a63fdecd2..0f33cc48fe4fc728 100644 +--- a/sysdeps/riscv/nptl/pthreaddef.h ++++ b/sysdeps/riscv/nptl/pthreaddef.h +@@ -28,8 +28,5 @@ + /* Minimal stack size after allocating thread descriptor and guard size. */ + #define MINIMAL_REST_STACK 2048 + +-/* Alignment requirement for TCB. */ +-#define TCB_ALIGNMENT 16 +- + /* Location of current stack frame. */ + #define CURRENT_STACK_FRAME __builtin_frame_address (0) +diff --git a/sysdeps/s390/nptl/pthreaddef.h b/sysdeps/s390/nptl/pthreaddef.h +index 091f82df24a4024c..0e32bd862f7fea48 100644 +--- a/sysdeps/s390/nptl/pthreaddef.h ++++ b/sysdeps/s390/nptl/pthreaddef.h +@@ -28,9 +28,6 @@ + /* Minimal stack size after allocating thread descriptor and guard size. */ + #define MINIMAL_REST_STACK 2048 + +-/* Alignment requirement for TCB. */ +-#define TCB_ALIGNMENT 16 +- + + /* Location of current stack frame. */ + #define CURRENT_STACK_FRAME __builtin_frame_address (0) +diff --git a/sysdeps/sh/nptl/pthreaddef.h b/sysdeps/sh/nptl/pthreaddef.h +index 3fa3d189ef969c90..f4e3a290df4ee6e6 100644 +--- a/sysdeps/sh/nptl/pthreaddef.h ++++ b/sysdeps/sh/nptl/pthreaddef.h +@@ -29,9 +29,6 @@ + /* Minimal stack size after allocating thread descriptor and guard size. */ + #define MINIMAL_REST_STACK 2048 + +-/* Alignment requirement for TCB. */ +-#define TCB_ALIGNMENT 8 +- + + /* Location of current stack frame. */ + #define CURRENT_STACK_FRAME __builtin_frame_address (0) +diff --git a/sysdeps/sparc/sparc32/pthreaddef.h b/sysdeps/sparc/sparc32/pthreaddef.h +index 6526fb3d6e7e1448..7a0a04789dac478e 100644 +--- a/sysdeps/sparc/sparc32/pthreaddef.h ++++ b/sysdeps/sparc/sparc32/pthreaddef.h +@@ -27,9 +27,6 @@ + /* Minimal stack size after allocating thread descriptor and guard size. */ + #define MINIMAL_REST_STACK 2048 + +-/* Alignment requirement for TCB. */ +-#define TCB_ALIGNMENT 16 +- + + /* Location of current stack frame. */ + #define CURRENT_STACK_FRAME (stack_pointer + (2 * 64)) +diff --git a/sysdeps/sparc/sparc64/pthreaddef.h b/sysdeps/sparc/sparc64/pthreaddef.h +index 3da9d7afc8054598..103842856d40432b 100644 +--- a/sysdeps/sparc/sparc64/pthreaddef.h ++++ b/sysdeps/sparc/sparc64/pthreaddef.h +@@ -27,10 +27,6 @@ + /* Minimal stack size after allocating thread descriptor and guard size. */ + #define MINIMAL_REST_STACK 4096 + +-/* Alignment requirement for TCB. */ +-#define TCB_ALIGNMENT 16 +- +- + /* Location of current stack frame. */ + #define CURRENT_STACK_FRAME (stack_pointer + (2 * 128)) + register char *stack_pointer __asm__("%sp"); diff --git a/glibc-rh2024347-3.patch b/glibc-rh2024347-3.patch new file mode 100644 index 0000000..08e30f7 --- /dev/null +++ b/glibc-rh2024347-3.patch @@ -0,0 +1,150 @@ +commit 4fb4e7e821e36180835bf88e363f9f13b5797e3a +Author: Florian Weimer +Date: Sun Dec 5 13:50:17 2021 +0100 + + csu: Always use __executable_start in gmon-start.c + + Current binutils defines __executable_start as the lowest text + address, so using the entry point address as a fallback is no + longer necessary. As a result, overriding is only + necessary if the entry point is not called _start. + + The previous approach to define __ASSEMBLY__ to suppress the + declaration breaks if headers included by are not + compatible with __ASSEMBLY__. This happens with rseq integration + because it is necessary to include kernel headers in more places. + + Reviewed-by: H.J. Lu + +diff --git a/csu/gmon-start.c b/csu/gmon-start.c +index 344606a676c188d4..260c7613e291a32d 100644 +--- a/csu/gmon-start.c ++++ b/csu/gmon-start.c +@@ -38,32 +38,12 @@ + #include + #include + #include +-#define __ASSEMBLY__ +-#include +- +-/* Beginning and end of our code segment. We cannot declare them +- as the external functions since we want the addresses of those +- labels. Taking the address of a function may have different +- meanings on different platforms. */ +-#ifdef ENTRY_POINT_DECL +-ENTRY_POINT_DECL(extern) +-#else +-extern char ENTRY_POINT[]; +-#endif +-extern char etext[]; + + /* Use __executable_start as the lowest address to keep profiling records + if it provided by the linker. */ +-extern const char executable_start[] asm ("__executable_start") +- __attribute__ ((weak, visibility ("hidden"))); ++extern const char __executable_start[] __attribute__ ((visibility ("hidden"))); + +-#ifndef TEXT_START +-# ifdef ENTRY_POINT_DECL +-# define TEXT_START ENTRY_POINT +-# else +-# define TEXT_START &ENTRY_POINT +-# endif +-#endif ++extern char etext[]; + + #if !ELF_INITFINI + /* Instead of defining __gmon_start__ globally in gcrt1.o, we make it +@@ -97,10 +77,7 @@ __gmon_start__ (void) + called = 1; + + /* Start keeping profiling records. */ +- if (&executable_start != NULL) +- __monstartup ((u_long) &executable_start, (u_long) &etext); +- else +- __monstartup ((u_long) TEXT_START, (u_long) &etext); ++ __monstartup ((u_long) &__executable_start, (u_long) &etext); + + /* Call _mcleanup before exiting; it will write out gmon.out from the + collected data. */ +diff --git a/sysdeps/hppa/entry.h b/sysdeps/hppa/entry.h +deleted file mode 100644 +index 5ea5b47448ceb2e7..0000000000000000 +--- a/sysdeps/hppa/entry.h ++++ /dev/null +@@ -1,13 +0,0 @@ +-#ifndef __ASSEMBLY__ +-extern void _start (void); +-#endif +- +-/* Lives in libgcc.so and canonicalizes function pointers for comparison. */ +-extern unsigned int __canonicalize_funcptr_for_compare (unsigned int fptr); +- +-/* The function's entry point is stored in the first word of the +- function descriptor (plabel) of _start(). */ +-#define ENTRY_POINT __canonicalize_funcptr_for_compare((unsigned int)_start) +- +-/* We have to provide a special declaration. */ +-#define ENTRY_POINT_DECL(class) class void _start (void); +diff --git a/sysdeps/ia64/entry.h b/sysdeps/ia64/entry.h +deleted file mode 100644 +index e11b49fc53602eb8..0000000000000000 +--- a/sysdeps/ia64/entry.h ++++ /dev/null +@@ -1,13 +0,0 @@ +-#include +-#include +- +-#ifndef __ASSEMBLY__ +-extern void _start (void); +-#endif +- +-/* The function's entry point is stored in the first word of the +- function descriptor (plabel) of _start(). */ +-#define ENTRY_POINT ELF_PTR_TO_FDESC (_start)->ip +- +-/* We have to provide a special declaration. */ +-#define ENTRY_POINT_DECL(class) class void _start (void); +diff --git a/sysdeps/powerpc/powerpc64/entry.h b/sysdeps/powerpc/powerpc64/entry.h +deleted file mode 100644 +index 99c81cb9820d188d..0000000000000000 +--- a/sysdeps/powerpc/powerpc64/entry.h ++++ /dev/null +@@ -1,37 +0,0 @@ +-/* Finding the entry point and start of text. PowerPC64 version. +- Copyright (C) 2002-2021 Free Software Foundation, Inc. +- This file is part of the GNU C Library. +- +- The GNU C Library is free software; you can redistribute it and/or +- modify it under the terms of the GNU Lesser General Public +- License as published by the Free Software Foundation; either +- version 2.1 of the License, or (at your option) any later version. +- +- The GNU C Library is distributed in the hope that it will be useful, +- but WITHOUT ANY WARRANTY; without even the implied warranty of +- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +- Lesser General Public License for more details. +- +- You should have received a copy of the GNU Lesser General Public +- License along with the GNU C Library; if not, see +- . */ +- +- +-#ifndef __ASSEMBLY__ +-extern void _start (void); +-#endif +- +-#define ENTRY_POINT _start +- +-#if _CALL_ELF != 2 +-/* We have to provide a special declaration. */ +-#define ENTRY_POINT_DECL(class) class void _start (void); +- +-/* Use the address of ._start as the lowest address for which we need +- to keep profiling records. We can't copy the ia64 scheme as our +- entry poiny address is really the address of the function +- descriptor, not the actual function entry. */ +-#define TEXT_START \ +- ({ extern unsigned long int _start_as_data[] asm ("_start"); \ +- _start_as_data[0]; }) +-#endif diff --git a/glibc-rh2024347-4.patch b/glibc-rh2024347-4.patch new file mode 100644 index 0000000..a49f626 --- /dev/null +++ b/glibc-rh2024347-4.patch @@ -0,0 +1,130 @@ +commit 8dbeb0561eeb876f557ac9eef5721912ec074ea5 +Author: Florian Weimer +Date: Thu Dec 9 09:49:32 2021 +0100 + + nptl: Add for defining __thread_pointer + + already contains a definition that is quite similar, + but it is not consistent across architectures. + + Only architectures for which rseq support is added are covered. + + Reviewed-by: Szabolcs Nagy + +diff --git a/sysdeps/nptl/thread_pointer.h b/sysdeps/nptl/thread_pointer.h +new file mode 100644 +index 0000000000000000..92f2f3093eba55bb +--- /dev/null ++++ b/sysdeps/nptl/thread_pointer.h +@@ -0,0 +1,28 @@ ++/* __thread_pointer definition. Generic version. ++ Copyright (C) 2021 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library. If not, see ++ . */ ++ ++#ifndef _SYS_THREAD_POINTER_H ++#define _SYS_THREAD_POINTER_H ++ ++static inline void * ++__thread_pointer (void) ++{ ++ return __builtin_thread_pointer (); ++} ++ ++#endif /* _SYS_THREAD_POINTER_H */ +diff --git a/sysdeps/powerpc/nptl/thread_pointer.h b/sysdeps/powerpc/nptl/thread_pointer.h +new file mode 100644 +index 0000000000000000..8fd5ba671f6f5e64 +--- /dev/null ++++ b/sysdeps/powerpc/nptl/thread_pointer.h +@@ -0,0 +1,33 @@ ++/* __thread_pointer definition. powerpc version. ++ Copyright (C) 2021 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library. If not, see ++ . */ ++ ++#ifndef _SYS_THREAD_POINTER_H ++#define _SYS_THREAD_POINTER_H ++ ++static inline void * ++__thread_pointer (void) ++{ ++#ifdef __powerpc64__ ++ register void *__result asm ("r13"); ++#else ++ register void *__result asm ("r2"); ++#endif ++ return __result; ++} ++ ++#endif /* _SYS_THREAD_POINTER_H */ +diff --git a/sysdeps/x86/nptl/thread_pointer.h b/sysdeps/x86/nptl/thread_pointer.h +new file mode 100644 +index 0000000000000000..6b71b6f7e1401e4c +--- /dev/null ++++ b/sysdeps/x86/nptl/thread_pointer.h +@@ -0,0 +1,38 @@ ++/* __thread_pointer definition. x86 version. ++ Copyright (C) 2021 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library. If not, see ++ . */ ++ ++#ifndef _SYS_THREAD_POINTER_H ++#define _SYS_THREAD_POINTER_H ++ ++static inline void * ++__thread_pointer (void) ++{ ++#if __GNUC_PREREQ (11, 1) ++ return __builtin_thread_pointer (); ++#else ++ void *__result; ++# ifdef __x86_64__ ++ __asm__ ("mov %%fs:0, %0" : "=r" (__result)); ++# else ++ __asm__ ("mov %%gs:0, %0" : "=r" (__result)); ++# endif ++ return __result; ++#endif /* !GCC 11 */ ++} ++ ++#endif /* _SYS_THREAD_POINTER_H */ diff --git a/glibc-rh2024347-5.patch b/glibc-rh2024347-5.patch new file mode 100644 index 0000000..36b1db1 --- /dev/null +++ b/glibc-rh2024347-5.patch @@ -0,0 +1,904 @@ +commit ce2248ab91b2ea09a378f85012f251f31ac65e31 +Author: Florian Weimer +Date: Thu Dec 9 09:49:32 2021 +0100 + + nptl: Introduce for THREAD_* accessors + + These are common between most architectures. Only the x86 targets + are outliers. + + Reviewed-by: Szabolcs Nagy + +diff --git a/sysdeps/aarch64/nptl/tls.h b/sysdeps/aarch64/nptl/tls.h +index 6e896207a659514f..cd9abb5d1d073593 100644 +--- a/sysdeps/aarch64/nptl/tls.h ++++ b/sysdeps/aarch64/nptl/tls.h +@@ -98,15 +98,7 @@ typedef struct + # define DB_THREAD_SELF \ + CONST_THREAD_AREA (64, sizeof (struct pthread)) + +-/* Access to data in the thread descriptor is easy. */ +-# define THREAD_GETMEM(descr, member) \ +- descr->member +-# define THREAD_GETMEM_NC(descr, member, idx) \ +- descr->member[idx] +-# define THREAD_SETMEM(descr, member, value) \ +- descr->member = (value) +-# define THREAD_SETMEM_NC(descr, member, idx, value) \ +- descr->member[idx] = (value) ++# include + + /* Get and set the global scope generation counter in struct pthread. */ + # define THREAD_GSCOPE_IN_TCB 1 +diff --git a/sysdeps/alpha/nptl/tls.h b/sysdeps/alpha/nptl/tls.h +index 4dbccc5249539325..5f4843b28e7f1ad1 100644 +--- a/sysdeps/alpha/nptl/tls.h ++++ b/sysdeps/alpha/nptl/tls.h +@@ -92,15 +92,7 @@ typedef struct + # define DB_THREAD_SELF \ + REGISTER (64, 64, 32 * 8, -sizeof (struct pthread)) + +-/* Access to data in the thread descriptor is easy. */ +-#define THREAD_GETMEM(descr, member) \ +- descr->member +-#define THREAD_GETMEM_NC(descr, member, idx) \ +- descr->member[idx] +-#define THREAD_SETMEM(descr, member, value) \ +- descr->member = (value) +-#define THREAD_SETMEM_NC(descr, member, idx, value) \ +- descr->member[idx] = (value) ++# include + + /* Get and set the global scope generation counter in struct pthread. */ + #define THREAD_GSCOPE_IN_TCB 1 +diff --git a/sysdeps/arc/nptl/tls.h b/sysdeps/arc/nptl/tls.h +index 95300fdd2159dc53..d9ada2f38089e6cd 100644 +--- a/sysdeps/arc/nptl/tls.h ++++ b/sysdeps/arc/nptl/tls.h +@@ -100,15 +100,7 @@ typedef struct + # define DB_THREAD_SELF \ + CONST_THREAD_AREA (32, sizeof (struct pthread)) + +-/* Access to data in the thread descriptor is easy. */ +-# define THREAD_GETMEM(descr, member) \ +- descr->member +-# define THREAD_GETMEM_NC(descr, member, idx) \ +- descr->member[idx] +-# define THREAD_SETMEM(descr, member, value) \ +- descr->member = (value) +-# define THREAD_SETMEM_NC(descr, member, idx, value) \ +- descr->member[idx] = (value) ++# include + + /* Get and set the global scope generation counter in struct pthread. */ + #define THREAD_GSCOPE_IN_TCB 1 +diff --git a/sysdeps/arm/nptl/tls.h b/sysdeps/arm/nptl/tls.h +index 1bd11307ce0a7f0a..354aae3318291395 100644 +--- a/sysdeps/arm/nptl/tls.h ++++ b/sysdeps/arm/nptl/tls.h +@@ -89,15 +89,7 @@ typedef struct + # define DB_THREAD_SELF \ + CONST_THREAD_AREA (32, sizeof (struct pthread)) + +-/* Access to data in the thread descriptor is easy. */ +-#define THREAD_GETMEM(descr, member) \ +- descr->member +-#define THREAD_GETMEM_NC(descr, member, idx) \ +- descr->member[idx] +-#define THREAD_SETMEM(descr, member, value) \ +- descr->member = (value) +-#define THREAD_SETMEM_NC(descr, member, idx, value) \ +- descr->member[idx] = (value) ++# include + + /* Get and set the global scope generation counter in struct pthread. */ + #define THREAD_GSCOPE_IN_TCB 1 +diff --git a/sysdeps/csky/nptl/tls.h b/sysdeps/csky/nptl/tls.h +index 7a234041ed0bff39..f3fa3fcb02748776 100644 +--- a/sysdeps/csky/nptl/tls.h ++++ b/sysdeps/csky/nptl/tls.h +@@ -116,15 +116,7 @@ typedef struct + # define DB_THREAD_SELF \ + CONST_THREAD_AREA (32, sizeof (struct pthread)) + +-/* Access to data in the thread descriptor is easy. */ +-# define THREAD_GETMEM(descr, member) \ +- descr->member +-# define THREAD_GETMEM_NC(descr, member, idx) \ +- descr->member[idx] +-# define THREAD_SETMEM(descr, member, value) \ +- descr->member = (value) +-# define THREAD_SETMEM_NC(descr, member, idx, value) \ +- descr->member[idx] = (value) ++# include + + /* Get and set the global scope generation counter in struct pthread. */ + # define THREAD_GSCOPE_IN_TCB 1 +diff --git a/sysdeps/hppa/nptl/tls.h b/sysdeps/hppa/nptl/tls.h +index 857003a7d35073eb..f0e274c45fb5e91e 100644 +--- a/sysdeps/hppa/nptl/tls.h ++++ b/sysdeps/hppa/nptl/tls.h +@@ -107,15 +107,7 @@ typedef struct + # define DB_THREAD_SELF \ + REGISTER (32, 32, 53 * 4, -sizeof (struct pthread)) + +-/* Access to data in the thread descriptor is easy. */ +-# define THREAD_GETMEM(descr, member) \ +- descr->member +-# define THREAD_GETMEM_NC(descr, member, idx) \ +- descr->member[idx] +-# define THREAD_SETMEM(descr, member, value) \ +- descr->member = (value) +-# define THREAD_SETMEM_NC(descr, member, idx, value) \ +- descr->member[idx] = (value) ++# include + + static inline struct pthread *__get_cr27(void) + { +diff --git a/sysdeps/i386/nptl/tcb-access.h b/sysdeps/i386/nptl/tcb-access.h +new file mode 100644 +index 0000000000000000..6c6d561e394817c7 +--- /dev/null ++++ b/sysdeps/i386/nptl/tcb-access.h +@@ -0,0 +1,123 @@ ++/* THREAD_* accessors. i386 version. ++ Copyright (C) 2002-2021 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++/* Read member of the thread descriptor directly. */ ++#define THREAD_GETMEM(descr, member) \ ++ ({ __typeof (descr->member) __value; \ ++ _Static_assert (sizeof (__value) == 1 \ ++ || sizeof (__value) == 4 \ ++ || sizeof (__value) == 8, \ ++ "size of per-thread data"); \ ++ if (sizeof (__value) == 1) \ ++ asm volatile ("movb %%gs:%P2,%b0" \ ++ : "=q" (__value) \ ++ : "0" (0), "i" (offsetof (struct pthread, member))); \ ++ else if (sizeof (__value) == 4) \ ++ asm volatile ("movl %%gs:%P1,%0" \ ++ : "=r" (__value) \ ++ : "i" (offsetof (struct pthread, member))); \ ++ else /* 8 */ \ ++ { \ ++ asm volatile ("movl %%gs:%P1,%%eax\n\t" \ ++ "movl %%gs:%P2,%%edx" \ ++ : "=A" (__value) \ ++ : "i" (offsetof (struct pthread, member)), \ ++ "i" (offsetof (struct pthread, member) + 4)); \ ++ } \ ++ __value; }) ++ ++ ++/* Same as THREAD_GETMEM, but the member offset can be non-constant. */ ++#define THREAD_GETMEM_NC(descr, member, idx) \ ++ ({ __typeof (descr->member[0]) __value; \ ++ _Static_assert (sizeof (__value) == 1 \ ++ || sizeof (__value) == 4 \ ++ || sizeof (__value) == 8, \ ++ "size of per-thread data"); \ ++ if (sizeof (__value) == 1) \ ++ asm volatile ("movb %%gs:%P2(%3),%b0" \ ++ : "=q" (__value) \ ++ : "0" (0), "i" (offsetof (struct pthread, member[0])), \ ++ "r" (idx)); \ ++ else if (sizeof (__value) == 4) \ ++ asm volatile ("movl %%gs:%P1(,%2,4),%0" \ ++ : "=r" (__value) \ ++ : "i" (offsetof (struct pthread, member[0])), \ ++ "r" (idx)); \ ++ else /* 8 */ \ ++ { \ ++ asm volatile ("movl %%gs:%P1(,%2,8),%%eax\n\t" \ ++ "movl %%gs:4+%P1(,%2,8),%%edx" \ ++ : "=&A" (__value) \ ++ : "i" (offsetof (struct pthread, member[0])), \ ++ "r" (idx)); \ ++ } \ ++ __value; }) ++ ++ ++ ++/* Set member of the thread descriptor directly. */ ++#define THREAD_SETMEM(descr, member, value) \ ++ ({ \ ++ _Static_assert (sizeof (descr->member) == 1 \ ++ || sizeof (descr->member) == 4 \ ++ || sizeof (descr->member) == 8, \ ++ "size of per-thread data"); \ ++ if (sizeof (descr->member) == 1) \ ++ asm volatile ("movb %b0,%%gs:%P1" : \ ++ : "iq" (value), \ ++ "i" (offsetof (struct pthread, member))); \ ++ else if (sizeof (descr->member) == 4) \ ++ asm volatile ("movl %0,%%gs:%P1" : \ ++ : "ir" (value), \ ++ "i" (offsetof (struct pthread, member))); \ ++ else /* 8 */ \ ++ { \ ++ asm volatile ("movl %%eax,%%gs:%P1\n\t" \ ++ "movl %%edx,%%gs:%P2" : \ ++ : "A" ((uint64_t) cast_to_integer (value)), \ ++ "i" (offsetof (struct pthread, member)), \ ++ "i" (offsetof (struct pthread, member) + 4)); \ ++ }}) ++ ++ ++/* Same as THREAD_SETMEM, but the member offset can be non-constant. */ ++#define THREAD_SETMEM_NC(descr, member, idx, value) \ ++ ({ \ ++ _Static_assert (sizeof (descr->member[0]) == 1 \ ++ || sizeof (descr->member[0]) == 4 \ ++ || sizeof (descr->member[0]) == 8, \ ++ "size of per-thread data"); \ ++ if (sizeof (descr->member[0]) == 1) \ ++ asm volatile ("movb %b0,%%gs:%P1(%2)" : \ ++ : "iq" (value), \ ++ "i" (offsetof (struct pthread, member)), \ ++ "r" (idx)); \ ++ else if (sizeof (descr->member[0]) == 4) \ ++ asm volatile ("movl %0,%%gs:%P1(,%2,4)" : \ ++ : "ir" (value), \ ++ "i" (offsetof (struct pthread, member)), \ ++ "r" (idx)); \ ++ else /* 8 */ \ ++ { \ ++ asm volatile ("movl %%eax,%%gs:%P1(,%2,8)\n\t" \ ++ "movl %%edx,%%gs:4+%P1(,%2,8)" : \ ++ : "A" ((uint64_t) cast_to_integer (value)), \ ++ "i" (offsetof (struct pthread, member)), \ ++ "r" (idx)); \ ++ }}) +diff --git a/sysdeps/i386/nptl/tls.h b/sysdeps/i386/nptl/tls.h +index 86ee1ef30270f960..111c9ee59df30bc3 100644 +--- a/sysdeps/i386/nptl/tls.h ++++ b/sysdeps/i386/nptl/tls.h +@@ -250,113 +250,7 @@ tls_fill_user_desc (union user_desc_init *desc, + REGISTER_THREAD_AREA (32, offsetof (struct user_regs_struct, xgs), 3) \ + REGISTER_THREAD_AREA (64, 26 * 8, 3) /* x86-64's user_regs_struct->gs */ + +- +-/* Read member of the thread descriptor directly. */ +-# define THREAD_GETMEM(descr, member) \ +- ({ __typeof (descr->member) __value; \ +- _Static_assert (sizeof (__value) == 1 \ +- || sizeof (__value) == 4 \ +- || sizeof (__value) == 8, \ +- "size of per-thread data"); \ +- if (sizeof (__value) == 1) \ +- asm volatile ("movb %%gs:%P2,%b0" \ +- : "=q" (__value) \ +- : "0" (0), "i" (offsetof (struct pthread, member))); \ +- else if (sizeof (__value) == 4) \ +- asm volatile ("movl %%gs:%P1,%0" \ +- : "=r" (__value) \ +- : "i" (offsetof (struct pthread, member))); \ +- else /* 8 */ \ +- { \ +- asm volatile ("movl %%gs:%P1,%%eax\n\t" \ +- "movl %%gs:%P2,%%edx" \ +- : "=A" (__value) \ +- : "i" (offsetof (struct pthread, member)), \ +- "i" (offsetof (struct pthread, member) + 4)); \ +- } \ +- __value; }) +- +- +-/* Same as THREAD_GETMEM, but the member offset can be non-constant. */ +-# define THREAD_GETMEM_NC(descr, member, idx) \ +- ({ __typeof (descr->member[0]) __value; \ +- _Static_assert (sizeof (__value) == 1 \ +- || sizeof (__value) == 4 \ +- || sizeof (__value) == 8, \ +- "size of per-thread data"); \ +- if (sizeof (__value) == 1) \ +- asm volatile ("movb %%gs:%P2(%3),%b0" \ +- : "=q" (__value) \ +- : "0" (0), "i" (offsetof (struct pthread, member[0])), \ +- "r" (idx)); \ +- else if (sizeof (__value) == 4) \ +- asm volatile ("movl %%gs:%P1(,%2,4),%0" \ +- : "=r" (__value) \ +- : "i" (offsetof (struct pthread, member[0])), \ +- "r" (idx)); \ +- else /* 8 */ \ +- { \ +- asm volatile ("movl %%gs:%P1(,%2,8),%%eax\n\t" \ +- "movl %%gs:4+%P1(,%2,8),%%edx" \ +- : "=&A" (__value) \ +- : "i" (offsetof (struct pthread, member[0])), \ +- "r" (idx)); \ +- } \ +- __value; }) +- +- +- +-/* Set member of the thread descriptor directly. */ +-# define THREAD_SETMEM(descr, member, value) \ +- ({ \ +- _Static_assert (sizeof (descr->member) == 1 \ +- || sizeof (descr->member) == 4 \ +- || sizeof (descr->member) == 8, \ +- "size of per-thread data"); \ +- if (sizeof (descr->member) == 1) \ +- asm volatile ("movb %b0,%%gs:%P1" : \ +- : "iq" (value), \ +- "i" (offsetof (struct pthread, member))); \ +- else if (sizeof (descr->member) == 4) \ +- asm volatile ("movl %0,%%gs:%P1" : \ +- : "ir" (value), \ +- "i" (offsetof (struct pthread, member))); \ +- else /* 8 */ \ +- { \ +- asm volatile ("movl %%eax,%%gs:%P1\n\t" \ +- "movl %%edx,%%gs:%P2" : \ +- : "A" ((uint64_t) cast_to_integer (value)), \ +- "i" (offsetof (struct pthread, member)), \ +- "i" (offsetof (struct pthread, member) + 4)); \ +- }}) +- +- +-/* Same as THREAD_SETMEM, but the member offset can be non-constant. */ +-# define THREAD_SETMEM_NC(descr, member, idx, value) \ +- ({ \ +- _Static_assert (sizeof (descr->member[0]) == 1 \ +- || sizeof (descr->member[0]) == 4 \ +- || sizeof (descr->member[0]) == 8, \ +- "size of per-thread data"); \ +- if (sizeof (descr->member[0]) == 1) \ +- asm volatile ("movb %b0,%%gs:%P1(%2)" : \ +- : "iq" (value), \ +- "i" (offsetof (struct pthread, member)), \ +- "r" (idx)); \ +- else if (sizeof (descr->member[0]) == 4) \ +- asm volatile ("movl %0,%%gs:%P1(,%2,4)" : \ +- : "ir" (value), \ +- "i" (offsetof (struct pthread, member)), \ +- "r" (idx)); \ +- else /* 8 */ \ +- { \ +- asm volatile ("movl %%eax,%%gs:%P1(,%2,8)\n\t" \ +- "movl %%edx,%%gs:4+%P1(,%2,8)" : \ +- : "A" ((uint64_t) cast_to_integer (value)), \ +- "i" (offsetof (struct pthread, member)), \ +- "r" (idx)); \ +- }}) +- ++# include + + /* Set the stack guard field in TCB head. */ + #define THREAD_SET_STACK_GUARD(value) \ +diff --git a/sysdeps/ia64/nptl/tls.h b/sysdeps/ia64/nptl/tls.h +index 66d9bf3189f0b727..26fe555cb4b5e164 100644 +--- a/sysdeps/ia64/nptl/tls.h ++++ b/sysdeps/ia64/nptl/tls.h +@@ -128,15 +128,7 @@ register struct pthread *__thread_self __asm__("r13"); + /* Magic for libthread_db to know how to do THREAD_SELF. */ + # define DB_THREAD_SELF REGISTER (64, 64, 13 * 8, -TLS_PRE_TCB_SIZE) + +-/* Access to data in the thread descriptor is easy. */ +-#define THREAD_GETMEM(descr, member) \ +- descr->member +-#define THREAD_GETMEM_NC(descr, member, idx) \ +- descr->member[idx] +-#define THREAD_SETMEM(descr, member, value) \ +- descr->member = (value) +-#define THREAD_SETMEM_NC(descr, member, idx, value) \ +- descr->member[idx] = (value) ++# include + + /* Set the stack guard field in TCB head. */ + #define THREAD_SET_STACK_GUARD(value) \ +diff --git a/sysdeps/m68k/nptl/tls.h b/sysdeps/m68k/nptl/tls.h +index cfcd6d2b7b59321c..9f562c38288df200 100644 +--- a/sysdeps/m68k/nptl/tls.h ++++ b/sysdeps/m68k/nptl/tls.h +@@ -118,15 +118,7 @@ extern void * __m68k_read_tp (void); + # define DB_THREAD_SELF \ + CONST_THREAD_AREA (32, TLS_TCB_OFFSET + TLS_PRE_TCB_SIZE) + +-/* Access to data in the thread descriptor is easy. */ +-# define THREAD_GETMEM(descr, member) \ +- descr->member +-# define THREAD_GETMEM_NC(descr, member, idx) \ +- descr->member[idx] +-# define THREAD_SETMEM(descr, member, value) \ +- descr->member = (value) +-# define THREAD_SETMEM_NC(descr, member, idx, value) \ +- descr->member[idx] = (value) ++# include + + /* l_tls_offset == 0 is perfectly valid on M68K, so we have to use some + different value to mean unset l_tls_offset. */ +diff --git a/sysdeps/microblaze/nptl/tls.h b/sysdeps/microblaze/nptl/tls.h +index c93d90b11bfe4c74..bfa6efa78049bb2d 100644 +--- a/sysdeps/microblaze/nptl/tls.h ++++ b/sysdeps/microblaze/nptl/tls.h +@@ -100,20 +100,7 @@ typedef struct + # define DB_THREAD_SELF \ + CONST_THREAD_AREA (32, sizeof (struct pthread)) + +-/* Read member of the thread descriptor directly. */ +-# define THREAD_GETMEM(descr, member) (descr->member) +- +-/* Same as THREAD_GETMEM, but the member offset can be non-constant. */ +-# define THREAD_GETMEM_NC(descr, member, idx) \ +- (descr->member[idx]) +- +-/* Set member of the thread descriptor directly. */ +-# define THREAD_SETMEM(descr, member, value) \ +- (descr->member = (value)) +- +-/* Same as THREAD_SETMEM, but the member offset can be non-constant. */ +-# define THREAD_SETMEM_NC(descr, member, idx, value) \ +- (descr->member[idx] = (value)) ++# include + + /* Get and set the global scope generation counter in struct pthread. */ + # define THREAD_GSCOPE_IN_TCB 1 +diff --git a/sysdeps/mips/nptl/tls.h b/sysdeps/mips/nptl/tls.h +index c09f49071cf3b5b9..ef99aa646c898e76 100644 +--- a/sysdeps/mips/nptl/tls.h ++++ b/sysdeps/mips/nptl/tls.h +@@ -144,14 +144,7 @@ typedef struct + CONST_THREAD_AREA (32, TLS_TCB_OFFSET + TLS_PRE_TCB_SIZE) + + /* Access to data in the thread descriptor is easy. */ +-# define THREAD_GETMEM(descr, member) \ +- descr->member +-# define THREAD_GETMEM_NC(descr, member, idx) \ +- descr->member[idx] +-# define THREAD_SETMEM(descr, member, value) \ +- descr->member = (value) +-# define THREAD_SETMEM_NC(descr, member, idx, value) \ +- descr->member[idx] = (value) ++# include + + /* l_tls_offset == 0 is perfectly valid on MIPS, so we have to use some + different value to mean unset l_tls_offset. */ +diff --git a/sysdeps/nios2/nptl/tls.h b/sysdeps/nios2/nptl/tls.h +index 02a05b4e741092bf..7110cfccad7131f4 100644 +--- a/sysdeps/nios2/nptl/tls.h ++++ b/sysdeps/nios2/nptl/tls.h +@@ -112,15 +112,7 @@ register struct pthread *__thread_self __asm__("r23"); + # define DB_THREAD_SELF \ + REGISTER (32, 32, 23 * 4, -TLS_PRE_TCB_SIZE - TLS_TCB_OFFSET) + +-/* Access to data in the thread descriptor is easy. */ +-# define THREAD_GETMEM(descr, member) \ +- descr->member +-# define THREAD_GETMEM_NC(descr, member, idx) \ +- descr->member[idx] +-# define THREAD_SETMEM(descr, member, value) \ +- descr->member = (value) +-# define THREAD_SETMEM_NC(descr, member, idx, value) \ +- descr->member[idx] = (value) ++# include + + # define THREAD_GET_POINTER_GUARD() \ + (((tcbhead_t *) (READ_THREAD_POINTER () \ +diff --git a/sysdeps/nptl/tcb-access.h b/sysdeps/nptl/tcb-access.h +new file mode 100644 +index 0000000000000000..b4137b8ab8067915 +--- /dev/null ++++ b/sysdeps/nptl/tcb-access.h +@@ -0,0 +1,30 @@ ++/* THREAD_* accessors. Generic version based on struct pthread pointers. ++ Copyright (C) 2002-2021 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++/* Note: These are for accessing the TCB of the *current* thread. ++ descr can be disregarded on some targets as an optimization. See ++ i386 for an example. */ ++ ++#define THREAD_GETMEM(descr, member) \ ++ descr->member ++#define THREAD_GETMEM_NC(descr, member, idx) \ ++ descr->member[idx] ++#define THREAD_SETMEM(descr, member, value) \ ++ descr->member = (value) ++#define THREAD_SETMEM_NC(descr, member, idx, value) \ ++ descr->member[idx] = (value) +diff --git a/sysdeps/powerpc/nptl/tls.h b/sysdeps/powerpc/nptl/tls.h +index 6c779b6609147d54..110d085d30c86302 100644 +--- a/sysdeps/powerpc/nptl/tls.h ++++ b/sysdeps/powerpc/nptl/tls.h +@@ -176,20 +176,7 @@ typedef struct + REGISTER (64, 64, PT_THREAD_POINTER * 8, \ + - TLS_TCB_OFFSET - TLS_PRE_TCB_SIZE) + +-/* Read member of the thread descriptor directly. */ +-# define THREAD_GETMEM(descr, member) ((void)(descr), (THREAD_SELF)->member) +- +-/* Same as THREAD_GETMEM, but the member offset can be non-constant. */ +-# define THREAD_GETMEM_NC(descr, member, idx) \ +- ((void)(descr), (THREAD_SELF)->member[idx]) +- +-/* Set member of the thread descriptor directly. */ +-# define THREAD_SETMEM(descr, member, value) \ +- ((void)(descr), (THREAD_SELF)->member = (value)) +- +-/* Same as THREAD_SETMEM, but the member offset can be non-constant. */ +-# define THREAD_SETMEM_NC(descr, member, idx, value) \ +- ((void)(descr), (THREAD_SELF)->member[idx] = (value)) ++# include + + /* Set the stack guard field in TCB head. */ + # define THREAD_SET_STACK_GUARD(value) \ +diff --git a/sysdeps/riscv/nptl/tls.h b/sysdeps/riscv/nptl/tls.h +index 5350bcc0498bab69..bdc0a3a6f91b51e8 100644 +--- a/sysdeps/riscv/nptl/tls.h ++++ b/sysdeps/riscv/nptl/tls.h +@@ -105,14 +105,7 @@ typedef struct + REGISTER (64, 64, 4 * 8, - TLS_TCB_OFFSET - TLS_PRE_TCB_SIZE) + + /* Access to data in the thread descriptor is easy. */ +-# define THREAD_GETMEM(descr, member) \ +- descr->member +-# define THREAD_GETMEM_NC(descr, member, idx) \ +- descr->member[idx] +-# define THREAD_SETMEM(descr, member, value) \ +- descr->member = (value) +-# define THREAD_SETMEM_NC(descr, member, idx, value) \ +- descr->member[idx] = (value) ++# include + + /* l_tls_offset == 0 is perfectly valid, so we have to use some different + value to mean unset l_tls_offset. */ +diff --git a/sysdeps/s390/nptl/tls.h b/sysdeps/s390/nptl/tls.h +index efb52515e05c06a9..2cdd18eb2907c060 100644 +--- a/sysdeps/s390/nptl/tls.h ++++ b/sysdeps/s390/nptl/tls.h +@@ -135,15 +135,7 @@ typedef struct + # define DB_THREAD_SELF REGISTER (32, 32, 18 * 4, 0) \ + REGISTER (64, __WORDSIZE, 18 * 8, 0) + +-/* Access to data in the thread descriptor is easy. */ +-#define THREAD_GETMEM(descr, member) \ +- descr->member +-#define THREAD_GETMEM_NC(descr, member, idx) \ +- descr->member[idx] +-#define THREAD_SETMEM(descr, member, value) \ +- descr->member = (value) +-#define THREAD_SETMEM_NC(descr, member, idx, value) \ +- descr->member[idx] = (value) ++# include + + /* Set the stack guard field in TCB head. */ + #define THREAD_SET_STACK_GUARD(value) \ +diff --git a/sysdeps/sh/nptl/tls.h b/sysdeps/sh/nptl/tls.h +index ac3c9a9e856ee686..390640020e45f716 100644 +--- a/sysdeps/sh/nptl/tls.h ++++ b/sysdeps/sh/nptl/tls.h +@@ -113,19 +113,7 @@ typedef struct + # define DB_THREAD_SELF \ + REGISTER (32, 32, REG_GBR * 4, -sizeof (struct pthread)) + +-/* Read member of the thread descriptor directly. */ +-# define THREAD_GETMEM(descr, member) (descr->member) +- +-/* Same as THREAD_GETMEM, but the member offset can be non-constant. */ +-# define THREAD_GETMEM_NC(descr, member, idx) (descr->member[idx]) +- +-/* Set member of the thread descriptor directly. */ +-# define THREAD_SETMEM(descr, member, value) \ +- descr->member = (value) +- +-/* Same as THREAD_SETMEM, but the member offset can be non-constant. */ +-# define THREAD_SETMEM_NC(descr, member, idx, value) \ +- descr->member[idx] = (value) ++# include + + #define THREAD_GET_POINTER_GUARD() \ + ({ tcbhead_t *__tcbp; \ +diff --git a/sysdeps/sparc/nptl/tls.h b/sysdeps/sparc/nptl/tls.h +index dd1eb82a595619a9..376d729989e35660 100644 +--- a/sysdeps/sparc/nptl/tls.h ++++ b/sysdeps/sparc/nptl/tls.h +@@ -112,15 +112,7 @@ register struct pthread *__thread_self __asm__("%g7"); + REGISTER (32, 32, 10 * 4, 0) \ + REGISTER (64, __WORDSIZE, (6 * 8) + (__WORDSIZE==64?0:4), 0) + +-/* Access to data in the thread descriptor is easy. */ +-#define THREAD_GETMEM(descr, member) \ +- descr->member +-#define THREAD_GETMEM_NC(descr, member, idx) \ +- descr->member[idx] +-#define THREAD_SETMEM(descr, member, value) \ +- descr->member = (value) +-#define THREAD_SETMEM_NC(descr, member, idx, value) \ +- descr->member[idx] = (value) ++# include + + /* Set the stack guard field in TCB head. */ + #define THREAD_SET_STACK_GUARD(value) \ +diff --git a/sysdeps/x86_64/nptl/tcb-access.h b/sysdeps/x86_64/nptl/tcb-access.h +new file mode 100644 +index 0000000000000000..18848a729d16a4f5 +--- /dev/null ++++ b/sysdeps/x86_64/nptl/tcb-access.h +@@ -0,0 +1,130 @@ ++/* THREAD_* accessors. x86_64 version. ++ Copyright (C) 2002-2021 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++/* Read member of the thread descriptor directly. */ ++# define THREAD_GETMEM(descr, member) \ ++ ({ __typeof (descr->member) __value; \ ++ _Static_assert (sizeof (__value) == 1 \ ++ || sizeof (__value) == 4 \ ++ || sizeof (__value) == 8, \ ++ "size of per-thread data"); \ ++ if (sizeof (__value) == 1) \ ++ asm volatile ("movb %%fs:%P2,%b0" \ ++ : "=q" (__value) \ ++ : "0" (0), "i" (offsetof (struct pthread, member))); \ ++ else if (sizeof (__value) == 4) \ ++ asm volatile ("movl %%fs:%P1,%0" \ ++ : "=r" (__value) \ ++ : "i" (offsetof (struct pthread, member))); \ ++ else /* 8 */ \ ++ { \ ++ asm volatile ("movq %%fs:%P1,%q0" \ ++ : "=r" (__value) \ ++ : "i" (offsetof (struct pthread, member))); \ ++ } \ ++ __value; }) ++ ++ ++/* Same as THREAD_GETMEM, but the member offset can be non-constant. */ ++# define THREAD_GETMEM_NC(descr, member, idx) \ ++ ({ __typeof (descr->member[0]) __value; \ ++ _Static_assert (sizeof (__value) == 1 \ ++ || sizeof (__value) == 4 \ ++ || sizeof (__value) == 8, \ ++ "size of per-thread data"); \ ++ if (sizeof (__value) == 1) \ ++ asm volatile ("movb %%fs:%P2(%q3),%b0" \ ++ : "=q" (__value) \ ++ : "0" (0), "i" (offsetof (struct pthread, member[0])), \ ++ "r" (idx)); \ ++ else if (sizeof (__value) == 4) \ ++ asm volatile ("movl %%fs:%P1(,%q2,4),%0" \ ++ : "=r" (__value) \ ++ : "i" (offsetof (struct pthread, member[0])), "r" (idx));\ ++ else /* 8 */ \ ++ { \ ++ asm volatile ("movq %%fs:%P1(,%q2,8),%q0" \ ++ : "=r" (__value) \ ++ : "i" (offsetof (struct pthread, member[0])), \ ++ "r" (idx)); \ ++ } \ ++ __value; }) ++ ++ ++/* Loading addresses of objects on x86-64 needs to be treated special ++ when generating PIC code. */ ++#ifdef __pic__ ++# define IMM_MODE "nr" ++#else ++# define IMM_MODE "ir" ++#endif ++ ++ ++/* Set member of the thread descriptor directly. */ ++# define THREAD_SETMEM(descr, member, value) \ ++ ({ \ ++ _Static_assert (sizeof (descr->member) == 1 \ ++ || sizeof (descr->member) == 4 \ ++ || sizeof (descr->member) == 8, \ ++ "size of per-thread data"); \ ++ if (sizeof (descr->member) == 1) \ ++ asm volatile ("movb %b0,%%fs:%P1" : \ ++ : "iq" (value), \ ++ "i" (offsetof (struct pthread, member))); \ ++ else if (sizeof (descr->member) == 4) \ ++ asm volatile ("movl %0,%%fs:%P1" : \ ++ : IMM_MODE (value), \ ++ "i" (offsetof (struct pthread, member))); \ ++ else /* 8 */ \ ++ { \ ++ /* Since movq takes a signed 32-bit immediate or a register source \ ++ operand, use "er" constraint for 32-bit signed integer constant \ ++ or register. */ \ ++ asm volatile ("movq %q0,%%fs:%P1" : \ ++ : "er" ((uint64_t) cast_to_integer (value)), \ ++ "i" (offsetof (struct pthread, member))); \ ++ }}) ++ ++ ++/* Same as THREAD_SETMEM, but the member offset can be non-constant. */ ++# define THREAD_SETMEM_NC(descr, member, idx, value) \ ++ ({ \ ++ _Static_assert (sizeof (descr->member[0]) == 1 \ ++ || sizeof (descr->member[0]) == 4 \ ++ || sizeof (descr->member[0]) == 8, \ ++ "size of per-thread data"); \ ++ if (sizeof (descr->member[0]) == 1) \ ++ asm volatile ("movb %b0,%%fs:%P1(%q2)" : \ ++ : "iq" (value), \ ++ "i" (offsetof (struct pthread, member[0])), \ ++ "r" (idx)); \ ++ else if (sizeof (descr->member[0]) == 4) \ ++ asm volatile ("movl %0,%%fs:%P1(,%q2,4)" : \ ++ : IMM_MODE (value), \ ++ "i" (offsetof (struct pthread, member[0])), \ ++ "r" (idx)); \ ++ else /* 8 */ \ ++ { \ ++ /* Since movq takes a signed 32-bit immediate or a register source \ ++ operand, use "er" constraint for 32-bit signed integer constant \ ++ or register. */ \ ++ asm volatile ("movq %q0,%%fs:%P1(,%q2,8)" : \ ++ : "er" ((uint64_t) cast_to_integer (value)), \ ++ "i" (offsetof (struct pthread, member[0])), \ ++ "r" (idx)); \ ++ }}) +diff --git a/sysdeps/x86_64/nptl/tls.h b/sysdeps/x86_64/nptl/tls.h +index a78c4f4d016002fa..3af1836e28b26fdb 100644 +--- a/sysdeps/x86_64/nptl/tls.h ++++ b/sysdeps/x86_64/nptl/tls.h +@@ -195,119 +195,7 @@ _Static_assert (offsetof (tcbhead_t, __glibc_unused2) == 0x80, + # define DB_THREAD_SELF_INCLUDE /* For the FS constant. */ + # define DB_THREAD_SELF CONST_THREAD_AREA (64, FS) + +-/* Read member of the thread descriptor directly. */ +-# define THREAD_GETMEM(descr, member) \ +- ({ __typeof (descr->member) __value; \ +- _Static_assert (sizeof (__value) == 1 \ +- || sizeof (__value) == 4 \ +- || sizeof (__value) == 8, \ +- "size of per-thread data"); \ +- if (sizeof (__value) == 1) \ +- asm volatile ("movb %%fs:%P2,%b0" \ +- : "=q" (__value) \ +- : "0" (0), "i" (offsetof (struct pthread, member))); \ +- else if (sizeof (__value) == 4) \ +- asm volatile ("movl %%fs:%P1,%0" \ +- : "=r" (__value) \ +- : "i" (offsetof (struct pthread, member))); \ +- else /* 8 */ \ +- { \ +- asm volatile ("movq %%fs:%P1,%q0" \ +- : "=r" (__value) \ +- : "i" (offsetof (struct pthread, member))); \ +- } \ +- __value; }) +- +- +-/* Same as THREAD_GETMEM, but the member offset can be non-constant. */ +-# define THREAD_GETMEM_NC(descr, member, idx) \ +- ({ __typeof (descr->member[0]) __value; \ +- _Static_assert (sizeof (__value) == 1 \ +- || sizeof (__value) == 4 \ +- || sizeof (__value) == 8, \ +- "size of per-thread data"); \ +- if (sizeof (__value) == 1) \ +- asm volatile ("movb %%fs:%P2(%q3),%b0" \ +- : "=q" (__value) \ +- : "0" (0), "i" (offsetof (struct pthread, member[0])), \ +- "r" (idx)); \ +- else if (sizeof (__value) == 4) \ +- asm volatile ("movl %%fs:%P1(,%q2,4),%0" \ +- : "=r" (__value) \ +- : "i" (offsetof (struct pthread, member[0])), "r" (idx));\ +- else /* 8 */ \ +- { \ +- asm volatile ("movq %%fs:%P1(,%q2,8),%q0" \ +- : "=r" (__value) \ +- : "i" (offsetof (struct pthread, member[0])), \ +- "r" (idx)); \ +- } \ +- __value; }) +- +- +-/* Loading addresses of objects on x86-64 needs to be treated special +- when generating PIC code. */ +-#ifdef __pic__ +-# define IMM_MODE "nr" +-#else +-# define IMM_MODE "ir" +-#endif +- +- +-/* Set member of the thread descriptor directly. */ +-# define THREAD_SETMEM(descr, member, value) \ +- ({ \ +- _Static_assert (sizeof (descr->member) == 1 \ +- || sizeof (descr->member) == 4 \ +- || sizeof (descr->member) == 8, \ +- "size of per-thread data"); \ +- if (sizeof (descr->member) == 1) \ +- asm volatile ("movb %b0,%%fs:%P1" : \ +- : "iq" (value), \ +- "i" (offsetof (struct pthread, member))); \ +- else if (sizeof (descr->member) == 4) \ +- asm volatile ("movl %0,%%fs:%P1" : \ +- : IMM_MODE (value), \ +- "i" (offsetof (struct pthread, member))); \ +- else /* 8 */ \ +- { \ +- /* Since movq takes a signed 32-bit immediate or a register source \ +- operand, use "er" constraint for 32-bit signed integer constant \ +- or register. */ \ +- asm volatile ("movq %q0,%%fs:%P1" : \ +- : "er" ((uint64_t) cast_to_integer (value)), \ +- "i" (offsetof (struct pthread, member))); \ +- }}) +- +- +-/* Same as THREAD_SETMEM, but the member offset can be non-constant. */ +-# define THREAD_SETMEM_NC(descr, member, idx, value) \ +- ({ \ +- _Static_assert (sizeof (descr->member[0]) == 1 \ +- || sizeof (descr->member[0]) == 4 \ +- || sizeof (descr->member[0]) == 8, \ +- "size of per-thread data"); \ +- if (sizeof (descr->member[0]) == 1) \ +- asm volatile ("movb %b0,%%fs:%P1(%q2)" : \ +- : "iq" (value), \ +- "i" (offsetof (struct pthread, member[0])), \ +- "r" (idx)); \ +- else if (sizeof (descr->member[0]) == 4) \ +- asm volatile ("movl %0,%%fs:%P1(,%q2,4)" : \ +- : IMM_MODE (value), \ +- "i" (offsetof (struct pthread, member[0])), \ +- "r" (idx)); \ +- else /* 8 */ \ +- { \ +- /* Since movq takes a signed 32-bit immediate or a register source \ +- operand, use "er" constraint for 32-bit signed integer constant \ +- or register. */ \ +- asm volatile ("movq %q0,%%fs:%P1(,%q2,8)" : \ +- : "er" ((uint64_t) cast_to_integer (value)), \ +- "i" (offsetof (struct pthread, member[0])), \ +- "r" (idx)); \ +- }}) +- ++# include + + /* Set the stack guard field in TCB head. */ + # define THREAD_SET_STACK_GUARD(value) \ diff --git a/glibc-rh2024347-6.patch b/glibc-rh2024347-6.patch new file mode 100644 index 0000000..4782cdf --- /dev/null +++ b/glibc-rh2024347-6.patch @@ -0,0 +1,49 @@ +commit 8d1927d8dc5aad0f01c929123086be3a5b799d18 +Author: Florian Weimer +Date: Thu Dec 9 09:49:32 2021 +0100 + + nptl: Introduce THREAD_GETMEM_VOLATILE + + This will be needed for rseq TCB access. + + Reviewed-by: Szabolcs Nagy + +diff --git a/sysdeps/i386/nptl/tcb-access.h b/sysdeps/i386/nptl/tcb-access.h +index 6c6d561e394817c7..5ddd83224bc8eb77 100644 +--- a/sysdeps/i386/nptl/tcb-access.h ++++ b/sysdeps/i386/nptl/tcb-access.h +@@ -41,6 +41,8 @@ + } \ + __value; }) + ++/* THREAD_GETMEM already forces a read. */ ++#define THREAD_GETMEM_VOLATILE(descr, member) THREAD_GETMEM (descr, member) + + /* Same as THREAD_GETMEM, but the member offset can be non-constant. */ + #define THREAD_GETMEM_NC(descr, member, idx) \ +diff --git a/sysdeps/nptl/tcb-access.h b/sysdeps/nptl/tcb-access.h +index b4137b8ab8067915..bbe20b7225b060fd 100644 +--- a/sysdeps/nptl/tcb-access.h ++++ b/sysdeps/nptl/tcb-access.h +@@ -22,6 +22,8 @@ + + #define THREAD_GETMEM(descr, member) \ + descr->member ++#define THREAD_GETMEM_VOLATILE(descr, member) \ ++ (*(volatile __typeof (descr->member) *)&descr->member) + #define THREAD_GETMEM_NC(descr, member, idx) \ + descr->member[idx] + #define THREAD_SETMEM(descr, member, value) \ +diff --git a/sysdeps/x86_64/nptl/tcb-access.h b/sysdeps/x86_64/nptl/tcb-access.h +index 18848a729d16a4f5..e4d2d07a9b218025 100644 +--- a/sysdeps/x86_64/nptl/tcb-access.h ++++ b/sysdeps/x86_64/nptl/tcb-access.h +@@ -39,6 +39,8 @@ + } \ + __value; }) + ++/* THREAD_GETMEM already forces a read. */ ++#define THREAD_GETMEM_VOLATILE(descr, member) THREAD_GETMEM (descr, member) + + /* Same as THREAD_GETMEM, but the member offset can be non-constant. */ + # define THREAD_GETMEM_NC(descr, member, idx) \ diff --git a/glibc-rh2024347-7.patch b/glibc-rh2024347-7.patch new file mode 100644 index 0000000..b0d158b --- /dev/null +++ b/glibc-rh2024347-7.patch @@ -0,0 +1,1130 @@ +commit 95e114a0919d844d8fe07839cb6538b7f5ee920e +Author: Florian Weimer +Date: Thu Dec 9 09:49:32 2021 +0100 + + nptl: Add rseq registration + + The rseq area is placed directly into struct pthread. rseq + registration failure is not treated as an error, so it is possible + that threads run with inconsistent registration status. + + is not yet installed as a public header. + + Co-Authored-By: Mathieu Desnoyers + Reviewed-by: Szabolcs Nagy + Reviewed-by: Siddhesh Poyarekar + +diff --git a/nptl/descr.h b/nptl/descr.h +index 57be5b4fef564b36..dabf980e29615db3 100644 +--- a/nptl/descr.h ++++ b/nptl/descr.h +@@ -35,6 +35,7 @@ + #include + #include + #include ++#include + + #ifndef TCB_ALIGNMENT + # define TCB_ALIGNMENT 32 +@@ -407,6 +408,9 @@ struct pthread + /* Used on strsignal. */ + struct tls_internal_t tls_state; + ++ /* rseq area registered with the kernel. */ ++ struct rseq rseq_area; ++ + /* This member must be last. */ + char end_padding[]; + +diff --git a/nptl/pthread_create.c b/nptl/pthread_create.c +index 3db0c9fdf40ae2bf..d2b40924dafad316 100644 +--- a/nptl/pthread_create.c ++++ b/nptl/pthread_create.c +@@ -33,6 +33,7 @@ + #include + #include + #include ++#include + #include "libioP.h" + #include + #include +@@ -367,6 +368,9 @@ start_thread (void *arg) + /* Initialize pointers to locale data. */ + __ctype_init (); + ++ /* Register rseq TLS to the kernel. */ ++ rseq_register_current_thread (pd); ++ + #ifndef __ASSUME_SET_ROBUST_LIST + if (__nptl_set_robust_list_avail) + #endif +@@ -572,6 +576,15 @@ out: + process is really dead since 'clone' got passed the CLONE_CHILD_CLEARTID + flag. The 'tid' field in the TCB will be set to zero. + ++ rseq TLS is still registered at this point. Rely on implicit ++ unregistration performed by the kernel on thread teardown. This is not a ++ problem because the rseq TLS lives on the stack, and the stack outlives ++ the thread. If TCB allocation is ever changed, additional steps may be ++ required, such as performing explicit rseq unregistration before ++ reclaiming the rseq TLS area memory. It is NOT sufficient to block ++ signals because the kernel may write to the rseq area even without ++ signals. ++ + The exit code is zero since in case all threads exit by calling + 'pthread_exit' the exit status must be 0 (zero). */ + while (1) +diff --git a/sysdeps/nptl/dl-tls_init_tp.c b/sysdeps/nptl/dl-tls_init_tp.c +index ca494dd3a52c4ebf..fedb876fdb2642d2 100644 +--- a/sysdeps/nptl/dl-tls_init_tp.c ++++ b/sysdeps/nptl/dl-tls_init_tp.c +@@ -21,6 +21,7 @@ + #include + #include + #include ++#include + + #ifndef __ASSUME_SET_ROBUST_LIST + bool __nptl_set_robust_list_avail; +@@ -57,11 +58,12 @@ __tls_pre_init_tp (void) + void + __tls_init_tp (void) + { ++ struct pthread *pd = THREAD_SELF; ++ + /* Set up thread stack list management. */ +- list_add (&THREAD_SELF->list, &GL (dl_stack_user)); ++ list_add (&pd->list, &GL (dl_stack_user)); + + /* Early initialization of the TCB. */ +- struct pthread *pd = THREAD_SELF; + pd->tid = INTERNAL_SYSCALL_CALL (set_tid_address, &pd->tid); + THREAD_SETMEM (pd, specific[0], &pd->specific_1stblock[0]); + THREAD_SETMEM (pd, user_stack, true); +@@ -90,6 +92,8 @@ __tls_init_tp (void) + } + } + ++ rseq_register_current_thread (pd); ++ + /* Set initial thread's stack block from 0 up to __libc_stack_end. + It will be bigger than it actually is, but for unwind.c/pt-longjmp.c + purposes this is good enough. */ +diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile +index 76ad06361c4323d7..f84ccd6bbb3b16ad 100644 +--- a/sysdeps/unix/sysv/linux/Makefile ++++ b/sysdeps/unix/sysv/linux/Makefile +@@ -130,7 +130,10 @@ ifeq ($(have-GLIBC_2.27)$(build-shared),yesyes) + tests += tst-ofdlocks-compat + endif + +-tests-internal += tst-sigcontext-get_pc ++tests-internal += \ ++ tst-rseq \ ++ tst-sigcontext-get_pc \ ++ # tests-internal + + tests-time64 += \ + tst-adjtimex-time64 \ +@@ -356,4 +359,8 @@ endif + + ifeq ($(subdir),nptl) + tests += tst-align-clone tst-getpid1 ++ ++# tst-rseq-nptl is an internal test because it requires a definition of ++# __NR_rseq from the internal system call list. ++tests-internal += tst-rseq-nptl + endif +diff --git a/sysdeps/unix/sysv/linux/aarch64/bits/rseq.h b/sysdeps/unix/sysv/linux/aarch64/bits/rseq.h +new file mode 100644 +index 0000000000000000..9ba92725c76b9d4f +--- /dev/null ++++ b/sysdeps/unix/sysv/linux/aarch64/bits/rseq.h +@@ -0,0 +1,43 @@ ++/* Restartable Sequences Linux aarch64 architecture header. ++ Copyright (C) 2021 Free Software Foundation, Inc. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#ifndef _SYS_RSEQ_H ++# error "Never use directly; include instead." ++#endif ++ ++/* RSEQ_SIG is a signature required before each abort handler code. ++ ++ It is a 32-bit value that maps to actual architecture code compiled ++ into applications and libraries. It needs to be defined for each ++ architecture. When choosing this value, it needs to be taken into ++ account that generating invalid instructions may have ill effects on ++ tools like objdump, and may also have impact on the CPU speculative ++ execution efficiency in some cases. ++ ++ aarch64 -mbig-endian generates mixed endianness code vs data: ++ little-endian code and big-endian data. Ensure the RSEQ_SIG signature ++ matches code endianness. */ ++ ++#define RSEQ_SIG_CODE 0xd428bc00 /* BRK #0x45E0. */ ++ ++#ifdef __AARCH64EB__ ++# define RSEQ_SIG_DATA 0x00bc28d4 /* BRK #0x45E0. */ ++#else ++# define RSEQ_SIG_DATA RSEQ_SIG_CODE ++#endif ++ ++#define RSEQ_SIG RSEQ_SIG_DATA +diff --git a/sysdeps/unix/sysv/linux/arm/bits/rseq.h b/sysdeps/unix/sysv/linux/arm/bits/rseq.h +new file mode 100644 +index 0000000000000000..0542b26f6a023dec +--- /dev/null ++++ b/sysdeps/unix/sysv/linux/arm/bits/rseq.h +@@ -0,0 +1,83 @@ ++/* Restartable Sequences Linux arm architecture header. ++ Copyright (C) 2021 Free Software Foundation, Inc. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#ifndef _SYS_RSEQ_H ++# error "Never use directly; include instead." ++#endif ++ ++/* ++ RSEQ_SIG is a signature required before each abort handler code. ++ ++ It is a 32-bit value that maps to actual architecture code compiled ++ into applications and libraries. It needs to be defined for each ++ architecture. When choosing this value, it needs to be taken into ++ account that generating invalid instructions may have ill effects on ++ tools like objdump, and may also have impact on the CPU speculative ++ execution efficiency in some cases. ++ ++ - ARM little endian ++ ++ RSEQ_SIG uses the udf A32 instruction with an uncommon immediate operand ++ value 0x5de3. This traps if user-space reaches this instruction by mistake, ++ and the uncommon operand ensures the kernel does not move the instruction ++ pointer to attacker-controlled code on rseq abort. ++ ++ The instruction pattern in the A32 instruction set is: ++ ++ e7f5def3 udf #24035 ; 0x5de3 ++ ++ This translates to the following instruction pattern in the T16 instruction ++ set: ++ ++ little endian: ++ def3 udf #243 ; 0xf3 ++ e7f5 b.n <7f5> ++ ++ - ARMv6+ big endian (BE8): ++ ++ ARMv6+ -mbig-endian generates mixed endianness code vs data: little-endian ++ code and big-endian data. The data value of the signature needs to have its ++ byte order reversed to generate the trap instruction: ++ ++ Data: 0xf3def5e7 ++ ++ Translates to this A32 instruction pattern: ++ ++ e7f5def3 udf #24035 ; 0x5de3 ++ ++ Translates to this T16 instruction pattern: ++ ++ def3 udf #243 ; 0xf3 ++ e7f5 b.n <7f5> ++ ++ - Prior to ARMv6 big endian (BE32): ++ ++ Prior to ARMv6, -mbig-endian generates big-endian code and data ++ (which match), so the endianness of the data representation of the ++ signature should not be reversed. However, the choice between BE32 ++ and BE8 is done by the linker, so we cannot know whether code and ++ data endianness will be mixed before the linker is invoked. So rather ++ than try to play tricks with the linker, the rseq signature is simply ++ data (not a trap instruction) prior to ARMv6 on big endian. This is ++ why the signature is expressed as data (.word) rather than as ++ instruction (.inst) in assembler. */ ++ ++#ifdef __ARMEB__ ++# define RSEQ_SIG 0xf3def5e7 /* udf #24035 ; 0x5de3 (ARMv6+) */ ++#else ++# define RSEQ_SIG 0xe7f5def3 /* udf #24035 ; 0x5de3 */ ++#endif +diff --git a/sysdeps/unix/sysv/linux/bits/rseq.h b/sysdeps/unix/sysv/linux/bits/rseq.h +new file mode 100644 +index 0000000000000000..46cf5d1c743f25eb +--- /dev/null ++++ b/sysdeps/unix/sysv/linux/bits/rseq.h +@@ -0,0 +1,29 @@ ++/* Restartable Sequences architecture header. Stub version. ++ Copyright (C) 2021 Free Software Foundation, Inc. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#ifndef _SYS_RSEQ_H ++# error "Never use directly; include instead." ++#endif ++ ++/* RSEQ_SIG is a signature required before each abort handler code. ++ ++ It is a 32-bit value that maps to actual architecture code compiled ++ into applications and libraries. It needs to be defined for each ++ architecture. When choosing this value, it needs to be taken into ++ account that generating invalid instructions may have ill effects on ++ tools like objdump, and may also have impact on the CPU speculative ++ execution efficiency in some cases. */ +diff --git a/sysdeps/unix/sysv/linux/mips/bits/rseq.h b/sysdeps/unix/sysv/linux/mips/bits/rseq.h +new file mode 100644 +index 0000000000000000..a9defee568ae04a5 +--- /dev/null ++++ b/sysdeps/unix/sysv/linux/mips/bits/rseq.h +@@ -0,0 +1,62 @@ ++/* Restartable Sequences Linux mips architecture header. ++ Copyright (C) 2021 Free Software Foundation, Inc. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#ifndef _SYS_RSEQ_H ++# error "Never use directly; include instead." ++#endif ++ ++/* RSEQ_SIG is a signature required before each abort handler code. ++ ++ It is a 32-bit value that maps to actual architecture code compiled ++ into applications and libraries. It needs to be defined for each ++ architecture. When choosing this value, it needs to be taken into ++ account that generating invalid instructions may have ill effects on ++ tools like objdump, and may also have impact on the CPU speculative ++ execution efficiency in some cases. ++ ++ RSEQ_SIG uses the break instruction. The instruction pattern is: ++ ++ On MIPS: ++ 0350000d break 0x350 ++ ++ On nanoMIPS: ++ 00100350 break 0x350 ++ ++ On microMIPS: ++ 0000d407 break 0x350 ++ ++ For nanoMIPS32 and microMIPS, the instruction stream is encoded as ++ 16-bit halfwords, so the signature halfwords need to be swapped ++ accordingly for little-endian. */ ++ ++#if defined (__nanomips__) ++# ifdef __MIPSEL__ ++# define RSEQ_SIG 0x03500010 ++# else ++# define RSEQ_SIG 0x00100350 ++# endif ++#elif defined (__mips_micromips) ++# ifdef __MIPSEL__ ++# define RSEQ_SIG 0xd4070000 ++# else ++# define RSEQ_SIG 0x0000d407 ++# endif ++#elif defined (__mips__) ++# define RSEQ_SIG 0x0350000d ++#else ++/* Unknown MIPS architecture. */ ++#endif +diff --git a/sysdeps/unix/sysv/linux/powerpc/bits/rseq.h b/sysdeps/unix/sysv/linux/powerpc/bits/rseq.h +new file mode 100644 +index 0000000000000000..05b3cf7b8fe75b92 +--- /dev/null ++++ b/sysdeps/unix/sysv/linux/powerpc/bits/rseq.h +@@ -0,0 +1,37 @@ ++/* Restartable Sequences Linux powerpc architecture header. ++ Copyright (C) 2021 Free Software Foundation, Inc. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#ifndef _SYS_RSEQ_H ++# error "Never use directly; include instead." ++#endif ++ ++/* RSEQ_SIG is a signature required before each abort handler code. ++ ++ It is a 32-bit value that maps to actual architecture code compiled ++ into applications and libraries. It needs to be defined for each ++ architecture. When choosing this value, it needs to be taken into ++ account that generating invalid instructions may have ill effects on ++ tools like objdump, and may also have impact on the CPU speculative ++ execution efficiency in some cases. ++ ++ RSEQ_SIG uses the following trap instruction: ++ ++ powerpc-be: 0f e5 00 0b twui r5,11 ++ powerpc64-le: 0b 00 e5 0f twui r5,11 ++ powerpc64-be: 0f e5 00 0b twui r5,11 */ ++ ++#define RSEQ_SIG 0x0fe5000b +diff --git a/sysdeps/unix/sysv/linux/rseq-internal.h b/sysdeps/unix/sysv/linux/rseq-internal.h +new file mode 100644 +index 0000000000000000..909f5478251d3d13 +--- /dev/null ++++ b/sysdeps/unix/sysv/linux/rseq-internal.h +@@ -0,0 +1,45 @@ ++/* Restartable Sequences internal API. Linux implementation. ++ Copyright (C) 2021 Free Software Foundation, Inc. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#ifndef RSEQ_INTERNAL_H ++#define RSEQ_INTERNAL_H ++ ++#include ++#include ++#include ++#include ++#include ++ ++#ifdef RSEQ_SIG ++static inline void ++rseq_register_current_thread (struct pthread *self) ++{ ++ int ret = INTERNAL_SYSCALL_CALL (rseq, ++ &self->rseq_area, sizeof (self->rseq_area), ++ 0, RSEQ_SIG); ++ if (INTERNAL_SYSCALL_ERROR_P (ret)) ++ THREAD_SETMEM (self, rseq_area.cpu_id, RSEQ_CPU_ID_REGISTRATION_FAILED); ++} ++#else /* RSEQ_SIG */ ++static inline void ++rseq_register_current_thread (struct pthread *self) ++{ ++ THREAD_SETMEM (self, rseq_area.cpu_id, RSEQ_CPU_ID_REGISTRATION_FAILED); ++} ++#endif /* RSEQ_SIG */ ++ ++#endif /* rseq-internal.h */ +diff --git a/sysdeps/unix/sysv/linux/s390/bits/rseq.h b/sysdeps/unix/sysv/linux/s390/bits/rseq.h +new file mode 100644 +index 0000000000000000..3030e38f403784b3 +--- /dev/null ++++ b/sysdeps/unix/sysv/linux/s390/bits/rseq.h +@@ -0,0 +1,37 @@ ++/* Restartable Sequences Linux s390 architecture header. ++ Copyright (C) 2021 Free Software Foundation, Inc. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#ifndef _SYS_RSEQ_H ++# error "Never use directly; include instead." ++#endif ++ ++/* RSEQ_SIG is a signature required before each abort handler code. ++ ++ It is a 32-bit value that maps to actual architecture code compiled ++ into applications and libraries. It needs to be defined for each ++ architecture. When choosing this value, it needs to be taken into ++ account that generating invalid instructions may have ill effects on ++ tools like objdump, and may also have impact on the CPU speculative ++ execution efficiency in some cases. ++ ++ RSEQ_SIG uses the trap4 instruction. As Linux does not make use of the ++ access-register mode nor the linkage stack this instruction will always ++ cause a special-operation exception (the trap-enabled bit in the DUCT ++ is and will stay 0). The instruction pattern is ++ b2 ff 0f ff trap4 4095(%r0) */ ++ ++#define RSEQ_SIG 0xB2FF0FFF +diff --git a/sysdeps/unix/sysv/linux/sys/rseq.h b/sysdeps/unix/sysv/linux/sys/rseq.h +new file mode 100644 +index 0000000000000000..c8edff50d40e29b6 +--- /dev/null ++++ b/sysdeps/unix/sysv/linux/sys/rseq.h +@@ -0,0 +1,174 @@ ++/* Restartable Sequences exported symbols. Linux header. ++ Copyright (C) 2021 Free Software Foundation, Inc. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#ifndef _SYS_RSEQ_H ++#define _SYS_RSEQ_H 1 ++ ++/* Architecture-specific rseq signature. */ ++#include ++ ++#include ++#include ++#include ++ ++#ifdef __has_include ++# if __has_include ("linux/rseq.h") ++# define __GLIBC_HAVE_KERNEL_RSEQ ++# endif ++#else ++# include ++# if LINUX_VERSION_CODE >= KERNEL_VERSION (4, 18, 0) ++# define __GLIBC_HAVE_KERNEL_RSEQ ++# endif ++#endif ++ ++#ifdef __GLIBC_HAVE_KERNEL_RSEQ ++/* We use the structures declarations from the kernel headers. */ ++# include ++#else /* __GLIBC_HAVE_KERNEL_RSEQ */ ++/* We use a copy of the include/uapi/linux/rseq.h kernel header. */ ++ ++enum rseq_cpu_id_state ++ { ++ RSEQ_CPU_ID_UNINITIALIZED = -1, ++ RSEQ_CPU_ID_REGISTRATION_FAILED = -2, ++ }; ++ ++enum rseq_flags ++ { ++ RSEQ_FLAG_UNREGISTER = (1 << 0), ++ }; ++ ++enum rseq_cs_flags_bit ++ { ++ RSEQ_CS_FLAG_NO_RESTART_ON_PREEMPT_BIT = 0, ++ RSEQ_CS_FLAG_NO_RESTART_ON_SIGNAL_BIT = 1, ++ RSEQ_CS_FLAG_NO_RESTART_ON_MIGRATE_BIT = 2, ++ }; ++ ++enum rseq_cs_flags ++ { ++ RSEQ_CS_FLAG_NO_RESTART_ON_PREEMPT = ++ (1U << RSEQ_CS_FLAG_NO_RESTART_ON_PREEMPT_BIT), ++ RSEQ_CS_FLAG_NO_RESTART_ON_SIGNAL = ++ (1U << RSEQ_CS_FLAG_NO_RESTART_ON_SIGNAL_BIT), ++ RSEQ_CS_FLAG_NO_RESTART_ON_MIGRATE = ++ (1U << RSEQ_CS_FLAG_NO_RESTART_ON_MIGRATE_BIT), ++ }; ++ ++/* struct rseq_cs is aligned on 32 bytes to ensure it is always ++ contained within a single cache-line. It is usually declared as ++ link-time constant data. */ ++struct rseq_cs ++ { ++ /* Version of this structure. */ ++ uint32_t version; ++ /* enum rseq_cs_flags. */ ++ uint32_t flags; ++ uint64_t start_ip; ++ /* Offset from start_ip. */ ++ uint64_t post_commit_offset; ++ uint64_t abort_ip; ++ } __attribute__ ((__aligned__ (32))); ++ ++/* struct rseq is aligned on 32 bytes to ensure it is always ++ contained within a single cache-line. ++ ++ A single struct rseq per thread is allowed. */ ++struct rseq ++ { ++ /* Restartable sequences cpu_id_start field. Updated by the ++ kernel. Read by user-space with single-copy atomicity ++ semantics. This field should only be read by the thread which ++ registered this data structure. Aligned on 32-bit. Always ++ contains a value in the range of possible CPUs, although the ++ value may not be the actual current CPU (e.g. if rseq is not ++ initialized). This CPU number value should always be compared ++ against the value of the cpu_id field before performing a rseq ++ commit or returning a value read from a data structure indexed ++ using the cpu_id_start value. */ ++ uint32_t cpu_id_start; ++ /* Restartable sequences cpu_id field. Updated by the kernel. ++ Read by user-space with single-copy atomicity semantics. This ++ field should only be read by the thread which registered this ++ data structure. Aligned on 32-bit. Values ++ RSEQ_CPU_ID_UNINITIALIZED and RSEQ_CPU_ID_REGISTRATION_FAILED ++ have a special semantic: the former means "rseq uninitialized", ++ and latter means "rseq initialization failed". This value is ++ meant to be read within rseq critical sections and compared ++ with the cpu_id_start value previously read, before performing ++ the commit instruction, or read and compared with the ++ cpu_id_start value before returning a value loaded from a data ++ structure indexed using the cpu_id_start value. */ ++ uint32_t cpu_id; ++ /* Restartable sequences rseq_cs field. ++ ++ Contains NULL when no critical section is active for the current ++ thread, or holds a pointer to the currently active struct rseq_cs. ++ ++ Updated by user-space, which sets the address of the currently ++ active rseq_cs at the beginning of assembly instruction sequence ++ block, and set to NULL by the kernel when it restarts an assembly ++ instruction sequence block, as well as when the kernel detects that ++ it is preempting or delivering a signal outside of the range ++ targeted by the rseq_cs. Also needs to be set to NULL by user-space ++ before reclaiming memory that contains the targeted struct rseq_cs. ++ ++ Read and set by the kernel. Set by user-space with single-copy ++ atomicity semantics. This field should only be updated by the ++ thread which registered this data structure. Aligned on 64-bit. */ ++ union ++ { ++ uint64_t ptr64; ++# ifdef __LP64__ ++ uint64_t ptr; ++# else /* __LP64__ */ ++ struct ++ { ++#if __BYTE_ORDER == __BIG_ENDIAN ++ uint32_t padding; /* Initialized to zero. */ ++ uint32_t ptr32; ++# else /* LITTLE */ ++ uint32_t ptr32; ++ uint32_t padding; /* Initialized to zero. */ ++# endif /* ENDIAN */ ++ } ptr; ++# endif /* __LP64__ */ ++ } rseq_cs; ++ ++ /* Restartable sequences flags field. ++ ++ This field should only be updated by the thread which ++ registered this data structure. Read by the kernel. ++ Mainly used for single-stepping through rseq critical sections ++ with debuggers. ++ ++ - RSEQ_CS_FLAG_NO_RESTART_ON_PREEMPT ++ Inhibit instruction sequence block restart on preemption ++ for this thread. ++ - RSEQ_CS_FLAG_NO_RESTART_ON_SIGNAL ++ Inhibit instruction sequence block restart on signal ++ delivery for this thread. ++ - RSEQ_CS_FLAG_NO_RESTART_ON_MIGRATE ++ Inhibit instruction sequence block restart on migration for ++ this thread. */ ++ uint32_t flags; ++ } __attribute__ ((__aligned__ (32))); ++ ++#endif /* __GLIBC_HAVE_KERNEL_RSEQ */ ++ ++#endif /* sys/rseq.h */ +diff --git a/sysdeps/unix/sysv/linux/tst-rseq-nptl.c b/sysdeps/unix/sysv/linux/tst-rseq-nptl.c +new file mode 100644 +index 0000000000000000..d31d94445caa9ee3 +--- /dev/null ++++ b/sysdeps/unix/sysv/linux/tst-rseq-nptl.c +@@ -0,0 +1,260 @@ ++/* Restartable Sequences NPTL test. ++ Copyright (C) 2021 Free Software Foundation, Inc. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++/* These tests validate that rseq is registered from various execution ++ contexts (main thread, destructor, other threads, other threads created ++ from destructor, forked process (without exec), pthread_atfork handlers, ++ pthread setspecific destructors, signal handlers, atexit handlers). ++ ++ See the Linux kernel selftests for extensive rseq stress-tests. */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#ifdef RSEQ_SIG ++# include ++# include ++# include ++# include ++# include ++# include ++# include ++# include ++# include ++# include ++# include ++# include ++# include "tst-rseq.h" ++ ++static pthread_key_t rseq_test_key; ++ ++static void ++atfork_prepare (void) ++{ ++ if (!rseq_thread_registered ()) ++ { ++ printf ("error: rseq not registered in pthread atfork prepare\n"); ++ support_record_failure (); ++ } ++} ++ ++static void ++atfork_parent (void) ++{ ++ if (!rseq_thread_registered ()) ++ { ++ printf ("error: rseq not registered in pthread atfork parent\n"); ++ support_record_failure (); ++ } ++} ++ ++static void ++atfork_child (void) ++{ ++ if (!rseq_thread_registered ()) ++ { ++ printf ("error: rseq not registered in pthread atfork child\n"); ++ support_record_failure (); ++ } ++} ++ ++static void ++rseq_key_destructor (void *arg) ++{ ++ /* Cannot use deferred failure reporting after main returns. */ ++ if (!rseq_thread_registered ()) ++ FAIL_EXIT1 ("rseq not registered in pthread key destructor"); ++} ++ ++static void ++atexit_handler (void) ++{ ++ /* Cannot use deferred failure reporting after main returns. */ ++ if (!rseq_thread_registered ()) ++ FAIL_EXIT1 ("rseq not registered in atexit handler"); ++} ++ ++/* Used to avoid -Werror=stringop-overread warning with ++ pthread_setspecific and GCC 11. */ ++static char one = 1; ++ ++static void ++do_rseq_main_test (void) ++{ ++ TEST_COMPARE (atexit (atexit_handler), 0); ++ rseq_test_key = xpthread_key_create (rseq_key_destructor); ++ TEST_COMPARE (pthread_atfork (atfork_prepare, atfork_parent, atfork_child), 0); ++ xraise (SIGUSR1); ++ TEST_COMPARE (pthread_setspecific (rseq_test_key, &one), 0); ++ TEST_VERIFY_EXIT (rseq_thread_registered ()); ++} ++ ++static void ++cancel_routine (void *arg) ++{ ++ if (!rseq_thread_registered ()) ++ { ++ printf ("error: rseq not registered in cancel routine\n"); ++ support_record_failure (); ++ } ++} ++ ++static pthread_barrier_t cancel_thread_barrier; ++static pthread_cond_t cancel_thread_cond = PTHREAD_COND_INITIALIZER; ++static pthread_mutex_t cancel_thread_mutex = PTHREAD_MUTEX_INITIALIZER; ++ ++static void ++test_cancel_thread (void) ++{ ++ pthread_cleanup_push (cancel_routine, NULL); ++ (void) xpthread_barrier_wait (&cancel_thread_barrier); ++ /* Wait forever until cancellation. */ ++ xpthread_cond_wait (&cancel_thread_cond, &cancel_thread_mutex); ++ pthread_cleanup_pop (0); ++} ++ ++static void * ++thread_function (void * arg) ++{ ++ int i = (int) (intptr_t) arg; ++ ++ xraise (SIGUSR1); ++ if (i == 0) ++ test_cancel_thread (); ++ TEST_COMPARE (pthread_setspecific (rseq_test_key, &one), 0); ++ return rseq_thread_registered () ? NULL : (void *) 1l; ++} ++ ++static void ++sighandler (int sig) ++{ ++ if (!rseq_thread_registered ()) ++ { ++ printf ("error: rseq not registered in signal handler\n"); ++ support_record_failure (); ++ } ++} ++ ++static void ++setup_signals (void) ++{ ++ struct sigaction sa; ++ ++ sigemptyset (&sa.sa_mask); ++ sigaddset (&sa.sa_mask, SIGUSR1); ++ sa.sa_flags = 0; ++ sa.sa_handler = sighandler; ++ xsigaction (SIGUSR1, &sa, NULL); ++} ++ ++static int ++do_rseq_threads_test (int nr_threads) ++{ ++ pthread_t th[nr_threads]; ++ int i; ++ int result = 0; ++ ++ xpthread_barrier_init (&cancel_thread_barrier, NULL, 2); ++ ++ for (i = 0; i < nr_threads; ++i) ++ th[i] = xpthread_create (NULL, thread_function, ++ (void *) (intptr_t) i); ++ ++ (void) xpthread_barrier_wait (&cancel_thread_barrier); ++ ++ xpthread_cancel (th[0]); ++ ++ for (i = 0; i < nr_threads; ++i) ++ { ++ void *v; ++ ++ v = xpthread_join (th[i]); ++ if (i != 0 && v != NULL) ++ { ++ printf ("error: join %d successful, but child failed\n", i); ++ result = 1; ++ } ++ else if (i == 0 && v == NULL) ++ { ++ printf ("error: join %d successful, child did not fail as expected\n", i); ++ result = 1; ++ } ++ } ++ ++ xpthread_barrier_destroy (&cancel_thread_barrier); ++ ++ return result; ++} ++ ++static void ++subprocess_callback (void *closure) ++{ ++ do_rseq_main_test (); ++} ++ ++static void ++do_rseq_fork_test (void) ++{ ++ support_isolate_in_subprocess (subprocess_callback, NULL); ++} ++ ++static int ++do_rseq_test (void) ++{ ++ int t[] = { 1, 2, 6, 5, 4, 3, 50 }; ++ int i, result = 0; ++ ++ if (!rseq_available ()) ++ FAIL_UNSUPPORTED ("kernel does not support rseq, skipping test"); ++ setup_signals (); ++ xraise (SIGUSR1); ++ do_rseq_main_test (); ++ for (i = 0; i < array_length (t); i++) ++ if (do_rseq_threads_test (t[i])) ++ result = 1; ++ do_rseq_fork_test (); ++ return result; ++} ++ ++static void __attribute__ ((destructor)) ++do_rseq_destructor_test (void) ++{ ++ /* Cannot use deferred failure reporting after main returns. */ ++ if (do_rseq_test ()) ++ FAIL_EXIT1 ("rseq not registered within destructor"); ++ xpthread_key_delete (rseq_test_key); ++} ++ ++#else /* RSEQ_SIG */ ++static int ++do_rseq_test (void) ++{ ++ FAIL_UNSUPPORTED ("glibc does not define RSEQ_SIG, skipping test"); ++ return 0; ++} ++#endif /* RSEQ_SIG */ ++ ++static int ++do_test (void) ++{ ++ return do_rseq_test (); ++} ++ ++#include +diff --git a/sysdeps/unix/sysv/linux/tst-rseq.c b/sysdeps/unix/sysv/linux/tst-rseq.c +new file mode 100644 +index 0000000000000000..926376b6a5446ece +--- /dev/null ++++ b/sysdeps/unix/sysv/linux/tst-rseq.c +@@ -0,0 +1,64 @@ ++/* Restartable Sequences single-threaded tests. ++ Copyright (C) 2021 Free Software Foundation, Inc. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++/* These tests validate that rseq is registered from main in an executable ++ not linked against libpthread. */ ++ ++#include ++#include ++#include ++#include ++ ++#ifdef RSEQ_SIG ++# include ++# include ++# include ++# include ++# include ++# include "tst-rseq.h" ++ ++static void ++do_rseq_main_test (void) ++{ ++ TEST_VERIFY_EXIT (rseq_thread_registered ()); ++} ++ ++static void ++do_rseq_test (void) ++{ ++ if (!rseq_available ()) ++ { ++ FAIL_UNSUPPORTED ("kernel does not support rseq, skipping test"); ++ } ++ do_rseq_main_test (); ++} ++#else /* RSEQ_SIG */ ++static void ++do_rseq_test (void) ++{ ++ FAIL_UNSUPPORTED ("glibc does not define RSEQ_SIG, skipping test"); ++} ++#endif /* RSEQ_SIG */ ++ ++static int ++do_test (void) ++{ ++ do_rseq_test (); ++ return 0; ++} ++ ++#include +diff --git a/sysdeps/unix/sysv/linux/tst-rseq.h b/sysdeps/unix/sysv/linux/tst-rseq.h +new file mode 100644 +index 0000000000000000..a476c316fc2671a0 +--- /dev/null ++++ b/sysdeps/unix/sysv/linux/tst-rseq.h +@@ -0,0 +1,57 @@ ++/* Restartable Sequences tests header. ++ Copyright (C) 2021 Free Software Foundation, Inc. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++static inline bool ++rseq_thread_registered (void) ++{ ++ return THREAD_GETMEM_VOLATILE (THREAD_SELF, rseq_area.cpu_id) >= 0; ++} ++ ++static inline int ++sys_rseq (struct rseq *rseq_abi, uint32_t rseq_len, int flags, uint32_t sig) ++{ ++ return syscall (__NR_rseq, rseq_abi, rseq_len, flags, sig); ++} ++ ++static inline bool ++rseq_available (void) ++{ ++ int rc; ++ ++ rc = sys_rseq (NULL, 0, 0, 0); ++ if (rc != -1) ++ FAIL_EXIT1 ("Unexpected rseq return value %d", rc); ++ switch (errno) ++ { ++ case ENOSYS: ++ return false; ++ case EINVAL: ++ /* rseq is implemented, but detected an invalid rseq_len parameter. */ ++ return true; ++ default: ++ FAIL_EXIT1 ("Unexpected rseq error %s", strerror (errno)); ++ } ++} +diff --git a/sysdeps/unix/sysv/linux/x86/bits/rseq.h b/sysdeps/unix/sysv/linux/x86/bits/rseq.h +new file mode 100644 +index 0000000000000000..9fc909e7c8a25bbb +--- /dev/null ++++ b/sysdeps/unix/sysv/linux/x86/bits/rseq.h +@@ -0,0 +1,30 @@ ++/* Restartable Sequences Linux x86 architecture header. ++ Copyright (C) 2021 Free Software Foundation, Inc. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#ifndef _SYS_RSEQ_H ++# error "Never use directly; include instead." ++#endif ++ ++/* RSEQ_SIG is a signature required before each abort handler code. ++ ++ RSEQ_SIG is used with the following reserved undefined instructions, which ++ trap in user-space: ++ ++ x86-32: 0f b9 3d 53 30 05 53 ud1 0x53053053,%edi ++ x86-64: 0f b9 3d 53 30 05 53 ud1 0x53053053(%rip),%edi */ ++ ++#define RSEQ_SIG 0x53053053 diff --git a/glibc-rh2024347-8.patch b/glibc-rh2024347-8.patch new file mode 100644 index 0000000..1436fe1 --- /dev/null +++ b/glibc-rh2024347-8.patch @@ -0,0 +1,43 @@ +commit 1d350aa06091211863e41169729cee1bca39f72f +Author: Florian Weimer +Date: Thu Dec 9 09:49:32 2021 +0100 + + Linux: Use rseq to accelerate sched_getcpu + + Co-Authored-By: Mathieu Desnoyers + Reviewed-by: Szabolcs Nagy + +diff --git a/sysdeps/unix/sysv/linux/sched_getcpu.c b/sysdeps/unix/sysv/linux/sched_getcpu.c +index c41e986f2cab5e42..6f78edaea1495342 100644 +--- a/sysdeps/unix/sysv/linux/sched_getcpu.c ++++ b/sysdeps/unix/sysv/linux/sched_getcpu.c +@@ -20,8 +20,8 @@ + #include + #include + +-int +-sched_getcpu (void) ++static int ++vsyscall_sched_getcpu (void) + { + unsigned int cpu; + int r = -1; +@@ -32,3 +32,18 @@ sched_getcpu (void) + #endif + return r == -1 ? r : cpu; + } ++ ++#ifdef RSEQ_SIG ++int ++sched_getcpu (void) ++{ ++ int cpu_id = THREAD_GETMEM_VOLATILE (THREAD_SELF, rseq_area.cpu_id); ++ return __glibc_likely (cpu_id >= 0) ? cpu_id : vsyscall_sched_getcpu (); ++} ++#else /* RSEQ_SIG */ ++int ++sched_getcpu (void) ++{ ++ return vsyscall_sched_getcpu (); ++} ++#endif /* RSEQ_SIG */ diff --git a/glibc-rh2024347-9.patch b/glibc-rh2024347-9.patch new file mode 100644 index 0000000..af25983 --- /dev/null +++ b/glibc-rh2024347-9.patch @@ -0,0 +1,278 @@ +commit e3e589829d16af9f7e73c7b70f74f3c5d5003e45 +Author: Florian Weimer +Date: Thu Dec 9 09:49:32 2021 +0100 + + nptl: Add glibc.pthread.rseq tunable to control rseq registration + + This tunable allows applications to register the rseq area instead + of glibc. + + Reviewed-by: Szabolcs Nagy + Reviewed-by: Siddhesh Poyarekar + +diff --git a/manual/tunables.texi b/manual/tunables.texi +index 658547c6137bf177..1f5c410288eeecec 100644 +--- a/manual/tunables.texi ++++ b/manual/tunables.texi +@@ -413,6 +413,16 @@ The value is measured in bytes. The default is @samp{41943040} + (fourty mibibytes). + @end deftp + ++@deftp Tunable glibc.pthread.rseq ++The @code{glibc.pthread.rseq} tunable can be set to @samp{0}, to disable ++restartable sequences support in @theglibc{}. This enables applications ++to perform direct restartable sequence registration with the kernel. ++The default is @samp{1}, which means that @theglibc{} performs ++registration on behalf of the application. ++ ++Restartable sequences are a Linux-specific extension. ++@end deftp ++ + @node Hardware Capability Tunables + @section Hardware Capability Tunables + @cindex hardware capability tunables +diff --git a/nptl/pthread_create.c b/nptl/pthread_create.c +index d2b40924dafad316..f405fa356c2955ce 100644 +--- a/nptl/pthread_create.c ++++ b/nptl/pthread_create.c +@@ -369,7 +369,10 @@ start_thread (void *arg) + __ctype_init (); + + /* Register rseq TLS to the kernel. */ +- rseq_register_current_thread (pd); ++ { ++ bool do_rseq = THREAD_GETMEM (pd, flags) & ATTR_FLAG_DO_RSEQ; ++ rseq_register_current_thread (pd, do_rseq); ++ } + + #ifndef __ASSUME_SET_ROBUST_LIST + if (__nptl_set_robust_list_avail) +@@ -678,6 +681,11 @@ __pthread_create_2_1 (pthread_t *newthread, const pthread_attr_t *attr, + pd->flags = ((iattr->flags & ~(ATTR_FLAG_SCHED_SET | ATTR_FLAG_POLICY_SET)) + | (self->flags & (ATTR_FLAG_SCHED_SET | ATTR_FLAG_POLICY_SET))); + ++ /* Inherit rseq registration state. Without seccomp filters, rseq ++ registration will either always fail or always succeed. */ ++ if ((int) THREAD_GETMEM_VOLATILE (self, rseq_area.cpu_id) >= 0) ++ pd->flags |= ATTR_FLAG_DO_RSEQ; ++ + /* Initialize the field for the ID of the thread which is waiting + for us. This is a self-reference in case the thread is created + detached. */ +diff --git a/sysdeps/nptl/dl-tls_init_tp.c b/sysdeps/nptl/dl-tls_init_tp.c +index fedb876fdb2642d2..b39dfbff2c6678d5 100644 +--- a/sysdeps/nptl/dl-tls_init_tp.c ++++ b/sysdeps/nptl/dl-tls_init_tp.c +@@ -23,6 +23,9 @@ + #include + #include + ++#define TUNABLE_NAMESPACE pthread ++#include ++ + #ifndef __ASSUME_SET_ROBUST_LIST + bool __nptl_set_robust_list_avail; + rtld_hidden_data_def (__nptl_set_robust_list_avail) +@@ -92,7 +95,13 @@ __tls_init_tp (void) + } + } + +- rseq_register_current_thread (pd); ++ { ++ bool do_rseq = true; ++#if HAVE_TUNABLES ++ do_rseq = TUNABLE_GET (rseq, int, NULL); ++#endif ++ rseq_register_current_thread (pd, do_rseq); ++ } + + /* Set initial thread's stack block from 0 up to __libc_stack_end. + It will be bigger than it actually is, but for unwind.c/pt-longjmp.c +diff --git a/sysdeps/nptl/dl-tunables.list b/sysdeps/nptl/dl-tunables.list +index ac5d053298725468..d24f4be0d08ba407 100644 +--- a/sysdeps/nptl/dl-tunables.list ++++ b/sysdeps/nptl/dl-tunables.list +@@ -27,5 +27,11 @@ glibc { + type: SIZE_T + default: 41943040 + } ++ rseq { ++ type: INT_32 ++ minval: 0 ++ maxval: 1 ++ default: 1 ++ } + } + } +diff --git a/sysdeps/nptl/internaltypes.h b/sysdeps/nptl/internaltypes.h +index 50a2ad19ae7210ae..8205c6d15a918952 100644 +--- a/sysdeps/nptl/internaltypes.h ++++ b/sysdeps/nptl/internaltypes.h +@@ -49,6 +49,7 @@ struct pthread_attr + #define ATTR_FLAG_OLDATTR 0x0010 + #define ATTR_FLAG_SCHED_SET 0x0020 + #define ATTR_FLAG_POLICY_SET 0x0040 ++#define ATTR_FLAG_DO_RSEQ 0x0080 + + /* Used to allocate a pthread_attr_t object which is also accessed + internally. */ +diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile +index f84ccd6bbb3b16ad..d30d21898b402d1e 100644 +--- a/sysdeps/unix/sysv/linux/Makefile ++++ b/sysdeps/unix/sysv/linux/Makefile +@@ -135,6 +135,12 @@ tests-internal += \ + tst-sigcontext-get_pc \ + # tests-internal + ++ifneq (no,$(have-tunables)) ++tests-internal += \ ++ tst-rseq-disable \ ++ # tests-internal $(have-tunables) ++endif ++ + tests-time64 += \ + tst-adjtimex-time64 \ + tst-clock_adjtime-time64 \ +@@ -226,6 +232,8 @@ $(objpfx)tst-mman-consts.out: ../sysdeps/unix/sysv/linux/tst-mman-consts.py + < /dev/null > $@ 2>&1; $(evaluate-test) + $(objpfx)tst-mman-consts.out: $(sysdeps-linux-python-deps) + ++tst-rseq-disable-ENV = GLIBC_TUNABLES=glibc.pthread.rseq=0 ++ + endif # $(subdir) == misc + + ifeq ($(subdir),time) +diff --git a/sysdeps/unix/sysv/linux/rseq-internal.h b/sysdeps/unix/sysv/linux/rseq-internal.h +index 909f5478251d3d13..15bc7ffd6eda632d 100644 +--- a/sysdeps/unix/sysv/linux/rseq-internal.h ++++ b/sysdeps/unix/sysv/linux/rseq-internal.h +@@ -21,22 +21,27 @@ + #include + #include + #include ++#include + #include + #include + + #ifdef RSEQ_SIG + static inline void +-rseq_register_current_thread (struct pthread *self) ++rseq_register_current_thread (struct pthread *self, bool do_rseq) + { +- int ret = INTERNAL_SYSCALL_CALL (rseq, +- &self->rseq_area, sizeof (self->rseq_area), +- 0, RSEQ_SIG); +- if (INTERNAL_SYSCALL_ERROR_P (ret)) +- THREAD_SETMEM (self, rseq_area.cpu_id, RSEQ_CPU_ID_REGISTRATION_FAILED); ++ if (do_rseq) ++ { ++ int ret = INTERNAL_SYSCALL_CALL (rseq, &self->rseq_area, ++ sizeof (self->rseq_area), ++ 0, RSEQ_SIG); ++ if (!INTERNAL_SYSCALL_ERROR_P (ret)) ++ return; ++ } ++ THREAD_SETMEM (self, rseq_area.cpu_id, RSEQ_CPU_ID_REGISTRATION_FAILED); + } + #else /* RSEQ_SIG */ + static inline void +-rseq_register_current_thread (struct pthread *self) ++rseq_register_current_thread (struct pthread *self, bool do_rseq) + { + THREAD_SETMEM (self, rseq_area.cpu_id, RSEQ_CPU_ID_REGISTRATION_FAILED); + } +diff --git a/sysdeps/unix/sysv/linux/tst-rseq-disable.c b/sysdeps/unix/sysv/linux/tst-rseq-disable.c +new file mode 100644 +index 0000000000000000..000e351872fc2f76 +--- /dev/null ++++ b/sysdeps/unix/sysv/linux/tst-rseq-disable.c +@@ -0,0 +1,89 @@ ++/* Test disabling of rseq registration via tunable. ++ Copyright (C) 2021 Free Software Foundation, Inc. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#ifdef RSEQ_SIG ++ ++/* Check that rseq can be registered and has not been taken by glibc. */ ++static void ++check_rseq_disabled (void) ++{ ++ struct pthread *pd = THREAD_SELF; ++ TEST_COMPARE ((int) pd->rseq_area.cpu_id, RSEQ_CPU_ID_REGISTRATION_FAILED); ++ ++ int ret = syscall (__NR_rseq, &pd->rseq_area, sizeof (pd->rseq_area), ++ 0, RSEQ_SIG); ++ if (ret == 0) ++ { ++ ret = syscall (__NR_rseq, &pd->rseq_area, sizeof (pd->rseq_area), ++ RSEQ_FLAG_UNREGISTER, RSEQ_SIG); ++ TEST_COMPARE (ret, 0); ++ pd->rseq_area.cpu_id = RSEQ_CPU_ID_REGISTRATION_FAILED; ++ } ++ else ++ { ++ TEST_VERIFY (errno != -EINVAL); ++ TEST_VERIFY (errno != -EBUSY); ++ } ++} ++ ++static void * ++thread_func (void *ignored) ++{ ++ check_rseq_disabled (); ++ return NULL; ++} ++ ++static void ++proc_func (void *ignored) ++{ ++ check_rseq_disabled (); ++} ++ ++static int ++do_test (void) ++{ ++ puts ("info: checking main thread"); ++ check_rseq_disabled (); ++ ++ puts ("info: checking main thread (2)"); ++ check_rseq_disabled (); ++ ++ puts ("info: checking new thread"); ++ xpthread_join (xpthread_create (NULL, thread_func, NULL)); ++ ++ puts ("info: checking subprocess"); ++ support_isolate_in_subprocess (proc_func, NULL); ++ ++ return 0; ++} ++#else /* !RSEQ_SIG */ ++static int ++do_test (void) ++{ ++ FAIL_UNSUPPORTED ("glibc does not define RSEQ_SIG, skipping test"); ++} ++#endif ++ ++#include diff --git a/glibc.spec b/glibc.spec index 00649b0..c097719 100644 --- a/glibc.spec +++ b/glibc.spec @@ -148,7 +148,7 @@ end \ Summary: The GNU libc libraries Name: glibc Version: %{glibcversion} -Release: 18%{?dist} +Release: 19%{?dist} # In general, GPLv2+ is used by programs, LGPLv2+ is used for # libraries. @@ -313,6 +313,19 @@ Patch113: glibc-rh2032647-3.patch Patch114: glibc-rh2032647-4.patch Patch115: glibc-rh2032647-5.patch Patch116: glibc-rh2032647-6.patch +Patch117: glibc-rh2024347-1.patch +Patch118: glibc-rh2024347-2.patch +Patch119: glibc-rh2024347-3.patch +Patch120: glibc-rh2024347-4.patch +Patch121: glibc-rh2024347-5.patch +Patch122: glibc-rh2024347-6.patch +Patch123: glibc-rh2024347-7.patch +Patch124: glibc-rh2024347-8.patch +Patch125: glibc-rh2024347-9.patch +Patch126: glibc-rh2024347-10.patch +Patch127: glibc-rh2024347-11.patch +Patch128: glibc-rh2024347-12.patch +Patch129: glibc-rh2024347-13.patch ############################################################################## # Continued list of core "glibc" package information: @@ -2341,6 +2354,9 @@ fi %files -f compat-libpthread-nonshared.filelist -n compat-libpthread-nonshared %changelog +* Fri Jan 14 2022 Florian Weimer - 2.34-19 +- Optionally accelerate sched_getcpu using rseq (#2024347) + * Thu Jan 13 2022 Florian Weimer - 2.34-18 - Backport optimized ELF dependency sorting algorithm (#2032647)