[CRIU] [PATCH 4/4] arch: Split get and save of user_regs_t and user_fpregs_t
Pavel Emelyanov
xemul at virtuozzo.com
Mon Sep 26 01:25:38 PDT 2016
Signed-off-by: Pavel Emelyanov <xemul at virtuozzo.com>
---
criu/arch/aarch64/crtools.c | 28 +++++---
criu/arch/arm/crtools.c | 23 +++---
criu/arch/ppc64/crtools.c | 117 +++++++++++++++++--------------
criu/arch/x86/crtools.c | 165 ++++++++++++++++++++++++--------------------
4 files changed, 187 insertions(+), 146 deletions(-)
diff --git a/criu/arch/aarch64/crtools.c b/criu/arch/aarch64/crtools.c
index 9e0bd99..b8c6893 100644
--- a/criu/arch/aarch64/crtools.c
+++ b/criu/arch/aarch64/crtools.c
@@ -78,14 +78,16 @@ int syscall_seized(struct parasite_ctl *ctl, int nr, unsigned long *ret,
return err;
}
+static int save_task_regs(CoreEntry *core,
+ user_regs_struct_t *regs, user_fpregs_struct_t *fpsimd)
-#define assign_reg(dst, src, e) dst->e = (__typeof__(dst->e))(src).e
+#define assign_reg(dst, src, e) dst->e = (__typeof__(dst->e))(src)->e
int get_task_regs(pid_t pid, user_regs_struct_t regs, CoreEntry *core)
{
struct iovec iov;
user_fpregs_struct_t fpsimd;
- int i, ret;
+ int ret;
pr_info("Dumping GP/FPU registers for %d\n", pid);
@@ -103,6 +105,15 @@ int get_task_regs(pid_t pid, user_regs_struct_t regs, CoreEntry *core)
goto err;
}
+ ret = save_task_regs(core, ®s, &fpsimd);
+err:
+ return ret;
+}
+
+static int save_task_regs(CoreEntry *core,
+ user_regs_struct_t *regs, user_fpregs_struct_t *fpsimd)
+{
+ int i;
// Save the Aarch64 CPU state
for (i = 0; i < 31; ++i)
@@ -115,16 +126,13 @@ int get_task_regs(pid_t pid, user_regs_struct_t regs, CoreEntry *core)
// Save the FP/SIMD state
for (i = 0; i < 32; ++i)
{
- core->ti_aarch64->fpsimd->vregs[2*i] = fpsimd.vregs[i];
- core->ti_aarch64->fpsimd->vregs[2*i + 1] = fpsimd.vregs[i] >> 64;
+ core->ti_aarch64->fpsimd->vregs[2*i] = fpsimd->vregs[i];
+ core->ti_aarch64->fpsimd->vregs[2*i + 1] = fpsimd->vregs[i] >> 64;
}
assign_reg(core->ti_aarch64->fpsimd, fpsimd, fpsr);
assign_reg(core->ti_aarch64->fpsimd, fpsimd, fpcr);
- ret = 0;
-
-err:
- return ret;
+ return 0;
}
int arch_alloc_thread_info(CoreEntry *core)
@@ -191,8 +199,8 @@ int restore_fpu(struct rt_sigframe *sigframe, CoreEntry *core)
for (i = 0; i < 32; ++i)
fpsimd->vregs[i] = (__uint128_t)core->ti_aarch64->fpsimd->vregs[2*i] |
((__uint128_t)core->ti_aarch64->fpsimd->vregs[2*i + 1] << 64);
- assign_reg(fpsimd, *core->ti_aarch64->fpsimd, fpsr);
- assign_reg(fpsimd, *core->ti_aarch64->fpsimd, fpcr);
+ assign_reg(fpsimd, core->ti_aarch64->fpsimd, fpsr);
+ assign_reg(fpsimd, core->ti_aarch64->fpsimd, fpcr);
fpsimd->head.magic = FPSIMD_MAGIC;
fpsimd->head.size = sizeof(*fpsimd);
diff --git a/criu/arch/arm/crtools.c b/criu/arch/arm/crtools.c
index 5325ff0..c3421b9 100644
--- a/criu/arch/arm/crtools.c
+++ b/criu/arch/arm/crtools.c
@@ -80,7 +80,10 @@ int syscall_seized(struct parasite_ctl *ctl, int nr, unsigned long *ret,
return err;
}
-#define assign_reg(dst, src, e) dst->e = (__typeof__(dst->e))src.ARM_##e
+static int save_task_regs(CoreEntry *core,
+ user_regs_struct_t *regs, user_fpregs_struct_t *fpregs)
+
+#define assign_reg(dst, src, e) dst->e = (__typeof__(dst->e))((src)->ARM_##e)
#define PTRACE_GETVFPREGS 27
int get_task_regs(pid_t pid, user_regs_struct_t regs, CoreEntry *core)
@@ -112,7 +115,14 @@ int get_task_regs(pid_t pid, user_regs_struct_t regs, CoreEntry *core)
}
}
+ ret = save_task_regs(core, ®s, &vfp);
+err:
+ return ret;
+}
+static int save_task_regs(CoreEntry *core,
+ user_regs_struct_t *regs, user_fpregs_struct_t *fpregs)
+{
// Save the ARM CPU state
assign_reg(core->ti_arm->gpregs, regs, r0);
@@ -132,18 +142,15 @@ int get_task_regs(pid_t pid, user_regs_struct_t regs, CoreEntry *core)
assign_reg(core->ti_arm->gpregs, regs, lr);
assign_reg(core->ti_arm->gpregs, regs, pc);
assign_reg(core->ti_arm->gpregs, regs, cpsr);
- core->ti_arm->gpregs->orig_r0 = regs.ARM_ORIG_r0;
+ core->ti_arm->gpregs->orig_r0 = regs->ARM_ORIG_r0;
// Save the VFP state
- memcpy(CORE_THREAD_ARCH_INFO(core)->fpstate->vfp_regs, &vfp.fpregs, sizeof(vfp.fpregs));
- CORE_THREAD_ARCH_INFO(core)->fpstate->fpscr = vfp.fpscr;
+ memcpy(CORE_THREAD_ARCH_INFO(core)->fpstate->vfp_regs, &fpregs->fpregs, sizeof(fpregs->fpregs));
+ CORE_THREAD_ARCH_INFO(core)->fpstate->fpscr = fpregs->fpscr;
- ret = 0;
-
-err:
- return ret;
+ return 0;
}
int arch_alloc_thread_info(CoreEntry *core)
diff --git a/criu/arch/ppc64/crtools.c b/criu/arch/ppc64/crtools.c
index 24b2550..5ae8657 100644
--- a/criu/arch/ppc64/crtools.c
+++ b/criu/arch/ppc64/crtools.c
@@ -501,14 +501,13 @@ static int put_tm_regs(struct rt_sigframe *f, UserPpc64TmRegsEntry *tme)
return 0;
}
+static int save_task_regs(CoreEntry *core,
+ user_regs_struct_t *regs, user_fpregs_struct_t *fpregs);
+
/****************************************************************************/
int get_task_regs(pid_t pid, user_regs_struct_t regs, CoreEntry *core)
{
user_fpregs_struct_t fpregs;
- UserPpc64RegsEntry *gpregs;
- UserPpc64FpstateEntry **fpstate;
- UserPpc64VrstateEntry **vrstate;
- UserPpc64VsxstateEntry **vsxstate;
int ret;
pr_info("Dumping GP/FPU registers for %d\n", pid);
@@ -557,7 +556,50 @@ int get_task_regs(pid_t pid, user_regs_struct_t regs, CoreEntry *core)
} else
fpregs.flags = 0;
- if (fpregs.flags) {
+ if (get_fpu_regs(pid, &fpregs))
+ return -1;
+
+ ret = get_altivec_regs(pid, &fpregs);
+ if (ret < 0)
+ return -1;
+
+ if (ret == 1) {
+ /*
+ * Force the MSR_VEC bit of the restored MSR otherwise the
+ * kernel will not restore them from the signal frame.
+ */
+
+ fpregs.flags |= 0x16;
+
+ /*
+ * Save the VSX registers if Altivec registers are supported
+ */
+ ret = get_vsx_regs(pid, &fpregs);
+ if (ret < 0)
+ return -1;
+
+ if (ret == 0) {
+ /*
+ * Force the MSR_VSX bit of the restored MSR otherwise
+ * the kernel will not restore them from the signal
+ * frame.
+ */
+ fpregs.flags |= 0x32;
+ }
+ }
+
+ return save_task_regs(core, ®s, &fpregs);
+}
+
+static int save_task_regs(CoreEntry *core,
+ user_regs_struct_t *regs, user_fpregs_struct_t *fpregs)
+{
+ UserPpc64RegsEntry *gpregs;
+ UserPpc64FpstateEntry **fpstate;
+ UserPpc64VrstateEntry **vrstate;
+ UserPpc64VsxstateEntry **vsxstate;
+
+ if (fpregs->flags) {
UserPpc64TmRegsEntry *tme;
tme = xmalloc(sizeof(*tme));
if (!tme)
@@ -575,28 +617,28 @@ int get_task_regs(pid_t pid, user_regs_struct_t regs, CoreEntry *core)
gpregs = core->ti_ppc64->gpregs;
gpregs->has_tfhar = true;
- gpregs->tfhar = fpregs.tm.tm_spr_regs.tfhar;
+ gpregs->tfhar = fpregs->tm.tm_spr_regs.tfhar;
gpregs->has_texasr = true;
- gpregs->texasr = fpregs.tm.tm_spr_regs.texasr;
+ gpregs->texasr = fpregs->tm.tm_spr_regs.texasr;
gpregs->has_tfiar = true;
- gpregs->tfiar = fpregs.tm.tm_spr_regs.tfiar;
+ gpregs->tfiar = fpregs->tm.tm_spr_regs.tfiar;
- copy_gp_regs(gpregs, &fpregs.tm.regs);
+ copy_gp_regs(gpregs, &fpregs->tm.regs);
- if (fpregs.flags & 0x2) {
- core->ti_ppc64->fpstate = copy_fp_regs(fpregs.tm.fpregs);
+ if (fpregs->flags & 0x2) {
+ core->ti_ppc64->fpstate = copy_fp_regs(fpregs->tm.fpregs);
if (!core->ti_ppc64->fpstate)
return -1;
}
- if (fpregs.flags & 0x4) {
- core->ti_ppc64->vrstate = copy_altivec_regs((unsigned char *)fpregs.tm.vmxregs);
+ if (fpregs->flags & 0x4) {
+ core->ti_ppc64->vrstate = copy_altivec_regs((unsigned char *)fpregs->tm.vmxregs);
if (!core->ti_ppc64->vrstate)
return -1;
}
- if (fpregs.flags & 0x8) {
- core->ti_ppc64->vsxstate = copy_vsx_regs(fpregs.tm.vsxregs);
+ if (fpregs->flags & 0x8) {
+ core->ti_ppc64->vsxstate = copy_vsx_regs(fpregs->tm.vsxregs);
if (!core->ti_ppc64->vsxstate)
return -1;
}
@@ -612,47 +654,18 @@ int get_task_regs(pid_t pid, user_regs_struct_t regs, CoreEntry *core)
vsxstate = &(core->ti_ppc64->vsxstate);
}
- if (get_fpu_regs(pid, &fpregs))
- return -1;
-
- ret = get_altivec_regs(pid, &fpregs);
- if (ret < 0)
- return -1;
-
- if (ret == 1) {
- /*
- * Force the MSR_VEC bit of the restored MSR otherwise the
- * kernel will not restore them from the signal frame.
- */
- gpregs->msr |= MSR_VEC;
-
- /*
- * Save the VSX registers if Altivec registers are supported
- */
- ret = get_vsx_regs(pid, &fpregs);
- if (ret < 0)
- return -1;
-
- if (ret == 0) {
- /*
- * Force the MSR_VSX bit of the restored MSR otherwise
- * the kernel will not restore them from the signal
- * frame.
- */
- gpregs->msr |= MSR_VSX;
- }
- }
-
- copy_gp_regs(gpregs, ®s);
- *fpstate = copy_fp_regs(fpregs.fpregs);
+ copy_gp_regs(gpregs, regs);
+ *fpstate = copy_fp_regs(fpregs->fpregs);
if (!*fpstate)
return -1;
- if (gpregs->msr & MSR_VEC) {
- *vrstate = copy_altivec_regs(fpregs.vrregs);
+ if (fpregs->flags & 0x16) {
+ gpregs->msr |= MSR_VEC;
+ *vrstate = copy_altivec_regs(fpregs->vrregs);
if (!*vrstate)
return -1;
- if (gpregs->msr & MSR_VSX) {
- *vsxstate = copy_vsx_regs(fpregs.vsregs);
+ if (fpregs->flags & 0x32) {
+ gpregs->msr |= MSR_VSX;
+ *vsxstate = copy_vsx_regs(fpregs->vsregs);
if (!*vsxstate)
return -1;
}
diff --git a/criu/arch/x86/crtools.c b/criu/arch/x86/crtools.c
index d74efc3..9fee84a 100644
--- a/criu/arch/x86/crtools.c
+++ b/criu/arch/x86/crtools.c
@@ -193,10 +193,12 @@ int syscall_seized(struct parasite_ctl *ctl, int nr, unsigned long *ret,
((user_regs_native(pregs)) ? (int64_t)((pregs)->native.name) : \
(int32_t)((pregs)->compat.name))
+static int save_task_regs(CoreEntry *core,
+ user_regs_struct_t *regs, user_fpregs_struct_t *fpregs);
+
int get_task_regs(pid_t pid, user_regs_struct_t regs, CoreEntry *core)
{
- user_fpregs_struct_t xsave = { };
- UserX86RegsEntry *gpregs = core->thread_info->gpregs;
+ user_fpregs_struct_t xsave = { }, *xs = NULL;
struct iovec iov;
int ret = -1;
@@ -221,60 +223,6 @@ int get_task_regs(pid_t pid, user_regs_struct_t regs, CoreEntry *core)
}
}
-#define assign_reg(dst, src, e) do { dst->e = (__typeof__(dst->e))src.e; } while (0)
-#define assign_array(dst, src, e) memcpy(dst->e, &src.e, sizeof(src.e))
-
- if (user_regs_native(®s)) {
- assign_reg(gpregs, regs.native, r15);
- assign_reg(gpregs, regs.native, r14);
- assign_reg(gpregs, regs.native, r13);
- assign_reg(gpregs, regs.native, r12);
- assign_reg(gpregs, regs.native, bp);
- assign_reg(gpregs, regs.native, bx);
- assign_reg(gpregs, regs.native, r11);
- assign_reg(gpregs, regs.native, r10);
- assign_reg(gpregs, regs.native, r9);
- assign_reg(gpregs, regs.native, r8);
- assign_reg(gpregs, regs.native, ax);
- assign_reg(gpregs, regs.native, cx);
- assign_reg(gpregs, regs.native, dx);
- assign_reg(gpregs, regs.native, si);
- assign_reg(gpregs, regs.native, di);
- assign_reg(gpregs, regs.native, orig_ax);
- assign_reg(gpregs, regs.native, ip);
- assign_reg(gpregs, regs.native, cs);
- assign_reg(gpregs, regs.native, flags);
- assign_reg(gpregs, regs.native, sp);
- assign_reg(gpregs, regs.native, ss);
- assign_reg(gpregs, regs.native, fs_base);
- assign_reg(gpregs, regs.native, gs_base);
- assign_reg(gpregs, regs.native, ds);
- assign_reg(gpregs, regs.native, es);
- assign_reg(gpregs, regs.native, fs);
- assign_reg(gpregs, regs.native, gs);
- gpregs->mode = USER_X86_REGS_MODE__NATIVE;
- } else {
- assign_reg(gpregs, regs.compat, bx);
- assign_reg(gpregs, regs.compat, cx);
- assign_reg(gpregs, regs.compat, dx);
- assign_reg(gpregs, regs.compat, si);
- assign_reg(gpregs, regs.compat, di);
- assign_reg(gpregs, regs.compat, bp);
- assign_reg(gpregs, regs.compat, ax);
- assign_reg(gpregs, regs.compat, ds);
- assign_reg(gpregs, regs.compat, es);
- assign_reg(gpregs, regs.compat, fs);
- assign_reg(gpregs, regs.compat, gs);
- assign_reg(gpregs, regs.compat, orig_ax);
- assign_reg(gpregs, regs.compat, ip);
- assign_reg(gpregs, regs.compat, cs);
- assign_reg(gpregs, regs.compat, flags);
- assign_reg(gpregs, regs.compat, sp);
- assign_reg(gpregs, regs.compat, ss);
- gpregs->mode = USER_X86_REGS_MODE__COMPAT;
- }
- gpregs->has_mode = true;
-
#ifndef PTRACE_GETREGSET
# define PTRACE_GETREGSET 0x4204
#endif
@@ -304,37 +252,102 @@ int get_task_regs(pid_t pid, user_regs_struct_t regs, CoreEntry *core)
}
}
- assign_reg(core->thread_info->fpregs, xsave.i387, cwd);
- assign_reg(core->thread_info->fpregs, xsave.i387, swd);
- assign_reg(core->thread_info->fpregs, xsave.i387, twd);
- assign_reg(core->thread_info->fpregs, xsave.i387, fop);
- assign_reg(core->thread_info->fpregs, xsave.i387, rip);
- assign_reg(core->thread_info->fpregs, xsave.i387, rdp);
- assign_reg(core->thread_info->fpregs, xsave.i387, mxcsr);
- assign_reg(core->thread_info->fpregs, xsave.i387, mxcsr_mask);
+ xs = &xsave;
+out:
+ ret = save_task_regs(core, ®s, xs);
+err:
+ return ret;
+}
+
+static int save_task_regs(CoreEntry *core,
+ user_regs_struct_t *regs, user_fpregs_struct_t *fpregs)
+{
+ UserX86RegsEntry *gpregs = core->thread_info->gpregs;
+
+#define assign_reg(dst, src, e) do { dst->e = (__typeof__(dst->e))src.e; } while (0)
+#define assign_array(dst, src, e) memcpy(dst->e, &src.e, sizeof(src.e))
+
+ if (user_regs_native(regs)) {
+ assign_reg(gpregs, regs->native, r15);
+ assign_reg(gpregs, regs->native, r14);
+ assign_reg(gpregs, regs->native, r13);
+ assign_reg(gpregs, regs->native, r12);
+ assign_reg(gpregs, regs->native, bp);
+ assign_reg(gpregs, regs->native, bx);
+ assign_reg(gpregs, regs->native, r11);
+ assign_reg(gpregs, regs->native, r10);
+ assign_reg(gpregs, regs->native, r9);
+ assign_reg(gpregs, regs->native, r8);
+ assign_reg(gpregs, regs->native, ax);
+ assign_reg(gpregs, regs->native, cx);
+ assign_reg(gpregs, regs->native, dx);
+ assign_reg(gpregs, regs->native, si);
+ assign_reg(gpregs, regs->native, di);
+ assign_reg(gpregs, regs->native, orig_ax);
+ assign_reg(gpregs, regs->native, ip);
+ assign_reg(gpregs, regs->native, cs);
+ assign_reg(gpregs, regs->native, flags);
+ assign_reg(gpregs, regs->native, sp);
+ assign_reg(gpregs, regs->native, ss);
+ assign_reg(gpregs, regs->native, fs_base);
+ assign_reg(gpregs, regs->native, gs_base);
+ assign_reg(gpregs, regs->native, ds);
+ assign_reg(gpregs, regs->native, es);
+ assign_reg(gpregs, regs->native, fs);
+ assign_reg(gpregs, regs->native, gs);
+ gpregs->mode = USER_X86_REGS_MODE__NATIVE;
+ } else {
+ assign_reg(gpregs, regs->compat, bx);
+ assign_reg(gpregs, regs->compat, cx);
+ assign_reg(gpregs, regs->compat, dx);
+ assign_reg(gpregs, regs->compat, si);
+ assign_reg(gpregs, regs->compat, di);
+ assign_reg(gpregs, regs->compat, bp);
+ assign_reg(gpregs, regs->compat, ax);
+ assign_reg(gpregs, regs->compat, ds);
+ assign_reg(gpregs, regs->compat, es);
+ assign_reg(gpregs, regs->compat, fs);
+ assign_reg(gpregs, regs->compat, gs);
+ assign_reg(gpregs, regs->compat, orig_ax);
+ assign_reg(gpregs, regs->compat, ip);
+ assign_reg(gpregs, regs->compat, cs);
+ assign_reg(gpregs, regs->compat, flags);
+ assign_reg(gpregs, regs->compat, sp);
+ assign_reg(gpregs, regs->compat, ss);
+ gpregs->mode = USER_X86_REGS_MODE__COMPAT;
+ }
+ gpregs->has_mode = true;
+
+ if (!fpregs)
+ return 0;
+
+ assign_reg(core->thread_info->fpregs, fpregs->i387, cwd);
+ assign_reg(core->thread_info->fpregs, fpregs->i387, swd);
+ assign_reg(core->thread_info->fpregs, fpregs->i387, twd);
+ assign_reg(core->thread_info->fpregs, fpregs->i387, fop);
+ assign_reg(core->thread_info->fpregs, fpregs->i387, rip);
+ assign_reg(core->thread_info->fpregs, fpregs->i387, rdp);
+ assign_reg(core->thread_info->fpregs, fpregs->i387, mxcsr);
+ assign_reg(core->thread_info->fpregs, fpregs->i387, mxcsr_mask);
/* Make sure we have enough space */
- BUG_ON(core->thread_info->fpregs->n_st_space != ARRAY_SIZE(xsave.i387.st_space));
- BUG_ON(core->thread_info->fpregs->n_xmm_space != ARRAY_SIZE(xsave.i387.xmm_space));
+ BUG_ON(core->thread_info->fpregs->n_st_space != ARRAY_SIZE(fpregs->i387.st_space));
+ BUG_ON(core->thread_info->fpregs->n_xmm_space != ARRAY_SIZE(fpregs->i387.xmm_space));
- assign_array(core->thread_info->fpregs, xsave.i387, st_space);
- assign_array(core->thread_info->fpregs, xsave.i387, xmm_space);
+ assign_array(core->thread_info->fpregs, fpregs->i387, st_space);
+ assign_array(core->thread_info->fpregs, fpregs->i387, xmm_space);
if (cpu_has_feature(X86_FEATURE_XSAVE)) {
- BUG_ON(core->thread_info->fpregs->xsave->n_ymmh_space != ARRAY_SIZE(xsave.ymmh.ymmh_space));
+ BUG_ON(core->thread_info->fpregs->xsave->n_ymmh_space != ARRAY_SIZE(fpregs->ymmh.ymmh_space));
- assign_reg(core->thread_info->fpregs->xsave, xsave.xsave_hdr, xstate_bv);
- assign_array(core->thread_info->fpregs->xsave, xsave.ymmh, ymmh_space);
+ assign_reg(core->thread_info->fpregs->xsave, fpregs->xsave_hdr, xstate_bv);
+ assign_array(core->thread_info->fpregs->xsave, fpregs->ymmh, ymmh_space);
}
#undef assign_reg
#undef assign_array
-out:
- ret = 0;
-
-err:
- return ret;
+ return 0;
}
int ptrace_get_regs(pid_t pid, user_regs_struct_t *regs)
--
2.5.0
More information about the CRIU
mailing list