1 /* Common target dependent for AArch64 systems.
2 
3    Copyright (C) 2018-2021 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 "gdbsupport/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 "gdbsupport/common-regcache.h"
28 #include "gdbsupport/byte-vector.h"
29 #include <endian.h>
30 
31 /* See nat/aarch64-sve-linux-ptrace.h.  */
32 
33 uint64_t
aarch64_sve_get_vq(int tid)34 aarch64_sve_get_vq (int tid)
35 {
36   struct iovec iovec;
37   struct user_sve_header header;
38 
39   iovec.iov_len = sizeof (header);
40   iovec.iov_base = &header;
41 
42   /* Ptrace gives the vector length in bytes.  Convert it to VQ, the number of
43      128bit chunks in a Z register.  We use VQ because 128bits is the minimum
44      a Z register can increase in size.  */
45 
46   if (ptrace (PTRACE_GETREGSET, tid, NT_ARM_SVE, &iovec) < 0)
47     {
48       /* SVE is not supported.  */
49       return 0;
50     }
51 
52   uint64_t vq = sve_vq_from_vl (header.vl);
53 
54   if (!sve_vl_valid (header.vl))
55     {
56       warning (_("Invalid SVE state from kernel; SVE disabled."));
57       return 0;
58     }
59 
60   return vq;
61 }
62 
63 /* See nat/aarch64-sve-linux-ptrace.h.  */
64 
65 bool
aarch64_sve_set_vq(int tid,uint64_t vq)66 aarch64_sve_set_vq (int tid, uint64_t vq)
67 {
68   struct iovec iovec;
69   struct user_sve_header header;
70 
71   iovec.iov_len = sizeof (header);
72   iovec.iov_base = &header;
73 
74   if (ptrace (PTRACE_GETREGSET, tid, NT_ARM_SVE, &iovec) < 0)
75     {
76       /* SVE is not supported.  */
77       return false;
78     }
79 
80   header.vl = sve_vl_from_vq (vq);
81 
82   if (ptrace (PTRACE_SETREGSET, tid, NT_ARM_SVE, &iovec) < 0)
83     {
84       /* Vector length change failed.  */
85       return false;
86     }
87 
88   return true;
89 }
90 
91 /* See nat/aarch64-sve-linux-ptrace.h.  */
92 
93 bool
aarch64_sve_set_vq(int tid,struct reg_buffer_common * reg_buf)94 aarch64_sve_set_vq (int tid, struct reg_buffer_common *reg_buf)
95 {
96   uint64_t reg_vg = 0;
97 
98   /* The VG register may not be valid if we've not collected any value yet.
99      This can happen, for example,  if we're restoring the regcache after an
100      inferior function call, and the VG register comes after the Z
101      registers.  */
102   if (reg_buf->get_register_status (AARCH64_SVE_VG_REGNUM) != REG_VALID)
103     {
104       /* If vg is not available yet, fetch it from ptrace.  The VG value from
105 	 ptrace is likely the correct one.  */
106       uint64_t vq = aarch64_sve_get_vq (tid);
107 
108       /* If something went wrong, just bail out.  */
109       if (vq == 0)
110 	return false;
111 
112       reg_vg = sve_vg_from_vq (vq);
113     }
114   else
115     reg_buf->raw_collect (AARCH64_SVE_VG_REGNUM, &reg_vg);
116 
117   return aarch64_sve_set_vq (tid, sve_vq_from_vg (reg_vg));
118 }
119 
120 /* See nat/aarch64-sve-linux-ptrace.h.  */
121 
122 std::unique_ptr<gdb_byte[]>
aarch64_sve_get_sveregs(int tid)123 aarch64_sve_get_sveregs (int tid)
124 {
125   struct iovec iovec;
126   uint64_t vq = aarch64_sve_get_vq (tid);
127 
128   if (vq == 0)
129     perror_with_name (_("Unable to fetch SVE register header"));
130 
131   /* A ptrace call with NT_ARM_SVE will return a header followed by either a
132      dump of all the SVE and FP registers, or an fpsimd structure (identical to
133      the one returned by NT_FPREGSET) if the kernel has not yet executed any
134      SVE code.  Make sure we allocate enough space for a full SVE dump.  */
135 
136   iovec.iov_len = SVE_PT_SIZE (vq, SVE_PT_REGS_SVE);
137   std::unique_ptr<gdb_byte[]> buf (new gdb_byte[iovec.iov_len]);
138   iovec.iov_base = buf.get ();
139 
140   if (ptrace (PTRACE_GETREGSET, tid, NT_ARM_SVE, &iovec) < 0)
141     perror_with_name (_("Unable to fetch SVE registers"));
142 
143   return buf;
144 }
145 
146 /* If we are running in BE mode, byteswap the contents
147    of SRC to DST for SIZE bytes.  Other, just copy the contents
148    from SRC to DST.  */
149 
150 static void
aarch64_maybe_swab128(gdb_byte * dst,const gdb_byte * src,size_t size)151 aarch64_maybe_swab128 (gdb_byte *dst, const gdb_byte *src, size_t size)
152 {
153   gdb_assert (src != nullptr && dst != nullptr);
154   gdb_assert (size > 1);
155 
156 #if (__BYTE_ORDER == __BIG_ENDIAN)
157   for (int i = 0; i < size - 1; i++)
158     dst[i] = src[size - i];
159 #else
160   memcpy (dst, src, size);
161 #endif
162 }
163 
164 /* See nat/aarch64-sve-linux-ptrace.h.  */
165 
166 void
aarch64_sve_regs_copy_to_reg_buf(struct reg_buffer_common * reg_buf,const void * buf)167 aarch64_sve_regs_copy_to_reg_buf (struct reg_buffer_common *reg_buf,
168 				  const void *buf)
169 {
170   char *base = (char *) buf;
171   struct user_sve_header *header = (struct user_sve_header *) buf;
172 
173   uint64_t vq = sve_vq_from_vl (header->vl);
174   uint64_t vg = sve_vg_from_vl (header->vl);
175 
176   /* Sanity check the data in the header.  */
177   if (!sve_vl_valid (header->vl)
178       || SVE_PT_SIZE (vq, header->flags) != header->size)
179     error (_("Invalid SVE header from kernel."));
180 
181   /* Update VG.  Note, the registers in the regcache will already be of the
182      correct length.  */
183   reg_buf->raw_supply (AARCH64_SVE_VG_REGNUM, &vg);
184 
185   if (HAS_SVE_STATE (*header))
186     {
187       /* The register dump contains a set of SVE registers.  */
188 
189       for (int i = 0; i < AARCH64_SVE_Z_REGS_NUM; i++)
190 	reg_buf->raw_supply (AARCH64_SVE_Z0_REGNUM + i,
191 			     base + SVE_PT_SVE_ZREG_OFFSET (vq, i));
192 
193       for (int i = 0; i < AARCH64_SVE_P_REGS_NUM; i++)
194 	reg_buf->raw_supply (AARCH64_SVE_P0_REGNUM + i,
195 			     base + SVE_PT_SVE_PREG_OFFSET (vq, i));
196 
197       reg_buf->raw_supply (AARCH64_SVE_FFR_REGNUM,
198 			   base + SVE_PT_SVE_FFR_OFFSET (vq));
199       reg_buf->raw_supply (AARCH64_FPSR_REGNUM,
200 			   base + SVE_PT_SVE_FPSR_OFFSET (vq));
201       reg_buf->raw_supply (AARCH64_FPCR_REGNUM,
202 			   base + SVE_PT_SVE_FPCR_OFFSET (vq));
203     }
204   else
205     {
206       /* WARNING: SIMD state is laid out in memory in target-endian format,
207 	 while SVE state is laid out in an endianness-independent format (LE).
208 
209 	 So we have a couple cases to consider:
210 
211 	 1 - If the target is big endian, then SIMD state is big endian,
212 	 requiring a byteswap.
213 
214 	 2 - If the target is little endian, then SIMD state is little endian,
215 	 which matches the SVE format, so no byteswap is needed. */
216 
217       /* There is no SVE state yet - the register dump contains a fpsimd
218 	 structure instead.  These registers still exist in the hardware, but
219 	 the kernel has not yet initialised them, and so they will be null.  */
220 
221       gdb_byte *reg = (gdb_byte *) alloca (SVE_PT_SVE_ZREG_SIZE (vq));
222       struct user_fpsimd_state *fpsimd
223 	= (struct user_fpsimd_state *)(base + SVE_PT_FPSIMD_OFFSET);
224 
225       /* Make sure we have a zeroed register buffer.  We will need the zero
226 	 padding below.  */
227       memset (reg, 0, SVE_PT_SVE_ZREG_SIZE (vq));
228 
229       /* Copy across the V registers from fpsimd structure to the Z registers,
230 	 ensuring the non overlapping state is set to null.  */
231 
232       for (int i = 0; i < AARCH64_SVE_Z_REGS_NUM; i++)
233 	{
234 	  /* Handle big endian/little endian SIMD/SVE conversion.  */
235 	  aarch64_maybe_swab128 (reg, (const gdb_byte *) &fpsimd->vregs[i],
236 				 V_REGISTER_SIZE);
237 	  reg_buf->raw_supply (AARCH64_SVE_Z0_REGNUM + i, reg);
238 	}
239 
240       reg_buf->raw_supply (AARCH64_FPSR_REGNUM, &fpsimd->fpsr);
241       reg_buf->raw_supply (AARCH64_FPCR_REGNUM, &fpsimd->fpcr);
242 
243       /* Clear the SVE only registers.  */
244       memset (reg, 0, SVE_PT_SVE_ZREG_SIZE (vq));
245 
246       for (int i = 0; i < AARCH64_SVE_P_REGS_NUM; i++)
247 	reg_buf->raw_supply (AARCH64_SVE_P0_REGNUM + i, reg);
248 
249       reg_buf->raw_supply (AARCH64_SVE_FFR_REGNUM, reg);
250     }
251 }
252 
253 /* See nat/aarch64-sve-linux-ptrace.h.  */
254 
255 void
aarch64_sve_regs_copy_from_reg_buf(const struct reg_buffer_common * reg_buf,void * buf)256 aarch64_sve_regs_copy_from_reg_buf (const struct reg_buffer_common *reg_buf,
257 				    void *buf)
258 {
259   struct user_sve_header *header = (struct user_sve_header *) buf;
260   char *base = (char *) buf;
261   uint64_t vq = sve_vq_from_vl (header->vl);
262 
263   /* Sanity check the data in the header.  */
264   if (!sve_vl_valid (header->vl)
265       || SVE_PT_SIZE (vq, header->flags) != header->size)
266     error (_("Invalid SVE header from kernel."));
267 
268   if (!HAS_SVE_STATE (*header))
269     {
270       /* There is no SVE state yet - the register dump contains a fpsimd
271 	 structure instead.  Where possible we want to write the reg_buf data
272 	 back to the kernel using the fpsimd structure.  However, if we cannot
273 	 then we'll need to reformat the fpsimd into a full SVE structure,
274 	 resulting in the initialization of SVE state written back to the
275 	 kernel, which is why we try to avoid it.  */
276 
277       bool has_sve_state = false;
278       gdb_byte *reg = (gdb_byte *) alloca (SVE_PT_SVE_ZREG_SIZE (vq));
279       struct user_fpsimd_state *fpsimd
280 	= (struct user_fpsimd_state *)(base + SVE_PT_FPSIMD_OFFSET);
281 
282       memset (reg, 0, SVE_PT_SVE_ZREG_SIZE (vq));
283 
284       /* Check in the reg_buf if any of the Z registers are set after the
285 	 first 128 bits, or if any of the other SVE registers are set.  */
286 
287       for (int i = 0; i < AARCH64_SVE_Z_REGS_NUM; i++)
288 	{
289 	  has_sve_state |= reg_buf->raw_compare (AARCH64_SVE_Z0_REGNUM + i,
290 						 reg, sizeof (__int128_t));
291 	  if (has_sve_state)
292 	    break;
293 	}
294 
295       if (!has_sve_state)
296 	for (int i = 0; i < AARCH64_SVE_P_REGS_NUM; i++)
297 	  {
298 	    has_sve_state |= reg_buf->raw_compare (AARCH64_SVE_P0_REGNUM + i,
299 						   reg, 0);
300 	    if (has_sve_state)
301 	      break;
302 	  }
303 
304       if (!has_sve_state)
305 	  has_sve_state |= reg_buf->raw_compare (AARCH64_SVE_FFR_REGNUM,
306 						 reg, 0);
307 
308       /* If no SVE state exists, then use the existing fpsimd structure to
309 	 write out state and return.  */
310       if (!has_sve_state)
311 	{
312 	  /* WARNING: SIMD state is laid out in memory in target-endian format,
313 	     while SVE state is laid out in an endianness-independent format
314 	     (LE).
315 
316 	     So we have a couple cases to consider:
317 
318 	     1 - If the target is big endian, then SIMD state is big endian,
319 	     requiring a byteswap.
320 
321 	     2 - If the target is little endian, then SIMD state is little
322 	     endian, which matches the SVE format, so no byteswap is needed. */
323 
324 	  /* The collects of the Z registers will overflow the size of a vreg.
325 	     There is enough space in the structure to allow for this, but we
326 	     cannot overflow into the next register as we might not be
327 	     collecting every register.  */
328 
329 	  for (int i = 0; i < AARCH64_SVE_Z_REGS_NUM; i++)
330 	    {
331 	      if (REG_VALID
332 		  == reg_buf->get_register_status (AARCH64_SVE_Z0_REGNUM + i))
333 		{
334 		  reg_buf->raw_collect (AARCH64_SVE_Z0_REGNUM + i, reg);
335 		  /* Handle big endian/little endian SIMD/SVE conversion.  */
336 		  aarch64_maybe_swab128 ((gdb_byte *) &fpsimd->vregs[i], reg,
337 					 V_REGISTER_SIZE);
338 		}
339 	    }
340 
341 	  if (REG_VALID == reg_buf->get_register_status (AARCH64_FPSR_REGNUM))
342 	    reg_buf->raw_collect (AARCH64_FPSR_REGNUM, &fpsimd->fpsr);
343 	  if (REG_VALID == reg_buf->get_register_status (AARCH64_FPCR_REGNUM))
344 	    reg_buf->raw_collect (AARCH64_FPCR_REGNUM, &fpsimd->fpcr);
345 
346 	  return;
347 	}
348 
349       /* Otherwise, reformat the fpsimd structure into a full SVE set, by
350 	 expanding the V registers (working backwards so we don't splat
351 	 registers before they are copied) and using null for everything else.
352 	 Note that enough space for a full SVE dump was originally allocated
353 	 for base.  */
354 
355       header->flags |= SVE_PT_REGS_SVE;
356       header->size = SVE_PT_SIZE (vq, SVE_PT_REGS_SVE);
357 
358       memcpy (base + SVE_PT_SVE_FPSR_OFFSET (vq), &fpsimd->fpsr,
359 	      sizeof (uint32_t));
360       memcpy (base + SVE_PT_SVE_FPCR_OFFSET (vq), &fpsimd->fpcr,
361 	      sizeof (uint32_t));
362 
363       for (int i = AARCH64_SVE_Z_REGS_NUM; i >= 0 ; i--)
364 	{
365 	  memcpy (base + SVE_PT_SVE_ZREG_OFFSET (vq, i), &fpsimd->vregs[i],
366 		  sizeof (__int128_t));
367 	}
368     }
369 
370   /* Replace the kernel values with those from reg_buf.  */
371 
372   for (int i = 0; i < AARCH64_SVE_Z_REGS_NUM; i++)
373     if (REG_VALID == reg_buf->get_register_status (AARCH64_SVE_Z0_REGNUM + i))
374       reg_buf->raw_collect (AARCH64_SVE_Z0_REGNUM + i,
375 			    base + SVE_PT_SVE_ZREG_OFFSET (vq, i));
376 
377   for (int i = 0; i < AARCH64_SVE_P_REGS_NUM; i++)
378     if (REG_VALID == reg_buf->get_register_status (AARCH64_SVE_P0_REGNUM + i))
379       reg_buf->raw_collect (AARCH64_SVE_P0_REGNUM + i,
380 			    base + SVE_PT_SVE_PREG_OFFSET (vq, i));
381 
382   if (REG_VALID == reg_buf->get_register_status (AARCH64_SVE_FFR_REGNUM))
383     reg_buf->raw_collect (AARCH64_SVE_FFR_REGNUM,
384 			  base + SVE_PT_SVE_FFR_OFFSET (vq));
385   if (REG_VALID == reg_buf->get_register_status (AARCH64_FPSR_REGNUM))
386     reg_buf->raw_collect (AARCH64_FPSR_REGNUM,
387 			  base + SVE_PT_SVE_FPSR_OFFSET (vq));
388   if (REG_VALID == reg_buf->get_register_status (AARCH64_FPCR_REGNUM))
389     reg_buf->raw_collect (AARCH64_FPCR_REGNUM,
390 			  base + SVE_PT_SVE_FPCR_OFFSET (vq));
391 
392 }
393