1 // SPDX-License-Identifier: GPL-2.0-or-later 2 3 #include <linux/regset.h> 4 #include <linux/elf.h> 5 6 #include <asm/switch_to.h> 7 8 #include "ptrace-decl.h" 9 10 /* 11 * Get/set all the altivec registers vr0..vr31, vscr, vrsave, in one go. 12 * The transfer totals 34 quadword. Quadwords 0-31 contain the 13 * corresponding vector registers. Quadword 32 contains the vscr as the 14 * last word (offset 12) within that quadword. Quadword 33 contains the 15 * vrsave as the first word (offset 0) within the quadword. 16 * 17 * This definition of the VMX state is compatible with the current PPC32 18 * ptrace interface. This allows signal handling and ptrace to use the 19 * same structures. This also simplifies the implementation of a bi-arch 20 * (combined (32- and 64-bit) gdb. 21 */ 22 23 int vr_active(struct task_struct *target, const struct user_regset *regset) 24 { 25 flush_altivec_to_thread(target); 26 return target->thread.used_vr ? regset->n : 0; 27 } 28 29 /* 30 * Regardless of transactions, 'vr_state' holds the current running 31 * value of all the VMX registers and 'ckvr_state' holds the last 32 * checkpointed value of all the VMX registers for the current 33 * transaction to fall back on in case it aborts. 34 * 35 * Userspace interface buffer layout: 36 * 37 * struct data { 38 * vector128 vr[32]; 39 * vector128 vscr; 40 * vector128 vrsave; 41 * }; 42 */ 43 int vr_get(struct task_struct *target, const struct user_regset *regset, 44 unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf) 45 { 46 int ret; 47 48 flush_altivec_to_thread(target); 49 50 BUILD_BUG_ON(offsetof(struct thread_vr_state, vscr) != 51 offsetof(struct thread_vr_state, vr[32])); 52 53 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, 54 &target->thread.vr_state, 0, 55 33 * sizeof(vector128)); 56 if (!ret) { 57 /* 58 * Copy out only the low-order word of vrsave. 59 */ 60 int start, end; 61 union { 62 elf_vrreg_t reg; 63 u32 word; 64 } vrsave; 65 memset(&vrsave, 0, sizeof(vrsave)); 66 67 vrsave.word = target->thread.vrsave; 68 69 start = 33 * sizeof(vector128); 70 end = start + sizeof(vrsave); 71 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, &vrsave, 72 start, end); 73 } 74 75 return ret; 76 } 77 78 /* 79 * Regardless of transactions, 'vr_state' holds the current running 80 * value of all the VMX registers and 'ckvr_state' holds the last 81 * checkpointed value of all the VMX registers for the current 82 * transaction to fall back on in case it aborts. 83 * 84 * Userspace interface buffer layout: 85 * 86 * struct data { 87 * vector128 vr[32]; 88 * vector128 vscr; 89 * vector128 vrsave; 90 * }; 91 */ 92 int vr_set(struct task_struct *target, const struct user_regset *regset, 93 unsigned int pos, unsigned int count, 94 const void *kbuf, const void __user *ubuf) 95 { 96 int ret; 97 98 flush_altivec_to_thread(target); 99 100 BUILD_BUG_ON(offsetof(struct thread_vr_state, vscr) != 101 offsetof(struct thread_vr_state, vr[32])); 102 103 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, 104 &target->thread.vr_state, 0, 105 33 * sizeof(vector128)); 106 if (!ret && count > 0) { 107 /* 108 * We use only the first word of vrsave. 109 */ 110 int start, end; 111 union { 112 elf_vrreg_t reg; 113 u32 word; 114 } vrsave; 115 memset(&vrsave, 0, sizeof(vrsave)); 116 117 vrsave.word = target->thread.vrsave; 118 119 start = 33 * sizeof(vector128); 120 end = start + sizeof(vrsave); 121 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &vrsave, 122 start, end); 123 if (!ret) 124 target->thread.vrsave = vrsave.word; 125 } 126 127 return ret; 128 } 129