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
23int 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 */
43int 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(s: &to, v: &vrsave, size: 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 */
79int 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: &pos, count: &count, kbuf: &kbuf, ubuf: &ubuf, data: &vrsave,
109 start_pos: start, end_pos: end);
110 if (!ret)
111 target->thread.vrsave = vrsave.word;
112 }
113
114 return ret;
115}
116

source code of linux/arch/powerpc/kernel/ptrace/ptrace-altivec.c