xref: /qemu/tests/tcg/multiarch/gdbstub/interrupt.py (revision 7893e42d5d9cafeeab30a114e8ec86517f8a1b36)
1761e3c10SMatheus Branco Borellafrom __future__ import print_function
2761e3c10SMatheus Branco Borella#
3*7893e42dSPhilippe Mathieu-Daudé# Test some of the system debug features with the multiarch memory
4761e3c10SMatheus Branco Borella# test. It is a port of the original vmlinux focused test case but
5761e3c10SMatheus Branco Borella# using the "memory" test instead.
6761e3c10SMatheus Branco Borella#
7761e3c10SMatheus Branco Borella# This is launched via tests/guest-debug/run-test.py
8761e3c10SMatheus Branco Borella#
9761e3c10SMatheus Branco Borella
10761e3c10SMatheus Branco Borellaimport gdb
11761e3c10SMatheus Branco Borellaimport sys
12761e3c10SMatheus Branco Borella
13761e3c10SMatheus Branco Borellafailcount = 0
14761e3c10SMatheus Branco Borella
15761e3c10SMatheus Branco Borella
16761e3c10SMatheus Branco Borelladef report(cond, msg):
17761e3c10SMatheus Branco Borella    "Report success/fail of test"
18761e3c10SMatheus Branco Borella    if cond:
19761e3c10SMatheus Branco Borella        print("PASS: %s" % (msg))
20761e3c10SMatheus Branco Borella    else:
21761e3c10SMatheus Branco Borella        print("FAIL: %s" % (msg))
22761e3c10SMatheus Branco Borella        global failcount
23761e3c10SMatheus Branco Borella        failcount += 1
24761e3c10SMatheus Branco Borella
25761e3c10SMatheus Branco Borella
26761e3c10SMatheus Branco Borelladef check_interrupt(thread):
27761e3c10SMatheus Branco Borella    """
28761e3c10SMatheus Branco Borella    Check that, if thread is resumed, we go back to the same thread when the
29761e3c10SMatheus Branco Borella    program gets interrupted.
30761e3c10SMatheus Branco Borella    """
31761e3c10SMatheus Branco Borella
32761e3c10SMatheus Branco Borella    # Switch to the thread we're going to be running the test in.
33761e3c10SMatheus Branco Borella    print("thread ", thread.num)
34761e3c10SMatheus Branco Borella    gdb.execute("thr %d" % thread.num)
35761e3c10SMatheus Branco Borella
36761e3c10SMatheus Branco Borella    # Enter the loop() function on this thread.
37761e3c10SMatheus Branco Borella    #
38761e3c10SMatheus Branco Borella    # While there are cleaner ways to do this, we want to minimize the number of
39761e3c10SMatheus Branco Borella    # side effects on the gdbstub's internal state, since those may mask bugs.
40761e3c10SMatheus Branco Borella    # Ideally, there should be no difference between what we're doing here and
41761e3c10SMatheus Branco Borella    # the program reaching the loop() function on its own.
42761e3c10SMatheus Branco Borella    #
43761e3c10SMatheus Branco Borella    # For this to be safe, we only need the prologue of loop() to not have
44761e3c10SMatheus Branco Borella    # instructions that may have problems with what we're doing here. We don't
45761e3c10SMatheus Branco Borella    # have to worry about anything else, as this function never returns.
46761e3c10SMatheus Branco Borella    gdb.execute("set $pc = loop")
47761e3c10SMatheus Branco Borella
48761e3c10SMatheus Branco Borella    # Continue and then interrupt the task.
49761e3c10SMatheus Branco Borella    gdb.post_event(lambda: gdb.execute("interrupt"))
50761e3c10SMatheus Branco Borella    gdb.execute("c")
51761e3c10SMatheus Branco Borella
52761e3c10SMatheus Branco Borella    # Check whether the thread we're in after the interruption is the same we
53761e3c10SMatheus Branco Borella    # ran continue from.
54761e3c10SMatheus Branco Borella    return (thread.num == gdb.selected_thread().num)
55761e3c10SMatheus Branco Borella
56761e3c10SMatheus Branco Borella
57761e3c10SMatheus Branco Borelladef run_test():
58761e3c10SMatheus Branco Borella    """
59761e3c10SMatheus Branco Borella    Test if interrupting the code always lands us on the same thread when
60761e3c10SMatheus Branco Borella    running with scheduler-lock enabled.
61761e3c10SMatheus Branco Borella    """
62761e3c10SMatheus Branco Borella
63761e3c10SMatheus Branco Borella    gdb.execute("set scheduler-locking on")
64761e3c10SMatheus Branco Borella    for thread in gdb.selected_inferior().threads():
65761e3c10SMatheus Branco Borella        report(check_interrupt(thread),
66761e3c10SMatheus Branco Borella               "thread %d resumes correctly on interrupt" % thread.num)
67761e3c10SMatheus Branco Borella
68761e3c10SMatheus Branco Borella
69761e3c10SMatheus Branco Borella#
70761e3c10SMatheus Branco Borella# This runs as the script it sourced (via -x, via run-test.py)
71761e3c10SMatheus Branco Borella#
72761e3c10SMatheus Branco Borellatry:
73761e3c10SMatheus Branco Borella    inferior = gdb.selected_inferior()
74761e3c10SMatheus Branco Borella    arch = inferior.architecture()
75761e3c10SMatheus Branco Borella    print("ATTACHED: %s" % arch.name())
76761e3c10SMatheus Branco Borellaexcept (gdb.error, AttributeError):
77761e3c10SMatheus Branco Borella    print("SKIPPING (not connected)", file=sys.stderr)
78761e3c10SMatheus Branco Borella    exit(0)
79761e3c10SMatheus Branco Borella
80761e3c10SMatheus Branco Borellaif gdb.parse_and_eval('$pc') == 0:
81761e3c10SMatheus Branco Borella    print("SKIP: PC not set")
82761e3c10SMatheus Branco Borella    exit(0)
83761e3c10SMatheus Branco Borellaif len(gdb.selected_inferior().threads()) == 1:
84761e3c10SMatheus Branco Borella    print("SKIP: set to run on a single thread")
85761e3c10SMatheus Branco Borella    exit(0)
86761e3c10SMatheus Branco Borella
87761e3c10SMatheus Branco Borellatry:
88761e3c10SMatheus Branco Borella    # Run the actual tests
89761e3c10SMatheus Branco Borella    run_test()
90761e3c10SMatheus Branco Borellaexcept (gdb.error):
91761e3c10SMatheus Branco Borella    print("GDB Exception: %s" % (sys.exc_info()[0]))
92761e3c10SMatheus Branco Borella    failcount += 1
93761e3c10SMatheus Branco Borella    pass
94761e3c10SMatheus Branco Borella
95761e3c10SMatheus Branco Borella# Finally kill the inferior and exit gdb with a count of failures
96761e3c10SMatheus Branco Borellagdb.execute("kill")
97761e3c10SMatheus Branco Borellaexit(failcount)
98