functional and tcg tests, plugins and MAINTAINERS

- update and expand aarch64 GPU tests
   - fix build dependence for plugins
   - update libvirt-ci to vulkan-tools
   - allow plugin tests to run on non-POSIX systems
   - tweak test/vm times
   - mark test-vma as linux only
   - various compiler fixes for tcg tests
   - add gitlab build unit tracker
   - error out early on stalled RME tests
   - compile core plugin code once
   - update MAINTAINERS
 -----BEGIN PGP SIGNATURE-----
 
 iQEzBAABCgAdFiEEZoWumedRZ7yvyN81+9DbCVqeKkQFAmfOwjcACgkQ+9DbCVqe
 KkRkcwgAlRTflCqYlZxdlo4CiOSXaHAFr8yfwWq138LJQRQH530JZnz1lZtxTbEM
 pXT7ixnuJQDMybCQJmvUlK5UTUkZhGS3VuAR1VeM2J8/3VXYzf5sFjZ7yko9mA8S
 2FX8vdfbko8/J31+lKccA0tpbHyi2AbMR+mO8xj6KZQoePwmHoRmhgH7p7LE35YO
 8ytaOjMwTKF5fReVK+tlcrVJHFMdGsGNwtsnB2FhhVjI56fQqyM5hGXfOING2Fx3
 iZH3rjzfDB4SWbBqaRsMgH9RXjuB9Eo4v0Qs5ve5SjDyzRJk+/CbbBJ4oRt9hurJ
 bA+CYZuNLGBf8Z/mUeYMavA7rxT5rw==
 =qobU
 -----END PGP SIGNATURE-----

Merge tag 'pull-10.0-for-softfreeze-100325-3' of https://gitlab.com/stsquad/qemu into staging

functional and tcg tests, plugins and MAINTAINERS

  - update and expand aarch64 GPU tests
  - fix build dependence for plugins
  - update libvirt-ci to vulkan-tools
  - allow plugin tests to run on non-POSIX systems
  - tweak test/vm times
  - mark test-vma as linux only
  - various compiler fixes for tcg tests
  - add gitlab build unit tracker
  - error out early on stalled RME tests
  - compile core plugin code once
  - update MAINTAINERS

# -----BEGIN PGP SIGNATURE-----
#
# iQEzBAABCgAdFiEEZoWumedRZ7yvyN81+9DbCVqeKkQFAmfOwjcACgkQ+9DbCVqe
# KkRkcwgAlRTflCqYlZxdlo4CiOSXaHAFr8yfwWq138LJQRQH530JZnz1lZtxTbEM
# pXT7ixnuJQDMybCQJmvUlK5UTUkZhGS3VuAR1VeM2J8/3VXYzf5sFjZ7yko9mA8S
# 2FX8vdfbko8/J31+lKccA0tpbHyi2AbMR+mO8xj6KZQoePwmHoRmhgH7p7LE35YO
# 8ytaOjMwTKF5fReVK+tlcrVJHFMdGsGNwtsnB2FhhVjI56fQqyM5hGXfOING2Fx3
# iZH3rjzfDB4SWbBqaRsMgH9RXjuB9Eo4v0Qs5ve5SjDyzRJk+/CbbBJ4oRt9hurJ
# bA+CYZuNLGBf8Z/mUeYMavA7rxT5rw==
# =qobU
# -----END PGP SIGNATURE-----
# gpg: Signature made Mon 10 Mar 2025 18:43:03 HKT
# 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-10.0-for-softfreeze-100325-3' of https://gitlab.com/stsquad/qemu: (31 commits)
  MAINTAINERS: remove widely sanctioned entities
  plugins/core: make a single build unit
  plugins/api: build only once
  plugins/api: split out time control helpers
  plugins/api: split out the vaddr/hwaddr helpers
  plugins/api: split out binary path/start/end/entry code
  plugins/loader: compile loader only once
  plugins/plugin.h: include queue.h
  plugins/api: clean-up the includes
  include/qemu: plugin-memory.h doesn't need cpu-defs.h
  plugins/loader: populate target_name with target_name()
  plugins/api: use qemu_target_page_mask() to get value
  tests/functional: add boot error detection for RME tests
  gitlab: add a new build_unit job to track build size
  tests/tcg: Suppress compiler false-positive warning on sha1.c
  tests/tcg: enable -fwrapv for test-i386-bmi
  tests/tcg: fix constraints in test-i386-adcox
  tests/tcg: add message to _Static_assert in test-avx
  tests/tcg: mark test-vma as a linux-only test
  tests/vm: bump timeout for shutdown
  ...

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
Stefan Hajnoczi 2025-03-11 09:26:14 +08:00
commit 6d1829fce4
62 changed files with 647 additions and 302 deletions

66
.gitlab-ci.d/check-units.py Executable file
View file

@ -0,0 +1,66 @@
#!/usr/bin/env python3
#
# check-units.py: check the number of compilation units and identify
# those that are rebuilt multiple times
#
# Copyright (C) 2025 Linaro Ltd.
#
# SPDX-License-Identifier: GPL-2.0-or-later
from os import access, R_OK, path
from sys import argv, exit
import json
from collections import Counter
def extract_build_units(cc_path):
"""
Extract the build units and their counds from compile_commands.json file.
Returns:
Hash table of ["unit"] = count
"""
j = json.load(open(cc_path, 'r'))
files = [f['file'] for f in j]
build_units = Counter(files)
return build_units
def analyse_units(build_units):
"""
Analyse the build units and report stats and the top 10 rebuilds
"""
print(f"Total source files: {len(build_units.keys())}")
print(f"Total build units: {sum(units.values())}")
# Create a sorted list by number of rebuilds
sorted_build_units = sorted(build_units.items(),
key=lambda item: item[1],
reverse=True)
print("Most rebuilt units:")
for unit, count in sorted_build_units[:20]:
print(f" {unit} built {count} times")
print("Least rebuilt units:")
for unit, count in sorted_build_units[-10:]:
print(f" {unit} built {count} times")
if __name__ == "__main__":
if len(argv) != 2:
script_name = path.basename(argv[0])
print(f"Usage: {script_name} <path_to_compile_commands.json>")
exit(1)
cc_path = argv[1]
if path.isfile(cc_path) and access(cc_path, R_OK):
units = extract_build_units(cc_path)
analyse_units(units)
exit(0)
else:
print(f"{cc_path} doesn't exist or isn't readable")
exit(1)

View file

@ -11,6 +11,6 @@ MAKE='/usr/local/bin/gmake'
NINJA='/usr/local/bin/ninja' NINJA='/usr/local/bin/ninja'
PACKAGING_COMMAND='pkg' PACKAGING_COMMAND='pkg'
PIP3='/usr/local/bin/pip' PIP3='/usr/local/bin/pip'
PKGS='alsa-lib bash bison bzip2 ca_root_nss capstone4 ccache4 cmocka ctags curl cyrus-sasl dbus diffutils dtc flex fusefs-libs3 gettext git glib gmake gnutls gsed gtk-vnc gtk3 json-c libepoxy libffi libgcrypt libjpeg-turbo libnfs libslirp libspice-server libssh libtasn1 llvm lzo2 meson mtools ncurses nettle ninja opencv pixman pkgconf png py311-numpy py311-pillow py311-pip py311-pyyaml py311-sphinx py311-sphinx_rtd_theme py311-tomli python3 rpm2cpio rust rust-bindgen-cli sdl2 sdl2_image snappy sndio socat spice-protocol tesseract usbredir virglrenderer vte3 xorriso zstd' PKGS='alsa-lib bash bison bzip2 ca_root_nss capstone4 ccache4 cmocka ctags curl cyrus-sasl dbus diffutils dtc flex fusefs-libs3 gettext git glib gmake gnutls gsed gtk-vnc gtk3 json-c libepoxy libffi libgcrypt libjpeg-turbo libnfs libslirp libspice-server libssh libtasn1 llvm lzo2 meson mtools ncurses nettle ninja opencv pixman pkgconf png py311-numpy py311-pillow py311-pip py311-pyyaml py311-sphinx py311-sphinx_rtd_theme py311-tomli python3 rpm2cpio rust rust-bindgen-cli sdl2 sdl2_image snappy sndio socat spice-protocol tesseract usbredir virglrenderer vte3 vulkan-tools xorriso zstd'
PYPI_PKGS='' PYPI_PKGS=''
PYTHON='/usr/local/bin/python3' PYTHON='/usr/local/bin/python3'

View file

@ -11,6 +11,6 @@ MAKE='/opt/homebrew/bin/gmake'
NINJA='/opt/homebrew/bin/ninja' NINJA='/opt/homebrew/bin/ninja'
PACKAGING_COMMAND='brew' PACKAGING_COMMAND='brew'
PIP3='/opt/homebrew/bin/pip3' PIP3='/opt/homebrew/bin/pip3'
PKGS='bash bc bindgen bison bzip2 capstone ccache cmocka ctags curl dbus diffutils dtc flex gcovr gettext git glib gnu-sed gnutls gtk+3 gtk-vnc jemalloc jpeg-turbo json-c libcbor libepoxy libffi libgcrypt libiscsi libnfs libpng libslirp libssh libtasn1 libusb llvm lzo make meson mtools ncurses nettle ninja pixman pkg-config python3 rpm2cpio rust sdl2 sdl2_image snappy socat sparse spice-protocol swtpm tesseract usbredir vde vte3 xorriso zlib zstd' PKGS='bash bc bindgen bison bzip2 capstone ccache cmocka ctags curl dbus diffutils dtc flex gcovr gettext git glib gnu-sed gnutls gtk+3 gtk-vnc jemalloc jpeg-turbo json-c libcbor libepoxy libffi libgcrypt libiscsi libnfs libpng libslirp libssh libtasn1 libusb llvm lzo make meson mtools ncurses nettle ninja pixman pkg-config python3 rpm2cpio rust sdl2 sdl2_image snappy socat sparse spice-protocol swtpm tesseract usbredir vde vte3 vulkan-tools xorriso zlib zstd'
PYPI_PKGS='PyYAML numpy pillow sphinx sphinx-rtd-theme tomli' PYPI_PKGS='PyYAML numpy pillow sphinx sphinx-rtd-theme tomli'
PYTHON='/opt/homebrew/bin/python3' PYTHON='/opt/homebrew/bin/python3'

View file

@ -70,3 +70,25 @@ check-rust-tools-nightly:
expire_in: 2 days expire_in: 2 days
paths: paths:
- rust/target/doc - rust/target/doc
check-build-units:
extends: .base_job_template
stage: build
image: $CI_REGISTRY_IMAGE/qemu/debian:$QEMU_CI_CONTAINER_TAG
needs:
job: amd64-debian-container
before_script:
- source scripts/ci/gitlab-ci-section
- section_start setup "Install Tools"
- apt install --assume-yes --no-install-recommends jq
- section_end setup
script:
- mkdir build
- cd build
- section_start configure "Running configure"
- ../configure
- cd ..
- section_end configure
- section_start analyse "Analyse"
- .gitlab-ci.d/check-units.py build/compile_commands.json
- section_end analyse

View file

@ -2547,8 +2547,7 @@ F: hw/i2c/i2c_mux_pca954x.c
F: include/hw/i2c/i2c_mux_pca954x.h F: include/hw/i2c/i2c_mux_pca954x.h
pcf8574 pcf8574
M: Dmitrii Sharikhin <d.sharikhin@yadro.com> S: Orphaned
S: Maintained
F: hw/gpio/pcf8574.c F: hw/gpio/pcf8574.c
F: include/gpio/pcf8574.h F: include/gpio/pcf8574.h
@ -2631,6 +2630,7 @@ F: hw/display/virtio-gpu*
F: hw/display/virtio-vga.* F: hw/display/virtio-vga.*
F: include/hw/virtio/virtio-gpu.h F: include/hw/virtio/virtio-gpu.h
F: docs/system/devices/virtio-gpu.rst F: docs/system/devices/virtio-gpu.rst
F: tests/functional/test_aarch64_virt_gpu.py
vhost-user-blk vhost-user-blk
M: Raphael Norwitz <raphael@enfabrica.net> M: Raphael Norwitz <raphael@enfabrica.net>
@ -3659,10 +3659,10 @@ F: net/filter-mirror.c
F: tests/qtest/test-filter* F: tests/qtest/test-filter*
Record/replay Record/replay
M: Pavel Dovgalyuk <pavel.dovgaluk@ispras.ru>
R: Paolo Bonzini <pbonzini@redhat.com> R: Paolo Bonzini <pbonzini@redhat.com>
R: Alex Bennée <alex.bennee@linaro.org>
W: https://wiki.qemu.org/Features/record-replay W: https://wiki.qemu.org/Features/record-replay
S: Supported S: Odd Fixes
F: replay/* F: replay/*
F: block/blkreplay.c F: block/blkreplay.c
F: net/filter-replay.c F: net/filter-replay.c

View file

@ -13,6 +13,7 @@ bsd_user_ss.add(files(
'elfload.c', 'elfload.c',
'main.c', 'main.c',
'mmap.c', 'mmap.c',
'plugin-api.c',
'signal.c', 'signal.c',
'strace.c', 'strace.c',
'uaccess.c', 'uaccess.c',

15
bsd-user/plugin-api.c Normal file
View file

@ -0,0 +1,15 @@
/*
* QEMU Plugin API - bsd-user-mode only implementations
*
* Common user-mode only APIs are in plugins/api-user. These helpers
* are only specific to bsd-user.
*
* Copyright (C) 2017, Emilio G. Cota <cota@braap.org>
* Copyright (C) 2019-2025, Linaro
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "qemu/osdep.h"
#include "qemu.h"
#include "common-user/plugin-api.c.inc"

View file

@ -0,0 +1,43 @@
/*
* QEMU Plugin API - *-user-mode only implementations
*
* Common user-mode only APIs are in plugins/api-user. These helpers
* are only specific to the *-user frontends.
*
* Copyright (C) 2017, Emilio G. Cota <cota@braap.org>
* Copyright (C) 2019-2025, Linaro
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "qemu/osdep.h"
#include "qemu/main-loop.h"
#include "qemu/plugin.h"
#include "qemu.h"
/*
* Binary path, start and end locations. Host specific due to TaskState.
*/
const char *qemu_plugin_path_to_binary(void)
{
TaskState *ts = get_task_state(current_cpu);
return g_strdup(ts->bprm->filename);
}
uint64_t qemu_plugin_start_code(void)
{
TaskState *ts = get_task_state(current_cpu);
return ts->info->start_code;
}
uint64_t qemu_plugin_end_code(void)
{
TaskState *ts = get_task_state(current_cpu);
return ts->info->end_code;
}
uint64_t qemu_plugin_entry_code(void)
{
TaskState *ts = get_task_state(current_cpu);
return ts->info->entry;
}

View file

@ -26,3 +26,5 @@ if t.length() > 0
else else
run_target('contrib-plugins', command: find_program('true')) run_target('contrib-plugins', command: find_program('true'))
endif endif
plugin_modules += t

View file

@ -9,7 +9,6 @@
#ifndef PLUGIN_MEMORY_H #ifndef PLUGIN_MEMORY_H
#define PLUGIN_MEMORY_H #define PLUGIN_MEMORY_H
#include "exec/cpu-defs.h"
#include "exec/hwaddr.h" #include "exec/hwaddr.h"
struct qemu_plugin_hwaddr { struct qemu_plugin_hwaddr {

View file

@ -27,6 +27,7 @@ linux_user_ss.add(libdw)
linux_user_ss.add(when: 'TARGET_HAS_BFLT', if_true: files('flatload.c')) linux_user_ss.add(when: 'TARGET_HAS_BFLT', if_true: files('flatload.c'))
linux_user_ss.add(when: 'TARGET_I386', if_true: files('vm86.c')) linux_user_ss.add(when: 'TARGET_I386', if_true: files('vm86.c'))
linux_user_ss.add(when: 'CONFIG_ARM_COMPATIBLE_SEMIHOSTING', if_true: files('semihost.c')) linux_user_ss.add(when: 'CONFIG_ARM_COMPATIBLE_SEMIHOSTING', if_true: files('semihost.c'))
linux_user_ss.add(when: 'CONFIG_TCG_PLUGINS', if_true: files('plugin-api.c'))
syscall_nr_generators = {} syscall_nr_generators = {}

15
linux-user/plugin-api.c Normal file
View file

@ -0,0 +1,15 @@
/*
* QEMU Plugin API - linux-user-mode only implementations
*
* Common user-mode only APIs are in plugins/api-user. These helpers
* are only specific to linux-user.
*
* Copyright (C) 2017, Emilio G. Cota <cota@braap.org>
* Copyright (C) 2019-2025, Linaro
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "qemu/osdep.h"
#include "qemu.h"
#include "common-user/plugin-api.c.inc"

View file

@ -3668,6 +3668,7 @@ qtest_module_ss = ss.source_set()
modules = {} modules = {}
target_modules = {} target_modules = {}
plugin_modules = []
hw_arch = {} hw_arch = {}
target_arch = {} target_arch = {}
target_system_arch = {} target_system_arch = {}

131
plugins/api-system.c Normal file
View file

@ -0,0 +1,131 @@
/*
* QEMU Plugin API - System specific implementations
*
* This provides the APIs that have a specific system implementation
* or are only relevant to system-mode.
*
* Copyright (C) 2017, Emilio G. Cota <cota@braap.org>
* Copyright (C) 2019-2025, Linaro
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "qemu/osdep.h"
#include "qemu/main-loop.h"
#include "qapi/error.h"
#include "migration/blocker.h"
#include "hw/boards.h"
#include "qemu/plugin-memory.h"
#include "qemu/plugin.h"
/*
* In system mode we cannot trace the binary being executed so the
* helpers all return NULL/0.
*/
const char *qemu_plugin_path_to_binary(void)
{
return NULL;
}
uint64_t qemu_plugin_start_code(void)
{
return 0;
}
uint64_t qemu_plugin_end_code(void)
{
return 0;
}
uint64_t qemu_plugin_entry_code(void)
{
return 0;
}
/*
* Virtual Memory queries
*/
static __thread struct qemu_plugin_hwaddr hwaddr_info;
struct qemu_plugin_hwaddr *qemu_plugin_get_hwaddr(qemu_plugin_meminfo_t info,
uint64_t vaddr)
{
CPUState *cpu = current_cpu;
unsigned int mmu_idx = get_mmuidx(info);
enum qemu_plugin_mem_rw rw = get_plugin_meminfo_rw(info);
hwaddr_info.is_store = (rw & QEMU_PLUGIN_MEM_W) != 0;
assert(mmu_idx < NB_MMU_MODES);
if (!tlb_plugin_lookup(cpu, vaddr, mmu_idx,
hwaddr_info.is_store, &hwaddr_info)) {
error_report("invalid use of qemu_plugin_get_hwaddr");
return NULL;
}
return &hwaddr_info;
}
bool qemu_plugin_hwaddr_is_io(const struct qemu_plugin_hwaddr *haddr)
{
return haddr->is_io;
}
uint64_t qemu_plugin_hwaddr_phys_addr(const struct qemu_plugin_hwaddr *haddr)
{
if (haddr) {
return haddr->phys_addr;
}
return 0;
}
const char *qemu_plugin_hwaddr_device_name(const struct qemu_plugin_hwaddr *h)
{
if (h && h->is_io) {
MemoryRegion *mr = h->mr;
if (!mr->name) {
unsigned maddr = (uintptr_t)mr;
g_autofree char *temp = g_strdup_printf("anon%08x", maddr);
return g_intern_string(temp);
} else {
return g_intern_string(mr->name);
}
} else {
return g_intern_static_string("RAM");
}
}
/*
* Time control
*/
static bool has_control;
static Error *migration_blocker;
const void *qemu_plugin_request_time_control(void)
{
if (!has_control) {
has_control = true;
error_setg(&migration_blocker,
"TCG plugin time control does not support migration");
migrate_add_blocker(&migration_blocker, NULL);
return &has_control;
}
return NULL;
}
static void advance_virtual_time__async(CPUState *cpu, run_on_cpu_data data)
{
int64_t new_time = data.host_ulong;
qemu_clock_advance_virtual_time(new_time);
}
void qemu_plugin_update_ns(const void *handle, int64_t new_time)
{
if (handle == &has_control) {
/* Need to execute out of cpu_exec, so bql can be locked. */
async_run_on_cpu(current_cpu,
advance_virtual_time__async,
RUN_ON_CPU_HOST_ULONG(new_time));
}
}

57
plugins/api-user.c Normal file
View file

@ -0,0 +1,57 @@
/*
* QEMU Plugin API - user-mode only implementations
*
* This provides the APIs that have a user-mode specific
* implementations or are only relevant to user-mode.
*
* Copyright (C) 2017, Emilio G. Cota <cota@braap.org>
* Copyright (C) 2019-2025, Linaro
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "qemu/osdep.h"
#include "qemu/plugin.h"
#include "exec/log.h"
/*
* Virtual Memory queries - these are all NOPs for user-mode which
* only ever has visibility of virtual addresses.
*/
struct qemu_plugin_hwaddr *qemu_plugin_get_hwaddr(qemu_plugin_meminfo_t info,
uint64_t vaddr)
{
return NULL;
}
bool qemu_plugin_hwaddr_is_io(const struct qemu_plugin_hwaddr *haddr)
{
return false;
}
uint64_t qemu_plugin_hwaddr_phys_addr(const struct qemu_plugin_hwaddr *haddr)
{
return 0;
}
const char *qemu_plugin_hwaddr_device_name(const struct qemu_plugin_hwaddr *h)
{
return g_intern_static_string("Invalid");
}
/*
* Time control - for user mode the only real time is wall clock time
* so realistically all you can do in user mode is slow down execution
* which doesn't require the ability to mess with the clock.
*/
const void *qemu_plugin_request_time_control(void)
{
return NULL;
}
void qemu_plugin_update_ns(const void *handle, int64_t new_time)
{
qemu_log_mask(LOG_UNIMP, "user-mode can't control time");
}

View file

@ -39,26 +39,13 @@
#include "qemu/main-loop.h" #include "qemu/main-loop.h"
#include "qemu/plugin.h" #include "qemu/plugin.h"
#include "qemu/log.h" #include "qemu/log.h"
#include "qemu/timer.h"
#include "tcg/tcg.h" #include "tcg/tcg.h"
#include "exec/exec-all.h"
#include "exec/gdbstub.h" #include "exec/gdbstub.h"
#include "exec/target_page.h"
#include "exec/translation-block.h" #include "exec/translation-block.h"
#include "exec/translator.h" #include "exec/translator.h"
#include "disas/disas.h" #include "disas/disas.h"
#include "plugin.h" #include "plugin.h"
#ifndef CONFIG_USER_ONLY
#include "qapi/error.h"
#include "migration/blocker.h"
#include "exec/ram_addr.h"
#include "qemu/plugin-memory.h"
#include "hw/boards.h"
#else
#include "qemu.h"
#ifdef CONFIG_LINUX
#include "loader.h"
#endif
#endif
/* Uninstall and Reset handlers */ /* Uninstall and Reset handlers */
@ -287,7 +274,7 @@ uint64_t qemu_plugin_insn_vaddr(const struct qemu_plugin_insn *insn)
void *qemu_plugin_insn_haddr(const struct qemu_plugin_insn *insn) void *qemu_plugin_insn_haddr(const struct qemu_plugin_insn *insn)
{ {
const DisasContextBase *db = tcg_ctx->plugin_db; const DisasContextBase *db = tcg_ctx->plugin_db;
vaddr page0_last = db->pc_first | ~TARGET_PAGE_MASK; vaddr page0_last = db->pc_first | ~qemu_target_page_mask();
if (db->fake_insn) { if (db->fake_insn) {
return NULL; return NULL;
@ -385,76 +372,6 @@ qemu_plugin_mem_value qemu_plugin_mem_get_value(qemu_plugin_meminfo_t info)
return value; return value;
} }
/*
* Virtual Memory queries
*/
#ifdef CONFIG_SOFTMMU
static __thread struct qemu_plugin_hwaddr hwaddr_info;
#endif
struct qemu_plugin_hwaddr *qemu_plugin_get_hwaddr(qemu_plugin_meminfo_t info,
uint64_t vaddr)
{
#ifdef CONFIG_SOFTMMU
CPUState *cpu = current_cpu;
unsigned int mmu_idx = get_mmuidx(info);
enum qemu_plugin_mem_rw rw = get_plugin_meminfo_rw(info);
hwaddr_info.is_store = (rw & QEMU_PLUGIN_MEM_W) != 0;
assert(mmu_idx < NB_MMU_MODES);
if (!tlb_plugin_lookup(cpu, vaddr, mmu_idx,
hwaddr_info.is_store, &hwaddr_info)) {
error_report("invalid use of qemu_plugin_get_hwaddr");
return NULL;
}
return &hwaddr_info;
#else
return NULL;
#endif
}
bool qemu_plugin_hwaddr_is_io(const struct qemu_plugin_hwaddr *haddr)
{
#ifdef CONFIG_SOFTMMU
return haddr->is_io;
#else
return false;
#endif
}
uint64_t qemu_plugin_hwaddr_phys_addr(const struct qemu_plugin_hwaddr *haddr)
{
#ifdef CONFIG_SOFTMMU
if (haddr) {
return haddr->phys_addr;
}
#endif
return 0;
}
const char *qemu_plugin_hwaddr_device_name(const struct qemu_plugin_hwaddr *h)
{
#ifdef CONFIG_SOFTMMU
if (h && h->is_io) {
MemoryRegion *mr = h->mr;
if (!mr->name) {
unsigned maddr = (uintptr_t)mr;
g_autofree char *temp = g_strdup_printf("anon%08x", maddr);
return g_intern_string(temp);
} else {
return g_intern_string(mr->name);
}
} else {
return g_intern_static_string("RAM");
}
#else
return g_intern_static_string("Invalid");
#endif
}
int qemu_plugin_num_vcpus(void) int qemu_plugin_num_vcpus(void)
{ {
return plugin_num_vcpus(); return plugin_num_vcpus();
@ -473,49 +390,6 @@ bool qemu_plugin_bool_parse(const char *name, const char *value, bool *ret)
return name && value && qapi_bool_parse(name, value, ret, NULL); return name && value && qapi_bool_parse(name, value, ret, NULL);
} }
/*
* Binary path, start and end locations
*/
const char *qemu_plugin_path_to_binary(void)
{
char *path = NULL;
#ifdef CONFIG_USER_ONLY
TaskState *ts = get_task_state(current_cpu);
path = g_strdup(ts->bprm->filename);
#endif
return path;
}
uint64_t qemu_plugin_start_code(void)
{
uint64_t start = 0;
#ifdef CONFIG_USER_ONLY
TaskState *ts = get_task_state(current_cpu);
start = ts->info->start_code;
#endif
return start;
}
uint64_t qemu_plugin_end_code(void)
{
uint64_t end = 0;
#ifdef CONFIG_USER_ONLY
TaskState *ts = get_task_state(current_cpu);
end = ts->info->end_code;
#endif
return end;
}
uint64_t qemu_plugin_entry_code(void)
{
uint64_t entry = 0;
#ifdef CONFIG_USER_ONLY
TaskState *ts = get_task_state(current_cpu);
entry = ts->info->entry;
#endif
return entry;
}
/* /*
* Create register handles. * Create register handles.
* *
@ -641,44 +515,3 @@ uint64_t qemu_plugin_u64_sum(qemu_plugin_u64 entry)
return total; return total;
} }
/*
* Time control
*/
static bool has_control;
#ifdef CONFIG_SOFTMMU
static Error *migration_blocker;
#endif
const void *qemu_plugin_request_time_control(void)
{
if (!has_control) {
has_control = true;
#ifdef CONFIG_SOFTMMU
error_setg(&migration_blocker,
"TCG plugin time control does not support migration");
migrate_add_blocker(&migration_blocker, NULL);
#endif
return &has_control;
}
return NULL;
}
#ifdef CONFIG_SOFTMMU
static void advance_virtual_time__async(CPUState *cpu, run_on_cpu_data data)
{
int64_t new_time = data.host_ulong;
qemu_clock_advance_virtual_time(new_time);
}
#endif
void qemu_plugin_update_ns(const void *handle, int64_t new_time)
{
#ifdef CONFIG_SOFTMMU
if (handle == &has_control) {
/* Need to execute out of cpu_exec, so bql can be locked. */
async_run_on_cpu(current_cpu,
advance_virtual_time__async,
RUN_ON_CPU_HOST_ULONG(new_time));
}
#endif
}

View file

@ -12,22 +12,14 @@
* SPDX-License-Identifier: GPL-2.0-or-later * SPDX-License-Identifier: GPL-2.0-or-later
*/ */
#include "qemu/osdep.h" #include "qemu/osdep.h"
#include "qemu/error-report.h"
#include "qemu/config-file.h"
#include "qapi/error.h"
#include "qemu/lockable.h" #include "qemu/lockable.h"
#include "qemu/option.h" #include "qemu/option.h"
#include "qemu/plugin.h" #include "qemu/plugin.h"
#include "qemu/queue.h" #include "qemu/queue.h"
#include "qemu/rcu_queue.h" #include "qemu/rcu_queue.h"
#include "qemu/xxhash.h"
#include "qemu/rcu.h" #include "qemu/rcu.h"
#include "hw/core/cpu.h"
#include "exec/exec-all.h"
#include "exec/tb-flush.h" #include "exec/tb-flush.h"
#include "tcg/tcg.h" #include "tcg/tcg-op-common.h"
#include "tcg/tcg-op.h"
#include "plugin.h" #include "plugin.h"
struct qemu_plugin_cb { struct qemu_plugin_cb {

View file

@ -31,9 +31,6 @@
#include "qemu/memalign.h" #include "qemu/memalign.h"
#include "hw/core/cpu.h" #include "hw/core/cpu.h"
#include "exec/tb-flush.h" #include "exec/tb-flush.h"
#ifndef CONFIG_USER_ONLY
#include "hw/boards.h"
#endif
#include "plugin.h" #include "plugin.h"
@ -297,17 +294,11 @@ int qemu_plugin_load_list(QemuPluginList *head, Error **errp)
struct qemu_plugin_desc *desc, *next; struct qemu_plugin_desc *desc, *next;
g_autofree qemu_info_t *info = g_new0(qemu_info_t, 1); g_autofree qemu_info_t *info = g_new0(qemu_info_t, 1);
info->target_name = TARGET_NAME; info->target_name = target_name();
info->version.min = QEMU_PLUGIN_MIN_VERSION; info->version.min = QEMU_PLUGIN_MIN_VERSION;
info->version.cur = QEMU_PLUGIN_VERSION; info->version.cur = QEMU_PLUGIN_VERSION;
#ifndef CONFIG_USER_ONLY
MachineState *ms = MACHINE(qdev_get_machine()); qemu_plugin_fillin_mode_info(info);
info->system_emulation = true;
info->system.smp_vcpus = ms->smp.cpus;
info->system.max_vcpus = ms->smp.max_cpus;
#else
info->system_emulation = false;
#endif
QTAILQ_FOREACH_SAFE(desc, head, entry, next) { QTAILQ_FOREACH_SAFE(desc, head, entry, next) {
int err; int err;

View file

@ -57,8 +57,9 @@ if host_os == 'windows'
command: dlltool_cmd command: dlltool_cmd
) )
endif endif
specific_ss.add(files(
'loader.c', user_ss.add(files('user.c', 'api-user.c'))
'core.c', system_ss.add(files('system.c', 'api-system.c'))
'api.c',
)) common_ss.add(files('loader.c', 'api.c', 'core.c'))

View file

@ -13,6 +13,7 @@
#define PLUGIN_H #define PLUGIN_H
#include <gmodule.h> #include <gmodule.h>
#include "qemu/queue.h"
#include "qemu/qht.h" #include "qemu/qht.h"
#define QEMU_PLUGIN_MIN_VERSION 2 #define QEMU_PLUGIN_MIN_VERSION 2
@ -118,4 +119,10 @@ struct qemu_plugin_scoreboard *plugin_scoreboard_new(size_t element_size);
void plugin_scoreboard_free(struct qemu_plugin_scoreboard *score); void plugin_scoreboard_free(struct qemu_plugin_scoreboard *score);
/**
* qemu_plugin_fillin_mode_info() - populate mode specific info
* info: pointer to qemu_info_t structure
*/
void qemu_plugin_fillin_mode_info(qemu_info_t *info);
#endif /* PLUGIN_H */ #endif /* PLUGIN_H */

24
plugins/system.c Normal file
View file

@ -0,0 +1,24 @@
/*
* QEMU Plugin system-emulation helpers
*
* Helpers that are specific to system emulation.
*
* Copyright (C) 2017, Emilio G. Cota <cota@braap.org>
* Copyright (C) 2019-2025, Linaro
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "qemu/osdep.h"
#include "qemu/plugin.h"
#include "hw/boards.h"
#include "plugin.h"
void qemu_plugin_fillin_mode_info(qemu_info_t *info)
{
MachineState *ms = MACHINE(qdev_get_machine());
info->system_emulation = true;
info->system.smp_vcpus = ms->smp.cpus;
info->system.max_vcpus = ms->smp.max_cpus;
}

19
plugins/user.c Normal file
View file

@ -0,0 +1,19 @@
/*
* QEMU Plugin user-mode helpers
*
* Helpers that are specific to user-mode.
*
* Copyright (C) 2017, Emilio G. Cota <cota@braap.org>
* Copyright (C) 2019-2025, Linaro
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "qemu/osdep.h"
#include "qemu/plugin.h"
#include "plugin.h"
void qemu_plugin_fillin_mode_info(qemu_info_t *info)
{
info->system_emulation = false;
}

View file

@ -123,6 +123,7 @@ packages:
- tar - tar
- tesseract-ocr - tesseract-ocr
- tesseract-ocr-eng - tesseract-ocr-eng
- vulkan-tools
- xorriso - xorriso
- zlib1g-dev - zlib1g-dev
- zstd - zstd

View file

@ -121,6 +121,7 @@ packages:
- tar - tar
- tesseract-ocr - tesseract-ocr
- tesseract-ocr-eng - tesseract-ocr-eng
- vulkan-tools
- xorriso - xorriso
- zlib1g-dev - zlib1g-dev
- zstd - zstd

View file

@ -1,10 +1,10 @@
# THIS FILE WAS AUTO-GENERATED # THIS FILE WAS AUTO-GENERATED
# #
# $ lcitool dockerfile --layers all alpine-319 qemu # $ lcitool dockerfile --layers all alpine-321 qemu
# #
# https://gitlab.com/libvirt/libvirt-ci # https://gitlab.com/libvirt/libvirt-ci
FROM docker.io/library/alpine:3.19 FROM docker.io/library/alpine:3.21
RUN apk update && \ RUN apk update && \
apk upgrade && \ apk upgrade && \
@ -111,6 +111,7 @@ RUN apk update && \
vde2-dev \ vde2-dev \
virglrenderer-dev \ virglrenderer-dev \
vte3-dev \ vte3-dev \
vulkan-tools \
which \ which \
xen-dev \ xen-dev \
xorriso \ xorriso \

View file

@ -115,6 +115,7 @@ RUN dnf distro-sync -y && \
usbredir-devel \ usbredir-devel \
util-linux \ util-linux \
vte291-devel \ vte291-devel \
vulkan-tools \
which \ which \
xorriso \ xorriso \
zlib-devel \ zlib-devel \

View file

@ -58,6 +58,7 @@ RUN export DEBIAN_FRONTEND=noninteractive && \
tar \ tar \
tesseract-ocr \ tesseract-ocr \
tesseract-ocr-eng \ tesseract-ocr-eng \
vulkan-tools \
xorriso \ xorriso \
zstd && \ zstd && \
eatmydata apt-get autoremove -y && \ eatmydata apt-get autoremove -y && \
@ -135,7 +136,7 @@ RUN export DEBIAN_FRONTEND=noninteractive && \
libsndio-dev:amd64 \ libsndio-dev:amd64 \
libspice-protocol-dev:amd64 \ libspice-protocol-dev:amd64 \
libspice-server-dev:amd64 \ libspice-server-dev:amd64 \
libssh-gcrypt-dev:amd64 \ libssh-dev:amd64 \
libsystemd-dev:amd64 \ libsystemd-dev:amd64 \
libtasn1-6-dev:amd64 \ libtasn1-6-dev:amd64 \
libubsan1:amd64 \ libubsan1:amd64 \

View file

@ -58,6 +58,7 @@ RUN export DEBIAN_FRONTEND=noninteractive && \
tar \ tar \
tesseract-ocr \ tesseract-ocr \
tesseract-ocr-eng \ tesseract-ocr-eng \
vulkan-tools \
xorriso \ xorriso \
zstd && \ zstd && \
eatmydata apt-get autoremove -y && \ eatmydata apt-get autoremove -y && \
@ -134,7 +135,7 @@ RUN export DEBIAN_FRONTEND=noninteractive && \
libsndio-dev:arm64 \ libsndio-dev:arm64 \
libspice-protocol-dev:arm64 \ libspice-protocol-dev:arm64 \
libspice-server-dev:arm64 \ libspice-server-dev:arm64 \
libssh-gcrypt-dev:arm64 \ libssh-dev:arm64 \
libsystemd-dev:arm64 \ libsystemd-dev:arm64 \
libtasn1-6-dev:arm64 \ libtasn1-6-dev:arm64 \
libubsan1:arm64 \ libubsan1:arm64 \

View file

@ -58,6 +58,7 @@ RUN export DEBIAN_FRONTEND=noninteractive && \
tar \ tar \
tesseract-ocr \ tesseract-ocr \
tesseract-ocr-eng \ tesseract-ocr-eng \
vulkan-tools \
xorriso \ xorriso \
zstd && \ zstd && \
eatmydata apt-get autoremove -y && \ eatmydata apt-get autoremove -y && \
@ -134,7 +135,7 @@ RUN export DEBIAN_FRONTEND=noninteractive && \
libsndio-dev:armhf \ libsndio-dev:armhf \
libspice-protocol-dev:armhf \ libspice-protocol-dev:armhf \
libspice-server-dev:armhf \ libspice-server-dev:armhf \
libssh-gcrypt-dev:armhf \ libssh-dev:armhf \
libsystemd-dev:armhf \ libsystemd-dev:armhf \
libtasn1-6-dev:armhf \ libtasn1-6-dev:armhf \
libubsan1:armhf \ libubsan1:armhf \

View file

@ -58,6 +58,7 @@ RUN export DEBIAN_FRONTEND=noninteractive && \
tar \ tar \
tesseract-ocr \ tesseract-ocr \
tesseract-ocr-eng \ tesseract-ocr-eng \
vulkan-tools \
xorriso \ xorriso \
zstd && \ zstd && \
eatmydata apt-get autoremove -y && \ eatmydata apt-get autoremove -y && \
@ -134,7 +135,7 @@ RUN export DEBIAN_FRONTEND=noninteractive && \
libsndio-dev:i386 \ libsndio-dev:i386 \
libspice-protocol-dev:i386 \ libspice-protocol-dev:i386 \
libspice-server-dev:i386 \ libspice-server-dev:i386 \
libssh-gcrypt-dev:i386 \ libssh-dev:i386 \
libsystemd-dev:i386 \ libsystemd-dev:i386 \
libtasn1-6-dev:i386 \ libtasn1-6-dev:i386 \
libubsan1:i386 \ libubsan1:i386 \

View file

@ -58,6 +58,7 @@ RUN export DEBIAN_FRONTEND=noninteractive && \
tar \ tar \
tesseract-ocr \ tesseract-ocr \
tesseract-ocr-eng \ tesseract-ocr-eng \
vulkan-tools \
xorriso \ xorriso \
zstd && \ zstd && \
eatmydata apt-get autoremove -y && \ eatmydata apt-get autoremove -y && \
@ -133,7 +134,7 @@ RUN export DEBIAN_FRONTEND=noninteractive && \
libsndio-dev:mips64el \ libsndio-dev:mips64el \
libspice-protocol-dev:mips64el \ libspice-protocol-dev:mips64el \
libspice-server-dev:mips64el \ libspice-server-dev:mips64el \
libssh-gcrypt-dev:mips64el \ libssh-dev:mips64el \
libsystemd-dev:mips64el \ libsystemd-dev:mips64el \
libtasn1-6-dev:mips64el \ libtasn1-6-dev:mips64el \
libudev-dev:mips64el \ libudev-dev:mips64el \

View file

@ -58,6 +58,7 @@ RUN export DEBIAN_FRONTEND=noninteractive && \
tar \ tar \
tesseract-ocr \ tesseract-ocr \
tesseract-ocr-eng \ tesseract-ocr-eng \
vulkan-tools \
xorriso \ xorriso \
zstd && \ zstd && \
eatmydata apt-get autoremove -y && \ eatmydata apt-get autoremove -y && \
@ -133,7 +134,7 @@ RUN export DEBIAN_FRONTEND=noninteractive && \
libsndio-dev:mipsel \ libsndio-dev:mipsel \
libspice-protocol-dev:mipsel \ libspice-protocol-dev:mipsel \
libspice-server-dev:mipsel \ libspice-server-dev:mipsel \
libssh-gcrypt-dev:mipsel \ libssh-dev:mipsel \
libsystemd-dev:mipsel \ libsystemd-dev:mipsel \
libtasn1-6-dev:mipsel \ libtasn1-6-dev:mipsel \
libudev-dev:mipsel \ libudev-dev:mipsel \

View file

@ -58,6 +58,7 @@ RUN export DEBIAN_FRONTEND=noninteractive && \
tar \ tar \
tesseract-ocr \ tesseract-ocr \
tesseract-ocr-eng \ tesseract-ocr-eng \
vulkan-tools \
xorriso \ xorriso \
zstd && \ zstd && \
eatmydata apt-get autoremove -y && \ eatmydata apt-get autoremove -y && \
@ -134,7 +135,7 @@ RUN export DEBIAN_FRONTEND=noninteractive && \
libsndio-dev:ppc64el \ libsndio-dev:ppc64el \
libspice-protocol-dev:ppc64el \ libspice-protocol-dev:ppc64el \
libspice-server-dev:ppc64el \ libspice-server-dev:ppc64el \
libssh-gcrypt-dev:ppc64el \ libssh-dev:ppc64el \
libsystemd-dev:ppc64el \ libsystemd-dev:ppc64el \
libtasn1-6-dev:ppc64el \ libtasn1-6-dev:ppc64el \
libubsan1:ppc64el \ libubsan1:ppc64el \

View file

@ -58,6 +58,7 @@ RUN export DEBIAN_FRONTEND=noninteractive && \
tar \ tar \
tesseract-ocr \ tesseract-ocr \
tesseract-ocr-eng \ tesseract-ocr-eng \
vulkan-tools \
xorriso \ xorriso \
zstd && \ zstd && \
eatmydata apt-get autoremove -y && \ eatmydata apt-get autoremove -y && \
@ -133,7 +134,7 @@ RUN export DEBIAN_FRONTEND=noninteractive && \
libsnappy-dev:s390x \ libsnappy-dev:s390x \
libsndio-dev:s390x \ libsndio-dev:s390x \
libspice-protocol-dev:s390x \ libspice-protocol-dev:s390x \
libssh-gcrypt-dev:s390x \ libssh-dev:s390x \
libsystemd-dev:s390x \ libsystemd-dev:s390x \
libtasn1-6-dev:s390x \ libtasn1-6-dev:s390x \
libubsan1:s390x \ libubsan1:s390x \

View file

@ -87,7 +87,7 @@ RUN export DEBIAN_FRONTEND=noninteractive && \
libsndio-dev \ libsndio-dev \
libspice-protocol-dev \ libspice-protocol-dev \
libspice-server-dev \ libspice-server-dev \
libssh-gcrypt-dev \ libssh-dev \
libsystemd-dev \ libsystemd-dev \
libtasn1-6-dev \ libtasn1-6-dev \
libubsan1 \ libubsan1 \
@ -131,6 +131,7 @@ RUN export DEBIAN_FRONTEND=noninteractive && \
tar \ tar \
tesseract-ocr \ tesseract-ocr \
tesseract-ocr-eng \ tesseract-ocr-eng \
vulkan-tools \
xorriso \ xorriso \
zlib1g-dev \ zlib1g-dev \
zstd && \ zstd && \

View file

@ -132,6 +132,7 @@ exec "$@"\n' > /usr/bin/nosync && \
util-linux \ util-linux \
virglrenderer-devel \ virglrenderer-devel \
vte291-devel \ vte291-devel \
vulkan-tools \
which \ which \
xen-devel \ xen-devel \
xorriso \ xorriso \

View file

@ -61,6 +61,7 @@ exec "$@"\n' > /usr/bin/nosync && \
tesseract \ tesseract \
tesseract-langpack-eng \ tesseract-langpack-eng \
util-linux \ util-linux \
vulkan-tools \
which \ which \
xorriso \ xorriso \
zstd && \ zstd && \

View file

@ -132,6 +132,7 @@ exec "$@"\n' > /usr/bin/nosync && \
util-linux \ util-linux \
virglrenderer-devel \ virglrenderer-devel \
vte291-devel \ vte291-devel \
vulkan-tools \
which \ which \
xen-devel \ xen-devel \
xorriso \ xorriso \

View file

@ -115,6 +115,7 @@ RUN zypper update -y && \
util-linux \ util-linux \
virglrenderer-devel \ virglrenderer-devel \
vte-devel \ vte-devel \
vulkan-tools \
which \ which \
xen-devel \ xen-devel \
xorriso \ xorriso \

View file

@ -130,6 +130,7 @@ RUN export DEBIAN_FRONTEND=noninteractive && \
tar \ tar \
tesseract-ocr \ tesseract-ocr \
tesseract-ocr-eng \ tesseract-ocr-eng \
vulkan-tools \
xorriso \ xorriso \
zlib1g-dev \ zlib1g-dev \
zstd && \ zstd && \

View file

@ -18,7 +18,8 @@ test_timeouts = {
'aarch64_sbsaref_alpine' : 1200, 'aarch64_sbsaref_alpine' : 1200,
'aarch64_sbsaref_freebsd' : 720, 'aarch64_sbsaref_freebsd' : 720,
'aarch64_tuxrun' : 240, 'aarch64_tuxrun' : 240,
'aarch64_virt' : 720, 'aarch64_virt' : 360,
'aarch64_virt_gpu' : 480,
'acpi_bits' : 420, 'acpi_bits' : 420,
'arm_aspeed_palmetto' : 120, 'arm_aspeed_palmetto' : 120,
'arm_aspeed_romulus' : 120, 'arm_aspeed_romulus' : 120,
@ -84,6 +85,7 @@ tests_aarch64_system_thorough = [
'aarch64_tcg_plugins', 'aarch64_tcg_plugins',
'aarch64_tuxrun', 'aarch64_tuxrun',
'aarch64_virt', 'aarch64_virt',
'aarch64_virt_gpu',
'aarch64_xen', 'aarch64_xen',
'aarch64_xlnx_versal', 'aarch64_xlnx_versal',
'multiprocess', 'multiprocess',
@ -383,7 +385,7 @@ foreach speed : ['quick', 'thorough']
# 'run_target' logic below & in Makefile.include # 'run_target' logic below & in Makefile.include
test('func-' + testname, test('func-' + testname,
python, python,
depends: [test_deps, test_emulator, emulator_modules], depends: [test_deps, test_emulator, emulator_modules, plugin_modules],
env: test_env, env: test_env,
args: [testpath], args: [testpath],
protocol: 'tap', protocol: 'tap',

View file

@ -7,7 +7,7 @@
from .asset import Asset from .asset import Asset
from .config import BUILD_DIR from .config import BUILD_DIR, dso_suffix
from .cmd import is_readable_executable_file, \ from .cmd import is_readable_executable_file, \
interrupt_interactive_console_until_pattern, wait_for_console_pattern, \ interrupt_interactive_console_until_pattern, wait_for_console_pattern, \
exec_command, exec_command_and_wait_for_pattern, get_qemu_img, which exec_command, exec_command_and_wait_for_pattern, get_qemu_img, which

View file

@ -13,6 +13,7 @@
import os import os
from pathlib import Path from pathlib import Path
import platform
def _source_dir(): def _source_dir():
@ -34,3 +35,14 @@ def _build_dir():
raise Exception("Cannot identify build dir, set QEMU_BUILD_ROOT") raise Exception("Cannot identify build dir, set QEMU_BUILD_ROOT")
BUILD_DIR = _build_dir() BUILD_DIR = _build_dir()
def dso_suffix():
'''Return the dynamic libraries suffix for the current platform'''
if platform.system() == "Darwin":
return "dylib"
if platform.system() == "Windows":
return "dll"
return "so"

View file

@ -27,7 +27,7 @@ from qemu.utils import kvm_available, tcg_available
from .archive import archive_extract from .archive import archive_extract
from .asset import Asset from .asset import Asset
from .config import BUILD_DIR from .config import BUILD_DIR, dso_suffix
from .uncompress import uncompress from .uncompress import uncompress
@ -183,6 +183,16 @@ class QemuBaseTest(unittest.TestCase):
def log_file(self, *args): def log_file(self, *args):
return str(Path(self.outputdir, *args)) return str(Path(self.outputdir, *args))
'''
@params plugin name
Return the full path to the plugin taking into account any host OS
specific suffixes.
'''
def plugin_file(self, plugin_name):
sfx = dso_suffix()
return os.path.join('tests', 'tcg', 'plugins', f'{plugin_name}.{sfx}')
def assets_available(self): def assets_available(self):
for name, asset in vars(self.__class__).items(): for name, asset in vars(self.__class__).items():
if name.startswith("ASSET_") and type(asset) == Asset: if name.startswith("ASSET_") and type(asset) == Asset:

View file

@ -60,7 +60,8 @@ class Aarch64RMESbsaRefMachine(QemuSystemTest):
self.vm.launch() self.vm.launch()
# Wait for host VM boot to complete. # Wait for host VM boot to complete.
wait_for_console_pattern(self, 'Welcome to Buildroot') wait_for_console_pattern(self, 'Welcome to Buildroot',
failure_message='Synchronous Exception at')
exec_command_and_wait_for_pattern(self, 'root', '#') exec_command_and_wait_for_pattern(self, 'root', '#')
test_realms_guest(self) test_realms_guest(self)

View file

@ -89,7 +89,8 @@ class Aarch64RMEVirtMachine(QemuSystemTest):
self.vm.launch() self.vm.launch()
# Wait for host VM boot to complete. # Wait for host VM boot to complete.
wait_for_console_pattern(self, 'Welcome to Buildroot') wait_for_console_pattern(self, 'Welcome to Buildroot',
failure_message='Synchronous Exception at')
exec_command_and_wait_for_pattern(self, 'root', '#') exec_command_and_wait_for_pattern(self, 'root', '#')
test_realms_guest(self) test_realms_guest(self)

View file

@ -13,6 +13,7 @@
import tempfile import tempfile
import mmap import mmap
import os
import re import re
from qemu.machine.machine import VMLaunchFailure from qemu.machine.machine import VMLaunchFailure
@ -74,7 +75,7 @@ class PluginKernelNormal(PluginKernelBase):
suffix=".log") suffix=".log")
self.run_vm(kernel_path, kernel_command_line, self.run_vm(kernel_path, kernel_command_line,
"tests/tcg/plugins/libinsn.so", plugin_log.name, self.plugin_file('libinsn'), plugin_log.name,
console_pattern) console_pattern)
with plugin_log as lf, \ with plugin_log as lf, \
@ -100,7 +101,7 @@ class PluginKernelNormal(PluginKernelBase):
suffix=".log") suffix=".log")
self.run_vm(kernel_path, kernel_command_line, self.run_vm(kernel_path, kernel_command_line,
"tests/tcg/plugins/libinsn.so", plugin_log.name, self.plugin_file('libinsn'), plugin_log.name,
console_pattern, console_pattern,
args=('-icount', 'shift=1')) args=('-icount', 'shift=1'))

View file

@ -134,77 +134,6 @@ class Aarch64VirtMachine(QemuSystemTest):
self.common_aarch64_virt("virt,gic-version=2") self.common_aarch64_virt("virt,gic-version=2")
ASSET_VIRT_GPU_KERNEL = Asset(
'https://fileserver.linaro.org/s/ce5jXBFinPxtEdx/'
'download?path=%2F&files='
'Image',
'89e5099d26166204cc5ca4bb6d1a11b92c217e1f82ec67e3ba363d09157462f6')
ASSET_VIRT_GPU_ROOTFS = Asset(
'https://fileserver.linaro.org/s/ce5jXBFinPxtEdx/'
'download?path=%2F&files='
'rootfs.ext4.zstd',
'792da7573f5dc2913ddb7c638151d4a6b2d028a4cb2afb38add513c1924bdad4')
@skipIfMissingCommands('zstd')
def test_aarch64_virt_with_gpu(self):
# This tests boots with a buildroot test image that contains
# vkmark and other GPU exercising tools. We run a headless
# weston that nevertheless still exercises the virtio-gpu
# backend.
self.set_machine('virt')
self.require_accelerator("tcg")
kernel_path = self.ASSET_VIRT_GPU_KERNEL.fetch()
image_path = self.uncompress(self.ASSET_VIRT_GPU_ROOTFS, format="zstd")
self.vm.set_console()
kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE +
'console=ttyAMA0 root=/dev/vda')
self.vm.add_args("-accel", "tcg")
self.vm.add_args("-cpu", "neoverse-v1,pauth-impdef=on")
self.vm.add_args("-machine", "virt,gic-version=max",
'-kernel', kernel_path,
'-append', kernel_command_line)
self.vm.add_args("-smp", "2", "-m", "2048")
self.vm.add_args("-device",
"virtio-gpu-gl-pci,hostmem=4G,blob=on,venus=on")
self.vm.add_args("-display", "egl-headless")
self.vm.add_args("-display", "dbus,gl=on")
self.vm.add_args("-device", "virtio-blk-device,drive=hd0")
self.vm.add_args("-blockdev",
"driver=raw,file.driver=file,"
"node-name=hd0,read-only=on,"
f"file.filename={image_path}")
self.vm.add_args("-snapshot")
try:
self.vm.launch()
except VMLaunchFailure as excp:
if "old virglrenderer, blob resources unsupported" in excp.output:
self.skipTest("No blob support for virtio-gpu")
elif "old virglrenderer, venus unsupported" in excp.output:
self.skipTest("No venus support for virtio-gpu")
elif "egl: no drm render node available" in excp.output:
self.skipTest("Can't access host DRM render node")
elif "'type' does not accept value 'egl-headless'" in excp.output:
self.skipTest("egl-headless support is not available")
else:
self.log.info(f"unhandled launch failure: {excp.output}")
raise excp
self.wait_for_console_pattern('buildroot login:')
exec_command(self, 'root')
exec_command(self, 'export XDG_RUNTIME_DIR=/tmp')
exec_command_and_wait_for_pattern(self,
"weston -B headless "
"--renderer gl "
"--shell kiosk "
"-- vkmark -b:duration=1.0",
"vkmark Score")
if __name__ == '__main__': if __name__ == '__main__':
QemuSystemTest.main() QemuSystemTest.main()

View file

@ -0,0 +1,137 @@
#!/usr/bin/env python3
#
# Functional tests for the various graphics modes we can support.
#
# Copyright (c) 2024, 2025 Linaro Ltd.
#
# Author:
# Alex Bennée <alex.bennee@linaro.org>
#
# SPDX-License-Identifier: GPL-2.0-or-later
from qemu.machine.machine import VMLaunchFailure
from qemu_test import Asset
from qemu_test import exec_command_and_wait_for_pattern as ec_and_wait
from qemu_test import skipIfMissingCommands
from qemu_test.linuxkernel import LinuxKernelTest
from re import search
from subprocess import check_output, CalledProcessError
class Aarch64VirtGPUMachine(LinuxKernelTest):
ASSET_VIRT_GPU_KERNEL = Asset(
'https://fileserver.linaro.org/s/ce5jXBFinPxtEdx/'
'download?path=%2F&files='
'Image.6.12.16.aarch64',
'7888c51c55d37e86bbbdeb5acea9f08c34e6b0f03c1f5b2463285f6a6f6eec8b')
ASSET_VIRT_GPU_ROOTFS = Asset(
'https://fileserver.linaro.org/s/ce5jXBFinPxtEdx/'
'download?path=%2F&files='
'rootfs.aarch64.ext2.zstd',
'd45118c899420b7e673f1539a37a35480134b3e36e3a59e2cb69b1781cbb14ef')
def _launch_virt_gpu(self, gpu_device):
self.set_machine('virt')
self.require_accelerator("tcg")
kernel_path = self.ASSET_VIRT_GPU_KERNEL.fetch()
image_path = self.uncompress(self.ASSET_VIRT_GPU_ROOTFS, format="zstd")
self.vm.set_console()
kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE +
'console=ttyAMA0 root=/dev/vda')
self.vm.add_args("-accel", "tcg")
self.vm.add_args("-cpu", "cortex-a72")
self.vm.add_args("-machine", "virt,gic-version=max",
'-kernel', kernel_path,
'-append', kernel_command_line)
self.vm.add_args("-smp", "2", "-m", "2048")
self.vm.add_args("-device", gpu_device)
self.vm.add_args("-display", "egl-headless")
self.vm.add_args("-display", "dbus,gl=on")
self.vm.add_args("-device", "virtio-blk-device,drive=hd0")
self.vm.add_args("-blockdev",
"driver=raw,file.driver=file,"
"node-name=hd0,read-only=on,"
f"file.filename={image_path}")
self.vm.add_args("-snapshot")
try:
self.vm.launch()
except VMLaunchFailure as excp:
if "old virglrenderer, blob resources unsupported" in excp.output:
self.skipTest("No blob support for virtio-gpu")
elif "old virglrenderer, venus unsupported" in excp.output:
self.skipTest("No venus support for virtio-gpu")
elif "egl: no drm render node available" in excp.output:
self.skipTest("Can't access host DRM render node")
elif "'type' does not accept value 'egl-headless'" in excp.output:
self.skipTest("egl-headless support is not available")
else:
self.log.info("unhandled launch failure: %s", excp.output)
raise excp
self.wait_for_console_pattern('buildroot login:')
ec_and_wait(self, 'root', '#')
def _run_virt_weston_test(self, cmd, fail = None):
# make it easier to detect successful return to shell
PS1 = 'RES=[$?] # '
OK_CMD = 'RES=[0] # '
ec_and_wait(self, 'export XDG_RUNTIME_DIR=/tmp', '#')
ec_and_wait(self, f"export PS1='{PS1}'", OK_CMD)
full_cmd = f"weston -B headless --renderer gl --shell kiosk -- {cmd}"
ec_and_wait(self, full_cmd, OK_CMD, fail)
@skipIfMissingCommands('zstd')
def test_aarch64_virt_with_virgl_gpu(self):
self.require_device('virtio-gpu-gl-pci')
self._launch_virt_gpu("virtio-gpu-gl-pci")
# subset of the glmark tests
tests = " ".join([f"-b {test}" for test in
["build", "texture", "shading",
"bump", "desktop", "buffer"]])
self._run_virt_weston_test("glmark2-wayland --validate " + tests)
@skipIfMissingCommands('zstd')
def test_aarch64_virt_with_virgl_blobs_gpu(self):
self.require_device('virtio-gpu-gl-pci')
self._launch_virt_gpu("virtio-gpu-gl-pci,hostmem=4G,blob=on")
self._run_virt_weston_test("glmark2-wayland -b:duration=1.0")
@skipIfMissingCommands('zstd')
def test_aarch64_virt_with_vulkan_gpu(self):
self.require_device('virtio-gpu-gl-pci')
try:
vk_info = check_output(["vulkaninfo", "--summary"],
encoding="utf-8")
except CalledProcessError as excp:
self.skipTest(f"Miss-configured host Vulkan: {excp.output}")
if search(r"driverID\s+=\s+DRIVER_ID_NVIDIA_PROPRIETARY", vk_info):
self.skipTest("Test skipped on NVIDIA proprietary driver")
self._launch_virt_gpu("virtio-gpu-gl-pci,hostmem=4G,blob=on,venus=on")
self._run_virt_weston_test("vkmark -b:duration=1.0",
"debug: stuck in fence wait with iter at")
if __name__ == '__main__':
LinuxKernelTest.main()

@ -1 +1 @@
Subproject commit b6a65806bc9b2b56985f5e97c936b77c7e7a99fc Subproject commit 18c4bfe02c467e5639bf9a687139735ccd7a3fff

View file

@ -122,6 +122,7 @@ packages:
- usbredir - usbredir
- virglrenderer - virglrenderer
- vte - vte
- vulkan-tools
- which - which
- xen - xen
- xorriso - xorriso

View file

@ -163,7 +163,7 @@ try:
# #
# Standard native builds # Standard native builds
# #
generate_dockerfile("alpine", "alpine-319") generate_dockerfile("alpine", "alpine-321")
generate_dockerfile("centos9", "centos-stream-9") generate_dockerfile("centos9", "centos-stream-9")
generate_dockerfile("debian", "debian-12", generate_dockerfile("debian", "debian-12",
trailer="".join(debian12_extras)) trailer="".join(debian12_extras))

View file

@ -83,7 +83,8 @@ test-aes: CFLAGS += -O -march=armv8-a+aes
test-aes: test-aes-main.c.inc test-aes: test-aes-main.c.inc
# Vector SHA1 # Vector SHA1
sha1-vector: CFLAGS=-O3 # Work around compiler false-positive warning, as we do for the 'sha1' test
sha1-vector: CFLAGS=-O3 -Wno-stringop-overread
sha1-vector: sha1.c sha1-vector: sha1.c
$(CC) $(CFLAGS) $(EXTRA_CFLAGS) $< -o $@ $(LDFLAGS) $(CC) $(CFLAGS) $(EXTRA_CFLAGS) $< -o $@ $(LDFLAGS)
run-sha1-vector: sha1-vector run-sha1 run-sha1-vector: sha1-vector run-sha1

View file

@ -61,7 +61,8 @@ endif
ARM_TESTS += commpage ARM_TESTS += commpage
# Vector SHA1 # Vector SHA1
sha1-vector: CFLAGS=-O3 # Work around compiler false-positive warning, as we do for the 'sha1' test
sha1-vector: CFLAGS=-O3 -Wno-stringop-overread
sha1-vector: sha1.c sha1-vector: sha1.c
$(CC) $(CFLAGS) $(EXTRA_CFLAGS) $< -o $@ $(LDFLAGS) $(CC) $(CFLAGS) $(EXTRA_CFLAGS) $< -o $@ $(LDFLAGS)
run-sha1-vector: sha1-vector run-sha1 run-sha1-vector: sha1-vector run-sha1

View file

@ -22,7 +22,7 @@ run-test-i386-sse-exceptions: QEMU_OPTS += -cpu max
test-i386-pcmpistri: CFLAGS += -msse4.2 test-i386-pcmpistri: CFLAGS += -msse4.2
run-test-i386-pcmpistri: QEMU_OPTS += -cpu max run-test-i386-pcmpistri: QEMU_OPTS += -cpu max
test-i386-bmi2: CFLAGS=-O2 test-i386-bmi2: CFLAGS=-O2 -fwrapv
run-test-i386-bmi2: QEMU_OPTS += -cpu max run-test-i386-bmi2: QEMU_OPTS += -cpu max
test-i386-adcox: CFLAGS=-O2 test-i386-adcox: CFLAGS=-O2

View file

@ -244,7 +244,7 @@ v4di indexd = {0x00000002ffffffcdull, 0xfffffff500000010ull,
0x0000003afffffff0ull, 0x000000000000000eull}; 0x0000003afffffff0ull, 0x000000000000000eull};
v4di gather_mem[0x20]; v4di gather_mem[0x20];
_Static_assert(sizeof(gather_mem) == 1024); _Static_assert(sizeof(gather_mem) == 1024, "gather_mem not expected size");
void init_f16reg(v4di *r) void init_f16reg(v4di *r)
{ {

View file

@ -29,7 +29,7 @@ void test_adox_adcx(uint32_t in_c, uint32_t in_o, REG adcx_operand, REG adox_ope
"adcx %3, %1;" "adcx %3, %1;"
"pushf; pop %0" "pushf; pop %0"
: "+r" (flags), "+r" (out_adcx), "+r" (out_adox) : "+r" (flags), "+r" (out_adcx), "+r" (out_adox)
: "r" ((REG)-1), "0" (flags), "1" (out_adcx), "2" (out_adox)); : "r" ((REG) - 1), "0" (flags), "1" (out_adcx), "2" (out_adox));
assert(out_adcx == in_c + adcx_operand - 1); assert(out_adcx == in_c + adcx_operand - 1);
assert(out_adox == in_o + adox_operand - 1); assert(out_adox == in_o + adox_operand - 1);
@ -53,8 +53,8 @@ void test_adcx_adox(uint32_t in_c, uint32_t in_o, REG adcx_operand, REG adox_ope
"adcx %3, %1;" "adcx %3, %1;"
"adox %3, %2;" "adox %3, %2;"
"pushf; pop %0" "pushf; pop %0"
: "+r" (flags), "+r" (out_adcx), "+r" (out_adox) : "+r"(flags), "+r"(out_adcx), "+r"(out_adox)
: "r" ((REG)-1), "0" (flags), "1" (out_adcx), "2" (out_adox)); : "r" ((REG)-1));
assert(out_adcx == in_c + adcx_operand - 1); assert(out_adcx == in_c + adcx_operand - 1);
assert(out_adox == in_o + adox_operand - 1); assert(out_adox == in_o + adox_operand - 1);

View file

@ -45,6 +45,14 @@ vma-pthread: LDFLAGS+=-pthread
sigreturn-sigmask: CFLAGS+=-pthread sigreturn-sigmask: CFLAGS+=-pthread
sigreturn-sigmask: LDFLAGS+=-pthread sigreturn-sigmask: LDFLAGS+=-pthread
# GCC versions 12/13/14/15 at least incorrectly complain about
# "'SHA1Transform' reading 64 bytes from a region of size 0"; see the gcc bug
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106709
# Since this is just a standard piece of library code we've borrowed for a
# TCG test case, suppress the warning rather than trying to modify the
# code to work around the compiler.
sha1: CFLAGS+=-Wno-stringop-overread -Wno-unknown-warning-option
# The vma-pthread seems very sensitive on gitlab and we currently # The vma-pthread seems very sensitive on gitlab and we currently
# don't know if its exposing a real bug or the test is flaky. # don't know if its exposing a real bug or the test is flaky.
ifneq ($(GITLAB_CI),) ifneq ($(GITLAB_CI),)

View file

@ -19,3 +19,5 @@ if t.length() > 0
else else
run_target('test-plugins', command: find_program('true')) run_target('test-plugins', command: find_program('true'))
endif endif
plugin_modules += t

View file

@ -83,7 +83,7 @@ class BaseVM(object):
# command to halt the guest, can be overridden by subclasses # command to halt the guest, can be overridden by subclasses
poweroff = "poweroff" poweroff = "poweroff"
# Time to wait for shutdown to finish. # Time to wait for shutdown to finish.
shutdown_timeout_default = 30 shutdown_timeout_default = 90
# enable IPv6 networking # enable IPv6 networking
ipv6 = True ipv6 = True
# This is the timeout on the wait for console bytes. # This is the timeout on the wait for console bytes.

View file

@ -73,6 +73,7 @@
"usbredir", "usbredir",
"virglrenderer", "virglrenderer",
"vte3", "vte3",
"vulkan-tools",
"xorriso", "xorriso",
"zstd" "zstd"
], ],