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