Skip to content

Commit dd2a63e

Browse files
committed
Revert "Revert "[LLDB] Arm64/Linux test case for MTE and Pointer Authentication regset""
This reverts commit feb6f2c.
1 parent 88a5b35 commit dd2a63e

File tree

4 files changed

+197
-2
lines changed

4 files changed

+197
-2
lines changed

lldb/packages/Python/lldbsuite/test/lldbtest.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1269,7 +1269,7 @@ def isPPC64le(self):
12691269
return True
12701270
return False
12711271

1272-
def isAArch64SVE(self):
1272+
def getCPUInfo(self):
12731273
triple = self.dbg.GetSelectedPlatform().GetTriple()
12741274

12751275
# TODO other platforms, please implement this function
@@ -1290,7 +1290,16 @@ def isAArch64SVE(self):
12901290
except:
12911291
return False
12921292

1293-
return " sve " in cpuinfo
1293+
return cpuinfo
1294+
1295+
def isAArch64SVE(self):
1296+
return "sve" in self.getCPUInfo()
1297+
1298+
def isAArch64MTE(self):
1299+
return "mte" in self.getCPUInfo()
1300+
1301+
def isAArch64PAuth(self):
1302+
return "paca" in self.getCPUInfo()
12941303

12951304
def hasLinuxVmFlags(self):
12961305
""" Check that the target machine has "VmFlags" lines in
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
C_SOURCES := main.c
2+
3+
CFLAGS_EXTRAS := -march=armv8-a+sve
4+
5+
include Makefile.rules
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
"""
2+
Test AArch64 dynamic register sets
3+
"""
4+
5+
import lldb
6+
from lldbsuite.test.decorators import *
7+
from lldbsuite.test.lldbtest import *
8+
from lldbsuite.test import lldbutil
9+
10+
11+
class RegisterCommandsTestCase(TestBase):
12+
13+
def check_sve_register_size(self, set, name, expected):
14+
reg_value = set.GetChildMemberWithName(name)
15+
self.assertTrue(reg_value.IsValid(),
16+
'Expected a register named %s' % (name))
17+
self.assertEqual(reg_value.GetByteSize(), expected,
18+
'Expected a register %s size == %i bytes' % (name, expected))
19+
20+
def sve_regs_read_dynamic(self, sve_registers):
21+
vg_reg = sve_registers.GetChildMemberWithName("vg")
22+
vg_reg_value = sve_registers.GetChildMemberWithName(
23+
"vg").GetValueAsUnsigned()
24+
25+
z_reg_size = vg_reg_value * 8
26+
p_reg_size = int(z_reg_size / 8)
27+
28+
for i in range(32):
29+
z_regs_value = '{' + \
30+
' '.join('0x{:02x}'.format(i + 1)
31+
for _ in range(z_reg_size)) + '}'
32+
self.expect('register read z%i' %
33+
(i), substrs=[z_regs_value])
34+
35+
# Set P registers with random test values. The P registers are predicate
36+
# registers, which hold one bit for each byte available in a Z register.
37+
# For below mentioned values of P registers, P(0,5,10,15) will have all
38+
# Z register lanes set while P(4,9,14) will have no lanes set.
39+
p_value_bytes = ['0xff', '0x55', '0x11', '0x01', '0x00']
40+
for i in range(16):
41+
p_regs_value = '{' + \
42+
' '.join(p_value_bytes[i % 5] for _ in range(p_reg_size)) + '}'
43+
self.expect('register read p%i' % (i), substrs=[p_regs_value])
44+
45+
self.expect("register read ffr", substrs=[p_regs_value])
46+
47+
for i in range(32):
48+
z_regs_value = '{' + \
49+
' '.join('0x{:02x}'.format(32 - i)
50+
for _ in range(z_reg_size)) + '}'
51+
self.runCmd("register write z%i '%s'" % (i, z_regs_value))
52+
self.expect('register read z%i' % (i), substrs=[z_regs_value])
53+
54+
for i in range(16):
55+
p_regs_value = '{' + \
56+
' '.join('0x{:02x}'.format(16 - i)
57+
for _ in range(p_reg_size)) + '}'
58+
self.runCmd("register write p%i '%s'" % (i, p_regs_value))
59+
self.expect('register read p%i' % (i), substrs=[p_regs_value])
60+
61+
p_regs_value = '{' + \
62+
' '.join('0x{:02x}'.format(8)
63+
for _ in range(p_reg_size)) + '}'
64+
self.runCmd('register write ffr ' + "'" + p_regs_value + "'")
65+
self.expect('register read ffr', substrs=[p_regs_value])
66+
67+
mydir = TestBase.compute_mydir(__file__)
68+
69+
@no_debug_info_test
70+
@skipIf(archs=no_match(["aarch64"]))
71+
@skipIf(oslist=no_match(['linux']))
72+
def test_aarch64_dynamic_regset_config(self):
73+
"""Test AArch64 Dynamic Register sets configuration."""
74+
self.build()
75+
self.line = line_number('main.c', '// Set a break point here.')
76+
77+
exe = self.getBuildArtifact("a.out")
78+
self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
79+
80+
lldbutil.run_break_set_by_file_and_line(
81+
self, "main.c", self.line, num_expected_locations=1)
82+
self.runCmd("run", RUN_SUCCEEDED)
83+
84+
self.expect("thread backtrace", STOPPED_DUE_TO_BREAKPOINT,
85+
substrs=["stop reason = breakpoint 1."])
86+
87+
target = self.dbg.GetSelectedTarget()
88+
process = target.GetProcess()
89+
thread = process.GetThreadAtIndex(0)
90+
currentFrame = thread.GetFrameAtIndex(0)
91+
92+
for registerSet in currentFrame.GetRegisters():
93+
if 'Scalable Vector Extension Registers' in registerSet.GetName():
94+
self.assertTrue(self.isAArch64SVE(),
95+
'LLDB enabled AArch64 SVE register set when it was disabled by target.')
96+
self.sve_regs_read_dynamic(registerSet)
97+
if 'MTE Control Register' in registerSet.GetName():
98+
self.assertTrue(self.isAArch64MTE(),
99+
'LLDB enabled AArch64 MTE register set when it was disabled by target.')
100+
self.runCmd("register write mte_ctrl 0x7fff9")
101+
self.expect("register read mte_ctrl",
102+
substrs=['mte_ctrl = 0x000000000007fff9'])
103+
if 'Pointer Authentication Registers' in registerSet.GetName():
104+
self.assertTrue(self.isAArch64PAuth(),
105+
'LLDB enabled AArch64 Pointer Authentication register set when it was disabled by target.')
106+
self.expect("register read data_mask",
107+
substrs=['data_mask = 0x'])
108+
self.expect("register read code_mask",
109+
substrs=['code_mask = 0x'])
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
#include <sys/auxv.h>
2+
3+
void set_sve_registers() {
4+
// AArch64 SVE extension ISA adds a new set of vector and predicate registers:
5+
// 32 Z registers, 16 P registers, and 1 FFR register.
6+
// Code below populates SVE registers to be read back by the debugger via
7+
// ptrace interface at runtime.
8+
// The P registers are predicate registers and hold one bit for each byte
9+
// available in a Z vector register. For example, an SVE implementation with
10+
// 1024-bit Z registers has 128-bit predicate registers.
11+
// ptrue/pfalse instruction is used to set a predicate lane with a pattern.
12+
// pattern is decided based on size specifier, b, h, s and d. if size
13+
// specified is b all lanes will be set to 1. which is needed to set all bytes
14+
// in a Z registers to the specified value.
15+
asm volatile("setffr\n\t");
16+
asm volatile("ptrue p0.b\n\t");
17+
asm volatile("ptrue p1.h\n\t");
18+
asm volatile("ptrue p2.s\n\t");
19+
asm volatile("ptrue p3.d\n\t");
20+
asm volatile("pfalse p4.b\n\t");
21+
asm volatile("ptrue p5.b\n\t");
22+
asm volatile("ptrue p6.h\n\t");
23+
asm volatile("ptrue p7.s\n\t");
24+
asm volatile("ptrue p8.d\n\t");
25+
asm volatile("pfalse p9.b\n\t");
26+
asm volatile("ptrue p10.b\n\t");
27+
asm volatile("ptrue p11.h\n\t");
28+
asm volatile("ptrue p12.s\n\t");
29+
asm volatile("ptrue p13.d\n\t");
30+
asm volatile("pfalse p14.b\n\t");
31+
asm volatile("ptrue p15.b\n\t");
32+
33+
asm volatile("cpy z0.b, p0/z, #1\n\t");
34+
asm volatile("cpy z1.b, p5/z, #2\n\t");
35+
asm volatile("cpy z2.b, p10/z, #3\n\t");
36+
asm volatile("cpy z3.b, p15/z, #4\n\t");
37+
asm volatile("cpy z4.b, p0/z, #5\n\t");
38+
asm volatile("cpy z5.b, p5/z, #6\n\t");
39+
asm volatile("cpy z6.b, p10/z, #7\n\t");
40+
asm volatile("cpy z7.b, p15/z, #8\n\t");
41+
asm volatile("cpy z8.b, p0/z, #9\n\t");
42+
asm volatile("cpy z9.b, p5/z, #10\n\t");
43+
asm volatile("cpy z10.b, p10/z, #11\n\t");
44+
asm volatile("cpy z11.b, p15/z, #12\n\t");
45+
asm volatile("cpy z12.b, p0/z, #13\n\t");
46+
asm volatile("cpy z13.b, p5/z, #14\n\t");
47+
asm volatile("cpy z14.b, p10/z, #15\n\t");
48+
asm volatile("cpy z15.b, p15/z, #16\n\t");
49+
asm volatile("cpy z16.b, p0/z, #17\n\t");
50+
asm volatile("cpy z17.b, p5/z, #18\n\t");
51+
asm volatile("cpy z18.b, p10/z, #19\n\t");
52+
asm volatile("cpy z19.b, p15/z, #20\n\t");
53+
asm volatile("cpy z20.b, p0/z, #21\n\t");
54+
asm volatile("cpy z21.b, p5/z, #22\n\t");
55+
asm volatile("cpy z22.b, p10/z, #23\n\t");
56+
asm volatile("cpy z23.b, p15/z, #24\n\t");
57+
asm volatile("cpy z24.b, p0/z, #25\n\t");
58+
asm volatile("cpy z25.b, p5/z, #26\n\t");
59+
asm volatile("cpy z26.b, p10/z, #27\n\t");
60+
asm volatile("cpy z27.b, p15/z, #28\n\t");
61+
asm volatile("cpy z28.b, p0/z, #29\n\t");
62+
asm volatile("cpy z29.b, p5/z, #30\n\t");
63+
asm volatile("cpy z30.b, p10/z, #31\n\t");
64+
asm volatile("cpy z31.b, p15/z, #32\n\t");
65+
}
66+
67+
int main() {
68+
if (getauxval(AT_HWCAP) & HWCAP_SVE) // check if SVE is present
69+
set_sve_registers();
70+
71+
return 0; // Set a break point here.
72+
}

0 commit comments

Comments
 (0)