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