diff options
author | Alexander Mikhalitsyn <alexander.mikhalitsyn@virtuozzo.com> | 2021-12-24 22:56:56 +0300 |
---|---|---|
committer | Andrei Vagin <avagin@gmail.com> | 2022-04-29 03:53:52 +0300 |
commit | 441310c2600e9f95e53a140a321981801c9941fd (patch) | |
tree | e6a6c039d436c7cb630ce49f4bd5b019ca2eab93 | |
parent | f70ddab24eeb99fcbab0015c8338b673d002d5e6 (diff) |
zdtm/static/rseq00: fix rseq test when linking with a fresh Glibc
Fresh Glibc does rseq() register by default. We need to unregister
rseq before registering our own.
Signed-off-by: Alexander Mikhalitsyn <alexander.mikhalitsyn@virtuozzo.com>
-rw-r--r-- | test/zdtm/static/rseq00.c | 57 |
1 files changed, 45 insertions, 12 deletions
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 <sys/rseq.h> +#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 <alexander.mikhalitsyn@virtuozzo.com>"; /* 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; |