180814287SRaphael Isemann //===-- NativeRegisterContextLinux_arm64.cpp ------------------------------===// 21e209fccSTamas Berghammer // 32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 61e209fccSTamas Berghammer // 71e209fccSTamas Berghammer //===----------------------------------------------------------------------===// 81e209fccSTamas Berghammer 9068f8a7eSTamas Berghammer #if defined(__arm64__) || defined(__aarch64__) 10068f8a7eSTamas Berghammer 11e85e6021STamas Berghammer #include "NativeRegisterContextLinux_arm.h" 121e209fccSTamas Berghammer #include "NativeRegisterContextLinux_arm64.h" 131e209fccSTamas Berghammer 14068f8a7eSTamas Berghammer 151e209fccSTamas Berghammer #include "lldb/Host/common/NativeProcessProtocol.h" 16da2e614fSDavid Spickett #include "lldb/Host/linux/Ptrace.h" 17666cc0b2SZachary Turner #include "lldb/Utility/DataBufferHeap.h" 186f9e6901SZachary Turner #include "lldb/Utility/Log.h" 19d821c997SPavel Labath #include "lldb/Utility/RegisterValue.h" 2097206d57SZachary Turner #include "lldb/Utility/Status.h" 211e209fccSTamas Berghammer 22068f8a7eSTamas Berghammer #include "Plugins/Process/Linux/NativeProcessLinux.h" 23068f8a7eSTamas Berghammer #include "Plugins/Process/Linux/Procfs.h" 24e85e6021STamas Berghammer #include "Plugins/Process/POSIX/ProcessPOSIXLog.h" 25da2e614fSDavid Spickett #include "Plugins/Process/Utility/MemoryTagManagerAArch64MTE.h" 26567ba6c4SMuhammad Omair Javaid #include "Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h" 27068f8a7eSTamas Berghammer 28b9c1b51eSKate Stone // System includes - They have to be included after framework includes because 2905097246SAdrian Prantl // they define some macros which collide with variable names in other modules 30068f8a7eSTamas Berghammer #include <sys/socket.h> 31068f8a7eSTamas Berghammer // NT_PRSTATUS and NT_FPREGSET definition 32068f8a7eSTamas Berghammer #include <elf.h> 33567ba6c4SMuhammad Omair Javaid 34567ba6c4SMuhammad Omair Javaid #ifndef NT_ARM_SVE 35567ba6c4SMuhammad Omair Javaid #define NT_ARM_SVE 0x405 /* ARM Scalable Vector Extension */ 36567ba6c4SMuhammad Omair Javaid #endif 37068f8a7eSTamas Berghammer 3888a5b35dSMuhammad Omair Javaid #ifndef NT_ARM_PAC_MASK 3988a5b35dSMuhammad Omair Javaid #define NT_ARM_PAC_MASK 0x406 /* Pointer authentication code masks */ 4088a5b35dSMuhammad Omair Javaid #endif 4188a5b35dSMuhammad Omair Javaid 4288a5b35dSMuhammad Omair Javaid #ifndef NT_ARM_TAGGED_ADDR_CTRL 4388a5b35dSMuhammad Omair Javaid #define NT_ARM_TAGGED_ADDR_CTRL 0x409 /* Tagged address control register */ 4488a5b35dSMuhammad Omair Javaid #endif 4588a5b35dSMuhammad Omair Javaid 4688a5b35dSMuhammad Omair Javaid #define HWCAP_PACA (1 << 30) 4788a5b35dSMuhammad Omair Javaid #define HWCAP2_MTE (1 << 18) 4888a5b35dSMuhammad Omair Javaid 49068f8a7eSTamas Berghammer #define REG_CONTEXT_SIZE (GetGPRSize() + GetFPRSize()) 501e209fccSTamas Berghammer 511e209fccSTamas Berghammer using namespace lldb; 521e209fccSTamas Berghammer using namespace lldb_private; 53db264a6dSTamas Berghammer using namespace lldb_private::process_linux; 541e209fccSTamas Berghammer 55d37349f3SPavel Labath std::unique_ptr<NativeRegisterContextLinux> 56b9c1b51eSKate Stone NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux( 57d1486e65SPavel Labath const ArchSpec &target_arch, NativeThreadLinux &native_thread) { 58b9c1b51eSKate Stone switch (target_arch.GetMachine()) { 59e85e6021STamas Berghammer case llvm::Triple::arm: 60a8f3ae7cSJonas Devlieghere return std::make_unique<NativeRegisterContextLinux_arm>(target_arch, 61d37349f3SPavel Labath native_thread); 62d6d3d21cSMuhammad Omair Javaid case llvm::Triple::aarch64: { 63d6d3d21cSMuhammad Omair Javaid // Configure register sets supported by this AArch64 target. 64d6d3d21cSMuhammad Omair Javaid // Read SVE header to check for SVE support. 65d6d3d21cSMuhammad Omair Javaid struct user_sve_header sve_header; 66d6d3d21cSMuhammad Omair Javaid struct iovec ioVec; 67d6d3d21cSMuhammad Omair Javaid ioVec.iov_base = &sve_header; 68d6d3d21cSMuhammad Omair Javaid ioVec.iov_len = sizeof(sve_header); 69d6d3d21cSMuhammad Omair Javaid unsigned int regset = NT_ARM_SVE; 70d6d3d21cSMuhammad Omair Javaid 71d6d3d21cSMuhammad Omair Javaid Flags opt_regsets; 72d6d3d21cSMuhammad Omair Javaid if (NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, 73d6d3d21cSMuhammad Omair Javaid native_thread.GetID(), ®set, 74d6d3d21cSMuhammad Omair Javaid &ioVec, sizeof(sve_header)) 75d6d3d21cSMuhammad Omair Javaid .Success()) 76d6d3d21cSMuhammad Omair Javaid opt_regsets.Set(RegisterInfoPOSIX_arm64::eRegsetMaskSVE); 77d6d3d21cSMuhammad Omair Javaid 7888a5b35dSMuhammad Omair Javaid NativeProcessLinux &process = native_thread.GetProcess(); 7988a5b35dSMuhammad Omair Javaid 8088a5b35dSMuhammad Omair Javaid llvm::Optional<uint64_t> auxv_at_hwcap = 8188a5b35dSMuhammad Omair Javaid process.GetAuxValue(AuxVector::AUXV_AT_HWCAP); 8288a5b35dSMuhammad Omair Javaid if (auxv_at_hwcap && (*auxv_at_hwcap & HWCAP_PACA)) 8388a5b35dSMuhammad Omair Javaid opt_regsets.Set(RegisterInfoPOSIX_arm64::eRegsetMaskPAuth); 8488a5b35dSMuhammad Omair Javaid 8588a5b35dSMuhammad Omair Javaid llvm::Optional<uint64_t> auxv_at_hwcap2 = 8688a5b35dSMuhammad Omair Javaid process.GetAuxValue(AuxVector::AUXV_AT_HWCAP2); 8788a5b35dSMuhammad Omair Javaid if (auxv_at_hwcap2 && (*auxv_at_hwcap2 & HWCAP2_MTE)) 8888a5b35dSMuhammad Omair Javaid opt_regsets.Set(RegisterInfoPOSIX_arm64::eRegsetMaskMTE); 8988a5b35dSMuhammad Omair Javaid 90d6d3d21cSMuhammad Omair Javaid auto register_info_up = 91d6d3d21cSMuhammad Omair Javaid std::make_unique<RegisterInfoPOSIX_arm64>(target_arch, opt_regsets); 92d6d3d21cSMuhammad Omair Javaid return std::make_unique<NativeRegisterContextLinux_arm64>( 93d6d3d21cSMuhammad Omair Javaid target_arch, native_thread, std::move(register_info_up)); 94d6d3d21cSMuhammad Omair Javaid } 95e85e6021STamas Berghammer default: 96ea1b6b17SPavel Labath llvm_unreachable("have no register context for architecture"); 97e85e6021STamas Berghammer } 98068f8a7eSTamas Berghammer } 99068f8a7eSTamas Berghammer 100b9c1b51eSKate Stone NativeRegisterContextLinux_arm64::NativeRegisterContextLinux_arm64( 101d6d3d21cSMuhammad Omair Javaid const ArchSpec &target_arch, NativeThreadProtocol &native_thread, 102d6d3d21cSMuhammad Omair Javaid std::unique_ptr<RegisterInfoPOSIX_arm64> register_info_up) 103d6d3d21cSMuhammad Omair Javaid : NativeRegisterContextRegisterInfo(native_thread, 104e1d4fb1eSPavel Labath register_info_up.release()), 105e1d4fb1eSPavel Labath NativeRegisterContextLinux(native_thread) { 1061e209fccSTamas Berghammer ::memset(&m_fpr, 0, sizeof(m_fpr)); 1071e209fccSTamas Berghammer ::memset(&m_gpr_arm64, 0, sizeof(m_gpr_arm64)); 108ea8c25a8SOmair Javaid ::memset(&m_hwp_regs, 0, sizeof(m_hwp_regs)); 109771c4c9cSMichał Górny ::memset(&m_hbp_regs, 0, sizeof(m_hbp_regs)); 110567ba6c4SMuhammad Omair Javaid ::memset(&m_sve_header, 0, sizeof(m_sve_header)); 11188a5b35dSMuhammad Omair Javaid ::memset(&m_pac_mask, 0, sizeof(m_pac_mask)); 11288a5b35dSMuhammad Omair Javaid 11388a5b35dSMuhammad Omair Javaid m_mte_ctrl_reg = 0; 114ea8c25a8SOmair Javaid 115ea8c25a8SOmair Javaid // 16 is just a maximum value, query hardware for actual watchpoint count 116ea8c25a8SOmair Javaid m_max_hwp_supported = 16; 117ea8c25a8SOmair Javaid m_max_hbp_supported = 16; 118567ba6c4SMuhammad Omair Javaid 119ea8c25a8SOmair Javaid m_refresh_hwdebug_info = true; 120b6f9d7b8SMuhammad Omair Javaid 121b6f9d7b8SMuhammad Omair Javaid m_gpr_is_valid = false; 122b6f9d7b8SMuhammad Omair Javaid m_fpu_is_valid = false; 123567ba6c4SMuhammad Omair Javaid m_sve_buffer_is_valid = false; 124567ba6c4SMuhammad Omair Javaid m_sve_header_is_valid = false; 12588a5b35dSMuhammad Omair Javaid m_pac_mask_is_valid = false; 12688a5b35dSMuhammad Omair Javaid m_mte_ctrl_is_valid = false; 127567ba6c4SMuhammad Omair Javaid 128d6d3d21cSMuhammad Omair Javaid if (GetRegisterInfo().IsSVEEnabled()) 129567ba6c4SMuhammad Omair Javaid m_sve_state = SVEState::Unknown; 130d6d3d21cSMuhammad Omair Javaid else 131d6d3d21cSMuhammad Omair Javaid m_sve_state = SVEState::Disabled; 1321e209fccSTamas Berghammer } 1331e209fccSTamas Berghammer 1347fa7b81bSMuhammad Omair Javaid RegisterInfoPOSIX_arm64 & 1357fa7b81bSMuhammad Omair Javaid NativeRegisterContextLinux_arm64::GetRegisterInfo() const { 1367fa7b81bSMuhammad Omair Javaid return static_cast<RegisterInfoPOSIX_arm64 &>(*m_register_info_interface_up); 1377fa7b81bSMuhammad Omair Javaid } 1387fa7b81bSMuhammad Omair Javaid 139b9c1b51eSKate Stone uint32_t NativeRegisterContextLinux_arm64::GetRegisterSetCount() const { 1407fa7b81bSMuhammad Omair Javaid return GetRegisterInfo().GetRegisterSetCount(); 1411e209fccSTamas Berghammer } 1421e209fccSTamas Berghammer 143db264a6dSTamas Berghammer const RegisterSet * 144b9c1b51eSKate Stone NativeRegisterContextLinux_arm64::GetRegisterSet(uint32_t set_index) const { 1457fa7b81bSMuhammad Omair Javaid return GetRegisterInfo().GetRegisterSet(set_index); 1461e209fccSTamas Berghammer } 1471e209fccSTamas Berghammer 148b9c1b51eSKate Stone uint32_t NativeRegisterContextLinux_arm64::GetUserRegisterCount() const { 149cec93c35STamas Berghammer uint32_t count = 0; 1507fa7b81bSMuhammad Omair Javaid for (uint32_t set_index = 0; set_index < GetRegisterSetCount(); ++set_index) 1517fa7b81bSMuhammad Omair Javaid count += GetRegisterSet(set_index)->num_registers; 152cec93c35STamas Berghammer return count; 153cec93c35STamas Berghammer } 154cec93c35STamas Berghammer 15597206d57SZachary Turner Status 15697206d57SZachary Turner NativeRegisterContextLinux_arm64::ReadRegister(const RegisterInfo *reg_info, 15797206d57SZachary Turner RegisterValue ®_value) { 15897206d57SZachary Turner Status error; 1591e209fccSTamas Berghammer 160b9c1b51eSKate Stone if (!reg_info) { 1611e209fccSTamas Berghammer error.SetErrorString("reg_info NULL"); 1621e209fccSTamas Berghammer return error; 1631e209fccSTamas Berghammer } 1641e209fccSTamas Berghammer 1651e209fccSTamas Berghammer const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; 1661e209fccSTamas Berghammer 167b6f9d7b8SMuhammad Omair Javaid if (reg == LLDB_INVALID_REGNUM) 168b6f9d7b8SMuhammad Omair Javaid return Status("no lldb regnum for %s", reg_info && reg_info->name 169b6f9d7b8SMuhammad Omair Javaid ? reg_info->name 170b6f9d7b8SMuhammad Omair Javaid : "<unknown register>"); 171b6f9d7b8SMuhammad Omair Javaid 172b6f9d7b8SMuhammad Omair Javaid uint8_t *src; 1734283320bSMuhammad Omair Javaid uint32_t offset = LLDB_INVALID_INDEX32; 174567ba6c4SMuhammad Omair Javaid uint64_t sve_vg; 175567ba6c4SMuhammad Omair Javaid std::vector<uint8_t> sve_reg_non_live; 176b6f9d7b8SMuhammad Omair Javaid 177b6f9d7b8SMuhammad Omair Javaid if (IsGPR(reg)) { 178b6f9d7b8SMuhammad Omair Javaid error = ReadGPR(); 179b6f9d7b8SMuhammad Omair Javaid if (error.Fail()) 180b6f9d7b8SMuhammad Omair Javaid return error; 181b6f9d7b8SMuhammad Omair Javaid 182b6f9d7b8SMuhammad Omair Javaid offset = reg_info->byte_offset; 183b6f9d7b8SMuhammad Omair Javaid assert(offset < GetGPRSize()); 184b6f9d7b8SMuhammad Omair Javaid src = (uint8_t *)GetGPRBuffer() + offset; 185b6f9d7b8SMuhammad Omair Javaid 186b6f9d7b8SMuhammad Omair Javaid } else if (IsFPR(reg)) { 187567ba6c4SMuhammad Omair Javaid if (m_sve_state == SVEState::Disabled) { 188567ba6c4SMuhammad Omair Javaid // SVE is disabled take legacy route for FPU register access 189068f8a7eSTamas Berghammer error = ReadFPR(); 190068f8a7eSTamas Berghammer if (error.Fail()) 1911e209fccSTamas Berghammer return error; 192567ba6c4SMuhammad Omair Javaid 193b6f9d7b8SMuhammad Omair Javaid offset = CalculateFprOffset(reg_info); 194b6f9d7b8SMuhammad Omair Javaid assert(offset < GetFPRSize()); 195b6f9d7b8SMuhammad Omair Javaid src = (uint8_t *)GetFPRBuffer() + offset; 196567ba6c4SMuhammad Omair Javaid } else { 197567ba6c4SMuhammad Omair Javaid // SVE enabled, we will read and cache SVE ptrace data 198567ba6c4SMuhammad Omair Javaid error = ReadAllSVE(); 199567ba6c4SMuhammad Omair Javaid if (error.Fail()) 200567ba6c4SMuhammad Omair Javaid return error; 201567ba6c4SMuhammad Omair Javaid 202567ba6c4SMuhammad Omair Javaid // FPSR and FPCR will be located right after Z registers in 203567ba6c4SMuhammad Omair Javaid // SVEState::FPSIMD while in SVEState::Full they will be located at the 204567ba6c4SMuhammad Omair Javaid // end of register data after an alignment correction based on currently 205567ba6c4SMuhammad Omair Javaid // selected vector length. 206567ba6c4SMuhammad Omair Javaid uint32_t sve_reg_num = LLDB_INVALID_REGNUM; 207567ba6c4SMuhammad Omair Javaid if (reg == GetRegisterInfo().GetRegNumFPSR()) { 208567ba6c4SMuhammad Omair Javaid sve_reg_num = reg; 209567ba6c4SMuhammad Omair Javaid if (m_sve_state == SVEState::Full) 21005915400SCaroline Tice offset = sve::PTraceFPSROffset(sve::vq_from_vl(m_sve_header.vl)); 211567ba6c4SMuhammad Omair Javaid else if (m_sve_state == SVEState::FPSIMD) 21205915400SCaroline Tice offset = sve::ptrace_fpsimd_offset + (32 * 16); 213567ba6c4SMuhammad Omair Javaid } else if (reg == GetRegisterInfo().GetRegNumFPCR()) { 214567ba6c4SMuhammad Omair Javaid sve_reg_num = reg; 215567ba6c4SMuhammad Omair Javaid if (m_sve_state == SVEState::Full) 21605915400SCaroline Tice offset = sve::PTraceFPCROffset(sve::vq_from_vl(m_sve_header.vl)); 217567ba6c4SMuhammad Omair Javaid else if (m_sve_state == SVEState::FPSIMD) 21805915400SCaroline Tice offset = sve::ptrace_fpsimd_offset + (32 * 16) + 4; 219567ba6c4SMuhammad Omair Javaid } else { 220567ba6c4SMuhammad Omair Javaid // Extract SVE Z register value register number for this reg_info 221567ba6c4SMuhammad Omair Javaid if (reg_info->value_regs && 222567ba6c4SMuhammad Omair Javaid reg_info->value_regs[0] != LLDB_INVALID_REGNUM) 223567ba6c4SMuhammad Omair Javaid sve_reg_num = reg_info->value_regs[0]; 224567ba6c4SMuhammad Omair Javaid offset = CalculateSVEOffset(GetRegisterInfoAtIndex(sve_reg_num)); 225567ba6c4SMuhammad Omair Javaid } 226567ba6c4SMuhammad Omair Javaid 227567ba6c4SMuhammad Omair Javaid assert(offset < GetSVEBufferSize()); 228567ba6c4SMuhammad Omair Javaid src = (uint8_t *)GetSVEBuffer() + offset; 229567ba6c4SMuhammad Omair Javaid } 230567ba6c4SMuhammad Omair Javaid } else if (IsSVE(reg)) { 231567ba6c4SMuhammad Omair Javaid 232567ba6c4SMuhammad Omair Javaid if (m_sve_state == SVEState::Disabled || m_sve_state == SVEState::Unknown) 233567ba6c4SMuhammad Omair Javaid return Status("SVE disabled or not supported"); 234567ba6c4SMuhammad Omair Javaid 235567ba6c4SMuhammad Omair Javaid if (GetRegisterInfo().IsSVERegVG(reg)) { 236567ba6c4SMuhammad Omair Javaid sve_vg = GetSVERegVG(); 237567ba6c4SMuhammad Omair Javaid src = (uint8_t *)&sve_vg; 238567ba6c4SMuhammad Omair Javaid } else { 239567ba6c4SMuhammad Omair Javaid // SVE enabled, we will read and cache SVE ptrace data 240567ba6c4SMuhammad Omair Javaid error = ReadAllSVE(); 241567ba6c4SMuhammad Omair Javaid if (error.Fail()) 242567ba6c4SMuhammad Omair Javaid return error; 243567ba6c4SMuhammad Omair Javaid 244567ba6c4SMuhammad Omair Javaid if (m_sve_state == SVEState::FPSIMD) { 245567ba6c4SMuhammad Omair Javaid // In FPSIMD state SVE payload mirrors legacy fpsimd struct and so 246567ba6c4SMuhammad Omair Javaid // just copy 16 bytes of v register to the start of z register. All 247567ba6c4SMuhammad Omair Javaid // other SVE register will be set to zero. 248567ba6c4SMuhammad Omair Javaid sve_reg_non_live.resize(reg_info->byte_size, 0); 249567ba6c4SMuhammad Omair Javaid src = sve_reg_non_live.data(); 250567ba6c4SMuhammad Omair Javaid 251567ba6c4SMuhammad Omair Javaid if (GetRegisterInfo().IsSVEZReg(reg)) { 252567ba6c4SMuhammad Omair Javaid offset = CalculateSVEOffset(reg_info); 253567ba6c4SMuhammad Omair Javaid assert(offset < GetSVEBufferSize()); 254567ba6c4SMuhammad Omair Javaid ::memcpy(sve_reg_non_live.data(), (uint8_t *)GetSVEBuffer() + offset, 255567ba6c4SMuhammad Omair Javaid 16); 256567ba6c4SMuhammad Omair Javaid } 257567ba6c4SMuhammad Omair Javaid } else { 258567ba6c4SMuhammad Omair Javaid offset = CalculateSVEOffset(reg_info); 259567ba6c4SMuhammad Omair Javaid assert(offset < GetSVEBufferSize()); 260567ba6c4SMuhammad Omair Javaid src = (uint8_t *)GetSVEBuffer() + offset; 261567ba6c4SMuhammad Omair Javaid } 262567ba6c4SMuhammad Omair Javaid } 26388a5b35dSMuhammad Omair Javaid } else if (IsPAuth(reg)) { 26488a5b35dSMuhammad Omair Javaid error = ReadPAuthMask(); 26588a5b35dSMuhammad Omair Javaid if (error.Fail()) 26688a5b35dSMuhammad Omair Javaid return error; 26788a5b35dSMuhammad Omair Javaid 26888a5b35dSMuhammad Omair Javaid offset = reg_info->byte_offset - GetRegisterInfo().GetPAuthOffset(); 26988a5b35dSMuhammad Omair Javaid assert(offset < GetPACMaskSize()); 27088a5b35dSMuhammad Omair Javaid src = (uint8_t *)GetPACMask() + offset; 27188a5b35dSMuhammad Omair Javaid } else if (IsMTE(reg)) { 27288a5b35dSMuhammad Omair Javaid error = ReadMTEControl(); 27388a5b35dSMuhammad Omair Javaid if (error.Fail()) 27488a5b35dSMuhammad Omair Javaid return error; 27588a5b35dSMuhammad Omair Javaid 27688a5b35dSMuhammad Omair Javaid offset = reg_info->byte_offset - GetRegisterInfo().GetMTEOffset(); 27788a5b35dSMuhammad Omair Javaid assert(offset < GetMTEControlSize()); 27888a5b35dSMuhammad Omair Javaid src = (uint8_t *)GetMTEControl() + offset; 279b6f9d7b8SMuhammad Omair Javaid } else 280b6f9d7b8SMuhammad Omair Javaid return Status("failed - register wasn't recognized to be a GPR or an FPR, " 281b6f9d7b8SMuhammad Omair Javaid "write strategy unknown"); 2821e209fccSTamas Berghammer 283b9c1b51eSKate Stone reg_value.SetFromMemoryData(reg_info, src, reg_info->byte_size, 284b9c1b51eSKate Stone eByteOrderLittle, error); 2851e209fccSTamas Berghammer 2861e209fccSTamas Berghammer return error; 2871e209fccSTamas Berghammer } 2881e209fccSTamas Berghammer 28997206d57SZachary Turner Status NativeRegisterContextLinux_arm64::WriteRegister( 290b9c1b51eSKate Stone const RegisterInfo *reg_info, const RegisterValue ®_value) { 291b6f9d7b8SMuhammad Omair Javaid Status error; 292b6f9d7b8SMuhammad Omair Javaid 2931e209fccSTamas Berghammer if (!reg_info) 29497206d57SZachary Turner return Status("reg_info NULL"); 2951e209fccSTamas Berghammer 296b6f9d7b8SMuhammad Omair Javaid const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; 297b6f9d7b8SMuhammad Omair Javaid 298b6f9d7b8SMuhammad Omair Javaid if (reg == LLDB_INVALID_REGNUM) 29997206d57SZachary Turner return Status("no lldb regnum for %s", reg_info && reg_info->name 300b9c1b51eSKate Stone ? reg_info->name 301b9c1b51eSKate Stone : "<unknown register>"); 3021e209fccSTamas Berghammer 303b6f9d7b8SMuhammad Omair Javaid uint8_t *dst; 3044283320bSMuhammad Omair Javaid uint32_t offset = LLDB_INVALID_INDEX32; 305567ba6c4SMuhammad Omair Javaid std::vector<uint8_t> sve_reg_non_live; 3061e209fccSTamas Berghammer 307b6f9d7b8SMuhammad Omair Javaid if (IsGPR(reg)) { 308b6f9d7b8SMuhammad Omair Javaid error = ReadGPR(); 309068f8a7eSTamas Berghammer if (error.Fail()) 310068f8a7eSTamas Berghammer return error; 3111e209fccSTamas Berghammer 312567ba6c4SMuhammad Omair Javaid assert(reg_info->byte_offset < GetGPRSize()); 313567ba6c4SMuhammad Omair Javaid dst = (uint8_t *)GetGPRBuffer() + reg_info->byte_offset; 314b6f9d7b8SMuhammad Omair Javaid ::memcpy(dst, reg_value.GetBytes(), reg_info->byte_size); 315b6f9d7b8SMuhammad Omair Javaid 316b6f9d7b8SMuhammad Omair Javaid return WriteGPR(); 317b6f9d7b8SMuhammad Omair Javaid } else if (IsFPR(reg)) { 318567ba6c4SMuhammad Omair Javaid if (m_sve_state == SVEState::Disabled) { 319567ba6c4SMuhammad Omair Javaid // SVE is disabled take legacy route for FPU register access 320b6f9d7b8SMuhammad Omair Javaid error = ReadFPR(); 321b6f9d7b8SMuhammad Omair Javaid if (error.Fail()) 322b6f9d7b8SMuhammad Omair Javaid return error; 323567ba6c4SMuhammad Omair Javaid 324b6f9d7b8SMuhammad Omair Javaid offset = CalculateFprOffset(reg_info); 325b6f9d7b8SMuhammad Omair Javaid assert(offset < GetFPRSize()); 326b6f9d7b8SMuhammad Omair Javaid dst = (uint8_t *)GetFPRBuffer() + offset; 327b6f9d7b8SMuhammad Omair Javaid ::memcpy(dst, reg_value.GetBytes(), reg_info->byte_size); 328b6f9d7b8SMuhammad Omair Javaid 329b6f9d7b8SMuhammad Omair Javaid return WriteFPR(); 330567ba6c4SMuhammad Omair Javaid } else { 331567ba6c4SMuhammad Omair Javaid // SVE enabled, we will read and cache SVE ptrace data 332567ba6c4SMuhammad Omair Javaid error = ReadAllSVE(); 333567ba6c4SMuhammad Omair Javaid if (error.Fail()) 334567ba6c4SMuhammad Omair Javaid return error; 335567ba6c4SMuhammad Omair Javaid 336567ba6c4SMuhammad Omair Javaid // FPSR and FPCR will be located right after Z registers in 337567ba6c4SMuhammad Omair Javaid // SVEState::FPSIMD while in SVEState::Full they will be located at the 338567ba6c4SMuhammad Omair Javaid // end of register data after an alignment correction based on currently 339567ba6c4SMuhammad Omair Javaid // selected vector length. 340567ba6c4SMuhammad Omair Javaid uint32_t sve_reg_num = LLDB_INVALID_REGNUM; 341567ba6c4SMuhammad Omair Javaid if (reg == GetRegisterInfo().GetRegNumFPSR()) { 342567ba6c4SMuhammad Omair Javaid sve_reg_num = reg; 343567ba6c4SMuhammad Omair Javaid if (m_sve_state == SVEState::Full) 34405915400SCaroline Tice offset = sve::PTraceFPSROffset(sve::vq_from_vl(m_sve_header.vl)); 345567ba6c4SMuhammad Omair Javaid else if (m_sve_state == SVEState::FPSIMD) 34605915400SCaroline Tice offset = sve::ptrace_fpsimd_offset + (32 * 16); 347567ba6c4SMuhammad Omair Javaid } else if (reg == GetRegisterInfo().GetRegNumFPCR()) { 348567ba6c4SMuhammad Omair Javaid sve_reg_num = reg; 349567ba6c4SMuhammad Omair Javaid if (m_sve_state == SVEState::Full) 35005915400SCaroline Tice offset = sve::PTraceFPCROffset(sve::vq_from_vl(m_sve_header.vl)); 351567ba6c4SMuhammad Omair Javaid else if (m_sve_state == SVEState::FPSIMD) 35205915400SCaroline Tice offset = sve::ptrace_fpsimd_offset + (32 * 16) + 4; 353567ba6c4SMuhammad Omair Javaid } else { 354567ba6c4SMuhammad Omair Javaid // Extract SVE Z register value register number for this reg_info 355567ba6c4SMuhammad Omair Javaid if (reg_info->value_regs && 356567ba6c4SMuhammad Omair Javaid reg_info->value_regs[0] != LLDB_INVALID_REGNUM) 357567ba6c4SMuhammad Omair Javaid sve_reg_num = reg_info->value_regs[0]; 358567ba6c4SMuhammad Omair Javaid offset = CalculateSVEOffset(GetRegisterInfoAtIndex(sve_reg_num)); 359b6f9d7b8SMuhammad Omair Javaid } 360b6f9d7b8SMuhammad Omair Javaid 361567ba6c4SMuhammad Omair Javaid assert(offset < GetSVEBufferSize()); 362567ba6c4SMuhammad Omair Javaid dst = (uint8_t *)GetSVEBuffer() + offset; 363567ba6c4SMuhammad Omair Javaid ::memcpy(dst, reg_value.GetBytes(), reg_info->byte_size); 364567ba6c4SMuhammad Omair Javaid return WriteAllSVE(); 365567ba6c4SMuhammad Omair Javaid } 366567ba6c4SMuhammad Omair Javaid } else if (IsSVE(reg)) { 367567ba6c4SMuhammad Omair Javaid if (m_sve_state == SVEState::Disabled || m_sve_state == SVEState::Unknown) 368567ba6c4SMuhammad Omair Javaid return Status("SVE disabled or not supported"); 369567ba6c4SMuhammad Omair Javaid else { 370567ba6c4SMuhammad Omair Javaid // Target has SVE enabled, we will read and cache SVE ptrace data 371567ba6c4SMuhammad Omair Javaid error = ReadAllSVE(); 372567ba6c4SMuhammad Omair Javaid if (error.Fail()) 373b6f9d7b8SMuhammad Omair Javaid return error; 374567ba6c4SMuhammad Omair Javaid 375e448ad78SMuhammad Omair Javaid if (GetRegisterInfo().IsSVERegVG(reg)) { 376e448ad78SMuhammad Omair Javaid uint64_t vg_value = reg_value.GetAsUInt64(); 377e448ad78SMuhammad Omair Javaid 378e448ad78SMuhammad Omair Javaid if (sve_vl_valid(vg_value * 8)) { 379e448ad78SMuhammad Omair Javaid if (m_sve_header_is_valid && vg_value == GetSVERegVG()) 380e448ad78SMuhammad Omair Javaid return error; 381e448ad78SMuhammad Omair Javaid 382e448ad78SMuhammad Omair Javaid SetSVERegVG(vg_value); 383e448ad78SMuhammad Omair Javaid 384e448ad78SMuhammad Omair Javaid error = WriteSVEHeader(); 385e448ad78SMuhammad Omair Javaid if (error.Success()) 386e448ad78SMuhammad Omair Javaid ConfigureRegisterContext(); 387e448ad78SMuhammad Omair Javaid 388e448ad78SMuhammad Omair Javaid if (m_sve_header_is_valid && vg_value == GetSVERegVG()) 389e448ad78SMuhammad Omair Javaid return error; 390e448ad78SMuhammad Omair Javaid } 391e448ad78SMuhammad Omair Javaid 392e448ad78SMuhammad Omair Javaid return Status("SVE vector length update failed."); 393e448ad78SMuhammad Omair Javaid } 394e448ad78SMuhammad Omair Javaid 395567ba6c4SMuhammad Omair Javaid // If target supports SVE but currently in FPSIMD mode. 396567ba6c4SMuhammad Omair Javaid if (m_sve_state == SVEState::FPSIMD) { 397567ba6c4SMuhammad Omair Javaid // Here we will check if writing this SVE register enables 398567ba6c4SMuhammad Omair Javaid // SVEState::Full 399567ba6c4SMuhammad Omair Javaid bool set_sve_state_full = false; 400567ba6c4SMuhammad Omair Javaid const uint8_t *reg_bytes = (const uint8_t *)reg_value.GetBytes(); 401567ba6c4SMuhammad Omair Javaid if (GetRegisterInfo().IsSVEZReg(reg)) { 402567ba6c4SMuhammad Omair Javaid for (uint32_t i = 16; i < reg_info->byte_size; i++) { 403567ba6c4SMuhammad Omair Javaid if (reg_bytes[i]) { 404567ba6c4SMuhammad Omair Javaid set_sve_state_full = true; 405567ba6c4SMuhammad Omair Javaid break; 406567ba6c4SMuhammad Omair Javaid } 407567ba6c4SMuhammad Omair Javaid } 408567ba6c4SMuhammad Omair Javaid } else if (GetRegisterInfo().IsSVEPReg(reg) || 409567ba6c4SMuhammad Omair Javaid reg == GetRegisterInfo().GetRegNumSVEFFR()) { 410567ba6c4SMuhammad Omair Javaid for (uint32_t i = 0; i < reg_info->byte_size; i++) { 411567ba6c4SMuhammad Omair Javaid if (reg_bytes[i]) { 412567ba6c4SMuhammad Omair Javaid set_sve_state_full = true; 413567ba6c4SMuhammad Omair Javaid break; 414567ba6c4SMuhammad Omair Javaid } 415567ba6c4SMuhammad Omair Javaid } 416567ba6c4SMuhammad Omair Javaid } 417567ba6c4SMuhammad Omair Javaid 418567ba6c4SMuhammad Omair Javaid if (!set_sve_state_full && GetRegisterInfo().IsSVEZReg(reg)) { 419567ba6c4SMuhammad Omair Javaid // We are writing a Z register which is zero beyond 16 bytes so copy 420567ba6c4SMuhammad Omair Javaid // first 16 bytes only as SVE payload mirrors legacy fpsimd structure 421567ba6c4SMuhammad Omair Javaid offset = CalculateSVEOffset(reg_info); 422567ba6c4SMuhammad Omair Javaid assert(offset < GetSVEBufferSize()); 423567ba6c4SMuhammad Omair Javaid dst = (uint8_t *)GetSVEBuffer() + offset; 424567ba6c4SMuhammad Omair Javaid ::memcpy(dst, reg_value.GetBytes(), 16); 425567ba6c4SMuhammad Omair Javaid 426567ba6c4SMuhammad Omair Javaid return WriteAllSVE(); 427567ba6c4SMuhammad Omair Javaid } else 428567ba6c4SMuhammad Omair Javaid return Status("SVE state change operation not supported"); 429567ba6c4SMuhammad Omair Javaid } else { 430567ba6c4SMuhammad Omair Javaid offset = CalculateSVEOffset(reg_info); 431567ba6c4SMuhammad Omair Javaid assert(offset < GetSVEBufferSize()); 432567ba6c4SMuhammad Omair Javaid dst = (uint8_t *)GetSVEBuffer() + offset; 433567ba6c4SMuhammad Omair Javaid ::memcpy(dst, reg_value.GetBytes(), reg_info->byte_size); 434567ba6c4SMuhammad Omair Javaid return WriteAllSVE(); 435567ba6c4SMuhammad Omair Javaid } 436567ba6c4SMuhammad Omair Javaid } 43788a5b35dSMuhammad Omair Javaid } else if (IsMTE(reg)) { 43888a5b35dSMuhammad Omair Javaid error = ReadMTEControl(); 43988a5b35dSMuhammad Omair Javaid if (error.Fail()) 44088a5b35dSMuhammad Omair Javaid return error; 44188a5b35dSMuhammad Omair Javaid 44288a5b35dSMuhammad Omair Javaid offset = reg_info->byte_offset - GetRegisterInfo().GetMTEOffset(); 44388a5b35dSMuhammad Omair Javaid assert(offset < GetMTEControlSize()); 44488a5b35dSMuhammad Omair Javaid dst = (uint8_t *)GetMTEControl() + offset; 44588a5b35dSMuhammad Omair Javaid ::memcpy(dst, reg_value.GetBytes(), reg_info->byte_size); 44688a5b35dSMuhammad Omair Javaid 44788a5b35dSMuhammad Omair Javaid return WriteMTEControl(); 448567ba6c4SMuhammad Omair Javaid } 449567ba6c4SMuhammad Omair Javaid 450567ba6c4SMuhammad Omair Javaid return Status("Failed to write register value"); 4511e209fccSTamas Berghammer } 4521e209fccSTamas Berghammer 45397206d57SZachary Turner Status NativeRegisterContextLinux_arm64::ReadAllRegisterValues( 454b9c1b51eSKate Stone lldb::DataBufferSP &data_sp) { 45597206d57SZachary Turner Status error; 4561e209fccSTamas Berghammer 457db264a6dSTamas Berghammer data_sp.reset(new DataBufferHeap(REG_CONTEXT_SIZE, 0)); 458567ba6c4SMuhammad Omair Javaid 459068f8a7eSTamas Berghammer error = ReadGPR(); 460068f8a7eSTamas Berghammer if (error.Fail()) 4611e209fccSTamas Berghammer return error; 4621e209fccSTamas Berghammer 463068f8a7eSTamas Berghammer error = ReadFPR(); 464068f8a7eSTamas Berghammer if (error.Fail()) 4651e209fccSTamas Berghammer return error; 466567ba6c4SMuhammad Omair Javaid 4671e209fccSTamas Berghammer uint8_t *dst = data_sp->GetBytes(); 468b6f9d7b8SMuhammad Omair Javaid ::memcpy(dst, GetGPRBuffer(), GetGPRSize()); 4691e209fccSTamas Berghammer dst += GetGPRSize(); 470b6f9d7b8SMuhammad Omair Javaid ::memcpy(dst, GetFPRBuffer(), GetFPRSize()); 4711e209fccSTamas Berghammer 4721e209fccSTamas Berghammer return error; 4731e209fccSTamas Berghammer } 4741e209fccSTamas Berghammer 47597206d57SZachary Turner Status NativeRegisterContextLinux_arm64::WriteAllRegisterValues( 476b9c1b51eSKate Stone const lldb::DataBufferSP &data_sp) { 47797206d57SZachary Turner Status error; 4781e209fccSTamas Berghammer 479b9c1b51eSKate Stone if (!data_sp) { 480b9c1b51eSKate Stone error.SetErrorStringWithFormat( 481b9c1b51eSKate Stone "NativeRegisterContextLinux_x86_64::%s invalid data_sp provided", 482b9c1b51eSKate Stone __FUNCTION__); 4831e209fccSTamas Berghammer return error; 4841e209fccSTamas Berghammer } 4851e209fccSTamas Berghammer 486b9c1b51eSKate Stone if (data_sp->GetByteSize() != REG_CONTEXT_SIZE) { 487b9c1b51eSKate Stone error.SetErrorStringWithFormat( 488b9c1b51eSKate Stone "NativeRegisterContextLinux_x86_64::%s data_sp contained mismatched " 489b9c1b51eSKate Stone "data size, expected %" PRIu64 ", actual %" PRIu64, 490b9c1b51eSKate Stone __FUNCTION__, REG_CONTEXT_SIZE, data_sp->GetByteSize()); 4911e209fccSTamas Berghammer return error; 4921e209fccSTamas Berghammer } 4931e209fccSTamas Berghammer 4941e209fccSTamas Berghammer uint8_t *src = data_sp->GetBytes(); 495b9c1b51eSKate Stone if (src == nullptr) { 496b9c1b51eSKate Stone error.SetErrorStringWithFormat("NativeRegisterContextLinux_x86_64::%s " 497b9c1b51eSKate Stone "DataBuffer::GetBytes() returned a null " 498b9c1b51eSKate Stone "pointer", 499b9c1b51eSKate Stone __FUNCTION__); 5001e209fccSTamas Berghammer return error; 5011e209fccSTamas Berghammer } 502b6f9d7b8SMuhammad Omair Javaid ::memcpy(GetGPRBuffer(), src, GetRegisterInfoInterface().GetGPRSize()); 5031e209fccSTamas Berghammer 504068f8a7eSTamas Berghammer error = WriteGPR(); 505068f8a7eSTamas Berghammer if (error.Fail()) 5061e209fccSTamas Berghammer return error; 5071e209fccSTamas Berghammer 5081e209fccSTamas Berghammer src += GetRegisterInfoInterface().GetGPRSize(); 509b6f9d7b8SMuhammad Omair Javaid ::memcpy(GetFPRBuffer(), src, GetFPRSize()); 5101e209fccSTamas Berghammer 511068f8a7eSTamas Berghammer error = WriteFPR(); 5121e209fccSTamas Berghammer if (error.Fail()) 5131e209fccSTamas Berghammer return error; 5141e209fccSTamas Berghammer 5151e209fccSTamas Berghammer return error; 5161e209fccSTamas Berghammer } 5171e209fccSTamas Berghammer 518b9c1b51eSKate Stone bool NativeRegisterContextLinux_arm64::IsGPR(unsigned reg) const { 5197fa7b81bSMuhammad Omair Javaid if (GetRegisterInfo().GetRegisterSetFromRegisterIndex(reg) == 5207fa7b81bSMuhammad Omair Javaid RegisterInfoPOSIX_arm64::GPRegSet) 5217fa7b81bSMuhammad Omair Javaid return true; 5227fa7b81bSMuhammad Omair Javaid return false; 5231e209fccSTamas Berghammer } 5241e209fccSTamas Berghammer 525b9c1b51eSKate Stone bool NativeRegisterContextLinux_arm64::IsFPR(unsigned reg) const { 5267fa7b81bSMuhammad Omair Javaid if (GetRegisterInfo().GetRegisterSetFromRegisterIndex(reg) == 5277fa7b81bSMuhammad Omair Javaid RegisterInfoPOSIX_arm64::FPRegSet) 5287fa7b81bSMuhammad Omair Javaid return true; 5297fa7b81bSMuhammad Omair Javaid return false; 5301e209fccSTamas Berghammer } 5311e209fccSTamas Berghammer 532567ba6c4SMuhammad Omair Javaid bool NativeRegisterContextLinux_arm64::IsSVE(unsigned reg) const { 533d6d3d21cSMuhammad Omair Javaid return GetRegisterInfo().IsSVEReg(reg); 534567ba6c4SMuhammad Omair Javaid } 535567ba6c4SMuhammad Omair Javaid 53688a5b35dSMuhammad Omair Javaid bool NativeRegisterContextLinux_arm64::IsPAuth(unsigned reg) const { 53788a5b35dSMuhammad Omair Javaid return GetRegisterInfo().IsPAuthReg(reg); 53888a5b35dSMuhammad Omair Javaid } 53988a5b35dSMuhammad Omair Javaid 54088a5b35dSMuhammad Omair Javaid bool NativeRegisterContextLinux_arm64::IsMTE(unsigned reg) const { 54188a5b35dSMuhammad Omair Javaid return GetRegisterInfo().IsMTEReg(reg); 54288a5b35dSMuhammad Omair Javaid } 54388a5b35dSMuhammad Omair Javaid 544771c4c9cSMichał Górny llvm::Error NativeRegisterContextLinux_arm64::ReadHardwareDebugInfo() { 545b9c1b51eSKate Stone if (!m_refresh_hwdebug_info) { 546771c4c9cSMichał Górny return llvm::Error::success(); 5471fd2a8cfSOmair Javaid } 5481fd2a8cfSOmair Javaid 549c7512fdcSPavel Labath ::pid_t tid = m_thread.GetID(); 550ea8c25a8SOmair Javaid 551c7512fdcSPavel Labath int regset = NT_ARM_HW_WATCH; 552c7512fdcSPavel Labath struct iovec ioVec; 553c7512fdcSPavel Labath struct user_hwdebug_state dreg_state; 55497206d57SZachary Turner Status error; 555c7512fdcSPavel Labath 556c7512fdcSPavel Labath ioVec.iov_base = &dreg_state; 557c7512fdcSPavel Labath ioVec.iov_len = sizeof(dreg_state); 558b9c1b51eSKate Stone error = NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, tid, ®set, 559b9c1b51eSKate Stone &ioVec, ioVec.iov_len); 5603a56363aSOmair Javaid 5613a56363aSOmair Javaid if (error.Fail()) 562771c4c9cSMichał Górny return error.ToError(); 5633a56363aSOmair Javaid 5641fd2a8cfSOmair Javaid m_max_hwp_supported = dreg_state.dbg_info & 0xff; 565c7512fdcSPavel Labath 566c7512fdcSPavel Labath regset = NT_ARM_HW_BREAK; 567b9c1b51eSKate Stone error = NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, tid, ®set, 568b9c1b51eSKate Stone &ioVec, ioVec.iov_len); 5691fd2a8cfSOmair Javaid 5703a56363aSOmair Javaid if (error.Fail()) 571771c4c9cSMichał Górny return error.ToError(); 5723a56363aSOmair Javaid 5733a56363aSOmair Javaid m_max_hbp_supported = dreg_state.dbg_info & 0xff; 5741fd2a8cfSOmair Javaid m_refresh_hwdebug_info = false; 575c7512fdcSPavel Labath 576771c4c9cSMichał Górny return llvm::Error::success(); 577ea8c25a8SOmair Javaid } 578068f8a7eSTamas Berghammer 579771c4c9cSMichał Górny llvm::Error 580771c4c9cSMichał Górny NativeRegisterContextLinux_arm64::WriteHardwareDebugRegs(DREGType hwbType) { 581c7512fdcSPavel Labath struct iovec ioVec; 582c7512fdcSPavel Labath struct user_hwdebug_state dreg_state; 583771c4c9cSMichał Górny int regset; 584c7512fdcSPavel Labath 585c7512fdcSPavel Labath memset(&dreg_state, 0, sizeof(dreg_state)); 586c7512fdcSPavel Labath ioVec.iov_base = &dreg_state; 587c7512fdcSPavel Labath 588771c4c9cSMichał Górny switch (hwbType) { 589771c4c9cSMichał Górny case eDREGTypeWATCH: 590771c4c9cSMichał Górny regset = NT_ARM_HW_WATCH; 591b9c1b51eSKate Stone ioVec.iov_len = sizeof(dreg_state.dbg_info) + sizeof(dreg_state.pad) + 592b9c1b51eSKate Stone (sizeof(dreg_state.dbg_regs[0]) * m_max_hwp_supported); 5931fd2a8cfSOmair Javaid 594b9c1b51eSKate Stone for (uint32_t i = 0; i < m_max_hwp_supported; i++) { 5951fd2a8cfSOmair Javaid dreg_state.dbg_regs[i].addr = m_hwp_regs[i].address; 5961fd2a8cfSOmair Javaid dreg_state.dbg_regs[i].ctrl = m_hwp_regs[i].control; 5971fd2a8cfSOmair Javaid } 598771c4c9cSMichał Górny break; 599771c4c9cSMichał Górny case eDREGTypeBREAK: 600771c4c9cSMichał Górny regset = NT_ARM_HW_BREAK; 601b9c1b51eSKate Stone ioVec.iov_len = sizeof(dreg_state.dbg_info) + sizeof(dreg_state.pad) + 602b9c1b51eSKate Stone (sizeof(dreg_state.dbg_regs[0]) * m_max_hbp_supported); 6031fd2a8cfSOmair Javaid 604b9c1b51eSKate Stone for (uint32_t i = 0; i < m_max_hbp_supported; i++) { 605771c4c9cSMichał Górny dreg_state.dbg_regs[i].addr = m_hbp_regs[i].address; 606771c4c9cSMichał Górny dreg_state.dbg_regs[i].ctrl = m_hbp_regs[i].control; 6071fd2a8cfSOmair Javaid } 608771c4c9cSMichał Górny break; 609068f8a7eSTamas Berghammer } 610068f8a7eSTamas Berghammer 611b9c1b51eSKate Stone return NativeProcessLinux::PtraceWrapper(PTRACE_SETREGSET, m_thread.GetID(), 612771c4c9cSMichał Górny ®set, &ioVec, ioVec.iov_len) 613771c4c9cSMichał Górny .ToError(); 614c7512fdcSPavel Labath } 615c7512fdcSPavel Labath 6163f3673eaSPavel Labath Status NativeRegisterContextLinux_arm64::ReadGPR() { 617b6f9d7b8SMuhammad Omair Javaid Status error; 618b6f9d7b8SMuhammad Omair Javaid 619567ba6c4SMuhammad Omair Javaid if (m_gpr_is_valid) 620567ba6c4SMuhammad Omair Javaid return error; 621b6f9d7b8SMuhammad Omair Javaid 622567ba6c4SMuhammad Omair Javaid struct iovec ioVec; 6233f3673eaSPavel Labath ioVec.iov_base = GetGPRBuffer(); 62426b8ea2eSMuhammad Omair Javaid ioVec.iov_len = GetGPRBufferSize(); 625b6f9d7b8SMuhammad Omair Javaid 62626b8ea2eSMuhammad Omair Javaid error = ReadRegisterSet(&ioVec, GetGPRBufferSize(), NT_PRSTATUS); 627b6f9d7b8SMuhammad Omair Javaid 628b6f9d7b8SMuhammad Omair Javaid if (error.Success()) 629b6f9d7b8SMuhammad Omair Javaid m_gpr_is_valid = true; 630b6f9d7b8SMuhammad Omair Javaid 631b6f9d7b8SMuhammad Omair Javaid return error; 632068f8a7eSTamas Berghammer } 633068f8a7eSTamas Berghammer 6343f3673eaSPavel Labath Status NativeRegisterContextLinux_arm64::WriteGPR() { 635567ba6c4SMuhammad Omair Javaid Status error = ReadGPR(); 636567ba6c4SMuhammad Omair Javaid if (error.Fail()) 637567ba6c4SMuhammad Omair Javaid return error; 638567ba6c4SMuhammad Omair Javaid 639c7512fdcSPavel Labath struct iovec ioVec; 6403f3673eaSPavel Labath ioVec.iov_base = GetGPRBuffer(); 64126b8ea2eSMuhammad Omair Javaid ioVec.iov_len = GetGPRBufferSize(); 642b6f9d7b8SMuhammad Omair Javaid 643567ba6c4SMuhammad Omair Javaid m_gpr_is_valid = false; 644567ba6c4SMuhammad Omair Javaid 64526b8ea2eSMuhammad Omair Javaid return WriteRegisterSet(&ioVec, GetGPRBufferSize(), NT_PRSTATUS); 646068f8a7eSTamas Berghammer } 647068f8a7eSTamas Berghammer 6483f3673eaSPavel Labath Status NativeRegisterContextLinux_arm64::ReadFPR() { 649b6f9d7b8SMuhammad Omair Javaid Status error; 650b6f9d7b8SMuhammad Omair Javaid 651567ba6c4SMuhammad Omair Javaid if (m_fpu_is_valid) 652567ba6c4SMuhammad Omair Javaid return error; 653b6f9d7b8SMuhammad Omair Javaid 654567ba6c4SMuhammad Omair Javaid struct iovec ioVec; 6553f3673eaSPavel Labath ioVec.iov_base = GetFPRBuffer(); 6563f3673eaSPavel Labath ioVec.iov_len = GetFPRSize(); 657b6f9d7b8SMuhammad Omair Javaid 658b6f9d7b8SMuhammad Omair Javaid error = ReadRegisterSet(&ioVec, GetFPRSize(), NT_FPREGSET); 659b6f9d7b8SMuhammad Omair Javaid 660b6f9d7b8SMuhammad Omair Javaid if (error.Success()) 661b6f9d7b8SMuhammad Omair Javaid m_fpu_is_valid = true; 662b6f9d7b8SMuhammad Omair Javaid 663b6f9d7b8SMuhammad Omair Javaid return error; 664068f8a7eSTamas Berghammer } 665068f8a7eSTamas Berghammer 6663f3673eaSPavel Labath Status NativeRegisterContextLinux_arm64::WriteFPR() { 667567ba6c4SMuhammad Omair Javaid Status error = ReadFPR(); 668567ba6c4SMuhammad Omair Javaid if (error.Fail()) 669567ba6c4SMuhammad Omair Javaid return error; 670567ba6c4SMuhammad Omair Javaid 671c7512fdcSPavel Labath struct iovec ioVec; 6723f3673eaSPavel Labath ioVec.iov_base = GetFPRBuffer(); 6733f3673eaSPavel Labath ioVec.iov_len = GetFPRSize(); 674b6f9d7b8SMuhammad Omair Javaid 675567ba6c4SMuhammad Omair Javaid m_fpu_is_valid = false; 676567ba6c4SMuhammad Omair Javaid 6773f3673eaSPavel Labath return WriteRegisterSet(&ioVec, GetFPRSize(), NT_FPREGSET); 678068f8a7eSTamas Berghammer } 679068f8a7eSTamas Berghammer 680b6f9d7b8SMuhammad Omair Javaid void NativeRegisterContextLinux_arm64::InvalidateAllRegisters() { 681b6f9d7b8SMuhammad Omair Javaid m_gpr_is_valid = false; 682b6f9d7b8SMuhammad Omair Javaid m_fpu_is_valid = false; 683567ba6c4SMuhammad Omair Javaid m_sve_buffer_is_valid = false; 684567ba6c4SMuhammad Omair Javaid m_sve_header_is_valid = false; 68588a5b35dSMuhammad Omair Javaid m_pac_mask_is_valid = false; 68688a5b35dSMuhammad Omair Javaid m_mte_ctrl_is_valid = false; 687567ba6c4SMuhammad Omair Javaid 688567ba6c4SMuhammad Omair Javaid // Update SVE registers in case there is change in configuration. 689567ba6c4SMuhammad Omair Javaid ConfigureRegisterContext(); 690567ba6c4SMuhammad Omair Javaid } 691567ba6c4SMuhammad Omair Javaid 692567ba6c4SMuhammad Omair Javaid Status NativeRegisterContextLinux_arm64::ReadSVEHeader() { 693567ba6c4SMuhammad Omair Javaid Status error; 694567ba6c4SMuhammad Omair Javaid 695567ba6c4SMuhammad Omair Javaid if (m_sve_header_is_valid) 696567ba6c4SMuhammad Omair Javaid return error; 697567ba6c4SMuhammad Omair Javaid 698567ba6c4SMuhammad Omair Javaid struct iovec ioVec; 699567ba6c4SMuhammad Omair Javaid ioVec.iov_base = GetSVEHeader(); 700567ba6c4SMuhammad Omair Javaid ioVec.iov_len = GetSVEHeaderSize(); 701567ba6c4SMuhammad Omair Javaid 702567ba6c4SMuhammad Omair Javaid error = ReadRegisterSet(&ioVec, GetSVEHeaderSize(), NT_ARM_SVE); 703567ba6c4SMuhammad Omair Javaid 70488a5b35dSMuhammad Omair Javaid if (error.Success()) 705567ba6c4SMuhammad Omair Javaid m_sve_header_is_valid = true; 706567ba6c4SMuhammad Omair Javaid 707567ba6c4SMuhammad Omair Javaid return error; 708567ba6c4SMuhammad Omair Javaid } 709567ba6c4SMuhammad Omair Javaid 71088a5b35dSMuhammad Omair Javaid Status NativeRegisterContextLinux_arm64::ReadPAuthMask() { 71188a5b35dSMuhammad Omair Javaid Status error; 71288a5b35dSMuhammad Omair Javaid 71388a5b35dSMuhammad Omair Javaid if (m_pac_mask_is_valid) 71488a5b35dSMuhammad Omair Javaid return error; 71588a5b35dSMuhammad Omair Javaid 71688a5b35dSMuhammad Omair Javaid struct iovec ioVec; 71788a5b35dSMuhammad Omair Javaid ioVec.iov_base = GetPACMask(); 71888a5b35dSMuhammad Omair Javaid ioVec.iov_len = GetPACMaskSize(); 71988a5b35dSMuhammad Omair Javaid 72088a5b35dSMuhammad Omair Javaid error = ReadRegisterSet(&ioVec, GetPACMaskSize(), NT_ARM_PAC_MASK); 72188a5b35dSMuhammad Omair Javaid 72288a5b35dSMuhammad Omair Javaid if (error.Success()) 72388a5b35dSMuhammad Omair Javaid m_pac_mask_is_valid = true; 72488a5b35dSMuhammad Omair Javaid 72588a5b35dSMuhammad Omair Javaid return error; 72688a5b35dSMuhammad Omair Javaid } 72788a5b35dSMuhammad Omair Javaid 728567ba6c4SMuhammad Omair Javaid Status NativeRegisterContextLinux_arm64::WriteSVEHeader() { 729567ba6c4SMuhammad Omair Javaid Status error; 730567ba6c4SMuhammad Omair Javaid 731567ba6c4SMuhammad Omair Javaid error = ReadSVEHeader(); 732567ba6c4SMuhammad Omair Javaid if (error.Fail()) 733567ba6c4SMuhammad Omair Javaid return error; 734567ba6c4SMuhammad Omair Javaid 735567ba6c4SMuhammad Omair Javaid struct iovec ioVec; 736567ba6c4SMuhammad Omair Javaid ioVec.iov_base = GetSVEHeader(); 737567ba6c4SMuhammad Omair Javaid ioVec.iov_len = GetSVEHeaderSize(); 738567ba6c4SMuhammad Omair Javaid 739567ba6c4SMuhammad Omair Javaid m_sve_buffer_is_valid = false; 740567ba6c4SMuhammad Omair Javaid m_sve_header_is_valid = false; 741567ba6c4SMuhammad Omair Javaid m_fpu_is_valid = false; 742567ba6c4SMuhammad Omair Javaid 743567ba6c4SMuhammad Omair Javaid return WriteRegisterSet(&ioVec, GetSVEHeaderSize(), NT_ARM_SVE); 744567ba6c4SMuhammad Omair Javaid } 745567ba6c4SMuhammad Omair Javaid 746567ba6c4SMuhammad Omair Javaid Status NativeRegisterContextLinux_arm64::ReadAllSVE() { 747567ba6c4SMuhammad Omair Javaid Status error; 748567ba6c4SMuhammad Omair Javaid 749567ba6c4SMuhammad Omair Javaid if (m_sve_buffer_is_valid) 750567ba6c4SMuhammad Omair Javaid return error; 751567ba6c4SMuhammad Omair Javaid 752567ba6c4SMuhammad Omair Javaid struct iovec ioVec; 753567ba6c4SMuhammad Omair Javaid ioVec.iov_base = GetSVEBuffer(); 754567ba6c4SMuhammad Omair Javaid ioVec.iov_len = GetSVEBufferSize(); 755567ba6c4SMuhammad Omair Javaid 756567ba6c4SMuhammad Omair Javaid error = ReadRegisterSet(&ioVec, GetSVEBufferSize(), NT_ARM_SVE); 757567ba6c4SMuhammad Omair Javaid 758567ba6c4SMuhammad Omair Javaid if (error.Success()) 759567ba6c4SMuhammad Omair Javaid m_sve_buffer_is_valid = true; 760567ba6c4SMuhammad Omair Javaid 761567ba6c4SMuhammad Omair Javaid return error; 762567ba6c4SMuhammad Omair Javaid } 763567ba6c4SMuhammad Omair Javaid 764567ba6c4SMuhammad Omair Javaid Status NativeRegisterContextLinux_arm64::WriteAllSVE() { 765567ba6c4SMuhammad Omair Javaid Status error; 766567ba6c4SMuhammad Omair Javaid 767567ba6c4SMuhammad Omair Javaid error = ReadAllSVE(); 768567ba6c4SMuhammad Omair Javaid if (error.Fail()) 769567ba6c4SMuhammad Omair Javaid return error; 770567ba6c4SMuhammad Omair Javaid 771567ba6c4SMuhammad Omair Javaid struct iovec ioVec; 772567ba6c4SMuhammad Omair Javaid 773567ba6c4SMuhammad Omair Javaid ioVec.iov_base = GetSVEBuffer(); 774567ba6c4SMuhammad Omair Javaid ioVec.iov_len = GetSVEBufferSize(); 775567ba6c4SMuhammad Omair Javaid 776567ba6c4SMuhammad Omair Javaid m_sve_buffer_is_valid = false; 777567ba6c4SMuhammad Omair Javaid m_sve_header_is_valid = false; 778567ba6c4SMuhammad Omair Javaid m_fpu_is_valid = false; 779567ba6c4SMuhammad Omair Javaid 780567ba6c4SMuhammad Omair Javaid return WriteRegisterSet(&ioVec, GetSVEBufferSize(), NT_ARM_SVE); 781567ba6c4SMuhammad Omair Javaid } 782567ba6c4SMuhammad Omair Javaid 78388a5b35dSMuhammad Omair Javaid Status NativeRegisterContextLinux_arm64::ReadMTEControl() { 78488a5b35dSMuhammad Omair Javaid Status error; 78588a5b35dSMuhammad Omair Javaid 78688a5b35dSMuhammad Omair Javaid if (m_mte_ctrl_is_valid) 78788a5b35dSMuhammad Omair Javaid return error; 78888a5b35dSMuhammad Omair Javaid 78988a5b35dSMuhammad Omair Javaid struct iovec ioVec; 79088a5b35dSMuhammad Omair Javaid ioVec.iov_base = GetMTEControl(); 79188a5b35dSMuhammad Omair Javaid ioVec.iov_len = GetMTEControlSize(); 79288a5b35dSMuhammad Omair Javaid 79388a5b35dSMuhammad Omair Javaid error = ReadRegisterSet(&ioVec, GetMTEControlSize(), NT_ARM_TAGGED_ADDR_CTRL); 79488a5b35dSMuhammad Omair Javaid 79588a5b35dSMuhammad Omair Javaid if (error.Success()) 79688a5b35dSMuhammad Omair Javaid m_mte_ctrl_is_valid = true; 79788a5b35dSMuhammad Omair Javaid 79888a5b35dSMuhammad Omair Javaid return error; 79988a5b35dSMuhammad Omair Javaid } 80088a5b35dSMuhammad Omair Javaid 80188a5b35dSMuhammad Omair Javaid Status NativeRegisterContextLinux_arm64::WriteMTEControl() { 80288a5b35dSMuhammad Omair Javaid Status error; 80388a5b35dSMuhammad Omair Javaid 80488a5b35dSMuhammad Omair Javaid error = ReadMTEControl(); 80588a5b35dSMuhammad Omair Javaid if (error.Fail()) 80688a5b35dSMuhammad Omair Javaid return error; 80788a5b35dSMuhammad Omair Javaid 80888a5b35dSMuhammad Omair Javaid struct iovec ioVec; 80988a5b35dSMuhammad Omair Javaid ioVec.iov_base = GetMTEControl(); 81088a5b35dSMuhammad Omair Javaid ioVec.iov_len = GetMTEControlSize(); 81188a5b35dSMuhammad Omair Javaid 81288a5b35dSMuhammad Omair Javaid m_mte_ctrl_is_valid = false; 81388a5b35dSMuhammad Omair Javaid 81488a5b35dSMuhammad Omair Javaid return WriteRegisterSet(&ioVec, GetMTEControlSize(), NT_ARM_TAGGED_ADDR_CTRL); 81588a5b35dSMuhammad Omair Javaid } 81688a5b35dSMuhammad Omair Javaid 817567ba6c4SMuhammad Omair Javaid void NativeRegisterContextLinux_arm64::ConfigureRegisterContext() { 818d6d3d21cSMuhammad Omair Javaid // ConfigureRegisterContext gets called from InvalidateAllRegisters 819d6d3d21cSMuhammad Omair Javaid // on every stop and configures SVE vector length. 820d6d3d21cSMuhammad Omair Javaid // If m_sve_state is set to SVEState::Disabled on first stop, code below will 821d6d3d21cSMuhammad Omair Javaid // be deemed non operational for the lifetime of current process. 822567ba6c4SMuhammad Omair Javaid if (!m_sve_header_is_valid && m_sve_state != SVEState::Disabled) { 823567ba6c4SMuhammad Omair Javaid Status error = ReadSVEHeader(); 824d6d3d21cSMuhammad Omair Javaid if (error.Success()) { 825d6d3d21cSMuhammad Omair Javaid // If SVE is enabled thread can switch between SVEState::FPSIMD and 826d6d3d21cSMuhammad Omair Javaid // SVEState::Full on every stop. 82705915400SCaroline Tice if ((m_sve_header.flags & sve::ptrace_regs_mask) == 82805915400SCaroline Tice sve::ptrace_regs_fpsimd) 829567ba6c4SMuhammad Omair Javaid m_sve_state = SVEState::FPSIMD; 83005915400SCaroline Tice else if ((m_sve_header.flags & sve::ptrace_regs_mask) == 83105915400SCaroline Tice sve::ptrace_regs_sve) 832567ba6c4SMuhammad Omair Javaid m_sve_state = SVEState::Full; 833567ba6c4SMuhammad Omair Javaid 834d6d3d21cSMuhammad Omair Javaid // On every stop we configure SVE vector length by calling 835d6d3d21cSMuhammad Omair Javaid // ConfigureVectorLength regardless of current SVEState of this thread. 836567ba6c4SMuhammad Omair Javaid uint32_t vq = RegisterInfoPOSIX_arm64::eVectorQuadwordAArch64SVE; 837567ba6c4SMuhammad Omair Javaid if (sve_vl_valid(m_sve_header.vl)) 83805915400SCaroline Tice vq = sve::vq_from_vl(m_sve_header.vl); 839d6d3d21cSMuhammad Omair Javaid 840d6d3d21cSMuhammad Omair Javaid GetRegisterInfo().ConfigureVectorLength(vq); 84105915400SCaroline Tice m_sve_ptrace_payload.resize(sve::PTraceSize(vq, sve::ptrace_regs_sve)); 842567ba6c4SMuhammad Omair Javaid } 843567ba6c4SMuhammad Omair Javaid } 844b6f9d7b8SMuhammad Omair Javaid } 845b6f9d7b8SMuhammad Omair Javaid 846b9c1b51eSKate Stone uint32_t NativeRegisterContextLinux_arm64::CalculateFprOffset( 847b9c1b51eSKate Stone const RegisterInfo *reg_info) const { 8487fa7b81bSMuhammad Omair Javaid return reg_info->byte_offset - GetGPRSize(); 849c40e7b17STamas Berghammer } 850c40e7b17STamas Berghammer 851567ba6c4SMuhammad Omair Javaid uint32_t NativeRegisterContextLinux_arm64::CalculateSVEOffset( 852567ba6c4SMuhammad Omair Javaid const RegisterInfo *reg_info) const { 853567ba6c4SMuhammad Omair Javaid // Start of Z0 data is after GPRs plus 8 bytes of vg register 854567ba6c4SMuhammad Omair Javaid uint32_t sve_reg_offset = LLDB_INVALID_INDEX32; 855567ba6c4SMuhammad Omair Javaid if (m_sve_state == SVEState::FPSIMD) { 856567ba6c4SMuhammad Omair Javaid const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; 85705915400SCaroline Tice sve_reg_offset = sve::ptrace_fpsimd_offset + 85805915400SCaroline Tice (reg - GetRegisterInfo().GetRegNumSVEZ0()) * 16; 859567ba6c4SMuhammad Omair Javaid } else if (m_sve_state == SVEState::Full) { 860661e4040SMuhammad Omair Javaid uint32_t sve_z0_offset = GetGPRSize() + 16; 861567ba6c4SMuhammad Omair Javaid sve_reg_offset = 86205915400SCaroline Tice sve::SigRegsOffset() + reg_info->byte_offset - sve_z0_offset; 863567ba6c4SMuhammad Omair Javaid } 864567ba6c4SMuhammad Omair Javaid return sve_reg_offset; 865567ba6c4SMuhammad Omair Javaid } 866567ba6c4SMuhammad Omair Javaid 867567ba6c4SMuhammad Omair Javaid void *NativeRegisterContextLinux_arm64::GetSVEBuffer() { 868567ba6c4SMuhammad Omair Javaid if (m_sve_state == SVEState::FPSIMD) 86905915400SCaroline Tice return m_sve_ptrace_payload.data() + sve::ptrace_fpsimd_offset; 870567ba6c4SMuhammad Omair Javaid 871567ba6c4SMuhammad Omair Javaid return m_sve_ptrace_payload.data(); 872567ba6c4SMuhammad Omair Javaid } 873567ba6c4SMuhammad Omair Javaid 8744e8aeb97SMuhammad Omair Javaid std::vector<uint32_t> NativeRegisterContextLinux_arm64::GetExpeditedRegisters( 8754e8aeb97SMuhammad Omair Javaid ExpeditedRegs expType) const { 8764e8aeb97SMuhammad Omair Javaid std::vector<uint32_t> expedited_reg_nums = 8774e8aeb97SMuhammad Omair Javaid NativeRegisterContext::GetExpeditedRegisters(expType); 8784e8aeb97SMuhammad Omair Javaid if (m_sve_state == SVEState::FPSIMD || m_sve_state == SVEState::Full) 8794e8aeb97SMuhammad Omair Javaid expedited_reg_nums.push_back(GetRegisterInfo().GetRegNumSVEVG()); 8804e8aeb97SMuhammad Omair Javaid 8814e8aeb97SMuhammad Omair Javaid return expedited_reg_nums; 8824e8aeb97SMuhammad Omair Javaid } 8834e8aeb97SMuhammad Omair Javaid 884da2e614fSDavid Spickett llvm::Expected<NativeRegisterContextLinux::MemoryTaggingDetails> 885da2e614fSDavid Spickett NativeRegisterContextLinux_arm64::GetMemoryTaggingDetails(int32_t type) { 886da2e614fSDavid Spickett if (type == MemoryTagManagerAArch64MTE::eMTE_allocation) { 887da2e614fSDavid Spickett return MemoryTaggingDetails{std::make_unique<MemoryTagManagerAArch64MTE>(), 888da2e614fSDavid Spickett PTRACE_PEEKMTETAGS, PTRACE_POKEMTETAGS}; 889da2e614fSDavid Spickett } 890da2e614fSDavid Spickett 891da2e614fSDavid Spickett return llvm::createStringError(llvm::inconvertibleErrorCode(), 892da2e614fSDavid Spickett "Unknown AArch64 memory tag type %d", type); 893da2e614fSDavid Spickett } 894da2e614fSDavid Spickett 895*5e6aabd4SMuhammad Omair Javaid lldb::addr_t NativeRegisterContextLinux_arm64::FixWatchpointHitAddress( 896*5e6aabd4SMuhammad Omair Javaid lldb::addr_t hit_addr) { 897*5e6aabd4SMuhammad Omair Javaid // Linux configures user-space virtual addresses with top byte ignored. 898*5e6aabd4SMuhammad Omair Javaid // We set default value of mask such that top byte is masked out. 899*5e6aabd4SMuhammad Omair Javaid lldb::addr_t mask = ~((1ULL << 56) - 1); 900*5e6aabd4SMuhammad Omair Javaid 901*5e6aabd4SMuhammad Omair Javaid // Try to read pointer authentication data_mask register and calculate a 902*5e6aabd4SMuhammad Omair Javaid // consolidated data address mask after ignoring the top byte. 903*5e6aabd4SMuhammad Omair Javaid if (ReadPAuthMask().Success()) 904*5e6aabd4SMuhammad Omair Javaid mask |= m_pac_mask.data_mask; 905*5e6aabd4SMuhammad Omair Javaid 906*5e6aabd4SMuhammad Omair Javaid return hit_addr & ~mask; 907*5e6aabd4SMuhammad Omair Javaid ; 908*5e6aabd4SMuhammad Omair Javaid } 909*5e6aabd4SMuhammad Omair Javaid 910068f8a7eSTamas Berghammer #endif // defined (__arm64__) || defined (__aarch64__) 911