Skip to content

Commit a0768b8

Browse files
committed
[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
1 parent d99d9d8 commit a0768b8

File tree

4 files changed

+75
-24
lines changed

4 files changed

+75
-24
lines changed

lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp

Lines changed: 47 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ NativeRegisterContextLinux_arm64::NativeRegisterContextLinux_arm64(
147147
::memset(&m_sve_header, 0, sizeof(m_sve_header));
148148
::memset(&m_pac_mask, 0, sizeof(m_pac_mask));
149149
::memset(&m_tls_regs, 0, sizeof(m_tls_regs));
150+
::memset(&m_sme_pseudo_regs, 0, sizeof(m_sme_pseudo_regs));
150151

151152
m_mte_ctrl_reg = 0;
152153

@@ -329,30 +330,40 @@ NativeRegisterContextLinux_arm64::ReadRegister(const RegisterInfo *reg_info,
329330
assert(offset < GetMTEControlSize());
330331
src = (uint8_t *)GetMTEControl() + offset;
331332
} else if (IsSME(reg)) {
332-
error = ReadZAHeader();
333-
if (error.Fail())
334-
return error;
333+
if (GetRegisterInfo().IsSMERegZA(reg)) {
334+
error = ReadZAHeader();
335+
if (error.Fail())
336+
return error;
335337

336-
// If there is only a header and no registers, ZA is inactive. Read as 0
337-
// in this case.
338-
if (m_za_header.size == sizeof(m_za_header)) {
339-
// This will get reconfigured/reset later, so we are safe to use it.
340-
// ZA is a square of VL * VL and the ptrace buffer also includes the
341-
// header itself.
342-
m_za_ptrace_payload.resize(((m_za_header.vl) * (m_za_header.vl)) +
343-
GetZAHeaderSize());
344-
std::fill(m_za_ptrace_payload.begin(), m_za_ptrace_payload.end(), 0);
338+
// If there is only a header and no registers, ZA is inactive. Read as 0
339+
// in this case.
340+
if (m_za_header.size == sizeof(m_za_header)) {
341+
// This will get reconfigured/reset later, so we are safe to use it.
342+
// ZA is a square of VL * VL and the ptrace buffer also includes the
343+
// header itself.
344+
m_za_ptrace_payload.resize(((m_za_header.vl) * (m_za_header.vl)) +
345+
GetZAHeaderSize());
346+
std::fill(m_za_ptrace_payload.begin(), m_za_ptrace_payload.end(), 0);
347+
} else {
348+
// ZA is active, read the real register.
349+
error = ReadZA();
350+
if (error.Fail())
351+
return error;
352+
}
353+
354+
// ZA is part of the SME set but uses a seperate member buffer for
355+
// storage. Therefore its effective byte offset is always 0 even if it
356+
// isn't 0 within the SME register set.
357+
src = (uint8_t *)GetZABuffer() + GetZAHeaderSize();
345358
} else {
346-
// ZA is active, read the real register.
347-
error = ReadZA();
359+
error = ReadSMESVG();
348360
if (error.Fail())
349361
return error;
350-
}
351362

352-
// ZA is part of the SME set but uses a seperate member buffer for storage.
353-
// Therefore its effective byte offset is always 0 even if it isn't 0 within
354-
// the SME register set.
355-
src = (uint8_t *)GetZABuffer() + GetZAHeaderSize();
363+
offset = reg_info->byte_offset - GetRegisterInfo().GetSMEOffset();
364+
assert(offset < GetSMEPseudoBufferSize());
365+
src = (uint8_t *)GetSMEPseudoBuffer() + offset;
366+
}
356367
} else
357368
return Status("failed - register wasn't recognized to be a GPR or an FPR, "
358369
"write strategy unknown");
@@ -538,6 +549,9 @@ Status NativeRegisterContextLinux_arm64::WriteRegister(
538549

539550
return WriteTLS();
540551
} else if (IsSME(reg)) {
552+
if (!GetRegisterInfo().IsSMERegZA(reg))
553+
return Status("Writing to SVG is not supported.");
554+
541555
error = ReadZA();
542556
if (error.Fail())
543557
return error;
@@ -1357,13 +1371,27 @@ uint32_t NativeRegisterContextLinux_arm64::CalculateSVEOffset(
13571371
return sve_reg_offset;
13581372
}
13591373

1374+
Status NativeRegisterContextLinux_arm64::ReadSMESVG() {
1375+
// This register is the streaming vector length, so we will get it from
1376+
// NT_ARM_ZA regardless of the current streaming mode.
1377+
Status error = ReadZAHeader();
1378+
if (error.Success())
1379+
m_sme_pseudo_regs.svg_reg = m_za_header.vl / 8;
1380+
1381+
return error;
1382+
}
1383+
13601384
std::vector<uint32_t> NativeRegisterContextLinux_arm64::GetExpeditedRegisters(
13611385
ExpeditedRegs expType) const {
13621386
std::vector<uint32_t> expedited_reg_nums =
13631387
NativeRegisterContext::GetExpeditedRegisters(expType);
13641388
// SVE, non-streaming vector length.
13651389
if (m_sve_state == SVEState::FPSIMD || m_sve_state == SVEState::Full)
13661390
expedited_reg_nums.push_back(GetRegisterInfo().GetRegNumSVEVG());
1391+
// SME, streaming vector length. This is used by the ZA register which is
1392+
// present even when streaming mode is not enabled.
1393+
if (GetRegisterInfo().IsSSVEEnabled())
1394+
expedited_reg_nums.push_back(GetRegisterInfo().GetRegNumSMESVG());
13671395

13681396
return expedited_reg_nums;
13691397
}

lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,12 @@ class NativeRegisterContextLinux_arm64
114114

115115
uint64_t m_mte_ctrl_reg;
116116

117+
struct sme_pseudo_regs {
118+
uint64_t svg_reg;
119+
};
120+
121+
struct sme_pseudo_regs m_sme_pseudo_regs;
122+
117123
struct tls_regs {
118124
uint64_t tpidr_reg;
119125
// Only valid when SME is present.
@@ -144,6 +150,8 @@ class NativeRegisterContextLinux_arm64
144150

145151
Status WriteTLS();
146152

153+
Status ReadSMESVG();
154+
147155
Status ReadZAHeader();
148156

149157
Status ReadZA();
@@ -176,6 +184,8 @@ class NativeRegisterContextLinux_arm64
176184

177185
void *GetTLSBuffer() { return &m_tls_regs; }
178186

187+
void *GetSMEPseudoBuffer() { return &m_sme_pseudo_regs; }
188+
179189
void *GetSVEBuffer() { return m_sve_ptrace_payload.data(); }
180190

181191
size_t GetSVEHeaderSize() { return sizeof(m_sve_header); }
@@ -194,6 +204,8 @@ class NativeRegisterContextLinux_arm64
194204

195205
size_t GetTLSBufferSize() { return m_tls_size; }
196206

207+
size_t GetSMEPseudoBufferSize() { return sizeof(m_sme_pseudo_regs); }
208+
197209
llvm::Error ReadHardwareDebugInfo() override;
198210

199211
llvm::Error WriteHardwareDebugRegs(DREGType hwbType) override;

lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.cpp

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -83,10 +83,11 @@ static lldb_private::RegisterInfo g_register_infos_tls[] = {
8383
// Only present when SME is present
8484
DEFINE_EXTENSION_REG(tpidr2)};
8585

86-
static lldb_private::RegisterInfo g_register_infos_sme[] =
86+
static lldb_private::RegisterInfo g_register_infos_sme[] = {
87+
DEFINE_EXTENSION_REG(svg),
8788
// 16 is a default size we will change later.
88-
{{"za", nullptr, 16, 0, lldb::eEncodingVector, lldb::eFormatVectorOfUInt8,
89-
KIND_ALL_INVALID, nullptr, nullptr, nullptr}};
89+
{"za", nullptr, 16, 0, lldb::eEncodingVector, lldb::eFormatVectorOfUInt8,
90+
KIND_ALL_INVALID, nullptr, nullptr, nullptr}};
9091

9192
// Number of register sets provided by this context.
9293
enum {
@@ -96,7 +97,7 @@ enum {
9697
k_num_mte_register = 1,
9798
// Number of TLS registers is dynamic so it is not listed here.
9899
k_num_pauth_register = 2,
99-
k_num_sme_register = 1,
100+
k_num_sme_register = 2,
100101
k_num_register_sets_default = 2,
101102
k_num_register_sets = 3
102103
};
@@ -448,7 +449,7 @@ void RegisterInfoPOSIX_arm64::ConfigureVectorLengthZA(uint32_t za_vq) {
448449
// dynamic set and is just 1 register so we make an exception to const here.
449450
lldb_private::RegisterInfo *non_const_reginfo =
450451
const_cast<lldb_private::RegisterInfo *>(m_register_info_p);
451-
non_const_reginfo[m_sme_regnum_collection[0]].byte_size =
452+
non_const_reginfo[m_sme_regnum_collection[1]].byte_size =
452453
(za_vq * 16) * (za_vq * 16);
453454
}
454455

@@ -471,6 +472,10 @@ bool RegisterInfoPOSIX_arm64::IsSVERegVG(unsigned reg) const {
471472
return sve_vg == reg;
472473
}
473474

475+
bool RegisterInfoPOSIX_arm64::IsSMERegZA(unsigned reg) const {
476+
return reg == m_sme_regnum_collection[1];
477+
}
478+
474479
bool RegisterInfoPOSIX_arm64::IsPAuthReg(unsigned reg) const {
475480
return llvm::is_contained(pauth_regnum_collection, reg);
476481
}
@@ -497,6 +502,10 @@ uint32_t RegisterInfoPOSIX_arm64::GetRegNumFPSR() const { return fpu_fpsr; }
497502

498503
uint32_t RegisterInfoPOSIX_arm64::GetRegNumSVEVG() const { return sve_vg; }
499504

505+
uint32_t RegisterInfoPOSIX_arm64::GetRegNumSMESVG() const {
506+
return m_sme_regnum_collection[0];
507+
}
508+
500509
uint32_t RegisterInfoPOSIX_arm64::GetPAuthOffset() const {
501510
return m_register_info_p[pauth_regnum_collection[0]].byte_offset;
502511
}

lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,12 +135,14 @@ class RegisterInfoPOSIX_arm64
135135
bool IsMTEReg(unsigned reg) const;
136136
bool IsTLSReg(unsigned reg) const;
137137
bool IsSMEReg(unsigned reg) const;
138+
bool IsSMERegZA(unsigned reg) const;
138139

139140
uint32_t GetRegNumSVEZ0() const;
140141
uint32_t GetRegNumSVEFFR() const;
141142
uint32_t GetRegNumFPCR() const;
142143
uint32_t GetRegNumFPSR() const;
143144
uint32_t GetRegNumSVEVG() const;
145+
uint32_t GetRegNumSMESVG() const;
144146
uint32_t GetPAuthOffset() const;
145147
uint32_t GetMTEOffset() const;
146148
uint32_t GetTLSOffset() const;

0 commit comments

Comments
 (0)