Skip to content

Commit f2c09e5

Browse files
[lldb][AArch64] Invalidate SVG prior to reconfiguring ZA regdef (#66768)
This fixes a bug where writing vg during streaming mode could prevent you reading za directly afterwards. vg is invalidated just prior to us reading it in AArch64Reconfigure, but svg was not. This lead to some situations where vg would be updated or cleared and re-read, but svg would not be. This meant it had some undefined value which lead to errors that prevented us reading ZA. Likely we received a lot more data than we were expecting. There are at least 2 ways to get into this situation: * Explicit write by the user to vg. * We have just stopped and need to get the potentially new svg and vg. The first is handled by invalidating svg client side before fetching the new one. This also covers some but not all of the second scenario. For the second, I've made writes to vg invalidate svg by noting this in the register information. Whichever one of those kicks in, we'll get the latest value of svg. The bug may depend on timing, I could not find a consistent way to trigger it. I originally found it when checking whether za is disabled after a vg change, so I've added checks for that to TestZAThreadedDynamic. The SVE VG version of the bug did show up on the buildbot, but not consistently. So it's possible that TestZAThreadedDynamic does in fact cover this, but I haven't run it enough times to know.
1 parent a770098 commit f2c09e5

File tree

3 files changed

+18
-0
lines changed

3 files changed

+18
-0
lines changed

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

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -374,6 +374,17 @@ void RegisterInfoPOSIX_arm64::AddRegSetSME() {
374374
std::make_pair(sme_regnum, m_dynamic_reg_infos.size());
375375
m_dynamic_reg_sets.push_back(g_reg_set_sme_arm64);
376376
m_dynamic_reg_sets.back().registers = m_sme_regnum_collection.data();
377+
378+
// When vg is written during streaming mode, svg will also change, as vg and
379+
// svg in this state are both showing the streaming vector length.
380+
// We model this as vg invalidating svg. In non-streaming mode this doesn't
381+
// happen but to keep things simple we will invalidate svg anyway.
382+
//
383+
// This must be added now, rather than when vg is defined because SME is a
384+
// dynamic set that may or may not be present.
385+
static const uint32_t vg_invalidates[] = {sme_regnum + 1 /*svg*/,
386+
LLDB_INVALID_REGNUM};
387+
m_dynamic_reg_infos[GetRegNumSMESVG()].invalidate_regs = vg_invalidates;
377388
}
378389

379390
uint32_t RegisterInfoPOSIX_arm64::ConfigureVectorLengthSVE(uint32_t sve_vq) {

lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -783,6 +783,11 @@ void GDBRemoteRegisterContext::AArch64Reconfigure() {
783783
std::optional<uint64_t> svg_reg_value;
784784
const RegisterInfo *svg_reg_info = m_reg_info_sp->GetRegisterInfo("svg");
785785
if (svg_reg_info) {
786+
// When vg is written it is automatically made invalid. Writing vg will also
787+
// change svg if we're in streaming mode but it will not be made invalid
788+
// so do this manually so the following read gets the latest svg value.
789+
SetRegisterIsValid(svg_reg_info, false);
790+
786791
uint32_t svg_reg_num = svg_reg_info->kinds[eRegisterKindLLDB];
787792
uint64_t reg_value = ReadRegisterAsUnsigned(svg_reg_num, fail_value);
788793
if (reg_value != fail_value && reg_value <= 32)

lldb/test/API/commands/register/register/aarch64_za_register/za_dynamic_resize/TestZAThreadedDynamic.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,11 +125,13 @@ def za_test_impl(self, enable_za):
125125
self.runCmd("thread select %d" % (idx + 1))
126126
self.check_za_register(4, 2)
127127
self.runCmd("register write vg 2")
128+
self.check_disabled_za_register(2)
128129

129130
elif stopped_at_line_number == thY_break_line1:
130131
self.runCmd("thread select %d" % (idx + 1))
131132
self.check_za_register(2, 3)
132133
self.runCmd("register write vg 4")
134+
self.check_disabled_za_register(4)
133135

134136
self.runCmd("thread continue 2")
135137
self.runCmd("thread continue 3")

0 commit comments

Comments
 (0)