diff --git a/test/zdtm/static/rseq00.c b/test/zdtm/static/rseq00.c index b73b1b258..471ad6a43 100644 --- a/test/zdtm/static/rseq00.c +++ b/test/zdtm/static/rseq00.c @@ -19,12 +19,52 @@ #include "zdtmtst.h" +#ifdef __has_include +#if __has_include("sys/rseq.h") +#include +#endif +#endif + #if defined(__x86_64__) +#if defined(RSEQ_SIG) +static inline void *__criu_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 /* __x86_64__ */ + return __result; +#endif /* !GCC 11 */ +} + +static inline void unregister_glibc_rseq(void) +{ + struct rseq *rseq = (struct rseq *)((char *)__criu_thread_pointer() + __rseq_offset); + + /* hack: mark glibc rseq structure as failed to register */ + rseq->cpu_id = RSEQ_CPU_ID_REGISTRATION_FAILED; + + /* unregister rseq */ + syscall(__NR_rseq, (void *)rseq, __rseq_size, 1, RSEQ_SIG); +} +#else +static inline void unregister_glibc_rseq(void) +{ +} +#endif /* defined(RSEQ_SIG) */ + const char *test_doc = "Check that rseq() basic C/R works"; const char *test_author = "Alexander Mikhalitsyn "; /* some useful definitions from kernel uapi */ +#ifndef RSEQ_SIG + enum rseq_flags { RSEQ_FLAG_UNREGISTER = (1 << 0), }; @@ -36,6 +76,10 @@ struct rseq { uint32_t flags; } __attribute__((aligned(4 * sizeof(uint64_t)))); +#define RSEQ_SIG 0x53053053 + +#endif /* RSEQ_SIG */ + #ifndef __NR_rseq #define __NR_rseq 334 #endif @@ -43,8 +87,6 @@ struct rseq { static __thread volatile struct rseq __rseq_abi; -#define RSEQ_SIG 0x53053053 - static int sys_rseq(volatile struct rseq *rseq_abi, uint32_t rseq_len, int flags, uint32_t sig) { return syscall(__NR_rseq, rseq_abi, rseq_len, flags, sig); @@ -53,6 +95,7 @@ static int sys_rseq(volatile struct rseq *rseq_abi, uint32_t rseq_len, int flags static void register_thread(void) { int rc; + unregister_glibc_rseq(); rc = sys_rseq(&__rseq_abi, sizeof(struct rseq), 0, RSEQ_SIG); if (rc) { fail("Failed to register rseq"); @@ -60,16 +103,6 @@ static void register_thread(void) } } -static void unregister_thread(void) -{ - int rc; - rc = sys_rseq(&__rseq_abi, sizeof(struct rseq), RSEQ_FLAG_UNREGISTER, RSEQ_SIG); - if (rc) { - fail("Failed to unregister rseq"); - exit(1); - } -} - static void check_thread(void) { int rc;