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( 44d37349f3SPavel Labath const ArchSpec &target_arch, NativeThreadProtocol &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); 49e85e6021STamas Berghammer case llvm::Triple::aarch64: 50a8f3ae7cSJonas Devlieghere return std::make_unique<NativeRegisterContextLinux_arm64>(target_arch, 51d37349f3SPavel Labath native_thread); 52e85e6021STamas Berghammer default: 53ea1b6b17SPavel Labath llvm_unreachable("have no register context for architecture"); 54e85e6021STamas Berghammer } 55068f8a7eSTamas Berghammer } 56068f8a7eSTamas Berghammer 57b9c1b51eSKate Stone NativeRegisterContextLinux_arm64::NativeRegisterContextLinux_arm64( 58d37349f3SPavel Labath const ArchSpec &target_arch, NativeThreadProtocol &native_thread) 59f5ca2756SMichał Górny : NativeRegisterContextRegisterInfo( 60f5ca2756SMichał Górny native_thread, new RegisterInfoPOSIX_arm64(target_arch)) { 611e209fccSTamas Berghammer ::memset(&m_fpr, 0, sizeof(m_fpr)); 621e209fccSTamas Berghammer ::memset(&m_gpr_arm64, 0, sizeof(m_gpr_arm64)); 63ea8c25a8SOmair Javaid ::memset(&m_hwp_regs, 0, sizeof(m_hwp_regs)); 64*771c4c9cSMichał Górny ::memset(&m_hbp_regs, 0, sizeof(m_hbp_regs)); 65567ba6c4SMuhammad Omair Javaid ::memset(&m_sve_header, 0, sizeof(m_sve_header)); 66ea8c25a8SOmair Javaid 67ea8c25a8SOmair Javaid // 16 is just a maximum value, query hardware for actual watchpoint count 68ea8c25a8SOmair Javaid m_max_hwp_supported = 16; 69ea8c25a8SOmair Javaid m_max_hbp_supported = 16; 70567ba6c4SMuhammad Omair Javaid 71ea8c25a8SOmair Javaid m_refresh_hwdebug_info = true; 72b6f9d7b8SMuhammad Omair Javaid 73b6f9d7b8SMuhammad Omair Javaid m_gpr_is_valid = false; 74b6f9d7b8SMuhammad Omair Javaid m_fpu_is_valid = false; 75567ba6c4SMuhammad Omair Javaid m_sve_buffer_is_valid = false; 76567ba6c4SMuhammad Omair Javaid m_sve_header_is_valid = false; 77567ba6c4SMuhammad Omair Javaid 78567ba6c4SMuhammad Omair Javaid // SVE is not enabled until we query user_sve_header 79567ba6c4SMuhammad Omair Javaid m_sve_state = SVEState::Unknown; 801e209fccSTamas Berghammer } 811e209fccSTamas Berghammer 827fa7b81bSMuhammad Omair Javaid RegisterInfoPOSIX_arm64 & 837fa7b81bSMuhammad Omair Javaid NativeRegisterContextLinux_arm64::GetRegisterInfo() const { 847fa7b81bSMuhammad Omair Javaid return static_cast<RegisterInfoPOSIX_arm64 &>(*m_register_info_interface_up); 857fa7b81bSMuhammad Omair Javaid } 867fa7b81bSMuhammad Omair Javaid 87b9c1b51eSKate Stone uint32_t NativeRegisterContextLinux_arm64::GetRegisterSetCount() const { 887fa7b81bSMuhammad Omair Javaid return GetRegisterInfo().GetRegisterSetCount(); 891e209fccSTamas Berghammer } 901e209fccSTamas Berghammer 91db264a6dSTamas Berghammer const RegisterSet * 92b9c1b51eSKate Stone NativeRegisterContextLinux_arm64::GetRegisterSet(uint32_t set_index) const { 937fa7b81bSMuhammad Omair Javaid return GetRegisterInfo().GetRegisterSet(set_index); 941e209fccSTamas Berghammer } 951e209fccSTamas Berghammer 96b9c1b51eSKate Stone uint32_t NativeRegisterContextLinux_arm64::GetUserRegisterCount() const { 97cec93c35STamas Berghammer uint32_t count = 0; 987fa7b81bSMuhammad Omair Javaid for (uint32_t set_index = 0; set_index < GetRegisterSetCount(); ++set_index) 997fa7b81bSMuhammad Omair Javaid count += GetRegisterSet(set_index)->num_registers; 100cec93c35STamas Berghammer return count; 101cec93c35STamas Berghammer } 102cec93c35STamas Berghammer 10397206d57SZachary Turner Status 10497206d57SZachary Turner NativeRegisterContextLinux_arm64::ReadRegister(const RegisterInfo *reg_info, 10597206d57SZachary Turner RegisterValue ®_value) { 10697206d57SZachary Turner Status error; 1071e209fccSTamas Berghammer 108b9c1b51eSKate Stone if (!reg_info) { 1091e209fccSTamas Berghammer error.SetErrorString("reg_info NULL"); 1101e209fccSTamas Berghammer return error; 1111e209fccSTamas Berghammer } 1121e209fccSTamas Berghammer 1131e209fccSTamas Berghammer const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; 1141e209fccSTamas Berghammer 115b6f9d7b8SMuhammad Omair Javaid if (reg == LLDB_INVALID_REGNUM) 116b6f9d7b8SMuhammad Omair Javaid return Status("no lldb regnum for %s", reg_info && reg_info->name 117b6f9d7b8SMuhammad Omair Javaid ? reg_info->name 118b6f9d7b8SMuhammad Omair Javaid : "<unknown register>"); 119b6f9d7b8SMuhammad Omair Javaid 120b6f9d7b8SMuhammad Omair Javaid uint8_t *src; 1214283320bSMuhammad Omair Javaid uint32_t offset = LLDB_INVALID_INDEX32; 122567ba6c4SMuhammad Omair Javaid uint64_t sve_vg; 123567ba6c4SMuhammad Omair Javaid std::vector<uint8_t> sve_reg_non_live; 124b6f9d7b8SMuhammad Omair Javaid 125b6f9d7b8SMuhammad Omair Javaid if (IsGPR(reg)) { 126b6f9d7b8SMuhammad Omair Javaid error = ReadGPR(); 127b6f9d7b8SMuhammad Omair Javaid if (error.Fail()) 128b6f9d7b8SMuhammad Omair Javaid return error; 129b6f9d7b8SMuhammad Omair Javaid 130b6f9d7b8SMuhammad Omair Javaid offset = reg_info->byte_offset; 131b6f9d7b8SMuhammad Omair Javaid assert(offset < GetGPRSize()); 132b6f9d7b8SMuhammad Omair Javaid src = (uint8_t *)GetGPRBuffer() + offset; 133b6f9d7b8SMuhammad Omair Javaid 134b6f9d7b8SMuhammad Omair Javaid } else if (IsFPR(reg)) { 135567ba6c4SMuhammad Omair Javaid if (m_sve_state == SVEState::Disabled) { 136567ba6c4SMuhammad Omair Javaid // SVE is disabled take legacy route for FPU register access 137068f8a7eSTamas Berghammer error = ReadFPR(); 138068f8a7eSTamas Berghammer if (error.Fail()) 1391e209fccSTamas Berghammer return error; 140567ba6c4SMuhammad Omair Javaid 141b6f9d7b8SMuhammad Omair Javaid offset = CalculateFprOffset(reg_info); 142b6f9d7b8SMuhammad Omair Javaid assert(offset < GetFPRSize()); 143b6f9d7b8SMuhammad Omair Javaid src = (uint8_t *)GetFPRBuffer() + offset; 144567ba6c4SMuhammad Omair Javaid } else { 145567ba6c4SMuhammad Omair Javaid // SVE enabled, we will read and cache SVE ptrace data 146567ba6c4SMuhammad Omair Javaid error = ReadAllSVE(); 147567ba6c4SMuhammad Omair Javaid if (error.Fail()) 148567ba6c4SMuhammad Omair Javaid return error; 149567ba6c4SMuhammad Omair Javaid 150567ba6c4SMuhammad Omair Javaid // FPSR and FPCR will be located right after Z registers in 151567ba6c4SMuhammad Omair Javaid // SVEState::FPSIMD while in SVEState::Full they will be located at the 152567ba6c4SMuhammad Omair Javaid // end of register data after an alignment correction based on currently 153567ba6c4SMuhammad Omair Javaid // selected vector length. 154567ba6c4SMuhammad Omair Javaid uint32_t sve_reg_num = LLDB_INVALID_REGNUM; 155567ba6c4SMuhammad Omair Javaid if (reg == GetRegisterInfo().GetRegNumFPSR()) { 156567ba6c4SMuhammad Omair Javaid sve_reg_num = reg; 157567ba6c4SMuhammad Omair Javaid if (m_sve_state == SVEState::Full) 158567ba6c4SMuhammad Omair Javaid offset = SVE_PT_SVE_FPSR_OFFSET(sve_vq_from_vl(m_sve_header.vl)); 159567ba6c4SMuhammad Omair Javaid else if (m_sve_state == SVEState::FPSIMD) 160567ba6c4SMuhammad Omair Javaid offset = SVE_PT_FPSIMD_OFFSET + (32 * 16); 161567ba6c4SMuhammad Omair Javaid } else if (reg == GetRegisterInfo().GetRegNumFPCR()) { 162567ba6c4SMuhammad Omair Javaid sve_reg_num = reg; 163567ba6c4SMuhammad Omair Javaid if (m_sve_state == SVEState::Full) 164567ba6c4SMuhammad Omair Javaid offset = SVE_PT_SVE_FPCR_OFFSET(sve_vq_from_vl(m_sve_header.vl)); 165567ba6c4SMuhammad Omair Javaid else if (m_sve_state == SVEState::FPSIMD) 166567ba6c4SMuhammad Omair Javaid offset = SVE_PT_FPSIMD_OFFSET + (32 * 16) + 4; 167567ba6c4SMuhammad Omair Javaid } else { 168567ba6c4SMuhammad Omair Javaid // Extract SVE Z register value register number for this reg_info 169567ba6c4SMuhammad Omair Javaid if (reg_info->value_regs && 170567ba6c4SMuhammad Omair Javaid reg_info->value_regs[0] != LLDB_INVALID_REGNUM) 171567ba6c4SMuhammad Omair Javaid sve_reg_num = reg_info->value_regs[0]; 172567ba6c4SMuhammad Omair Javaid offset = CalculateSVEOffset(GetRegisterInfoAtIndex(sve_reg_num)); 173567ba6c4SMuhammad Omair Javaid } 174567ba6c4SMuhammad Omair Javaid 175567ba6c4SMuhammad Omair Javaid assert(offset < GetSVEBufferSize()); 176567ba6c4SMuhammad Omair Javaid src = (uint8_t *)GetSVEBuffer() + offset; 177567ba6c4SMuhammad Omair Javaid } 178567ba6c4SMuhammad Omair Javaid } else if (IsSVE(reg)) { 179567ba6c4SMuhammad Omair Javaid 180567ba6c4SMuhammad Omair Javaid if (m_sve_state == SVEState::Disabled || m_sve_state == SVEState::Unknown) 181567ba6c4SMuhammad Omair Javaid return Status("SVE disabled or not supported"); 182567ba6c4SMuhammad Omair Javaid 183567ba6c4SMuhammad Omair Javaid if (GetRegisterInfo().IsSVERegVG(reg)) { 184567ba6c4SMuhammad Omair Javaid sve_vg = GetSVERegVG(); 185567ba6c4SMuhammad Omair Javaid src = (uint8_t *)&sve_vg; 186567ba6c4SMuhammad Omair Javaid } else { 187567ba6c4SMuhammad Omair Javaid // SVE enabled, we will read and cache SVE ptrace data 188567ba6c4SMuhammad Omair Javaid error = ReadAllSVE(); 189567ba6c4SMuhammad Omair Javaid if (error.Fail()) 190567ba6c4SMuhammad Omair Javaid return error; 191567ba6c4SMuhammad Omair Javaid 192567ba6c4SMuhammad Omair Javaid if (m_sve_state == SVEState::FPSIMD) { 193567ba6c4SMuhammad Omair Javaid // In FPSIMD state SVE payload mirrors legacy fpsimd struct and so 194567ba6c4SMuhammad Omair Javaid // just copy 16 bytes of v register to the start of z register. All 195567ba6c4SMuhammad Omair Javaid // other SVE register will be set to zero. 196567ba6c4SMuhammad Omair Javaid sve_reg_non_live.resize(reg_info->byte_size, 0); 197567ba6c4SMuhammad Omair Javaid src = sve_reg_non_live.data(); 198567ba6c4SMuhammad Omair Javaid 199567ba6c4SMuhammad Omair Javaid if (GetRegisterInfo().IsSVEZReg(reg)) { 200567ba6c4SMuhammad Omair Javaid offset = CalculateSVEOffset(reg_info); 201567ba6c4SMuhammad Omair Javaid assert(offset < GetSVEBufferSize()); 202567ba6c4SMuhammad Omair Javaid ::memcpy(sve_reg_non_live.data(), (uint8_t *)GetSVEBuffer() + offset, 203567ba6c4SMuhammad Omair Javaid 16); 204567ba6c4SMuhammad Omair Javaid } 205567ba6c4SMuhammad Omair Javaid } else { 206567ba6c4SMuhammad Omair Javaid offset = CalculateSVEOffset(reg_info); 207567ba6c4SMuhammad Omair Javaid assert(offset < GetSVEBufferSize()); 208567ba6c4SMuhammad Omair Javaid src = (uint8_t *)GetSVEBuffer() + offset; 209567ba6c4SMuhammad Omair Javaid } 210567ba6c4SMuhammad Omair Javaid } 211b6f9d7b8SMuhammad Omair Javaid } else 212b6f9d7b8SMuhammad Omair Javaid return Status("failed - register wasn't recognized to be a GPR or an FPR, " 213b6f9d7b8SMuhammad Omair Javaid "write strategy unknown"); 2141e209fccSTamas Berghammer 215b9c1b51eSKate Stone reg_value.SetFromMemoryData(reg_info, src, reg_info->byte_size, 216b9c1b51eSKate Stone eByteOrderLittle, error); 2171e209fccSTamas Berghammer 2181e209fccSTamas Berghammer return error; 2191e209fccSTamas Berghammer } 2201e209fccSTamas Berghammer 22197206d57SZachary Turner Status NativeRegisterContextLinux_arm64::WriteRegister( 222b9c1b51eSKate Stone const RegisterInfo *reg_info, const RegisterValue ®_value) { 223b6f9d7b8SMuhammad Omair Javaid Status error; 224b6f9d7b8SMuhammad Omair Javaid 2251e209fccSTamas Berghammer if (!reg_info) 22697206d57SZachary Turner return Status("reg_info NULL"); 2271e209fccSTamas Berghammer 228b6f9d7b8SMuhammad Omair Javaid const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; 229b6f9d7b8SMuhammad Omair Javaid 230b6f9d7b8SMuhammad Omair Javaid if (reg == LLDB_INVALID_REGNUM) 23197206d57SZachary Turner return Status("no lldb regnum for %s", reg_info && reg_info->name 232b9c1b51eSKate Stone ? reg_info->name 233b9c1b51eSKate Stone : "<unknown register>"); 2341e209fccSTamas Berghammer 235b6f9d7b8SMuhammad Omair Javaid uint8_t *dst; 2364283320bSMuhammad Omair Javaid uint32_t offset = LLDB_INVALID_INDEX32; 237567ba6c4SMuhammad Omair Javaid std::vector<uint8_t> sve_reg_non_live; 2381e209fccSTamas Berghammer 239b6f9d7b8SMuhammad Omair Javaid if (IsGPR(reg)) { 240b6f9d7b8SMuhammad Omair Javaid error = ReadGPR(); 241068f8a7eSTamas Berghammer if (error.Fail()) 242068f8a7eSTamas Berghammer return error; 2431e209fccSTamas Berghammer 244567ba6c4SMuhammad Omair Javaid assert(reg_info->byte_offset < GetGPRSize()); 245567ba6c4SMuhammad Omair Javaid dst = (uint8_t *)GetGPRBuffer() + reg_info->byte_offset; 246b6f9d7b8SMuhammad Omair Javaid ::memcpy(dst, reg_value.GetBytes(), reg_info->byte_size); 247b6f9d7b8SMuhammad Omair Javaid 248b6f9d7b8SMuhammad Omair Javaid return WriteGPR(); 249b6f9d7b8SMuhammad Omair Javaid } else if (IsFPR(reg)) { 250567ba6c4SMuhammad Omair Javaid if (m_sve_state == SVEState::Disabled) { 251567ba6c4SMuhammad Omair Javaid // SVE is disabled take legacy route for FPU register access 252b6f9d7b8SMuhammad Omair Javaid error = ReadFPR(); 253b6f9d7b8SMuhammad Omair Javaid if (error.Fail()) 254b6f9d7b8SMuhammad Omair Javaid return error; 255567ba6c4SMuhammad Omair Javaid 256b6f9d7b8SMuhammad Omair Javaid offset = CalculateFprOffset(reg_info); 257b6f9d7b8SMuhammad Omair Javaid assert(offset < GetFPRSize()); 258b6f9d7b8SMuhammad Omair Javaid dst = (uint8_t *)GetFPRBuffer() + offset; 259b6f9d7b8SMuhammad Omair Javaid ::memcpy(dst, reg_value.GetBytes(), reg_info->byte_size); 260b6f9d7b8SMuhammad Omair Javaid 261b6f9d7b8SMuhammad Omair Javaid return WriteFPR(); 262567ba6c4SMuhammad Omair Javaid } else { 263567ba6c4SMuhammad Omair Javaid // SVE enabled, we will read and cache SVE ptrace data 264567ba6c4SMuhammad Omair Javaid error = ReadAllSVE(); 265567ba6c4SMuhammad Omair Javaid if (error.Fail()) 266567ba6c4SMuhammad Omair Javaid return error; 267567ba6c4SMuhammad Omair Javaid 268567ba6c4SMuhammad Omair Javaid // FPSR and FPCR will be located right after Z registers in 269567ba6c4SMuhammad Omair Javaid // SVEState::FPSIMD while in SVEState::Full they will be located at the 270567ba6c4SMuhammad Omair Javaid // end of register data after an alignment correction based on currently 271567ba6c4SMuhammad Omair Javaid // selected vector length. 272567ba6c4SMuhammad Omair Javaid uint32_t sve_reg_num = LLDB_INVALID_REGNUM; 273567ba6c4SMuhammad Omair Javaid if (reg == GetRegisterInfo().GetRegNumFPSR()) { 274567ba6c4SMuhammad Omair Javaid sve_reg_num = reg; 275567ba6c4SMuhammad Omair Javaid if (m_sve_state == SVEState::Full) 276567ba6c4SMuhammad Omair Javaid offset = SVE_PT_SVE_FPSR_OFFSET(sve_vq_from_vl(m_sve_header.vl)); 277567ba6c4SMuhammad Omair Javaid else if (m_sve_state == SVEState::FPSIMD) 278567ba6c4SMuhammad Omair Javaid offset = SVE_PT_FPSIMD_OFFSET + (32 * 16); 279567ba6c4SMuhammad Omair Javaid } else if (reg == GetRegisterInfo().GetRegNumFPCR()) { 280567ba6c4SMuhammad Omair Javaid sve_reg_num = reg; 281567ba6c4SMuhammad Omair Javaid if (m_sve_state == SVEState::Full) 282567ba6c4SMuhammad Omair Javaid offset = SVE_PT_SVE_FPCR_OFFSET(sve_vq_from_vl(m_sve_header.vl)); 283567ba6c4SMuhammad Omair Javaid else if (m_sve_state == SVEState::FPSIMD) 284567ba6c4SMuhammad Omair Javaid offset = SVE_PT_FPSIMD_OFFSET + (32 * 16) + 4; 285567ba6c4SMuhammad Omair Javaid } else { 286567ba6c4SMuhammad Omair Javaid // Extract SVE Z register value register number for this reg_info 287567ba6c4SMuhammad Omair Javaid if (reg_info->value_regs && 288567ba6c4SMuhammad Omair Javaid reg_info->value_regs[0] != LLDB_INVALID_REGNUM) 289567ba6c4SMuhammad Omair Javaid sve_reg_num = reg_info->value_regs[0]; 290567ba6c4SMuhammad Omair Javaid offset = CalculateSVEOffset(GetRegisterInfoAtIndex(sve_reg_num)); 291b6f9d7b8SMuhammad Omair Javaid } 292b6f9d7b8SMuhammad Omair Javaid 293567ba6c4SMuhammad Omair Javaid assert(offset < GetSVEBufferSize()); 294567ba6c4SMuhammad Omair Javaid dst = (uint8_t *)GetSVEBuffer() + offset; 295567ba6c4SMuhammad Omair Javaid ::memcpy(dst, reg_value.GetBytes(), reg_info->byte_size); 296567ba6c4SMuhammad Omair Javaid return WriteAllSVE(); 297567ba6c4SMuhammad Omair Javaid } 298567ba6c4SMuhammad Omair Javaid } else if (IsSVE(reg)) { 299567ba6c4SMuhammad Omair Javaid if (m_sve_state == SVEState::Disabled || m_sve_state == SVEState::Unknown) 300567ba6c4SMuhammad Omair Javaid return Status("SVE disabled or not supported"); 301567ba6c4SMuhammad Omair Javaid else { 302567ba6c4SMuhammad Omair Javaid // Target has SVE enabled, we will read and cache SVE ptrace data 303567ba6c4SMuhammad Omair Javaid error = ReadAllSVE(); 304567ba6c4SMuhammad Omair Javaid if (error.Fail()) 305b6f9d7b8SMuhammad Omair Javaid return error; 306567ba6c4SMuhammad Omair Javaid 307e448ad78SMuhammad Omair Javaid if (GetRegisterInfo().IsSVERegVG(reg)) { 308e448ad78SMuhammad Omair Javaid uint64_t vg_value = reg_value.GetAsUInt64(); 309e448ad78SMuhammad Omair Javaid 310e448ad78SMuhammad Omair Javaid if (sve_vl_valid(vg_value * 8)) { 311e448ad78SMuhammad Omair Javaid if (m_sve_header_is_valid && vg_value == GetSVERegVG()) 312e448ad78SMuhammad Omair Javaid return error; 313e448ad78SMuhammad Omair Javaid 314e448ad78SMuhammad Omair Javaid SetSVERegVG(vg_value); 315e448ad78SMuhammad Omair Javaid 316e448ad78SMuhammad Omair Javaid error = WriteSVEHeader(); 317e448ad78SMuhammad Omair Javaid if (error.Success()) 318e448ad78SMuhammad Omair Javaid ConfigureRegisterContext(); 319e448ad78SMuhammad Omair Javaid 320e448ad78SMuhammad Omair Javaid if (m_sve_header_is_valid && vg_value == GetSVERegVG()) 321e448ad78SMuhammad Omair Javaid return error; 322e448ad78SMuhammad Omair Javaid } 323e448ad78SMuhammad Omair Javaid 324e448ad78SMuhammad Omair Javaid return Status("SVE vector length update failed."); 325e448ad78SMuhammad Omair Javaid } 326e448ad78SMuhammad Omair Javaid 327567ba6c4SMuhammad Omair Javaid // If target supports SVE but currently in FPSIMD mode. 328567ba6c4SMuhammad Omair Javaid if (m_sve_state == SVEState::FPSIMD) { 329567ba6c4SMuhammad Omair Javaid // Here we will check if writing this SVE register enables 330567ba6c4SMuhammad Omair Javaid // SVEState::Full 331567ba6c4SMuhammad Omair Javaid bool set_sve_state_full = false; 332567ba6c4SMuhammad Omair Javaid const uint8_t *reg_bytes = (const uint8_t *)reg_value.GetBytes(); 333567ba6c4SMuhammad Omair Javaid if (GetRegisterInfo().IsSVEZReg(reg)) { 334567ba6c4SMuhammad Omair Javaid for (uint32_t i = 16; i < reg_info->byte_size; i++) { 335567ba6c4SMuhammad Omair Javaid if (reg_bytes[i]) { 336567ba6c4SMuhammad Omair Javaid set_sve_state_full = true; 337567ba6c4SMuhammad Omair Javaid break; 338567ba6c4SMuhammad Omair Javaid } 339567ba6c4SMuhammad Omair Javaid } 340567ba6c4SMuhammad Omair Javaid } else if (GetRegisterInfo().IsSVEPReg(reg) || 341567ba6c4SMuhammad Omair Javaid reg == GetRegisterInfo().GetRegNumSVEFFR()) { 342567ba6c4SMuhammad Omair Javaid for (uint32_t i = 0; i < reg_info->byte_size; i++) { 343567ba6c4SMuhammad Omair Javaid if (reg_bytes[i]) { 344567ba6c4SMuhammad Omair Javaid set_sve_state_full = true; 345567ba6c4SMuhammad Omair Javaid break; 346567ba6c4SMuhammad Omair Javaid } 347567ba6c4SMuhammad Omair Javaid } 348567ba6c4SMuhammad Omair Javaid } 349567ba6c4SMuhammad Omair Javaid 350567ba6c4SMuhammad Omair Javaid if (!set_sve_state_full && GetRegisterInfo().IsSVEZReg(reg)) { 351567ba6c4SMuhammad Omair Javaid // We are writing a Z register which is zero beyond 16 bytes so copy 352567ba6c4SMuhammad Omair Javaid // first 16 bytes only as SVE payload mirrors legacy fpsimd structure 353567ba6c4SMuhammad Omair Javaid offset = CalculateSVEOffset(reg_info); 354567ba6c4SMuhammad Omair Javaid assert(offset < GetSVEBufferSize()); 355567ba6c4SMuhammad Omair Javaid dst = (uint8_t *)GetSVEBuffer() + offset; 356567ba6c4SMuhammad Omair Javaid ::memcpy(dst, reg_value.GetBytes(), 16); 357567ba6c4SMuhammad Omair Javaid 358567ba6c4SMuhammad Omair Javaid return WriteAllSVE(); 359567ba6c4SMuhammad Omair Javaid } else 360567ba6c4SMuhammad Omair Javaid return Status("SVE state change operation not supported"); 361567ba6c4SMuhammad Omair Javaid } else { 362567ba6c4SMuhammad Omair Javaid offset = CalculateSVEOffset(reg_info); 363567ba6c4SMuhammad Omair Javaid assert(offset < GetSVEBufferSize()); 364567ba6c4SMuhammad Omair Javaid dst = (uint8_t *)GetSVEBuffer() + offset; 365567ba6c4SMuhammad Omair Javaid ::memcpy(dst, reg_value.GetBytes(), reg_info->byte_size); 366567ba6c4SMuhammad Omair Javaid return WriteAllSVE(); 367567ba6c4SMuhammad Omair Javaid } 368567ba6c4SMuhammad Omair Javaid } 369567ba6c4SMuhammad Omair Javaid } 370567ba6c4SMuhammad Omair Javaid 371567ba6c4SMuhammad Omair Javaid return Status("Failed to write register value"); 3721e209fccSTamas Berghammer } 3731e209fccSTamas Berghammer 37497206d57SZachary Turner Status NativeRegisterContextLinux_arm64::ReadAllRegisterValues( 375b9c1b51eSKate Stone lldb::DataBufferSP &data_sp) { 37697206d57SZachary Turner Status error; 3771e209fccSTamas Berghammer 378db264a6dSTamas Berghammer data_sp.reset(new DataBufferHeap(REG_CONTEXT_SIZE, 0)); 379567ba6c4SMuhammad Omair Javaid 380068f8a7eSTamas Berghammer error = ReadGPR(); 381068f8a7eSTamas Berghammer if (error.Fail()) 3821e209fccSTamas Berghammer return error; 3831e209fccSTamas Berghammer 384068f8a7eSTamas Berghammer error = ReadFPR(); 385068f8a7eSTamas Berghammer if (error.Fail()) 3861e209fccSTamas Berghammer return error; 387567ba6c4SMuhammad Omair Javaid 3881e209fccSTamas Berghammer uint8_t *dst = data_sp->GetBytes(); 389b6f9d7b8SMuhammad Omair Javaid ::memcpy(dst, GetGPRBuffer(), GetGPRSize()); 3901e209fccSTamas Berghammer dst += GetGPRSize(); 391b6f9d7b8SMuhammad Omair Javaid ::memcpy(dst, GetFPRBuffer(), GetFPRSize()); 3921e209fccSTamas Berghammer 3931e209fccSTamas Berghammer return error; 3941e209fccSTamas Berghammer } 3951e209fccSTamas Berghammer 39697206d57SZachary Turner Status NativeRegisterContextLinux_arm64::WriteAllRegisterValues( 397b9c1b51eSKate Stone const lldb::DataBufferSP &data_sp) { 39897206d57SZachary Turner Status error; 3991e209fccSTamas Berghammer 400b9c1b51eSKate Stone if (!data_sp) { 401b9c1b51eSKate Stone error.SetErrorStringWithFormat( 402b9c1b51eSKate Stone "NativeRegisterContextLinux_x86_64::%s invalid data_sp provided", 403b9c1b51eSKate Stone __FUNCTION__); 4041e209fccSTamas Berghammer return error; 4051e209fccSTamas Berghammer } 4061e209fccSTamas Berghammer 407b9c1b51eSKate Stone if (data_sp->GetByteSize() != REG_CONTEXT_SIZE) { 408b9c1b51eSKate Stone error.SetErrorStringWithFormat( 409b9c1b51eSKate Stone "NativeRegisterContextLinux_x86_64::%s data_sp contained mismatched " 410b9c1b51eSKate Stone "data size, expected %" PRIu64 ", actual %" PRIu64, 411b9c1b51eSKate Stone __FUNCTION__, REG_CONTEXT_SIZE, data_sp->GetByteSize()); 4121e209fccSTamas Berghammer return error; 4131e209fccSTamas Berghammer } 4141e209fccSTamas Berghammer 4151e209fccSTamas Berghammer uint8_t *src = data_sp->GetBytes(); 416b9c1b51eSKate Stone if (src == nullptr) { 417b9c1b51eSKate Stone error.SetErrorStringWithFormat("NativeRegisterContextLinux_x86_64::%s " 418b9c1b51eSKate Stone "DataBuffer::GetBytes() returned a null " 419b9c1b51eSKate Stone "pointer", 420b9c1b51eSKate Stone __FUNCTION__); 4211e209fccSTamas Berghammer return error; 4221e209fccSTamas Berghammer } 423b6f9d7b8SMuhammad Omair Javaid ::memcpy(GetGPRBuffer(), src, GetRegisterInfoInterface().GetGPRSize()); 4241e209fccSTamas Berghammer 425068f8a7eSTamas Berghammer error = WriteGPR(); 426068f8a7eSTamas Berghammer if (error.Fail()) 4271e209fccSTamas Berghammer return error; 4281e209fccSTamas Berghammer 4291e209fccSTamas Berghammer src += GetRegisterInfoInterface().GetGPRSize(); 430b6f9d7b8SMuhammad Omair Javaid ::memcpy(GetFPRBuffer(), src, GetFPRSize()); 4311e209fccSTamas Berghammer 432068f8a7eSTamas Berghammer error = WriteFPR(); 4331e209fccSTamas Berghammer if (error.Fail()) 4341e209fccSTamas Berghammer return error; 4351e209fccSTamas Berghammer 4361e209fccSTamas Berghammer return error; 4371e209fccSTamas Berghammer } 4381e209fccSTamas Berghammer 439b9c1b51eSKate Stone bool NativeRegisterContextLinux_arm64::IsGPR(unsigned reg) const { 4407fa7b81bSMuhammad Omair Javaid if (GetRegisterInfo().GetRegisterSetFromRegisterIndex(reg) == 4417fa7b81bSMuhammad Omair Javaid RegisterInfoPOSIX_arm64::GPRegSet) 4427fa7b81bSMuhammad Omair Javaid return true; 4437fa7b81bSMuhammad Omair Javaid return false; 4441e209fccSTamas Berghammer } 4451e209fccSTamas Berghammer 446b9c1b51eSKate Stone bool NativeRegisterContextLinux_arm64::IsFPR(unsigned reg) const { 4477fa7b81bSMuhammad Omair Javaid if (GetRegisterInfo().GetRegisterSetFromRegisterIndex(reg) == 4487fa7b81bSMuhammad Omair Javaid RegisterInfoPOSIX_arm64::FPRegSet) 4497fa7b81bSMuhammad Omair Javaid return true; 4507fa7b81bSMuhammad Omair Javaid return false; 4511e209fccSTamas Berghammer } 4521e209fccSTamas Berghammer 453567ba6c4SMuhammad Omair Javaid bool NativeRegisterContextLinux_arm64::IsSVE(unsigned reg) const { 454567ba6c4SMuhammad Omair Javaid if (GetRegisterInfo().GetRegisterSetFromRegisterIndex(reg) == 455567ba6c4SMuhammad Omair Javaid RegisterInfoPOSIX_arm64::SVERegSet) 456567ba6c4SMuhammad Omair Javaid return true; 457567ba6c4SMuhammad Omair Javaid return false; 458567ba6c4SMuhammad Omair Javaid } 459567ba6c4SMuhammad Omair Javaid 460*771c4c9cSMichał Górny llvm::Error NativeRegisterContextLinux_arm64::ReadHardwareDebugInfo() { 461b9c1b51eSKate Stone if (!m_refresh_hwdebug_info) { 462*771c4c9cSMichał Górny return llvm::Error::success(); 4631fd2a8cfSOmair Javaid } 4641fd2a8cfSOmair Javaid 465c7512fdcSPavel Labath ::pid_t tid = m_thread.GetID(); 466ea8c25a8SOmair Javaid 467c7512fdcSPavel Labath int regset = NT_ARM_HW_WATCH; 468c7512fdcSPavel Labath struct iovec ioVec; 469c7512fdcSPavel Labath struct user_hwdebug_state dreg_state; 47097206d57SZachary Turner Status error; 471c7512fdcSPavel Labath 472c7512fdcSPavel Labath ioVec.iov_base = &dreg_state; 473c7512fdcSPavel Labath ioVec.iov_len = sizeof(dreg_state); 474b9c1b51eSKate Stone error = NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, tid, ®set, 475b9c1b51eSKate Stone &ioVec, ioVec.iov_len); 4763a56363aSOmair Javaid 4773a56363aSOmair Javaid if (error.Fail()) 478*771c4c9cSMichał Górny return error.ToError(); 4793a56363aSOmair Javaid 4801fd2a8cfSOmair Javaid m_max_hwp_supported = dreg_state.dbg_info & 0xff; 481c7512fdcSPavel Labath 482c7512fdcSPavel Labath regset = NT_ARM_HW_BREAK; 483b9c1b51eSKate Stone error = NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, tid, ®set, 484b9c1b51eSKate Stone &ioVec, ioVec.iov_len); 4851fd2a8cfSOmair Javaid 4863a56363aSOmair Javaid if (error.Fail()) 487*771c4c9cSMichał Górny return error.ToError(); 4883a56363aSOmair Javaid 4893a56363aSOmair Javaid m_max_hbp_supported = dreg_state.dbg_info & 0xff; 4901fd2a8cfSOmair Javaid m_refresh_hwdebug_info = false; 491c7512fdcSPavel Labath 492*771c4c9cSMichał Górny return llvm::Error::success(); 493ea8c25a8SOmair Javaid } 494068f8a7eSTamas Berghammer 495*771c4c9cSMichał Górny llvm::Error 496*771c4c9cSMichał Górny NativeRegisterContextLinux_arm64::WriteHardwareDebugRegs(DREGType hwbType) { 497c7512fdcSPavel Labath struct iovec ioVec; 498c7512fdcSPavel Labath struct user_hwdebug_state dreg_state; 499*771c4c9cSMichał Górny int regset; 500c7512fdcSPavel Labath 501c7512fdcSPavel Labath memset(&dreg_state, 0, sizeof(dreg_state)); 502c7512fdcSPavel Labath ioVec.iov_base = &dreg_state; 503c7512fdcSPavel Labath 504*771c4c9cSMichał Górny switch (hwbType) { 505*771c4c9cSMichał Górny case eDREGTypeWATCH: 506*771c4c9cSMichał Górny regset = NT_ARM_HW_WATCH; 507b9c1b51eSKate Stone ioVec.iov_len = sizeof(dreg_state.dbg_info) + sizeof(dreg_state.pad) + 508b9c1b51eSKate Stone (sizeof(dreg_state.dbg_regs[0]) * m_max_hwp_supported); 5091fd2a8cfSOmair Javaid 510b9c1b51eSKate Stone for (uint32_t i = 0; i < m_max_hwp_supported; i++) { 5111fd2a8cfSOmair Javaid dreg_state.dbg_regs[i].addr = m_hwp_regs[i].address; 5121fd2a8cfSOmair Javaid dreg_state.dbg_regs[i].ctrl = m_hwp_regs[i].control; 5131fd2a8cfSOmair Javaid } 514*771c4c9cSMichał Górny break; 515*771c4c9cSMichał Górny case eDREGTypeBREAK: 516*771c4c9cSMichał Górny regset = NT_ARM_HW_BREAK; 517b9c1b51eSKate Stone ioVec.iov_len = sizeof(dreg_state.dbg_info) + sizeof(dreg_state.pad) + 518b9c1b51eSKate Stone (sizeof(dreg_state.dbg_regs[0]) * m_max_hbp_supported); 5191fd2a8cfSOmair Javaid 520b9c1b51eSKate Stone for (uint32_t i = 0; i < m_max_hbp_supported; i++) { 521*771c4c9cSMichał Górny dreg_state.dbg_regs[i].addr = m_hbp_regs[i].address; 522*771c4c9cSMichał Górny dreg_state.dbg_regs[i].ctrl = m_hbp_regs[i].control; 5231fd2a8cfSOmair Javaid } 524*771c4c9cSMichał Górny break; 525068f8a7eSTamas Berghammer } 526068f8a7eSTamas Berghammer 527b9c1b51eSKate Stone return NativeProcessLinux::PtraceWrapper(PTRACE_SETREGSET, m_thread.GetID(), 528*771c4c9cSMichał Górny ®set, &ioVec, ioVec.iov_len) 529*771c4c9cSMichał Górny .ToError(); 530c7512fdcSPavel Labath } 531c7512fdcSPavel Labath 5323f3673eaSPavel Labath Status NativeRegisterContextLinux_arm64::ReadGPR() { 533b6f9d7b8SMuhammad Omair Javaid Status error; 534b6f9d7b8SMuhammad Omair Javaid 535567ba6c4SMuhammad Omair Javaid if (m_gpr_is_valid) 536567ba6c4SMuhammad Omair Javaid return error; 537b6f9d7b8SMuhammad Omair Javaid 538567ba6c4SMuhammad Omair Javaid struct iovec ioVec; 5393f3673eaSPavel Labath ioVec.iov_base = GetGPRBuffer(); 54026b8ea2eSMuhammad Omair Javaid ioVec.iov_len = GetGPRBufferSize(); 541b6f9d7b8SMuhammad Omair Javaid 54226b8ea2eSMuhammad Omair Javaid error = ReadRegisterSet(&ioVec, GetGPRBufferSize(), NT_PRSTATUS); 543b6f9d7b8SMuhammad Omair Javaid 544b6f9d7b8SMuhammad Omair Javaid if (error.Success()) 545b6f9d7b8SMuhammad Omair Javaid m_gpr_is_valid = true; 546b6f9d7b8SMuhammad Omair Javaid 547b6f9d7b8SMuhammad Omair Javaid return error; 548068f8a7eSTamas Berghammer } 549068f8a7eSTamas Berghammer 5503f3673eaSPavel Labath Status NativeRegisterContextLinux_arm64::WriteGPR() { 551567ba6c4SMuhammad Omair Javaid Status error = ReadGPR(); 552567ba6c4SMuhammad Omair Javaid if (error.Fail()) 553567ba6c4SMuhammad Omair Javaid return error; 554567ba6c4SMuhammad Omair Javaid 555c7512fdcSPavel Labath struct iovec ioVec; 5563f3673eaSPavel Labath ioVec.iov_base = GetGPRBuffer(); 55726b8ea2eSMuhammad Omair Javaid ioVec.iov_len = GetGPRBufferSize(); 558b6f9d7b8SMuhammad Omair Javaid 559567ba6c4SMuhammad Omair Javaid m_gpr_is_valid = false; 560567ba6c4SMuhammad Omair Javaid 56126b8ea2eSMuhammad Omair Javaid return WriteRegisterSet(&ioVec, GetGPRBufferSize(), NT_PRSTATUS); 562068f8a7eSTamas Berghammer } 563068f8a7eSTamas Berghammer 5643f3673eaSPavel Labath Status NativeRegisterContextLinux_arm64::ReadFPR() { 565b6f9d7b8SMuhammad Omair Javaid Status error; 566b6f9d7b8SMuhammad Omair Javaid 567567ba6c4SMuhammad Omair Javaid if (m_fpu_is_valid) 568567ba6c4SMuhammad Omair Javaid return error; 569b6f9d7b8SMuhammad Omair Javaid 570567ba6c4SMuhammad Omair Javaid struct iovec ioVec; 5713f3673eaSPavel Labath ioVec.iov_base = GetFPRBuffer(); 5723f3673eaSPavel Labath ioVec.iov_len = GetFPRSize(); 573b6f9d7b8SMuhammad Omair Javaid 574b6f9d7b8SMuhammad Omair Javaid error = ReadRegisterSet(&ioVec, GetFPRSize(), NT_FPREGSET); 575b6f9d7b8SMuhammad Omair Javaid 576b6f9d7b8SMuhammad Omair Javaid if (error.Success()) 577b6f9d7b8SMuhammad Omair Javaid m_fpu_is_valid = true; 578b6f9d7b8SMuhammad Omair Javaid 579b6f9d7b8SMuhammad Omair Javaid return error; 580068f8a7eSTamas Berghammer } 581068f8a7eSTamas Berghammer 5823f3673eaSPavel Labath Status NativeRegisterContextLinux_arm64::WriteFPR() { 583567ba6c4SMuhammad Omair Javaid Status error = ReadFPR(); 584567ba6c4SMuhammad Omair Javaid if (error.Fail()) 585567ba6c4SMuhammad Omair Javaid return error; 586567ba6c4SMuhammad Omair Javaid 587c7512fdcSPavel Labath struct iovec ioVec; 5883f3673eaSPavel Labath ioVec.iov_base = GetFPRBuffer(); 5893f3673eaSPavel Labath ioVec.iov_len = GetFPRSize(); 590b6f9d7b8SMuhammad Omair Javaid 591567ba6c4SMuhammad Omair Javaid m_fpu_is_valid = false; 592567ba6c4SMuhammad Omair Javaid 5933f3673eaSPavel Labath return WriteRegisterSet(&ioVec, GetFPRSize(), NT_FPREGSET); 594068f8a7eSTamas Berghammer } 595068f8a7eSTamas Berghammer 596b6f9d7b8SMuhammad Omair Javaid void NativeRegisterContextLinux_arm64::InvalidateAllRegisters() { 597b6f9d7b8SMuhammad Omair Javaid m_gpr_is_valid = false; 598b6f9d7b8SMuhammad Omair Javaid m_fpu_is_valid = false; 599567ba6c4SMuhammad Omair Javaid m_sve_buffer_is_valid = false; 600567ba6c4SMuhammad Omair Javaid m_sve_header_is_valid = false; 601567ba6c4SMuhammad Omair Javaid 602567ba6c4SMuhammad Omair Javaid // Update SVE registers in case there is change in configuration. 603567ba6c4SMuhammad Omair Javaid ConfigureRegisterContext(); 604567ba6c4SMuhammad Omair Javaid } 605567ba6c4SMuhammad Omair Javaid 606567ba6c4SMuhammad Omair Javaid Status NativeRegisterContextLinux_arm64::ReadSVEHeader() { 607567ba6c4SMuhammad Omair Javaid Status error; 608567ba6c4SMuhammad Omair Javaid 609567ba6c4SMuhammad Omair Javaid if (m_sve_header_is_valid) 610567ba6c4SMuhammad Omair Javaid return error; 611567ba6c4SMuhammad Omair Javaid 612567ba6c4SMuhammad Omair Javaid struct iovec ioVec; 613567ba6c4SMuhammad Omair Javaid ioVec.iov_base = GetSVEHeader(); 614567ba6c4SMuhammad Omair Javaid ioVec.iov_len = GetSVEHeaderSize(); 615567ba6c4SMuhammad Omair Javaid 616567ba6c4SMuhammad Omair Javaid error = ReadRegisterSet(&ioVec, GetSVEHeaderSize(), NT_ARM_SVE); 617567ba6c4SMuhammad Omair Javaid 618567ba6c4SMuhammad Omair Javaid m_sve_header_is_valid = true; 619567ba6c4SMuhammad Omair Javaid 620567ba6c4SMuhammad Omair Javaid return error; 621567ba6c4SMuhammad Omair Javaid } 622567ba6c4SMuhammad Omair Javaid 623567ba6c4SMuhammad Omair Javaid Status NativeRegisterContextLinux_arm64::WriteSVEHeader() { 624567ba6c4SMuhammad Omair Javaid Status error; 625567ba6c4SMuhammad Omair Javaid 626567ba6c4SMuhammad Omair Javaid error = ReadSVEHeader(); 627567ba6c4SMuhammad Omair Javaid if (error.Fail()) 628567ba6c4SMuhammad Omair Javaid return error; 629567ba6c4SMuhammad Omair Javaid 630567ba6c4SMuhammad Omair Javaid struct iovec ioVec; 631567ba6c4SMuhammad Omair Javaid ioVec.iov_base = GetSVEHeader(); 632567ba6c4SMuhammad Omair Javaid ioVec.iov_len = GetSVEHeaderSize(); 633567ba6c4SMuhammad Omair Javaid 634567ba6c4SMuhammad Omair Javaid m_sve_buffer_is_valid = false; 635567ba6c4SMuhammad Omair Javaid m_sve_header_is_valid = false; 636567ba6c4SMuhammad Omair Javaid m_fpu_is_valid = false; 637567ba6c4SMuhammad Omair Javaid 638567ba6c4SMuhammad Omair Javaid return WriteRegisterSet(&ioVec, GetSVEHeaderSize(), NT_ARM_SVE); 639567ba6c4SMuhammad Omair Javaid } 640567ba6c4SMuhammad Omair Javaid 641567ba6c4SMuhammad Omair Javaid Status NativeRegisterContextLinux_arm64::ReadAllSVE() { 642567ba6c4SMuhammad Omair Javaid Status error; 643567ba6c4SMuhammad Omair Javaid 644567ba6c4SMuhammad Omair Javaid if (m_sve_buffer_is_valid) 645567ba6c4SMuhammad Omair Javaid return error; 646567ba6c4SMuhammad Omair Javaid 647567ba6c4SMuhammad Omair Javaid struct iovec ioVec; 648567ba6c4SMuhammad Omair Javaid ioVec.iov_base = GetSVEBuffer(); 649567ba6c4SMuhammad Omair Javaid ioVec.iov_len = GetSVEBufferSize(); 650567ba6c4SMuhammad Omair Javaid 651567ba6c4SMuhammad Omair Javaid error = ReadRegisterSet(&ioVec, GetSVEBufferSize(), NT_ARM_SVE); 652567ba6c4SMuhammad Omair Javaid 653567ba6c4SMuhammad Omair Javaid if (error.Success()) 654567ba6c4SMuhammad Omair Javaid m_sve_buffer_is_valid = true; 655567ba6c4SMuhammad Omair Javaid 656567ba6c4SMuhammad Omair Javaid return error; 657567ba6c4SMuhammad Omair Javaid } 658567ba6c4SMuhammad Omair Javaid 659567ba6c4SMuhammad Omair Javaid Status NativeRegisterContextLinux_arm64::WriteAllSVE() { 660567ba6c4SMuhammad Omair Javaid Status error; 661567ba6c4SMuhammad Omair Javaid 662567ba6c4SMuhammad Omair Javaid error = ReadAllSVE(); 663567ba6c4SMuhammad Omair Javaid if (error.Fail()) 664567ba6c4SMuhammad Omair Javaid return error; 665567ba6c4SMuhammad Omair Javaid 666567ba6c4SMuhammad Omair Javaid struct iovec ioVec; 667567ba6c4SMuhammad Omair Javaid 668567ba6c4SMuhammad Omair Javaid ioVec.iov_base = GetSVEBuffer(); 669567ba6c4SMuhammad Omair Javaid ioVec.iov_len = GetSVEBufferSize(); 670567ba6c4SMuhammad Omair Javaid 671567ba6c4SMuhammad Omair Javaid m_sve_buffer_is_valid = false; 672567ba6c4SMuhammad Omair Javaid m_sve_header_is_valid = false; 673567ba6c4SMuhammad Omair Javaid m_fpu_is_valid = false; 674567ba6c4SMuhammad Omair Javaid 675567ba6c4SMuhammad Omair Javaid return WriteRegisterSet(&ioVec, GetSVEBufferSize(), NT_ARM_SVE); 676567ba6c4SMuhammad Omair Javaid } 677567ba6c4SMuhammad Omair Javaid 678567ba6c4SMuhammad Omair Javaid void NativeRegisterContextLinux_arm64::ConfigureRegisterContext() { 679567ba6c4SMuhammad Omair Javaid // Read SVE configuration data and configure register infos. 680567ba6c4SMuhammad Omair Javaid if (!m_sve_header_is_valid && m_sve_state != SVEState::Disabled) { 681567ba6c4SMuhammad Omair Javaid Status error = ReadSVEHeader(); 682567ba6c4SMuhammad Omair Javaid if (!error.Success() && m_sve_state == SVEState::Unknown) { 683567ba6c4SMuhammad Omair Javaid m_sve_state = SVEState::Disabled; 684567ba6c4SMuhammad Omair Javaid GetRegisterInfo().ConfigureVectorRegisterInfos( 685567ba6c4SMuhammad Omair Javaid RegisterInfoPOSIX_arm64::eVectorQuadwordAArch64); 686567ba6c4SMuhammad Omair Javaid } else { 687567ba6c4SMuhammad Omair Javaid if ((m_sve_header.flags & SVE_PT_REGS_MASK) == SVE_PT_REGS_FPSIMD) 688567ba6c4SMuhammad Omair Javaid m_sve_state = SVEState::FPSIMD; 689567ba6c4SMuhammad Omair Javaid else if ((m_sve_header.flags & SVE_PT_REGS_MASK) == SVE_PT_REGS_SVE) 690567ba6c4SMuhammad Omair Javaid m_sve_state = SVEState::Full; 691567ba6c4SMuhammad Omair Javaid 692567ba6c4SMuhammad Omair Javaid uint32_t vq = RegisterInfoPOSIX_arm64::eVectorQuadwordAArch64SVE; 693567ba6c4SMuhammad Omair Javaid if (sve_vl_valid(m_sve_header.vl)) 694567ba6c4SMuhammad Omair Javaid vq = sve_vq_from_vl(m_sve_header.vl); 695567ba6c4SMuhammad Omair Javaid GetRegisterInfo().ConfigureVectorRegisterInfos(vq); 696567ba6c4SMuhammad Omair Javaid m_sve_ptrace_payload.resize(SVE_PT_SIZE(vq, SVE_PT_REGS_SVE)); 697567ba6c4SMuhammad Omair Javaid } 698567ba6c4SMuhammad Omair Javaid } 699b6f9d7b8SMuhammad Omair Javaid } 700b6f9d7b8SMuhammad Omair Javaid 701b9c1b51eSKate Stone uint32_t NativeRegisterContextLinux_arm64::CalculateFprOffset( 702b9c1b51eSKate Stone const RegisterInfo *reg_info) const { 7037fa7b81bSMuhammad Omair Javaid return reg_info->byte_offset - GetGPRSize(); 704c40e7b17STamas Berghammer } 705c40e7b17STamas Berghammer 706567ba6c4SMuhammad Omair Javaid uint32_t NativeRegisterContextLinux_arm64::CalculateSVEOffset( 707567ba6c4SMuhammad Omair Javaid const RegisterInfo *reg_info) const { 708567ba6c4SMuhammad Omair Javaid // Start of Z0 data is after GPRs plus 8 bytes of vg register 709567ba6c4SMuhammad Omair Javaid uint32_t sve_reg_offset = LLDB_INVALID_INDEX32; 710567ba6c4SMuhammad Omair Javaid if (m_sve_state == SVEState::FPSIMD) { 711567ba6c4SMuhammad Omair Javaid const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; 712567ba6c4SMuhammad Omair Javaid sve_reg_offset = 713567ba6c4SMuhammad Omair Javaid SVE_PT_FPSIMD_OFFSET + (reg - GetRegisterInfo().GetRegNumSVEZ0()) * 16; 714567ba6c4SMuhammad Omair Javaid } else if (m_sve_state == SVEState::Full) { 715661e4040SMuhammad Omair Javaid uint32_t sve_z0_offset = GetGPRSize() + 16; 716567ba6c4SMuhammad Omair Javaid sve_reg_offset = 717567ba6c4SMuhammad Omair Javaid SVE_SIG_REGS_OFFSET + reg_info->byte_offset - sve_z0_offset; 718567ba6c4SMuhammad Omair Javaid } 719567ba6c4SMuhammad Omair Javaid return sve_reg_offset; 720567ba6c4SMuhammad Omair Javaid } 721567ba6c4SMuhammad Omair Javaid 722567ba6c4SMuhammad Omair Javaid void *NativeRegisterContextLinux_arm64::GetSVEBuffer() { 723567ba6c4SMuhammad Omair Javaid if (m_sve_state == SVEState::FPSIMD) 724567ba6c4SMuhammad Omair Javaid return m_sve_ptrace_payload.data() + SVE_PT_FPSIMD_OFFSET; 725567ba6c4SMuhammad Omair Javaid 726567ba6c4SMuhammad Omair Javaid return m_sve_ptrace_payload.data(); 727567ba6c4SMuhammad Omair Javaid } 728567ba6c4SMuhammad Omair Javaid 7294e8aeb97SMuhammad Omair Javaid std::vector<uint32_t> NativeRegisterContextLinux_arm64::GetExpeditedRegisters( 7304e8aeb97SMuhammad Omair Javaid ExpeditedRegs expType) const { 7314e8aeb97SMuhammad Omair Javaid std::vector<uint32_t> expedited_reg_nums = 7324e8aeb97SMuhammad Omair Javaid NativeRegisterContext::GetExpeditedRegisters(expType); 7334e8aeb97SMuhammad Omair Javaid if (m_sve_state == SVEState::FPSIMD || m_sve_state == SVEState::Full) 7344e8aeb97SMuhammad Omair Javaid expedited_reg_nums.push_back(GetRegisterInfo().GetRegNumSVEVG()); 7354e8aeb97SMuhammad Omair Javaid 7364e8aeb97SMuhammad Omair Javaid return expedited_reg_nums; 7374e8aeb97SMuhammad Omair Javaid } 7384e8aeb97SMuhammad Omair Javaid 739068f8a7eSTamas Berghammer #endif // defined (__arm64__) || defined (__aarch64__) 740