xref: /qemu/tests/tcg/aarch64/gdbstub/test-mte.py (revision fdf250e5a37830615e324017cb3a503e84b3712c)
1340ca46bSGustavo Romerofrom __future__ import print_function
2340ca46bSGustavo Romero#
3340ca46bSGustavo Romero# Test GDB memory-tag commands that exercise the stubs for the qIsAddressTagged,
406dd94e8SGustavo Romero# qMemTag, and QMemTag packets, which are used for manipulating allocation tags.
506dd94e8SGustavo Romero# Logical tags-related commands rely on local operations, hence don't exercise
606dd94e8SGustavo Romero# any stub and so are not used in this test.
7340ca46bSGustavo Romero#
806dd94e8SGustavo Romero# The test consists in breaking just after a tag is set in a specific memory
906dd94e8SGustavo Romero# chunk, and then using the GDB 'memory-tagging' subcommands to set/get tags in
1006dd94e8SGustavo 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
1606dd94e8SGustavo Romerotry:
17340ca46bSGustavo Romero    import gdb
1806dd94e8SGustavo Romeroexcept ModuleNotFoundError:
1906dd94e8SGustavo Romero    from sys import exit
2006dd94e8SGustavo Romero    exit("This script must be launched via tests/guest-debug/run-test.py!")
21340ca46bSGustavo Romeroimport re
2206dd94e8SGustavo Romerofrom sys import argv
2306dd94e8SGustavo Romerofrom test_gdbstub import arg_parser, main, report
24340ca46bSGustavo Romero
25340ca46bSGustavo Romero
26*bb77c68dSGustavo RomeroPATTERN_0 = r"Memory tags for address 0x[0-9a-f]+ match \(0x[0-9a-f]+\)."
27*bb77c68dSGustavo RomeroPATTERN_1 = r".*(0x[0-9a-f]+)"
28340ca46bSGustavo Romero
29340ca46bSGustavo Romero
30340ca46bSGustavo Romerodef run_test():
3106dd94e8SGustavo Romero    p = arg_parser(prog="test-mte.py", description="TCG MTE tests.")
3206dd94e8SGustavo Romero    p.add_argument("--mode", help="Run test for QEMU system or user mode.",
3306dd94e8SGustavo Romero                   required=True, choices=['system','user'])
3406dd94e8SGustavo Romero
3506dd94e8SGustavo Romero    args = p.parse_args(args=argv)
3606dd94e8SGustavo Romero
3706dd94e8SGustavo Romero    if args.mode == "system":
3806dd94e8SGustavo Romero        # Break address: where to break before performing the tests
3906dd94e8SGustavo Romero        # See mte.S for details about this label.
4006dd94e8SGustavo Romero        ba = "main_end"
4106dd94e8SGustavo Romero        # Tagged address: the start of the MTE-enabled memory chunk to be tested
4206dd94e8SGustavo Romero        # 'tagged_addr' (x1) is a pointer to the MTE-enabled page. See mte.S.
4306dd94e8SGustavo Romero        ta = "$x1"
4406dd94e8SGustavo Romero    else: # mode="user"
4506dd94e8SGustavo Romero        # Line 95 in mte-8.c
4606dd94e8SGustavo Romero        ba = "95"
4706dd94e8SGustavo Romero        # 'a' array. See mte-8.c
4806dd94e8SGustavo Romero        ta = "a"
4906dd94e8SGustavo Romero
5006dd94e8SGustavo Romero    gdb.execute(f"break {ba}", False, True)
51340ca46bSGustavo Romero    gdb.execute("continue", False, True)
5206dd94e8SGustavo Romero
53340ca46bSGustavo Romero    try:
5406dd94e8SGustavo Romero        # Test if we can check correctly that the allocation tag for the address
5506dd94e8SGustavo Romero        # in {ta} matches the logical tag in {ta}.
5606dd94e8SGustavo 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
6706dd94e8SGustavo Romero        # address starting at {ta} address to a known value, i.e. 0x04.
6806dd94e8SGustavo 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
7206dd94e8SGustavo Romero        # set correctly and don't run over each other.
7306dd94e8SGustavo 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
7706dd94e8SGustavo 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
8006dd94e8SGustavo 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.
8906dd94e8SGustavo 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.
9406dd94e8SGustavo 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
9706dd94e8SGustavo 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:
10606dd94e8SGustavo Romero        # This usually happens because a GDB version that does not support
10706dd94e8SGustavo 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