[PATCH] ppc64: Add PTRACE_{GET|SET}VRREGS
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>
This commit is contained in:
parent
4267292b0f
commit
962bca7f38
3 changed files with 102 additions and 0 deletions
|
@ -17,6 +17,7 @@
|
||||||
* this archive for more details.
|
* this archive for more details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <linux/config.h>
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/sched.h>
|
#include <linux/sched.h>
|
||||||
#include <linux/mm.h>
|
#include <linux/mm.h>
|
||||||
|
@ -274,6 +275,20 @@ int sys_ptrace(long request, long pid, long addr, long data)
|
||||||
break;
|
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:
|
default:
|
||||||
ret = ptrace_request(child, request, addr, data);
|
ret = ptrace_request(child, request, addr, data);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
* this archive for more details.
|
* this archive for more details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <linux/config.h>
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/sched.h>
|
#include <linux/sched.h>
|
||||||
#include <linux/mm.h>
|
#include <linux/mm.h>
|
||||||
|
@ -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);
|
ret = put_user(child->ptrace_message, (unsigned int __user *) data);
|
||||||
break;
|
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:
|
default:
|
||||||
ret = ptrace_request(child, request, addr, data);
|
ret = ptrace_request(child, request, addr, data);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -11,6 +11,9 @@
|
||||||
|
|
||||||
#ifndef _PPC64_PTRACE_COMMON_H
|
#ifndef _PPC64_PTRACE_COMMON_H
|
||||||
#define _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.
|
* Set of msr bits that gdb can change on behalf of a process.
|
||||||
*/
|
*/
|
||||||
|
@ -69,4 +72,73 @@ static inline void clear_single_step(struct task_struct *task)
|
||||||
clear_ti_thread_flag(task->thread_info, TIF_SINGLESTEP);
|
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 */
|
#endif /* _PPC64_PTRACE_COMMON_H */
|
||||||
|
|
Loading…
Add table
Reference in a new issue