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