DavidSpickett updated this revision to Diff 541542.
DavidSpickett marked an inline comment as done.
DavidSpickett added a comment.
Add missing newline.
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)
@@ -206,4 +211,4 @@
@skipIf(archs=no_match(["aarch64"]))
@skipIf(oslist=no_match(["linux"]))
def test_registers_expr_read_write_ssve_sve(self):
- self.sve_registers_read_write_impl(Mode.SSVE, Mode.SVE)
\ No newline at end of file
+ self.sve_registers_read_write_impl(Mode.SSVE, Mode.SVE)
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
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits