Skip to content

Commit

Permalink
introduce user_fpregs_struct_t on 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 d651dd7 commit 6245ad7
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 39 deletions.
72 changes: 33 additions & 39 deletions criu/arch/ppc64/crtools.c
Expand Up @@ -162,16 +162,14 @@ static UserPpc64FpstateEntry *copy_fp_regs(uint64_t *fpregs)
*/
#define NVSXREG 32

static UserPpc64FpstateEntry *get_fpu_regs(pid_t pid)
static int get_fpu_regs(pid_t pid, user_fpregs_struct_t *fp)
{
uint64_t fpregs[NFPREG];

if (ptrace(PTRACE_GETFPREGS, pid, 0, (void *)&fpregs) < 0) {
if (ptrace(PTRACE_GETFPREGS, pid, 0, (void *)&fp->fp) < 0) {
pr_perror("Couldn't get floating-point registers");
return NULL;;
return -1;
}

return copy_fp_regs(fpregs);
return 0;
}

static void put_fpu_regs(mcontext_t *mc, UserPpc64FpstateEntry *fpe)
Expand Down Expand Up @@ -216,33 +214,23 @@ static UserPpc64VrstateEntry *copy_altivec_regs(unsigned char *vrregs)
return vse;
}

static UserPpc64VrstateEntry *get_altivec_regs(pid_t pid)
static int get_altivec_regs(pid_t pid, user_fpregs_struct_t *fp)
{
/* 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];

if (ptrace(PTRACE_GETVRREGS, pid, 0, (void*)&vrregs) < 0) {
if (ptrace(PTRACE_GETVRREGS, pid, 0, (void*)&fp->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;
return -1;
}
pr_debug("Altivec not supported\n");
return NULL;
return 0;
}

pr_debug("Dumping Altivec registers\n");

return copy_altivec_regs(vrregs);
return 1;
}

static int put_altivec_regs(mcontext_t *mc, UserPpc64VrstateEntry *vse)
Expand Down Expand Up @@ -305,11 +293,9 @@ static UserPpc64VsxstateEntry* copy_vsx_regs(uint64_t *vsregs)
* 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 UserPpc64VsxstateEntry *get_vsx_regs(pid_t pid)
static int get_vsx_regs(pid_t pid, user_fpregs_struct_t *fp)
{
uint64_t vsregs[NVSXREG];

if (ptrace(PTRACE_GETVSRREGS, pid, 0, (void*)&vsregs) < 0) {
if (ptrace(PTRACE_GETVSRREGS, pid, 0, (void*)&fp->vsregs) < 0) {
/*
* EIO is returned in the case PTRACE_GETVRREGS is not
* supported.
Expand All @@ -319,11 +305,10 @@ static UserPpc64VsxstateEntry *get_vsx_regs(pid_t pid)
return 0;
}
pr_perror("Couldn't get VSX registers");
return (UserPpc64VsxstateEntry *)-1L;
return -1;
}

pr_debug("Dumping VSX registers\n");
return copy_vsx_regs(vsregs);
return 1;
}

static int put_vsx_regs(mcontext_t *mc, UserPpc64VsxstateEntry *vse)
Expand Down Expand Up @@ -554,10 +539,12 @@ static int put_tm_regs(struct rt_sigframe *f, UserPpc64TmRegsEntry *tme)
/****************************************************************************/
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);

Expand Down Expand Up @@ -613,16 +600,14 @@ int get_task_regs(pid_t pid, user_regs_struct_t regs, CoreEntry *core)
vsxstate = &(core->ti_ppc64->vsxstate);
}

copy_gp_regs(gpregs, &regs);
if (get_fpu_regs(pid, &fpregs))
return -1;

*fpstate = get_fpu_regs(pid);
if (!*fpstate)
ret = get_altivec_regs(pid, &fpregs);
if (ret < 0)
return -1;

*vrstate = get_altivec_regs(pid);
if (*vrstate) {
if (*vrstate == (UserPpc64VrstateEntry*)-1L)
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.
Expand All @@ -632,10 +617,11 @@ int get_task_regs(pid_t pid, user_regs_struct_t regs, CoreEntry *core)
/*
* Save the VSX registers if Altivec registers are supported
*/
*vsxstate = get_vsx_regs(pid);
if (*vsxstate) {
if (*vsxstate == (UserPpc64VsxstateEntry *)-1L)
return -1;
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
Expand All @@ -645,6 +631,14 @@ int get_task_regs(pid_t pid, user_regs_struct_t regs, CoreEntry *core)
}
}

copy_gp_regs(gpregs, &regs);
*fpstate = copy_fp_regs(fpregs.fpregs);
if (gpregs->msr & MSR_VEC) {
*vrstate = copy_altivec_regs(fpregs.vrregs);
if (gpregs->msr & MSR_VSX)
*vsxstate = copy_vsx_regs(fpregs.vsregs);
}

return 0;
}

Expand Down
16 changes: 16 additions & 0 deletions criu/arch/ppc64/include/asm/types.h
Expand Up @@ -61,6 +61,22 @@ typedef struct {
unsigned long result; /* Result of a system call */
} user_regs_struct_t;

typedef struct {
uint64_t fpregs[NFPREG];
/* 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];
uint64_t vsregs[NVSXREG];
} user_fpregs_struct_t;


typedef UserPpc64RegsEntry UserRegsEntry;

#define CORE_ENTRY__MARCH CORE_ENTRY__MARCH__PPC64
Expand Down

0 comments on commit 6245ad7

Please sign in to comment.