xref: /llvm-project/libcxx/utils/qemu_baremetal.py (revision acbb491ab23fd04e201b58195f78e04c5a647d47)
1d002ce55SAlexander Richardson#!/usr/bin/env python3
2d002ce55SAlexander Richardson# ===----------------------------------------------------------------------===##
3d002ce55SAlexander Richardson#
4d002ce55SAlexander Richardson# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5d002ce55SAlexander Richardson# See https://llvm.org/LICENSE.txt for license information.
6d002ce55SAlexander Richardson# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7d002ce55SAlexander Richardson#
8d002ce55SAlexander Richardson# ===----------------------------------------------------------------------===##
9d002ce55SAlexander Richardson
10d002ce55SAlexander Richardson"""qemu_baremetal.py is a utility for running a program with QEMU's system mode.
11d002ce55SAlexander Richardson
12d002ce55SAlexander RichardsonIt is able to pass command line arguments to the program and forward input and
13d002ce55SAlexander Richardsonoutput (if the underlying baremetal enviroment supports QEMU semihosting).
14d002ce55SAlexander Richardson"""
15d002ce55SAlexander Richardson
16d002ce55SAlexander Richardsonimport argparse
17d002ce55SAlexander Richardsonimport os
18d002ce55SAlexander Richardsonimport sys
19*acbb491aSDavid Spickettimport shutil
20d002ce55SAlexander Richardson
21d002ce55SAlexander Richardson
22d002ce55SAlexander Richardsondef main():
23d002ce55SAlexander Richardson    parser = argparse.ArgumentParser()
24d002ce55SAlexander Richardson    parser.add_argument("--qemu", type=str, required=True)
25d002ce55SAlexander Richardson    parser.add_argument("--cpu", type=str, required=False)
26d002ce55SAlexander Richardson    parser.add_argument("--machine", type=str, default="virt")
27d002ce55SAlexander Richardson    parser.add_argument(
28d002ce55SAlexander Richardson        "--qemu-arg", dest="qemu_args", type=str, action="append", default=[]
29d002ce55SAlexander Richardson    )
30d002ce55SAlexander Richardson    parser.add_argument("--semihosting", action="store_true", default=True)
31d002ce55SAlexander Richardson    parser.add_argument("--no-semihosting", dest="semihosting", action="store_false")
32d002ce55SAlexander Richardson    parser.add_argument("--execdir", type=str, required=True)
33d002ce55SAlexander Richardson    parser.add_argument("test_binary")
34d002ce55SAlexander Richardson    parser.add_argument("test_args", nargs=argparse.ZERO_OR_MORE, default=[])
35d002ce55SAlexander Richardson    args = parser.parse_args()
36*acbb491aSDavid Spickett
37*acbb491aSDavid Spickett    if not shutil.which(args.qemu):
38*acbb491aSDavid Spickett        sys.exit(f"Failed to find QEMU binary from --qemu value: '{args.qemu}'")
39*acbb491aSDavid Spickett
40d002ce55SAlexander Richardson    if not os.path.exists(args.test_binary):
41d002ce55SAlexander Richardson        sys.exit(f"Expected argument to be a test executable: '{args.test_binary}'")
42*acbb491aSDavid Spickett
43d002ce55SAlexander Richardson    qemu_commandline = [
44d002ce55SAlexander Richardson        args.qemu,
45d002ce55SAlexander Richardson        "-chardev",
46d002ce55SAlexander Richardson        "stdio,mux=on,id=stdio0",
47d002ce55SAlexander Richardson        "-monitor",
48d002ce55SAlexander Richardson        "none",
49d002ce55SAlexander Richardson        "-serial",
50d002ce55SAlexander Richardson        "none",
51d002ce55SAlexander Richardson        "-machine",
52d002ce55SAlexander Richardson        f"{args.machine},accel=tcg",
53d002ce55SAlexander Richardson        "-device",
54d002ce55SAlexander Richardson        f"loader,file={args.test_binary},cpu-num=0",
55d002ce55SAlexander Richardson        "-nographic",
56d002ce55SAlexander Richardson        *args.qemu_args,
57d002ce55SAlexander Richardson    ]
58d002ce55SAlexander Richardson    if args.cpu:
59d002ce55SAlexander Richardson        qemu_commandline += ["-cpu", args.cpu]
60d002ce55SAlexander Richardson
61d002ce55SAlexander Richardson    if args.semihosting:
62d002ce55SAlexander Richardson        # Use QEMU's semihosting support to pass argv (supported by picolibc)
63d002ce55SAlexander Richardson        semihosting_config = f"enable=on,chardev=stdio0,arg={args.test_binary}"
64d002ce55SAlexander Richardson        for arg in args.test_args:
65d002ce55SAlexander Richardson            semihosting_config += f",arg={arg}"
66d002ce55SAlexander Richardson        qemu_commandline += ["-semihosting-config", semihosting_config]
67d002ce55SAlexander Richardson    elif args.test_args:
68d002ce55SAlexander Richardson        sys.exit(
69d002ce55SAlexander Richardson            "Got non-empty test arguments but do no know how to pass them to "
70d002ce55SAlexander Richardson            "QEMU without semihosting support"
71d002ce55SAlexander Richardson        )
72d002ce55SAlexander Richardson    os.execvp(qemu_commandline[0], qemu_commandline)
73d002ce55SAlexander Richardson
74d002ce55SAlexander Richardson
75d002ce55SAlexander Richardsonif __name__ == "__main__":
76d002ce55SAlexander Richardson    exit(main())
77