Skip to content

Commit

Permalink
[POWERPC] ptrace cleanups
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Benjamin Herrenschmidt authored and Paul Mackerras committed Jun 14, 2007
1 parent 0b3d5c4 commit acd8982
Show file tree
Hide file tree
Showing 5 changed files with 197 additions and 242 deletions.
89 changes: 41 additions & 48 deletions arch/powerpc/kernel/ptrace-common.h
Original file line number Diff line number Diff line change
@@ -1,21 +1,15 @@
/*
* Copyright (c) 2002 Stephen Rothwell, IBM Coproration
* Copyright (c) 2007 Benjamin Herrenschmidt, IBM Coproration
* Extracted from ptrace.c and ptrace32.c
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file README.legal in the main directory of
* this archive for more details.
*/

#ifndef _PPC64_PTRACE_COMMON_H
#define _PPC64_PTRACE_COMMON_H

#include <asm/system.h>

/*
* Set of msr bits that gdb can change on behalf of a process.
*/
#define MSR_DEBUGCHANGE (MSR_FE0 | MSR_SE | MSR_BE | MSR_FE1)
#ifndef _POWERPC_PTRACE_COMMON_H
#define _POWERPC_PTRACE_COMMON_H

/*
* Get contents of register REGNO in task TASK.
Expand All @@ -24,18 +18,18 @@ static inline unsigned long get_reg(struct task_struct *task, int regno)
{
unsigned long tmp = 0;

/*
* Put the correct FP bits in, they might be wrong as a result
* of our lazy FP restore.
*/
if (task->thread.regs == NULL)
return -EIO;

if (regno == PT_MSR) {
tmp = ((unsigned long *)task->thread.regs)[PT_MSR];
tmp |= task->thread.fpexc_mode;
} else if (regno < (sizeof(struct pt_regs) / sizeof(unsigned long))) {
tmp = ((unsigned long *)task->thread.regs)[regno];
return PT_MUNGE_MSR(tmp, task);
}

return tmp;
if (regno < (sizeof(struct pt_regs) / sizeof(unsigned long)))
return ((unsigned long *)task->thread.regs)[regno];

return -EIO;
}

/*
Expand All @@ -44,7 +38,10 @@ static inline unsigned long get_reg(struct task_struct *task, int regno)
static inline int put_reg(struct task_struct *task, int regno,
unsigned long data)
{
if (regno < PT_SOFTE) {
if (task->thread.regs == NULL)
return -EIO;

if (regno <= PT_MAX_PUT_REG) {
if (regno == PT_MSR)
data = (data & MSR_DEBUGCHANGE)
| (task->thread.regs->msr & ~MSR_DEBUGCHANGE);
Expand All @@ -54,21 +51,6 @@ static inline int put_reg(struct task_struct *task, int regno,
return -EIO;
}

static inline void set_single_step(struct task_struct *task)
{
struct pt_regs *regs = task->thread.regs;
if (regs != NULL)
regs->msr |= MSR_SE;
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)
regs->msr &= ~MSR_SE;
clear_tsk_thread_flag(task, TIF_SINGLESTEP);
}

#ifdef CONFIG_ALTIVEC
/*
Expand Down Expand Up @@ -137,25 +119,36 @@ static inline int set_vrregs(struct task_struct *task,

return 0;
}
#endif
#endif /* CONFIG_ALTIVEC */

static inline int ptrace_set_debugreg(struct task_struct *task,
unsigned long addr, unsigned long data)
static inline void set_single_step(struct task_struct *task)
{
/* We only support one DABR and no IABRS at the moment */
if (addr > 0)
return -EINVAL;
struct pt_regs *regs = task->thread.regs;

/* The bottom 3 bits are flags */
if ((data & ~0x7UL) >= TASK_SIZE)
return -EIO;
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);
}

/* Ensure translation is on */
if (data && !(data & DABR_TRANSLATION))
return -EIO;
static inline void clear_single_step(struct task_struct *task)
{
struct pt_regs *regs = task->thread.regs;

task->thread.dabr = data;
return 0;
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 /* _PPC64_PTRACE_COMMON_H */
#endif /* _POWERPC_PTRACE_COMMON_H */
100 changes: 100 additions & 0 deletions arch/powerpc/kernel/ptrace-ppc32.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
/*
* Copyright (c) 2007 Benjamin Herrenschmidt, IBM Coproration
* Extracted from ptrace.c and ptrace32.c
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file README.legal in the main directory of
* this archive for more details.
*/

#ifndef _POWERPC_PTRACE_PPC32_H
#define _POWERPC_PTRACE_PPC32_H

/*
* 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

/*
* Max register writeable via put_reg
*/
#define PT_MAX_PUT_REG PT_MQ

/*
* Munging of MSR on return from get_regs
*
* Nothing to do on ppc32
*/
#define PT_MUNGE_MSR(msr, task) (msr)


#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 */


#endif /* _POWERPC_PTRACE_PPC32_H */
51 changes: 51 additions & 0 deletions arch/powerpc/kernel/ptrace-ppc64.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* Copyright (c) 2002 Stephen Rothwell, IBM Coproration
* Extracted from ptrace.c and ptrace32.c
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file README.legal in the main directory of
* this archive for more details.
*/

#ifndef _POWERPC_PTRACE_PPC64_H
#define _POWERPC_PTRACE_PPC64_H

/*
* Set of msr bits that gdb can change on behalf of a process.
*/
#define MSR_DEBUGCHANGE (MSR_FE0 | MSR_SE | MSR_BE | MSR_FE1)

/*
* Max register writeable via put_reg
*/
#define PT_MAX_PUT_REG PT_CCR

/*
* Munging of MSR on return from get_regs
*
* Put the correct FP bits in, they might be wrong as a result
* of our lazy FP restore.
*/

#define PT_MUNGE_MSR(msr, task) ({ (msr) | (task)->thread.fpexc_mode; })

static inline int ptrace_set_debugreg(struct task_struct *task,
unsigned long addr, unsigned long data)
{
/* We only support one DABR and no IABRS at the moment */
if (addr > 0)
return -EINVAL;

/* The bottom 3 bits are flags */
if ((data & ~0x7UL) >= TASK_SIZE)
return -EIO;

/* Ensure translation is on */
if (data && !(data & DABR_TRANSLATION))
return -EIO;

task->thread.dabr = data;
return 0;
}

#endif /* _POWERPC_PTRACE_PPC64_H */
Loading

0 comments on commit acd8982

Please sign in to comment.