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 } 325