DavidSpickett created this revision. Herald added subscribers: ctetreau, kristof.beyls. Herald added a project: All. DavidSpickett requested review of this revision. Herald added a project: LLDB. Herald added a subscriber: lldb-commits.
The size of ZA depends on the streamnig vector length regardless of the active mode. So in addition to vg (which reports the active mode) we must send the client svg. Otherwise the mechanics are the same as for non-streaming SVE. Use the svg value to update the defined size of ZA, accounting for the fact that ZA is not a single vector but a suqare matrix. So if svg is 8, a single streaming vector would be 8*8 = 64 bytes. ZA is that squared, so 64*64 = 4096 bytes. Testing is included in a later patch. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D159504 Files: lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp lldb/source/Target/DynamicRegisterInfo.cpp
Index: lldb/source/Target/DynamicRegisterInfo.cpp =================================================================== --- lldb/source/Target/DynamicRegisterInfo.cpp +++ lldb/source/Target/DynamicRegisterInfo.cpp @@ -614,10 +614,11 @@ ConfigureOffsets(); // Check if register info is reconfigurable - // AArch64 SVE register set has configurable register sizes + // AArch64 SVE register set has configurable register sizes, as does the ZA + // register that SME added (the streaming state of SME reuses the SVE state). if (arch.GetTriple().isAArch64()) { for (const auto ® : m_regs) { - if (strcmp(reg.name, "vg") == 0) { + if ((strcmp(reg.name, "vg") == 0) || (strcmp(reg.name, "svg") == 0)) { m_is_reconfigurable = true; break; } Index: lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp =================================================================== --- lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -1660,17 +1660,19 @@ gdb_thread->PrivateSetRegisterValue(lldb_regnum, buffer_sp->GetData()); } - // AArch64 SVE specific code below calls AArch64SVEReconfigure to update - // SVE register sizes and offsets if value of VG register has changed - // since last stop. + // AArch64 SVE/SME specific code below updates SVE and ZA register sizes and + // offsets if value of VG or SVG registers has changed since last stop. const ArchSpec &arch = GetTarget().GetArchitecture(); if (arch.IsValid() && arch.GetTriple().isAArch64()) { GDBRemoteRegisterContext *reg_ctx_sp = static_cast<GDBRemoteRegisterContext *>( gdb_thread->GetRegisterContext().get()); - if (reg_ctx_sp) + if (reg_ctx_sp) { reg_ctx_sp->AArch64SVEReconfigure(); + reg_ctx_sp->AArch64SMEReconfigure(); + reg_ctx_sp->InvalidateAllRegisters(); + } } thread_sp->SetName(thread_name.empty() ? nullptr : thread_name.c_str()); Index: lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h =================================================================== --- lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h +++ lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h @@ -39,6 +39,7 @@ ~GDBRemoteDynamicRegisterInfo() override = default; void UpdateARM64SVERegistersInfos(uint64_t vg); + void UpdateARM64SMERegistersInfos(uint64_t vg); }; class GDBRemoteRegisterContext : public RegisterContext { @@ -77,7 +78,9 @@ uint32_t ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num) override; - bool AArch64SVEReconfigure(); + void AArch64SVEReconfigure(); + + void AArch64SMEReconfigure(); protected: friend class ThreadGDBRemote; Index: lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp =================================================================== --- lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp +++ lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp @@ -373,14 +373,14 @@ if (dst == nullptr) return false; - // Code below is specific to AArch64 target in SVE state + // Code below is specific to AArch64 target in SVE or SMEstate // If vector granule (vg) register is being written then thread's // register context reconfiguration is triggered on success. - bool do_reconfigure_arm64_sve = false; + // We do not allow writes to SVG so it is not mentioned here. const ArchSpec &arch = process->GetTarget().GetArchitecture(); - if (arch.IsValid() && arch.GetTriple().isAArch64()) - if (strcmp(reg_info->name, "vg") == 0) - do_reconfigure_arm64_sve = true; + bool do_reconfigure_arm64_sve = arch.IsValid() && + arch.GetTriple().isAArch64() && + (strcmp(reg_info->name, "vg") == 0); if (data.CopyByteOrderedData(data_offset, // src offset reg_info->byte_size, // src length @@ -400,10 +400,12 @@ {m_reg_data.GetDataStart(), size_t(m_reg_data.GetByteSize())})) { - SetAllRegisterValid(false); - - if (do_reconfigure_arm64_sve) + if (do_reconfigure_arm64_sve) { AArch64SVEReconfigure(); + AArch64SMEReconfigure(); + } + + InvalidateAllRegisters(); return true; } @@ -435,8 +437,11 @@ // This is an actual register, write it success = SetPrimordialRegister(reg_info, gdb_comm); - if (success && do_reconfigure_arm64_sve) + if (success && do_reconfigure_arm64_sve) { AArch64SVEReconfigure(); + AArch64SMEReconfigure(); + InvalidateAllRegisters(); + } } // Check if writing this register will invalidate any other register @@ -760,37 +765,52 @@ return m_reg_info_sp->ConvertRegisterKindToRegisterNumber(kind, num); } -bool GDBRemoteRegisterContext::AArch64SVEReconfigure() { - if (!m_reg_info_sp) - return false; - +void GDBRemoteRegisterContext::AArch64SVEReconfigure() { + assert(m_reg_info_sp); const RegisterInfo *reg_info = m_reg_info_sp->GetRegisterInfo("vg"); if (!reg_info) - return false; + return; uint64_t fail_value = LLDB_INVALID_ADDRESS; uint32_t vg_reg_num = reg_info->kinds[eRegisterKindLLDB]; uint64_t vg_reg_value = ReadRegisterAsUnsigned(vg_reg_num, fail_value); if (vg_reg_value == fail_value || vg_reg_value > 32) - return false; + return; reg_info = m_reg_info_sp->GetRegisterInfo("p0"); // Predicate registers have 1 bit per byte in the vector so their size is // VL / 8. VG is in units of 8 bytes already, so if the size of p0 == VG // already, we do not have to reconfigure. if (!reg_info || vg_reg_value == reg_info->byte_size) - return false; + return; m_reg_info_sp->UpdateARM64SVERegistersInfos(vg_reg_value); // Make a heap based buffer that is big enough to store all registers m_reg_data.SetData(std::make_shared<DataBufferHeap>( m_reg_info_sp->GetRegisterDataByteSize(), 0)); m_reg_data.SetByteOrder(GetByteOrder()); +} - InvalidateAllRegisters(); +void GDBRemoteRegisterContext::AArch64SMEReconfigure() { + assert(m_reg_info_sp); + const RegisterInfo *reg_info = m_reg_info_sp->GetRegisterInfo("svg"); + // Target does not have SME, nothing for us to reconfigure. + if (!reg_info) + return; - return true; + uint64_t fail_value = LLDB_INVALID_ADDRESS; + uint32_t svg_reg_num = reg_info->kinds[eRegisterKindLLDB]; + uint64_t svg_reg_value = ReadRegisterAsUnsigned(svg_reg_num, fail_value); + + if (svg_reg_value == LLDB_INVALID_ADDRESS || svg_reg_value > 32) + return; + + m_reg_info_sp->UpdateARM64SMERegistersInfos(svg_reg_value); + // Make a heap based buffer that is big enough to store all registers + m_reg_data.SetData(std::make_shared<DataBufferHeap>( + m_reg_info_sp->GetRegisterDataByteSize(), 0)); + m_reg_data.SetByteOrder(GetByteOrder()); } void GDBRemoteDynamicRegisterInfo::UpdateARM64SVERegistersInfos(uint64_t vg) { @@ -815,3 +835,15 @@ // Re-calculate register offsets ConfigureOffsets(); } + +void GDBRemoteDynamicRegisterInfo::UpdateARM64SMERegistersInfos(uint64_t svg) { + for (auto ® : m_regs) { + if (strcmp(reg.name, "za") == 0) { + // ZA is a register with size (svg*8) * (svg*8). A square essentially. + reg.byte_size = (svg * 8) * (svg * 8); + } + reg.byte_offset = LLDB_INVALID_INDEX32; + } + + ConfigureOffsets(); +}
_______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits