[CRIU] [PATCH v2 5/6] ppc64: Extract copy to protobuf functions

Laurent Dufour ldufour at linux.vnet.ibm.com
Wed Aug 31 09:15:12 PDT 2016


Since the Transactional memory state will contains VSX, VMX and FP
registers, extracting the common code copying data to protobuf buffer in
separate functions.

Signed-off-by: Laurent Dufour <ldufour at linux.vnet.ibm.com>
---
 criu/arch/ppc64/crtools.c | 319 ++++++++++++++++++++++++++--------------------
 1 file changed, 179 insertions(+), 140 deletions(-)

diff --git a/criu/arch/ppc64/crtools.c b/criu/arch/ppc64/crtools.c
index fbd043fa191c..7463366891ad 100644
--- a/criu/arch/ppc64/crtools.c
+++ b/criu/arch/ppc64/crtools.c
@@ -84,6 +84,30 @@ int syscall_seized(struct parasite_ctl *ctl, int nr, unsigned long *ret,
 	return err;
 }
 
+static UserPpc64FpstateEntry *copy_fp_regs(uint64_t *fpregs)
+{
+	UserPpc64FpstateEntry *fpe;
+	int i;
+
+	fpe = xmalloc(sizeof(UserPpc64FpstateEntry));
+	if (!fpe)
+		return NULL;
+	user_ppc64_fpstate_entry__init(fpe);
+
+	fpe->n_fpregs = NFPREG;
+	fpe->fpregs = xmalloc(fpe->n_fpregs * sizeof(fpe->fpregs[0]));
+	if (!fpe->fpregs) {
+		xfree(fpe);
+		return NULL;
+	}
+
+	/* FPSRC is the last (33th) register in the set */
+	for (i = 0; i < NFPREG; i++)
+		fpe->fpregs[i] = fpregs[i];
+
+	return fpe;
+}
+
 /* This is the layout of the POWER7 VSX registers and the way they
  * overlap with the existing FPR and VMX registers.
  *
@@ -121,37 +145,18 @@ int syscall_seized(struct parasite_ctl *ctl, int nr, unsigned long *ret,
  * word registers are saved through FPR[0..32] and the remaining registers
  * are saved when saving the Altivec registers VR[0..32].
  */
-#define NVSXREG		32
+#define NVSXREG	32
 
-static int get_fpu_regs(pid_t pid, CoreEntry *core)
+static UserPpc64FpstateEntry *get_fpu_regs(pid_t pid)
 {
 	uint64_t fpregs[NFPREG];
-	UserPpc64FpstateEntry *fpe;
-	int i;
 
 	if (ptrace(PTRACE_GETFPREGS, pid, 0, (void *)&fpregs) < 0) {
 		pr_perror("Couldn't get floating-point registers");
-		return -1;
+		return NULL;;
 	}
 
-	fpe = xmalloc(sizeof(UserPpc64FpstateEntry));
-	if (!fpe)
-		return -1;
-	user_ppc64_fpstate_entry__init(fpe);
-
-	fpe->n_fpregs = NFPREG;
-	fpe->fpregs = xmalloc(fpe->n_fpregs * sizeof(fpe->fpregs[0]));
-	if (!fpe->fpregs) {
-		xfree(fpe);
-		return -1;
-	}
-
-	/* FPSRC is the last (33th) register in the set */
-	for (i = 0; i < NFPREG; i++)
-		fpe->fpregs[i] = fpregs[i];
-
-	core->ti_ppc64->fpstate = fpe;
-	return 0;
+	return copy_fp_regs(fpregs);
 }
 
 static void put_fpu_regs(mcontext_t *mc, UserPpc64FpstateEntry *fpe)
@@ -163,39 +168,16 @@ static void put_fpu_regs(mcontext_t *mc, UserPpc64FpstateEntry *fpe)
 		mcfp[i] =  fpe->fpregs[i];
 }
 
-static int get_altivec_regs(pid_t pid, CoreEntry *core)
+static UserPpc64VrstateEntry *copy_altivec_regs(unsigned char *vrregs)
 {
-	/* The kernel returns :
-	 *   32 Vector registers (128bit)
-	 *   VSCR (32bit) stored in a 128bit entry (odd)
-	 *   VRSAVE (32bit) store at the end.
-	 *
-	 * Kernel setup_sigcontext's comment mentions:
-	 * "Userland shall check AT_HWCAP to know whether it can rely on the
-	 * v_regs pointer or not"
-	 */
-	unsigned char vrregs[(NVRREG-1) * 16 + 4];
 	UserPpc64VrstateEntry *vse;
 	uint64_t *p64;
 	uint32_t *p32;
 	int i;
 
-	if (ptrace(PTRACE_GETVRREGS, pid, 0, (void*)&vrregs) < 0) {
-		/* PTRACE_GETVRREGS returns EIO if Altivec is not supported.
-		 * This should not happen if msr_vec is set. */
-		if (errno != EIO) {
-			pr_perror("Couldn't get Altivec registers");
-			return -1;
-		}
-		pr_debug("Altivec not supported\n");
-		return 0;
-	}
-
-	pr_debug("Dumping Altivec registers\n");
-
 	vse = xmalloc(sizeof(*vse));
 	if (!vse)
-		return -1;
+		return NULL;
 	user_ppc64_vrstate_entry__init(vse);
 
 	/* protocol buffer store only 64bit entries and we need 128bit */
@@ -203,7 +185,7 @@ static int get_altivec_regs(pid_t pid, CoreEntry *core)
 	vse->vrregs = xmalloc(vse->n_vrregs * sizeof(vse->vrregs[0]));
 	if (!vse->vrregs) {
 		xfree(vse);
-		return -1;
+		return NULL;
 	}
 
 	/* Vectors are 2*64bits entries */
@@ -216,15 +198,36 @@ static int get_altivec_regs(pid_t pid, CoreEntry *core)
 	p32 = (uint32_t*) &vrregs[(NVRREG-1) * 2 * sizeof(uint64_t)];
 	vse->vrsave = *p32;
 
-	core->ti_ppc64->vrstate = vse;
+	return vse;
+}
 
-	/*
-	 * Force the MSR_VEC bit of the restored MSR otherwise the kernel
-	 * will not restore them from the signal frame.
+static UserPpc64VrstateEntry *get_altivec_regs(pid_t pid)
+{
+	/* The kernel returns :
+	 *   32 Vector registers (128bit)
+	 *   VSCR (32bit) stored in a 128bit entry (odd)
+	 *   VRSAVE (32bit) store at the end.
+	 *
+	 * Kernel setup_sigcontext's comment mentions:
+	 * "Userland shall check AT_HWCAP to know whether it can rely on the
+	 * v_regs pointer or not"
 	 */
-	core->ti_ppc64->gpregs->msr |= MSR_VEC;
+	unsigned char vrregs[(NVRREG-1) * 16 + 4];
 
-	return 0;
+	if (ptrace(PTRACE_GETVRREGS, pid, 0, (void*)&vrregs) < 0) {
+		/* PTRACE_GETVRREGS returns EIO if Altivec is not supported.
+		 * This should not happen if msr_vec is set. */
+		if (errno != EIO) {
+			pr_perror("Couldn't get Altivec registers");
+			return (UserPpc64VrstateEntry*)-1L;
+		}
+		pr_debug("Altivec not supported\n");
+		return NULL;
+	}
+
+	pr_debug("Dumping Altivec registers\n");
+
+	return copy_altivec_regs(vrregs);
 }
 
 static int put_altivec_regs(mcontext_t *mc, UserPpc64VrstateEntry *vse)
@@ -254,6 +257,30 @@ static int put_altivec_regs(mcontext_t *mc, UserPpc64VrstateEntry *vse)
 	return 0;
 }
 
+static UserPpc64VsxstateEntry* copy_vsx_regs(uint64_t *vsregs)
+{
+	UserPpc64VsxstateEntry *vse;
+	int i;
+
+	vse = xmalloc(sizeof(*vse));
+	if (!vse)
+		return NULL;
+
+	user_ppc64_vsxstate_entry__init(vse);
+	vse->n_vsxregs = NVSXREG;
+
+	vse->vsxregs = xmalloc(vse->n_vsxregs*sizeof(vse->vsxregs[0]));
+	if (!vse->vsxregs) {
+		xfree(vse);
+		return NULL;
+	}
+
+	for (i = 0; i < vse->n_vsxregs; i++)
+		vse->vsxregs[i] = vsregs[i];
+
+	return vse;
+}
+
 /*
  * Since the FPR[0-31] is stored in the first double word of VSR[0-31] and
  * FPR are saved through the FP state, there is no need to save the upper part
@@ -263,11 +290,9 @@ static int put_altivec_regs(mcontext_t *mc, UserPpc64VrstateEntry *vse)
  * As a consequence, only the doubleword 1 of the 32 first VSX registers have
  * to be saved (the ones are returned by PTRACE_GETVSRREGS).
  */
-static int get_vsx_regs(pid_t pid, CoreEntry *core)
+static UserPpc64VsxstateEntry *get_vsx_regs(pid_t pid)
 {
-	UserPpc64VsxstateEntry *vse;
 	uint64_t vsregs[NVSXREG];
-	int i;
 
 	if (ptrace(PTRACE_GETVSRREGS, pid, 0, (void*)&vsregs) < 0) {
 		/*
@@ -279,34 +304,11 @@ static int get_vsx_regs(pid_t pid, CoreEntry *core)
 			return 0;
 		}
 		pr_perror("Couldn't get VSX registers");
-		return -1;
+		return (UserPpc64VsxstateEntry *)-1L;
 	}
 
 	pr_debug("Dumping VSX registers\n");
-
-	vse = xmalloc(sizeof(*vse));
-	if (!vse)
-		return -1;
-	user_ppc64_vsxstate_entry__init(vse);
-
-	vse->n_vsxregs = NVSXREG;
-	vse->vsxregs = xmalloc(vse->n_vsxregs * sizeof(vse->vsxregs[0]));
-	if (!vse->vsxregs) {
-		xfree(vse);
-		return -1;
-	}
-
-	for (i = 0; i < vse->n_vsxregs; i++)
-		vse->vsxregs[i] = vsregs[i];
-
-	core->ti_ppc64->vsxstate = vse;
-
-	/*
-	 * Force the MSR_VSX bit of the restored MSR otherwise the kernel
-	 * will not restore them from the signal frame.
-	 */
-	core->ti_ppc64->gpregs->msr |= MSR_VSX;
-	return 0;
+	return copy_vsx_regs(vsregs);
 }
 
 static int put_vsx_regs(mcontext_t *mc, UserPpc64VsxstateEntry *vse)
@@ -331,10 +333,67 @@ static int put_vsx_regs(mcontext_t *mc, UserPpc64VsxstateEntry *vse)
 	return 0;
 }
 
-int get_task_regs(pid_t pid, user_regs_struct_t regs, CoreEntry *core)
+
+static void copy_gp_regs(UserPpc64RegsEntry *dst, user_regs_struct_t *src)
 {
 	int i;
 
+#define assign_reg(e) do {			\
+	dst->e = (__typeof__(dst->e))src->e;	\
+} while (0)
+
+	for (i=0; i<32; i++)
+		assign_reg(gpr[i]);
+	assign_reg(nip);
+	assign_reg(msr);
+	assign_reg(orig_gpr3);
+	assign_reg(ctr);
+	assign_reg(link);
+	assign_reg(xer);
+	assign_reg(ccr);
+	assign_reg(trap);
+#undef assign_reg
+}
+
+static void restore_gp_regs(mcontext_t *dst, UserPpc64RegsEntry *src)
+{
+	int i;
+
+	/* r0 to r31 */
+	for (i=0; i<32; i++)
+		dst->gp_regs[i] 	= src->gpr[i];
+
+	dst->gp_regs[PT_NIP] 		= src->nip;
+	dst->gp_regs[PT_MSR] 		= src->msr;
+	dst->gp_regs[PT_ORIG_R3]	= src->orig_gpr3;
+	dst->gp_regs[PT_CTR] 		= src->ctr;
+	dst->gp_regs[PT_LNK] 		= src->link;
+	dst->gp_regs[PT_XER] 		= src->xer;
+	dst->gp_regs[PT_CCR] 		= src->ccr;
+	dst->gp_regs[PT_TRAP] 		= src->trap;
+}
+
+static UserPpc64RegsEntry *allocate_gp_regs(void)
+{
+	UserPpc64RegsEntry *gpregs;
+
+	gpregs = xmalloc(sizeof(*gpregs));
+	if (!gpregs)
+		return NULL;
+	user_ppc64_regs_entry__init(gpregs);
+
+	gpregs->n_gpr = 32;
+	gpregs->gpr = xmalloc(32 * sizeof(uint64_t));
+	if (!gpregs->gpr) {
+		xfree(gpregs);
+		return NULL;
+	}
+
+	return gpregs;
+}
+
+int get_task_regs(pid_t pid, user_regs_struct_t regs, CoreEntry *core)
+{
 	pr_info("Dumping GP/FPU registers for %d\n", pid);
 
 	/*
@@ -364,35 +423,37 @@ int get_task_regs(pid_t pid, user_regs_struct_t regs, CoreEntry *core)
 	/* Resetting trap since we are now coming from user space. */
 	regs.trap = 0;
 
-#define assign_reg(dst, src, e) do {			\
-		dst->e = (__typeof__(dst->e))src.e;	\
-} while (0)
+	copy_gp_regs(core->ti_ppc64->gpregs, &regs);
 
-	for (i=0; i<32; i++)
-		assign_reg(core->ti_ppc64->gpregs, regs, gpr[i]);
-
-	assign_reg(core->ti_ppc64->gpregs, regs, nip);
-	assign_reg(core->ti_ppc64->gpregs, regs, msr);
-	assign_reg(core->ti_ppc64->gpregs, regs, orig_gpr3);
-	assign_reg(core->ti_ppc64->gpregs, regs, ctr);
-	assign_reg(core->ti_ppc64->gpregs, regs, link);
-	assign_reg(core->ti_ppc64->gpregs, regs, xer);
-	assign_reg(core->ti_ppc64->gpregs, regs, ccr);
-	assign_reg(core->ti_ppc64->gpregs, regs, trap);
-#undef assign_reg
-
-	if (get_fpu_regs(pid, core))
+	core->ti_ppc64->fpstate = get_fpu_regs(pid);
+	if (!core->ti_ppc64->fpstate)
 		return -1;
 
-	if (get_altivec_regs(pid, core))
-		return -1;
+	core->ti_ppc64->vrstate = get_altivec_regs(pid);
+	if (core->ti_ppc64->vrstate) {
+		if (core->ti_ppc64->vrstate == (UserPpc64VrstateEntry*)-1L)
+			return -1;
+		/*
+		 * Force the MSR_VEC bit of the restored MSR otherwise the
+		 * kernel will not restore them from the signal frame.
+		 */
+		core->ti_ppc64->gpregs->msr |= MSR_VEC;
 
-	/*
-	 * Don't save the VSX registers if Altivec registers are not
-	 * supported
-	 */
-	if (CORE_THREAD_ARCH_INFO(core)->vrstate && get_vsx_regs(pid, core))
-		return -1;
+		/*
+		 * Save the VSX registers if Altivec registers are supported
+		 */
+		core->ti_ppc64->vsxstate = get_vsx_regs(pid);
+		if (core->ti_ppc64->vsxstate) {
+			if (core->ti_ppc64->vsxstate == (UserPpc64VsxstateEntry *)-1L)
+				return -1;
+			/*
+			 * Force the MSR_VSX bit of the restored MSR otherwise
+			 * the kernel will not restore them from the signal
+			 * frame.
+			 */
+			core->ti_ppc64->gpregs->msr |= MSR_VSX;
+		}
+	}
 
 	return 0;
 }
@@ -400,30 +461,21 @@ int get_task_regs(pid_t pid, user_regs_struct_t regs, CoreEntry *core)
 int arch_alloc_thread_info(CoreEntry *core)
 {
 	ThreadInfoPpc64 *ti_ppc64;
-	UserPpc64RegsEntry *regs;
 
 	ti_ppc64 = xmalloc(sizeof(*ti_ppc64));
 	if(!ti_ppc64)
-		goto err;
-	thread_info_ppc64__init(ti_ppc64);
-	CORE_THREAD_ARCH_INFO(core) = ti_ppc64;
-
-	/* user_ppc64_regs_entry */
-	regs = xmalloc(sizeof(*regs));
-	if (!regs)
-		goto err;
-	user_ppc64_regs_entry__init(regs);
+		return -1;
 
-	regs->gpr = xmalloc(32*sizeof(uint64_t));
-	if (!regs->gpr)
-		goto err;
-	regs->n_gpr = 32;
+	thread_info_ppc64__init(ti_ppc64);
 
-	ti_ppc64->gpregs = regs;
+	ti_ppc64->gpregs = allocate_gp_regs();
+	if (!ti_ppc64->gpregs) {
+		xfree(ti_ppc64);
+		return -1;
+	}
 
+	CORE_THREAD_ARCH_INFO(core) = ti_ppc64;
 	return 0;
-err:
-	return -1;
 }
 
 void arch_free_thread_info(CoreEntry *core)
@@ -498,20 +550,7 @@ int sigreturn_prep_fpu_frame(struct rt_sigframe *frame,
 
 int restore_gpregs(struct rt_sigframe *f, UserPpc64RegsEntry *r)
 {
-	int i;
-
-	/* r0 to r31 */
-	for (i=0; i<32; i++)
-		f->uc.uc_mcontext.gp_regs[i] = r->gpr[i];
-
-	f->uc.uc_mcontext.gp_regs[PT_NIP] = r->nip;
-	f->uc.uc_mcontext.gp_regs[PT_MSR] = r->msr;
-	f->uc.uc_mcontext.gp_regs[PT_ORIG_R3] = r->orig_gpr3;
-	f->uc.uc_mcontext.gp_regs[PT_CTR] = r->ctr;
-	f->uc.uc_mcontext.gp_regs[PT_LNK] = r->link;
-	f->uc.uc_mcontext.gp_regs[PT_XER] = r->xer;
-	f->uc.uc_mcontext.gp_regs[PT_CCR] = r->ccr;
-	f->uc.uc_mcontext.gp_regs[PT_TRAP] = r->trap;
+	restore_gp_regs(&f->uc.uc_mcontext, r);
 
 	return 0;
 }
-- 
2.7.4



More information about the CRIU mailing list