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 
vr_active(struct task_struct * target,const struct user_regset * regset)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  */
vr_get(struct task_struct * target,const struct user_regset * regset,struct membuf to)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  */
vr_set(struct task_struct * target,const struct user_regset * regset,unsigned int pos,unsigned int count,const void * kbuf,const void __user * ubuf)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