mirror of
https://github.com/checkpoint-restore/criu
synced 2025-08-30 05:48:05 +00:00
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>
This commit is contained in:
parent
f70ddab24e
commit
441310c260
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user