summaryrefslogtreecommitdiffstats
path: root/arch/powerpc
diff options
context:
space:
mode:
authorAnshuman Khandual <khandual@linux.vnet.ibm.com>2016-07-27 22:57:34 -0400
committerMichael Ellerman <mpe@ellerman.id.au>2016-07-31 21:15:17 -0400
commit94b7d3610e5b03399f1791d7905103f5298784bc (patch)
treec644eda1914e469213a28eb260590db4bd8ad63d /arch/powerpc
parentd844e279152c27e5b1a56dc40de08ddfd99176f3 (diff)
powerpc/ptrace: Enable in transaction NT_PPC_VSX ptrace requests
This patch enables in transaction NT_PPC_VSX ptrace requests. The function vsr_get which gets the running value of all VSX registers and the function vsr_set which sets the running value of of all VSX registers work on the running set of VMX registers whose location will be different if transaction is active. This patch makes these functions adapt to situations when the transaction is active. Signed-off-by: Anshuman Khandual <khandual@linux.vnet.ibm.com> Signed-off-by: Simon Guo <wei.guo.simon@gmail.com> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Diffstat (limited to 'arch/powerpc')
-rw-r--r--arch/powerpc/kernel/ptrace.c64
1 files changed, 64 insertions, 0 deletions
diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c
index 72da7dc924f1..9c0e405dc4cd 100644
--- a/arch/powerpc/kernel/ptrace.c
+++ b/arch/powerpc/kernel/ptrace.c
@@ -681,6 +681,21 @@ static int vsr_active(struct task_struct *target,
681 return target->thread.used_vsr ? regset->n : 0; 681 return target->thread.used_vsr ? regset->n : 0;
682} 682}
683 683
684/*
685 * When the transaction is active, 'transact_fp' holds the current running
686 * value of all FPR registers and 'fp_state' holds the last checkpointed
687 * value of all FPR registers for the current transaction. When transaction
688 * is not active 'fp_state' holds the current running state of all the FPR
689 * registers. So this function which returns the current running values of
690 * all the FPR registers, needs to know whether any transaction is active
691 * or not.
692 *
693 * Userspace interface buffer layout:
694 *
695 * struct data {
696 * u64 vsx[32];
697 * };
698 */
684static int vsr_get(struct task_struct *target, const struct user_regset *regset, 699static int vsr_get(struct task_struct *target, const struct user_regset *regset,
685 unsigned int pos, unsigned int count, 700 unsigned int pos, unsigned int count,
686 void *kbuf, void __user *ubuf) 701 void *kbuf, void __user *ubuf)
@@ -688,16 +703,47 @@ static int vsr_get(struct task_struct *target, const struct user_regset *regset,
688 u64 buf[32]; 703 u64 buf[32];
689 int ret, i; 704 int ret, i;
690 705
706#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
707 flush_fp_to_thread(target);
708 flush_altivec_to_thread(target);
709 flush_tmregs_to_thread(target);
710#endif
691 flush_vsx_to_thread(target); 711 flush_vsx_to_thread(target);
692 712
713#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
714 if (MSR_TM_ACTIVE(target->thread.regs->msr)) {
715 for (i = 0; i < 32 ; i++)
716 buf[i] = target->thread.
717 transact_fp.fpr[i][TS_VSRLOWOFFSET];
718 } else {
719 for (i = 0; i < 32 ; i++)
720 buf[i] = target->thread.
721 fp_state.fpr[i][TS_VSRLOWOFFSET];
722 }
723#else
693 for (i = 0; i < 32 ; i++) 724 for (i = 0; i < 32 ; i++)
694 buf[i] = target->thread.fp_state.fpr[i][TS_VSRLOWOFFSET]; 725 buf[i] = target->thread.fp_state.fpr[i][TS_VSRLOWOFFSET];
726#endif
695 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, 727 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
696 buf, 0, 32 * sizeof(double)); 728 buf, 0, 32 * sizeof(double));
697 729
698 return ret; 730 return ret;
699} 731}
700 732
733/*
734 * When the transaction is active, 'transact_fp' holds the current running
735 * value of all FPR registers and 'fp_state' holds the last checkpointed
736 * value of all FPR registers for the current transaction. When transaction
737 * is not active 'fp_state' holds the current running state of all the FPR
738 * registers. So this function which sets the current running values of all
739 * the FPR registers, needs to know whether any transaction is active or not.
740 *
741 * Userspace interface buffer layout:
742 *
743 * struct data {
744 * u64 vsx[32];
745 * };
746 */
701static int vsr_set(struct task_struct *target, const struct user_regset *regset, 747static int vsr_set(struct task_struct *target, const struct user_regset *regset,
702 unsigned int pos, unsigned int count, 748 unsigned int pos, unsigned int count,
703 const void *kbuf, const void __user *ubuf) 749 const void *kbuf, const void __user *ubuf)
@@ -705,12 +751,30 @@ static int vsr_set(struct task_struct *target, const struct user_regset *regset,
705 u64 buf[32]; 751 u64 buf[32];
706 int ret,i; 752 int ret,i;
707 753
754#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
755 flush_fp_to_thread(target);
756 flush_altivec_to_thread(target);
757 flush_tmregs_to_thread(target);
758#endif
708 flush_vsx_to_thread(target); 759 flush_vsx_to_thread(target);
709 760
710 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, 761 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
711 buf, 0, 32 * sizeof(double)); 762 buf, 0, 32 * sizeof(double));
763
764#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
765 if (MSR_TM_ACTIVE(target->thread.regs->msr)) {
766 for (i = 0; i < 32 ; i++)
767 target->thread.transact_fp.
768 fpr[i][TS_VSRLOWOFFSET] = buf[i];
769 } else {
770 for (i = 0; i < 32 ; i++)
771 target->thread.fp_state.
772 fpr[i][TS_VSRLOWOFFSET] = buf[i];
773 }
774#else
712 for (i = 0; i < 32 ; i++) 775 for (i = 0; i < 32 ; i++)
713 target->thread.fp_state.fpr[i][TS_VSRLOWOFFSET] = buf[i]; 776 target->thread.fp_state.fpr[i][TS_VSRLOWOFFSET] = buf[i];
777#endif
714 778
715 779
716 return ret; 780 return ret;