Automatic date update in version.in
[external/binutils.git] / gdb / nat / aarch64-sve-linux-ptrace.c
1 /* Common target dependent for AArch64 systems.
2
3    Copyright (C) 2018-2019 Free Software Foundation, Inc.
4
5    This file is part of GDB.
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
19
20 #include <sys/utsname.h>
21 #include <sys/uio.h>
22 #include "common/common-defs.h"
23 #include "elf/external.h"
24 #include "elf/common.h"
25 #include "aarch64-sve-linux-ptrace.h"
26 #include "arch/aarch64.h"
27 #include "common/common-regcache.h"
28 #include "common/byte-vector.h"
29
30 static bool vq_change_warned = false;
31
32 /* See nat/aarch64-sve-linux-ptrace.h.  */
33
34 uint64_t
35 aarch64_sve_get_vq (int tid)
36 {
37   struct iovec iovec;
38   struct user_sve_header header;
39
40   iovec.iov_len = sizeof (header);
41   iovec.iov_base = &header;
42
43   /* Ptrace gives the vector length in bytes.  Convert it to VQ, the number of
44      128bit chunks in a Z register.  We use VQ because 128bits is the minimum
45      a Z register can increase in size.  */
46
47   if (ptrace (PTRACE_GETREGSET, tid, NT_ARM_SVE, &iovec) < 0)
48     {
49       /* SVE is not supported.  */
50       return 0;
51     }
52
53   uint64_t vq = sve_vq_from_vl (header.vl);
54
55   if (!sve_vl_valid (header.vl))
56     {
57       warning (_("Invalid SVE state from kernel; SVE disabled."));
58       return 0;
59     }
60
61   return vq;
62 }
63
64 /* See nat/aarch64-sve-linux-ptrace.h.  */
65
66 std::unique_ptr<gdb_byte[]>
67 aarch64_sve_get_sveregs (int tid)
68 {
69   struct iovec iovec;
70   uint64_t vq = aarch64_sve_get_vq (tid);
71
72   if (vq == 0)
73     perror_with_name (_("Unable to fetch SVE register header"));
74
75   /* A ptrace call with NT_ARM_SVE will return a header followed by either a
76      dump of all the SVE and FP registers, or an fpsimd structure (identical to
77      the one returned by NT_FPREGSET) if the kernel has not yet executed any
78      SVE code.  Make sure we allocate enough space for a full SVE dump.  */
79
80   iovec.iov_len = SVE_PT_SIZE (vq, SVE_PT_REGS_SVE);
81   std::unique_ptr<gdb_byte[]> buf (new gdb_byte[iovec.iov_len]);
82   iovec.iov_base = buf.get ();
83
84   if (ptrace (PTRACE_GETREGSET, tid, NT_ARM_SVE, &iovec) < 0)
85     perror_with_name (_("Unable to fetch SVE registers"));
86
87   return buf;
88 }
89
90 /* See nat/aarch64-sve-linux-ptrace.h.  */
91
92 void
93 aarch64_sve_regs_copy_to_reg_buf (struct reg_buffer_common *reg_buf,
94                                   const void *buf)
95 {
96   char *base = (char *) buf;
97   struct user_sve_header *header = (struct user_sve_header *) buf;
98   uint64_t vq, vg_reg_buf = 0;
99
100   vq = sve_vq_from_vl (header->vl);
101
102   /* Sanity check the data in the header.  */
103   if (!sve_vl_valid (header->vl)
104       || SVE_PT_SIZE (vq, header->flags) != header->size)
105     error (_("Invalid SVE header from kernel."));
106
107   if (REG_VALID == reg_buf->get_register_status (AARCH64_SVE_VG_REGNUM))
108     reg_buf->raw_collect (AARCH64_SVE_VG_REGNUM, &vg_reg_buf);
109
110   if (vg_reg_buf == 0)
111     {
112       /* VG has not been set.  */
113       vg_reg_buf = sve_vg_from_vl (header->vl);
114       reg_buf->raw_supply (AARCH64_SVE_VG_REGNUM, &vg_reg_buf);
115     }
116   else if (vg_reg_buf != sve_vg_from_vl (header->vl) && !vq_change_warned)
117     {
118       /* Vector length on the running process has changed.  GDB currently does
119          not support this and will result in GDB showing incorrect partially
120          incorrect data for the vector registers.  Warn once and continue.  We
121          do not expect many programs to exhibit this behaviour.  To fix this
122          we need to spot the change earlier and generate a new target
123          descriptor.  */
124       warning (_("SVE Vector length has changed (%ld to %d). "
125                  "Vector registers may show incorrect data."),
126                vg_reg_buf, sve_vg_from_vl (header->vl));
127       vq_change_warned = true;
128     }
129
130   if (HAS_SVE_STATE (*header))
131     {
132       /* The register dump contains a set of SVE registers.  */
133
134       for (int i = 0; i < AARCH64_SVE_Z_REGS_NUM; i++)
135         reg_buf->raw_supply (AARCH64_SVE_Z0_REGNUM + i,
136                              base + SVE_PT_SVE_ZREG_OFFSET (vq, i));
137
138       for (int i = 0; i < AARCH64_SVE_P_REGS_NUM; i++)
139         reg_buf->raw_supply (AARCH64_SVE_P0_REGNUM + i,
140                              base + SVE_PT_SVE_PREG_OFFSET (vq, i));
141
142       reg_buf->raw_supply (AARCH64_SVE_FFR_REGNUM,
143                            base + SVE_PT_SVE_FFR_OFFSET (vq));
144       reg_buf->raw_supply (AARCH64_FPSR_REGNUM,
145                            base + SVE_PT_SVE_FPSR_OFFSET (vq));
146       reg_buf->raw_supply (AARCH64_FPCR_REGNUM,
147                            base + SVE_PT_SVE_FPCR_OFFSET (vq));
148     }
149   else
150     {
151       /* There is no SVE state yet - the register dump contains a fpsimd
152          structure instead.  These registers still exist in the hardware, but
153          the kernel has not yet initialised them, and so they will be null.  */
154
155       char *zero_reg = (char *) alloca (SVE_PT_SVE_ZREG_SIZE (vq));
156       struct user_fpsimd_state *fpsimd
157         = (struct user_fpsimd_state *)(base + SVE_PT_FPSIMD_OFFSET);
158
159       /* Copy across the V registers from fpsimd structure to the Z registers,
160          ensuring the non overlapping state is set to null.  */
161
162       memset (zero_reg, 0, SVE_PT_SVE_ZREG_SIZE (vq));
163
164       for (int i = 0; i < AARCH64_SVE_Z_REGS_NUM; i++)
165         {
166           memcpy (zero_reg, &fpsimd->vregs[i], sizeof (__int128_t));
167           reg_buf->raw_supply (AARCH64_SVE_Z0_REGNUM + i, zero_reg);
168         }
169
170       reg_buf->raw_supply (AARCH64_FPSR_REGNUM, &fpsimd->fpsr);
171       reg_buf->raw_supply (AARCH64_FPCR_REGNUM, &fpsimd->fpcr);
172
173       /* Clear the SVE only registers.  */
174
175       for (int i = 0; i < AARCH64_SVE_P_REGS_NUM; i++)
176         reg_buf->raw_supply (AARCH64_SVE_P0_REGNUM + i, zero_reg);
177
178       reg_buf->raw_supply (AARCH64_SVE_FFR_REGNUM, zero_reg);
179     }
180 }
181
182 /* See nat/aarch64-sve-linux-ptrace.h.  */
183
184 void
185 aarch64_sve_regs_copy_from_reg_buf (const struct reg_buffer_common *reg_buf,
186                                     void *buf)
187 {
188   struct user_sve_header *header = (struct user_sve_header *) buf;
189   char *base = (char *) buf;
190   uint64_t vq, vg_reg_buf = 0;
191
192   vq = sve_vq_from_vl (header->vl);
193
194   /* Sanity check the data in the header.  */
195   if (!sve_vl_valid (header->vl)
196       || SVE_PT_SIZE (vq, header->flags) != header->size)
197     error (_("Invalid SVE header from kernel."));
198
199   if (REG_VALID == reg_buf->get_register_status (AARCH64_SVE_VG_REGNUM))
200     reg_buf->raw_collect (AARCH64_SVE_VG_REGNUM, &vg_reg_buf);
201
202   if (vg_reg_buf != 0 && vg_reg_buf != sve_vg_from_vl (header->vl))
203     {
204       /* Vector length on the running process has changed.  GDB currently does
205          not support this and will result in GDB writing invalid data back to
206          the vector registers.  Error and exit.  We do not expect many programs
207          to exhibit this behaviour.  To fix this we need to spot the change
208          earlier and generate a new target descriptor.  */
209       error (_("SVE Vector length has changed (%ld to %d). "
210                "Cannot write back registers."),
211              vg_reg_buf, sve_vg_from_vl (header->vl));
212     }
213
214   if (!HAS_SVE_STATE (*header))
215     {
216       /* There is no SVE state yet - the register dump contains a fpsimd
217          structure instead.  Where possible we want to write the reg_buf data
218          back to the kernel using the fpsimd structure.  However, if we cannot
219          then we'll need to reformat the fpsimd into a full SVE structure,
220          resulting in the initialization of SVE state written back to the
221          kernel, which is why we try to avoid it.  */
222
223       bool has_sve_state = false;
224       char *zero_reg = (char *) alloca (SVE_PT_SVE_ZREG_SIZE (vq));
225       struct user_fpsimd_state *fpsimd
226         = (struct user_fpsimd_state *)(base + SVE_PT_FPSIMD_OFFSET);
227
228       memset (zero_reg, 0, SVE_PT_SVE_ZREG_SIZE (vq));
229
230       /* Check in the reg_buf if any of the Z registers are set after the
231          first 128 bits, or if any of the other SVE registers are set.  */
232
233       for (int i = 0; i < AARCH64_SVE_Z_REGS_NUM; i++)
234         {
235           has_sve_state |= reg_buf->raw_compare (AARCH64_SVE_Z0_REGNUM + i,
236                                                  zero_reg, sizeof (__int128_t));
237           if (has_sve_state)
238             break;
239         }
240
241       if (!has_sve_state)
242         for (int i = 0; i < AARCH64_SVE_P_REGS_NUM; i++)
243           {
244             has_sve_state |= reg_buf->raw_compare (AARCH64_SVE_P0_REGNUM + i,
245                                                    zero_reg, 0);
246             if (has_sve_state)
247               break;
248           }
249
250       if (!has_sve_state)
251           has_sve_state |= reg_buf->raw_compare (AARCH64_SVE_FFR_REGNUM,
252                                                  zero_reg, 0);
253
254       /* If no SVE state exists, then use the existing fpsimd structure to
255          write out state and return.  */
256       if (!has_sve_state)
257         {
258           /* The collects of the Z registers will overflow the size of a vreg.
259              There is enough space in the structure to allow for this, but we
260              cannot overflow into the next register as we might not be
261              collecting every register.  */
262
263           for (int i = 0; i < AARCH64_SVE_Z_REGS_NUM; i++)
264             {
265               if (REG_VALID
266                   == reg_buf->get_register_status (AARCH64_SVE_Z0_REGNUM + i))
267                 {
268                   reg_buf->raw_collect (AARCH64_SVE_Z0_REGNUM + i, zero_reg);
269                   memcpy (&fpsimd->vregs[i], zero_reg, sizeof (__int128_t));
270                 }
271             }
272
273           if (REG_VALID == reg_buf->get_register_status (AARCH64_FPSR_REGNUM))
274             reg_buf->raw_collect (AARCH64_FPSR_REGNUM, &fpsimd->fpsr);
275           if (REG_VALID == reg_buf->get_register_status (AARCH64_FPCR_REGNUM))
276             reg_buf->raw_collect (AARCH64_FPCR_REGNUM, &fpsimd->fpcr);
277
278           return;
279         }
280
281       /* Otherwise, reformat the fpsimd structure into a full SVE set, by
282          expanding the V registers (working backwards so we don't splat
283          registers before they are copied) and using null for everything else.
284          Note that enough space for a full SVE dump was originally allocated
285          for base.  */
286
287       header->flags |= SVE_PT_REGS_SVE;
288       header->size = SVE_PT_SIZE (vq, SVE_PT_REGS_SVE);
289
290       memcpy (base + SVE_PT_SVE_FPSR_OFFSET (vq), &fpsimd->fpsr,
291               sizeof (uint32_t));
292       memcpy (base + SVE_PT_SVE_FPCR_OFFSET (vq), &fpsimd->fpcr,
293               sizeof (uint32_t));
294
295       for (int i = AARCH64_SVE_Z_REGS_NUM; i >= 0 ; i--)
296         {
297           memcpy (base + SVE_PT_SVE_ZREG_OFFSET (vq, i), &fpsimd->vregs[i],
298                   sizeof (__int128_t));
299         }
300     }
301
302   /* Replace the kernel values with those from reg_buf.  */
303
304   for (int i = 0; i < AARCH64_SVE_Z_REGS_NUM; i++)
305     if (REG_VALID == reg_buf->get_register_status (AARCH64_SVE_Z0_REGNUM + i))
306       reg_buf->raw_collect (AARCH64_SVE_Z0_REGNUM + i,
307                             base + SVE_PT_SVE_ZREG_OFFSET (vq, i));
308
309   for (int i = 0; i < AARCH64_SVE_P_REGS_NUM; i++)
310     if (REG_VALID == reg_buf->get_register_status (AARCH64_SVE_P0_REGNUM + i))
311       reg_buf->raw_collect (AARCH64_SVE_P0_REGNUM + i,
312                             base + SVE_PT_SVE_PREG_OFFSET (vq, i));
313
314   if (REG_VALID == reg_buf->get_register_status (AARCH64_SVE_FFR_REGNUM))
315     reg_buf->raw_collect (AARCH64_SVE_FFR_REGNUM,
316                           base + SVE_PT_SVE_FFR_OFFSET (vq));
317   if (REG_VALID == reg_buf->get_register_status (AARCH64_FPSR_REGNUM))
318     reg_buf->raw_collect (AARCH64_FPSR_REGNUM,
319                           base + SVE_PT_SVE_FPSR_OFFSET (vq));
320   if (REG_VALID == reg_buf->get_register_status (AARCH64_FPCR_REGNUM))
321     reg_buf->raw_collect (AARCH64_FPCR_REGNUM,
322                           base + SVE_PT_SVE_FPCR_OFFSET (vq));
323
324 }