lkml.org 
[lkml]   [2007]   [Dec]   [20]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH -mm 11/43] powerpc user_regset altivec
    Date
    This implements user_regset-style accessors for the powerpc Altivec data,
    and rewrites the existing ptrace code in terms of those calls.

    Signed-off-by: Roland McGrath <roland@redhat.com>
    ---
    arch/powerpc/kernel/ptrace.c | 112 +++++++++++++++++++++++++++++-------------
    1 files changed, 78 insertions(+), 34 deletions(-)

    diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c
    index f1ce646..7cdf35a 100644
    --- a/arch/powerpc/kernel/ptrace.c
    +++ b/arch/powerpc/kernel/ptrace.c
    @@ -22,6 +22,7 @@
    #include <linux/errno.h>
    #include <linux/ptrace.h>
    #include <linux/regset.h>
    +#include <linux/elf.h>
    #include <linux/user.h>
    #include <linux/security.h>
    #include <linux/signal.h>
    @@ -163,30 +164,87 @@ static int set_fpregs(void __user *data, struct task_struct *task,
    * (combined (32- and 64-bit) gdb.
    */

    +static int vr_active(struct task_struct *target,
    + const struct user_regset *regset)
    +{
    + flush_altivec_to_thread(target);
    + return target->thread.used_vr ? regset->n : 0;
    +}
    +
    +static int vr_get(struct task_struct *target, const struct user_regset *regset,
    + unsigned int pos, unsigned int count,
    + void *kbuf, void __user *ubuf)
    +{
    + int ret;
    +
    + flush_altivec_to_thread(target);
    +
    + BUILD_BUG_ON(offsetof(struct thread_struct, vscr) !=
    + offsetof(struct thread_struct, vr[32]));
    +
    + ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
    + &target->thread.vr, 0,
    + 33 * sizeof(vector128));
    + if (!ret) {
    + /*
    + * Copy out only the low-order word of vrsave.
    + */
    + union {
    + elf_vrreg_t reg;
    + u32 word;
    + } vrsave;
    + memset(&vrsave, 0, sizeof(vrsave));
    + vrsave.word = target->thread.vrsave;
    + ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, &vrsave,
    + 33 * sizeof(vector128), -1);
    + }
    +
    + return ret;
    +}
    +
    +static int vr_set(struct task_struct *target, const struct user_regset *regset,
    + unsigned int pos, unsigned int count,
    + const void *kbuf, const void __user *ubuf)
    +{
    + int ret;
    +
    + flush_altivec_to_thread(target);
    +
    + BUILD_BUG_ON(offsetof(struct thread_struct, vscr) !=
    + offsetof(struct thread_struct, vr[32]));
    +
    + ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
    + &target->thread.vr, 0, 33 * sizeof(vector128));
    + if (!ret && count > 0) {
    + /*
    + * We use only the first word of vrsave.
    + */
    + union {
    + elf_vrreg_t reg;
    + u32 word;
    + } vrsave;
    + memset(&vrsave, 0, sizeof(vrsave));
    + vrsave.word = target->thread.vrsave;
    + ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &vrsave,
    + 33 * sizeof(vector128), -1);
    + if (!ret)
    + target->thread.vrsave = vrsave.word;
    + }
    +
    + return ret;
    +}
    +
    /*
    * Get contents of AltiVec register state in task TASK
    */
    static int get_vrregs(unsigned long __user *data, struct task_struct *task)
    {
    - unsigned long regsize;
    -
    - /* copy AltiVec registers VR[0] .. VR[31] */
    - regsize = 32 * sizeof(vector128);
    - if (copy_to_user(data, task->thread.vr, regsize))
    - return -EFAULT;
    - data += (regsize / sizeof(unsigned long));
    -
    - /* copy VSCR */
    - regsize = 1 * sizeof(vector128);
    - if (copy_to_user(data, &task->thread.vscr, regsize))
    + if (!access_ok(VERIFY_WRITE, data,
    + 33 * sizeof(vector128) + sizeof(u32)))
    return -EFAULT;
    - data += (regsize / sizeof(unsigned long));

    - /* copy VRSAVE */
    - if (put_user(task->thread.vrsave, (u32 __user *)data))
    - return -EFAULT;
    -
    - return 0;
    + return vr_get(task, NULL, 0, 33 * sizeof(vector128) + sizeof(u32),
    + NULL, data);
    }

    /*
    @@ -194,25 +252,11 @@ static int get_vrregs(unsigned long __user *data, struct task_struct *task)
    */
    static int set_vrregs(struct task_struct *task, unsigned long __user *data)
    {
    - unsigned long regsize;
    -
    - /* copy AltiVec registers VR[0] .. VR[31] */
    - regsize = 32 * sizeof(vector128);
    - if (copy_from_user(task->thread.vr, data, regsize))
    - return -EFAULT;
    - data += (regsize / sizeof(unsigned long));
    -
    - /* copy VSCR */
    - regsize = 1 * sizeof(vector128);
    - if (copy_from_user(&task->thread.vscr, data, regsize))
    - return -EFAULT;
    - data += (regsize / sizeof(unsigned long));
    -
    - /* copy VRSAVE */
    - if (get_user(task->thread.vrsave, (u32 __user *)data))
    + if (!access_ok(VERIFY_READ, data, 33 * sizeof(vector128) + sizeof(u32)))
    return -EFAULT;

    - return 0;
    + return vr_set(task, NULL, 0, 33 * sizeof(vector128) + sizeof(u32),
    + NULL, data);
    }
    #endif /* CONFIG_ALTIVEC */

    --
    1.5.3.6


    \
     
     \ /
      Last update: 2007-12-20 13:07    [W:0.027 / U:177.836 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site