[llvm-branch-commits] [lldb] e448ad7 - [LLDB] Add support to resize SVE registers at run-time

Muhammad Omair Javaid via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Tue Jan 19 02:06:04 PST 2021


Author: Muhammad Omair Javaid
Date: 2021-01-19T15:01:32+05:00
New Revision: e448ad787e16119f8db8cc6999896e678a0356ac

URL: https://github.com/llvm/llvm-project/commit/e448ad787e16119f8db8cc6999896e678a0356ac
DIFF: https://github.com/llvm/llvm-project/commit/e448ad787e16119f8db8cc6999896e678a0356ac.diff

LOG: [LLDB] Add support to resize SVE registers at run-time

This patch builds on previously submitted SVE patches regarding expedited
register set and per thread register infos. (D82853 D82855 and D82857)

We need to resize SVE register based on value received in expedited list.
Also we need to resize SVE registers when we write vg register using
register write vg command. The resize will result in a updated offset
for all of fpr and sve register set. This offset will be configured
in native register context by RegisterInfoInterface and will also be
be updated on client side in GDBRemoteRegisterContext.

A follow up patch will provide a API test to verify this change.

Reviewed By: labath

Differential Revision: https://reviews.llvm.org/D82863

Added: 
    

Modified: 
    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

Removed: 
    


################################################################################
diff  --git a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
index 6b2dd25ba44d..c34afe65d47a 100644
--- a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
+++ b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
@@ -299,14 +299,31 @@ Status NativeRegisterContextLinux_arm64::WriteRegister(
     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

diff  --git a/lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp b/lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp
index 8b85c7805f5b..5463a071503c 100644
--- a/lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp
+++ b/lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp
@@ -617,6 +617,17 @@ void DynamicRegisterInfo::Finalize(const ArchSpec &arch) {
   // targets supporting dynamic offset calculation. It also calculates
   // total byte size of register data.
   ConfigureOffsets();
+
+  // Check if register info is reconfigurable
+  // AArch64 SVE register set has configurable register sizes
+  if (arch.GetTriple().isAArch64()) {
+    for (const auto &reg : m_regs) {
+      if (strcmp(reg.name, "vg") == 0) {
+        m_is_reconfigurable = true;
+        break;
+      }
+    }
+  }
 }
 
 void DynamicRegisterInfo::ConfigureOffsets() {

diff  --git a/lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.h b/lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.h
index 31d040e2e137..fbf9db685b71 100644
--- a/lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.h
+++ b/lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.h
@@ -66,6 +66,9 @@ class DynamicRegisterInfo {
 
   bool IsReconfigurable();
 
+  const lldb_private::RegisterInfo *
+  GetRegisterInfo(llvm::StringRef reg_name) const;
+
 protected:
   // Classes that inherit from DynamicRegisterInfo can see and modify these
   typedef std::vector<lldb_private::RegisterInfo> reg_collection;
@@ -77,9 +80,6 @@ class DynamicRegisterInfo {
   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);
 
   void ConfigureOffsets();

diff  --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
index 19bcac5dc4b7..10006616b0c6 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
@@ -214,8 +214,8 @@ bool GDBRemoteRegisterContext::ReadRegisterBytes(const RegisterInfo *reg_info,
           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;
@@ -344,6 +344,15 @@ bool GDBRemoteRegisterContext::WriteRegisterBytes(const RegisterInfo *reg_info,
   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
@@ -363,6 +372,10 @@ bool GDBRemoteRegisterContext::WriteRegisterBytes(const RegisterInfo *reg_info,
 
         {
           SetAllRegisterValid(false);
+
+          if (do_reconfigure_arm64_sve)
+            AArch64SVEReconfigure();
+
           return true;
         }
       } else {
@@ -391,6 +404,9 @@ bool GDBRemoteRegisterContext::WriteRegisterBytes(const RegisterInfo *reg_info,
         } else {
           // This is an actual register, write it
           success = SetPrimordialRegister(reg_info, gdb_comm);
+
+          if (success && do_reconfigure_arm64_sve)
+            AArch64SVEReconfigure();
         }
 
         // Check if writing this register will invalidate any other register
@@ -656,9 +672,8 @@ bool GDBRemoteRegisterContext::WriteAllRegisterValues(
       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;
@@ -713,6 +728,62 @@ uint32_t GDBRemoteRegisterContext::ConvertRegisterKindToRegisterNumber(
   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;
+
+    if (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();
+
+      return true;
+    }
+  }
+
+  return false;
+}
+
+bool GDBRemoteDynamicRegisterInfo::UpdateARM64SVERegistersInfos(uint64_t vg) {
+  // SVE Z register size is vg x 8 bytes.
+  uint32_t z_reg_byte_size = vg * 8;
+
+  // SVE vector length has changed, accordingly set size of Z, P and FFR
+  // registers. Also invalidate register offsets it will be recalculated
+  // after SVE register size update.
+  for (auto &reg : m_regs) {
+    if (reg.value_regs == nullptr) {
+      if (reg.name[0] == 'z' && isdigit(reg.name[1]))
+        reg.byte_size = z_reg_byte_size;
+      else if (reg.name[0] == 'p' && isdigit(reg.name[1]))
+        reg.byte_size = vg;
+      else if (strcmp(reg.name, "ffr") == 0)
+        reg.byte_size = vg;
+    }
+    reg.byte_offset = LLDB_INVALID_INDEX32;
+  }
+
+  // Re-calculate register offsets
+  ConfigureOffsets();
+  return true;
+}
+
 void GDBRemoteDynamicRegisterInfo::HardcodeARMRegisters(bool from_scratch) {
   // For Advanced SIMD and VFP register mapping.
   static uint32_t g_d0_regs[] = {26, 27, LLDB_INVALID_REGNUM};  // (s0, s1)

diff  --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h
index 475e65a54001..252d7b359ee8 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h
@@ -39,6 +39,7 @@ class GDBRemoteDynamicRegisterInfo final : public DynamicRegisterInfo {
   ~GDBRemoteDynamicRegisterInfo() override = default;
 
   void HardcodeARMRegisters(bool from_scratch);
+  bool UpdateARM64SVERegistersInfos(uint64_t vg);
 };
 
 class GDBRemoteRegisterContext : public RegisterContext {
@@ -77,6 +78,8 @@ class GDBRemoteRegisterContext : public RegisterContext {
   uint32_t ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind,
                                                uint32_t num) override;
 
+  bool AArch64SVEReconfigure();
+
 protected:
   friend class ThreadGDBRemote;
 

diff  --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
index f9b0632dcd8b..89a85977ad5c 100644
--- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
@@ -1763,6 +1763,19 @@ ThreadSP ProcessGDBRemote::SetThreadStopInfo(
         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);


        


More information about the llvm-branch-commits mailing list