see https://github.com/checkpoint-restore/criu/issues/1696 and https://github.com/checkpoint-restore/criu/pull/1706
218 lines
5.2 KiB
Diff
218 lines
5.2 KiB
Diff
From 5005c08e32dc29dbf0b3a2a582e75d249c190d96 Mon Sep 17 00:00:00 2001
|
|
From: bb-cat <ningyu9@huawei.com>
|
|
Date: Wed, 2 Mar 2022 14:54:28 +0800
|
|
Subject: [PATCH 07/16] zdtm: add simple test for rseq C/R Signed-off-by:
|
|
Alexander Mikhalitsyn <alexander.mikhalitsyn@virtuozzo.com>
|
|
|
|
---
|
|
test/zdtm/static/Makefile | 1 +
|
|
test/zdtm/static/rseq00.c | 174 +++++++++++++++++++++++
|
|
test/zdtm/static/rseq00.desc | 1 +
|
|
3 files changed, 176 insertions(+)
|
|
create mode 100644 test/zdtm/static/rseq00.c
|
|
create mode 100644 test/zdtm/static/rseq00.desc
|
|
|
|
diff --git a/test/zdtm/static/Makefile b/test/zdtm/static/Makefile
|
|
index 70123cf..563d947 100644
|
|
--- a/test/zdtm/static/Makefile
|
|
+++ b/test/zdtm/static/Makefile
|
|
@@ -61,6 +61,7 @@ TST_NOFILE := \
|
|
pthread02 \
|
|
pthread_timers \
|
|
pthread_timers_h \
|
|
+ rseq00 \
|
|
vdso00 \
|
|
vdso01 \
|
|
vdso02 \
|
|
diff --git a/test/zdtm/static/rseq00.c b/test/zdtm/static/rseq00.c
|
|
new file mode 100644
|
|
index 0000000..26f41a2
|
|
--- /dev/null
|
|
+++ b/test/zdtm/static/rseq00.c
|
|
@@ -0,0 +1,174 @@
|
|
+/*
|
|
+ * test for rseq() syscall
|
|
+ * See also https://www.efficios.com/blog/2019/02/08/linux-restartable-sequences/
|
|
+ * https://github.com/torvalds/linux/commit/d7822b1e24f2df5df98c76f0e94a5416349ff759
|
|
+ */
|
|
+#include <stdio.h>
|
|
+#include <stdlib.h>
|
|
+#include <unistd.h>
|
|
+#include <signal.h>
|
|
+#include <string.h>
|
|
+
|
|
+#include <sys/types.h>
|
|
+#include <sys/wait.h>
|
|
+#include <sys/stat.h>
|
|
+#include <sys/mman.h>
|
|
+#include <fcntl.h>
|
|
+#include <pthread.h>
|
|
+#include <syscall.h>
|
|
+
|
|
+#include "zdtmtst.h"
|
|
+
|
|
+#if defined(__x86_64__)
|
|
+
|
|
+const char *test_doc = "Check that rseq() basic C/R works";
|
|
+const char *test_author = "Alexander Mikhalitsyn <alexander.mikhalitsyn@virtuozzo.com>";
|
|
+/* parts of code borrowed from https://www.efficios.com/blog/2019/02/08/linux-restartable-sequences/ */
|
|
+
|
|
+/* some useful definitions from kernel uapi */
|
|
+enum rseq_flags {
|
|
+ RSEQ_FLAG_UNREGISTER = (1 << 0),
|
|
+};
|
|
+
|
|
+struct rseq {
|
|
+ uint32_t cpu_id_start;
|
|
+ uint32_t cpu_id;
|
|
+ uint64_t rseq_cs;
|
|
+ uint32_t flags;
|
|
+} __attribute__((aligned(4 * sizeof(uint64_t))));
|
|
+
|
|
+#ifndef __NR_rseq
|
|
+#define __NR_rseq 334
|
|
+#endif
|
|
+/* EOF */
|
|
+
|
|
+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);
|
|
+}
|
|
+
|
|
+static void register_thread(void)
|
|
+{
|
|
+ int rc;
|
|
+ rc = sys_rseq(&__rseq_abi, sizeof(struct rseq), 0, RSEQ_SIG);
|
|
+ if (rc) {
|
|
+ fail("Failed to register rseq");
|
|
+ exit(1);
|
|
+ }
|
|
+}
|
|
+
|
|
+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;
|
|
+ rc = sys_rseq(&__rseq_abi, sizeof(struct rseq), 0, RSEQ_SIG);
|
|
+ if (!(rc && errno == EBUSY)) {
|
|
+ fail("Failed to check rseq %d", rc);
|
|
+ exit(1);
|
|
+ }
|
|
+}
|
|
+
|
|
+#define RSEQ_ACCESS_ONCE(x) (*(__volatile__ __typeof__(x) *)&(x))
|
|
+
|
|
+static int rseq_addv(intptr_t *v, intptr_t count, int cpu)
|
|
+{
|
|
+ /* clang-format off */
|
|
+ __asm__ __volatile__ goto(
|
|
+ ".pushsection __rseq_table, \"aw\"\n\t"
|
|
+ ".balign 32\n\t"
|
|
+ "cs_obj:\n\t"
|
|
+ /* version, flags */
|
|
+ ".long 0, 0\n\t"
|
|
+ /* start_ip, post_commit_ip, abort_ip */
|
|
+ ".quad 1f, (2f-1f), 4f\n\t"
|
|
+ ".popsection\n\t"
|
|
+ "1:\n\t"
|
|
+ "leaq cs_obj(%%rip), %%rax\n\t"
|
|
+ "movq %%rax, %[rseq_cs]\n\t"
|
|
+ "cmpl %[cpu_id], %[current_cpu_id]\n\t"
|
|
+ "jnz 4f\n\t"
|
|
+ "addq %[count], %[v]\n\t" /* final store */
|
|
+ "2:\n\t"
|
|
+ ".pushsection __rseq_failure, \"ax\"\n\t"
|
|
+ /* Disassembler-friendly signature: nopl <sig>(%rip). */
|
|
+ ".byte 0x0f, 0x1f, 0x05\n\t"
|
|
+ ".long 0x53053053\n\t" /* RSEQ_FLAGS */
|
|
+ "4:\n\t"
|
|
+ "jmp abort\n\t"
|
|
+ ".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),
|
|
+ /* final store input */
|
|
+ [v] "m" (*v),
|
|
+ [count] "er" (count)
|
|
+ : "memory", "cc", "rax"
|
|
+ : abort
|
|
+ );
|
|
+ /* clang-format on */
|
|
+
|
|
+ return 0;
|
|
+abort:
|
|
+ return -1;
|
|
+}
|
|
+
|
|
+int main(int argc, char *argv[])
|
|
+{
|
|
+ int cpu, ret;
|
|
+ intptr_t *cpu_data;
|
|
+ long nr_cpus = sysconf(_SC_NPROCESSORS_ONLN);
|
|
+
|
|
+ test_init(argc, argv);
|
|
+
|
|
+ cpu_data = calloc(nr_cpus, sizeof(*cpu_data));
|
|
+ if (!cpu_data) {
|
|
+ fail("calloc");
|
|
+ exit(EXIT_FAILURE);
|
|
+ }
|
|
+
|
|
+ register_thread();
|
|
+
|
|
+ test_daemon();
|
|
+ test_waitsig();
|
|
+
|
|
+ check_thread();
|
|
+
|
|
+ cpu = RSEQ_ACCESS_ONCE(__rseq_abi.cpu_id_start);
|
|
+ ret = rseq_addv(&cpu_data[cpu], 2, cpu);
|
|
+ if (ret)
|
|
+ fail("Failed to increment per-cpu counter");
|
|
+ else
|
|
+ test_msg("cpu_data[%d] == %ld\n", cpu, (long int)cpu_data[cpu]);
|
|
+
|
|
+ if (cpu_data[cpu] == 2)
|
|
+ pass();
|
|
+ else
|
|
+ fail();
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+#else
|
|
+
|
|
+int main(int argc, char *argv[])
|
|
+{
|
|
+ test_init(argc, argv);
|
|
+ skip("Unsupported arch");
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+#endif
|
|
\ No newline at end of file
|
|
diff --git a/test/zdtm/static/rseq00.desc b/test/zdtm/static/rseq00.desc
|
|
new file mode 100644
|
|
index 0000000..0324fa3
|
|
--- /dev/null
|
|
+++ b/test/zdtm/static/rseq00.desc
|
|
@@ -0,0 +1 @@
|
|
+{'flavor': 'h', 'arch': 'x86_64', 'feature': 'get_rseq_conf'}
|
|
--
|
|
2.30.0
|
|
|