[POWERPC] ptrace cleanups

The powerpc ptrace code has some weirdness, like a ptrace-common.h file that
is actually ppc64 only and some of the 32 bits code ifdef'ed inside ptrace.c.

There are also separate implementations for things like get/set_vrregs for
32 and 64 bits which is totally unnecessary.

This patch cleans that up a bit by having a ptrace-common.h which contains
really common code (and makes a lot more code common), and ptrace-ppc32.h and
ptrace-ppc64.h files that contain the few remaining different bits.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Paul Mackerras <paulus@samba.org>
This commit is contained in:
Benjamin Herrenschmidt
2007-06-04 15:15:41 +10:00
committed by Paul Mackerras
parent 0b3d5c48a9
commit acd8982848
5 changed files with 199 additions and 244 deletions

View File

@ -36,208 +36,18 @@
#include <asm/system.h>
#ifdef CONFIG_PPC64
#include "ptrace-common.h"
#include "ptrace-ppc64.h"
#else
#include "ptrace-ppc32.h"
#endif
#ifdef CONFIG_PPC32
/*
* Set of msr bits that gdb can change on behalf of a process.
*/
#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
#define MSR_DEBUGCHANGE 0
#else
#define MSR_DEBUGCHANGE (MSR_SE | MSR_BE)
#endif
#endif /* CONFIG_PPC32 */
#include "ptrace-common.h"
/*
* does not yet catch signals sent when the child dies.
* in exit.c or in signal.c.
*/
#ifdef CONFIG_PPC32
/*
* Get contents of register REGNO in task TASK.
*/
static inline unsigned long get_reg(struct task_struct *task, int regno)
{
if (regno < sizeof(struct pt_regs) / sizeof(unsigned long)
&& task->thread.regs != NULL)
return ((unsigned long *)task->thread.regs)[regno];
return (0);
}
/*
* Write contents of register REGNO in task TASK.
*/
static inline int put_reg(struct task_struct *task, int regno,
unsigned long data)
{
if (regno <= PT_MQ && task->thread.regs != NULL) {
if (regno == PT_MSR)
data = (data & MSR_DEBUGCHANGE)
| (task->thread.regs->msr & ~MSR_DEBUGCHANGE);
((unsigned long *)task->thread.regs)[regno] = data;
return 0;
}
return -EIO;
}
#ifdef CONFIG_ALTIVEC
/*
* Get contents of AltiVec register state in task TASK
*/
static inline int get_vrregs(unsigned long __user *data, struct task_struct *task)
{
int i, j;
if (!access_ok(VERIFY_WRITE, data, 133 * sizeof(unsigned long)))
return -EFAULT;
/* copy AltiVec registers VR[0] .. VR[31] */
for (i = 0; i < 32; i++)
for (j = 0; j < 4; j++, data++)
if (__put_user(task->thread.vr[i].u[j], data))
return -EFAULT;
/* copy VSCR */
for (i = 0; i < 4; i++, data++)
if (__put_user(task->thread.vscr.u[i], data))
return -EFAULT;
/* copy VRSAVE */
if (__put_user(task->thread.vrsave, 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)
{
int i, j;
if (!access_ok(VERIFY_READ, data, 133 * sizeof(unsigned long)))
return -EFAULT;
/* copy AltiVec registers VR[0] .. VR[31] */
for (i = 0; i < 32; i++)
for (j = 0; j < 4; j++, data++)
if (__get_user(task->thread.vr[i].u[j], data))
return -EFAULT;
/* copy VSCR */
for (i = 0; i < 4; i++, data++)
if (__get_user(task->thread.vscr.u[i], data))
return -EFAULT;
/* copy VRSAVE */
if (__get_user(task->thread.vrsave, data))
return -EFAULT;
return 0;
}
#endif
#ifdef CONFIG_SPE
/*
* For get_evrregs/set_evrregs functions 'data' has the following layout:
*
* struct {
* u32 evr[32];
* u64 acc;
* u32 spefscr;
* }
*/
/*
* Get contents of SPE register state in task TASK.
*/
static inline int get_evrregs(unsigned long *data, struct task_struct *task)
{
int i;
if (!access_ok(VERIFY_WRITE, data, 35 * sizeof(unsigned long)))
return -EFAULT;
/* copy SPEFSCR */
if (__put_user(task->thread.spefscr, &data[34]))
return -EFAULT;
/* copy SPE registers EVR[0] .. EVR[31] */
for (i = 0; i < 32; i++, data++)
if (__put_user(task->thread.evr[i], data))
return -EFAULT;
/* copy ACC */
if (__put_user64(task->thread.acc, (unsigned long long *)data))
return -EFAULT;
return 0;
}
/*
* Write contents of SPE register state into task TASK.
*/
static inline int set_evrregs(struct task_struct *task, unsigned long *data)
{
int i;
if (!access_ok(VERIFY_READ, data, 35 * sizeof(unsigned long)))
return -EFAULT;
/* copy SPEFSCR */
if (__get_user(task->thread.spefscr, &data[34]))
return -EFAULT;
/* copy SPE registers EVR[0] .. EVR[31] */
for (i = 0; i < 32; i++, data++)
if (__get_user(task->thread.evr[i], data))
return -EFAULT;
/* copy ACC */
if (__get_user64(task->thread.acc, (unsigned long long*)data))
return -EFAULT;
return 0;
}
#endif /* CONFIG_SPE */
static inline void
set_single_step(struct task_struct *task)
{
struct pt_regs *regs = task->thread.regs;
if (regs != NULL) {
#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
task->thread.dbcr0 = DBCR0_IDM | DBCR0_IC;
regs->msr |= MSR_DE;
#else
regs->msr |= MSR_SE;
#endif
}
set_tsk_thread_flag(task, TIF_SINGLESTEP);
}
static inline void
clear_single_step(struct task_struct *task)
{
struct pt_regs *regs = task->thread.regs;
if (regs != NULL) {
#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
task->thread.dbcr0 = 0;
regs->msr &= ~MSR_DE;
#else
regs->msr &= ~MSR_SE;
#endif
}
clear_tsk_thread_flag(task, TIF_SINGLESTEP);
}
#endif /* CONFIG_PPC32 */
/*
* Called by kernel/ptrace.c when detaching..
*