DavidSpickett updated this revision to Diff 541540.
DavidSpickett added a comment.

Rebase, fix typo.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D154927/new/

https://reviews.llvm.org/D154927

Files:
  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
  
lldb/test/API/commands/register/register/aarch64_sve_registers/rw_access_static_config/TestSVERegisters.py

Index: lldb/test/API/commands/register/register/aarch64_sve_registers/rw_access_static_config/TestSVERegisters.py
===================================================================
--- lldb/test/API/commands/register/register/aarch64_sve_registers/rw_access_static_config/TestSVERegisters.py
+++ lldb/test/API/commands/register/register/aarch64_sve_registers/rw_access_static_config/TestSVERegisters.py
@@ -22,7 +22,12 @@
             reg_value.GetByteSize(), expected, 'Verify "%s" == %i' % (name, expected)
         )
 
-    def check_sve_regs_read(self, z_reg_size):
+    def check_sve_regs_read(self, z_reg_size, expected_mode):
+        if self.isAArch64SME():
+            expected_value = "1" if expected_mode == Mode.SSVE else "0"
+            self.expect("register read svcr", substrs=[
+                "0x000000000000000" + expected_value])
+
         p_reg_size = int(z_reg_size / 8)
 
         for i in range(32):
@@ -162,7 +167,7 @@
 
         vg_reg_value = sve_registers.GetChildMemberWithName("vg").GetValueAsUnsigned()
         z_reg_size = vg_reg_value * 8
-        self.check_sve_regs_read(z_reg_size)
+        self.check_sve_regs_read(z_reg_size, start_mode)
 
         # Evaluate simple expression and print function expr_eval_func address.
         self.expect("expression expr_eval_func", substrs=["= 0x"])
@@ -174,7 +179,7 @@
 
         # We called a jitted function above which must not have changed SVE
         # vector length or register values.
-        self.check_sve_regs_read(z_reg_size)
+        self.check_sve_regs_read(z_reg_size, start_mode)
 
         self.check_sve_regs_read_after_write(z_reg_size)
 
Index: lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h
===================================================================
--- lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h
+++ lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h
@@ -106,6 +106,8 @@
 
   void AddRegSetTLS();
 
+  void AddRegSetSME();
+
   uint32_t ConfigureVectorLength(uint32_t sve_vq);
 
   bool VectorSizeIsValid(uint32_t vq) {
@@ -127,6 +129,7 @@
   bool IsPAuthReg(unsigned reg) const;
   bool IsMTEReg(unsigned reg) const;
   bool IsTLSReg(unsigned reg) const;
+  bool IsSMEReg(unsigned reg) const;
 
   uint32_t GetRegNumSVEZ0() const;
   uint32_t GetRegNumSVEFFR() const;
@@ -136,6 +139,7 @@
   uint32_t GetPAuthOffset() const;
   uint32_t GetMTEOffset() const;
   uint32_t GetTLSOffset() const;
+  uint32_t GetSMEOffset() const;
 
 private:
   typedef std::map<uint32_t, std::vector<lldb_private::RegisterInfo>>
@@ -163,6 +167,7 @@
   std::vector<uint32_t> pauth_regnum_collection;
   std::vector<uint32_t> m_mte_regnum_collection;
   std::vector<uint32_t> m_tls_regnum_collection;
+  std::vector<uint32_t> m_sme_regnum_collection;
 };
 
 #endif
Index: lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.cpp
===================================================================
--- lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.cpp
+++ lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.cpp
@@ -81,6 +81,9 @@
 static lldb_private::RegisterInfo g_register_infos_tls[] = {
     DEFINE_EXTENSION_REG(tpidr)};
 
+static lldb_private::RegisterInfo g_register_infos_sme[] = {
+    DEFINE_EXTENSION_REG(svcr)};
+
 // Number of register sets provided by this context.
 enum {
   k_num_gpr_registers = gpr_w28 - gpr_x0 + 1,
@@ -89,6 +92,7 @@
   k_num_mte_register = 1,
   k_num_tls_register = 1,
   k_num_pauth_register = 2,
+  k_num_sme_register = 1,
   k_num_register_sets_default = 2,
   k_num_register_sets = 3
 };
@@ -196,6 +200,9 @@
 static const lldb_private::RegisterSet g_reg_set_tls_arm64 = {
     "Thread Local Storage Registers", "tls", k_num_tls_register, nullptr};
 
+static const lldb_private::RegisterSet g_reg_set_sme_arm64 = {
+    "Scalable Matrix Extension Registers", "sme", k_num_sme_register, nullptr};
+
 RegisterInfoPOSIX_arm64::RegisterInfoPOSIX_arm64(
     const lldb_private::ArchSpec &target_arch, lldb_private::Flags opt_regsets)
     : lldb_private::RegisterInfoAndSetInterface(target_arch),
@@ -240,6 +247,9 @@
       // done as a dynamic set.
       AddRegSetTLS();
 
+      if (m_opt_regsets.AllSet(eRegsetMaskSSVE))
+        AddRegSetSME();
+
       m_register_info_count = m_dynamic_reg_infos.size();
       m_register_info_p = m_dynamic_reg_infos.data();
       m_register_set_p = m_dynamic_reg_sets.data();
@@ -338,6 +348,21 @@
   m_dynamic_reg_sets.back().registers = m_tls_regnum_collection.data();
 }
 
+void RegisterInfoPOSIX_arm64::AddRegSetSME() {
+  uint32_t sme_regnum = m_dynamic_reg_infos.size();
+  m_sme_regnum_collection.push_back(sme_regnum);
+  m_dynamic_reg_infos.push_back(g_register_infos_sme[0]);
+  m_dynamic_reg_infos[sme_regnum].byte_offset =
+      m_dynamic_reg_infos[sme_regnum - 1].byte_offset +
+      m_dynamic_reg_infos[sme_regnum - 1].byte_size;
+  m_dynamic_reg_infos[sme_regnum].kinds[lldb::eRegisterKindLLDB] = sme_regnum;
+
+  m_per_regset_regnum_range[m_register_set_count] =
+      std::make_pair(sme_regnum, sme_regnum + 1);
+  m_dynamic_reg_sets.push_back(g_reg_set_sme_arm64);
+  m_dynamic_reg_sets.back().registers = m_sme_regnum_collection.data();
+}
+
 uint32_t RegisterInfoPOSIX_arm64::ConfigureVectorLength(uint32_t sve_vq) {
   // sve_vq contains SVE Quad vector length in context of AArch64 SVE.
   // SVE register infos if enabled cannot be disabled by selecting sve_vq = 0.
@@ -433,6 +458,10 @@
   return llvm::is_contained(m_tls_regnum_collection, reg);
 }
 
+bool RegisterInfoPOSIX_arm64::IsSMEReg(unsigned reg) const {
+  return llvm::is_contained(m_sme_regnum_collection, reg);
+}
+
 uint32_t RegisterInfoPOSIX_arm64::GetRegNumSVEZ0() const { return sve_z0; }
 
 uint32_t RegisterInfoPOSIX_arm64::GetRegNumSVEFFR() const { return sve_ffr; }
@@ -454,3 +483,7 @@
 uint32_t RegisterInfoPOSIX_arm64::GetTLSOffset() const {
   return m_register_info_p[m_tls_regnum_collection[0]].byte_offset;
 }
+
+uint32_t RegisterInfoPOSIX_arm64::GetSMEOffset() const {
+  return m_register_info_p[m_sme_regnum_collection[0]].byte_offset;
+}
Index: lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h
===================================================================
--- lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h
+++ lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h
@@ -107,6 +107,7 @@
   struct user_pac_mask m_pac_mask;
 
   uint64_t m_mte_ctrl_reg;
+  uint64_t m_sme_ctrl_reg;
 
   uint64_t m_tls_tpidr_reg;
 
@@ -132,10 +133,14 @@
 
   Status WriteTLSTPIDR();
 
+  // SVCR is a pseudo register and we do not allow writes to it.
+  Status ReadSMEControl();
+
   bool IsSVE(unsigned reg) const;
   bool IsPAuth(unsigned reg) const;
   bool IsMTE(unsigned reg) const;
   bool IsTLS(unsigned reg) const;
+  bool IsSME(unsigned reg) const;
 
   uint64_t GetSVERegVG() { return m_sve_header.vl / 8; }
 
@@ -163,6 +168,10 @@
 
   size_t GetTLSTPIDRSize() { return sizeof(m_tls_tpidr_reg); }
 
+  void *GetSMEControl() { return &m_sme_ctrl_reg; }
+
+  size_t GetSMEControlSize() { return sizeof(m_sme_ctrl_reg); }
+
   llvm::Error ReadHardwareDebugInfo() override;
 
   llvm::Error WriteHardwareDebugRegs(DREGType hwbType) override;
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
@@ -135,6 +135,7 @@
 
   m_mte_ctrl_reg = 0;
   m_tls_tpidr_reg = 0;
+  m_sme_ctrl_reg = 0;
 
   // 16 is just a maximum value, query hardware for actual watchpoint count
   m_max_hwp_supported = 16;
@@ -310,6 +311,13 @@
     offset = reg_info->byte_offset - GetRegisterInfo().GetMTEOffset();
     assert(offset < GetMTEControlSize());
     src = (uint8_t *)GetMTEControl() + offset;
+  } else if (IsSME(reg)) {
+    // This is a psuedo so it never fails.
+    ReadSMEControl();
+
+    offset = reg_info->byte_offset - GetRegisterInfo().GetSMEOffset();
+    assert(offset < GetSMEControlSize());
+    src = (uint8_t *)GetSMEControl() + offset;
   } else
     return Status("failed - register wasn't recognized to be a GPR or an FPR, "
                   "write strategy unknown");
@@ -490,6 +498,8 @@
     ::memcpy(dst, reg_value.GetBytes(), reg_info->byte_size);
 
     return WriteTLSTPIDR();
+  } else if (IsSME(reg)) {
+    return Status("Writing to SVCR is not supported.");
   }
 
   return Status("Failed to write register value");
@@ -702,6 +712,10 @@
   return GetRegisterInfo().IsTLSReg(reg);
 }
 
+bool NativeRegisterContextLinux_arm64::IsSME(unsigned reg) const {
+  return GetRegisterInfo().IsSMEReg(reg);
+}
+
 llvm::Error NativeRegisterContextLinux_arm64::ReadHardwareDebugInfo() {
   if (!m_refresh_hwdebug_info) {
     return llvm::Error::success();
@@ -945,6 +959,16 @@
   return WriteRegisterSet(&ioVec, GetSVEBufferSize(), GetSVERegSet());
 }
 
+Status NativeRegisterContextLinux_arm64::ReadSMEControl() {
+  // The real register is SVCR and is accessible from EL0. However we don't want
+  // to have to JIT code into the target process so we'll just recreate it using
+  // what we know from ptrace.
+  // Bit 1 indicates whether streaming mode is active.
+  // Bit 2 indicates whether the array storage is active (not yet implemented).
+  m_sme_ctrl_reg = m_sve_state == SVEState::Streaming;
+  return {};
+}
+
 Status NativeRegisterContextLinux_arm64::ReadMTEControl() {
   Status error;
 
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to