lkml.org 
[lkml]   [2014]   [Nov]   [11]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH V4 5/8] powerpc, ptrace: Enable vr_(get/set) for transactional memory
    Date
    This patch enables the vr_get which gets the running value of all
    the VMX registers and the vr_set which sets the running value of
    of all the VMX registers to accommodate in transaction ptrace
    interface based requests.

    Signed-off-by: Anshuman Khandual <khandual@linux.vnet.ibm.com>
    ---
    arch/powerpc/kernel/ptrace.c | 94 ++++++++++++++++++++++++++++++++++++++++++--
    1 file changed, 91 insertions(+), 3 deletions(-)

    diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c
    index fd36b32..2bbbd10 100644
    --- a/arch/powerpc/kernel/ptrace.c
    +++ b/arch/powerpc/kernel/ptrace.c
    @@ -523,10 +523,30 @@ static int vr_active(struct task_struct *target,
    return target->thread.used_vr ? regset->n : 0;
    }

    +/*
    + * vr_get
    + *
    + * When the transaction is active, 'transact_vr' holds the current running
    + * value of all the VMX registers and 'vr_state' holds the last checkpointed
    + * value of all the VMX registers for the current transaction to fall back
    + * on in case it aborts. When transaction is not active 'vr_state' holds
    + * the current running state of all the VMX registers. So this function which
    + * gets the current running values of all the VMX registers, needs to know
    + * whether any transaction is active or not.
    + *
    + * Userspace interface buffer layout:
    + *
    + * struct data {
    + * vector128 vr[32];
    + * vector128 vscr;
    + * vector128 vrsave;
    + * };
    + */
    static int vr_get(struct task_struct *target, const struct user_regset *regset,
    unsigned int pos, unsigned int count,
    void *kbuf, void __user *ubuf)
    {
    + struct thread_vr_state *addr;
    int ret;

    flush_altivec_to_thread(target);
    @@ -534,8 +554,19 @@ static int vr_get(struct task_struct *target, const struct user_regset *regset,
    BUILD_BUG_ON(offsetof(struct thread_vr_state, vscr) !=
    offsetof(struct thread_vr_state, vr[32]));

    +#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
    + if (MSR_TM_ACTIVE(target->thread.regs->msr)) {
    + flush_fp_to_thread(target);
    + flush_tmregs_to_thread(target);
    + addr = &target->thread.transact_vr;
    + } else {
    + addr = &target->thread.vr_state;
    + }
    +#else
    + addr = &target->thread.vr_state;
    +#endif
    ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
    - &target->thread.vr_state, 0,
    + addr, 0,
    33 * sizeof(vector128));
    if (!ret) {
    /*
    @@ -546,7 +577,16 @@ static int vr_get(struct task_struct *target, const struct user_regset *regset,
    u32 word;
    } vrsave;
    memset(&vrsave, 0, sizeof(vrsave));
    +
    +#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
    + if (MSR_TM_ACTIVE(target->thread.regs->msr))
    + vrsave.word = target->thread.transact_vrsave;
    + else
    + vrsave.word = target->thread.vrsave;
    +#else
    vrsave.word = target->thread.vrsave;
    +#endif
    +
    ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, &vrsave,
    33 * sizeof(vector128), -1);
    }
    @@ -554,10 +594,30 @@ static int vr_get(struct task_struct *target, const struct user_regset *regset,
    return ret;
    }

    +/*
    + * vr_set
    + *
    + * When the transaction is active, 'transact_vr' holds the current running
    + * value of all the VMX registers and 'vr_state' holds the last checkpointed
    + * value of all the VMX registers for the current transaction to fall back
    + * on in case it aborts. When transaction is not active 'vr_state' holds
    + * the current running state of all the VMX registers. So this function which
    + * sets the current running values of all the VMX registers, needs to know
    + * whether any transaction is active or not.
    + *
    + * Userspace interface buffer layout:
    + *
    + * struct data {
    + * vector128 vr[32];
    + * vector128 vscr;
    + * vector128 vrsave;
    + * };
    + */
    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)
    {
    + struct thread_vr_state *addr;
    int ret;

    flush_altivec_to_thread(target);
    @@ -565,8 +625,19 @@ static int vr_set(struct task_struct *target, const struct user_regset *regset,
    BUILD_BUG_ON(offsetof(struct thread_vr_state, vscr) !=
    offsetof(struct thread_vr_state, vr[32]));

    +#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
    + if (MSR_TM_ACTIVE(target->thread.regs->msr)) {
    + flush_fp_to_thread(target);
    + flush_tmregs_to_thread(target);
    + addr = &target->thread.transact_vr;
    + } else {
    + addr = &target->thread.vr_state;
    + }
    +#else
    + addr = &target->thread.vr_state;
    +#endif
    ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
    - &target->thread.vr_state, 0,
    + addr, 0,
    33 * sizeof(vector128));
    if (!ret && count > 0) {
    /*
    @@ -577,11 +648,28 @@ static int vr_set(struct task_struct *target, const struct user_regset *regset,
    u32 word;
    } vrsave;
    memset(&vrsave, 0, sizeof(vrsave));
    +
    +#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
    + if (MSR_TM_ACTIVE(target->thread.regs->msr))
    + vrsave.word = target->thread.transact_vrsave;
    + else
    + vrsave.word = target->thread.vrsave;
    +#else
    vrsave.word = target->thread.vrsave;
    +#endif
    ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &vrsave,
    33 * sizeof(vector128), -1);
    - if (!ret)
    + if (!ret) {
    +
    +#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
    + if (MSR_TM_ACTIVE(target->thread.regs->msr))
    + target->thread.transact_vrsave = vrsave.word;
    + else
    + target->thread.vrsave = vrsave.word;
    +#else
    target->thread.vrsave = vrsave.word;
    +#endif
    + }
    }

    return ret;
    --
    1.9.3


    \
     
     \ /
      Last update: 2014-11-11 07:01    [W:3.987 / U:0.036 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site