|
@@ -36,208 +36,18 @@
|
|
|
#include <asm/system.h>
|
|
|
|
|
|
#ifdef CONFIG_PPC64
|
|
|
-#include "ptrace-common.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
|
|
|
+#include "ptrace-ppc64.h"
|
|
|
#else
|
|
|
-#define MSR_DEBUGCHANGE (MSR_SE | MSR_BE)
|
|
|
+#include "ptrace-ppc32.h"
|
|
|
#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..
|
|
|
*
|