Blob Blame History Raw
From d4274171388ee9594d5ec74451e3de4ac83d9682 Mon Sep 17 00:00:00 2001
From: Alexander Mikhalitsyn <alexander.mikhalitsyn@virtuozzo.com>
Date: Fri, 24 Dec 2021 22:56:56 +0300
Subject: [PATCH 10/10] zdtm fixup: fix rseq test when linking with fresh glibc

Signed-off-by: Alexander Mikhalitsyn <alexander.mikhalitsyn@virtuozzo.com>
---
 test/zdtm/static/rseq.c | 58 ++++++++++++++++++++++++++++++++++++-----
 1 file changed, 51 insertions(+), 7 deletions(-)

diff --git a/test/zdtm/static/rseq.c b/test/zdtm/static/rseq.c
index f2fccb8f4..a679ebd7a 100644
--- a/test/zdtm/static/rseq.c
+++ b/test/zdtm/static/rseq.c
@@ -19,6 +19,32 @@
 
 #include "zdtmtst.h"
 
+#if defined(__x86_64__) && (__GLIBC__ >= 2 && __GLIBC_MINOR__ >= 34)
+#include <sys/rseq.h>
+#endif
+
+#if defined(__x86_64__) && defined(RSEQ_SIG)
+static inline void *
+thread_pointer (void)
+{
+  void *result;
+  asm ("mov %%fs:0, %0" : "=r" (result));
+  return result;
+}
+
+static inline void
+unregister_rseq_asdf (void)
+{
+	/* unregister rseq */
+	syscall(__NR_rseq, (void *)((char *) thread_pointer () + __rseq_offset), __rseq_size, 1, RSEQ_SIG);
+}
+#else
+static inline void
+unregister_rseq_asdf (void)
+{
+}
+#endif
+
 #if defined(__x86_64__)
 
 const char *test_doc = "Check that rseq() basic C/R works";
@@ -26,6 +52,8 @@ const char *test_author = "Alexander Mikhalitsyn <alexander.mikhalitsyn@virtuozz
 /* parts of code borrowed from https://www.efficios.com/blog/2019/02/08/linux-restartable-sequences/ */
 
 /* some useful definitions from kernel uapi */
+#ifndef RSEQ_SIG
+
 enum rseq_flags {
 	RSEQ_FLAG_UNREGISTER = (1 << 0),
 };
@@ -37,14 +65,22 @@ struct rseq {
 	uint32_t flags;
 } __attribute__((aligned(4 * sizeof(uint64_t))));
 
+#define RSEQ_SIG 0x53053053
+
+#endif
+
 #ifndef __NR_rseq
 #define __NR_rseq 334
 #endif
 /* EOF */
 
+#define RSEQ_TLS_ALLOC 0
+
+static volatile struct rseq *rseq_ptr;
+#if RSEQ_TLS_ALLOC
 static __thread volatile struct rseq __rseq_abi;
+#endif
 
-#define RSEQ_SIG 0x53053053
 #define TESTRSEQ 1
 #ifdef TESTRSEQ
 static int sys_rseq(volatile struct rseq *rseq_abi, uint32_t rseq_len, int flags, uint32_t sig)
@@ -55,7 +91,8 @@ static int sys_rseq(volatile struct rseq *rseq_abi, uint32_t rseq_len, int flags
 static void register_thread(void)
 {
 	int rc;
-	rc = sys_rseq(&__rseq_abi, sizeof(struct rseq), 0, RSEQ_SIG);
+	unregister_rseq_asdf();
+	rc = sys_rseq(rseq_ptr, sizeof(struct rseq), 0, RSEQ_SIG);
 	if (rc) {
 		fail("Failed to register rseq");
 		exit(1);
@@ -65,7 +102,7 @@ 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);
+	rc = sys_rseq(rseq_ptr, sizeof(struct rseq), RSEQ_FLAG_UNREGISTER, RSEQ_SIG);
 	if (rc) {
 		fail("Failed to unregister rseq");
 		exit(1);
@@ -75,7 +112,7 @@ static void unregister_thread(void)
 static void check_thread(void)
 {
 	int rc;
-	rc = sys_rseq(&__rseq_abi, sizeof(struct rseq), 0, RSEQ_SIG);
+	rc = sys_rseq(rseq_ptr, sizeof(struct rseq), 0, RSEQ_SIG);
 	if (!(rc && errno == EBUSY)) {
 		fail("Failed to check rseq %d", rc);
 		exit(1);
@@ -112,8 +149,8 @@ static int rseq_addv(intptr_t *v, intptr_t count, int cpu)
 		".popsection\n\t"
 		: /* gcc asm goto does not allow outputs */
 	       	: [cpu_id]              "r" (cpu),
-		[current_cpu_id]      "m" (__rseq_abi.cpu_id),
-		[rseq_cs]             "m" (__rseq_abi.rseq_cs),
+		[current_cpu_id]      "m" (rseq_ptr->cpu_id),
+		[rseq_cs]             "m" (rseq_ptr->rseq_cs),
 		/* final store input */
 		[v]                   "m" (*v),
 		[count]               "er" (count)
@@ -135,6 +172,13 @@ int main(int argc, char *argv[])
 	intptr_t *cpu_data;
 	long nr_cpus = sysconf(_SC_NPROCESSORS_ONLN);
 
+#if RSEQ_TLS_ALLOC
+	rseq_ptr = &__rseq_abi;
+#else
+	//rseq_ptr = malloc(sizeof(struct rseq));
+	rseq_ptr = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED, 0, 0);
+#endif
+
 	test_init(argc, argv);
 
 	cpu_data = calloc(nr_cpus, sizeof(*cpu_data));
@@ -151,7 +195,7 @@ int main(int argc, char *argv[])
 #ifdef TESTRSEQ
 	check_thread();
 
-	cpu = RSEQ_ACCESS_ONCE(__rseq_abi.cpu_id_start);
+	cpu = RSEQ_ACCESS_ONCE(rseq_ptr->cpu_id_start);
 	ret = rseq_addv(&cpu_data[cpu], 2, cpu);
 	if (ret)
 		fail("Failed to increment per-cpu counter");
-- 
2.34.1