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 struct membuf to) 45 { 46 union { 47 elf_vrreg_t reg; 48 u32 word; 49 } vrsave; 50 51 flush_altivec_to_thread(target); 52 53 BUILD_BUG_ON(offsetof(struct thread_vr_state, vscr) != 54 offsetof(struct thread_vr_state, vr[32])); 55 56 membuf_write(&to, &target->thread.vr_state, 33 * sizeof(vector128)); 57 /* 58 * Copy out only the low-order word of vrsave. 59 */ 60 memset(&vrsave, 0, sizeof(vrsave)); 61 vrsave.word = target->thread.vrsave; 62 return membuf_write(&to, &vrsave, sizeof(vrsave)); 63 } 64 65 /* 66 * Regardless of transactions, 'vr_state' holds the current running 67 * value of all the VMX registers and 'ckvr_state' holds the last 68 * checkpointed value of all the VMX registers for the current 69 * transaction to fall back on in case it aborts. 70 * 71 * Userspace interface buffer layout: 72 * 73 * struct data { 74 * vector128 vr[32]; 75 * vector128 vscr; 76 * vector128 vrsave; 77 * }; 78 */ 79 int vr_set(struct task_struct *target, const struct user_regset *regset, 80 unsigned int pos, unsigned int count, 81 const void *kbuf, const void __user *ubuf) 82 { 83 int ret; 84 85 flush_altivec_to_thread(target); 86 87 BUILD_BUG_ON(offsetof(struct thread_vr_state, vscr) != 88 offsetof(struct thread_vr_state, vr[32])); 89 90 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, 91 &target->thread.vr_state, 0, 92 33 * sizeof(vector128)); 93 if (!ret && count > 0) { 94 /* 95 * We use only the first word of vrsave. 96 */ 97 int start, end; 98 union { 99 elf_vrreg_t reg; 100 u32 word; 101 } vrsave; 102 memset(&vrsave, 0, sizeof(vrsave)); 103 104 vrsave.word = target->thread.vrsave; 105 106 start = 33 * sizeof(vector128); 107 end = start + sizeof(vrsave); 108 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &vrsave, 109 start, end); 110 if (!ret) 111 target->thread.vrsave = vrsave.word; 112 } 113 114 return ret; 115 } 116