1 //===-- NativeRegisterContextLinux_arm64.cpp ------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #if defined(__arm64__) || defined(__aarch64__) 10 11 #include "NativeRegisterContextLinux_arm.h" 12 #include "NativeRegisterContextLinux_arm64.h" 13 14 15 #include "lldb/Host/common/NativeProcessProtocol.h" 16 #include "lldb/Utility/DataBufferHeap.h" 17 #include "lldb/Utility/Log.h" 18 #include "lldb/Utility/RegisterValue.h" 19 #include "lldb/Utility/Status.h" 20 21 #include "Plugins/Process/Linux/NativeProcessLinux.h" 22 #include "Plugins/Process/Linux/Procfs.h" 23 #include "Plugins/Process/POSIX/ProcessPOSIXLog.h" 24 #include "Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h" 25 26 // System includes - They have to be included after framework includes because 27 // they define some macros which collide with variable names in other modules 28 #include <sys/socket.h> 29 // NT_PRSTATUS and NT_FPREGSET definition 30 #include <elf.h> 31 32 #ifndef NT_ARM_SVE 33 #define NT_ARM_SVE 0x405 /* ARM Scalable Vector Extension */ 34 #endif 35 36 #ifndef NT_ARM_PAC_MASK 37 #define NT_ARM_PAC_MASK 0x406 /* Pointer authentication code masks */ 38 #endif 39 40 #ifndef NT_ARM_TAGGED_ADDR_CTRL 41 #define NT_ARM_TAGGED_ADDR_CTRL 0x409 /* Tagged address control register */ 42 #endif 43 44 #define HWCAP_PACA (1 << 30) 45 #define HWCAP2_MTE (1 << 18) 46 47 #define REG_CONTEXT_SIZE (GetGPRSize() + GetFPRSize()) 48 49 using namespace lldb; 50 using namespace lldb_private; 51 using namespace lldb_private::process_linux; 52 53 std::unique_ptr<NativeRegisterContextLinux> 54 NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux( 55 const ArchSpec &target_arch, NativeThreadLinux &native_thread) { 56 switch (target_arch.GetMachine()) { 57 case llvm::Triple::arm: 58 return std::make_unique<NativeRegisterContextLinux_arm>(target_arch, 59 native_thread); 60 case llvm::Triple::aarch64: { 61 // Configure register sets supported by this AArch64 target. 62 // Read SVE header to check for SVE support. 63 struct user_sve_header sve_header; 64 struct iovec ioVec; 65 ioVec.iov_base = &sve_header; 66 ioVec.iov_len = sizeof(sve_header); 67 unsigned int regset = NT_ARM_SVE; 68 69 Flags opt_regsets; 70 if (NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, 71 native_thread.GetID(), ®set, 72 &ioVec, sizeof(sve_header)) 73 .Success()) 74 opt_regsets.Set(RegisterInfoPOSIX_arm64::eRegsetMaskSVE); 75 76 NativeProcessLinux &process = native_thread.GetProcess(); 77 78 llvm::Optional<uint64_t> auxv_at_hwcap = 79 process.GetAuxValue(AuxVector::AUXV_AT_HWCAP); 80 if (auxv_at_hwcap && (*auxv_at_hwcap & HWCAP_PACA)) 81 opt_regsets.Set(RegisterInfoPOSIX_arm64::eRegsetMaskPAuth); 82 83 llvm::Optional<uint64_t> auxv_at_hwcap2 = 84 process.GetAuxValue(AuxVector::AUXV_AT_HWCAP2); 85 if (auxv_at_hwcap && (*auxv_at_hwcap2 & HWCAP2_MTE)) 86 opt_regsets.Set(RegisterInfoPOSIX_arm64::eRegsetMaskMTE); 87 88 auto register_info_up = 89 std::make_unique<RegisterInfoPOSIX_arm64>(target_arch, opt_regsets); 90 return std::make_unique<NativeRegisterContextLinux_arm64>( 91 target_arch, native_thread, std::move(register_info_up)); 92 } 93 default: 94 llvm_unreachable("have no register context for architecture"); 95 } 96 } 97 98 NativeRegisterContextLinux_arm64::NativeRegisterContextLinux_arm64( 99 const ArchSpec &target_arch, NativeThreadProtocol &native_thread, 100 std::unique_ptr<RegisterInfoPOSIX_arm64> register_info_up) 101 : NativeRegisterContextRegisterInfo(native_thread, 102 register_info_up.release()) { 103 ::memset(&m_fpr, 0, sizeof(m_fpr)); 104 ::memset(&m_gpr_arm64, 0, sizeof(m_gpr_arm64)); 105 ::memset(&m_hwp_regs, 0, sizeof(m_hwp_regs)); 106 ::memset(&m_hbp_regs, 0, sizeof(m_hbp_regs)); 107 ::memset(&m_sve_header, 0, sizeof(m_sve_header)); 108 ::memset(&m_pac_mask, 0, sizeof(m_pac_mask)); 109 110 m_mte_ctrl_reg = 0; 111 112 // 16 is just a maximum value, query hardware for actual watchpoint count 113 m_max_hwp_supported = 16; 114 m_max_hbp_supported = 16; 115 116 m_refresh_hwdebug_info = true; 117 118 m_gpr_is_valid = false; 119 m_fpu_is_valid = false; 120 m_sve_buffer_is_valid = false; 121 m_sve_header_is_valid = false; 122 m_pac_mask_is_valid = false; 123 m_mte_ctrl_is_valid = false; 124 125 if (GetRegisterInfo().IsSVEEnabled()) 126 m_sve_state = SVEState::Unknown; 127 else 128 m_sve_state = SVEState::Disabled; 129 } 130 131 RegisterInfoPOSIX_arm64 & 132 NativeRegisterContextLinux_arm64::GetRegisterInfo() const { 133 return static_cast<RegisterInfoPOSIX_arm64 &>(*m_register_info_interface_up); 134 } 135 136 uint32_t NativeRegisterContextLinux_arm64::GetRegisterSetCount() const { 137 return GetRegisterInfo().GetRegisterSetCount(); 138 } 139 140 const RegisterSet * 141 NativeRegisterContextLinux_arm64::GetRegisterSet(uint32_t set_index) const { 142 return GetRegisterInfo().GetRegisterSet(set_index); 143 } 144 145 uint32_t NativeRegisterContextLinux_arm64::GetUserRegisterCount() const { 146 uint32_t count = 0; 147 for (uint32_t set_index = 0; set_index < GetRegisterSetCount(); ++set_index) 148 count += GetRegisterSet(set_index)->num_registers; 149 return count; 150 } 151 152 Status 153 NativeRegisterContextLinux_arm64::ReadRegister(const RegisterInfo *reg_info, 154 RegisterValue ®_value) { 155 Status error; 156 157 if (!reg_info) { 158 error.SetErrorString("reg_info NULL"); 159 return error; 160 } 161 162 const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; 163 164 if (reg == LLDB_INVALID_REGNUM) 165 return Status("no lldb regnum for %s", reg_info && reg_info->name 166 ? reg_info->name 167 : "<unknown register>"); 168 169 uint8_t *src; 170 uint32_t offset = LLDB_INVALID_INDEX32; 171 uint64_t sve_vg; 172 std::vector<uint8_t> sve_reg_non_live; 173 174 if (IsGPR(reg)) { 175 error = ReadGPR(); 176 if (error.Fail()) 177 return error; 178 179 offset = reg_info->byte_offset; 180 assert(offset < GetGPRSize()); 181 src = (uint8_t *)GetGPRBuffer() + offset; 182 183 } else if (IsFPR(reg)) { 184 if (m_sve_state == SVEState::Disabled) { 185 // SVE is disabled take legacy route for FPU register access 186 error = ReadFPR(); 187 if (error.Fail()) 188 return error; 189 190 offset = CalculateFprOffset(reg_info); 191 assert(offset < GetFPRSize()); 192 src = (uint8_t *)GetFPRBuffer() + offset; 193 } else { 194 // SVE enabled, we will read and cache SVE ptrace data 195 error = ReadAllSVE(); 196 if (error.Fail()) 197 return error; 198 199 // FPSR and FPCR will be located right after Z registers in 200 // SVEState::FPSIMD while in SVEState::Full they will be located at the 201 // end of register data after an alignment correction based on currently 202 // selected vector length. 203 uint32_t sve_reg_num = LLDB_INVALID_REGNUM; 204 if (reg == GetRegisterInfo().GetRegNumFPSR()) { 205 sve_reg_num = reg; 206 if (m_sve_state == SVEState::Full) 207 offset = SVE_PT_SVE_FPSR_OFFSET(sve_vq_from_vl(m_sve_header.vl)); 208 else if (m_sve_state == SVEState::FPSIMD) 209 offset = SVE_PT_FPSIMD_OFFSET + (32 * 16); 210 } else if (reg == GetRegisterInfo().GetRegNumFPCR()) { 211 sve_reg_num = reg; 212 if (m_sve_state == SVEState::Full) 213 offset = SVE_PT_SVE_FPCR_OFFSET(sve_vq_from_vl(m_sve_header.vl)); 214 else if (m_sve_state == SVEState::FPSIMD) 215 offset = SVE_PT_FPSIMD_OFFSET + (32 * 16) + 4; 216 } else { 217 // Extract SVE Z register value register number for this reg_info 218 if (reg_info->value_regs && 219 reg_info->value_regs[0] != LLDB_INVALID_REGNUM) 220 sve_reg_num = reg_info->value_regs[0]; 221 offset = CalculateSVEOffset(GetRegisterInfoAtIndex(sve_reg_num)); 222 } 223 224 assert(offset < GetSVEBufferSize()); 225 src = (uint8_t *)GetSVEBuffer() + offset; 226 } 227 } else if (IsSVE(reg)) { 228 229 if (m_sve_state == SVEState::Disabled || m_sve_state == SVEState::Unknown) 230 return Status("SVE disabled or not supported"); 231 232 if (GetRegisterInfo().IsSVERegVG(reg)) { 233 sve_vg = GetSVERegVG(); 234 src = (uint8_t *)&sve_vg; 235 } else { 236 // SVE enabled, we will read and cache SVE ptrace data 237 error = ReadAllSVE(); 238 if (error.Fail()) 239 return error; 240 241 if (m_sve_state == SVEState::FPSIMD) { 242 // In FPSIMD state SVE payload mirrors legacy fpsimd struct and so 243 // just copy 16 bytes of v register to the start of z register. All 244 // other SVE register will be set to zero. 245 sve_reg_non_live.resize(reg_info->byte_size, 0); 246 src = sve_reg_non_live.data(); 247 248 if (GetRegisterInfo().IsSVEZReg(reg)) { 249 offset = CalculateSVEOffset(reg_info); 250 assert(offset < GetSVEBufferSize()); 251 ::memcpy(sve_reg_non_live.data(), (uint8_t *)GetSVEBuffer() + offset, 252 16); 253 } 254 } else { 255 offset = CalculateSVEOffset(reg_info); 256 assert(offset < GetSVEBufferSize()); 257 src = (uint8_t *)GetSVEBuffer() + offset; 258 } 259 } 260 } else if (IsPAuth(reg)) { 261 error = ReadPAuthMask(); 262 if (error.Fail()) 263 return error; 264 265 offset = reg_info->byte_offset - GetRegisterInfo().GetPAuthOffset(); 266 assert(offset < GetPACMaskSize()); 267 src = (uint8_t *)GetPACMask() + offset; 268 } else if (IsMTE(reg)) { 269 error = ReadMTEControl(); 270 if (error.Fail()) 271 return error; 272 273 offset = reg_info->byte_offset - GetRegisterInfo().GetMTEOffset(); 274 assert(offset < GetMTEControlSize()); 275 src = (uint8_t *)GetMTEControl() + offset; 276 } else 277 return Status("failed - register wasn't recognized to be a GPR or an FPR, " 278 "write strategy unknown"); 279 280 reg_value.SetFromMemoryData(reg_info, src, reg_info->byte_size, 281 eByteOrderLittle, error); 282 283 return error; 284 } 285 286 Status NativeRegisterContextLinux_arm64::WriteRegister( 287 const RegisterInfo *reg_info, const RegisterValue ®_value) { 288 Status error; 289 290 if (!reg_info) 291 return Status("reg_info NULL"); 292 293 const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; 294 295 if (reg == LLDB_INVALID_REGNUM) 296 return Status("no lldb regnum for %s", reg_info && reg_info->name 297 ? reg_info->name 298 : "<unknown register>"); 299 300 uint8_t *dst; 301 uint32_t offset = LLDB_INVALID_INDEX32; 302 std::vector<uint8_t> sve_reg_non_live; 303 304 if (IsGPR(reg)) { 305 error = ReadGPR(); 306 if (error.Fail()) 307 return error; 308 309 assert(reg_info->byte_offset < GetGPRSize()); 310 dst = (uint8_t *)GetGPRBuffer() + reg_info->byte_offset; 311 ::memcpy(dst, reg_value.GetBytes(), reg_info->byte_size); 312 313 return WriteGPR(); 314 } else if (IsFPR(reg)) { 315 if (m_sve_state == SVEState::Disabled) { 316 // SVE is disabled take legacy route for FPU register access 317 error = ReadFPR(); 318 if (error.Fail()) 319 return error; 320 321 offset = CalculateFprOffset(reg_info); 322 assert(offset < GetFPRSize()); 323 dst = (uint8_t *)GetFPRBuffer() + offset; 324 ::memcpy(dst, reg_value.GetBytes(), reg_info->byte_size); 325 326 return WriteFPR(); 327 } else { 328 // SVE enabled, we will read and cache SVE ptrace data 329 error = ReadAllSVE(); 330 if (error.Fail()) 331 return error; 332 333 // FPSR and FPCR will be located right after Z registers in 334 // SVEState::FPSIMD while in SVEState::Full they will be located at the 335 // end of register data after an alignment correction based on currently 336 // selected vector length. 337 uint32_t sve_reg_num = LLDB_INVALID_REGNUM; 338 if (reg == GetRegisterInfo().GetRegNumFPSR()) { 339 sve_reg_num = reg; 340 if (m_sve_state == SVEState::Full) 341 offset = SVE_PT_SVE_FPSR_OFFSET(sve_vq_from_vl(m_sve_header.vl)); 342 else if (m_sve_state == SVEState::FPSIMD) 343 offset = SVE_PT_FPSIMD_OFFSET + (32 * 16); 344 } else if (reg == GetRegisterInfo().GetRegNumFPCR()) { 345 sve_reg_num = reg; 346 if (m_sve_state == SVEState::Full) 347 offset = SVE_PT_SVE_FPCR_OFFSET(sve_vq_from_vl(m_sve_header.vl)); 348 else if (m_sve_state == SVEState::FPSIMD) 349 offset = SVE_PT_FPSIMD_OFFSET + (32 * 16) + 4; 350 } else { 351 // Extract SVE Z register value register number for this reg_info 352 if (reg_info->value_regs && 353 reg_info->value_regs[0] != LLDB_INVALID_REGNUM) 354 sve_reg_num = reg_info->value_regs[0]; 355 offset = CalculateSVEOffset(GetRegisterInfoAtIndex(sve_reg_num)); 356 } 357 358 assert(offset < GetSVEBufferSize()); 359 dst = (uint8_t *)GetSVEBuffer() + offset; 360 ::memcpy(dst, reg_value.GetBytes(), reg_info->byte_size); 361 return WriteAllSVE(); 362 } 363 } else if (IsSVE(reg)) { 364 if (m_sve_state == SVEState::Disabled || m_sve_state == SVEState::Unknown) 365 return Status("SVE disabled or not supported"); 366 else { 367 // Target has SVE enabled, we will read and cache SVE ptrace data 368 error = ReadAllSVE(); 369 if (error.Fail()) 370 return error; 371 372 if (GetRegisterInfo().IsSVERegVG(reg)) { 373 uint64_t vg_value = reg_value.GetAsUInt64(); 374 375 if (sve_vl_valid(vg_value * 8)) { 376 if (m_sve_header_is_valid && vg_value == GetSVERegVG()) 377 return error; 378 379 SetSVERegVG(vg_value); 380 381 error = WriteSVEHeader(); 382 if (error.Success()) 383 ConfigureRegisterContext(); 384 385 if (m_sve_header_is_valid && vg_value == GetSVERegVG()) 386 return error; 387 } 388 389 return Status("SVE vector length update failed."); 390 } 391 392 // If target supports SVE but currently in FPSIMD mode. 393 if (m_sve_state == SVEState::FPSIMD) { 394 // Here we will check if writing this SVE register enables 395 // SVEState::Full 396 bool set_sve_state_full = false; 397 const uint8_t *reg_bytes = (const uint8_t *)reg_value.GetBytes(); 398 if (GetRegisterInfo().IsSVEZReg(reg)) { 399 for (uint32_t i = 16; i < reg_info->byte_size; i++) { 400 if (reg_bytes[i]) { 401 set_sve_state_full = true; 402 break; 403 } 404 } 405 } else if (GetRegisterInfo().IsSVEPReg(reg) || 406 reg == GetRegisterInfo().GetRegNumSVEFFR()) { 407 for (uint32_t i = 0; i < reg_info->byte_size; i++) { 408 if (reg_bytes[i]) { 409 set_sve_state_full = true; 410 break; 411 } 412 } 413 } 414 415 if (!set_sve_state_full && GetRegisterInfo().IsSVEZReg(reg)) { 416 // We are writing a Z register which is zero beyond 16 bytes so copy 417 // first 16 bytes only as SVE payload mirrors legacy fpsimd structure 418 offset = CalculateSVEOffset(reg_info); 419 assert(offset < GetSVEBufferSize()); 420 dst = (uint8_t *)GetSVEBuffer() + offset; 421 ::memcpy(dst, reg_value.GetBytes(), 16); 422 423 return WriteAllSVE(); 424 } else 425 return Status("SVE state change operation not supported"); 426 } else { 427 offset = CalculateSVEOffset(reg_info); 428 assert(offset < GetSVEBufferSize()); 429 dst = (uint8_t *)GetSVEBuffer() + offset; 430 ::memcpy(dst, reg_value.GetBytes(), reg_info->byte_size); 431 return WriteAllSVE(); 432 } 433 } 434 } else if (IsMTE(reg)) { 435 error = ReadMTEControl(); 436 if (error.Fail()) 437 return error; 438 439 offset = reg_info->byte_offset - GetRegisterInfo().GetMTEOffset(); 440 assert(offset < GetMTEControlSize()); 441 dst = (uint8_t *)GetMTEControl() + offset; 442 ::memcpy(dst, reg_value.GetBytes(), reg_info->byte_size); 443 444 return WriteMTEControl(); 445 } 446 447 return Status("Failed to write register value"); 448 } 449 450 Status NativeRegisterContextLinux_arm64::ReadAllRegisterValues( 451 lldb::DataBufferSP &data_sp) { 452 Status error; 453 454 data_sp.reset(new DataBufferHeap(REG_CONTEXT_SIZE, 0)); 455 456 error = ReadGPR(); 457 if (error.Fail()) 458 return error; 459 460 error = ReadFPR(); 461 if (error.Fail()) 462 return error; 463 464 uint8_t *dst = data_sp->GetBytes(); 465 ::memcpy(dst, GetGPRBuffer(), GetGPRSize()); 466 dst += GetGPRSize(); 467 ::memcpy(dst, GetFPRBuffer(), GetFPRSize()); 468 469 return error; 470 } 471 472 Status NativeRegisterContextLinux_arm64::WriteAllRegisterValues( 473 const lldb::DataBufferSP &data_sp) { 474 Status error; 475 476 if (!data_sp) { 477 error.SetErrorStringWithFormat( 478 "NativeRegisterContextLinux_x86_64::%s invalid data_sp provided", 479 __FUNCTION__); 480 return error; 481 } 482 483 if (data_sp->GetByteSize() != REG_CONTEXT_SIZE) { 484 error.SetErrorStringWithFormat( 485 "NativeRegisterContextLinux_x86_64::%s data_sp contained mismatched " 486 "data size, expected %" PRIu64 ", actual %" PRIu64, 487 __FUNCTION__, REG_CONTEXT_SIZE, data_sp->GetByteSize()); 488 return error; 489 } 490 491 uint8_t *src = data_sp->GetBytes(); 492 if (src == nullptr) { 493 error.SetErrorStringWithFormat("NativeRegisterContextLinux_x86_64::%s " 494 "DataBuffer::GetBytes() returned a null " 495 "pointer", 496 __FUNCTION__); 497 return error; 498 } 499 ::memcpy(GetGPRBuffer(), src, GetRegisterInfoInterface().GetGPRSize()); 500 501 error = WriteGPR(); 502 if (error.Fail()) 503 return error; 504 505 src += GetRegisterInfoInterface().GetGPRSize(); 506 ::memcpy(GetFPRBuffer(), src, GetFPRSize()); 507 508 error = WriteFPR(); 509 if (error.Fail()) 510 return error; 511 512 return error; 513 } 514 515 bool NativeRegisterContextLinux_arm64::IsGPR(unsigned reg) const { 516 if (GetRegisterInfo().GetRegisterSetFromRegisterIndex(reg) == 517 RegisterInfoPOSIX_arm64::GPRegSet) 518 return true; 519 return false; 520 } 521 522 bool NativeRegisterContextLinux_arm64::IsFPR(unsigned reg) const { 523 if (GetRegisterInfo().GetRegisterSetFromRegisterIndex(reg) == 524 RegisterInfoPOSIX_arm64::FPRegSet) 525 return true; 526 return false; 527 } 528 529 bool NativeRegisterContextLinux_arm64::IsSVE(unsigned reg) const { 530 return GetRegisterInfo().IsSVEReg(reg); 531 } 532 533 bool NativeRegisterContextLinux_arm64::IsPAuth(unsigned reg) const { 534 return GetRegisterInfo().IsPAuthReg(reg); 535 } 536 537 bool NativeRegisterContextLinux_arm64::IsMTE(unsigned reg) const { 538 return GetRegisterInfo().IsMTEReg(reg); 539 } 540 541 llvm::Error NativeRegisterContextLinux_arm64::ReadHardwareDebugInfo() { 542 if (!m_refresh_hwdebug_info) { 543 return llvm::Error::success(); 544 } 545 546 ::pid_t tid = m_thread.GetID(); 547 548 int regset = NT_ARM_HW_WATCH; 549 struct iovec ioVec; 550 struct user_hwdebug_state dreg_state; 551 Status error; 552 553 ioVec.iov_base = &dreg_state; 554 ioVec.iov_len = sizeof(dreg_state); 555 error = NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, tid, ®set, 556 &ioVec, ioVec.iov_len); 557 558 if (error.Fail()) 559 return error.ToError(); 560 561 m_max_hwp_supported = dreg_state.dbg_info & 0xff; 562 563 regset = NT_ARM_HW_BREAK; 564 error = NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, tid, ®set, 565 &ioVec, ioVec.iov_len); 566 567 if (error.Fail()) 568 return error.ToError(); 569 570 m_max_hbp_supported = dreg_state.dbg_info & 0xff; 571 m_refresh_hwdebug_info = false; 572 573 return llvm::Error::success(); 574 } 575 576 llvm::Error 577 NativeRegisterContextLinux_arm64::WriteHardwareDebugRegs(DREGType hwbType) { 578 struct iovec ioVec; 579 struct user_hwdebug_state dreg_state; 580 int regset; 581 582 memset(&dreg_state, 0, sizeof(dreg_state)); 583 ioVec.iov_base = &dreg_state; 584 585 switch (hwbType) { 586 case eDREGTypeWATCH: 587 regset = NT_ARM_HW_WATCH; 588 ioVec.iov_len = sizeof(dreg_state.dbg_info) + sizeof(dreg_state.pad) + 589 (sizeof(dreg_state.dbg_regs[0]) * m_max_hwp_supported); 590 591 for (uint32_t i = 0; i < m_max_hwp_supported; i++) { 592 dreg_state.dbg_regs[i].addr = m_hwp_regs[i].address; 593 dreg_state.dbg_regs[i].ctrl = m_hwp_regs[i].control; 594 } 595 break; 596 case eDREGTypeBREAK: 597 regset = NT_ARM_HW_BREAK; 598 ioVec.iov_len = sizeof(dreg_state.dbg_info) + sizeof(dreg_state.pad) + 599 (sizeof(dreg_state.dbg_regs[0]) * m_max_hbp_supported); 600 601 for (uint32_t i = 0; i < m_max_hbp_supported; i++) { 602 dreg_state.dbg_regs[i].addr = m_hbp_regs[i].address; 603 dreg_state.dbg_regs[i].ctrl = m_hbp_regs[i].control; 604 } 605 break; 606 } 607 608 return NativeProcessLinux::PtraceWrapper(PTRACE_SETREGSET, m_thread.GetID(), 609 ®set, &ioVec, ioVec.iov_len) 610 .ToError(); 611 } 612 613 Status NativeRegisterContextLinux_arm64::ReadGPR() { 614 Status error; 615 616 if (m_gpr_is_valid) 617 return error; 618 619 struct iovec ioVec; 620 ioVec.iov_base = GetGPRBuffer(); 621 ioVec.iov_len = GetGPRBufferSize(); 622 623 error = ReadRegisterSet(&ioVec, GetGPRBufferSize(), NT_PRSTATUS); 624 625 if (error.Success()) 626 m_gpr_is_valid = true; 627 628 return error; 629 } 630 631 Status NativeRegisterContextLinux_arm64::WriteGPR() { 632 Status error = ReadGPR(); 633 if (error.Fail()) 634 return error; 635 636 struct iovec ioVec; 637 ioVec.iov_base = GetGPRBuffer(); 638 ioVec.iov_len = GetGPRBufferSize(); 639 640 m_gpr_is_valid = false; 641 642 return WriteRegisterSet(&ioVec, GetGPRBufferSize(), NT_PRSTATUS); 643 } 644 645 Status NativeRegisterContextLinux_arm64::ReadFPR() { 646 Status error; 647 648 if (m_fpu_is_valid) 649 return error; 650 651 struct iovec ioVec; 652 ioVec.iov_base = GetFPRBuffer(); 653 ioVec.iov_len = GetFPRSize(); 654 655 error = ReadRegisterSet(&ioVec, GetFPRSize(), NT_FPREGSET); 656 657 if (error.Success()) 658 m_fpu_is_valid = true; 659 660 return error; 661 } 662 663 Status NativeRegisterContextLinux_arm64::WriteFPR() { 664 Status error = ReadFPR(); 665 if (error.Fail()) 666 return error; 667 668 struct iovec ioVec; 669 ioVec.iov_base = GetFPRBuffer(); 670 ioVec.iov_len = GetFPRSize(); 671 672 m_fpu_is_valid = false; 673 674 return WriteRegisterSet(&ioVec, GetFPRSize(), NT_FPREGSET); 675 } 676 677 void NativeRegisterContextLinux_arm64::InvalidateAllRegisters() { 678 m_gpr_is_valid = false; 679 m_fpu_is_valid = false; 680 m_sve_buffer_is_valid = false; 681 m_sve_header_is_valid = false; 682 m_pac_mask_is_valid = false; 683 m_mte_ctrl_is_valid = false; 684 685 // Update SVE registers in case there is change in configuration. 686 ConfigureRegisterContext(); 687 } 688 689 Status NativeRegisterContextLinux_arm64::ReadSVEHeader() { 690 Status error; 691 692 if (m_sve_header_is_valid) 693 return error; 694 695 struct iovec ioVec; 696 ioVec.iov_base = GetSVEHeader(); 697 ioVec.iov_len = GetSVEHeaderSize(); 698 699 error = ReadRegisterSet(&ioVec, GetSVEHeaderSize(), NT_ARM_SVE); 700 701 if (error.Success()) 702 m_sve_header_is_valid = true; 703 704 return error; 705 } 706 707 Status NativeRegisterContextLinux_arm64::ReadPAuthMask() { 708 Status error; 709 710 if (m_pac_mask_is_valid) 711 return error; 712 713 struct iovec ioVec; 714 ioVec.iov_base = GetPACMask(); 715 ioVec.iov_len = GetPACMaskSize(); 716 717 error = ReadRegisterSet(&ioVec, GetPACMaskSize(), NT_ARM_PAC_MASK); 718 719 if (error.Success()) 720 m_pac_mask_is_valid = true; 721 722 return error; 723 } 724 725 Status NativeRegisterContextLinux_arm64::WriteSVEHeader() { 726 Status error; 727 728 error = ReadSVEHeader(); 729 if (error.Fail()) 730 return error; 731 732 struct iovec ioVec; 733 ioVec.iov_base = GetSVEHeader(); 734 ioVec.iov_len = GetSVEHeaderSize(); 735 736 m_sve_buffer_is_valid = false; 737 m_sve_header_is_valid = false; 738 m_fpu_is_valid = false; 739 740 return WriteRegisterSet(&ioVec, GetSVEHeaderSize(), NT_ARM_SVE); 741 } 742 743 Status NativeRegisterContextLinux_arm64::ReadAllSVE() { 744 Status error; 745 746 if (m_sve_buffer_is_valid) 747 return error; 748 749 struct iovec ioVec; 750 ioVec.iov_base = GetSVEBuffer(); 751 ioVec.iov_len = GetSVEBufferSize(); 752 753 error = ReadRegisterSet(&ioVec, GetSVEBufferSize(), NT_ARM_SVE); 754 755 if (error.Success()) 756 m_sve_buffer_is_valid = true; 757 758 return error; 759 } 760 761 Status NativeRegisterContextLinux_arm64::WriteAllSVE() { 762 Status error; 763 764 error = ReadAllSVE(); 765 if (error.Fail()) 766 return error; 767 768 struct iovec ioVec; 769 770 ioVec.iov_base = GetSVEBuffer(); 771 ioVec.iov_len = GetSVEBufferSize(); 772 773 m_sve_buffer_is_valid = false; 774 m_sve_header_is_valid = false; 775 m_fpu_is_valid = false; 776 777 return WriteRegisterSet(&ioVec, GetSVEBufferSize(), NT_ARM_SVE); 778 } 779 780 Status NativeRegisterContextLinux_arm64::ReadMTEControl() { 781 Status error; 782 783 if (m_mte_ctrl_is_valid) 784 return error; 785 786 struct iovec ioVec; 787 ioVec.iov_base = GetMTEControl(); 788 ioVec.iov_len = GetMTEControlSize(); 789 790 error = ReadRegisterSet(&ioVec, GetMTEControlSize(), NT_ARM_TAGGED_ADDR_CTRL); 791 792 if (error.Success()) 793 m_mte_ctrl_is_valid = true; 794 795 return error; 796 } 797 798 Status NativeRegisterContextLinux_arm64::WriteMTEControl() { 799 Status error; 800 801 error = ReadMTEControl(); 802 if (error.Fail()) 803 return error; 804 805 struct iovec ioVec; 806 ioVec.iov_base = GetMTEControl(); 807 ioVec.iov_len = GetMTEControlSize(); 808 809 m_mte_ctrl_is_valid = false; 810 811 return WriteRegisterSet(&ioVec, GetMTEControlSize(), NT_ARM_TAGGED_ADDR_CTRL); 812 } 813 814 void NativeRegisterContextLinux_arm64::ConfigureRegisterContext() { 815 // ConfigureRegisterContext gets called from InvalidateAllRegisters 816 // on every stop and configures SVE vector length. 817 // If m_sve_state is set to SVEState::Disabled on first stop, code below will 818 // be deemed non operational for the lifetime of current process. 819 if (!m_sve_header_is_valid && m_sve_state != SVEState::Disabled) { 820 Status error = ReadSVEHeader(); 821 if (error.Success()) { 822 // If SVE is enabled thread can switch between SVEState::FPSIMD and 823 // SVEState::Full on every stop. 824 if ((m_sve_header.flags & SVE_PT_REGS_MASK) == SVE_PT_REGS_FPSIMD) 825 m_sve_state = SVEState::FPSIMD; 826 else if ((m_sve_header.flags & SVE_PT_REGS_MASK) == SVE_PT_REGS_SVE) 827 m_sve_state = SVEState::Full; 828 829 // On every stop we configure SVE vector length by calling 830 // ConfigureVectorLength regardless of current SVEState of this thread. 831 uint32_t vq = RegisterInfoPOSIX_arm64::eVectorQuadwordAArch64SVE; 832 if (sve_vl_valid(m_sve_header.vl)) 833 vq = sve_vq_from_vl(m_sve_header.vl); 834 835 GetRegisterInfo().ConfigureVectorLength(vq); 836 m_sve_ptrace_payload.resize(SVE_PT_SIZE(vq, SVE_PT_REGS_SVE)); 837 } 838 } 839 } 840 841 uint32_t NativeRegisterContextLinux_arm64::CalculateFprOffset( 842 const RegisterInfo *reg_info) const { 843 return reg_info->byte_offset - GetGPRSize(); 844 } 845 846 uint32_t NativeRegisterContextLinux_arm64::CalculateSVEOffset( 847 const RegisterInfo *reg_info) const { 848 // Start of Z0 data is after GPRs plus 8 bytes of vg register 849 uint32_t sve_reg_offset = LLDB_INVALID_INDEX32; 850 if (m_sve_state == SVEState::FPSIMD) { 851 const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; 852 sve_reg_offset = 853 SVE_PT_FPSIMD_OFFSET + (reg - GetRegisterInfo().GetRegNumSVEZ0()) * 16; 854 } else if (m_sve_state == SVEState::Full) { 855 uint32_t sve_z0_offset = GetGPRSize() + 16; 856 sve_reg_offset = 857 SVE_SIG_REGS_OFFSET + reg_info->byte_offset - sve_z0_offset; 858 } 859 return sve_reg_offset; 860 } 861 862 void *NativeRegisterContextLinux_arm64::GetSVEBuffer() { 863 if (m_sve_state == SVEState::FPSIMD) 864 return m_sve_ptrace_payload.data() + SVE_PT_FPSIMD_OFFSET; 865 866 return m_sve_ptrace_payload.data(); 867 } 868 869 std::vector<uint32_t> NativeRegisterContextLinux_arm64::GetExpeditedRegisters( 870 ExpeditedRegs expType) const { 871 std::vector<uint32_t> expedited_reg_nums = 872 NativeRegisterContext::GetExpeditedRegisters(expType); 873 if (m_sve_state == SVEState::FPSIMD || m_sve_state == SVEState::Full) 874 expedited_reg_nums.push_back(GetRegisterInfo().GetRegNumSVEVG()); 875 876 return expedited_reg_nums; 877 } 878 879 #endif // defined (__arm64__) || defined (__aarch64__) 880