see https://github.com/checkpoint-restore/criu/issues/1696 and https://github.com/checkpoint-restore/criu/pull/1706
178 lines
4.9 KiB
Diff
178 lines
4.9 KiB
Diff
From bb8295ae4f1224db2236fdd3134912e093ed20d9 Mon Sep 17 00:00:00 2001
|
|
From: bb-cat <ningyu9@huawei.com>
|
|
Date: Wed, 2 Mar 2022 15:10:24 +0800
|
|
Subject: [PATCH 16/16] zdtm: add rseq02 transition test with NO_RESTART CS
|
|
flag Signed-off-by: Alexander Mikhalitsyn
|
|
<alexander.mikhalitsyn@virtuozzo.com>
|
|
|
|
---
|
|
test/zdtm/transition/Makefile | 2 +
|
|
test/zdtm/transition/rseq01.c | 61 +++++++++++++++++++-
|
|
test/zdtm/transition/rseq02.c | 1 +
|
|
test/zdtm/transition/rseq02.desc | 1 +
|
|
4 files changed, 63 insertions(+), 2 deletions(-)
|
|
create mode 120000 test/zdtm/transition/rseq02.c
|
|
create mode 120000 test/zdtm/transition/rseq02.desc
|
|
|
|
diff --git a/test/zdtm/transition/Makefile b/test/zdtm/transition/Makefile
|
|
index fae4e27..378a4fc 100644
|
|
--- a/test/zdtm/transition/Makefile
|
|
+++ b/test/zdtm/transition/Makefile
|
|
@@ -24,6 +24,7 @@ TST_NOFILE = \
|
|
pid_reuse \
|
|
pidfd_store_sk \
|
|
rseq01 \
|
|
+ rseq02 \
|
|
|
|
|
|
TST_FILE = \
|
|
@@ -82,6 +83,7 @@ ptrace: LDFLAGS += -pthread
|
|
fork2: CFLAGS += -D FORK2
|
|
thread-bomb.o: CFLAGS += -pthread
|
|
thread-bomb: LDFLAGS += -pthread
|
|
+rseq02: CFLAGS += -D NOABORT
|
|
|
|
%: %.sh
|
|
cp $< $@
|
|
diff --git a/test/zdtm/transition/rseq01.c b/test/zdtm/transition/rseq01.c
|
|
index 5fac5a6..25e1d61 100644
|
|
--- a/test/zdtm/transition/rseq01.c
|
|
+++ b/test/zdtm/transition/rseq01.c
|
|
@@ -53,6 +53,18 @@ enum rseq_flags {
|
|
RSEQ_FLAG_UNREGISTER = (1 << 0),
|
|
};
|
|
|
|
+enum rseq_cs_flags_bit {
|
|
+ RSEQ_CS_FLAG_NO_RESTART_ON_PREEMPT_BIT = 0,
|
|
+ RSEQ_CS_FLAG_NO_RESTART_ON_SIGNAL_BIT = 1,
|
|
+ RSEQ_CS_FLAG_NO_RESTART_ON_MIGRATE_BIT = 2,
|
|
+};
|
|
+
|
|
+enum rseq_cs_flags {
|
|
+ RSEQ_CS_FLAG_NO_RESTART_ON_PREEMPT = (1U << RSEQ_CS_FLAG_NO_RESTART_ON_PREEMPT_BIT),
|
|
+ RSEQ_CS_FLAG_NO_RESTART_ON_SIGNAL = (1U << RSEQ_CS_FLAG_NO_RESTART_ON_SIGNAL_BIT),
|
|
+ RSEQ_CS_FLAG_NO_RESTART_ON_MIGRATE = (1U << RSEQ_CS_FLAG_NO_RESTART_ON_MIGRATE_BIT),
|
|
+};
|
|
+
|
|
struct rseq {
|
|
uint32_t cpu_id_start;
|
|
uint32_t cpu_id;
|
|
@@ -104,6 +116,7 @@ static int rseq_addv(intptr_t *v, intptr_t count, int cpu)
|
|
{
|
|
double a = 10000000000000000.0;
|
|
double b = -1;
|
|
+ uint64_t rseq_cs1, rseq_cs2;
|
|
/*test_msg("enter %f %f\n", a, b);*/
|
|
|
|
/* clang-format off */
|
|
@@ -129,6 +142,9 @@ static int rseq_addv(intptr_t *v, intptr_t count, int cpu)
|
|
"dec %%rcx\n\t"
|
|
"jnz 5b\n\t"
|
|
"fstpl %[y]\n\t"
|
|
+ "movq %%rax, %[rseq_cs_check2]\n\t"
|
|
+ "movq %[rseq_cs], %%rax\n\t"
|
|
+ "movq %%rax, %[rseq_cs_check1]\n\t"
|
|
"2:\n\t"
|
|
".pushsection __rseq_failure, \"ax\"\n\t"
|
|
/* Disassembler-friendly signature: nopl <sig>(%rip). */
|
|
@@ -143,6 +159,8 @@ static int rseq_addv(intptr_t *v, intptr_t count, int cpu)
|
|
: [cpu_id] "r" (cpu),
|
|
[current_cpu_id] "m" (rseq_ptr->cpu_id),
|
|
[rseq_cs] "m" (rseq_ptr->rseq_cs),
|
|
+ [rseq_cs_check1] "m" (rseq_cs1),
|
|
+ [rseq_cs_check2] "m" (rseq_cs2),
|
|
/* final store input */
|
|
[v] "m" (*v),
|
|
[count] "er" (count),
|
|
@@ -153,8 +171,20 @@ static int rseq_addv(intptr_t *v, intptr_t count, int cpu)
|
|
);
|
|
/* clang-format on */
|
|
/*test_msg("exit %f %f\n", a, b);*/
|
|
+ test_msg("%lx %lx\n", rseq_cs1, rseq_cs2);
|
|
+ if (rseq_cs1 != rseq_cs2) {
|
|
+ /*
|
|
+ * It means that we finished critical section
|
|
+ * *normally* (haven't jumped to abort) but the kernel had cleaned up
|
|
+ * rseq_ptr->rseq_cs before we left critical section
|
|
+ * and CRIU wasn't restored it correctly.
|
|
+ * That's a bug picture.
|
|
+ */
|
|
+ return -1;
|
|
+ }
|
|
return 0;
|
|
abort:
|
|
+ test_msg("%lx %lx\n", rseq_cs1, rseq_cs2);
|
|
/*test_msg("abort %f %f\n", a, b);*/
|
|
return -1;
|
|
}
|
|
@@ -177,21 +207,48 @@ int main(int argc, char *argv[])
|
|
fail("calloc");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
+
|
|
register_thread();
|
|
|
|
+ /*
|
|
+ * We want to test that RSEQ_CS_FLAG_NO_RESTART_ON_SIGNAL
|
|
+ * is handled properly by CRIU, but that flag can be used
|
|
+ * only with all another flags set.
|
|
+ * Please, refer to
|
|
+ * https://github.com/torvalds/linux/blob/master/kernel/rseq.c#L192
|
|
+ */
|
|
+#ifdef NOABORT
|
|
+ rseq_ptr->flags = RSEQ_CS_FLAG_NO_RESTART_ON_PREEMPT |
|
|
+ RSEQ_CS_FLAG_NO_RESTART_ON_SIGNAL |
|
|
+ RSEQ_CS_FLAG_NO_RESTART_ON_MIGRATE;
|
|
+#endif
|
|
+
|
|
test_daemon();
|
|
|
|
while (test_go()) {
|
|
cpu = RSEQ_ACCESS_ONCE(rseq_ptr->cpu_id_start);
|
|
ret = rseq_addv(&cpu_data[cpu], 2, cpu);
|
|
- if (ret)
|
|
+#ifndef NOABORT
|
|
+ /* just ignore abort */
|
|
+ ret = 0;
|
|
+#else
|
|
+ if (ret) {
|
|
fail("Failed to increment per-cpu counter");
|
|
+ break;
|
|
+ } else {
|
|
+ //test_msg("cpu_data[%d] == %ld\n", cpu, (long int)cpu_data[cpu]);
|
|
+ }
|
|
+#endif
|
|
}
|
|
|
|
test_waitsig();
|
|
|
|
check_thread();
|
|
- pass();
|
|
+
|
|
+ if (ret)
|
|
+ fail();
|
|
+ else
|
|
+ pass();
|
|
|
|
return 0;
|
|
}
|
|
diff --git a/test/zdtm/transition/rseq02.c b/test/zdtm/transition/rseq02.c
|
|
new file mode 120000
|
|
index 0000000..d564917
|
|
--- /dev/null
|
|
+++ b/test/zdtm/transition/rseq02.c
|
|
@@ -0,0 +1 @@
|
|
+rseq01.c
|
|
\ No newline at end of file
|
|
diff --git a/test/zdtm/transition/rseq02.desc b/test/zdtm/transition/rseq02.desc
|
|
new file mode 120000
|
|
index 0000000..b888f0d
|
|
--- /dev/null
|
|
+++ b/test/zdtm/transition/rseq02.desc
|
|
@@ -0,0 +1 @@
|
|
+rseq01.desc
|
|
\ No newline at end of file
|
|
--
|
|
2.30.0
|
|
|