omjavaid updated this revision to Diff 308341.
omjavaid added a comment.
Updated after re-base over D91241 <https://reviews.llvm.org/D91241>
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D82863/new/
https://reviews.llvm.org/D82863
Files:
lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp
lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.h
lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h
lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
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
@@ -1766,6 +1766,19 @@
gdb_thread->PrivateSetRegisterValue(pair.first, 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.
+ 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)
+ reg_ctx_sp->AArch64SVEReconfigure();
+ }
+
thread_sp->SetName(thread_name.empty() ? nullptr : thread_name.c_str());
gdb_thread->SetThreadDispatchQAddr(thread_dispatch_qaddr);
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
@@ -40,6 +40,9 @@
void HardcodeARMRegisters(bool from_scratch);
+ bool UpdateARM64SVERegistersInfos(uint64_t vg, uint32_t &end_reg_offset,
+ std::vector<uint32_t> &invalidate_regs);
+
void CloneFrom(GDBRemoteDynamicRegisterInfoSP process_reginfo);
};
@@ -79,6 +82,8 @@
uint32_t ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind,
uint32_t num) override;
+ bool AArch64SVEReconfigure();
+
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
@@ -213,8 +213,8 @@
for (int i = 0; i < regcount; i++) {
struct RegisterInfo *reginfo =
m_reg_info_sp->GetRegisterInfoAtIndex(i);
- if (reginfo->byte_offset + reginfo->byte_size
- <= buffer_sp->GetByteSize()) {
+ if (reginfo->byte_offset + reginfo->byte_size <=
+ buffer_sp->GetByteSize()) {
m_reg_valid[i] = true;
} else {
m_reg_valid[i] = false;
@@ -343,6 +343,15 @@
if (dst == nullptr)
return false;
+ // Code below is specific to AArch64 target in SVE state
+ // If vector granule (vg) register is being written then thread's
+ // register context reconfiguration is triggered on success.
+ bool do_reconfigure_arm64_sve = false;
+ const ArchSpec &arch = process->GetTarget().GetArchitecture();
+ if (arch.IsValid() && arch.GetTriple().isAArch64())
+ if (strcmp(reg_info->name, "vg") == 0)
+ do_reconfigure_arm64_sve = true;
+
if (data.CopyByteOrderedData(data_offset, // src offset
reg_info->byte_size, // src length
dst, // dst
@@ -362,6 +371,11 @@
{
SetAllRegisterValid(false);
+
+ if (do_reconfigure_arm64_sve &&
+ GetPrimordialRegister(reg_info, gdb_comm))
+ AArch64SVEReconfigure();
+
return true;
}
} else {
@@ -390,6 +404,10 @@
} else {
// This is an actual register, write it
success = SetPrimordialRegister(reg_info, gdb_comm);
+
+ if (success && do_reconfigure_arm64_sve &&
+ GetPrimordialRegister(reg_info, gdb_comm))
+ AArch64SVEReconfigure();
}
// Check if writing this register will invalidate any other register
@@ -655,9 +673,8 @@
if (m_thread.GetProcess().get()) {
const ArchSpec &arch =
m_thread.GetProcess()->GetTarget().GetArchitecture();
- if (arch.IsValid() &&
- (arch.GetMachine() == llvm::Triple::aarch64 ||
- arch.GetMachine() == llvm::Triple::aarch64_32) &&
+ if (arch.IsValid() && (arch.GetMachine() == llvm::Triple::aarch64 ||
+ arch.GetMachine() == llvm::Triple::aarch64_32) &&
arch.GetTriple().getVendor() == llvm::Triple::Apple &&
arch.GetTriple().getOS() == llvm::Triple::IOS) {
arm64_debugserver = true;
@@ -712,6 +729,79 @@
return m_reg_info_sp->ConvertRegisterKindToRegisterNumber(kind, num);
}
+bool GDBRemoteRegisterContext::AArch64SVEReconfigure() {
+ if (!m_reg_info_sp)
+ return false;
+
+ const RegisterInfo *reg_info = m_reg_info_sp->GetRegisterInfo("vg");
+ if (!reg_info)
+ return false;
+
+ 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) {
+ const RegisterInfo *reg_info = m_reg_info_sp->GetRegisterInfo("p0");
+ if (!reg_info || vg_reg_value == reg_info->byte_size)
+ return false;
+
+ uint32_t end_reg_offset = 0;
+ std::vector<uint32_t> invalidate_regs;
+ if (m_reg_info_sp->UpdateARM64SVERegistersInfos(
+ vg_reg_value, end_reg_offset, invalidate_regs)) {
+ uint64_t bytes_to_copy = m_reg_data.GetByteSize();
+ if (end_reg_offset < bytes_to_copy)
+ bytes_to_copy = end_reg_offset;
+
+ // Make a heap based buffer that is big enough to store all registers
+ DataBufferSP reg_data_sp(new DataBufferHeap(end_reg_offset, 0));
+ m_reg_data.CopyData(0, bytes_to_copy, reg_data_sp->GetBytes());
+ m_reg_data.Clear();
+ m_reg_data.SetData(reg_data_sp);
+ m_reg_data.SetByteOrder(GetByteOrder());
+
+ for (auto ® : invalidate_regs)
+ m_reg_valid[reg] = false;
+
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool GDBRemoteDynamicRegisterInfo::UpdateARM64SVERegistersInfos(
+ uint64_t vg, uint32_t &end_reg_offset,
+ std::vector<uint32_t> &invalidate_regs) {
+ // SVE Z register size is vg x 8 bytes.
+ uint32_t z_reg_byte_size = vg * 8;
+
+ for (auto ® : m_regs) {
+ if (reg.value_regs == nullptr) {
+ if (reg.name[0] == 'z' && isdigit(reg.name[1])) {
+ reg.byte_size = z_reg_byte_size;
+ invalidate_regs.push_back(reg.kinds[eRegisterKindLLDB]);
+ } else if (reg.name[0] == 'p' && isdigit(reg.name[1])) {
+ reg.byte_size = vg;
+ invalidate_regs.push_back(reg.kinds[eRegisterKindLLDB]);
+ } else if (strcmp(reg.name, "ffr") == 0) {
+ reg.byte_size = vg;
+ invalidate_regs.push_back(reg.kinds[eRegisterKindLLDB]);
+ }
+ reg.byte_offset = end_reg_offset;
+ end_reg_offset += reg.byte_size;
+ }
+ }
+
+ for (auto ® : m_regs) {
+ if (reg.value_regs != nullptr)
+ reg.byte_offset = GetRegisterInfoAtIndex(reg.value_regs[0])->byte_offset;
+ }
+
+ return true;
+}
+
void GDBRemoteDynamicRegisterInfo::CloneFrom(
GDBRemoteDynamicRegisterInfoSP proc_reginfo) {
m_regs = proc_reginfo->m_regs;
Index: lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.h
===================================================================
--- lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.h
+++ lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.h
@@ -59,6 +59,9 @@
uint32_t ConvertRegisterKindToRegisterNumber(uint32_t kind,
uint32_t num) const;
+ const lldb_private::RegisterInfo *
+ GetRegisterInfo(llvm::StringRef reg_name) const;
+
void Dump() const;
void Clear();
@@ -76,9 +79,6 @@
typedef std::vector<uint8_t> dwarf_opcode;
typedef std::map<uint32_t, dwarf_opcode> dynamic_reg_size_map;
- const lldb_private::RegisterInfo *
- GetRegisterInfo(llvm::StringRef reg_name) const;
-
void MoveFrom(DynamicRegisterInfo &&info);
reg_collection m_regs;
Index: lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp
===================================================================
--- lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp
+++ lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp
@@ -564,6 +564,17 @@
}
}
+ // Check if register info is reconfigurable
+ // AArch64 SVE register set has configurable register sizes
+ if (arch.GetTriple().isAArch64()) {
+ for (const auto ® : m_regs) {
+ if (strcmp(reg.name, "vg") == 0) {
+ m_is_reconfigurable = true;
+ break;
+ }
+ }
+ }
+
if (!generic_regs_specified) {
switch (arch.GetMachine()) {
case llvm::Triple::aarch64:
Index: lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
===================================================================
--- lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
+++ lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
@@ -299,14 +299,31 @@
if (m_sve_state == SVEState::Disabled || m_sve_state == SVEState::Unknown)
return Status("SVE disabled or not supported");
else {
- if (GetRegisterInfo().IsSVERegVG(reg))
- return Status("SVE state change operation not supported");
-
// Target has SVE enabled, we will read and cache SVE ptrace data
error = ReadAllSVE();
if (error.Fail())
return error;
+ if (GetRegisterInfo().IsSVERegVG(reg)) {
+ uint64_t vg_value = reg_value.GetAsUInt64();
+
+ if (sve_vl_valid(vg_value * 8)) {
+ if (m_sve_header_is_valid && vg_value == GetSVERegVG())
+ return error;
+
+ SetSVERegVG(vg_value);
+
+ error = WriteSVEHeader();
+ if (error.Success())
+ ConfigureRegisterContext();
+
+ if (m_sve_header_is_valid && vg_value == GetSVERegVG())
+ return error;
+ }
+
+ return Status("SVE vector length update failed.");
+ }
+
// If target supports SVE but currently in FPSIMD mode.
if (m_sve_state == SVEState::FPSIMD) {
// Here we will check if writing this SVE register enables
_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits