[CRIU] [PATCH] ppc64: Fix checkpoint --leave-running

Laurent Dufour ldufour at linux.vnet.ibm.com
Tue Sep 8 02:43:16 PDT 2015


The commit ba7435095417 which introduces support for Altivec and VSX
support was breaking the checkpoint --leave-running.

The root cause is that the address of the Altivec and VSX registers in the
signal frame should be computed for the stack in the context of the
checkpointed process.

This patch fixes this issue through the sigreturn_prep_fpu_frame which is
designed to update the signal frame based on the remote address.

Fixes: ba7435095417 ("ppc64: Add Altivec and VSX support")
Reported-by: Andrey Vagin <avagin at openvz.org>
Signed-off-by: Laurent Dufour <ldufour at linux.vnet.ibm.com>
---
 arch/ppc64/crtools.c              | 23 +++++++++++++++++++++++
 arch/ppc64/include/asm/restorer.h |  7 ++-----
 2 files changed, 25 insertions(+), 5 deletions(-)

diff --git a/arch/ppc64/crtools.c b/arch/ppc64/crtools.c
index 7fcc076dcab8..c7e6606f10ac 100644
--- a/arch/ppc64/crtools.c
+++ b/arch/ppc64/crtools.c
@@ -227,6 +227,7 @@ static int put_altivec_regs(mcontext_t *mc, UserPpc64VrstateEntry *vse)
 	vrregset_t *v_regs = (vrregset_t *)(((unsigned long)mc->vmx_reserve + 15) & ~0xful);
 
 	pr_debug("Restoring Altivec registers\n");
+
 	if (vse->n_vrregs != 33*2) {
 		pr_err("Corrupted Altivec dump data");
 		return -1;
@@ -275,6 +276,8 @@ static int get_vsx_regs(pid_t pid, CoreEntry *core)
 		return -1;
 	}
 
+	pr_debug("Dumping VSX registers\n");
+
 	vse = xmalloc(sizeof(*vse));
 	if (!vse)
 		return -1;
@@ -465,6 +468,26 @@ int restore_fpu(struct rt_sigframe *sigframe, CoreEntry *core)
 	return ret;
 }
 
+/*
+ * The signal frame has been built using local addresses. Since it has to be
+ * used in the context of the checkpointed process, the v_regs pointer in the
+ * signal frame must be updated to match the address in the remote stack.
+ */
+int sigreturn_prep_fpu_frame(struct rt_sigframe *frame, mcontext_t *rcontext)
+{
+	mcontext_t *lcontext = &frame->uc.uc_mcontext;
+
+	if (lcontext->v_regs) {
+		uint64_t offset = (uint64_t)(lcontext->v_regs) - (uint64_t)lcontext;
+		lcontext->v_regs = (vrregset_t *)((uint64_t)rcontext + offset);
+
+		pr_debug("Updated v_regs:%llx (rcontext:%llx)\n",
+			 (unsigned long long) lcontext->v_regs,
+			 (unsigned long long) rcontext);
+	}
+	return 0;
+}
+
 int restore_gpregs(struct rt_sigframe *f, UserPpc64RegsEntry *r)
 {
 	int i;
diff --git a/arch/ppc64/include/asm/restorer.h b/arch/ppc64/include/asm/restorer.h
index d4560f74cf29..e728f133535e 100644
--- a/arch/ppc64/include/asm/restorer.h
+++ b/arch/ppc64/include/asm/restorer.h
@@ -122,11 +122,8 @@ static inline int ptrace_flush_breakpoints(pid_t pid)
         return 0;
 }
 
-static inline int sigreturn_prep_fpu_frame(struct rt_sigframe *sigframe,
-					   mcontext_t *sigcontext)
-{
-	return 0;
-}
+int sigreturn_prep_fpu_frame(struct rt_sigframe *sigframe,
+			     mcontext_t *sigcontext);
 
 /*
  * Defined in arch/ppc64/syscall-common-ppc64.S
-- 
1.9.1



More information about the CRIU mailing list