[CRIU] [PATCH RFC] compel: Save thread registers before executing parasite code
Dmitry Safonov
0x7f454c46 at gmail.com
Wed Jul 19 23:20:59 MSK 2017
2017-07-19 23:05 GMT+03:00 Dmitry Safonov <0x7f454c46 at gmail.com>:
> 2017-07-19 21:54 GMT+03:00 Michael Holzheu <holzheu at linux.vnet.ibm.com>:
>> For dumping threads we execute parasite code before we collect the
>> floating point registers with get_task_regs().
>>
>> The following describes the code path were this is done:
>>
>> dump_task_threads()
>> for (i = 0; i < item->nr_threads; i++)
>> dump_task_thread()
>> parasite_dump_thread_seized()
>> compel_prepare_thread()
>> prepare_thread()
>>
>> ### Get general purpose registers ###
>> ptrace_get_regs(ctx->regs)
>>
>> ### Parasite code is executed in thread ###
>> compel_run_in_thread(tctl, PARASITE_CMD_DUMP_THREAD)
>>
>> compel_get_thread_regs()
>>
>> ### Get FP and VX registers ###
>> get_task_regs()
>>
>> On s390 gcc uses floating point registers to cache general purpose
>> registers. Therefore we use the -msoft-float option to ensure that
>> floating point registers are not clobbered in compel_run_in_thread().
>>
>> There might be a better option:
>>
>> First save the thread registers and then call the parasite code. This
>> allows us to remove the -msoft-float on s390.
>>
>> Signed-off-by: Michael Holzheu <holzheu at linux.vnet.ibm.com>
>> ---
>> Makefile.compel | 4 ++--
>> criu/parasite-syscall.c | 11 +++++------
>> criu/pie/Makefile | 7 -------
>> criu/pie/Makefile.library | 6 ------
>> 4 files changed, 7 insertions(+), 21 deletions(-)
>>
>> diff --git a/Makefile.compel b/Makefile.compel
>> index 5c854e3..d200cb8 100644
>> --- a/Makefile.compel
>> +++ b/Makefile.compel
>> @@ -77,6 +77,6 @@ compel-install-targets += $(compel-plugins)
>> # commit "S/390: Fix 64 bit sibcall".
>> #
>> ifeq ($(ARCH),s390)
>> -CFLAGS += -msoft-float -fno-optimize-sibling-calls
>> -HOSTCFLAGS += -msoft-float -fno-optimize-sibling-calls
>> +CFLAGS += -fno-optimize-sibling-calls
>> +HOSTCFLAGS += -fno-optimize-sibling-calls
>> endif
>> diff --git a/criu/parasite-syscall.c b/criu/parasite-syscall.c
>> index 69dba60..76e943e 100644
>> --- a/criu/parasite-syscall.c
>> +++ b/criu/parasite-syscall.c
>> @@ -198,6 +198,11 @@ int parasite_dump_thread_seized(struct parasite_ctl *ctl, const struct pstree_it
>>
>> tc->has_blk_sigset = true;
>> memcpy(&tc->blk_sigset, compel_thread_sigmask(tctl), sizeof(k_rtsigset_t));
>> + ret = compel_get_thread_regs(tctl, save_task_regs, core);
>> + if (ret) {
>> + pr_err("Can't obtain regs for thread %d\n", pid);
>> + goto err_rth;
>> + }
>
> That *looks* not very correct by the following reason:
>
> ucontext_extended has fpu/vxr registers on it, so for the *task*
> they will be restored on parasite's CMD_FINI.
> And you get them before running parasite in a task - that's ok.
>
> But from the point of *thread*'s view - you dump them here,
> run parasite inside thread, which can change fpu/vxr, but only
> restore generic registers after (parasite_run()=>ptrace_set_regs()).
>
> That means that dumping thread's core may corrupt fpu/vxr, which
> will break as the result --leave-running and err-path recovery curing
> for the parasite.
>
> Please, also correct comment near ptrace_get_regs() for s390.
And if you want to verify that all works as expected, I would suggest
to add fpu03 s390-version test having as an example x86 versions
test/zdtm/static/{fpu00.c,fpu01.c}.
Also might be worth if the test would have a couple of threads, to
check the mentioned issue.
>
>>
>> ret = compel_run_in_thread(tctl, PARASITE_CMD_DUMP_THREAD);
>> if (ret) {
>> @@ -211,12 +216,6 @@ int parasite_dump_thread_seized(struct parasite_ctl *ctl, const struct pstree_it
>> goto err_rth;
>> }
>>
>> - ret = compel_get_thread_regs(tctl, save_task_regs, core);
>> - if (ret) {
>> - pr_err("Can't obtain regs for thread %d\n", pid);
>> - goto err_rth;
>> - }
>> -
>> compel_release_thread(tctl);
>>
>> *parasite_tid = args->tid;
>> diff --git a/criu/pie/Makefile b/criu/pie/Makefile
>> index 76c3535..73d95d5 100644
>> --- a/criu/pie/Makefile
>> +++ b/criu/pie/Makefile
>> @@ -16,13 +16,6 @@ ifeq ($(SRCARCH),arm)
>> ccflags-y += -marm
>> endif
>>
>> -# We assume that compel code does not change floating point registers.
>> -# On s390 gcc uses fprs to cache gprs. Therefore disable floating point
>> -# with -msoft-float.
>> -ifeq ($(SRCARCH),s390)
>> - ccflags-y += -msoft-float
>> -endif
>> -
>> asflags-y += -D__ASSEMBLY__
>>
>> LDS := compel/arch/$(SRCARCH)/scripts/compel-pack.lds.S
>> diff --git a/criu/pie/Makefile.library b/criu/pie/Makefile.library
>> index ceadc1d..f589333 100644
>> --- a/criu/pie/Makefile.library
>> +++ b/criu/pie/Makefile.library
>> @@ -41,9 +41,3 @@ ccflags-y += $(COMPEL_UAPI_INCLUDES)
>> ifeq ($(SRCARCH),arm)
>> ccflags-y += -marm
>> endif
>> -# We assume that compel code does not change floating point registers.
>> -# On s390 gcc uses fprs to cache gprs. Therefore disable floating point
>> -# with -msoft-float.
>> -ifeq ($(SRCARCH),s390)
>> - ccflags-y += -msoft-float
>> -endif
--
Dmitry
More information about the CRIU
mailing list