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;
} }
} }
/* /*
* linux/arch/ppc/kernel/ptrace32.c * linux/arch/ppc64/kernel/ptrace32.c
* *
* PowerPC version * PowerPC version
* Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
...@@ -30,64 +30,18 @@ ...@@ -30,64 +30,18 @@
#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.
* (Put DATA into task TASK's register REGNO.)
*/
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;
}
int sys32_ptrace(long request, long pid, unsigned long addr, unsigned long data) int sys32_ptrace(long request, long pid, unsigned long addr, unsigned long data)
{ {
struct task_struct *child; struct task_struct *child;
int ret = -EPERM; int ret = -EPERM;
lock_kernel(); lock_kernel();
if (request == PTRACE_TRACEME) { if (request == PTRACE_TRACEME) {
/* are we already being traced? */ /* are we already being traced? */
...@@ -120,92 +74,95 @@ int sys32_ptrace(long request, long pid, unsigned long addr, unsigned long data) ...@@ -120,92 +74,95 @@ int sys32_ptrace(long request, long pid, unsigned long addr, unsigned long data)
if (ret < 0) if (ret < 0)
goto out_tsk; goto out_tsk;
switch (request) switch (request) {
{
/* Read word at location ADDR */
/* when I and D space are separate, these will need to be fixed. */ /* when I and D space are separate, these will need to be fixed. */
case PTRACE_PEEKTEXT: /* read word at location addr. */ case PTRACE_PEEKTEXT: /* read word at location addr. */
case PTRACE_PEEKDATA: case PTRACE_PEEKDATA: {
{ unsigned int tmp;
unsigned int tmp_mem_value;
int copied; int copied;
copied = access_process_vm(child, addr, &tmp_mem_value, sizeof(tmp_mem_value), 0); copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
ret = -EIO; ret = -EIO;
if (copied != sizeof(tmp_mem_value)) if (copied != sizeof(tmp))
break; break;
ret = put_user(tmp_mem_value, (u32*)data); // copy 4 bytes of data into the user location specified by the 8 byte pointer in "data". ret = put_user(tmp, (u32*)data);
break; break;
} }
/* Read 4 bytes of the other process' storage */ /*
/* data is a pointer specifying where the user wants the 4 bytes copied into */ * Read 4 bytes of the other process' storage
/* addr is a pointer in the user's storage that contains an 8 byte address in the other process of the 4 bytes that is to be read */ * data is a pointer specifying where the user wants the
/* (this is run in a 32-bit process looking at a 64-bit process) */ * 4 bytes copied into
/* when I and D space are separate, these will need to be fixed. */ * addr is a pointer in the user's storage that contains an 8 byte
* address in the other process of the 4 bytes that is to be read
* (this is run in a 32-bit process looking at a 64-bit process)
* when I and D space are separate, these will need to be fixed.
*/
case PPC_PTRACE_PEEKTEXT_3264: case PPC_PTRACE_PEEKTEXT_3264:
case PPC_PTRACE_PEEKDATA_3264: case PPC_PTRACE_PEEKDATA_3264: {
{ u32 tmp;
u32 tmp_mem_value; int copied;
int copied;
u32* addrOthers; u32* addrOthers;
ret = -EIO; ret = -EIO;
/* Get the addr in the other process that we want to read */ /* Get the addr in the other process that we want to read */
if (get_user(addrOthers,(u32**)addr) != 0) if (get_user(addrOthers, (u32**)addr) != 0)
break; break;
copied = access_process_vm(child, (u64)addrOthers, &tmp_mem_value, sizeof(tmp_mem_value), 0); copied = access_process_vm(child, (u64)addrOthers, &tmp,
if (copied != sizeof(tmp_mem_value)) sizeof(tmp), 0);
if (copied != sizeof(tmp))
break; break;
ret = put_user(tmp_mem_value, (u32*)data); // copy 4 bytes of data into the user location specified by the 8 byte pointer in "data". ret = put_user(tmp, (u32*)data);
break; break;
} }
/* Read a register (specified by ADDR) out of the "user area" */ /* Read a register (specified by ADDR) out of the "user area" */
case PTRACE_PEEKUSR: { case PTRACE_PEEKUSR: {
int index; int index;
unsigned int reg32bits; unsigned long tmp;
unsigned long tmp_reg_value;
ret = -EIO; ret = -EIO;
/* convert to index and check */ /* convert to index and check */
index = (unsigned long) addr >> 2; index = (unsigned long) addr >> 2;
if ((addr & 3) || index > PT_FPSCR32) if ((addr & 3) || (index > PT_FPSCR32))
break; break;
if (index < PT_FPR0) { if (index < PT_FPR0) {
tmp_reg_value = get_reg(child, index); tmp = get_reg(child, index);
} else { } else {
if (child->thread.regs->msr & MSR_FP) if (child->thread.regs->msr & MSR_FP)
giveup_fpu(child); giveup_fpu(child);
/* the user space code considers the floating point to be /*
* an array of unsigned int (32 bits) - the index passed * the user space code considers the floating point
* in is based on this assumption. * to be an array of unsigned int (32 bits) - the
* index passed in is based on this assumption.
*/ */
tmp_reg_value = ((unsigned int *)child->thread.fpr)[index - PT_FPR0]; tmp = ((unsigned int *)child->thread.fpr)[index - PT_FPR0];
} }
reg32bits = tmp_reg_value; ret = put_user((unsigned int)tmp, (u32*)data);
ret = put_user(reg32bits, (u32*)data); // copy 4 bytes of data into the user location specified by the 8 byte pointer in "data".
break; break;
} }
/* Read 4 bytes out of the other process' pt_regs area */ /*
/* data is a pointer specifying where the user wants the 4 bytes copied into */ * Read 4 bytes out of the other process' pt_regs area
/* addr is the offset into the other process' pt_regs structure that is to be read */ * data is a pointer specifying where the user wants the
/* (this is run in a 32-bit process looking at a 64-bit process) */ * 4 bytes copied into
case PPC_PTRACE_PEEKUSR_3264: * addr is the offset into the other process' pt_regs structure
{ * that is to be read
* (this is run in a 32-bit process looking at a 64-bit process)
*/
case PPC_PTRACE_PEEKUSR_3264: {
u32 index; u32 index;
u32 reg32bits; u32 reg32bits;
u64 tmp_reg_value; u64 tmp;
u32 numReg; u32 numReg;
u32 part; u32 part;
ret = -EIO; ret = -EIO;
/* Determine which register the user wants */ /* Determine which register the user wants */
index = (u64)addr >> 2; /* Divide addr by 4 */ index = (u64)addr >> 2;
numReg = index / 2; numReg = index / 2;
/* Determine which part of the register the user wants */ /* Determine which part of the register the user wants */
if (index % 2) if (index % 2)
...@@ -217,117 +174,115 @@ int sys32_ptrace(long request, long pid, unsigned long addr, unsigned long data) ...@@ -217,117 +174,115 @@ int sys32_ptrace(long request, long pid, unsigned long addr, unsigned long data)
if ((addr & 3) || numReg > PT_FPSCR) if ((addr & 3) || numReg > PT_FPSCR)
break; break;
if (numReg >= PT_FPR0) if (numReg >= PT_FPR0) {
{
if (child->thread.regs->msr & MSR_FP) if (child->thread.regs->msr & MSR_FP)
giveup_fpu(child); giveup_fpu(child);
} }
tmp_reg_value = get_reg(child, numReg); tmp = get_reg(child, numReg);
reg32bits = ((u32*)&tmp_reg_value)[part]; reg32bits = ((u32*)&tmp)[part];
ret = put_user(reg32bits, (u32*)data); /* copy 4 bytes of data into the user location specified by the 8 byte pointer in "data". */ ret = put_user(reg32bits, (u32*)data);
break; break;
} }
/* Write the word at location ADDR */
/* If I and D space are separate, this will have to be fixed. */ /* If I and D space are separate, this will have to be fixed. */
case PTRACE_POKETEXT: /* write the word at location addr. */ case PTRACE_POKETEXT: /* write the word at location addr. */
case PTRACE_POKEDATA: { case PTRACE_POKEDATA: {
unsigned int tmp_value_to_write; unsigned int tmp;
tmp_value_to_write = data; tmp = data;
ret = 0; ret = 0;
if (access_process_vm(child, addr, &tmp_value_to_write, sizeof(tmp_value_to_write), 1) == sizeof(tmp_value_to_write)) if (access_process_vm(child, addr, &tmp, sizeof(tmp), 1)
== sizeof(tmp))
break; break;
ret = -EIO; ret = -EIO;
break; break;
} }
/* Write 4 bytes into the other process' storage */ /*
/* data is the 4 bytes that the user wants written */ * Write 4 bytes into the other process' storage
/* addr is a pointer in the user's storage that contains an 8 byte address in the other process where the 4 bytes that is to be written */ * data is the 4 bytes that the user wants written
/* (this is run in a 32-bit process looking at a 64-bit process) */ * addr is a pointer in the user's storage that contains an
/* when I and D space are separate, these will need to be fixed. */ * 8 byte address in the other process where the 4 bytes
* that is to be written
* (this is run in a 32-bit process looking at a 64-bit process)
* when I and D space are separate, these will need to be fixed.
*/
case PPC_PTRACE_POKETEXT_3264: case PPC_PTRACE_POKETEXT_3264:
case PPC_PTRACE_POKEDATA_3264: case PPC_PTRACE_POKEDATA_3264: {
{ u32 tmp = data;
u32 tmp_value_to_write = data;
u32* addrOthers; u32* addrOthers;
int bytesWritten;
/* Get the addr in the other process that we want to write into */ /* Get the addr in the other process that we want to write into */
ret = -EIO; ret = -EIO;
if (get_user(addrOthers,(u32**)addr) != 0) if (get_user(addrOthers, (u32**)addr) != 0)
break; break;
ret = 0; ret = 0;
bytesWritten = access_process_vm(child, (u64)addrOthers, &tmp_value_to_write, sizeof(tmp_value_to_write), 1); if (access_process_vm(child, (u64)addrOthers, &tmp,
if (bytesWritten == sizeof(tmp_value_to_write)) sizeof(tmp), 1) == sizeof(tmp))
break; break;
ret = -EIO; ret = -EIO;
break; break;
} }
/* Write DATA into location ADDR within the USER area */ /* write the word at location addr in the USER area */
case PTRACE_POKEUSR: { case PTRACE_POKEUSR: {
unsigned long index; unsigned long index;
ret = -EIO; ret = -EIO;
/* convert to index and check */ /* convert to index and check */
index = (unsigned long) addr >> 2; index = (unsigned long) addr >> 2;
if ((addr & 3) || index > PT_FPSCR32) if ((addr & 3) || (index > PT_FPSCR32))
break; break;
if (index == PT_ORIG_R3) if (index == PT_ORIG_R3)
break; break;
if (index < PT_FPR0) { if (index < PT_FPR0) {
ret = put_reg(child, index, data); ret = put_reg(child, index, data);
} else { } else {
if (child->thread.regs->msr & MSR_FP) if (child->thread.regs->msr & MSR_FP)
giveup_fpu(child); giveup_fpu(child);
/* the user space code considers the floating point to be /*
* an array of unsigned int (32 bits) - the index passed * the user space code considers the floating point
* in is based on this assumption. * to be an array of unsigned int (32 bits) - the
*/ * index passed in is based on this assumption.
*/
((unsigned int *)child->thread.fpr)[index - PT_FPR0] = data; ((unsigned int *)child->thread.fpr)[index - PT_FPR0] = data;
ret = 0; ret = 0;
} }
break; break;
} }
/* Write 4 bytes into the other process' pt_regs area */ /*
/* data is the 4 bytes that the user wants written */ * Write 4 bytes into the other process' pt_regs area
/* addr is the offset into the other process' pt_regs structure that is to be written into */ * data is the 4 bytes that the user wants written
/* (this is run in a 32-bit process looking at a 64-bit process) */ * addr is the offset into the other process' pt_regs structure
case PPC_PTRACE_POKEUSR_3264: * that is to be written into
{ * (this is run in a 32-bit process looking at a 64-bit process)
*/
case PPC_PTRACE_POKEUSR_3264: {
u32 index; u32 index;
u32 numReg; u32 numReg;
ret = -EIO; ret = -EIO;
/* Determine which register the user wants */ /* Determine which register the user wants */
index = (u64)addr >> 2; /* Divide addr by 4 */ index = (u64)addr >> 2;
numReg = index / 2; numReg = index / 2;
/*
/* Validate the input - check to see if address is on the wrong boundary or beyond the end of the user area */ * Validate the input - check to see if address is on the
if ((addr & 3) || numReg > PT_FPSCR) * wrong boundary or beyond the end of the user area
*/
if ((addr & 3) || (numReg > PT_FPSCR))
break; break;
/* Insure it is a register we let them change */ /* Insure it is a register we let them change */
if ((numReg == PT_ORIG_R3) || ((numReg > PT_CCR) && (numReg < PT_FPR0))) if ((numReg == PT_ORIG_R3)
|| ((numReg > PT_CCR) && (numReg < PT_FPR0)))
break; break;
if (numReg >= PT_FPR0) {
if (numReg >= PT_FPR0)
{
if (child->thread.regs->msr & MSR_FP) if (child->thread.regs->msr & MSR_FP)
giveup_fpu(child); giveup_fpu(child);
} }
if (numReg == PT_MSR) if (numReg == PT_MSR)
data = (data & MSR_DEBUGCHANGE) | (child->thread.regs->msr & ~MSR_DEBUGCHANGE); data = (data & MSR_DEBUGCHANGE)
| (child->thread.regs->msr & ~MSR_DEBUGCHANGE);
((u32*)child->thread.regs)[index] = data; ((u32*)child->thread.regs)[index] = data;
ret = 0; ret = 0;
break; break;
...@@ -351,8 +306,8 @@ int sys32_ptrace(long request, long pid, unsigned long addr, unsigned long data) ...@@ -351,8 +306,8 @@ int sys32_ptrace(long request, long pid, unsigned long addr, unsigned long data)
} }
/* /*
* 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: {
......
/*
* 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