[CRIU] [PATCH RFC] compel: Save thread registers before executing parasite code

Dmitry Safonov 0x7f454c46 at gmail.com
Wed Jul 19 23:05:38 MSK 2017


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.

>
>         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