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" 16666cc0b2SZachary Turner #include "lldb/Utility/DataBufferHeap.h" 176f9e6901SZachary Turner #include "lldb/Utility/Log.h" 18d821c997SPavel Labath #include "lldb/Utility/RegisterValue.h" 1997206d57SZachary Turner #include "lldb/Utility/Status.h" 201e209fccSTamas Berghammer 21068f8a7eSTamas Berghammer #include "Plugins/Process/Linux/NativeProcessLinux.h" 22068f8a7eSTamas Berghammer #include "Plugins/Process/Linux/Procfs.h" 23e85e6021STamas Berghammer #include "Plugins/Process/POSIX/ProcessPOSIXLog.h" 24567ba6c4SMuhammad Omair Javaid #include "Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h" 25068f8a7eSTamas Berghammer 26b9c1b51eSKate Stone // System includes - They have to be included after framework includes because 2705097246SAdrian Prantl // they define some macros which collide with variable names in other modules 28068f8a7eSTamas Berghammer #include <sys/socket.h> 29068f8a7eSTamas Berghammer // NT_PRSTATUS and NT_FPREGSET definition 30068f8a7eSTamas Berghammer #include <elf.h> 31567ba6c4SMuhammad Omair Javaid 32567ba6c4SMuhammad Omair Javaid #ifndef NT_ARM_SVE 33567ba6c4SMuhammad Omair Javaid #define NT_ARM_SVE 0x405 /* ARM Scalable Vector Extension */ 34567ba6c4SMuhammad Omair Javaid #endif 35068f8a7eSTamas Berghammer 36068f8a7eSTamas Berghammer #define REG_CONTEXT_SIZE (GetGPRSize() + GetFPRSize()) 371e209fccSTamas Berghammer 381e209fccSTamas Berghammer using namespace lldb; 391e209fccSTamas Berghammer using namespace lldb_private; 40db264a6dSTamas Berghammer using namespace lldb_private::process_linux; 411e209fccSTamas Berghammer 42d37349f3SPavel Labath std::unique_ptr<NativeRegisterContextLinux> 43b9c1b51eSKate Stone NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux( 44d1486e65SPavel Labath const ArchSpec &target_arch, NativeThreadLinux &native_thread) { 45b9c1b51eSKate Stone switch (target_arch.GetMachine()) { 46e85e6021STamas Berghammer case llvm::Triple::arm: 47a8f3ae7cSJonas Devlieghere return std::make_unique<NativeRegisterContextLinux_arm>(target_arch, 48d37349f3SPavel Labath native_thread); 49d6d3d21cSMuhammad Omair Javaid case llvm::Triple::aarch64: { 50d6d3d21cSMuhammad Omair Javaid // Configure register sets supported by this AArch64 target. 51d6d3d21cSMuhammad Omair Javaid // Read SVE header to check for SVE support. 52d6d3d21cSMuhammad Omair Javaid struct user_sve_header sve_header; 53d6d3d21cSMuhammad Omair Javaid struct iovec ioVec; 54d6d3d21cSMuhammad Omair Javaid ioVec.iov_base = &sve_header; 55d6d3d21cSMuhammad Omair Javaid ioVec.iov_len = sizeof(sve_header); 56d6d3d21cSMuhammad Omair Javaid unsigned int regset = NT_ARM_SVE; 57d6d3d21cSMuhammad Omair Javaid 58d6d3d21cSMuhammad Omair Javaid Flags opt_regsets; 59d6d3d21cSMuhammad Omair Javaid if (NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, 60d6d3d21cSMuhammad Omair Javaid native_thread.GetID(), ®set, 61d6d3d21cSMuhammad Omair Javaid &ioVec, sizeof(sve_header)) 62d6d3d21cSMuhammad Omair Javaid .Success()) 63d6d3d21cSMuhammad Omair Javaid opt_regsets.Set(RegisterInfoPOSIX_arm64::eRegsetMaskSVE); 64d6d3d21cSMuhammad Omair Javaid 65d6d3d21cSMuhammad Omair Javaid auto register_info_up = 66d6d3d21cSMuhammad Omair Javaid std::make_unique<RegisterInfoPOSIX_arm64>(target_arch, opt_regsets); 67d6d3d21cSMuhammad Omair Javaid return std::make_unique<NativeRegisterContextLinux_arm64>( 68d6d3d21cSMuhammad Omair Javaid target_arch, native_thread, std::move(register_info_up)); 69d6d3d21cSMuhammad Omair Javaid } 70e85e6021STamas Berghammer default: 71ea1b6b17SPavel Labath llvm_unreachable("have no register context for architecture"); 72e85e6021STamas Berghammer } 73068f8a7eSTamas Berghammer } 74068f8a7eSTamas Berghammer 75b9c1b51eSKate Stone NativeRegisterContextLinux_arm64::NativeRegisterContextLinux_arm64( 76d6d3d21cSMuhammad Omair Javaid const ArchSpec &target_arch, NativeThreadProtocol &native_thread, 77d6d3d21cSMuhammad Omair Javaid std::unique_ptr<RegisterInfoPOSIX_arm64> register_info_up) 78d6d3d21cSMuhammad Omair Javaid : NativeRegisterContextRegisterInfo(native_thread, 79*e1d4fb1eSPavel Labath register_info_up.release()), 80*e1d4fb1eSPavel Labath NativeRegisterContextLinux(native_thread) { 811e209fccSTamas Berghammer ::memset(&m_fpr, 0, sizeof(m_fpr)); 821e209fccSTamas Berghammer ::memset(&m_gpr_arm64, 0, sizeof(m_gpr_arm64)); 83ea8c25a8SOmair Javaid ::memset(&m_hwp_regs, 0, sizeof(m_hwp_regs)); 84771c4c9cSMichał Górny ::memset(&m_hbp_regs, 0, sizeof(m_hbp_regs)); 85567ba6c4SMuhammad Omair Javaid ::memset(&m_sve_header, 0, sizeof(m_sve_header)); 86ea8c25a8SOmair Javaid 87ea8c25a8SOmair Javaid // 16 is just a maximum value, query hardware for actual watchpoint count 88ea8c25a8SOmair Javaid m_max_hwp_supported = 16; 89ea8c25a8SOmair Javaid m_max_hbp_supported = 16; 90567ba6c4SMuhammad Omair Javaid 91ea8c25a8SOmair Javaid m_refresh_hwdebug_info = true; 92b6f9d7b8SMuhammad Omair Javaid 93b6f9d7b8SMuhammad Omair Javaid m_gpr_is_valid = false; 94b6f9d7b8SMuhammad Omair Javaid m_fpu_is_valid = false; 95567ba6c4SMuhammad Omair Javaid m_sve_buffer_is_valid = false; 96567ba6c4SMuhammad Omair Javaid m_sve_header_is_valid = false; 97567ba6c4SMuhammad Omair Javaid 98d6d3d21cSMuhammad Omair Javaid if (GetRegisterInfo().IsSVEEnabled()) 99567ba6c4SMuhammad Omair Javaid m_sve_state = SVEState::Unknown; 100d6d3d21cSMuhammad Omair Javaid else 101d6d3d21cSMuhammad Omair Javaid m_sve_state = SVEState::Disabled; 1021e209fccSTamas Berghammer } 1031e209fccSTamas Berghammer 1047fa7b81bSMuhammad Omair Javaid RegisterInfoPOSIX_arm64 & 1057fa7b81bSMuhammad Omair Javaid NativeRegisterContextLinux_arm64::GetRegisterInfo() const { 1067fa7b81bSMuhammad Omair Javaid return static_cast<RegisterInfoPOSIX_arm64 &>(*m_register_info_interface_up); 1077fa7b81bSMuhammad Omair Javaid } 1087fa7b81bSMuhammad Omair Javaid 109b9c1b51eSKate Stone uint32_t NativeRegisterContextLinux_arm64::GetRegisterSetCount() const { 1107fa7b81bSMuhammad Omair Javaid return GetRegisterInfo().GetRegisterSetCount(); 1111e209fccSTamas Berghammer } 1121e209fccSTamas Berghammer 113db264a6dSTamas Berghammer const RegisterSet * 114b9c1b51eSKate Stone NativeRegisterContextLinux_arm64::GetRegisterSet(uint32_t set_index) const { 1157fa7b81bSMuhammad Omair Javaid return GetRegisterInfo().GetRegisterSet(set_index); 1161e209fccSTamas Berghammer } 1171e209fccSTamas Berghammer 118b9c1b51eSKate Stone uint32_t NativeRegisterContextLinux_arm64::GetUserRegisterCount() const { 119cec93c35STamas Berghammer uint32_t count = 0; 1207fa7b81bSMuhammad Omair Javaid for (uint32_t set_index = 0; set_index < GetRegisterSetCount(); ++set_index) 1217fa7b81bSMuhammad Omair Javaid count += GetRegisterSet(set_index)->num_registers; 122cec93c35STamas Berghammer return count; 123cec93c35STamas Berghammer } 124cec93c35STamas Berghammer 12597206d57SZachary Turner Status 12697206d57SZachary Turner NativeRegisterContextLinux_arm64::ReadRegister(const RegisterInfo *reg_info, 12797206d57SZachary Turner RegisterValue ®_value) { 12897206d57SZachary Turner Status error; 1291e209fccSTamas Berghammer 130b9c1b51eSKate Stone if (!reg_info) { 1311e209fccSTamas Berghammer error.SetErrorString("reg_info NULL"); 1321e209fccSTamas Berghammer return error; 1331e209fccSTamas Berghammer } 1341e209fccSTamas Berghammer 1351e209fccSTamas Berghammer const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; 1361e209fccSTamas Berghammer 137b6f9d7b8SMuhammad Omair Javaid if (reg == LLDB_INVALID_REGNUM) 138b6f9d7b8SMuhammad Omair Javaid return Status("no lldb regnum for %s", reg_info && reg_info->name 139b6f9d7b8SMuhammad Omair Javaid ? reg_info->name 140b6f9d7b8SMuhammad Omair Javaid : "<unknown register>"); 141b6f9d7b8SMuhammad Omair Javaid 142b6f9d7b8SMuhammad Omair Javaid uint8_t *src; 1434283320bSMuhammad Omair Javaid uint32_t offset = LLDB_INVALID_INDEX32; 144567ba6c4SMuhammad Omair Javaid uint64_t sve_vg; 145567ba6c4SMuhammad Omair Javaid std::vector<uint8_t> sve_reg_non_live; 146b6f9d7b8SMuhammad Omair Javaid 147b6f9d7b8SMuhammad Omair Javaid if (IsGPR(reg)) { 148b6f9d7b8SMuhammad Omair Javaid error = ReadGPR(); 149b6f9d7b8SMuhammad Omair Javaid if (error.Fail()) 150b6f9d7b8SMuhammad Omair Javaid return error; 151b6f9d7b8SMuhammad Omair Javaid 152b6f9d7b8SMuhammad Omair Javaid offset = reg_info->byte_offset; 153b6f9d7b8SMuhammad Omair Javaid assert(offset < GetGPRSize()); 154b6f9d7b8SMuhammad Omair Javaid src = (uint8_t *)GetGPRBuffer() + offset; 155b6f9d7b8SMuhammad Omair Javaid 156b6f9d7b8SMuhammad Omair Javaid } else if (IsFPR(reg)) { 157567ba6c4SMuhammad Omair Javaid if (m_sve_state == SVEState::Disabled) { 158567ba6c4SMuhammad Omair Javaid // SVE is disabled take legacy route for FPU register access 159068f8a7eSTamas Berghammer error = ReadFPR(); 160068f8a7eSTamas Berghammer if (error.Fail()) 1611e209fccSTamas Berghammer return error; 162567ba6c4SMuhammad Omair Javaid 163b6f9d7b8SMuhammad Omair Javaid offset = CalculateFprOffset(reg_info); 164b6f9d7b8SMuhammad Omair Javaid assert(offset < GetFPRSize()); 165b6f9d7b8SMuhammad Omair Javaid src = (uint8_t *)GetFPRBuffer() + offset; 166567ba6c4SMuhammad Omair Javaid } else { 167567ba6c4SMuhammad Omair Javaid // SVE enabled, we will read and cache SVE ptrace data 168567ba6c4SMuhammad Omair Javaid error = ReadAllSVE(); 169567ba6c4SMuhammad Omair Javaid if (error.Fail()) 170567ba6c4SMuhammad Omair Javaid return error; 171567ba6c4SMuhammad Omair Javaid 172567ba6c4SMuhammad Omair Javaid // FPSR and FPCR will be located right after Z registers in 173567ba6c4SMuhammad Omair Javaid // SVEState::FPSIMD while in SVEState::Full they will be located at the 174567ba6c4SMuhammad Omair Javaid // end of register data after an alignment correction based on currently 175567ba6c4SMuhammad Omair Javaid // selected vector length. 176567ba6c4SMuhammad Omair Javaid uint32_t sve_reg_num = LLDB_INVALID_REGNUM; 177567ba6c4SMuhammad Omair Javaid if (reg == GetRegisterInfo().GetRegNumFPSR()) { 178567ba6c4SMuhammad Omair Javaid sve_reg_num = reg; 179567ba6c4SMuhammad Omair Javaid if (m_sve_state == SVEState::Full) 180567ba6c4SMuhammad Omair Javaid offset = SVE_PT_SVE_FPSR_OFFSET(sve_vq_from_vl(m_sve_header.vl)); 181567ba6c4SMuhammad Omair Javaid else if (m_sve_state == SVEState::FPSIMD) 182567ba6c4SMuhammad Omair Javaid offset = SVE_PT_FPSIMD_OFFSET + (32 * 16); 183567ba6c4SMuhammad Omair Javaid } else if (reg == GetRegisterInfo().GetRegNumFPCR()) { 184567ba6c4SMuhammad Omair Javaid sve_reg_num = reg; 185567ba6c4SMuhammad Omair Javaid if (m_sve_state == SVEState::Full) 186567ba6c4SMuhammad Omair Javaid offset = SVE_PT_SVE_FPCR_OFFSET(sve_vq_from_vl(m_sve_header.vl)); 187567ba6c4SMuhammad Omair Javaid else if (m_sve_state == SVEState::FPSIMD) 188567ba6c4SMuhammad Omair Javaid offset = SVE_PT_FPSIMD_OFFSET + (32 * 16) + 4; 189567ba6c4SMuhammad Omair Javaid } else { 190567ba6c4SMuhammad Omair Javaid // Extract SVE Z register value register number for this reg_info 191567ba6c4SMuhammad Omair Javaid if (reg_info->value_regs && 192567ba6c4SMuhammad Omair Javaid reg_info->value_regs[0] != LLDB_INVALID_REGNUM) 193567ba6c4SMuhammad Omair Javaid sve_reg_num = reg_info->value_regs[0]; 194567ba6c4SMuhammad Omair Javaid offset = CalculateSVEOffset(GetRegisterInfoAtIndex(sve_reg_num)); 195567ba6c4SMuhammad Omair Javaid } 196567ba6c4SMuhammad Omair Javaid 197567ba6c4SMuhammad Omair Javaid assert(offset < GetSVEBufferSize()); 198567ba6c4SMuhammad Omair Javaid src = (uint8_t *)GetSVEBuffer() + offset; 199567ba6c4SMuhammad Omair Javaid } 200567ba6c4SMuhammad Omair Javaid } else if (IsSVE(reg)) { 201567ba6c4SMuhammad Omair Javaid 202567ba6c4SMuhammad Omair Javaid if (m_sve_state == SVEState::Disabled || m_sve_state == SVEState::Unknown) 203567ba6c4SMuhammad Omair Javaid return Status("SVE disabled or not supported"); 204567ba6c4SMuhammad Omair Javaid 205567ba6c4SMuhammad Omair Javaid if (GetRegisterInfo().IsSVERegVG(reg)) { 206567ba6c4SMuhammad Omair Javaid sve_vg = GetSVERegVG(); 207567ba6c4SMuhammad Omair Javaid src = (uint8_t *)&sve_vg; 208567ba6c4SMuhammad Omair Javaid } else { 209567ba6c4SMuhammad Omair Javaid // SVE enabled, we will read and cache SVE ptrace data 210567ba6c4SMuhammad Omair Javaid error = ReadAllSVE(); 211567ba6c4SMuhammad Omair Javaid if (error.Fail()) 212567ba6c4SMuhammad Omair Javaid return error; 213567ba6c4SMuhammad Omair Javaid 214567ba6c4SMuhammad Omair Javaid if (m_sve_state == SVEState::FPSIMD) { 215567ba6c4SMuhammad Omair Javaid // In FPSIMD state SVE payload mirrors legacy fpsimd struct and so 216567ba6c4SMuhammad Omair Javaid // just copy 16 bytes of v register to the start of z register. All 217567ba6c4SMuhammad Omair Javaid // other SVE register will be set to zero. 218567ba6c4SMuhammad Omair Javaid sve_reg_non_live.resize(reg_info->byte_size, 0); 219567ba6c4SMuhammad Omair Javaid src = sve_reg_non_live.data(); 220567ba6c4SMuhammad Omair Javaid 221567ba6c4SMuhammad Omair Javaid if (GetRegisterInfo().IsSVEZReg(reg)) { 222567ba6c4SMuhammad Omair Javaid offset = CalculateSVEOffset(reg_info); 223567ba6c4SMuhammad Omair Javaid assert(offset < GetSVEBufferSize()); 224567ba6c4SMuhammad Omair Javaid ::memcpy(sve_reg_non_live.data(), (uint8_t *)GetSVEBuffer() + offset, 225567ba6c4SMuhammad Omair Javaid 16); 226567ba6c4SMuhammad Omair Javaid } 227567ba6c4SMuhammad Omair Javaid } else { 228567ba6c4SMuhammad Omair Javaid offset = CalculateSVEOffset(reg_info); 229567ba6c4SMuhammad Omair Javaid assert(offset < GetSVEBufferSize()); 230567ba6c4SMuhammad Omair Javaid src = (uint8_t *)GetSVEBuffer() + offset; 231567ba6c4SMuhammad Omair Javaid } 232567ba6c4SMuhammad Omair Javaid } 233b6f9d7b8SMuhammad Omair Javaid } else 234b6f9d7b8SMuhammad Omair Javaid return Status("failed - register wasn't recognized to be a GPR or an FPR, " 235b6f9d7b8SMuhammad Omair Javaid "write strategy unknown"); 2361e209fccSTamas Berghammer 237b9c1b51eSKate Stone reg_value.SetFromMemoryData(reg_info, src, reg_info->byte_size, 238b9c1b51eSKate Stone eByteOrderLittle, error); 2391e209fccSTamas Berghammer 2401e209fccSTamas Berghammer return error; 2411e209fccSTamas Berghammer } 2421e209fccSTamas Berghammer 24397206d57SZachary Turner Status NativeRegisterContextLinux_arm64::WriteRegister( 244b9c1b51eSKate Stone const RegisterInfo *reg_info, const RegisterValue ®_value) { 245b6f9d7b8SMuhammad Omair Javaid Status error; 246b6f9d7b8SMuhammad Omair Javaid 2471e209fccSTamas Berghammer if (!reg_info) 24897206d57SZachary Turner return Status("reg_info NULL"); 2491e209fccSTamas Berghammer 250b6f9d7b8SMuhammad Omair Javaid const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; 251b6f9d7b8SMuhammad Omair Javaid 252b6f9d7b8SMuhammad Omair Javaid if (reg == LLDB_INVALID_REGNUM) 25397206d57SZachary Turner return Status("no lldb regnum for %s", reg_info && reg_info->name 254b9c1b51eSKate Stone ? reg_info->name 255b9c1b51eSKate Stone : "<unknown register>"); 2561e209fccSTamas Berghammer 257b6f9d7b8SMuhammad Omair Javaid uint8_t *dst; 2584283320bSMuhammad Omair Javaid uint32_t offset = LLDB_INVALID_INDEX32; 259567ba6c4SMuhammad Omair Javaid std::vector<uint8_t> sve_reg_non_live; 2601e209fccSTamas Berghammer 261b6f9d7b8SMuhammad Omair Javaid if (IsGPR(reg)) { 262b6f9d7b8SMuhammad Omair Javaid error = ReadGPR(); 263068f8a7eSTamas Berghammer if (error.Fail()) 264068f8a7eSTamas Berghammer return error; 2651e209fccSTamas Berghammer 266567ba6c4SMuhammad Omair Javaid assert(reg_info->byte_offset < GetGPRSize()); 267567ba6c4SMuhammad Omair Javaid dst = (uint8_t *)GetGPRBuffer() + reg_info->byte_offset; 268b6f9d7b8SMuhammad Omair Javaid ::memcpy(dst, reg_value.GetBytes(), reg_info->byte_size); 269b6f9d7b8SMuhammad Omair Javaid 270b6f9d7b8SMuhammad Omair Javaid return WriteGPR(); 271b6f9d7b8SMuhammad Omair Javaid } else if (IsFPR(reg)) { 272567ba6c4SMuhammad Omair Javaid if (m_sve_state == SVEState::Disabled) { 273567ba6c4SMuhammad Omair Javaid // SVE is disabled take legacy route for FPU register access 274b6f9d7b8SMuhammad Omair Javaid error = ReadFPR(); 275b6f9d7b8SMuhammad Omair Javaid if (error.Fail()) 276b6f9d7b8SMuhammad Omair Javaid return error; 277567ba6c4SMuhammad Omair Javaid 278b6f9d7b8SMuhammad Omair Javaid offset = CalculateFprOffset(reg_info); 279b6f9d7b8SMuhammad Omair Javaid assert(offset < GetFPRSize()); 280b6f9d7b8SMuhammad Omair Javaid dst = (uint8_t *)GetFPRBuffer() + offset; 281b6f9d7b8SMuhammad Omair Javaid ::memcpy(dst, reg_value.GetBytes(), reg_info->byte_size); 282b6f9d7b8SMuhammad Omair Javaid 283b6f9d7b8SMuhammad Omair Javaid return WriteFPR(); 284567ba6c4SMuhammad Omair Javaid } else { 285567ba6c4SMuhammad Omair Javaid // SVE enabled, we will read and cache SVE ptrace data 286567ba6c4SMuhammad Omair Javaid error = ReadAllSVE(); 287567ba6c4SMuhammad Omair Javaid if (error.Fail()) 288567ba6c4SMuhammad Omair Javaid return error; 289567ba6c4SMuhammad Omair Javaid 290567ba6c4SMuhammad Omair Javaid // FPSR and FPCR will be located right after Z registers in 291567ba6c4SMuhammad Omair Javaid // SVEState::FPSIMD while in SVEState::Full they will be located at the 292567ba6c4SMuhammad Omair Javaid // end of register data after an alignment correction based on currently 293567ba6c4SMuhammad Omair Javaid // selected vector length. 294567ba6c4SMuhammad Omair Javaid uint32_t sve_reg_num = LLDB_INVALID_REGNUM; 295567ba6c4SMuhammad Omair Javaid if (reg == GetRegisterInfo().GetRegNumFPSR()) { 296567ba6c4SMuhammad Omair Javaid sve_reg_num = reg; 297567ba6c4SMuhammad Omair Javaid if (m_sve_state == SVEState::Full) 298567ba6c4SMuhammad Omair Javaid offset = SVE_PT_SVE_FPSR_OFFSET(sve_vq_from_vl(m_sve_header.vl)); 299567ba6c4SMuhammad Omair Javaid else if (m_sve_state == SVEState::FPSIMD) 300567ba6c4SMuhammad Omair Javaid offset = SVE_PT_FPSIMD_OFFSET + (32 * 16); 301567ba6c4SMuhammad Omair Javaid } else if (reg == GetRegisterInfo().GetRegNumFPCR()) { 302567ba6c4SMuhammad Omair Javaid sve_reg_num = reg; 303567ba6c4SMuhammad Omair Javaid if (m_sve_state == SVEState::Full) 304567ba6c4SMuhammad Omair Javaid offset = SVE_PT_SVE_FPCR_OFFSET(sve_vq_from_vl(m_sve_header.vl)); 305567ba6c4SMuhammad Omair Javaid else if (m_sve_state == SVEState::FPSIMD) 306567ba6c4SMuhammad Omair Javaid offset = SVE_PT_FPSIMD_OFFSET + (32 * 16) + 4; 307567ba6c4SMuhammad Omair Javaid } else { 308567ba6c4SMuhammad Omair Javaid // Extract SVE Z register value register number for this reg_info 309567ba6c4SMuhammad Omair Javaid if (reg_info->value_regs && 310567ba6c4SMuhammad Omair Javaid reg_info->value_regs[0] != LLDB_INVALID_REGNUM) 311567ba6c4SMuhammad Omair Javaid sve_reg_num = reg_info->value_regs[0]; 312567ba6c4SMuhammad Omair Javaid offset = CalculateSVEOffset(GetRegisterInfoAtIndex(sve_reg_num)); 313b6f9d7b8SMuhammad Omair Javaid } 314b6f9d7b8SMuhammad Omair Javaid 315567ba6c4SMuhammad Omair Javaid assert(offset < GetSVEBufferSize()); 316567ba6c4SMuhammad Omair Javaid dst = (uint8_t *)GetSVEBuffer() + offset; 317567ba6c4SMuhammad Omair Javaid ::memcpy(dst, reg_value.GetBytes(), reg_info->byte_size); 318567ba6c4SMuhammad Omair Javaid return WriteAllSVE(); 319567ba6c4SMuhammad Omair Javaid } 320567ba6c4SMuhammad Omair Javaid } else if (IsSVE(reg)) { 321567ba6c4SMuhammad Omair Javaid if (m_sve_state == SVEState::Disabled || m_sve_state == SVEState::Unknown) 322567ba6c4SMuhammad Omair Javaid return Status("SVE disabled or not supported"); 323567ba6c4SMuhammad Omair Javaid else { 324567ba6c4SMuhammad Omair Javaid // Target has SVE enabled, we will read and cache SVE ptrace data 325567ba6c4SMuhammad Omair Javaid error = ReadAllSVE(); 326567ba6c4SMuhammad Omair Javaid if (error.Fail()) 327b6f9d7b8SMuhammad Omair Javaid return error; 328567ba6c4SMuhammad Omair Javaid 329e448ad78SMuhammad Omair Javaid if (GetRegisterInfo().IsSVERegVG(reg)) { 330e448ad78SMuhammad Omair Javaid uint64_t vg_value = reg_value.GetAsUInt64(); 331e448ad78SMuhammad Omair Javaid 332e448ad78SMuhammad Omair Javaid if (sve_vl_valid(vg_value * 8)) { 333e448ad78SMuhammad Omair Javaid if (m_sve_header_is_valid && vg_value == GetSVERegVG()) 334e448ad78SMuhammad Omair Javaid return error; 335e448ad78SMuhammad Omair Javaid 336e448ad78SMuhammad Omair Javaid SetSVERegVG(vg_value); 337e448ad78SMuhammad Omair Javaid 338e448ad78SMuhammad Omair Javaid error = WriteSVEHeader(); 339e448ad78SMuhammad Omair Javaid if (error.Success()) 340e448ad78SMuhammad Omair Javaid ConfigureRegisterContext(); 341e448ad78SMuhammad Omair Javaid 342e448ad78SMuhammad Omair Javaid if (m_sve_header_is_valid && vg_value == GetSVERegVG()) 343e448ad78SMuhammad Omair Javaid return error; 344e448ad78SMuhammad Omair Javaid } 345e448ad78SMuhammad Omair Javaid 346e448ad78SMuhammad Omair Javaid return Status("SVE vector length update failed."); 347e448ad78SMuhammad Omair Javaid } 348e448ad78SMuhammad Omair Javaid 349567ba6c4SMuhammad Omair Javaid // If target supports SVE but currently in FPSIMD mode. 350567ba6c4SMuhammad Omair Javaid if (m_sve_state == SVEState::FPSIMD) { 351567ba6c4SMuhammad Omair Javaid // Here we will check if writing this SVE register enables 352567ba6c4SMuhammad Omair Javaid // SVEState::Full 353567ba6c4SMuhammad Omair Javaid bool set_sve_state_full = false; 354567ba6c4SMuhammad Omair Javaid const uint8_t *reg_bytes = (const uint8_t *)reg_value.GetBytes(); 355567ba6c4SMuhammad Omair Javaid if (GetRegisterInfo().IsSVEZReg(reg)) { 356567ba6c4SMuhammad Omair Javaid for (uint32_t i = 16; i < reg_info->byte_size; i++) { 357567ba6c4SMuhammad Omair Javaid if (reg_bytes[i]) { 358567ba6c4SMuhammad Omair Javaid set_sve_state_full = true; 359567ba6c4SMuhammad Omair Javaid break; 360567ba6c4SMuhammad Omair Javaid } 361567ba6c4SMuhammad Omair Javaid } 362567ba6c4SMuhammad Omair Javaid } else if (GetRegisterInfo().IsSVEPReg(reg) || 363567ba6c4SMuhammad Omair Javaid reg == GetRegisterInfo().GetRegNumSVEFFR()) { 364567ba6c4SMuhammad Omair Javaid for (uint32_t i = 0; i < reg_info->byte_size; i++) { 365567ba6c4SMuhammad Omair Javaid if (reg_bytes[i]) { 366567ba6c4SMuhammad Omair Javaid set_sve_state_full = true; 367567ba6c4SMuhammad Omair Javaid break; 368567ba6c4SMuhammad Omair Javaid } 369567ba6c4SMuhammad Omair Javaid } 370567ba6c4SMuhammad Omair Javaid } 371567ba6c4SMuhammad Omair Javaid 372567ba6c4SMuhammad Omair Javaid if (!set_sve_state_full && GetRegisterInfo().IsSVEZReg(reg)) { 373567ba6c4SMuhammad Omair Javaid // We are writing a Z register which is zero beyond 16 bytes so copy 374567ba6c4SMuhammad Omair Javaid // first 16 bytes only as SVE payload mirrors legacy fpsimd structure 375567ba6c4SMuhammad Omair Javaid offset = CalculateSVEOffset(reg_info); 376567ba6c4SMuhammad Omair Javaid assert(offset < GetSVEBufferSize()); 377567ba6c4SMuhammad Omair Javaid dst = (uint8_t *)GetSVEBuffer() + offset; 378567ba6c4SMuhammad Omair Javaid ::memcpy(dst, reg_value.GetBytes(), 16); 379567ba6c4SMuhammad Omair Javaid 380567ba6c4SMuhammad Omair Javaid return WriteAllSVE(); 381567ba6c4SMuhammad Omair Javaid } else 382567ba6c4SMuhammad Omair Javaid return Status("SVE state change operation not supported"); 383567ba6c4SMuhammad Omair Javaid } else { 384567ba6c4SMuhammad Omair Javaid offset = CalculateSVEOffset(reg_info); 385567ba6c4SMuhammad Omair Javaid assert(offset < GetSVEBufferSize()); 386567ba6c4SMuhammad Omair Javaid dst = (uint8_t *)GetSVEBuffer() + offset; 387567ba6c4SMuhammad Omair Javaid ::memcpy(dst, reg_value.GetBytes(), reg_info->byte_size); 388567ba6c4SMuhammad Omair Javaid return WriteAllSVE(); 389567ba6c4SMuhammad Omair Javaid } 390567ba6c4SMuhammad Omair Javaid } 391567ba6c4SMuhammad Omair Javaid } 392567ba6c4SMuhammad Omair Javaid 393567ba6c4SMuhammad Omair Javaid return Status("Failed to write register value"); 3941e209fccSTamas Berghammer } 3951e209fccSTamas Berghammer 39697206d57SZachary Turner Status NativeRegisterContextLinux_arm64::ReadAllRegisterValues( 397b9c1b51eSKate Stone lldb::DataBufferSP &data_sp) { 39897206d57SZachary Turner Status error; 3991e209fccSTamas Berghammer 400db264a6dSTamas Berghammer data_sp.reset(new DataBufferHeap(REG_CONTEXT_SIZE, 0)); 401567ba6c4SMuhammad Omair Javaid 402068f8a7eSTamas Berghammer error = ReadGPR(); 403068f8a7eSTamas Berghammer if (error.Fail()) 4041e209fccSTamas Berghammer return error; 4051e209fccSTamas Berghammer 406068f8a7eSTamas Berghammer error = ReadFPR(); 407068f8a7eSTamas Berghammer if (error.Fail()) 4081e209fccSTamas Berghammer return error; 409567ba6c4SMuhammad Omair Javaid 4101e209fccSTamas Berghammer uint8_t *dst = data_sp->GetBytes(); 411b6f9d7b8SMuhammad Omair Javaid ::memcpy(dst, GetGPRBuffer(), GetGPRSize()); 4121e209fccSTamas Berghammer dst += GetGPRSize(); 413b6f9d7b8SMuhammad Omair Javaid ::memcpy(dst, GetFPRBuffer(), GetFPRSize()); 4141e209fccSTamas Berghammer 4151e209fccSTamas Berghammer return error; 4161e209fccSTamas Berghammer } 4171e209fccSTamas Berghammer 41897206d57SZachary Turner Status NativeRegisterContextLinux_arm64::WriteAllRegisterValues( 419b9c1b51eSKate Stone const lldb::DataBufferSP &data_sp) { 42097206d57SZachary Turner Status error; 4211e209fccSTamas Berghammer 422b9c1b51eSKate Stone if (!data_sp) { 423b9c1b51eSKate Stone error.SetErrorStringWithFormat( 424b9c1b51eSKate Stone "NativeRegisterContextLinux_x86_64::%s invalid data_sp provided", 425b9c1b51eSKate Stone __FUNCTION__); 4261e209fccSTamas Berghammer return error; 4271e209fccSTamas Berghammer } 4281e209fccSTamas Berghammer 429b9c1b51eSKate Stone if (data_sp->GetByteSize() != REG_CONTEXT_SIZE) { 430b9c1b51eSKate Stone error.SetErrorStringWithFormat( 431b9c1b51eSKate Stone "NativeRegisterContextLinux_x86_64::%s data_sp contained mismatched " 432b9c1b51eSKate Stone "data size, expected %" PRIu64 ", actual %" PRIu64, 433b9c1b51eSKate Stone __FUNCTION__, REG_CONTEXT_SIZE, data_sp->GetByteSize()); 4341e209fccSTamas Berghammer return error; 4351e209fccSTamas Berghammer } 4361e209fccSTamas Berghammer 4371e209fccSTamas Berghammer uint8_t *src = data_sp->GetBytes(); 438b9c1b51eSKate Stone if (src == nullptr) { 439b9c1b51eSKate Stone error.SetErrorStringWithFormat("NativeRegisterContextLinux_x86_64::%s " 440b9c1b51eSKate Stone "DataBuffer::GetBytes() returned a null " 441b9c1b51eSKate Stone "pointer", 442b9c1b51eSKate Stone __FUNCTION__); 4431e209fccSTamas Berghammer return error; 4441e209fccSTamas Berghammer } 445b6f9d7b8SMuhammad Omair Javaid ::memcpy(GetGPRBuffer(), src, GetRegisterInfoInterface().GetGPRSize()); 4461e209fccSTamas Berghammer 447068f8a7eSTamas Berghammer error = WriteGPR(); 448068f8a7eSTamas Berghammer if (error.Fail()) 4491e209fccSTamas Berghammer return error; 4501e209fccSTamas Berghammer 4511e209fccSTamas Berghammer src += GetRegisterInfoInterface().GetGPRSize(); 452b6f9d7b8SMuhammad Omair Javaid ::memcpy(GetFPRBuffer(), src, GetFPRSize()); 4531e209fccSTamas Berghammer 454068f8a7eSTamas Berghammer error = WriteFPR(); 4551e209fccSTamas Berghammer if (error.Fail()) 4561e209fccSTamas Berghammer return error; 4571e209fccSTamas Berghammer 4581e209fccSTamas Berghammer return error; 4591e209fccSTamas Berghammer } 4601e209fccSTamas Berghammer 461b9c1b51eSKate Stone bool NativeRegisterContextLinux_arm64::IsGPR(unsigned reg) const { 4627fa7b81bSMuhammad Omair Javaid if (GetRegisterInfo().GetRegisterSetFromRegisterIndex(reg) == 4637fa7b81bSMuhammad Omair Javaid RegisterInfoPOSIX_arm64::GPRegSet) 4647fa7b81bSMuhammad Omair Javaid return true; 4657fa7b81bSMuhammad Omair Javaid return false; 4661e209fccSTamas Berghammer } 4671e209fccSTamas Berghammer 468b9c1b51eSKate Stone bool NativeRegisterContextLinux_arm64::IsFPR(unsigned reg) const { 4697fa7b81bSMuhammad Omair Javaid if (GetRegisterInfo().GetRegisterSetFromRegisterIndex(reg) == 4707fa7b81bSMuhammad Omair Javaid RegisterInfoPOSIX_arm64::FPRegSet) 4717fa7b81bSMuhammad Omair Javaid return true; 4727fa7b81bSMuhammad Omair Javaid return false; 4731e209fccSTamas Berghammer } 4741e209fccSTamas Berghammer 475567ba6c4SMuhammad Omair Javaid bool NativeRegisterContextLinux_arm64::IsSVE(unsigned reg) const { 476d6d3d21cSMuhammad Omair Javaid return GetRegisterInfo().IsSVEReg(reg); 477567ba6c4SMuhammad Omair Javaid } 478567ba6c4SMuhammad Omair Javaid 479771c4c9cSMichał Górny llvm::Error NativeRegisterContextLinux_arm64::ReadHardwareDebugInfo() { 480b9c1b51eSKate Stone if (!m_refresh_hwdebug_info) { 481771c4c9cSMichał Górny return llvm::Error::success(); 4821fd2a8cfSOmair Javaid } 4831fd2a8cfSOmair Javaid 484c7512fdcSPavel Labath ::pid_t tid = m_thread.GetID(); 485ea8c25a8SOmair Javaid 486c7512fdcSPavel Labath int regset = NT_ARM_HW_WATCH; 487c7512fdcSPavel Labath struct iovec ioVec; 488c7512fdcSPavel Labath struct user_hwdebug_state dreg_state; 48997206d57SZachary Turner Status error; 490c7512fdcSPavel Labath 491c7512fdcSPavel Labath ioVec.iov_base = &dreg_state; 492c7512fdcSPavel Labath ioVec.iov_len = sizeof(dreg_state); 493b9c1b51eSKate Stone error = NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, tid, ®set, 494b9c1b51eSKate Stone &ioVec, ioVec.iov_len); 4953a56363aSOmair Javaid 4963a56363aSOmair Javaid if (error.Fail()) 497771c4c9cSMichał Górny return error.ToError(); 4983a56363aSOmair Javaid 4991fd2a8cfSOmair Javaid m_max_hwp_supported = dreg_state.dbg_info & 0xff; 500c7512fdcSPavel Labath 501c7512fdcSPavel Labath regset = NT_ARM_HW_BREAK; 502b9c1b51eSKate Stone error = NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, tid, ®set, 503b9c1b51eSKate Stone &ioVec, ioVec.iov_len); 5041fd2a8cfSOmair Javaid 5053a56363aSOmair Javaid if (error.Fail()) 506771c4c9cSMichał Górny return error.ToError(); 5073a56363aSOmair Javaid 5083a56363aSOmair Javaid m_max_hbp_supported = dreg_state.dbg_info & 0xff; 5091fd2a8cfSOmair Javaid m_refresh_hwdebug_info = false; 510c7512fdcSPavel Labath 511771c4c9cSMichał Górny return llvm::Error::success(); 512ea8c25a8SOmair Javaid } 513068f8a7eSTamas Berghammer 514771c4c9cSMichał Górny llvm::Error 515771c4c9cSMichał Górny NativeRegisterContextLinux_arm64::WriteHardwareDebugRegs(DREGType hwbType) { 516c7512fdcSPavel Labath struct iovec ioVec; 517c7512fdcSPavel Labath struct user_hwdebug_state dreg_state; 518771c4c9cSMichał Górny int regset; 519c7512fdcSPavel Labath 520c7512fdcSPavel Labath memset(&dreg_state, 0, sizeof(dreg_state)); 521c7512fdcSPavel Labath ioVec.iov_base = &dreg_state; 522c7512fdcSPavel Labath 523771c4c9cSMichał Górny switch (hwbType) { 524771c4c9cSMichał Górny case eDREGTypeWATCH: 525771c4c9cSMichał Górny regset = NT_ARM_HW_WATCH; 526b9c1b51eSKate Stone ioVec.iov_len = sizeof(dreg_state.dbg_info) + sizeof(dreg_state.pad) + 527b9c1b51eSKate Stone (sizeof(dreg_state.dbg_regs[0]) * m_max_hwp_supported); 5281fd2a8cfSOmair Javaid 529b9c1b51eSKate Stone for (uint32_t i = 0; i < m_max_hwp_supported; i++) { 5301fd2a8cfSOmair Javaid dreg_state.dbg_regs[i].addr = m_hwp_regs[i].address; 5311fd2a8cfSOmair Javaid dreg_state.dbg_regs[i].ctrl = m_hwp_regs[i].control; 5321fd2a8cfSOmair Javaid } 533771c4c9cSMichał Górny break; 534771c4c9cSMichał Górny case eDREGTypeBREAK: 535771c4c9cSMichał Górny regset = NT_ARM_HW_BREAK; 536b9c1b51eSKate Stone ioVec.iov_len = sizeof(dreg_state.dbg_info) + sizeof(dreg_state.pad) + 537b9c1b51eSKate Stone (sizeof(dreg_state.dbg_regs[0]) * m_max_hbp_supported); 5381fd2a8cfSOmair Javaid 539b9c1b51eSKate Stone for (uint32_t i = 0; i < m_max_hbp_supported; i++) { 540771c4c9cSMichał Górny dreg_state.dbg_regs[i].addr = m_hbp_regs[i].address; 541771c4c9cSMichał Górny dreg_state.dbg_regs[i].ctrl = m_hbp_regs[i].control; 5421fd2a8cfSOmair Javaid } 543771c4c9cSMichał Górny break; 544068f8a7eSTamas Berghammer } 545068f8a7eSTamas Berghammer 546b9c1b51eSKate Stone return NativeProcessLinux::PtraceWrapper(PTRACE_SETREGSET, m_thread.GetID(), 547771c4c9cSMichał Górny ®set, &ioVec, ioVec.iov_len) 548771c4c9cSMichał Górny .ToError(); 549c7512fdcSPavel Labath } 550c7512fdcSPavel Labath 5513f3673eaSPavel Labath Status NativeRegisterContextLinux_arm64::ReadGPR() { 552b6f9d7b8SMuhammad Omair Javaid Status error; 553b6f9d7b8SMuhammad Omair Javaid 554567ba6c4SMuhammad Omair Javaid if (m_gpr_is_valid) 555567ba6c4SMuhammad Omair Javaid return error; 556b6f9d7b8SMuhammad Omair Javaid 557567ba6c4SMuhammad Omair Javaid struct iovec ioVec; 5583f3673eaSPavel Labath ioVec.iov_base = GetGPRBuffer(); 55926b8ea2eSMuhammad Omair Javaid ioVec.iov_len = GetGPRBufferSize(); 560b6f9d7b8SMuhammad Omair Javaid 56126b8ea2eSMuhammad Omair Javaid error = ReadRegisterSet(&ioVec, GetGPRBufferSize(), NT_PRSTATUS); 562b6f9d7b8SMuhammad Omair Javaid 563b6f9d7b8SMuhammad Omair Javaid if (error.Success()) 564b6f9d7b8SMuhammad Omair Javaid m_gpr_is_valid = true; 565b6f9d7b8SMuhammad Omair Javaid 566b6f9d7b8SMuhammad Omair Javaid return error; 567068f8a7eSTamas Berghammer } 568068f8a7eSTamas Berghammer 5693f3673eaSPavel Labath Status NativeRegisterContextLinux_arm64::WriteGPR() { 570567ba6c4SMuhammad Omair Javaid Status error = ReadGPR(); 571567ba6c4SMuhammad Omair Javaid if (error.Fail()) 572567ba6c4SMuhammad Omair Javaid return error; 573567ba6c4SMuhammad Omair Javaid 574c7512fdcSPavel Labath struct iovec ioVec; 5753f3673eaSPavel Labath ioVec.iov_base = GetGPRBuffer(); 57626b8ea2eSMuhammad Omair Javaid ioVec.iov_len = GetGPRBufferSize(); 577b6f9d7b8SMuhammad Omair Javaid 578567ba6c4SMuhammad Omair Javaid m_gpr_is_valid = false; 579567ba6c4SMuhammad Omair Javaid 58026b8ea2eSMuhammad Omair Javaid return WriteRegisterSet(&ioVec, GetGPRBufferSize(), NT_PRSTATUS); 581068f8a7eSTamas Berghammer } 582068f8a7eSTamas Berghammer 5833f3673eaSPavel Labath Status NativeRegisterContextLinux_arm64::ReadFPR() { 584b6f9d7b8SMuhammad Omair Javaid Status error; 585b6f9d7b8SMuhammad Omair Javaid 586567ba6c4SMuhammad Omair Javaid if (m_fpu_is_valid) 587567ba6c4SMuhammad Omair Javaid return error; 588b6f9d7b8SMuhammad Omair Javaid 589567ba6c4SMuhammad Omair Javaid struct iovec ioVec; 5903f3673eaSPavel Labath ioVec.iov_base = GetFPRBuffer(); 5913f3673eaSPavel Labath ioVec.iov_len = GetFPRSize(); 592b6f9d7b8SMuhammad Omair Javaid 593b6f9d7b8SMuhammad Omair Javaid error = ReadRegisterSet(&ioVec, GetFPRSize(), NT_FPREGSET); 594b6f9d7b8SMuhammad Omair Javaid 595b6f9d7b8SMuhammad Omair Javaid if (error.Success()) 596b6f9d7b8SMuhammad Omair Javaid m_fpu_is_valid = true; 597b6f9d7b8SMuhammad Omair Javaid 598b6f9d7b8SMuhammad Omair Javaid return error; 599068f8a7eSTamas Berghammer } 600068f8a7eSTamas Berghammer 6013f3673eaSPavel Labath Status NativeRegisterContextLinux_arm64::WriteFPR() { 602567ba6c4SMuhammad Omair Javaid Status error = ReadFPR(); 603567ba6c4SMuhammad Omair Javaid if (error.Fail()) 604567ba6c4SMuhammad Omair Javaid return error; 605567ba6c4SMuhammad Omair Javaid 606c7512fdcSPavel Labath struct iovec ioVec; 6073f3673eaSPavel Labath ioVec.iov_base = GetFPRBuffer(); 6083f3673eaSPavel Labath ioVec.iov_len = GetFPRSize(); 609b6f9d7b8SMuhammad Omair Javaid 610567ba6c4SMuhammad Omair Javaid m_fpu_is_valid = false; 611567ba6c4SMuhammad Omair Javaid 6123f3673eaSPavel Labath return WriteRegisterSet(&ioVec, GetFPRSize(), NT_FPREGSET); 613068f8a7eSTamas Berghammer } 614068f8a7eSTamas Berghammer 615b6f9d7b8SMuhammad Omair Javaid void NativeRegisterContextLinux_arm64::InvalidateAllRegisters() { 616b6f9d7b8SMuhammad Omair Javaid m_gpr_is_valid = false; 617b6f9d7b8SMuhammad Omair Javaid m_fpu_is_valid = false; 618567ba6c4SMuhammad Omair Javaid m_sve_buffer_is_valid = false; 619567ba6c4SMuhammad Omair Javaid m_sve_header_is_valid = false; 620567ba6c4SMuhammad Omair Javaid 621567ba6c4SMuhammad Omair Javaid // Update SVE registers in case there is change in configuration. 622567ba6c4SMuhammad Omair Javaid ConfigureRegisterContext(); 623567ba6c4SMuhammad Omair Javaid } 624567ba6c4SMuhammad Omair Javaid 625567ba6c4SMuhammad Omair Javaid Status NativeRegisterContextLinux_arm64::ReadSVEHeader() { 626567ba6c4SMuhammad Omair Javaid Status error; 627567ba6c4SMuhammad Omair Javaid 628567ba6c4SMuhammad Omair Javaid if (m_sve_header_is_valid) 629567ba6c4SMuhammad Omair Javaid return error; 630567ba6c4SMuhammad Omair Javaid 631567ba6c4SMuhammad Omair Javaid struct iovec ioVec; 632567ba6c4SMuhammad Omair Javaid ioVec.iov_base = GetSVEHeader(); 633567ba6c4SMuhammad Omair Javaid ioVec.iov_len = GetSVEHeaderSize(); 634567ba6c4SMuhammad Omair Javaid 635567ba6c4SMuhammad Omair Javaid error = ReadRegisterSet(&ioVec, GetSVEHeaderSize(), NT_ARM_SVE); 636567ba6c4SMuhammad Omair Javaid 637567ba6c4SMuhammad Omair Javaid m_sve_header_is_valid = true; 638567ba6c4SMuhammad Omair Javaid 639567ba6c4SMuhammad Omair Javaid return error; 640567ba6c4SMuhammad Omair Javaid } 641567ba6c4SMuhammad Omair Javaid 642567ba6c4SMuhammad Omair Javaid Status NativeRegisterContextLinux_arm64::WriteSVEHeader() { 643567ba6c4SMuhammad Omair Javaid Status error; 644567ba6c4SMuhammad Omair Javaid 645567ba6c4SMuhammad Omair Javaid error = ReadSVEHeader(); 646567ba6c4SMuhammad Omair Javaid if (error.Fail()) 647567ba6c4SMuhammad Omair Javaid return error; 648567ba6c4SMuhammad Omair Javaid 649567ba6c4SMuhammad Omair Javaid struct iovec ioVec; 650567ba6c4SMuhammad Omair Javaid ioVec.iov_base = GetSVEHeader(); 651567ba6c4SMuhammad Omair Javaid ioVec.iov_len = GetSVEHeaderSize(); 652567ba6c4SMuhammad Omair Javaid 653567ba6c4SMuhammad Omair Javaid m_sve_buffer_is_valid = false; 654567ba6c4SMuhammad Omair Javaid m_sve_header_is_valid = false; 655567ba6c4SMuhammad Omair Javaid m_fpu_is_valid = false; 656567ba6c4SMuhammad Omair Javaid 657567ba6c4SMuhammad Omair Javaid return WriteRegisterSet(&ioVec, GetSVEHeaderSize(), NT_ARM_SVE); 658567ba6c4SMuhammad Omair Javaid } 659567ba6c4SMuhammad Omair Javaid 660567ba6c4SMuhammad Omair Javaid Status NativeRegisterContextLinux_arm64::ReadAllSVE() { 661567ba6c4SMuhammad Omair Javaid Status error; 662567ba6c4SMuhammad Omair Javaid 663567ba6c4SMuhammad Omair Javaid if (m_sve_buffer_is_valid) 664567ba6c4SMuhammad Omair Javaid return error; 665567ba6c4SMuhammad Omair Javaid 666567ba6c4SMuhammad Omair Javaid struct iovec ioVec; 667567ba6c4SMuhammad Omair Javaid ioVec.iov_base = GetSVEBuffer(); 668567ba6c4SMuhammad Omair Javaid ioVec.iov_len = GetSVEBufferSize(); 669567ba6c4SMuhammad Omair Javaid 670567ba6c4SMuhammad Omair Javaid error = ReadRegisterSet(&ioVec, GetSVEBufferSize(), NT_ARM_SVE); 671567ba6c4SMuhammad Omair Javaid 672567ba6c4SMuhammad Omair Javaid if (error.Success()) 673567ba6c4SMuhammad Omair Javaid m_sve_buffer_is_valid = true; 674567ba6c4SMuhammad Omair Javaid 675567ba6c4SMuhammad Omair Javaid return error; 676567ba6c4SMuhammad Omair Javaid } 677567ba6c4SMuhammad Omair Javaid 678567ba6c4SMuhammad Omair Javaid Status NativeRegisterContextLinux_arm64::WriteAllSVE() { 679567ba6c4SMuhammad Omair Javaid Status error; 680567ba6c4SMuhammad Omair Javaid 681567ba6c4SMuhammad Omair Javaid error = ReadAllSVE(); 682567ba6c4SMuhammad Omair Javaid if (error.Fail()) 683567ba6c4SMuhammad Omair Javaid return error; 684567ba6c4SMuhammad Omair Javaid 685567ba6c4SMuhammad Omair Javaid struct iovec ioVec; 686567ba6c4SMuhammad Omair Javaid 687567ba6c4SMuhammad Omair Javaid ioVec.iov_base = GetSVEBuffer(); 688567ba6c4SMuhammad Omair Javaid ioVec.iov_len = GetSVEBufferSize(); 689567ba6c4SMuhammad Omair Javaid 690567ba6c4SMuhammad Omair Javaid m_sve_buffer_is_valid = false; 691567ba6c4SMuhammad Omair Javaid m_sve_header_is_valid = false; 692567ba6c4SMuhammad Omair Javaid m_fpu_is_valid = false; 693567ba6c4SMuhammad Omair Javaid 694567ba6c4SMuhammad Omair Javaid return WriteRegisterSet(&ioVec, GetSVEBufferSize(), NT_ARM_SVE); 695567ba6c4SMuhammad Omair Javaid } 696567ba6c4SMuhammad Omair Javaid 697567ba6c4SMuhammad Omair Javaid void NativeRegisterContextLinux_arm64::ConfigureRegisterContext() { 698d6d3d21cSMuhammad Omair Javaid // ConfigureRegisterContext gets called from InvalidateAllRegisters 699d6d3d21cSMuhammad Omair Javaid // on every stop and configures SVE vector length. 700d6d3d21cSMuhammad Omair Javaid // If m_sve_state is set to SVEState::Disabled on first stop, code below will 701d6d3d21cSMuhammad Omair Javaid // be deemed non operational for the lifetime of current process. 702567ba6c4SMuhammad Omair Javaid if (!m_sve_header_is_valid && m_sve_state != SVEState::Disabled) { 703567ba6c4SMuhammad Omair Javaid Status error = ReadSVEHeader(); 704d6d3d21cSMuhammad Omair Javaid if (error.Success()) { 705d6d3d21cSMuhammad Omair Javaid // If SVE is enabled thread can switch between SVEState::FPSIMD and 706d6d3d21cSMuhammad Omair Javaid // SVEState::Full on every stop. 707567ba6c4SMuhammad Omair Javaid if ((m_sve_header.flags & SVE_PT_REGS_MASK) == SVE_PT_REGS_FPSIMD) 708567ba6c4SMuhammad Omair Javaid m_sve_state = SVEState::FPSIMD; 709567ba6c4SMuhammad Omair Javaid else if ((m_sve_header.flags & SVE_PT_REGS_MASK) == SVE_PT_REGS_SVE) 710567ba6c4SMuhammad Omair Javaid m_sve_state = SVEState::Full; 711567ba6c4SMuhammad Omair Javaid 712d6d3d21cSMuhammad Omair Javaid // On every stop we configure SVE vector length by calling 713d6d3d21cSMuhammad Omair Javaid // ConfigureVectorLength regardless of current SVEState of this thread. 714567ba6c4SMuhammad Omair Javaid uint32_t vq = RegisterInfoPOSIX_arm64::eVectorQuadwordAArch64SVE; 715567ba6c4SMuhammad Omair Javaid if (sve_vl_valid(m_sve_header.vl)) 716567ba6c4SMuhammad Omair Javaid vq = sve_vq_from_vl(m_sve_header.vl); 717d6d3d21cSMuhammad Omair Javaid 718d6d3d21cSMuhammad Omair Javaid GetRegisterInfo().ConfigureVectorLength(vq); 719567ba6c4SMuhammad Omair Javaid m_sve_ptrace_payload.resize(SVE_PT_SIZE(vq, SVE_PT_REGS_SVE)); 720567ba6c4SMuhammad Omair Javaid } 721567ba6c4SMuhammad Omair Javaid } 722b6f9d7b8SMuhammad Omair Javaid } 723b6f9d7b8SMuhammad Omair Javaid 724b9c1b51eSKate Stone uint32_t NativeRegisterContextLinux_arm64::CalculateFprOffset( 725b9c1b51eSKate Stone const RegisterInfo *reg_info) const { 7267fa7b81bSMuhammad Omair Javaid return reg_info->byte_offset - GetGPRSize(); 727c40e7b17STamas Berghammer } 728c40e7b17STamas Berghammer 729567ba6c4SMuhammad Omair Javaid uint32_t NativeRegisterContextLinux_arm64::CalculateSVEOffset( 730567ba6c4SMuhammad Omair Javaid const RegisterInfo *reg_info) const { 731567ba6c4SMuhammad Omair Javaid // Start of Z0 data is after GPRs plus 8 bytes of vg register 732567ba6c4SMuhammad Omair Javaid uint32_t sve_reg_offset = LLDB_INVALID_INDEX32; 733567ba6c4SMuhammad Omair Javaid if (m_sve_state == SVEState::FPSIMD) { 734567ba6c4SMuhammad Omair Javaid const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; 735567ba6c4SMuhammad Omair Javaid sve_reg_offset = 736567ba6c4SMuhammad Omair Javaid SVE_PT_FPSIMD_OFFSET + (reg - GetRegisterInfo().GetRegNumSVEZ0()) * 16; 737567ba6c4SMuhammad Omair Javaid } else if (m_sve_state == SVEState::Full) { 738661e4040SMuhammad Omair Javaid uint32_t sve_z0_offset = GetGPRSize() + 16; 739567ba6c4SMuhammad Omair Javaid sve_reg_offset = 740567ba6c4SMuhammad Omair Javaid SVE_SIG_REGS_OFFSET + reg_info->byte_offset - sve_z0_offset; 741567ba6c4SMuhammad Omair Javaid } 742567ba6c4SMuhammad Omair Javaid return sve_reg_offset; 743567ba6c4SMuhammad Omair Javaid } 744567ba6c4SMuhammad Omair Javaid 745567ba6c4SMuhammad Omair Javaid void *NativeRegisterContextLinux_arm64::GetSVEBuffer() { 746567ba6c4SMuhammad Omair Javaid if (m_sve_state == SVEState::FPSIMD) 747567ba6c4SMuhammad Omair Javaid return m_sve_ptrace_payload.data() + SVE_PT_FPSIMD_OFFSET; 748567ba6c4SMuhammad Omair Javaid 749567ba6c4SMuhammad Omair Javaid return m_sve_ptrace_payload.data(); 750567ba6c4SMuhammad Omair Javaid } 751567ba6c4SMuhammad Omair Javaid 7524e8aeb97SMuhammad Omair Javaid std::vector<uint32_t> NativeRegisterContextLinux_arm64::GetExpeditedRegisters( 7534e8aeb97SMuhammad Omair Javaid ExpeditedRegs expType) const { 7544e8aeb97SMuhammad Omair Javaid std::vector<uint32_t> expedited_reg_nums = 7554e8aeb97SMuhammad Omair Javaid NativeRegisterContext::GetExpeditedRegisters(expType); 7564e8aeb97SMuhammad Omair Javaid if (m_sve_state == SVEState::FPSIMD || m_sve_state == SVEState::Full) 7574e8aeb97SMuhammad Omair Javaid expedited_reg_nums.push_back(GetRegisterInfo().GetRegNumSVEVG()); 7584e8aeb97SMuhammad Omair Javaid 7594e8aeb97SMuhammad Omair Javaid return expedited_reg_nums; 7604e8aeb97SMuhammad Omair Javaid } 7614e8aeb97SMuhammad Omair Javaid 762068f8a7eSTamas Berghammer #endif // defined (__arm64__) || defined (__aarch64__) 763