DavidSpickett updated this revision to Diff 549951.
DavidSpickett added a comment.
Rebase and reimplement this on top of ZA/SVG.
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/test/API/commands/register/register/aarch64_dynamic_regset/TestArm64DynamicRegsets.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/main.c
lldb/test/API/commands/register/register/aarch64_za_reg/za_save_restore/TestZARegisterSaveRestore.py
Index: lldb/test/API/commands/register/register/aarch64_za_reg/za_save_restore/TestZARegisterSaveRestore.py
===================================================================
--- lldb/test/API/commands/register/register/aarch64_za_reg/za_save_restore/TestZARegisterSaveRestore.py
+++ lldb/test/API/commands/register/register/aarch64_za_reg/za_save_restore/TestZARegisterSaveRestore.py
@@ -149,6 +149,10 @@
self.runCmd("register read " + sve_reg_names)
sve_values = self.res.GetOutput()
+ svcr_value = 1 if sve_mode == Mode.SSVE else 0
+ if za_state == ZA.Enabled:
+ svcr_value += 2
+
def check_regs():
if za_state == ZA.Enabled:
self.check_za(start_vl)
@@ -160,6 +164,7 @@
self.assertEqual(start_vg, self.read_vg())
self.expect("register read " + sve_reg_names, substrs=[sve_values])
+ self.expect("register read svcr", substrs=["0x{:016x}".format(svcr_value)])
for expr in exprs:
expr_cmd = "expression {}()".format(expr)
Index: lldb/test/API/commands/register/register/aarch64_sve_registers/rw_access_static_config/main.c
===================================================================
--- lldb/test/API/commands/register/register/aarch64_sve_registers/rw_access_static_config/main.c
+++ lldb/test/API/commands/register/register/aarch64_sve_registers/rw_access_static_config/main.c
@@ -5,7 +5,7 @@
#define PR_SME_SET_VL 63
#endif
-#define SMSTART() asm volatile("msr s0_3_c4_c7_3, xzr" /*smstart*/)
+#define SMSTART_SM() asm volatile("msr s0_3_c4_c3_3, xzr" /*smstart sm*/)
void write_sve_regs() {
// We assume the smefa64 feature is present, which allows ffr access
@@ -126,18 +126,18 @@
// Note that doing a syscall brings you back to non-streaming mode, so we
// don't need to SMSTOP here.
if (streaming)
- SMSTART();
+ SMSTART_SM();
write_sve_regs_expr();
prctl(SET_VL_OPT, 8 * 4);
if (streaming)
- SMSTART();
+ SMSTART_SM();
write_sve_regs_expr();
return 1;
}
int main() {
#ifdef START_SSVE
- SMSTART();
+ SMSTART_SM();
#endif
write_sve_regs();
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
@@ -24,7 +24,14 @@
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():
+ # This test uses SMSTART SM, which only enables streaming mode,
+ # leaving ZA disabled.
+ 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):
@@ -168,7 +175,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"])
@@ -184,7 +191,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/test/API/commands/register/register/aarch64_dynamic_regset/TestArm64DynamicRegsets.py
===================================================================
--- lldb/test/API/commands/register/register/aarch64_dynamic_regset/TestArm64DynamicRegsets.py
+++ lldb/test/API/commands/register/register/aarch64_dynamic_regset/TestArm64DynamicRegsets.py
@@ -177,6 +177,11 @@
svg = sme_registers.GetChildMemberWithName("svg").GetValueAsUnsigned()
self.assertEqual(vg, svg)
+ # SVCR should be SVCR.SM | SVCR.ZA aka 3 because streaming mode is on
+ # and ZA is enabled.
+ svcr = sme_registers.GetChildMemberWithName("svcr").GetValueAsUnsigned()
+ self.assertEqual(3, svcr)
+
@no_debug_info_test
@skipIf(archs=no_match(["aarch64"]))
@skipIf(oslist=no_match(["linux"]))
@@ -196,6 +201,10 @@
self.assertTrue(sme_registers.IsValid())
svg = sme_registers.GetChildMemberWithName("svg").GetValueAsUnsigned()
+ # We are not in streaming mode, ZA is disabled, so this should be 0.
+ svcr = sme_registers.GetChildMemberWithName("svcr").GetValueAsUnsigned()
+ self.assertEqual(0, svcr)
+
za_register = register_sets.GetFirstValueByName(
"Scalable Matrix Array Storage Registers")
self.assertTrue(za_register.IsValid())
@@ -207,3 +216,6 @@
# it back.
self.runCmd("register write za '{}'".format(za_value))
self.expect("register read za", substrs=[za_value])
+
+ # Now SVCR.ZA should be set, which is bit 1.
+ self.expect("register read svcr", substrs=["0x0000000000000002"])
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
@@ -89,7 +89,7 @@
KIND_ALL_INVALID, nullptr, nullptr, nullptr}};
static lldb_private::RegisterInfo g_register_infos_sme[] = {
- DEFINE_EXTENSION_REG(svg)};
+ DEFINE_EXTENSION_REG(svg), DEFINE_EXTENSION_REG(svcr)};
// Number of register sets provided by this context.
enum {
@@ -100,7 +100,7 @@
// Number of TLS registers is dynamic so it is not listed here.
k_num_pauth_register = 2,
k_num_za_register = 1,
- k_num_sme_register = 1,
+ k_num_sme_register = 2,
k_num_register_sets_default = 2,
k_num_register_sets = 3
};
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
@@ -116,6 +116,7 @@
struct sme_regs {
uint64_t svg_reg;
+ uint64_t ctrl_reg;
};
struct sme_regs m_sme_regs;
@@ -162,6 +163,9 @@
// Instead use WriteZA and ensure you have the correct ZA buffer size set
// beforehand if you wish to disable it.
+ // SVCR is a pseudo register and we do not allow writes to it.
+ Status ReadSMEControl();
+
bool IsSVE(unsigned reg) const;
bool IsZA(unsigned reg) const;
bool IsPAuth(unsigned reg) const;
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
@@ -359,6 +359,9 @@
if (error.Fail())
return error;
+ // This is a psuedo so it never fails.
+ ReadSMEControl();
+
offset = reg_info->byte_offset - GetRegisterInfo().GetSMEOffset();
assert(offset < GetSMEBufferSize());
src = (uint8_t *)GetSMEBuffer() + offset;
@@ -562,7 +565,7 @@
// 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("Writing to SVG or SVCR is not supported.");
}
return Status("Failed to write register value");
@@ -576,7 +579,8 @@
MTE,
TLS,
ZA,
- // SME pseudo registers are read only.
+ // SME not here because SVG and SVCR are read only pseudo regiters derived
+ // from the other registers.
};
static uint8_t *AddSavedRegistersKind(uint8_t *dst, SavedRegistersKind kind) {
@@ -1161,6 +1165,24 @@
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 0 indicates whether streaming mode is active.
+ m_sme_regs.ctrl_reg = m_sve_state == SVEState::Streaming;
+
+ // Bit 1 indicates whether the array storage is active.
+ // It is active if we can read the header and the size field tells us that
+ // there is register data following it.
+ Status error = ReadZAHeader();
+ if (error.Success() && (m_za_header.size > sizeof(m_za_header)))
+ m_sme_regs.ctrl_reg |= 2;
+
+ return {};
+}
+
Status NativeRegisterContextLinux_arm64::ReadMTEControl() {
Status error;
_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits