summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/powerpc/kernel/process.c28
-rw-r--r--include/asm-powerpc/elf.h8
-rw-r--r--include/linux/elf.h1
3 files changed, 34 insertions, 3 deletions
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index 7949c203cb89..ea6ad7a2a7e3 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -149,10 +149,32 @@ void flush_altivec_to_thread(struct task_struct *tsk)
}
}
-int dump_task_altivec(struct pt_regs *regs, elf_vrregset_t *vrregs)
+int dump_task_altivec(struct task_struct *tsk, elf_vrregset_t *vrregs)
{
- flush_altivec_to_thread(current);
- memcpy(vrregs, &current->thread.vr[0], sizeof(*vrregs));
+ /* ELF_NVRREG includes the VSCR and VRSAVE which we need to save
+ * separately, see below */
+ const int nregs = ELF_NVRREG - 2;
+ elf_vrreg_t *reg;
+ u32 *dest;
+
+ if (tsk == current)
+ flush_altivec_to_thread(tsk);
+
+ reg = (elf_vrreg_t *)vrregs;
+
+ /* copy the 32 vr registers */
+ memcpy(reg, &tsk->thread.vr[0], nregs * sizeof(*reg));
+ reg += nregs;
+
+ /* copy the vscr */
+ memcpy(reg, &tsk->thread.vscr, sizeof(*reg));
+ reg++;
+
+ /* vrsave is stored in the high 32bit slot of the final 128bits */
+ memset(reg, 0, sizeof(*reg));
+ dest = (u32 *)reg;
+ *dest = tsk->thread.vrsave;
+
return 1;
}
#endif /* CONFIG_ALTIVEC */
diff --git a/include/asm-powerpc/elf.h b/include/asm-powerpc/elf.h
index e42820d6d25b..5b9e3f41d649 100644
--- a/include/asm-powerpc/elf.h
+++ b/include/asm-powerpc/elf.h
@@ -212,6 +212,14 @@ static inline int dump_task_regs(struct task_struct *tsk,
extern int dump_task_fpu(struct task_struct *, elf_fpregset_t *);
#define ELF_CORE_COPY_FPREGS(tsk, elf_fpregs) dump_task_fpu(tsk, elf_fpregs)
+typedef elf_vrregset_t elf_fpxregset_t;
+
+#ifdef CONFIG_ALTIVEC
+extern int dump_task_altivec(struct task_struct *, elf_vrregset_t *vrregs);
+#define ELF_CORE_COPY_XFPREGS(tsk, regs) dump_task_altivec(tsk, regs)
+#define ELF_CORE_XFPREG_TYPE NT_PPC_VMX
+#endif
+
#endif /* __KERNEL__ */
/* ELF_HWCAP yields a mask that user programs can use to figure out what
diff --git a/include/linux/elf.h b/include/linux/elf.h
index d2da84acf45d..0eb9ed2f4189 100644
--- a/include/linux/elf.h
+++ b/include/linux/elf.h
@@ -355,6 +355,7 @@ typedef struct elf64_shdr {
#define NT_TASKSTRUCT 4
#define NT_AUXV 6
#define NT_PRXFPREG 0x46e62b7f /* copied from gdb5.1/include/elf/common.h */
+#define NT_PPC_VMX 0x100 /* PowerPC Altivec/VMX registers */
/* Note header in a PT_NOTE section */