Author: David Spickett
Date: 2023-09-19T11:18:27Z
New Revision: a0768b8237ad83a6493a5053e615e0c38d7410ee

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

LOG: [lldb][AArch64] Add SME streaming vector length pseduo register

This adds a register "svg" which mirrors SVE's "vg" register.
This reports the streaming vector length at all times, read
from the ZA ptrace header.

This register is needed first to implement ZA resizing as
the streaming vector length changes. Like vg, svg will be
expedited to the client so it can reconfigure its register
definitions.

The other use is for users to be able to know the streaming
vector length without resorting to counting the (many, many)
bytes in ZA, or temporarily entering streaming mode (which
would be destructive).

Some refactoring has been done so we don't have to recalculate the
register offsets twice.

Testing for this will come in a later patch.

Reviewed By: omjavaid

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

Added: 
    

Modified: 
    lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
    lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h
    lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.cpp
    lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h

Removed: 
    


################################################################################
diff  --git 
a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp 
b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
index 8d743a4ff83d22e..7d246eeb5fc9b7e 100644
--- a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
+++ b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
@@ -147,6 +147,7 @@ 
NativeRegisterContextLinux_arm64::NativeRegisterContextLinux_arm64(
   ::memset(&m_sve_header, 0, sizeof(m_sve_header));
   ::memset(&m_pac_mask, 0, sizeof(m_pac_mask));
   ::memset(&m_tls_regs, 0, sizeof(m_tls_regs));
+  ::memset(&m_sme_pseudo_regs, 0, sizeof(m_sme_pseudo_regs));
 
   m_mte_ctrl_reg = 0;
 
@@ -329,30 +330,40 @@ NativeRegisterContextLinux_arm64::ReadRegister(const 
RegisterInfo *reg_info,
     assert(offset < GetMTEControlSize());
     src = (uint8_t *)GetMTEControl() + offset;
   } else if (IsSME(reg)) {
-    error = ReadZAHeader();
-    if (error.Fail())
-      return error;
+    if (GetRegisterInfo().IsSMERegZA(reg)) {
+      error = ReadZAHeader();
+      if (error.Fail())
+        return error;
 
-    // If there is only a header and no registers, ZA is inactive. Read as 0
-    // in this case.
-    if (m_za_header.size == sizeof(m_za_header)) {
-      // This will get reconfigured/reset later, so we are safe to use it.
-      // ZA is a square of VL * VL and the ptrace buffer also includes the
-      // header itself.
-      m_za_ptrace_payload.resize(((m_za_header.vl) * (m_za_header.vl)) +
-                                 GetZAHeaderSize());
-      std::fill(m_za_ptrace_payload.begin(), m_za_ptrace_payload.end(), 0);
+      // If there is only a header and no registers, ZA is inactive. Read as 0
+      // in this case.
+      if (m_za_header.size == sizeof(m_za_header)) {
+        // This will get reconfigured/reset later, so we are safe to use it.
+        // ZA is a square of VL * VL and the ptrace buffer also includes the
+        // header itself.
+        m_za_ptrace_payload.resize(((m_za_header.vl) * (m_za_header.vl)) +
+                                   GetZAHeaderSize());
+        std::fill(m_za_ptrace_payload.begin(), m_za_ptrace_payload.end(), 0);
+      } else {
+        // ZA is active, read the real register.
+        error = ReadZA();
+        if (error.Fail())
+          return error;
+      }
+
+      // ZA is part of the SME set but uses a seperate member buffer for
+      // storage. Therefore its effective byte offset is always 0 even if it
+      // isn't 0 within the SME register set.
+      src = (uint8_t *)GetZABuffer() + GetZAHeaderSize();
     } else {
-      // ZA is active, read the real register.
-      error = ReadZA();
+      error = ReadSMESVG();
       if (error.Fail())
         return error;
-    }
 
-    // ZA is part of the SME set but uses a seperate member buffer for storage.
-    // Therefore its effective byte offset is always 0 even if it isn't 0 
within
-    // the SME register set.
-    src = (uint8_t *)GetZABuffer() + GetZAHeaderSize();
+      offset = reg_info->byte_offset - GetRegisterInfo().GetSMEOffset();
+      assert(offset < GetSMEPseudoBufferSize());
+      src = (uint8_t *)GetSMEPseudoBuffer() + offset;
+    }
   } else
     return Status("failed - register wasn't recognized to be a GPR or an FPR, "
                   "write strategy unknown");
@@ -538,6 +549,9 @@ Status NativeRegisterContextLinux_arm64::WriteRegister(
 
     return WriteTLS();
   } else if (IsSME(reg)) {
+    if (!GetRegisterInfo().IsSMERegZA(reg))
+      return Status("Writing to SVG is not supported.");
+
     error = ReadZA();
     if (error.Fail())
       return error;
@@ -1357,6 +1371,16 @@ uint32_t 
NativeRegisterContextLinux_arm64::CalculateSVEOffset(
   return sve_reg_offset;
 }
 
+Status NativeRegisterContextLinux_arm64::ReadSMESVG() {
+  // This register is the streaming vector length, so we will get it from
+  // NT_ARM_ZA regardless of the current streaming mode.
+  Status error = ReadZAHeader();
+  if (error.Success())
+    m_sme_pseudo_regs.svg_reg = m_za_header.vl / 8;
+
+  return error;
+}
+
 std::vector<uint32_t> NativeRegisterContextLinux_arm64::GetExpeditedRegisters(
     ExpeditedRegs expType) const {
   std::vector<uint32_t> expedited_reg_nums =
@@ -1364,6 +1388,10 @@ std::vector<uint32_t> 
NativeRegisterContextLinux_arm64::GetExpeditedRegisters(
   // SVE, non-streaming vector length.
   if (m_sve_state == SVEState::FPSIMD || m_sve_state == SVEState::Full)
     expedited_reg_nums.push_back(GetRegisterInfo().GetRegNumSVEVG());
+  // SME, streaming vector length. This is used by the ZA register which is
+  // present even when streaming mode is not enabled.
+  if (GetRegisterInfo().IsSSVEEnabled())
+    expedited_reg_nums.push_back(GetRegisterInfo().GetRegNumSMESVG());
 
   return expedited_reg_nums;
 }

diff  --git 
a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h 
b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h
index 2d351390ec0bd30..20e262fcd0f3dc9 100644
--- a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h
+++ b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h
@@ -114,6 +114,12 @@ class NativeRegisterContextLinux_arm64
 
   uint64_t m_mte_ctrl_reg;
 
+  struct sme_pseudo_regs {
+    uint64_t svg_reg;
+  };
+
+  struct sme_pseudo_regs m_sme_pseudo_regs;
+
   struct tls_regs {
     uint64_t tpidr_reg;
     // Only valid when SME is present.
@@ -144,6 +150,8 @@ class NativeRegisterContextLinux_arm64
 
   Status WriteTLS();
 
+  Status ReadSMESVG();
+
   Status ReadZAHeader();
 
   Status ReadZA();
@@ -176,6 +184,8 @@ class NativeRegisterContextLinux_arm64
 
   void *GetTLSBuffer() { return &m_tls_regs; }
 
+  void *GetSMEPseudoBuffer() { return &m_sme_pseudo_regs; }
+
   void *GetSVEBuffer() { return m_sve_ptrace_payload.data(); }
 
   size_t GetSVEHeaderSize() { return sizeof(m_sve_header); }
@@ -194,6 +204,8 @@ class NativeRegisterContextLinux_arm64
 
   size_t GetTLSBufferSize() { return m_tls_size; }
 
+  size_t GetSMEPseudoBufferSize() { return sizeof(m_sme_pseudo_regs); }
+
   llvm::Error ReadHardwareDebugInfo() override;
 
   llvm::Error WriteHardwareDebugRegs(DREGType hwbType) override;

diff  --git a/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.cpp 
b/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.cpp
index 6d32b772afeead5..8b23f17ca573fff 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.cpp
+++ b/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.cpp
@@ -83,10 +83,11 @@ static lldb_private::RegisterInfo g_register_infos_tls[] = {
     // Only present when SME is present
     DEFINE_EXTENSION_REG(tpidr2)};
 
-static lldb_private::RegisterInfo g_register_infos_sme[] =
+static lldb_private::RegisterInfo g_register_infos_sme[] = {
+    DEFINE_EXTENSION_REG(svg),
     // 16 is a default size we will change later.
-    {{"za", nullptr, 16, 0, lldb::eEncodingVector, lldb::eFormatVectorOfUInt8,
-      KIND_ALL_INVALID, nullptr, nullptr, nullptr}};
+    {"za", nullptr, 16, 0, lldb::eEncodingVector, lldb::eFormatVectorOfUInt8,
+     KIND_ALL_INVALID, nullptr, nullptr, nullptr}};
 
 // Number of register sets provided by this context.
 enum {
@@ -96,7 +97,7 @@ enum {
   k_num_mte_register = 1,
   // Number of TLS registers is dynamic so it is not listed here.
   k_num_pauth_register = 2,
-  k_num_sme_register = 1,
+  k_num_sme_register = 2,
   k_num_register_sets_default = 2,
   k_num_register_sets = 3
 };
@@ -448,7 +449,7 @@ void 
RegisterInfoPOSIX_arm64::ConfigureVectorLengthZA(uint32_t za_vq) {
   // dynamic set and is just 1 register so we make an exception to const here.
   lldb_private::RegisterInfo *non_const_reginfo =
       const_cast<lldb_private::RegisterInfo *>(m_register_info_p);
-  non_const_reginfo[m_sme_regnum_collection[0]].byte_size =
+  non_const_reginfo[m_sme_regnum_collection[1]].byte_size =
       (za_vq * 16) * (za_vq * 16);
 }
 
@@ -471,6 +472,10 @@ bool RegisterInfoPOSIX_arm64::IsSVERegVG(unsigned reg) 
const {
   return sve_vg == reg;
 }
 
+bool RegisterInfoPOSIX_arm64::IsSMERegZA(unsigned reg) const {
+  return reg == m_sme_regnum_collection[1];
+}
+
 bool RegisterInfoPOSIX_arm64::IsPAuthReg(unsigned reg) const {
   return llvm::is_contained(pauth_regnum_collection, reg);
 }
@@ -497,6 +502,10 @@ uint32_t RegisterInfoPOSIX_arm64::GetRegNumFPSR() const { 
return fpu_fpsr; }
 
 uint32_t RegisterInfoPOSIX_arm64::GetRegNumSVEVG() const { return sve_vg; }
 
+uint32_t RegisterInfoPOSIX_arm64::GetRegNumSMESVG() const {
+  return m_sme_regnum_collection[0];
+}
+
 uint32_t RegisterInfoPOSIX_arm64::GetPAuthOffset() const {
   return m_register_info_p[pauth_regnum_collection[0]].byte_offset;
 }

diff  --git a/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h 
b/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h
index 06961987e488533..debdf4c76abc25b 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h
+++ b/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h
@@ -135,12 +135,14 @@ class RegisterInfoPOSIX_arm64
   bool IsMTEReg(unsigned reg) const;
   bool IsTLSReg(unsigned reg) const;
   bool IsSMEReg(unsigned reg) const;
+  bool IsSMERegZA(unsigned reg) const;
 
   uint32_t GetRegNumSVEZ0() const;
   uint32_t GetRegNumSVEFFR() const;
   uint32_t GetRegNumFPCR() const;
   uint32_t GetRegNumFPSR() const;
   uint32_t GetRegNumSVEVG() const;
+  uint32_t GetRegNumSMESVG() const;
   uint32_t GetPAuthOffset() const;
   uint32_t GetMTEOffset() const;
   uint32_t GetTLSOffset() const;


        
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to