Commit 2df556fd authored by Anton Blanchard's avatar Anton Blanchard

ppc64: ptrace cleanup from Stephen Rothwell

parent c1aa8ae8
/* /*
* linux/arch/ppc/kernel/ptrace.c * linux/arch/ppc64/kernel/ptrace.c
* *
* PowerPC version * PowerPC version
* Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
...@@ -30,59 +30,13 @@ ...@@ -30,59 +30,13 @@
#include <asm/page.h> #include <asm/page.h>
#include <asm/pgtable.h> #include <asm/pgtable.h>
#include <asm/system.h> #include <asm/system.h>
#include <asm/ptrace-common.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)
/* /*
* does not yet catch signals sent when the child dies. * does not yet catch signals sent when the child dies.
* in exit.c or in signal.c. * in exit.c or in signal.c.
*/ */
/*
* 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))
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_SOFTE) {
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;
}
static inline void
set_single_step(struct task_struct *task)
{
struct pt_regs *regs = task->thread.regs;
if (regs != NULL)
regs->msr |= MSR_SE;
}
static inline void
clear_single_step(struct task_struct *task)
{
struct pt_regs *regs = task->thread.regs;
if (regs != NULL)
regs->msr &= ~MSR_SE;
}
/* /*
* Called by kernel/ptrace.c when detaching.. * Called by kernel/ptrace.c when detaching..
* *
...@@ -148,16 +102,17 @@ int sys_ptrace(long request, long pid, long addr, long data) ...@@ -148,16 +102,17 @@ int sys_ptrace(long request, long pid, long addr, long data)
/* read the word at location addr in the USER area. */ /* read the word at location addr in the USER area. */
case PTRACE_PEEKUSR: { case PTRACE_PEEKUSR: {
unsigned long index, tmp; unsigned long index;
unsigned long tmp;
ret = -EIO; ret = -EIO;
/* convert to index and check */ /* convert to index and check */
index = (unsigned long) addr >> 3; index = (unsigned long) addr >> 3;
if ((addr & 7) || index > PT_FPSCR) if ((addr & 7) || (index > PT_FPSCR))
break; break;
if (index < PT_FPR0) { if (index < PT_FPR0) {
tmp = get_reg(child, (int) index); tmp = get_reg(child, (int)index);
} else { } else {
if (child->thread.regs->msr & MSR_FP) if (child->thread.regs->msr & MSR_FP)
giveup_fpu(child); giveup_fpu(child);
...@@ -171,7 +126,8 @@ int sys_ptrace(long request, long pid, long addr, long data) ...@@ -171,7 +126,8 @@ int sys_ptrace(long request, long pid, long addr, long data)
case PTRACE_POKETEXT: /* write the word at location addr. */ case PTRACE_POKETEXT: /* write the word at location addr. */
case PTRACE_POKEDATA: case PTRACE_POKEDATA:
ret = 0; ret = 0;
if (access_process_vm(child, addr, &data, sizeof(data), 1) == sizeof(data)) if (access_process_vm(child, addr, &data, sizeof(data), 1)
== sizeof(data))
break; break;
ret = -EIO; ret = -EIO;
break; break;
...@@ -183,7 +139,7 @@ int sys_ptrace(long request, long pid, long addr, long data) ...@@ -183,7 +139,7 @@ int sys_ptrace(long request, long pid, long addr, long data)
ret = -EIO; ret = -EIO;
/* convert to index and check */ /* convert to index and check */
index = (unsigned long) addr >> 3; index = (unsigned long) addr >> 3;
if ((addr & 7) || index > PT_FPSCR) if ((addr & 7) || (index > PT_FPSCR))
break; break;
if (index == PT_ORIG_R3) if (index == PT_ORIG_R3)
...@@ -216,11 +172,11 @@ int sys_ptrace(long request, long pid, long addr, long data) ...@@ -216,11 +172,11 @@ int sys_ptrace(long request, long pid, long addr, long data)
break; break;
} }
/* /*
* make the child exit. Best I can do is send it a sigkill. * make the child exit. Best I can do is send it a sigkill.
* perhaps it should be put in the status that it wants to * perhaps it should be put in the status that it wants to
* exit. * exit.
*/ */
case PTRACE_KILL: { case PTRACE_KILL: {
ret = 0; ret = 0;
if (child->state == TASK_ZOMBIE) /* already dead */ if (child->state == TASK_ZOMBIE) /* already dead */
...@@ -249,56 +205,50 @@ int sys_ptrace(long request, long pid, long addr, long data) ...@@ -249,56 +205,50 @@ int sys_ptrace(long request, long pid, long addr, long data)
ret = ptrace_detach(child, data); ret = ptrace_detach(child, data);
break; break;
case PPC_PTRACE_GETREGS: case PPC_PTRACE_GETREGS: { /* Get GPRs 0 - 31. */
{ /* Get GPRs 0 - 31. */
u64 tmp; u64 tmp;
u64 cntr; u64 cntr;
ret = 0; ret = 0;
for (cntr=0; cntr<32 && ret==0; ++cntr) for (cntr=0; cntr<32 && ret==0; ++cntr) {
{
tmp = ((u64*)child->thread.regs)[cntr]; tmp = ((u64*)child->thread.regs)[cntr];
ret = put_user(tmp, (u64*)(data+cntr)); ret = put_user(tmp, (u64*)(data+cntr));
} }
break; break;
} }
case PPC_PTRACE_SETREGS: case PPC_PTRACE_SETREGS: { /* Set GPRs 0 - 31. */
{ /* Set GPRs 0 - 31. */
u64 cntr; u64 cntr;
ret = 0; ret = 0;
for (cntr=0; cntr<32 && ret==0; ++cntr) for (cntr=0; cntr<32 && ret==0; ++cntr)
{
ret = put_reg(child, cntr, *(u64*)(data+cntr)); ret = put_reg(child, cntr, *(u64*)(data+cntr));
}
break; break;
} }
case PPC_PTRACE_GETFPREGS: case PPC_PTRACE_GETFPREGS: { /* Get FPRs 0 - 31. */
{ /* Get FPRs 0 - 31. */
u64 tmp; u64 tmp;
u64 cntr; u64 cntr;
ret = -EIO; ret = -EIO;
if (child->thread.regs->msr & MSR_FP) if (child->thread.regs->msr & MSR_FP)
giveup_fpu(child); giveup_fpu(child);
ret = 0; ret = 0;
for (cntr=0; cntr<32 && ret==0; ++cntr) for (cntr=0; cntr<32 && ret==0; ++cntr) {
{
tmp = ((u64*)child->thread.fpr)[cntr]; tmp = ((u64*)child->thread.fpr)[cntr];
ret = put_user(tmp, (u64*)(data+cntr)); ret = put_user(tmp, (u64*)(data+cntr));
} }
break; break;
} }
case PPC_PTRACE_SETFPREGS: case PPC_PTRACE_SETFPREGS: { /* Get FPRs 0 - 31. */
{ /* Get FPRs 0 - 31. */
u64 cntr; u64 cntr;
ret = -EIO; ret = -EIO;
if (child->thread.regs->msr & MSR_FP) if (child->thread.regs->msr & MSR_FP)
giveup_fpu(child); giveup_fpu(child);
for (cntr=0; cntr<32; ++cntr) for (cntr=0; cntr<32; ++cntr)
{
((u64*)child->thread.fpr)[cntr] = *(u64*)(data+cntr); ((u64*)child->thread.fpr)[cntr] = *(u64*)(data+cntr);
}
ret = 0; ret = 0;
break; break;
} }
...@@ -334,4 +284,3 @@ void do_syscall_trace(void) ...@@ -334,4 +284,3 @@ void do_syscall_trace(void)
current->exit_code = 0; current->exit_code = 0;
} }
} }
This diff is collapsed.
/*
* linux/arch/ppc64/kernel/ptrace-common.h
*
* 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.
*/
/*
* Set of msr bits that gdb can change on behalf of a process.
*/
#define MSR_DEBUGCHANGE (MSR_FE0 | MSR_SE | MSR_BE | MSR_FE1)
/*
* 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)))
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_SOFTE) {
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;
}
static inline void set_single_step(struct task_struct *task)
{
struct pt_regs *regs = task->thread.regs;
if (regs != NULL)
regs->msr |= MSR_SE;
}
static inline void clear_single_step(struct task_struct *task)
{
struct pt_regs *regs = task->thread.regs;
if (regs != NULL)
regs->msr &= ~MSR_SE;
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment