diff --git a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h --- a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h +++ b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h @@ -114,6 +114,12 @@ uint64_t m_mte_ctrl_reg; + struct sme_regs { + uint64_t svg_reg; + }; + + struct sme_regs m_sme_regs; + struct tls_regs { uint64_t tpidr_reg; // Only valid when SME is present. @@ -144,6 +150,8 @@ Status WriteTLS(); + Status ReadSMESVG(); + Status ReadZAHeader(); Status ReadZA(); @@ -159,6 +167,7 @@ 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; } @@ -176,6 +185,8 @@ void *GetTLSBuffer() { return &m_tls_regs; } + void *GetSMEBuffer() { return &m_sme_regs; } + void *GetSVEBuffer() { return m_sve_ptrace_payload.data(); } size_t GetSVEHeaderSize() { return sizeof(m_sve_header); } @@ -194,6 +205,8 @@ size_t GetTLSBufferSize() { return m_tls_size; } + size_t GetSMEBufferSize() { return sizeof(m_sme_regs); } + llvm::Error ReadHardwareDebugInfo() override; llvm::Error WriteHardwareDebugRegs(DREGType hwbType) override; diff --git a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp --- a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp +++ b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp @@ -147,6 +147,7 @@ ::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_regs, 0, sizeof(m_sme_regs)); m_mte_ctrl_reg = 0; @@ -353,6 +354,14 @@ GetZAHeaderSize(); assert(offset < GetZABufferSize()); src = (uint8_t *)GetZABuffer() + offset; + } else if (IsSME(reg)) { + error = ReadSMESVG(); + if (error.Fail()) + return error; + + offset = reg_info->byte_offset - GetRegisterInfo().GetSMEOffset(); + assert(offset < GetSMEBufferSize()); + src = (uint8_t *)GetSMEBuffer() + offset; } else return Status("failed - register wasn't recognized to be a GPR or an FPR, " "write strategy unknown"); @@ -552,6 +561,8 @@ // way to change that is via the vg register. So here we assume the length // will always be the current length and no reconfigure is needed. return WriteZA(); + } else if (IsSME(reg)) { + return Status("Writing to SVG is not supported."); } return Status("Failed to write register value"); @@ -901,6 +912,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(); @@ -1357,6 +1372,16 @@ 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_regs.svg_reg = m_za_header.vl / 8; + + return error; +} + std::vector NativeRegisterContextLinux_arm64::GetExpeditedRegisters( ExpeditedRegs expType) const { std::vector expedited_reg_nums = diff --git a/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h b/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h --- a/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h +++ b/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h @@ -109,6 +109,8 @@ void AddRegSetZA(); + void AddRegSetSME(); + uint32_t ConfigureVectorLength(uint32_t sve_vq); void ConfigureVectorLengthZA(uint32_t za_vq); @@ -147,6 +149,7 @@ uint32_t GetMTEOffset() const; uint32_t GetTLSOffset() const; uint32_t GetZAOffset() const; + uint32_t GetSMEOffset() const; private: typedef std::map> diff --git a/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.cpp b/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.cpp --- a/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.cpp @@ -88,6 +88,9 @@ {{"za", nullptr, 16, 0, lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, KIND_ALL_INVALID, nullptr, nullptr, nullptr}}; +static lldb_private::RegisterInfo g_register_infos_sme[] = { + DEFINE_EXTENSION_REG(svg)}; + // Number of register sets provided by this context. enum { k_num_gpr_registers = gpr_w28 - gpr_x0 + 1, @@ -255,8 +258,10 @@ // present. AddRegSetTLS(m_opt_regsets.AllSet(eRegsetMaskSSVE)); - if (m_opt_regsets.AnySet(eRegsetMaskSSVE)) + if (m_opt_regsets.AnySet(eRegsetMaskSSVE)) { AddRegSetZA(); + AddRegSetSME(); + } m_register_info_count = m_dynamic_reg_infos.size(); m_register_info_p = m_dynamic_reg_infos.data(); @@ -377,6 +382,24 @@ m_dynamic_reg_sets.back().registers = m_za_regnum_collection.data(); } +void RegisterInfoPOSIX_arm64::AddRegSetSME() { + uint32_t sme_regnum = m_dynamic_reg_infos.size(); + for (uint32_t i = 0; i < k_num_sme_register; i++) { + m_sme_regnum_collection.push_back(sme_regnum + i); + m_dynamic_reg_infos.push_back(g_register_infos_sme[i]); + m_dynamic_reg_infos[sme_regnum + i].byte_offset = + m_dynamic_reg_infos[sme_regnum + i - 1].byte_offset + + m_dynamic_reg_infos[sme_regnum + i - 1].byte_size; + m_dynamic_reg_infos[sme_regnum + i].kinds[lldb::eRegisterKindLLDB] = + sme_regnum + i; + } + + m_per_regset_regnum_range[m_register_set_count] = + std::make_pair(sme_regnum, m_dynamic_reg_infos.size()); + 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. @@ -523,3 +546,7 @@ uint32_t RegisterInfoPOSIX_arm64::GetZAOffset() const { return m_register_info_p[m_za_regnum_collection[0]].byte_offset; } + +uint32_t RegisterInfoPOSIX_arm64::GetSMEOffset() const { + return m_register_info_p[m_sme_regnum_collection[0]].byte_offset; +}