X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=arch%2Fppc%2Fkernel%2Fptrace.c;h=1f370cb2e03e13a4b2706a74b8a86936daeab5ae;hb=6a77f38946aaee1cd85eeec6cf4229b204c15071;hp=f9120785bd9058b92d77eea9e6e649bcbc42abc1;hpb=a8e794ca871505c8ea96cc102f4ad555c5231d7f;p=linux-2.6.git diff --git a/arch/ppc/kernel/ptrace.c b/arch/ppc/kernel/ptrace.c index f9120785b..1f370cb2e 100644 --- a/arch/ppc/kernel/ptrace.c +++ b/arch/ppc/kernel/ptrace.c @@ -35,7 +35,7 @@ /* * Set of msr bits that gdb can change on behalf of a process. */ -#ifdef CONFIG_4xx +#if defined(CONFIG_40x) || defined(CONFIG_BOOKE) #define MSR_DEBUGCHANGE 0 #else #define MSR_DEBUGCHANGE (MSR_SE | MSR_BE) @@ -77,7 +77,7 @@ static inline int put_reg(struct task_struct *task, int regno, /* * Get contents of AltiVec register state in task TASK */ -static inline int get_vrregs(unsigned long *data, struct task_struct *task) +static inline int get_vrregs(unsigned long __user *data, struct task_struct *task) { int i, j; @@ -105,7 +105,7 @@ static inline int get_vrregs(unsigned long *data, struct task_struct *task) /* * Write contents of AltiVec register state into task TASK. */ -static inline int set_vrregs(struct task_struct *task, unsigned long *data) +static inline int set_vrregs(struct task_struct *task, unsigned long __user *data) { int i, j; @@ -131,15 +131,79 @@ static inline int set_vrregs(struct task_struct *task, unsigned long *data) } #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) { -#ifdef CONFIG_4xx +#if defined(CONFIG_40x) || defined(CONFIG_BOOKE) task->thread.dbcr0 = DBCR0_IDM | DBCR0_IC; - /* MSR.DE should already be set */ + regs->msr |= MSR_DE; #else regs->msr |= MSR_SE; #endif @@ -152,8 +216,9 @@ clear_single_step(struct task_struct *task) struct pt_regs *regs = task->thread.regs; if (regs != NULL) { -#ifdef CONFIG_4xx +#if defined(CONFIG_40x) || defined(CONFIG_BOOKE) task->thread.dbcr0 = 0; + regs->msr &= ~MSR_DE; #else regs->msr &= ~MSR_SE; #endif @@ -224,7 +289,7 @@ int sys_ptrace(long request, long pid, long addr, long data) ret = -EIO; if (copied != sizeof(tmp)) break; - ret = put_user(tmp,(unsigned long *) data); + ret = put_user(tmp,(unsigned long __user *) data); break; } @@ -250,7 +315,7 @@ int sys_ptrace(long request, long pid, long addr, long data) preempt_enable(); tmp = ((unsigned long *)child->thread.fpr)[index - PT_FPR0]; } - ret = put_user(tmp,(unsigned long *) data); + ret = put_user(tmp,(unsigned long __user *) data); break; } @@ -315,7 +380,7 @@ int sys_ptrace(long request, long pid, long addr, long data) */ case PTRACE_KILL: { ret = 0; - if (child->state == TASK_ZOMBIE) /* already dead */ + if (child->exit_state == EXIT_ZOMBIE) /* already dead */ break; child->exit_code = SIGKILL; /* make sure the single step bit is not set. */ @@ -348,7 +413,7 @@ int sys_ptrace(long request, long pid, long addr, long data) if (child->thread.regs->msr & MSR_VEC) giveup_altivec(child); preempt_enable(); - ret = get_vrregs((unsigned long *)data, child); + ret = get_vrregs((unsigned long __user *)data, child); break; case PTRACE_SETVRREGS: @@ -359,7 +424,24 @@ int sys_ptrace(long request, long pid, long addr, long data) if (child->thread.regs->msr & MSR_VEC) giveup_altivec(child); preempt_enable(); - ret = set_vrregs(child, (unsigned long *)data); + ret = set_vrregs(child, (unsigned long __user *)data); + break; +#endif +#ifdef CONFIG_SPE + case PTRACE_GETEVRREGS: + /* Get the child spe register state. */ + if (child->thread.regs->msr & MSR_SPE) + giveup_spe(child); + ret = get_evrregs((unsigned long __user *)data, child); + break; + + case PTRACE_SETEVRREGS: + /* Set the child spe register state. */ + /* this is to clear the MSR_SPE bit to force a reload + * of register state from memory */ + if (child->thread.regs->msr & MSR_SPE) + giveup_spe(child); + ret = set_evrregs(child, (unsigned long __user *)data); break; #endif