Commit 09023677 authored by Laurent Dufour's avatar Laurent Dufour Committed by Pavel Emelyanov

ppc64: Fix checkpoint --leave-running

The commit ba743509 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: ba743509 ("ppc64: Add Altivec and VSX support")
Reported-by: 's avatarAndrey Vagin <avagin@openvz.org>
Signed-off-by: 's avatarLaurent Dufour <ldufour@linux.vnet.ibm.com>
Tested-by: 's avatarAndrew Vagin <avagin@openvz.org>
Signed-off-by: 's avatarPavel Emelyanov <xemul@parallels.com>
parent a99d47e0
...@@ -227,6 +227,7 @@ static int put_altivec_regs(mcontext_t *mc, UserPpc64VrstateEntry *vse) ...@@ -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); vrregset_t *v_regs = (vrregset_t *)(((unsigned long)mc->vmx_reserve + 15) & ~0xful);
pr_debug("Restoring Altivec registers\n"); pr_debug("Restoring Altivec registers\n");
if (vse->n_vrregs != 33*2) { if (vse->n_vrregs != 33*2) {
pr_err("Corrupted Altivec dump data"); pr_err("Corrupted Altivec dump data");
return -1; return -1;
...@@ -275,6 +276,8 @@ static int get_vsx_regs(pid_t pid, CoreEntry *core) ...@@ -275,6 +276,8 @@ static int get_vsx_regs(pid_t pid, CoreEntry *core)
return -1; return -1;
} }
pr_debug("Dumping VSX registers\n");
vse = xmalloc(sizeof(*vse)); vse = xmalloc(sizeof(*vse));
if (!vse) if (!vse)
return -1; return -1;
...@@ -465,6 +468,26 @@ int restore_fpu(struct rt_sigframe *sigframe, CoreEntry *core) ...@@ -465,6 +468,26 @@ int restore_fpu(struct rt_sigframe *sigframe, CoreEntry *core)
return ret; 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 restore_gpregs(struct rt_sigframe *f, UserPpc64RegsEntry *r)
{ {
int i; int i;
......
...@@ -122,11 +122,8 @@ static inline int ptrace_flush_breakpoints(pid_t pid) ...@@ -122,11 +122,8 @@ static inline int ptrace_flush_breakpoints(pid_t pid)
return 0; return 0;
} }
static inline int sigreturn_prep_fpu_frame(struct rt_sigframe *sigframe, int sigreturn_prep_fpu_frame(struct rt_sigframe *sigframe,
mcontext_t *sigcontext) mcontext_t *sigcontext);
{
return 0;
}
/* /*
* Defined in arch/ppc64/syscall-common-ppc64.S * Defined in arch/ppc64/syscall-common-ppc64.S
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment