xref: /qemu/tests/tcg/aarch64/gdbstub/test-mte.py (revision 06dd94e84336d2c5a86c99049dc9abb4a1d6b2e5)
1340ca46bSGustavo Romerofrom __future__ import print_function
2340ca46bSGustavo Romero#
3340ca46bSGustavo Romero# Test GDB memory-tag commands that exercise the stubs for the qIsAddressTagged,
4*06dd94e8SGustavo Romero# qMemTag, and QMemTag packets, which are used for manipulating allocation tags.
5*06dd94e8SGustavo Romero# Logical tags-related commands rely on local operations, hence don't exercise
6*06dd94e8SGustavo Romero# any stub and so are not used in this test.
7340ca46bSGustavo Romero#
8*06dd94e8SGustavo Romero# The test consists in breaking just after a tag is set in a specific memory
9*06dd94e8SGustavo Romero# chunk, and then using the GDB 'memory-tagging' subcommands to set/get tags in
10*06dd94e8SGustavo Romero# different memory locations and ranges in the MTE-enabled memory chunk.
11340ca46bSGustavo Romero#
12340ca46bSGustavo Romero# This is launched via tests/guest-debug/run-test.py
13340ca46bSGustavo Romero#
14340ca46bSGustavo Romero
15340ca46bSGustavo Romero
16*06dd94e8SGustavo Romerotry:
17340ca46bSGustavo Romero    import gdb
18*06dd94e8SGustavo Romeroexcept ModuleNotFoundError:
19*06dd94e8SGustavo Romero    from sys import exit
20*06dd94e8SGustavo Romero    exit("This script must be launched via tests/guest-debug/run-test.py!")
21340ca46bSGustavo Romeroimport re
22*06dd94e8SGustavo Romerofrom sys import argv
23*06dd94e8SGustavo Romerofrom test_gdbstub import arg_parser, main, report
24340ca46bSGustavo Romero
25340ca46bSGustavo Romero
26c135d5eaSRichard HendersonPATTERN_0 = "Memory tags for address 0x[0-9a-f]+ match \\(0x[0-9a-f]+\\)."
27340ca46bSGustavo RomeroPATTERN_1 = ".*(0x[0-9a-f]+)"
28340ca46bSGustavo Romero
29340ca46bSGustavo Romero
30340ca46bSGustavo Romerodef run_test():
31*06dd94e8SGustavo Romero    p = arg_parser(prog="test-mte.py", description="TCG MTE tests.")
32*06dd94e8SGustavo Romero    p.add_argument("--mode", help="Run test for QEMU system or user mode.",
33*06dd94e8SGustavo Romero                   required=True, choices=['system','user'])
34*06dd94e8SGustavo Romero
35*06dd94e8SGustavo Romero    args = p.parse_args(args=argv)
36*06dd94e8SGustavo Romero
37*06dd94e8SGustavo Romero    if args.mode == "system":
38*06dd94e8SGustavo Romero        # Break address: where to break before performing the tests
39*06dd94e8SGustavo Romero        # See mte.S for details about this label.
40*06dd94e8SGustavo Romero        ba = "main_end"
41*06dd94e8SGustavo Romero        # Tagged address: the start of the MTE-enabled memory chunk to be tested
42*06dd94e8SGustavo Romero        # 'tagged_addr' (x1) is a pointer to the MTE-enabled page. See mte.S.
43*06dd94e8SGustavo Romero        ta = "$x1"
44*06dd94e8SGustavo Romero    else: # mode="user"
45*06dd94e8SGustavo Romero        # Line 95 in mte-8.c
46*06dd94e8SGustavo Romero        ba = "95"
47*06dd94e8SGustavo Romero        # 'a' array. See mte-8.c
48*06dd94e8SGustavo Romero        ta = "a"
49*06dd94e8SGustavo Romero
50*06dd94e8SGustavo Romero    gdb.execute(f"break {ba}", False, True)
51340ca46bSGustavo Romero    gdb.execute("continue", False, True)
52*06dd94e8SGustavo Romero
53340ca46bSGustavo Romero    try:
54*06dd94e8SGustavo Romero        # Test if we can check correctly that the allocation tag for the address
55*06dd94e8SGustavo Romero        # in {ta} matches the logical tag in {ta}.
56*06dd94e8SGustavo Romero        co = gdb.execute(f"memory-tag check {ta}", False, True)
57340ca46bSGustavo Romero        tags_match = re.findall(PATTERN_0, co, re.MULTILINE)
58340ca46bSGustavo Romero        if tags_match:
59340ca46bSGustavo Romero            report(True, f"{tags_match[0]}")
60340ca46bSGustavo Romero        else:
61340ca46bSGustavo Romero            report(False, "Logical and allocation tags don't match!")
62340ca46bSGustavo Romero
63340ca46bSGustavo Romero        # Test allocation tag 'set and print' commands. Commands on logical
64340ca46bSGustavo Romero        # tags rely on local operation and so don't exercise any stub.
65340ca46bSGustavo Romero
66340ca46bSGustavo Romero        # Set the allocation tag for the first granule (16 bytes) of
67*06dd94e8SGustavo Romero        # address starting at {ta} address to a known value, i.e. 0x04.
68*06dd94e8SGustavo Romero        gdb.execute(f"memory-tag set-allocation-tag {ta} 1 04", False, True)
69340ca46bSGustavo Romero
70340ca46bSGustavo Romero        # Then set the allocation tag for the second granule to a known
71340ca46bSGustavo Romero        # value, i.e. 0x06. This tests that contiguous tag granules are
72*06dd94e8SGustavo Romero        # set correctly and don't run over each other.
73*06dd94e8SGustavo Romero        gdb.execute(f"memory-tag set-allocation-tag {ta}+16 1 06", False, True)
74340ca46bSGustavo Romero
75340ca46bSGustavo Romero        # Read the known values back and check if they remain the same.
76340ca46bSGustavo Romero
77*06dd94e8SGustavo Romero        co = gdb.execute(f"memory-tag print-allocation-tag {ta}", False, True)
78340ca46bSGustavo Romero        first_tag = re.match(PATTERN_1, co)[1]
79340ca46bSGustavo Romero
80*06dd94e8SGustavo Romero        co = gdb.execute(f"memory-tag print-allocation-tag {ta}+16", False, True)
81340ca46bSGustavo Romero        second_tag = re.match(PATTERN_1, co)[1]
82340ca46bSGustavo Romero
83340ca46bSGustavo Romero        if first_tag == "0x4" and second_tag == "0x6":
84340ca46bSGustavo Romero            report(True, "Allocation tags are correctly set/printed.")
85340ca46bSGustavo Romero        else:
86340ca46bSGustavo Romero            report(False, "Can't set/print allocation tags!")
87340ca46bSGustavo Romero
88340ca46bSGustavo Romero        # Now test fill pattern by setting a whole page with a pattern.
89*06dd94e8SGustavo Romero        gdb.execute(f"memory-tag set-allocation-tag {ta} 4096 0a0b", False, True)
90340ca46bSGustavo Romero
91340ca46bSGustavo Romero        # And read back the tags of the last two granules in page so
92340ca46bSGustavo Romero        # we also test if the pattern is set correctly up to the end of
93340ca46bSGustavo Romero        # the page.
94*06dd94e8SGustavo Romero        co = gdb.execute(f"memory-tag print-allocation-tag {ta}+4096-32", False, True)
95340ca46bSGustavo Romero        tag = re.match(PATTERN_1, co)[1]
96340ca46bSGustavo Romero
97*06dd94e8SGustavo Romero        co = gdb.execute(f"memory-tag print-allocation-tag {ta}+4096-16", False, True)
98340ca46bSGustavo Romero        last_tag = re.match(PATTERN_1, co)[1]
99340ca46bSGustavo Romero
100340ca46bSGustavo Romero        if tag == "0xa" and last_tag == "0xb":
101340ca46bSGustavo Romero            report(True, "Fill pattern is ok.")
102340ca46bSGustavo Romero        else:
103340ca46bSGustavo Romero            report(False, "Fill pattern failed!")
104340ca46bSGustavo Romero
105340ca46bSGustavo Romero    except gdb.error:
106*06dd94e8SGustavo Romero        # This usually happens because a GDB version that does not support
107*06dd94e8SGustavo Romero        # memory tagging was used to run the test.
108340ca46bSGustavo Romero        report(False, "'memory-tag' command failed!")
109340ca46bSGustavo Romero
110340ca46bSGustavo Romero
111340ca46bSGustavo Romeromain(run_test, expected_arch="aarch64")
112