mirror of
https://github.com/checkpoint-restore/criu.git
synced 2026-01-23 02:14:37 +00:00
zdtm: add rseq02 transition test with NO_RESTART CS flag
Signed-off-by: Alexander Mikhalitsyn <alexander.mikhalitsyn@virtuozzo.com>
This commit is contained in:
parent
1e0bed3d69
commit
db9ec13616
4 changed files with 51 additions and 0 deletions
|
|
@ -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 NORESTART
|
||||
|
||||
%: %.sh
|
||||
cp $< $@
|
||||
|
|
|
|||
|
|
@ -58,6 +58,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;
|
||||
|
|
@ -111,6 +123,7 @@ static int rseq_addv(intptr_t *v, intptr_t count, int cpu)
|
|||
{
|
||||
double a = 10000000000000000.0;
|
||||
double b = -1;
|
||||
uint64_t rseq_cs1 = 0, rseq_cs2 = 0;
|
||||
|
||||
/* clang-format off */
|
||||
__asm__ __volatile__ goto(
|
||||
|
|
@ -134,6 +147,9 @@ static int rseq_addv(intptr_t *v, intptr_t count, int cpu)
|
|||
"fsqrt\n\t" /* heavy instruction */
|
||||
"dec %%rcx\n\t"
|
||||
"jnz 5b\n\t"
|
||||
"movq %%rax, %[rseq_cs_check2]\n\t"
|
||||
"movq %[rseq_cs], %%rax\n\t"
|
||||
"movq %%rax, %[rseq_cs_check1]\n\t"
|
||||
"fstpl %[y]\n\t"
|
||||
"2:\n\t"
|
||||
".pushsection __rseq_failure, \"ax\"\n\t"
|
||||
|
|
@ -149,6 +165,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),
|
||||
|
|
@ -159,9 +177,22 @@ static int rseq_addv(intptr_t *v, intptr_t count, int cpu)
|
|||
);
|
||||
/* clang-format on */
|
||||
rseq_after_asm_goto();
|
||||
test_msg("exit %lx %lx %f %f\n", rseq_cs1, rseq_cs2, a, b);
|
||||
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 didn't restore it correctly.
|
||||
* That's a bug picture.
|
||||
*/
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
abort:
|
||||
rseq_after_asm_goto();
|
||||
test_msg("abort %lx %lx %f %f\n", rseq_cs1, rseq_cs2, a, b);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
@ -183,16 +214,32 @@ 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/ce522ba9/kernel/rseq.c#L192
|
||||
*/
|
||||
#ifdef NORESTART
|
||||
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);
|
||||
|
||||
/* NORESTART is NOT set */
|
||||
#ifndef NORESTART
|
||||
/* just ignore abort */
|
||||
ret = 0;
|
||||
#endif
|
||||
|
||||
if (ret)
|
||||
break;
|
||||
|
|
|
|||
1
test/zdtm/transition/rseq02.c
Symbolic link
1
test/zdtm/transition/rseq02.c
Symbolic link
|
|
@ -0,0 +1 @@
|
|||
rseq01.c
|
||||
1
test/zdtm/transition/rseq02.desc
Symbolic link
1
test/zdtm/transition/rseq02.desc
Symbolic link
|
|
@ -0,0 +1 @@
|
|||
rseq01.desc
|
||||
Loading…
Add table
Add a link
Reference in a new issue