diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index 7949c203cb89f5df7a7b27471d1b904e9af672a0..ea6ad7a2a7e3df329b9e56e4aaca83e524905148 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, ¤t->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 e42820d6d25bcf0a218948d58a26fc7f149566fd..5b9e3f41d649883e9c5c7218fb4989d490649ebb 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 d2da84acf45d8266bc4fd1b7cea428b1c7296a73..0eb9ed2f4189a675758ca212b27f68b7879afd25 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 */