Skip to content

Commit

Permalink
split tm regs for ppc64
Browse files Browse the repository at this point in the history
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
  • Loading branch information
xemul committed Sep 23, 2016
1 parent de1ad71 commit a9b7274
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 58 deletions.
134 changes: 76 additions & 58 deletions criu/arch/ppc64/crtools.c
Expand Up @@ -418,28 +418,12 @@ static void xfree_tm_state(UserPpc64TmRegsEntry *tme)
}
}

static int get_tm_regs(pid_t pid, CoreEntry *core)
static int get_tm_regs(pid_t pid, user_fpregs_struct_t *fpregs)
{
struct {
uint64_t tfhar, texasr, tfiar;
} tm_spr_regs;
user_regs_struct_t regs;
uint64_t fpregs[NFPREG], vmxregs[34][2], vsxregs[32];
struct iovec iov;
UserPpc64TmRegsEntry *tme;
UserPpc64RegsEntry *gpregs = core->ti_ppc64->gpregs;

pr_debug("Dumping TM registers\n");

tme = xmalloc(sizeof(*tme));
if (!tme)
return -1;
user_ppc64_tm_regs_entry__init(tme);

tme->gpregs = allocate_gp_regs();
if (!tme->gpregs)
goto out_free;

#define TM_REQUIRED 0
#define TM_OPTIONAL 1
#define PTRACE_GET_TM(s,n,c,u) do { \
Expand All @@ -458,43 +442,26 @@ static int get_tm_regs(pid_t pid, CoreEntry *core)
} while(0)

/* Get special registers */
PTRACE_GET_TM(tm_spr_regs, "SPR", NT_PPC_TM_SPR, TM_REQUIRED);
gpregs->has_tfhar = true;
gpregs->tfhar = tm_spr_regs.tfhar;
gpregs->has_texasr = true;
gpregs->texasr = tm_spr_regs.texasr;
gpregs->has_tfiar = true;
gpregs->tfiar = tm_spr_regs.tfiar;
PTRACE_GET_TM(fpregs->tm.tm_spr_regs, "SPR", NT_PPC_TM_SPR, TM_REQUIRED);

/* Get checkpointed regular registers */
PTRACE_GET_TM(regs, "GPR", NT_PPC_TM_CGPR, TM_REQUIRED);
copy_gp_regs(gpregs, &regs);
PTRACE_GET_TM(fpregs->tm.regs, "GPR", NT_PPC_TM_CGPR, TM_REQUIRED);

/* Get checkpointed FP registers */
PTRACE_GET_TM(fpregs, "FPR", NT_PPC_TM_CFPR, TM_OPTIONAL);
if (iov.iov_base) {
core->ti_ppc64->fpstate = copy_fp_regs(fpregs);
if (!core->ti_ppc64->fpstate)
goto out_free;
}
PTRACE_GET_TM(fpregs->tm.fpregs, "FPR", NT_PPC_TM_CFPR, TM_OPTIONAL);
if (iov.iov_base)
fpregs->flags |= 0x2;

/* Get checkpointed VMX (Altivec) registers */
PTRACE_GET_TM(vmxregs, "VMX", NT_PPC_TM_CVMX, TM_OPTIONAL);
if (iov.iov_base) {
core->ti_ppc64->vrstate = copy_altivec_regs((unsigned char *)vmxregs);
if (!core->ti_ppc64->vrstate)
goto out_free;
}
PTRACE_GET_TM(fpregs->tm.vmxregs, "VMX", NT_PPC_TM_CVMX, TM_OPTIONAL);
if (iov.iov_base)
fpregs->flags |= 0x4;

/* Get checkpointed VSX registers */
PTRACE_GET_TM(vsxregs, "VSX", NT_PPC_TM_CVSX, TM_OPTIONAL);
if (iov.iov_base) {
core->ti_ppc64->vsxstate = copy_vsx_regs(vsxregs);
if (!core->ti_ppc64->vsxstate)
goto out_free;
}
PTRACE_GET_TM(fpregs->tm.vsxregs, "VSX", NT_PPC_TM_CVSX, TM_OPTIONAL);
if (iov.iov_base)
fpregs->flags |= 0x8;

core->ti_ppc64->tmstate = tme;
return 0;

out_free:
Expand Down Expand Up @@ -585,19 +552,11 @@ int get_task_regs(pid_t pid, user_regs_struct_t regs, CoreEntry *core)
pid,
(regs.msr & MSR_TMS) ? "a suspended" : "an active",
regs.nip);
if (get_tm_regs(pid, core))
fpregs.flags = 1;
if (get_tm_regs(pid, &fpregs))
return -1;

gpregs = core->ti_ppc64->tmstate->gpregs;
fpstate = &(core->ti_ppc64->tmstate->fpstate);
vrstate = &(core->ti_ppc64->tmstate->vrstate);
vsxstate = &(core->ti_ppc64->tmstate->vsxstate);
} else {
gpregs = core->ti_ppc64->gpregs;
fpstate = &(core->ti_ppc64->fpstate);
vrstate = &(core->ti_ppc64->vrstate);
vsxstate = &(core->ti_ppc64->vsxstate);
}
} else
fpregs.flags = 0;

if (get_fpu_regs(pid, &fpregs))
return -1;
Expand Down Expand Up @@ -630,12 +589,71 @@ int get_task_regs(pid_t pid, user_regs_struct_t regs, CoreEntry *core)
}
}

if (fpregs.flags) {
UserPpc64TmRegsEntry *tme;
tme = xmalloc(sizeof(*tme));
if (!tme)
return -1;
user_ppc64_tm_regs_entry__init(tme);

tme->gpregs = allocate_gp_regs();
if (!tme->gpregs)
goto out_free;

core->ti_ppc64->tmstate = tme;

gpregs = core->ti_ppc64->gpregs;

gpregs->has_tfhar = true;
gpregs->tfhar = fpregs->tm.tm_spr_regs.tfhar;
gpregs->has_texasr = true;
gpregs->texasr = tfpregs->tm.m_spr_regs.texasr;
gpregs->has_tfiar = true;
gpregs->tfiar = tfpregs->tm.m_spr_regs.tfiar;

copy_gp_regs(gpregs, &fpregs->tm.regs);

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 (!core->ti_ppc64->vrstate)
return -1;
}

if (fpregs->flags & 0x8) {
core->ti_ppc64->vsxstate = copy_vsx_regs(fpregs->tm.vsxregs);
if (!core->ti_ppc64->vsxstate)
goto out_free;
}

gpregs = core->ti_ppc64->tmstate->gpregs;
fpstate = &(core->ti_ppc64->tmstate->fpstate);
vrstate = &(core->ti_ppc64->tmstate->vrstate);
vsxstate = &(core->ti_ppc64->tmstate->vsxstate);
} else {
gpregs = core->ti_ppc64->gpregs;
fpstate = &(core->ti_ppc64->fpstate);
vrstate = &(core->ti_ppc64->vrstate);
vsxstate = &(core->ti_ppc64->vsxstate);
}

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 (gpregs->msr & MSR_VSX)
if (!*vrstate)
return -1;
if (gpregs->msr & MSR_VSX) {
*vsxstate = copy_vsx_regs(fpregs.vsregs);
if (!*vsxstate)
return -1;
}

return 0;
Expand Down
9 changes: 9 additions & 0 deletions criu/arch/ppc64/include/asm/types.h
Expand Up @@ -76,6 +76,15 @@ typedef struct {
*/
unsigned char vrregs[(NVRREG-1) * 16 + 4];
uint64_t vsregs[NVSXREG];

int flags;
struct tm_regs {
struct {
uint64_t tfhar, texasr, tfiar;
} tm_spr_regs;
user_regs_struct_t regs;
uint64_t fpregs[NFPREG], vmxregs[34][2], vsxregs[32];
} tm;
} user_fpregs_struct_t;


Expand Down

0 comments on commit a9b7274

Please sign in to comment.