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