Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 
0003 #include <linux/regset.h>
0004 
0005 #include <asm/switch_to.h>
0006 
0007 #include "ptrace-decl.h"
0008 
0009 /*
0010  * Regardless of transactions, 'fp_state' holds the current running
0011  * value of all FPR registers and 'ckfp_state' holds the last checkpointed
0012  * value of all FPR registers for the current transaction.
0013  *
0014  * Userspace interface buffer layout:
0015  *
0016  * struct data {
0017  *  u64 fpr[32];
0018  *  u64 fpscr;
0019  * };
0020  */
0021 int fpr_get(struct task_struct *target, const struct user_regset *regset,
0022         struct membuf to)
0023 {
0024     u64 buf[33];
0025     int i;
0026 
0027     flush_fp_to_thread(target);
0028 
0029     /* copy to local buffer then write that out */
0030     for (i = 0; i < 32 ; i++)
0031         buf[i] = target->thread.TS_FPR(i);
0032     buf[32] = target->thread.fp_state.fpscr;
0033     return membuf_write(&to, buf, 33 * sizeof(u64));
0034 }
0035 
0036 /*
0037  * Regardless of transactions, 'fp_state' holds the current running
0038  * value of all FPR registers and 'ckfp_state' holds the last checkpointed
0039  * value of all FPR registers for the current transaction.
0040  *
0041  * Userspace interface buffer layout:
0042  *
0043  * struct data {
0044  *  u64 fpr[32];
0045  *  u64 fpscr;
0046  * };
0047  *
0048  */
0049 int fpr_set(struct task_struct *target, const struct user_regset *regset,
0050         unsigned int pos, unsigned int count,
0051         const void *kbuf, const void __user *ubuf)
0052 {
0053     u64 buf[33];
0054     int i;
0055 
0056     flush_fp_to_thread(target);
0057 
0058     for (i = 0; i < 32 ; i++)
0059         buf[i] = target->thread.TS_FPR(i);
0060     buf[32] = target->thread.fp_state.fpscr;
0061 
0062     /* copy to local buffer then write that out */
0063     i = user_regset_copyin(&pos, &count, &kbuf, &ubuf, buf, 0, -1);
0064     if (i)
0065         return i;
0066 
0067     for (i = 0; i < 32 ; i++)
0068         target->thread.TS_FPR(i) = buf[i];
0069     target->thread.fp_state.fpscr = buf[32];
0070     return 0;
0071 }
0072 
0073 /*
0074  * Currently to set and get all the vsx state, you need to call
0075  * the fp and VMX calls as well.  This only get/sets the lower 32
0076  * 128bit VSX registers.
0077  */
0078 
0079 int vsr_active(struct task_struct *target, const struct user_regset *regset)
0080 {
0081     flush_vsx_to_thread(target);
0082     return target->thread.used_vsr ? regset->n : 0;
0083 }
0084 
0085 /*
0086  * Regardless of transactions, 'fp_state' holds the current running
0087  * value of all FPR registers and 'ckfp_state' holds the last
0088  * checkpointed value of all FPR registers for the current
0089  * transaction.
0090  *
0091  * Userspace interface buffer layout:
0092  *
0093  * struct data {
0094  *  u64 vsx[32];
0095  * };
0096  */
0097 int vsr_get(struct task_struct *target, const struct user_regset *regset,
0098         struct membuf to)
0099 {
0100     u64 buf[32];
0101     int i;
0102 
0103     flush_tmregs_to_thread(target);
0104     flush_fp_to_thread(target);
0105     flush_altivec_to_thread(target);
0106     flush_vsx_to_thread(target);
0107 
0108     for (i = 0; i < 32 ; i++)
0109         buf[i] = target->thread.fp_state.fpr[i][TS_VSRLOWOFFSET];
0110 
0111     return membuf_write(&to, buf, 32 * sizeof(double));
0112 }
0113 
0114 /*
0115  * Regardless of transactions, 'fp_state' holds the current running
0116  * value of all FPR registers and 'ckfp_state' holds the last
0117  * checkpointed value of all FPR registers for the current
0118  * transaction.
0119  *
0120  * Userspace interface buffer layout:
0121  *
0122  * struct data {
0123  *  u64 vsx[32];
0124  * };
0125  */
0126 int vsr_set(struct task_struct *target, const struct user_regset *regset,
0127         unsigned int pos, unsigned int count,
0128         const void *kbuf, const void __user *ubuf)
0129 {
0130     u64 buf[32];
0131     int ret, i;
0132 
0133     flush_tmregs_to_thread(target);
0134     flush_fp_to_thread(target);
0135     flush_altivec_to_thread(target);
0136     flush_vsx_to_thread(target);
0137 
0138     for (i = 0; i < 32 ; i++)
0139         buf[i] = target->thread.fp_state.fpr[i][TS_VSRLOWOFFSET];
0140 
0141     ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
0142                  buf, 0, 32 * sizeof(double));
0143     if (!ret)
0144         for (i = 0; i < 32 ; i++)
0145             target->thread.fp_state.fpr[i][TS_VSRLOWOFFSET] = buf[i];
0146 
0147     return ret;
0148 }