1 // SPDX-License-Identifier: GPL-2.0-or-later 2 3 #include <linux/regset.h> 4 5 #include <asm/switch_to.h> 6 7 #include "ptrace-decl.h" 8 9 /* 10 * Regardless of transactions, 'fp_state' holds the current running 11 * value of all FPR registers and 'ckfp_state' holds the last checkpointed 12 * value of all FPR registers for the current transaction. 13 * 14 * Userspace interface buffer layout: 15 * 16 * struct data { 17 * u64 fpr[32]; 18 * u64 fpscr; 19 * }; 20 */ 21 int fpr_get(struct task_struct *target, const struct user_regset *regset, 22 unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf) 23 { 24 u64 buf[33]; 25 int i; 26 27 flush_fp_to_thread(target); 28 29 /* copy to local buffer then write that out */ 30 for (i = 0; i < 32 ; i++) 31 buf[i] = target->thread.TS_FPR(i); 32 buf[32] = target->thread.fp_state.fpscr; 33 return user_regset_copyout(&pos, &count, &kbuf, &ubuf, buf, 0, -1); 34 } 35 36 /* 37 * Regardless of transactions, 'fp_state' holds the current running 38 * value of all FPR registers and 'ckfp_state' holds the last checkpointed 39 * value of all FPR registers for the current transaction. 40 * 41 * Userspace interface buffer layout: 42 * 43 * struct data { 44 * u64 fpr[32]; 45 * u64 fpscr; 46 * }; 47 * 48 */ 49 int fpr_set(struct task_struct *target, const struct user_regset *regset, 50 unsigned int pos, unsigned int count, 51 const void *kbuf, const void __user *ubuf) 52 { 53 u64 buf[33]; 54 int i; 55 56 flush_fp_to_thread(target); 57 58 for (i = 0; i < 32 ; i++) 59 buf[i] = target->thread.TS_FPR(i); 60 buf[32] = target->thread.fp_state.fpscr; 61 62 /* copy to local buffer then write that out */ 63 i = user_regset_copyin(&pos, &count, &kbuf, &ubuf, buf, 0, -1); 64 if (i) 65 return i; 66 67 for (i = 0; i < 32 ; i++) 68 target->thread.TS_FPR(i) = buf[i]; 69 target->thread.fp_state.fpscr = buf[32]; 70 return 0; 71 } 72 73 /* 74 * Currently to set and and get all the vsx state, you need to call 75 * the fp and VMX calls as well. This only get/sets the lower 32 76 * 128bit VSX registers. 77 */ 78 79 int vsr_active(struct task_struct *target, const struct user_regset *regset) 80 { 81 flush_vsx_to_thread(target); 82 return target->thread.used_vsr ? regset->n : 0; 83 } 84 85 /* 86 * Regardless of transactions, 'fp_state' holds the current running 87 * value of all FPR registers and 'ckfp_state' holds the last 88 * checkpointed value of all FPR registers for the current 89 * transaction. 90 * 91 * Userspace interface buffer layout: 92 * 93 * struct data { 94 * u64 vsx[32]; 95 * }; 96 */ 97 int vsr_get(struct task_struct *target, const struct user_regset *regset, 98 unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf) 99 { 100 u64 buf[32]; 101 int ret, i; 102 103 flush_tmregs_to_thread(target); 104 flush_fp_to_thread(target); 105 flush_altivec_to_thread(target); 106 flush_vsx_to_thread(target); 107 108 for (i = 0; i < 32 ; i++) 109 buf[i] = target->thread.fp_state.fpr[i][TS_VSRLOWOFFSET]; 110 111 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, 112 buf, 0, 32 * sizeof(double)); 113 114 return ret; 115 } 116 117 /* 118 * Regardless of transactions, 'fp_state' holds the current running 119 * value of all FPR registers and 'ckfp_state' holds the last 120 * checkpointed value of all FPR registers for the current 121 * transaction. 122 * 123 * Userspace interface buffer layout: 124 * 125 * struct data { 126 * u64 vsx[32]; 127 * }; 128 */ 129 int vsr_set(struct task_struct *target, const struct user_regset *regset, 130 unsigned int pos, unsigned int count, 131 const void *kbuf, const void __user *ubuf) 132 { 133 u64 buf[32]; 134 int ret, i; 135 136 flush_tmregs_to_thread(target); 137 flush_fp_to_thread(target); 138 flush_altivec_to_thread(target); 139 flush_vsx_to_thread(target); 140 141 for (i = 0; i < 32 ; i++) 142 buf[i] = target->thread.fp_state.fpr[i][TS_VSRLOWOFFSET]; 143 144 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, 145 buf, 0, 32 * sizeof(double)); 146 if (!ret) 147 for (i = 0; i < 32 ; i++) 148 target->thread.fp_state.fpr[i][TS_VSRLOWOFFSET] = buf[i]; 149 150 return ret; 151 } 152