mirror of
https://gitlab.com/qemu-project/qemu.git
synced 2026-10-28 14:04:39 +08:00
Merge tag 'pull-11.2-gdbstub-kvm-231026-1' of https://gitlab.com/stsquad/qemu into staging
testing updates (tcg, gdbstub): - make sure we have TCG to run test_acpi_bits - fix overflow in linux-sigrtminmax - make .dir-locals aware of PYTHONPATH - detect gdb in top-level meson - fetch kernel assets with symbols for x86, aarch64 and s390 tuxruns - use arrays in gdb run-test to make quoting less messy - add support for --symbols and --kargs to gdbstub run-test.py - restore old kvm gdb test script with a few fixes - add tuxrun_kvm_gdb tests for x86,aarch64 and s390 # -----BEGIN PGP SIGNATURE----- # # iQEzBAABCgAdFiEEZoWumedRZ7yvyN81+9DbCVqeKkQFAmrbjRYACgkQ+9DbCVqe # KkTtGwf/eDJawSsUD6rDYuNEegv5buJVlE5Vkh8EUUSbrr56xstPlclLXZQbXZKN # gGxw7RGpoZZMUN/RGRbV001E6HhsUhWjkSDFGOH21MkQUj9OPVlroPhFPo+m0Xvb # ppXSRvK09tXlM7YKFS8GWOT5sYzsHl/b5nbI2UONlLDmLl0futFlVeTMQ/qptR7t # EKzsi86O6iEb69TuFlypZnIf++NsXYhcgSf/3pWGzLDBcstM+PDqHQn5Y+TTZUS3 # S56sCr6ihLNPRZl3ynkQvFArln3lO8I/K6RlOssRtUZ9QKV0oQ2aZDvMIqBytxBe # sfBhrL/KrLgL8Uw4S8sQELXR8we+Bg== # =u32E # -----END PGP SIGNATURE----- # gpg: Signature made Fri 23 Oct 2026 06:36:38 PM CEST # gpg: using RSA key 6685AE99E75167BCAFC8DF35FBD0DB095A9E2A44 # gpg: Good signature from "Alex Bennée (Master Work Key) <alex.bennee@linaro.org>" [unknown] # gpg: WARNING: This key is not certified with a trusted signature! # gpg: There is no indication that the signature belongs to the owner. # Primary key fingerprint: 6685 AE99 E751 67BC AFC8 DF35 FBD0 DB09 5A9E 2A44 * tag 'pull-11.2-gdbstub-kvm-231026-1' of https://gitlab.com/stsquad/qemu: tests/functional: add tuxrun kvm gdb test for s390x tests/functional: update s390x tuxrun images tests/functional: split s390x tuxrun into tcg and kvm run tests/functional: add tuxrun kvm gdb test for arm64 tests/functional: update arm64 tuxrun images tests/functional: split aarch64 tuxrun into tcg and kvm run tests/functional: add tuxrun kvm gdb test for x86_64 tests/functional: teach tuxrun about launching gdb tests tests/guest-debug: add --symbols option to run-test tests/guest-debug: add --kargs option to run-test tests/guest-debug: convert cmd to an qemu_cmd array tests/guest-debug: convert gdb_cmd to an array tests/functional: update x86_64 tuxrun images tests/functional: split x86_64 tuxrun into tcg and kvm run tests/functional: allow tuxrun tests to be passed "accel" meson: move gdb detection into the top level build file .dir-locals: include QEMU code in PYTHONPATH tests/tcg: fix buffer overflow in multiarch/linux/linux-sigrtminmax tests/functional: test_acpi_bits requires TCG Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
commit
594bf10d18
13 files changed
+444
-74
No files matched your search
+7
-1
@@ -1,2 +1,8 @@
|
||||
((c-mode . ((c-file-style . "stroustrup")
|
||||
(indent-tabs-mode . nil))))
|
||||
(indent-tabs-mode . nil)))
|
||||
(python-mode .
|
||||
((eval . (when-let* ((root (locate-dominating-file default-directory ".dir-locals.el")))
|
||||
(setq-local process-environment (copy-sequence process-environment))
|
||||
(setenv "PYTHONPATH"
|
||||
(concat (expand-file-name "python" root) ":"
|
||||
(expand-file-name "tests/functional" root))))))))
|
||||
+7
-8
@@ -163,6 +163,12 @@ else
|
||||
iasl = find_program(get_option('iasl'), required: true)
|
||||
endif
|
||||
|
||||
if get_option('gdb') == ''
|
||||
gdb = find_program(['gdb-multiarch', 'gdb'], required: false)
|
||||
else
|
||||
gdb = find_program(get_option('gdb'), required: true)
|
||||
endif
|
||||
|
||||
edk2_targets = [ 'arm-softmmu', 'aarch64-softmmu', 'i386-softmmu', 'x86_64-softmmu', 'riscv64-softmmu', 'loongarch64-softmmu' ]
|
||||
unpack_edk2_blobs = false
|
||||
foreach target : edk2_targets
|
||||
@@ -4710,14 +4716,7 @@ summary(summary_info, bool_yn: true, section: 'Directories')
|
||||
summary_info = {}
|
||||
summary_info += {'python': '@0@ (version: @1@)'.format(python.full_path(), python.language_version())}
|
||||
summary_info += {'sphinx-build': sphinx_build}
|
||||
|
||||
# FIXME: the [binaries] section of machine files, which can be probed
|
||||
# with find_program(), would be great for passing gdb and genisoimage
|
||||
# paths from configure to Meson. However, there seems to be no way to
|
||||
# hide a program (for example if gdb is too old).
|
||||
if config_host.has_key('GDB')
|
||||
summary_info += {'gdb': config_host['GDB']}
|
||||
endif
|
||||
summary_info += {'gdb': gdb}
|
||||
summary_info += {'iasl': iasl}
|
||||
summary_info += {'genisoimage': config_host['GENISOIMAGE']}
|
||||
if host_os == 'windows' and have_ga
|
||||
|
||||
@@ -11,17 +11,20 @@
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
from qemu_test import Asset
|
||||
from qemu_test import Asset, skipIfMissingEnv
|
||||
from qemu_test.tuxruntest import TuxRunBaselineTest
|
||||
|
||||
class TuxRunAarch64Test(TuxRunBaselineTest):
|
||||
|
||||
ASSET_ARM64_KERNEL = Asset(
|
||||
'https://storage.tuxboot.com/buildroot/20241119/arm64/Image',
|
||||
'b74743c5e89e1cea0f73368d24ae0ae85c5204ff84be3b5e9610417417d2f235')
|
||||
'https://storage.tuxboot.com/kernels/6.18.54/arm64/Image.gz',
|
||||
'39f4633bbcb444267d4d829bd28d8868a287c4c160cda64b0fd23fb090571c4e')
|
||||
ASSET_ARM64_VMLINUX = Asset(
|
||||
'https://storage.tuxboot.com/kernels/6.18.54/arm64/vmlinux.xz',
|
||||
'6487eb113ef6e841aedab6cb6fa704006377d68f64dd544570aa42f462a52b85')
|
||||
ASSET_ARM64_ROOTFS = Asset(
|
||||
'https://storage.tuxboot.com/buildroot/20241119/arm64/rootfs.ext4.zst',
|
||||
'a1acaaae2068df4648d04ff75f532aaa8c5edcd6b936122b6f0db4848a07b465')
|
||||
'https://storage.tuxboot.com/buildroot/20260924/arm64/rootfs.ext4.zst',
|
||||
'4ab8cec9d1e17dbb1abdf2ae1939ad4f9d0dc2466230f6a119a7c1845cdef0b1')
|
||||
|
||||
def test_arm64(self):
|
||||
self.set_machine('virt')
|
||||
@@ -32,6 +35,28 @@ class TuxRunAarch64Test(TuxRunBaselineTest):
|
||||
self.common_tuxrun(kernel_asset=self.ASSET_ARM64_KERNEL,
|
||||
rootfs_asset=self.ASSET_ARM64_ROOTFS)
|
||||
|
||||
def test_arm64_kvm(self):
|
||||
self.set_machine('virt')
|
||||
self.require_accelerator('kvm')
|
||||
self.cpu='host'
|
||||
self.console='ttyAMA0'
|
||||
self.wait_for_shutdown=False
|
||||
self.common_tuxrun(kernel_asset=self.ASSET_ARM64_KERNEL,
|
||||
rootfs_asset=self.ASSET_ARM64_ROOTFS,
|
||||
accel="kvm")
|
||||
|
||||
@skipIfMissingEnv("QEMU_TEST_GDB")
|
||||
def test_arm64_kvm_gdb(self):
|
||||
self.set_machine('virt')
|
||||
self.require_accelerator('kvm')
|
||||
self.cpu='host'
|
||||
self.console='ttyAMA0'
|
||||
self.wait_for_shutdown=False
|
||||
self.common_tuxrun_gdb(kernel_asset=self.ASSET_ARM64_KERNEL,
|
||||
vmlinux_asset=self.ASSET_ARM64_VMLINUX,
|
||||
rootfs_asset=self.ASSET_ARM64_ROOTFS,
|
||||
accel="kvm")
|
||||
|
||||
ASSET_ARM64BE_KERNEL = Asset(
|
||||
'https://storage.tuxboot.com/buildroot/20241119/arm64be/Image',
|
||||
'fd6af4f16689d17a2c24fe0053cc212edcdf77abdcaf301800b8d38fa9f6e109')
|
||||
|
||||
@@ -0,0 +1,164 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
#
|
||||
# Generic Kernel GDB script to verify functionality:
|
||||
# - Single-stepping
|
||||
# - Hardware breakpoints
|
||||
# - Software breakpoints
|
||||
# - Watchpoints
|
||||
#
|
||||
# It relies on fairly common kernel points to break at and symbols for
|
||||
# the kernel. Address space randomisation (kaslr) needs to be disabled.
|
||||
#
|
||||
# Copyright (c) 2026 Linaro Limited
|
||||
#
|
||||
# Author:
|
||||
# Alex Bennée <alex.bennee@linaro.org>
|
||||
#
|
||||
# This is launched by the tuxrun functional tests via tests/guest-debug/run-test.py
|
||||
|
||||
import gdb
|
||||
from test_gdbstub import main, report
|
||||
|
||||
def parse_registers():
|
||||
"""Parse 'info registers' into a name -> value dictionary."""
|
||||
regs = {}
|
||||
for line in gdb.execute("info registers", to_string=True).splitlines():
|
||||
parts = line.split()
|
||||
if len(parts) >= 2:
|
||||
regs[parts[0]] = parts[1]
|
||||
return regs
|
||||
|
||||
|
||||
def check_step():
|
||||
"Step an instruction, check it moved."
|
||||
start_pc = gdb.parse_and_eval('$pc')
|
||||
gdb.execute("si")
|
||||
end_pc = gdb.parse_and_eval('$pc')
|
||||
|
||||
return not (start_pc == end_pc)
|
||||
|
||||
|
||||
def check_reg_updates(regs_start):
|
||||
regs_end = parse_registers()
|
||||
|
||||
changed = [k for k in regs_start
|
||||
if k in regs_end and regs_start[k] != regs_end[k]]
|
||||
|
||||
report(len(changed) > 0, f"{len(changed)} registers changed.")
|
||||
|
||||
|
||||
def check_break(sym_name):
|
||||
"Setup breakpoint, continue and check we stopped."
|
||||
bp = gdb.Breakpoint(sym_name)
|
||||
gdb.execute("c")
|
||||
res = bp.hit_count == 1
|
||||
bp.delete()
|
||||
|
||||
return res
|
||||
|
||||
|
||||
def check_hbreak(sym_name):
|
||||
"Setup hardware breakpoint, continue and check we stopped."
|
||||
bp = gdb.Breakpoint(sym_name, type = gdb.BP_HARDWARE_BREAKPOINT)
|
||||
gdb.execute("c")
|
||||
res = bp.hit_count == 1
|
||||
bp.delete()
|
||||
|
||||
return res
|
||||
|
||||
|
||||
class WatchPoint(gdb.Breakpoint):
|
||||
|
||||
def __init__(self, sym_name, type):
|
||||
super(WatchPoint, self).__init__(sym_name, gdb.BP_WATCHPOINT, type)
|
||||
|
||||
def stop(self):
|
||||
end_pc = gdb.parse_and_eval('$pc')
|
||||
print("HIT WP @ %s" % (end_pc))
|
||||
return True
|
||||
|
||||
|
||||
def do_one_watch(sym, wtype, text):
|
||||
|
||||
wp = WatchPoint(sym, wtype)
|
||||
gdb.execute("c")
|
||||
report_str = "%s for %s" % (text, sym)
|
||||
|
||||
if wp.hit_count > 0:
|
||||
report(True, report_str)
|
||||
else:
|
||||
report(False, report_str)
|
||||
|
||||
wp.delete()
|
||||
|
||||
|
||||
def check_watches(sym_name):
|
||||
"Watch a symbol for any access."
|
||||
|
||||
# s390 only supports write watchpoints
|
||||
if "s390" not in gdb.selected_frame().architecture().name():
|
||||
# Should hit for any read
|
||||
do_one_watch(sym_name, gdb.WP_ACCESS, "awatch")
|
||||
|
||||
# Again should hit for reads
|
||||
do_one_watch(sym_name, gdb.WP_READ, "rwatch")
|
||||
|
||||
# Finally when it is written
|
||||
do_one_watch(sym_name, gdb.WP_WRITE, "watch")
|
||||
|
||||
|
||||
class CatchBreakpoint(gdb.Breakpoint):
|
||||
def __init__(self, sym_name):
|
||||
super(CatchBreakpoint, self).__init__(sym_name, type = gdb.BP_BREAKPOINT)
|
||||
self.sym, ok = gdb.lookup_symbol(sym_name)
|
||||
|
||||
def stop(self):
|
||||
end_pc = gdb.parse_and_eval('$pc')
|
||||
print("CB: %s == %s" % (end_pc, self.sym.value()))
|
||||
if end_pc == self.sym.value():
|
||||
report(False, "Hit final catchpoint")
|
||||
|
||||
|
||||
def run_test():
|
||||
"Run through the tests one by one"
|
||||
|
||||
# get the initial register state
|
||||
regs_start = parse_registers()
|
||||
|
||||
print("Checking we can step the first few instructions")
|
||||
step_ok = 0
|
||||
for i in range(3):
|
||||
if check_step():
|
||||
step_ok += 1
|
||||
|
||||
report(step_ok == 3, "single step in boot code")
|
||||
|
||||
# check some registers changed
|
||||
print("Checking register access works")
|
||||
check_reg_updates(regs_start)
|
||||
|
||||
print("Checking HW breakpoint works")
|
||||
break_ok = check_hbreak("kernel_init")
|
||||
report(break_ok, "hbreak @ kernel_init")
|
||||
|
||||
# Can't set this up until we are in the kernel proper
|
||||
# if we make it to run_init_process we've over-run and
|
||||
# one of the tests failed
|
||||
|
||||
print("Setup catch-all for run_init_process")
|
||||
cbp = CatchBreakpoint("run_init_process")
|
||||
|
||||
# We should see wait_for_completion called right at the start of
|
||||
# kernel_init
|
||||
print("Checking Normal breakpoint works")
|
||||
break_ok = check_break("wait_for_completion")
|
||||
report(break_ok, "break @ wait_for_completion")
|
||||
|
||||
print("Checking watchpoint works")
|
||||
check_watches("system_state")
|
||||
|
||||
# check we didn't hit the end
|
||||
report(cbp.hit_count == 0, "CatchBreakpoint not hit")
|
||||
|
||||
|
||||
main(run_test)
|
||||
@@ -83,9 +83,8 @@ foreach speed : ['quick', 'thorough']
|
||||
separator : ':')
|
||||
|
||||
# Define the GDB environment variable if gdb is available.
|
||||
gdb = get_option('gdb')
|
||||
if gdb != ''
|
||||
test_env.set('QEMU_TEST_GDB', gdb)
|
||||
if gdb.found()
|
||||
test_env.set('QEMU_TEST_GDB', gdb.full_path())
|
||||
endif
|
||||
|
||||
foreach test : target_tests
|
||||
|
||||
@@ -9,7 +9,10 @@
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
import logging
|
||||
import os
|
||||
import shlex
|
||||
import subprocess
|
||||
|
||||
from qemu_test import QemuSystemTest
|
||||
from qemu_test import exec_command_and_wait_for_pattern
|
||||
@@ -18,7 +21,8 @@ from qemu_test import which, get_qemu_img
|
||||
|
||||
class TuxRunBaselineTest(QemuSystemTest):
|
||||
|
||||
KERNEL_COMMON_COMMAND_LINE = 'printk.time=0'
|
||||
# nokaslr is needed for gdb tests but it makes things simpler anyway
|
||||
KERNEL_COMMON_COMMAND_LINE = 'printk.time=0 nokaslr'
|
||||
# Tests are ~10-40s, allow for --debug/--enable-gcov overhead
|
||||
timeout = 100
|
||||
|
||||
@@ -55,17 +59,20 @@ class TuxRunBaselineTest(QemuSystemTest):
|
||||
failure_message='Kernel panic - not syncing',
|
||||
vm=vm)
|
||||
|
||||
def fetch_tuxrun_assets(self, kernel_asset, rootfs_asset, dtb_asset=None):
|
||||
def fetch_tuxrun_assets(self, kernel_asset, rootfs_asset,
|
||||
dtb_asset=None, vmlinux_asset=None):
|
||||
"""
|
||||
Fetch the TuxBoot assets.
|
||||
"""
|
||||
kernel_image = kernel_asset.fetch()
|
||||
disk_image = self.uncompress(rootfs_asset)
|
||||
dtb = dtb_asset.fetch() if dtb_asset is not None else None
|
||||
vmlinux = self.uncompress(vmlinux_asset) if vmlinux_asset is not None else None
|
||||
|
||||
return (kernel_image, disk_image, dtb)
|
||||
return (kernel_image, disk_image, dtb, vmlinux)
|
||||
|
||||
def prepare_run(self, kernel, disk, drive, dtb=None, console_index=0):
|
||||
def prepare_run(self, accel, kernel, disk, drive,
|
||||
dtb=None, console_index=0, append = True):
|
||||
"""
|
||||
Setup to run and add the common parameters to the system
|
||||
"""
|
||||
@@ -79,9 +86,19 @@ class TuxRunBaselineTest(QemuSystemTest):
|
||||
self.kcmd_line += f" root=/dev/{self.root}"
|
||||
self.kcmd_line += f" console={self.console}"
|
||||
|
||||
self.vm.add_args('-kernel', kernel,
|
||||
'-append', self.kcmd_line,
|
||||
'-blockdev', blockdev)
|
||||
# have we specified an accelerator?
|
||||
if accel:
|
||||
self.vm.add_args('-accel', accel)
|
||||
|
||||
if kernel:
|
||||
self.vm.add_args('-kernel', kernel)
|
||||
|
||||
# When using the gdb run script we might not want to include
|
||||
# the kcmd line directly in the QEMU args.
|
||||
if append:
|
||||
self.vm.add_args('-append', self.kcmd_line)
|
||||
|
||||
self.vm.add_args('-blockdev', blockdev)
|
||||
|
||||
# Sometimes we need extra devices attached
|
||||
if self.extradev:
|
||||
@@ -118,6 +135,7 @@ class TuxRunBaselineTest(QemuSystemTest):
|
||||
def common_tuxrun(self,
|
||||
kernel_asset,
|
||||
rootfs_asset,
|
||||
accel=None,
|
||||
dtb_asset=None,
|
||||
drive="virtio-blk-device",
|
||||
haltmsg="reboot: System halted",
|
||||
@@ -127,10 +145,80 @@ class TuxRunBaselineTest(QemuSystemTest):
|
||||
special with the command line we can process most things using
|
||||
the tag metadata.
|
||||
"""
|
||||
(kernel, disk, dtb) = self.fetch_tuxrun_assets(kernel_asset, rootfs_asset,
|
||||
dtb_asset)
|
||||
(kernel, disk, dtb, _) = self.fetch_tuxrun_assets(kernel_asset,
|
||||
rootfs_asset,
|
||||
dtb_asset)
|
||||
|
||||
self.prepare_run(kernel, disk, drive, dtb, console_index)
|
||||
self.prepare_run(accel, kernel, disk, drive, dtb, console_index)
|
||||
self.vm.launch()
|
||||
self.run_tuxtest_tests(haltmsg)
|
||||
os.remove(disk)
|
||||
|
||||
def common_tuxrun_gdb(self,
|
||||
kernel_asset,
|
||||
vmlinux_asset,
|
||||
rootfs_asset,
|
||||
accel=None,
|
||||
dtb_asset=None,
|
||||
symbol_off = None,
|
||||
drive="virtio-blk-device",
|
||||
console_index=0):
|
||||
"""
|
||||
Common path for LKFT tests under gdb. Unlike the common_tuxrun
|
||||
function we need to launch with the gdb test script and deal
|
||||
with munging the arguments for that especially.
|
||||
"""
|
||||
(kernel, disk, dtb, vmlinux) = self.fetch_tuxrun_assets(kernel_asset,
|
||||
rootfs_asset,
|
||||
dtb_asset,
|
||||
vmlinux_asset)
|
||||
|
||||
gdb_path = os.getenv("QEMU_TEST_GDB")
|
||||
run_script = self.data_file('..', 'guest-debug','run-test.py')
|
||||
test_script = self.data_file('gdb-scripts', 'kernel_gdb_test.py')
|
||||
|
||||
# Instead of launching QEMU via the functional test machinery
|
||||
# we need to launch it with the gdb run script. We utilise the
|
||||
# existing prepare_run machinery to build the command line but
|
||||
# we pass the kernel args separately to avoid horrible string
|
||||
# escaping.
|
||||
|
||||
self.prepare_run(accel, kernel, disk, drive, dtb,
|
||||
console_index, append = False)
|
||||
|
||||
# the functional test machinery adds more stuff for handling
|
||||
# console redirection which we need to do manually.
|
||||
|
||||
qargs = self.vm.args
|
||||
qargs.extend(["-display", "none", "-serial", "stdio"])
|
||||
|
||||
# and the machine type
|
||||
if self.vm._machine is not None:
|
||||
qargs.extend(["-machine", self.vm._machine])
|
||||
|
||||
cmd = [
|
||||
str(run_script),
|
||||
"--qemu", self.qemu_bin,
|
||||
"--qargs", shlex.join(qargs),
|
||||
"--kargs", self.kcmd_line,
|
||||
"--symbols", str(vmlinux),
|
||||
"--test", str(test_script),
|
||||
"--gdb", gdb_path,
|
||||
]
|
||||
|
||||
if symbol_off is not None:
|
||||
cmd.extend(["--symbol-offset", f"{symbol_off}"])
|
||||
|
||||
log_cmd = " ".join(f'"{arg}"' if ' ' in arg else arg for arg in cmd)
|
||||
self.log.info(f"run-test: {log_cmd}")
|
||||
|
||||
res = subprocess.run(cmd, text=True,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.STDOUT)
|
||||
|
||||
if res.stdout:
|
||||
console_logger = logging.getLogger('console')
|
||||
console_logger.info(res.stdout)
|
||||
|
||||
self.assertEqual(res.returncode, 0,
|
||||
f"run-test.py failed ({res.returncode}):\n")
|
||||
@@ -11,25 +11,52 @@
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
from qemu_test import Asset
|
||||
from qemu_test import Asset, skipIfMissingEnv
|
||||
from qemu_test.tuxruntest import TuxRunBaselineTest
|
||||
|
||||
class TuxRunS390xTest(TuxRunBaselineTest):
|
||||
|
||||
ASSET_S390X_KERNEL = Asset(
|
||||
'https://storage.tuxboot.com/buildroot/20241119/s390/bzImage',
|
||||
'ee67e91db52a2aed104a7c72b2a08987c678f8179c029626789c35d6dd0fedf1')
|
||||
'https://storage.tuxboot.com/kernels/6.18.54/s390/bzImage',
|
||||
'5efeb31754b211440e1595ab11355bb006fe78a2c0604ed0a8c55c4598b71aec')
|
||||
ASSET_S390X_VMLINUX = Asset(
|
||||
'https://storage.tuxboot.com/kernels/6.18.54/s390/vmlinux.xz',
|
||||
'5bbd4d34e0950f88053a9bfd16078896df4b1ee1696fc2ad62488e681a6bdd8e')
|
||||
ASSET_S390X_ROOTFS = Asset(
|
||||
'https://storage.tuxboot.com/buildroot/20241119/s390/rootfs.ext4.zst',
|
||||
'bff7971fc2fef56372d98afe4557b82fd0a785a241e44c29b058e577ad1bbb44')
|
||||
'https://storage.tuxboot.com/buildroot/20260924/s390/rootfs.ext4.zst',
|
||||
'5ba18c4d18831c50a0c743990f7bdee1d3b520629d423c55b668d8fbbac9c6f5')
|
||||
|
||||
def test_s390(self):
|
||||
self.set_machine('s390-ccw-virtio')
|
||||
self.require_accelerator('tcg')
|
||||
self.wait_for_shutdown=False
|
||||
self.common_tuxrun(kernel_asset=self.ASSET_S390X_KERNEL,
|
||||
rootfs_asset=self.ASSET_S390X_ROOTFS,
|
||||
drive="virtio-blk-ccw",
|
||||
haltmsg="Requesting system halt")
|
||||
|
||||
def test_s390_kvm(self):
|
||||
self.set_machine('s390-ccw-virtio')
|
||||
self.require_accelerator('kvm')
|
||||
self.wait_for_shutdown=False
|
||||
self.common_tuxrun(kernel_asset=self.ASSET_S390X_KERNEL,
|
||||
rootfs_asset=self.ASSET_S390X_ROOTFS,
|
||||
drive="virtio-blk-ccw",
|
||||
haltmsg="Requesting system halt",
|
||||
accel="kvm")
|
||||
|
||||
@skipIfMissingEnv("QEMU_TEST_GDB")
|
||||
def test_s390_kvm_gdb(self):
|
||||
self.set_machine('s390-ccw-virtio')
|
||||
self.require_accelerator('kvm')
|
||||
self.wait_for_shutdown=False
|
||||
self.common_tuxrun_gdb(kernel_asset=self.ASSET_S390X_KERNEL,
|
||||
vmlinux_asset=self.ASSET_S390X_VMLINUX,
|
||||
rootfs_asset=self.ASSET_S390X_ROOTFS,
|
||||
symbol_off="0x3ffe0000000",
|
||||
drive="virtio-blk-ccw",
|
||||
haltmsg="Requesting system halt",
|
||||
accel="kvm")
|
||||
|
||||
if __name__ == '__main__':
|
||||
TuxRunBaselineTest.main()
|
||||
@@ -31,11 +31,11 @@ class TuxRunSh4Test(TuxRunBaselineTest):
|
||||
|
||||
# The test is currently too unstable to do much in userspace
|
||||
# so we skip common_tuxrun and do a minimal boot and shutdown.
|
||||
(kernel, disk, dtb) = self.fetch_tuxrun_assets(self.ASSET_SH4_KERNEL,
|
||||
self.ASSET_SH4_ROOTFS)
|
||||
(kernel, disk, dtb, _) = self.fetch_tuxrun_assets(self.ASSET_SH4_KERNEL,
|
||||
self.ASSET_SH4_ROOTFS)
|
||||
|
||||
# the console comes on the second serial port
|
||||
self.prepare_run(kernel, disk,
|
||||
self.prepare_run(None, kernel, disk,
|
||||
"driver=ide-hd,bus=ide.0,unit=0",
|
||||
console_index=1)
|
||||
self.vm.launch()
|
||||
|
||||
@@ -303,6 +303,9 @@ class AcpiBitsTest(QemuSystemTest): #pylint: disable=too-many-instance-attribute
|
||||
"""The main test case implementation."""
|
||||
|
||||
self.set_machine('pc')
|
||||
# see icount comment below
|
||||
self.require_accelerator('tcg')
|
||||
|
||||
iso_file = self.scratch_file('bits-%d.iso' % self.BITS_INTERNAL_VER)
|
||||
|
||||
self.assertTrue(os.access(iso_file, os.R_OK))
|
||||
|
||||
@@ -11,26 +11,59 @@
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
from qemu_test import Asset
|
||||
from qemu_test import Asset, skipIfMissingEnv
|
||||
from qemu_test.tuxruntest import TuxRunBaselineTest
|
||||
|
||||
class TuxRunX86Test(TuxRunBaselineTest):
|
||||
|
||||
ASSET_X86_64_KERNEL = Asset(
|
||||
'https://storage.tuxboot.com/buildroot/20241119/x86_64/bzImage',
|
||||
'f57bfc6553bcd6e0a54aab86095bf642b33b5571d14e3af1731b18c87ed5aef8')
|
||||
'https://storage.tuxboot.com/kernels/6.18.54/x86_64/bzImage',
|
||||
'24a3ade610c2cc426ff821050de8a35930b0371357d94cc2c334abac6658552b')
|
||||
ASSET_X86_64_VMLINUX = Asset(
|
||||
'https://storage.tuxboot.com/kernels/6.18.54/x86_64/vmlinux.xz',
|
||||
'77bf44cca48c9c1b9c142e16a2311d58b8ae3462b61bce44bcaf9243b5f26628')
|
||||
ASSET_X86_64_ROOTFS = Asset(
|
||||
'https://storage.tuxboot.com/buildroot/20241119/x86_64/rootfs.ext4.zst',
|
||||
'4b8b2a99117519c5290e1202cb36eb6c7aaba92b357b5160f5970cf5fb78a751')
|
||||
'https://storage.tuxboot.com/buildroot/20260924/x86_64/rootfs.ext4.zst',
|
||||
'8e310455b0244414ccff29c507f7ccfd4032e3587cc405e49ab0322738e3e27c')
|
||||
|
||||
def test_x86_64(self):
|
||||
self.require_accelerator("tcg")
|
||||
|
||||
self.set_machine('q35')
|
||||
self.cpu="Nehalem"
|
||||
self.root='sda'
|
||||
self.wait_for_shutdown=False
|
||||
self.common_tuxrun(kernel_asset=self.ASSET_X86_64_KERNEL,
|
||||
rootfs_asset=self.ASSET_X86_64_ROOTFS,
|
||||
drive="driver=ide-hd,bus=ide.0,unit=0")
|
||||
drive="driver=ide-hd,bus=ide.0,unit=0",
|
||||
accel="tcg")
|
||||
|
||||
def test_x86_64_kvm(self):
|
||||
self.require_accelerator("kvm")
|
||||
|
||||
self.set_machine('q35')
|
||||
self.cpu="Nehalem"
|
||||
self.root='sda'
|
||||
self.wait_for_shutdown=False
|
||||
self.common_tuxrun(kernel_asset=self.ASSET_X86_64_KERNEL,
|
||||
rootfs_asset=self.ASSET_X86_64_ROOTFS,
|
||||
drive="driver=ide-hd,bus=ide.0,unit=0",
|
||||
accel="kvm")
|
||||
|
||||
@skipIfMissingEnv("QEMU_TEST_GDB")
|
||||
def test_x86_64_kvm_gdb(self):
|
||||
self.require_accelerator("kvm")
|
||||
|
||||
self.set_machine('q35')
|
||||
self.cpu="Nehalem"
|
||||
self.root='sda'
|
||||
self.wait_for_shutdown=False
|
||||
self.common_tuxrun_gdb(kernel_asset=self.ASSET_X86_64_KERNEL,
|
||||
vmlinux_asset=self.ASSET_X86_64_VMLINUX,
|
||||
rootfs_asset=self.ASSET_X86_64_ROOTFS,
|
||||
drive="driver=ide-hd,bus=ide.0,unit=0",
|
||||
accel="kvm")
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
TuxRunBaselineTest.main()
|
||||
@@ -25,8 +25,10 @@ def get_args():
|
||||
required=True)
|
||||
parser.add_argument("--qargs", help="Qemu arguments for test")
|
||||
parser.add_argument("--pargs", help="Program arguments for test")
|
||||
parser.add_argument("--binary", help="Binary to debug",
|
||||
required=True)
|
||||
parser.add_argument("--kargs", help="Kernel args to --append")
|
||||
parser.add_argument("--binary", help="Binary to debug")
|
||||
parser.add_argument("--symbols", help="Symbol file for binary to debug")
|
||||
parser.add_argument("--symbol-offset", help="offset to apply to symbols")
|
||||
parser.add_argument("--test", help="GDB test script")
|
||||
parser.add_argument('test_args', nargs='*',
|
||||
help="Additional args for GDB test script. "
|
||||
@@ -51,6 +53,10 @@ def log(output, msg):
|
||||
print(msg)
|
||||
|
||||
|
||||
def format_cmd(cmd):
|
||||
return " ".join(shlex.quote(arg) for arg in cmd)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
args = get_args()
|
||||
|
||||
@@ -75,55 +81,80 @@ if __name__ == '__main__':
|
||||
socket_name = os.path.join(socket_dir.name, "gdbstub.socket")
|
||||
|
||||
# Launch QEMU with binary
|
||||
qemu_cmd = [args.qemu]
|
||||
if args.qargs:
|
||||
qemu_cmd.extend(shlex.split(args.qargs))
|
||||
|
||||
if "system" in args.qemu:
|
||||
if args.no_suspend:
|
||||
suspend = ''
|
||||
else:
|
||||
suspend = ' -S'
|
||||
cmd = f'{args.qemu} {args.qargs} {args.binary}' \
|
||||
f'{suspend} -gdb unix:path={socket_name},server=on'
|
||||
# for system mode we assume qargs has set-up for binary if
|
||||
# indeed we have set one.
|
||||
if args.binary:
|
||||
qemu_cmd.append(args.binary)
|
||||
if not args.no_suspend:
|
||||
qemu_cmd.append("-S")
|
||||
qemu_cmd.extend(["-gdb", f"unix:path={socket_name},server=on"])
|
||||
|
||||
if args.kargs:
|
||||
qemu_cmd.extend(["--append", args.kargs])
|
||||
|
||||
# There is no guest program command-line in system mode.
|
||||
assert not args.pargs
|
||||
else:
|
||||
qemu_cmd.append("-g")
|
||||
if args.no_suspend:
|
||||
suspend = ',suspend=n'
|
||||
qemu_cmd.append(f"{socket_name},suspend=n")
|
||||
else:
|
||||
suspend = ''
|
||||
cmd = f'{args.qemu} {args.qargs} -g {socket_name}{suspend}' \
|
||||
f' {args.binary}'
|
||||
if args.pargs:
|
||||
cmd += f' {args.pargs}'
|
||||
qemu_cmd.append(f"{socket_name}")
|
||||
|
||||
log(output, "QEMU CMD: %s" % (cmd))
|
||||
inferior = subprocess.Popen(shlex.split(cmd))
|
||||
# There are no appended args in user-mode
|
||||
assert not args.kargs
|
||||
|
||||
# for user mode binary and args always go at the end
|
||||
qemu_cmd.append(args.binary)
|
||||
if args.pargs:
|
||||
qemu_cmd.extend(shlex.split(args.pargs))
|
||||
|
||||
log(output, "QEMU CMD: %s" % (format_cmd(qemu_cmd)))
|
||||
inferior = subprocess.Popen(qemu_cmd)
|
||||
|
||||
# Now launch gdb with our test and collect the result
|
||||
gdb_cmd = "%s %s" % (args.gdb, args.binary)
|
||||
gdb_cmd = [args.gdb]
|
||||
|
||||
if args.binary:
|
||||
gdb_cmd.append(args.binary)
|
||||
if args.gdb_args:
|
||||
gdb_cmd += " %s" % (args.gdb_args)
|
||||
gdb_cmd.extend(shlex.split(args.gdb_args))
|
||||
|
||||
# run quietly and ignore .gdbinit
|
||||
gdb_cmd += " -q -n -batch"
|
||||
gdb_cmd.extend(["-q", "-n", "-batch"])
|
||||
# disable pagination
|
||||
gdb_cmd += " -ex 'set pagination off'"
|
||||
gdb_cmd.extend(["-ex", "set pagination off"])
|
||||
# disable prompts in case of crash
|
||||
gdb_cmd += " -ex 'set confirm off'"
|
||||
gdb_cmd.extend(["-ex", "set confirm off"])
|
||||
# connect to remote
|
||||
gdb_cmd += " -ex 'target remote %s'" % (socket_name)
|
||||
gdb_cmd.extend(["-ex", f"target remote {socket_name}"])
|
||||
|
||||
if args.symbols:
|
||||
sym_arg = f"symbol-file {args.symbols}"
|
||||
if args.symbol_offset:
|
||||
sym_arg += f" -o {args.symbol_offset}"
|
||||
|
||||
gdb_cmd.extend(["-ex", sym_arg])
|
||||
|
||||
# finally the test script itself
|
||||
if args.test:
|
||||
if args.test_args:
|
||||
gdb_cmd += f" -ex \"py sys.argv={args.test_args}\""
|
||||
gdb_cmd += " -x %s" % (args.test)
|
||||
|
||||
gdb_cmd.extend(["-ex", f"py sys.argv={args.test_args}"])
|
||||
gdb_cmd.extend(["-x", args.test])
|
||||
|
||||
sleep(1)
|
||||
log(output, "GDB CMD: %s" % (gdb_cmd))
|
||||
log(output, "GDB CMD: %s" % (format_cmd(gdb_cmd)))
|
||||
|
||||
gdb_env = dict(os.environ)
|
||||
gdb_pythonpath = gdb_env.get("PYTHONPATH", "").split(os.pathsep)
|
||||
gdb_pythonpath.append(os.path.dirname(os.path.realpath(__file__)))
|
||||
gdb_env["PYTHONPATH"] = os.pathsep.join(gdb_pythonpath)
|
||||
result = subprocess.call(gdb_cmd, shell=True, stdout=output, stderr=stderr,
|
||||
result = subprocess.call(gdb_cmd, stdout=output, stderr=stderr,
|
||||
env=gdb_env)
|
||||
|
||||
# A result of greater than 128 indicates a fatal signal (likely a
|
||||
|
||||
@@ -1,11 +1,6 @@
|
||||
env = find_program('env')
|
||||
|
||||
docker_wrapper = find_program('../docker/docker.py')
|
||||
if get_option('gdb') != ''
|
||||
gdb = find_program(get_option('gdb'), required: true)
|
||||
else
|
||||
gdb = find_program(['gdb-multiarch', 'gdb'], required: false)
|
||||
endif
|
||||
prog_check_plugin_output = find_program('./scripts/check_plugin_output.sh')
|
||||
prog_gdb_test = find_program('../guest-debug/run-test.py')
|
||||
prog_record_replay = find_program('./scripts/record_replay.sh')
|
||||
|
||||
@@ -39,7 +39,7 @@ int main(int argc, char **argv)
|
||||
assert(qemu);
|
||||
|
||||
if (!getenv("QEMU_RTSIG_MAP")) {
|
||||
char **new_argv = malloc((argc + 2) + sizeof(char *));
|
||||
char **new_argv = malloc((argc + 2) * sizeof(char *));
|
||||
int tsig1, hsig1, count1, tsig2, hsig2, count2;
|
||||
char rt_sigmap[64];
|
||||
|
||||
|
||||
Reference in new issue
Block a user