Skip to content

Commit

Permalink
[PATCH] ppc64: Add PTRACE_{GET|SET}VRREGS
Browse files Browse the repository at this point in the history
The ptrace get and set methods for VMX/Altivec registers present in the
ppc tree were missing for ppc64.  This patch adds the 32-bit and
64-bit methods.  Updated with the suggestions from Anton following the lines
of his code snippet.

Added:
 - flush_altivec_to_thread calls as suggested by Anton
 - piecewise copy of structure to preserve 32-bit vrsave data as per
   Anton

(I consolidated the 32 and 64bit versions with 2 helper macros - Anton)

Signed-off-by: Robert C Jennings <rcjenn@austin.ibm.com>
Signed-off-by: Anton Blanchard <anton@samba.org>
Signed-off-by: Paul Mackerras <paulus@samba.org>
  • Loading branch information
Robert Jennings authored and Paul Mackerras committed Sep 12, 2005
1 parent 4267292 commit 962bca7
Show file tree
Hide file tree
Showing 3 changed files with 102 additions and 0 deletions.
15 changes: 15 additions & 0 deletions arch/ppc64/kernel/ptrace.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
* this archive for more details.
*/

#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/mm.h>
Expand Down Expand Up @@ -274,6 +275,20 @@ int sys_ptrace(long request, long pid, long addr, long data)
break;
}

#ifdef CONFIG_ALTIVEC
case PTRACE_GETVRREGS:
/* Get the child altivec register state. */
flush_altivec_to_thread(child);
ret = get_vrregs((unsigned long __user *)data, child);
break;

case PTRACE_SETVRREGS:
/* Set the child altivec register state. */
flush_altivec_to_thread(child);
ret = set_vrregs(child, (unsigned long __user *)data);
break;
#endif

default:
ret = ptrace_request(child, request, addr, data);
break;
Expand Down
15 changes: 15 additions & 0 deletions arch/ppc64/kernel/ptrace32.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
* this archive for more details.
*/

#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/mm.h>
Expand Down Expand Up @@ -409,6 +410,20 @@ int sys32_ptrace(long request, long pid, unsigned long addr, unsigned long data)
ret = put_user(child->ptrace_message, (unsigned int __user *) data);
break;

#ifdef CONFIG_ALTIVEC
case PTRACE_GETVRREGS:
/* Get the child altivec register state. */
flush_altivec_to_thread(child);
ret = get_vrregs((unsigned long __user *)data, child);
break;

case PTRACE_SETVRREGS:
/* Set the child altivec register state. */
flush_altivec_to_thread(child);
ret = set_vrregs(child, (unsigned long __user *)data);
break;
#endif

default:
ret = ptrace_request(child, request, addr, data);
break;
Expand Down
72 changes: 72 additions & 0 deletions include/asm-ppc64/ptrace-common.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@

#ifndef _PPC64_PTRACE_COMMON_H
#define _PPC64_PTRACE_COMMON_H

#include <linux/config.h>

/*
* Set of msr bits that gdb can change on behalf of a process.
*/
Expand Down Expand Up @@ -69,4 +72,73 @@ static inline void clear_single_step(struct task_struct *task)
clear_ti_thread_flag(task->thread_info, TIF_SINGLESTEP);
}

#ifdef CONFIG_ALTIVEC
/*
* Get/set all the altivec registers vr0..vr31, vscr, vrsave, in one go.
* The transfer totals 34 quadword. Quadwords 0-31 contain the
* corresponding vector registers. Quadword 32 contains the vscr as the
* last word (offset 12) within that quadword. Quadword 33 contains the
* vrsave as the first word (offset 0) within the quadword.
*
* This definition of the VMX state is compatible with the current PPC32
* ptrace interface. This allows signal handling and ptrace to use the
* same structures. This also simplifies the implementation of a bi-arch
* (combined (32- and 64-bit) gdb.
*/

/*
* Get contents of AltiVec register state in task TASK
*/
static inline int get_vrregs(unsigned long __user *data,
struct task_struct *task)
{
unsigned long regsize;

/* copy AltiVec registers VR[0] .. VR[31] */
regsize = 32 * sizeof(vector128);
if (copy_to_user(data, task->thread.vr, regsize))
return -EFAULT;
data += (regsize / sizeof(unsigned long));

/* copy VSCR */
regsize = 1 * sizeof(vector128);
if (copy_to_user(data, &task->thread.vscr, regsize))
return -EFAULT;
data += (regsize / sizeof(unsigned long));

/* copy VRSAVE */
if (put_user(task->thread.vrsave, (u32 __user *)data))
return -EFAULT;

return 0;
}

/*
* Write contents of AltiVec register state into task TASK.
*/
static inline int set_vrregs(struct task_struct *task,
unsigned long __user *data)
{
unsigned long regsize;

/* copy AltiVec registers VR[0] .. VR[31] */
regsize = 32 * sizeof(vector128);
if (copy_from_user(task->thread.vr, data, regsize))
return -EFAULT;
data += (regsize / sizeof(unsigned long));

/* copy VSCR */
regsize = 1 * sizeof(vector128);
if (copy_from_user(&task->thread.vscr, data, regsize))
return -EFAULT;
data += (regsize / sizeof(unsigned long));

/* copy VRSAVE */
if (get_user(task->thread.vrsave, (u32 __user *)data))
return -EFAULT;

return 0;
}
#endif

#endif /* _PPC64_PTRACE_COMMON_H */

0 comments on commit 962bca7

Please sign in to comment.