Skip to content

Commit 46b961f

Browse files
committed
[lldb][AArch64] Implement resizing of SME's ZA register
The size of ZA depends on the streaming 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. Reviewed By: omjavaid Differential Revision: https://reviews.llvm.org/D159504
1 parent 61d819d commit 46b961f

File tree

5 files changed

+72
-49
lines changed

5 files changed

+72
-49
lines changed

lldb/include/lldb/Target/DynamicRegisterInfo.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,8 @@ class DynamicRegisterInfo {
9393
return llvm::iterator_range<reg_collection::const_iterator>(m_regs);
9494
}
9595

96+
void ConfigureOffsets();
97+
9698
protected:
9799
// Classes that inherit from DynamicRegisterInfo can see and modify these
98100
typedef std::vector<lldb_private::RegisterSet> set_collection;
@@ -116,8 +118,6 @@ class DynamicRegisterInfo {
116118

117119
void Finalize(const lldb_private::ArchSpec &arch);
118120

119-
void ConfigureOffsets();
120-
121121
reg_collection m_regs;
122122
set_collection m_sets;
123123
set_reg_num_collection m_set_reg_nums;

lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp

Lines changed: 58 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -373,14 +373,14 @@ bool GDBRemoteRegisterContext::WriteRegisterBytes(const RegisterInfo *reg_info,
373373
if (dst == nullptr)
374374
return false;
375375

376-
// Code below is specific to AArch64 target in SVE state
376+
// Code below is specific to AArch64 target in SVE or SME state
377377
// If vector granule (vg) register is being written then thread's
378378
// register context reconfiguration is triggered on success.
379-
bool do_reconfigure_arm64_sve = false;
379+
// We do not allow writes to SVG so it is not mentioned here.
380380
const ArchSpec &arch = process->GetTarget().GetArchitecture();
381-
if (arch.IsValid() && arch.GetTriple().isAArch64())
382-
if (strcmp(reg_info->name, "vg") == 0)
383-
do_reconfigure_arm64_sve = true;
381+
bool do_reconfigure_arm64_sve = arch.IsValid() &&
382+
arch.GetTriple().isAArch64() &&
383+
(strcmp(reg_info->name, "vg") == 0);
384384

385385
if (data.CopyByteOrderedData(data_offset, // src offset
386386
reg_info->byte_size, // src length
@@ -400,10 +400,10 @@ bool GDBRemoteRegisterContext::WriteRegisterBytes(const RegisterInfo *reg_info,
400400
{m_reg_data.GetDataStart(), size_t(m_reg_data.GetByteSize())}))
401401

402402
{
403-
SetAllRegisterValid(false);
404-
405403
if (do_reconfigure_arm64_sve)
406-
AArch64SVEReconfigure();
404+
AArch64Reconfigure();
405+
406+
InvalidateAllRegisters();
407407

408408
return true;
409409
}
@@ -435,8 +435,10 @@ bool GDBRemoteRegisterContext::WriteRegisterBytes(const RegisterInfo *reg_info,
435435
// This is an actual register, write it
436436
success = SetPrimordialRegister(reg_info, gdb_comm);
437437

438-
if (success && do_reconfigure_arm64_sve)
439-
AArch64SVEReconfigure();
438+
if (success && do_reconfigure_arm64_sve) {
439+
AArch64Reconfigure();
440+
InvalidateAllRegisters();
441+
}
440442
}
441443

442444
// Check if writing this register will invalidate any other register
@@ -760,37 +762,47 @@ uint32_t GDBRemoteRegisterContext::ConvertRegisterKindToRegisterNumber(
760762
return m_reg_info_sp->ConvertRegisterKindToRegisterNumber(kind, num);
761763
}
762764

763-
bool GDBRemoteRegisterContext::AArch64SVEReconfigure() {
764-
if (!m_reg_info_sp)
765-
return false;
766-
767-
const RegisterInfo *reg_info = m_reg_info_sp->GetRegisterInfo("vg");
768-
if (!reg_info)
769-
return false;
770-
771-
uint64_t fail_value = LLDB_INVALID_ADDRESS;
772-
uint32_t vg_reg_num = reg_info->kinds[eRegisterKindLLDB];
773-
uint64_t vg_reg_value = ReadRegisterAsUnsigned(vg_reg_num, fail_value);
765+
void GDBRemoteRegisterContext::AArch64Reconfigure() {
766+
assert(m_reg_info_sp);
774767

775-
if (vg_reg_value == fail_value || vg_reg_value > 32)
776-
return false;
777-
778-
reg_info = m_reg_info_sp->GetRegisterInfo("p0");
779-
// Predicate registers have 1 bit per byte in the vector so their size is
780-
// VL / 8. VG is in units of 8 bytes already, so if the size of p0 == VG
781-
// already, we do not have to reconfigure.
782-
if (!reg_info || vg_reg_value == reg_info->byte_size)
783-
return false;
768+
// Once we start to reconfigure registers, we cannot read any of them.
769+
// So we must read VG and SVG up front.
784770

785-
m_reg_info_sp->UpdateARM64SVERegistersInfos(vg_reg_value);
786-
// Make a heap based buffer that is big enough to store all registers
787-
m_reg_data.SetData(std::make_shared<DataBufferHeap>(
788-
m_reg_info_sp->GetRegisterDataByteSize(), 0));
789-
m_reg_data.SetByteOrder(GetByteOrder());
771+
const uint64_t fail_value = LLDB_INVALID_ADDRESS;
772+
std::optional<uint64_t> vg_reg_value;
773+
const RegisterInfo *vg_reg_info = m_reg_info_sp->GetRegisterInfo("vg");
774+
if (vg_reg_info) {
775+
uint32_t vg_reg_num = vg_reg_info->kinds[eRegisterKindLLDB];
776+
uint64_t reg_value = ReadRegisterAsUnsigned(vg_reg_num, fail_value);
777+
if (reg_value != fail_value && reg_value <= 32)
778+
vg_reg_value = reg_value;
779+
}
790780

791-
InvalidateAllRegisters();
781+
std::optional<uint64_t> svg_reg_value;
782+
const RegisterInfo *svg_reg_info = m_reg_info_sp->GetRegisterInfo("svg");
783+
if (svg_reg_info) {
784+
uint32_t svg_reg_num = svg_reg_info->kinds[eRegisterKindLLDB];
785+
uint64_t reg_value = ReadRegisterAsUnsigned(svg_reg_num, fail_value);
786+
if (reg_value != fail_value && reg_value <= 32)
787+
svg_reg_value = reg_value;
788+
}
792789

793-
return true;
790+
if (vg_reg_value)
791+
m_reg_info_sp->UpdateARM64SVERegistersInfos(*vg_reg_value);
792+
if (svg_reg_value)
793+
m_reg_info_sp->UpdateARM64SMERegistersInfos(*svg_reg_value);
794+
795+
// At this point if we have updated any registers, their offsets will all be
796+
// invalid. If we did, we need to update them all.
797+
if (vg_reg_value || svg_reg_value) {
798+
m_reg_info_sp->ConfigureOffsets();
799+
// From here we are able to read registers again.
800+
801+
// Make a heap based buffer that is big enough to store all registers
802+
m_reg_data.SetData(std::make_shared<DataBufferHeap>(
803+
m_reg_info_sp->GetRegisterDataByteSize(), 0));
804+
m_reg_data.SetByteOrder(GetByteOrder());
805+
}
794806
}
795807

796808
void GDBRemoteDynamicRegisterInfo::UpdateARM64SVERegistersInfos(uint64_t vg) {
@@ -811,7 +823,14 @@ void GDBRemoteDynamicRegisterInfo::UpdateARM64SVERegistersInfos(uint64_t vg) {
811823
}
812824
reg.byte_offset = LLDB_INVALID_INDEX32;
813825
}
826+
}
814827

815-
// Re-calculate register offsets
816-
ConfigureOffsets();
828+
void GDBRemoteDynamicRegisterInfo::UpdateARM64SMERegistersInfos(uint64_t svg) {
829+
for (auto &reg : m_regs) {
830+
if (strcmp(reg.name, "za") == 0) {
831+
// ZA is a register with size (svg*8) * (svg*8). A square essentially.
832+
reg.byte_size = (svg * 8) * (svg * 8);
833+
}
834+
reg.byte_offset = LLDB_INVALID_INDEX32;
835+
}
817836
}

lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ class GDBRemoteDynamicRegisterInfo final : public DynamicRegisterInfo {
3939
~GDBRemoteDynamicRegisterInfo() override = default;
4040

4141
void UpdateARM64SVERegistersInfos(uint64_t vg);
42+
void UpdateARM64SMERegistersInfos(uint64_t svg);
4243
};
4344

4445
class GDBRemoteRegisterContext : public RegisterContext {
@@ -77,7 +78,8 @@ class GDBRemoteRegisterContext : public RegisterContext {
7778
uint32_t ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind,
7879
uint32_t num) override;
7980

80-
bool AArch64SVEReconfigure();
81+
// Reconfigure variable sized registers for AArch64 SVE and SME.
82+
void AArch64Reconfigure();
8183

8284
protected:
8385
friend class ThreadGDBRemote;

lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1660,17 +1660,18 @@ ThreadSP ProcessGDBRemote::SetThreadStopInfo(
16601660
gdb_thread->PrivateSetRegisterValue(lldb_regnum, buffer_sp->GetData());
16611661
}
16621662

1663-
// AArch64 SVE specific code below calls AArch64SVEReconfigure to update
1664-
// SVE register sizes and offsets if value of VG register has changed
1665-
// since last stop.
1663+
// AArch64 SVE/SME specific code below updates SVE and ZA register sizes and
1664+
// offsets if value of VG or SVG registers has changed since last stop.
16661665
const ArchSpec &arch = GetTarget().GetArchitecture();
16671666
if (arch.IsValid() && arch.GetTriple().isAArch64()) {
16681667
GDBRemoteRegisterContext *reg_ctx_sp =
16691668
static_cast<GDBRemoteRegisterContext *>(
16701669
gdb_thread->GetRegisterContext().get());
16711670

1672-
if (reg_ctx_sp)
1673-
reg_ctx_sp->AArch64SVEReconfigure();
1671+
if (reg_ctx_sp) {
1672+
reg_ctx_sp->AArch64Reconfigure();
1673+
reg_ctx_sp->InvalidateAllRegisters();
1674+
}
16741675
}
16751676

16761677
thread_sp->SetName(thread_name.empty() ? nullptr : thread_name.c_str());

lldb/source/Target/DynamicRegisterInfo.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -614,10 +614,11 @@ void DynamicRegisterInfo::Finalize(const ArchSpec &arch) {
614614
ConfigureOffsets();
615615

616616
// Check if register info is reconfigurable
617-
// AArch64 SVE register set has configurable register sizes
617+
// AArch64 SVE register set has configurable register sizes, as does the ZA
618+
// register that SME added (the streaming state of SME reuses the SVE state).
618619
if (arch.GetTriple().isAArch64()) {
619620
for (const auto &reg : m_regs) {
620-
if (strcmp(reg.name, "vg") == 0) {
621+
if ((strcmp(reg.name, "vg") == 0) || (strcmp(reg.name, "svg") == 0)) {
621622
m_is_reconfigurable = true;
622623
break;
623624
}

0 commit comments

Comments
 (0)