1 change: 1 addition & 0 deletions hw/ppc/ppc4xx_sdram.c
Expand Up @@ -33,6 +33,7 @@
#include "qemu/units.h"
#include "qapi/error.h"
#include "qemu/log.h"
#include "qemu/error-report.h"
#include "exec/address-spaces.h" /* get_system_memory() */
#include "hw/irq.h"
#include "hw/qdev-properties.h"
Expand Down
2 changes: 2 additions & 0 deletions hw/ppc/spapr_softmmu.c
@@ -1,12 +1,14 @@
#include "qemu/osdep.h"
#include "qemu/cutils.h"
#include "qemu/memalign.h"
#include "qemu/error-report.h"
#include "cpu.h"
#include "helper_regs.h"
#include "hw/ppc/spapr.h"
#include "mmu-hash64.h"
#include "mmu-book3s-v3.h"


static inline bool valid_ptex(PowerPCCPU *cpu, target_ulong ptex)
{
/*
Expand Down
1 change: 1 addition & 0 deletions hw/riscv/opentitan.c
Expand Up @@ -22,6 +22,7 @@
#include "qemu/cutils.h"
#include "hw/riscv/opentitan.h"
#include "qapi/error.h"
#include "qemu/error-report.h"
#include "hw/boards.h"
#include "hw/misc/unimp.h"
#include "hw/riscv/boot.h"
Expand Down
1 change: 1 addition & 0 deletions hw/riscv/shakti_c.c
Expand Up @@ -20,6 +20,7 @@
#include "hw/boards.h"
#include "hw/riscv/shakti_c.h"
#include "qapi/error.h"
#include "qemu/error-report.h"
#include "hw/intc/sifive_plic.h"
#include "hw/intc/riscv_aclint.h"
#include "sysemu/sysemu.h"
Expand Down
1 change: 1 addition & 0 deletions hw/riscv/virt-acpi-build.c
Expand Up @@ -29,6 +29,7 @@
#include "hw/acpi/aml-build.h"
#include "hw/acpi/utils.h"
#include "qapi/error.h"
#include "qemu/error-report.h"
#include "sysemu/reset.h"
#include "migration/vmstate.h"
#include "hw/riscv/virt.h"
Expand Down
1 change: 1 addition & 0 deletions hw/vfio/display.c
Expand Up @@ -14,6 +14,7 @@
#include <linux/vfio.h>
#include <sys/ioctl.h>

#include "qemu/error-report.h"
#include "hw/display/edid.h"
#include "ui/console.h"
#include "qapi/error.h"
Expand Down
1 change: 1 addition & 0 deletions hw/vfio/igd.c
Expand Up @@ -12,6 +12,7 @@

#include "qemu/osdep.h"
#include "qemu/units.h"
#include "qemu/error-report.h"
#include "qapi/error.h"
#include "hw/hw.h"
#include "hw/nvram/fw_cfg.h"
Expand Down
1 change: 1 addition & 0 deletions hw/vfio/migration.c
Expand Up @@ -11,6 +11,7 @@
#include "qemu/main-loop.h"
#include "qemu/cutils.h"
#include "qemu/units.h"
#include "qemu/error-report.h"
#include <linux/vfio.h>
#include <sys/ioctl.h>

Expand Down
2 changes: 1 addition & 1 deletion include/hw/core/cpu.h
Expand Up @@ -30,7 +30,7 @@
#include "qemu/rcu_queue.h"
#include "qemu/queue.h"
#include "qemu/thread.h"
#include "qemu/plugin.h"
#include "qemu/plugin-event.h"
#include "qom/object.h"

typedef int (*WriteCoreDumpFunction)(const void *buf, size_t size,
Expand Down
26 changes: 26 additions & 0 deletions include/qemu/plugin-event.h
@@ -0,0 +1,26 @@
/*
* Copyright (C) 2017, Emilio G. Cota <cota@braap.org>
*
* License: GNU GPL, version 2 or later.
* See the COPYING file in the top-level directory.
*/
#ifndef QEMU_PLUGIN_EVENT_H
#define QEMU_PLUGIN_EVENT_H

/*
* Events that plugins can subscribe to.
*/
enum qemu_plugin_event {
QEMU_PLUGIN_EV_VCPU_INIT,
QEMU_PLUGIN_EV_VCPU_EXIT,
QEMU_PLUGIN_EV_VCPU_TB_TRANS,
QEMU_PLUGIN_EV_VCPU_IDLE,
QEMU_PLUGIN_EV_VCPU_RESUME,
QEMU_PLUGIN_EV_VCPU_SYSCALL,
QEMU_PLUGIN_EV_VCPU_SYSCALL_RET,
QEMU_PLUGIN_EV_FLUSH,
QEMU_PLUGIN_EV_ATEXIT,
QEMU_PLUGIN_EV_MAX, /* total number of plugin events we support */
};

#endif /* QEMU_PLUGIN_EVENT_H */
27 changes: 6 additions & 21 deletions include/qemu/plugin.h
Expand Up @@ -12,23 +12,9 @@
#include "qemu/error-report.h"
#include "qemu/queue.h"
#include "qemu/option.h"
#include "qemu/plugin-event.h"
#include "exec/memopidx.h"

/*
* Events that plugins can subscribe to.
*/
enum qemu_plugin_event {
QEMU_PLUGIN_EV_VCPU_INIT,
QEMU_PLUGIN_EV_VCPU_EXIT,
QEMU_PLUGIN_EV_VCPU_TB_TRANS,
QEMU_PLUGIN_EV_VCPU_IDLE,
QEMU_PLUGIN_EV_VCPU_RESUME,
QEMU_PLUGIN_EV_VCPU_SYSCALL,
QEMU_PLUGIN_EV_VCPU_SYSCALL_RET,
QEMU_PLUGIN_EV_FLUSH,
QEMU_PLUGIN_EV_ATEXIT,
QEMU_PLUGIN_EV_MAX, /* total number of plugin events we support */
};
#include "hw/core/cpu.h"

/*
* Option parsing/processing.
Expand Down Expand Up @@ -59,8 +45,6 @@ get_plugin_meminfo_rw(qemu_plugin_meminfo_t i)
#ifdef CONFIG_PLUGIN
extern QemuOptsList qemu_plugin_opts;

#define QEMU_PLUGIN_ASSERT(cond) g_assert(cond)

static inline void qemu_plugin_add_opts(void)
{
qemu_add_opts(&qemu_plugin_opts);
Expand Down Expand Up @@ -221,7 +205,10 @@ void qemu_plugin_atexit_cb(void);

void qemu_plugin_add_dyn_cb_arr(GArray *arr);

void qemu_plugin_disable_mem_helpers(CPUState *cpu);
static inline void qemu_plugin_disable_mem_helpers(CPUState *cpu)
{
cpu->plugin_mem_cbs = NULL;
}

/**
* qemu_plugin_user_exit(): clean-up callbacks before calling exit callbacks
Expand Down Expand Up @@ -252,8 +239,6 @@ void qemu_plugin_user_postfork(bool is_child);

#else /* !CONFIG_PLUGIN */

#define QEMU_PLUGIN_ASSERT(cond)

static inline void qemu_plugin_add_opts(void)
{ }

Expand Down
47 changes: 43 additions & 4 deletions include/qemu/qemu-plugin.h
Expand Up @@ -481,17 +481,56 @@ uint64_t qemu_plugin_hwaddr_phys_addr(const struct qemu_plugin_hwaddr *haddr);
*/
const char *qemu_plugin_hwaddr_device_name(const struct qemu_plugin_hwaddr *h);

typedef void
(*qemu_plugin_vcpu_mem_cb_t)(unsigned int vcpu_index,
qemu_plugin_meminfo_t info, uint64_t vaddr,
void *userdata);
/**
* typedef qemu_plugin_vcpu_mem_cb_t - memory callback function type
* @vcpu_index: the executing vCPU
* @info: an opaque handle for further queries about the memory
* @vaddr: the virtual address of the transaction
* @userdata: any user data attached to the callback
*/
typedef void (*qemu_plugin_vcpu_mem_cb_t) (unsigned int vcpu_index,
qemu_plugin_meminfo_t info,
uint64_t vaddr,
void *userdata);

/**
* qemu_plugin_register_vcpu_mem_cb() - register memory access callback
* @insn: handle for instruction to instrument
* @cb: callback of type qemu_plugin_vcpu_mem_cb_t
* @flags: (currently unused) callback flags
* @rw: monitor reads, writes or both
* @userdata: opaque pointer for userdata
*
* This registers a full callback for every memory access generated by
* an instruction. If the instruction doesn't access memory no
* callback will be made.
*
* The callback reports the vCPU the access took place on, the virtual
* address of the access and a handle for further queries. The user
* can attach some userdata to the callback for additional purposes.
*
* Other execution threads will continue to execute during the
* callback so the plugin is responsible for ensuring it doesn't get
* confused by making appropriate use of locking if required.
*/
void qemu_plugin_register_vcpu_mem_cb(struct qemu_plugin_insn *insn,
qemu_plugin_vcpu_mem_cb_t cb,
enum qemu_plugin_cb_flags flags,
enum qemu_plugin_mem_rw rw,
void *userdata);

/**
* qemu_plugin_register_vcpu_mem_inline() - register an inline op to any memory access
* @insn: handle for instruction to instrument
* @rw: apply to reads, writes or both
* @op: the op, of type qemu_plugin_op
* @ptr: pointer memory for the op
* @imm: immediate data for @op
*
* This registers a inline op every memory access generated by the
* instruction. This provides for a lightweight but not thread-safe
* way of counting the number of operations done.
*/
void qemu_plugin_register_vcpu_mem_inline(struct qemu_plugin_insn *insn,
enum qemu_plugin_mem_rw rw,
enum qemu_plugin_op op, void *ptr,
Expand Down
1 change: 1 addition & 0 deletions include/user/syscall-trace.h
Expand Up @@ -11,6 +11,7 @@
#define SYSCALL_TRACE_H

#include "exec/user/abitypes.h"
#include "qemu/plugin.h"
#include "trace/trace-root.h"

/*
Expand Down
1 change: 1 addition & 0 deletions linux-user/elfload.c
Expand Up @@ -18,6 +18,7 @@
#include "qemu/units.h"
#include "qemu/selfmap.h"
#include "qapi/error.h"
#include "qemu/error-report.h"
#include "target_signal.h"
#include "accel/tcg/debuginfo.h"

Expand Down
1 change: 1 addition & 0 deletions linux-user/exit.c
Expand Up @@ -21,6 +21,7 @@
#include "gdbstub/syscalls.h"
#include "qemu.h"
#include "user-internals.h"
#include "qemu/plugin.h"
#ifdef CONFIG_GPROF
#include <sys/gmon.h>
#endif
Expand Down
1 change: 1 addition & 0 deletions linux-user/syscall.c
Expand Up @@ -22,6 +22,7 @@
#include "qemu/path.h"
#include "qemu/memfd.h"
#include "qemu/queue.h"
#include "qemu/plugin.h"
#include "target_mman.h"
#include <elf.h>
#include <endian.h>
Expand Down
1 change: 1 addition & 0 deletions migration/dirtyrate.c
Expand Up @@ -11,6 +11,7 @@
*/

#include "qemu/osdep.h"
#include "qemu/error-report.h"
#include <zlib.h>
#include "qapi/error.h"
#include "cpu.h"
Expand Down
1 change: 1 addition & 0 deletions migration/exec.c
Expand Up @@ -18,6 +18,7 @@
*/

#include "qemu/osdep.h"
#include "qemu/error-report.h"
#include "channel.h"
#include "exec.h"
#include "migration.h"
Expand Down
11 changes: 0 additions & 11 deletions plugins/core.c
Expand Up @@ -553,17 +553,6 @@ void qemu_plugin_user_postfork(bool is_child)
}
}


/*
* Call this function after longjmp'ing to the main loop. It's possible that the
* last instruction of a TB might have used helpers, and therefore the
* "disable" instruction will never execute because it ended up as dead code.
*/
void qemu_plugin_disable_mem_helpers(CPUState *cpu)
{
cpu->plugin_mem_cbs = NULL;
}

static bool plugin_dyn_cb_arr_cmp(const void *ap, const void *bp)
{
return ap == bp;
Expand Down
1 change: 1 addition & 0 deletions scripts/ci/org.centos/stream/8/build-environment.yml
Expand Up @@ -55,6 +55,7 @@
- librados-devel
- librbd-devel
- libseccomp-devel
- libslirp-devel
- libssh-devel
- libxkbcommon-devel
- lzo-devel
Expand Down
20 changes: 18 additions & 2 deletions scripts/ci/setup/gitlab-runner.yml
Expand Up @@ -48,13 +48,29 @@
- debug:
msg: gitlab-runner arch is {{ gitlab_runner_arch }}

- name: Download the matching gitlab-runner
- name: Download the matching gitlab-runner (DEB)
get_url:
dest: "/root/"
url: "https://gitlab-runner-downloads.s3.amazonaws.com/latest/deb/gitlab-runner_{{ gitlab_runner_arch }}.deb"
when:
- ansible_facts['distribution'] == 'Ubuntu'

- name: Download the matching gitlab-runner (RPM)
get_url:
dest: "/root/"
url: "https://gitlab-runner-downloads.s3.amazonaws.com/latest/rpm/gitlab-runner_{{ gitlab_runner_arch }}.rpm"
when:
- ansible_facts['distribution'] == 'CentOS'

- name: Install gitlab-runner via package manager
- name: Install gitlab-runner via package manager (DEB)
apt: deb="/root/gitlab-runner_{{ gitlab_runner_arch }}.deb"
when:
- ansible_facts['distribution'] == 'Ubuntu'

- name: Install gitlab-runner via package manager (RPM)
yum: name="/root/gitlab-runner_{{ gitlab_runner_arch }}.rpm"
when:
- ansible_facts['distribution'] == 'CentOS'

- name: Register the gitlab-runner
command: "/usr/bin/gitlab-runner register --non-interactive --url {{ gitlab_runner_server_url }} --registration-token {{ gitlab_runner_registration_token }} --executor shell --tag-list {{ ansible_facts[\"architecture\"] }},{{ ansible_facts[\"distribution\"]|lower }}_{{ ansible_facts[\"distribution_version\"] }} --description '{{ ansible_facts[\"distribution\"] }} {{ ansible_facts[\"distribution_version\"] }} {{ ansible_facts[\"architecture\"] }} ({{ ansible_facts[\"os_family\"] }})'"
Expand Down
1 change: 1 addition & 0 deletions target/i386/cpu.c
Expand Up @@ -29,6 +29,7 @@
#include "kvm/kvm_i386.h"
#include "sev.h"
#include "qapi/error.h"
#include "qemu/error-report.h"
#include "qapi/qapi-visit-machine.h"
#include "qapi/qmp/qerror.h"
#include "standard-headers/asm-x86/kvm_para.h"
Expand Down
1 change: 1 addition & 0 deletions target/i386/host-cpu.c
Expand Up @@ -11,6 +11,7 @@
#include "cpu.h"
#include "host-cpu.h"
#include "qapi/error.h"
#include "qemu/error-report.h"
#include "sysemu/sysemu.h"

/* Note: Only safe for use on x86(-64) hosts */
Expand Down
1 change: 1 addition & 0 deletions target/i386/kvm/xen-emu.c
Expand Up @@ -12,6 +12,7 @@
#include "qemu/osdep.h"
#include "qemu/log.h"
#include "qemu/main-loop.h"
#include "qemu/error-report.h"
#include "hw/xen/xen.h"
#include "sysemu/kvm_int.h"
#include "sysemu/kvm_xen.h"
Expand Down
1 change: 1 addition & 0 deletions target/i386/sev.c
Expand Up @@ -23,6 +23,7 @@
#include "qemu/base64.h"
#include "qemu/module.h"
#include "qemu/uuid.h"
#include "qemu/error-report.h"
#include "crypto/hash.h"
#include "sysemu/kvm.h"
#include "sev.h"
Expand Down
1 change: 1 addition & 0 deletions target/i386/whpx/whpx-apic.c
Expand Up @@ -11,6 +11,7 @@
* See the COPYING file in the top-level directory.
*/
#include "qemu/osdep.h"
#include "qemu/error-report.h"
#include "cpu.h"
#include "hw/i386/apic_internal.h"
#include "hw/i386/apic-msidef.h"
Expand Down
1 change: 1 addition & 0 deletions target/mips/cpu.c
Expand Up @@ -21,6 +21,7 @@
#include "qemu/osdep.h"
#include "qemu/cutils.h"
#include "qemu/qemu-print.h"
#include "qemu/error-report.h"
#include "qapi/error.h"
#include "cpu.h"
#include "internal.h"
Expand Down
1 change: 1 addition & 0 deletions target/s390x/cpu-sysemu.c
Expand Up @@ -21,6 +21,7 @@
*/

#include "qemu/osdep.h"
#include "qemu/error-report.h"
#include "qapi/error.h"
#include "cpu.h"
#include "s390x-internal.h"
Expand Down
1 change: 1 addition & 0 deletions target/s390x/cpu_models.c
Expand Up @@ -17,6 +17,7 @@
#include "sysemu/kvm.h"
#include "sysemu/tcg.h"
#include "qapi/error.h"
#include "qemu/error-report.h"
#include "qapi/visitor.h"
#include "qemu/module.h"
#include "qemu/hw-version.h"
Expand Down
2 changes: 2 additions & 0 deletions target/s390x/diag.c
Expand Up @@ -22,6 +22,8 @@
#include "hw/s390x/pv.h"
#include "sysemu/kvm.h"
#include "kvm/kvm_s390x.h"
#include "qemu/error-report.h"


int handle_diag_288(CPUS390XState *env, uint64_t r1, uint64_t r3)
{
Expand Down
1 change: 0 additions & 1 deletion tcg/tcg-op.c
Expand Up @@ -2808,7 +2808,6 @@ void tcg_gen_exit_tb(const TranslationBlock *tb, unsigned idx)
tcg_debug_assert(idx == TB_EXIT_REQUESTED);
}

plugin_gen_disable_mem_helpers();
tcg_gen_op1i(INDEX_op_exit_tb, val);
}

Expand Down
10 changes: 10 additions & 0 deletions tests/avocado/avocado_qemu/__init__.py
Expand Up @@ -309,6 +309,16 @@ def require_netdev(self, netdevname):
if netdevhelp.find('\n' + netdevname + '\n') < 0:
self.cancel('no support for user networking')

def require_multiprocess(self):
"""
Test for the presence of the x-pci-proxy-dev which is required
to support multiprocess.
"""
devhelp = run_cmd([self.qemu_bin,
'-M', 'none', '-device', 'help'])[0];
if devhelp.find('x-pci-proxy-dev') < 0:
self.cancel('no support for multiprocess device emulation')

def _new_vm(self, name, *args):
self._sd = tempfile.TemporaryDirectory(prefix="qemu_")
vm = QEMUMachine(self.qemu_bin, base_temp_dir=self.workdir,
Expand Down
38 changes: 0 additions & 38 deletions tests/avocado/igb.py

This file was deleted.

8 changes: 4 additions & 4 deletions tests/avocado/machine_aarch64_virt.py
Expand Up @@ -38,11 +38,11 @@ def test_alpine_virt_tcg_gic_max(self):
:avocado: tags=accel:tcg
"""
iso_url = ('https://dl-cdn.alpinelinux.org/'
'alpine/v3.16/releases/aarch64/'
'alpine-virt-3.16.3-aarch64.iso')
'alpine/v3.17/releases/aarch64/'
'alpine-standard-3.17.2-aarch64.iso')

# Alpine use sha256 so I recalculated this myself
iso_sha1 = '0683bc089486d55c91bf6607d5ecb93925769bc0'
iso_sha1 = '76284fcd7b41fe899b0c2375ceb8470803eea839'
iso_path = self.fetch_asset(iso_url, asset_hash=iso_sha1)

self.vm.set_console()
Expand All @@ -65,7 +65,7 @@ def test_alpine_virt_tcg_gic_max(self):
self.vm.add_args('-object', 'rng-random,id=rng0,filename=/dev/urandom')

self.vm.launch()
self.wait_for_console_pattern('Welcome to Alpine Linux 3.16')
self.wait_for_console_pattern('Welcome to Alpine Linux 3.17')


def common_aarch64_virt(self, machine):
Expand Down
1 change: 1 addition & 0 deletions tests/avocado/multiprocess.py
Expand Up @@ -22,6 +22,7 @@ def do_test(self, kernel_url, initrd_url, kernel_command_line,
machine_type):
"""Main test method"""
self.require_accelerator('kvm')
self.require_multiprocess()

# Create socketpair to connect proxy and remote processes
proxy_sock, remote_sock = socket.socketpair(socket.AF_UNIX,
Expand Down
116 changes: 116 additions & 0 deletions tests/avocado/netdev-ethtool.py
@@ -0,0 +1,116 @@
# ethtool tests for emulated network devices
#
# This test leverages ethtool's --test sequence to validate network
# device behaviour.
#
# SPDX-License-Identifier: GPL-2.0-or-late

from avocado import skip
from avocado_qemu import QemuSystemTest
from avocado_qemu import exec_command, exec_command_and_wait_for_pattern
from avocado_qemu import wait_for_console_pattern

class NetDevEthtool(QemuSystemTest):
"""
:avocado: tags=arch:x86_64
:avocado: tags=machine:q35
"""

# Runs in about 17s under KVM, 19s under TCG, 25s under GCOV
timeout = 45

# Fetch assets from the netdev-ethtool subdir of my shared test
# images directory on fileserver.linaro.org.
def get_asset(self, name, sha1):
base_url = ('https://fileserver.linaro.org/s/'
'kE4nCFLdQcoBF9t/download?'
'path=%2Fnetdev-ethtool&files=' )
url = base_url + name
# use explicit name rather than failing to neatly parse the
# URL into a unique one
return self.fetch_asset(name=name, locations=(url), asset_hash=sha1)

def common_test_code(self, netdev, extra_args=None, kvm=False):

# This custom kernel has drivers for all the supported network
# devices we can emulate in QEMU
kernel = self.get_asset("bzImage",
"33469d7802732d5815226166581442395cb289e2")

rootfs = self.get_asset("rootfs.squashfs",
"9793cea7021414ae844bda51f558bd6565b50cdc")

append = 'printk.time=0 console=ttyS0 '
append += 'root=/dev/sr0 rootfstype=squashfs '

# any additional kernel tweaks for the test
if extra_args:
append += extra_args

# finally invoke ethtool directly
append += ' init=/usr/sbin/ethtool -- -t eth1 offline'

# add the rootfs via a readonly cdrom image
drive = f"file={rootfs},if=ide,index=0,media=cdrom"

self.vm.add_args('-kernel', kernel,
'-append', append,
'-drive', drive,
'-device', netdev)

if kvm:
self.vm.add_args('-accel', 'kvm')

self.vm.set_console(console_index=0)
self.vm.launch()

wait_for_console_pattern(self,
"The test result is PASS",
"The test result is FAIL",
vm=None)
# no need to gracefully shutdown, just finish
self.vm.kill()

# Skip testing for MSI for now. Allegedly it was fixed by:
# 28e96556ba (igb: Allocate MSI-X vector when testing)
# but I'm seeing oops in the kernel
@skip("Kernel bug with MSI enabled")
def test_igb(self):
"""
:avocado: tags=device:igb
"""
self.common_test_code("igb")

def test_igb_nomsi(self):
"""
:avocado: tags=device:igb
"""
self.common_test_code("igb", "pci=nomsi")

def test_igb_nomsi_kvm(self):
"""
:avocado: tags=device:igb
"""
self.require_accelerator('kvm')
self.common_test_code("igb", "pci=nomsi", True)

# It seems the other popular cards we model in QEMU currently fail
# the pattern test with:
#
# pattern test failed (reg 0x00178): got 0x00000000 expected 0x00005A5A
#
# So for now we skip them.

@skip("Incomplete reg 0x00178 support")
def test_e1000(self):
"""
:avocado: tags=device:e1000
"""
self.common_test_code("e1000")

@skip("Incomplete reg 0x00178 support")
def test_i82550(self):
"""
:avocado: tags=device:i82550
"""
self.common_test_code("i82550")
60 changes: 24 additions & 36 deletions tests/avocado/tuxrun_baselines.py
Expand Up @@ -67,9 +67,6 @@ def setUp(self):
# The name of the kernel Image file
self.image = self.get_tag('image', "Image")

# The block device drive type
self.drive = self.get_tag('drive', "virtio-blk-device")

self.root = self.get_tag('root', "vda")

# Occasionally we need extra devices to hook things up
Expand Down Expand Up @@ -99,7 +96,7 @@ def fetch_tuxrun_assets(self, dt=None):

return (kernel_image, self.workdir + "/rootfs.ext4", dtb)

def prepare_run(self, kernel, disk, dtb=None, console_index=0):
def prepare_run(self, kernel, disk, drive, dtb=None, console_index=0):
"""
Setup to run and add the common parameters to the system
"""
Expand All @@ -121,10 +118,8 @@ def prepare_run(self, kernel, disk, dtb=None, console_index=0):
if self.extradev:
self.vm.add_args('-device', self.extradev)

# Some machines already define a drive device
if self.drive != "none":
self.vm.add_args('-device',
f"{self.drive},drive=hd0")
self.vm.add_args('-device',
f"{drive},drive=hd0")

# Some machines need an explicit DTB
if dtb:
Expand Down Expand Up @@ -154,7 +149,9 @@ def run_tuxtest_tests(self, haltmsg):
else:
self.vm.wait()

def common_tuxrun(self, dt=None, haltmsg="reboot: System halted",
def common_tuxrun(self, dt=None,
drive="virtio-blk-device",
haltmsg="reboot: System halted",
console_index=0):
"""
Common path for LKFT tests. Unless we need to do something
Expand All @@ -163,7 +160,7 @@ def common_tuxrun(self, dt=None, haltmsg="reboot: System halted",
"""
(kernel, disk, dtb) = self.fetch_tuxrun_assets(dt)

self.prepare_run(kernel, disk, dtb, console_index)
self.prepare_run(kernel, disk, drive, dtb, console_index)
self.vm.launch()
self.run_tuxtest_tests(haltmsg)

Expand Down Expand Up @@ -206,11 +203,11 @@ def test_armv5(self):
:avocado: tags=machine:versatilepb
:avocado: tags=tuxboot:armv5
:avocado: tags=image:zImage
:avocado: tags=drive:virtio-blk-pci
:avocado: tags=console:ttyAMA0
:avocado: tags=shutdown:nowait
"""
self.common_tuxrun(dt="versatile-pb.dtb")
self.common_tuxrun(drive="virtio-blk-pci",
dt="versatile-pb.dtb")

def test_armv7(self):
"""
Expand Down Expand Up @@ -244,10 +241,9 @@ def test_i386(self):
:avocado: tags=machine:q35
:avocado: tags=tuxboot:i386
:avocado: tags=image:bzImage
:avocado: tags=drive:virtio-blk-pci
:avocado: tags=shutdown:nowait
"""
self.common_tuxrun()
self.common_tuxrun(drive="virtio-blk-pci")

def test_mips32(self):
"""
Expand All @@ -257,11 +253,10 @@ def test_mips32(self):
:avocado: tags=endian:big
:avocado: tags=tuxboot:mips32
:avocado: tags=image:vmlinux
:avocado: tags=drive:driver=ide-hd,bus=ide.0,unit=0
:avocado: tags=root:sda
:avocado: tags=shutdown:nowait
"""
self.common_tuxrun()
self.common_tuxrun(drive="driver=ide-hd,bus=ide.0,unit=0")

def test_mips32el(self):
"""
Expand All @@ -270,11 +265,10 @@ def test_mips32el(self):
:avocado: tags=cpu:mips32r6-generic
:avocado: tags=tuxboot:mips32el
:avocado: tags=image:vmlinux
:avocado: tags=drive:driver=ide-hd,bus=ide.0,unit=0
:avocado: tags=root:sda
:avocado: tags=shutdown:nowait
"""
self.common_tuxrun()
self.common_tuxrun(drive="driver=ide-hd,bus=ide.0,unit=0")

@skip("QEMU currently broken") # regression against stable QEMU
def test_mips64(self):
Expand All @@ -284,23 +278,21 @@ def test_mips64(self):
:avocado: tags=tuxboot:mips64
:avocado: tags=endian:big
:avocado: tags=image:vmlinux
:avocado: tags=drive:driver=ide-hd,bus=ide.0,unit=0
:avocado: tags=root:sda
:avocado: tags=shutdown:nowait
"""
self.common_tuxrun()
self.common_tuxrun(drive="driver=ide-hd,bus=ide.0,unit=0")

def test_mips64el(self):
"""
:avocado: tags=arch:mips64el
:avocado: tags=machine:malta
:avocado: tags=tuxboot:mips64el
:avocado: tags=image:vmlinux
:avocado: tags=drive:driver=ide-hd,bus=ide.0,unit=0
:avocado: tags=root:sda
:avocado: tags=shutdown:nowait
"""
self.common_tuxrun()
self.common_tuxrun(drive="driver=ide-hd,bus=ide.0,unit=0")

def test_ppc32(self):
"""
Expand All @@ -309,10 +301,9 @@ def test_ppc32(self):
:avocado: tags=cpu:e500mc
:avocado: tags=tuxboot:ppc32
:avocado: tags=image:uImage
:avocado: tags=drive:virtio-blk-pci
:avocado: tags=shutdown:nowait
"""
self.common_tuxrun()
self.common_tuxrun(drive="virtio-blk-pci")

def test_ppc64(self):
"""
Expand All @@ -324,10 +315,9 @@ def test_ppc64(self):
:avocado: tags=tuxboot:ppc64
:avocado: tags=image:vmlinux
:avocado: tags=extradev:driver=spapr-vscsi
:avocado: tags=drive:scsi-hd
:avocado: tags=root:sda
"""
self.common_tuxrun()
self.common_tuxrun(drive="scsi-hd")

def test_ppc64le(self):
"""
Expand All @@ -338,10 +328,9 @@ def test_ppc64le(self):
:avocado: tags=tuxboot:ppc64le
:avocado: tags=image:vmlinux
:avocado: tags=extradev:driver=spapr-vscsi
:avocado: tags=drive:scsi-hd
:avocado: tags=root:sda
"""
self.common_tuxrun()
self.common_tuxrun(drive="scsi-hd")

def test_riscv32(self):
"""
Expand All @@ -365,10 +354,10 @@ def test_s390(self):
:avocado: tags=endian:big
:avocado: tags=tuxboot:s390
:avocado: tags=image:bzImage
:avocado: tags=drive:virtio-blk-ccw
:avocado: tags=shutdown:nowait
"""
self.common_tuxrun(haltmsg="Requesting system halt")
self.common_tuxrun(drive="virtio-blk-ccw",
haltmsg="Requesting system halt")

# Note: some segfaults caused by unaligned userspace access
@skipIf(os.getenv('GITLAB_CI'), 'Skipping unstable test on GitLab')
Expand All @@ -380,15 +369,16 @@ def test_sh4(self):
:avocado: tags=tuxboot:sh4
:avocado: tags=image:zImage
:avocado: tags=root:sda
:avocado: tags=drive:driver=ide-hd,bus=ide.0,unit=0
:avocado: tags=console:ttySC1
"""
# 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()

# the console comes on the second serial port
self.prepare_run(kernel, disk, console_index=1)
self.prepare_run(kernel, disk,
"driver=ide-hd,bus=ide.0,unit=0",
console_index=1)
self.vm.launch()

self.wait_for_console_pattern("Welcome to TuxTest")
Expand All @@ -404,10 +394,9 @@ def test_sparc64(self):
:avocado: tags=tuxboot:sparc64
:avocado: tags=image:vmlinux
:avocado: tags=root:sda
:avocado: tags=drive:driver=ide-hd,bus=ide.0,unit=0
:avocado: tags=shutdown:nowait
"""
self.common_tuxrun()
self.common_tuxrun(drive="driver=ide-hd,bus=ide.0,unit=0")

def test_x86_64(self):
"""
Expand All @@ -417,7 +406,6 @@ def test_x86_64(self):
:avocado: tags=tuxboot:x86_64
:avocado: tags=image:bzImage
:avocado: tags=root:sda
:avocado: tags=drive:driver=ide-hd,bus=ide.0,unit=0
:avocado: tags=shutdown:nowait
"""
self.common_tuxrun()
self.common_tuxrun(drive="driver=ide-hd,bus=ide.0,unit=0")
43 changes: 0 additions & 43 deletions tests/check-block.sh

This file was deleted.

2 changes: 1 addition & 1 deletion tests/docker/Makefile.include
Expand Up @@ -39,7 +39,7 @@ docker-qemu-src: $(DOCKER_SRC_COPY)
# General rule for building docker images.
docker-image-%: $(DOCKER_FILES_DIR)/%.docker
$(call quiet-command, \
$(RUNC) build \
DOCKER_BUILDKIT=1 $(RUNC) build \
$(if $V,,--quiet) \
$(if $(NOCACHE),--no-cache, \
$(if $(DOCKER_REGISTRY),--cache-from $(DOCKER_REGISTRY)/qemu/$*)) \
Expand Down
30 changes: 26 additions & 4 deletions tests/qemu-iotests/check
Expand Up @@ -26,9 +26,23 @@ from findtests import TestFinder
from testenv import TestEnv
from testrunner import TestRunner

def get_default_path(follow_link=False):
"""
Try to automagically figure out the path we are running from.
"""
# called from the build tree?
if os.path.islink(sys.argv[0]):
if follow_link:
return os.path.dirname(os.readlink(sys.argv[0]))
else:
return os.path.dirname(os.path.abspath(sys.argv[0]))
else: # or source tree?
return os.getcwd()

def make_argparser() -> argparse.ArgumentParser:
p = argparse.ArgumentParser(description="Test run options")
p = argparse.ArgumentParser(
description="Test run options",
formatter_class=argparse.ArgumentDefaultsHelpFormatter)

p.add_argument('-n', '--dry-run', action='store_true',
help='show me, do not run tests')
Expand Down Expand Up @@ -113,18 +127,26 @@ def make_argparser() -> argparse.ArgumentParser:
'middle of the process.')
g_sel.add_argument('tests', metavar='TEST_FILES', nargs='*',
help='tests to run, or "--" followed by a command')
g_sel.add_argument('--build-dir', default=get_default_path(),
help='Path to iotests build directory')
g_sel.add_argument('--source-dir',
default=get_default_path(follow_link=True),
help='Path to iotests build directory')

return p


if __name__ == '__main__':
args = make_argparser().parse_args()

env = TestEnv(imgfmt=args.imgfmt, imgproto=args.imgproto,
env = TestEnv(source_dir=args.source_dir,
build_dir=args.build_dir,
imgfmt=args.imgfmt, imgproto=args.imgproto,
aiomode=args.aiomode, cachemode=args.cachemode,
imgopts=args.imgopts, misalign=args.misalign,
debug=args.debug, valgrind=args.valgrind,
gdb=args.gdb, qprint=args.print)
gdb=args.gdb, qprint=args.print,
dry_run=args.dry_run)

if len(sys.argv) > 1 and sys.argv[-len(args.tests)-1] == '--':
if not args.tests:
Expand Down Expand Up @@ -162,7 +184,7 @@ if __name__ == '__main__':
sys.exit(str(e))

if args.dry_run:
print('\n'.join(tests))
print('\n'.join([os.path.basename(t) for t in tests]))
else:
with TestRunner(env, tap=args.tap,
color=args.color) as tr:
Expand Down
35 changes: 29 additions & 6 deletions tests/qemu-iotests/meson.build
Expand Up @@ -32,16 +32,39 @@ foreach k, v : emulators
endif
endforeach

qemu_iotests_check_cmd = files('check')

foreach format, speed: qemu_iotests_formats
if speed == 'quick'
suites = 'block'
else
suites = ['block-' + speed, speed]
endif
test('qemu-iotests ' + format, sh, args: [files('../check-block.sh'), format],
depends: qemu_iotests_binaries, env: qemu_iotests_env,
protocol: 'tap',
suite: suites,
timeout: 0,
is_parallel: false)

args = ['-tap', '-' + format]
if speed == 'quick'
args += ['-g', 'auto']
endif

rc = run_command(
[qemu_iotests_check_cmd] + args + ['-n'],
check: true,
)

foreach item: rc.stdout().strip().split()
args = ['-tap', '-' + format, item,
'--source-dir', meson.current_source_dir(),
'--build-dir', meson.current_build_dir()]
# Some individual tests take as long as 45 seconds
# Bump the timeout to 3 minutes for some headroom
# on slow machines to minimize spurious failures
test('io-' + format + '-' + item,
qemu_iotests_check_cmd,
args: args,
depends: qemu_iotests_binaries,
env: qemu_iotests_env,
protocol: 'tap',
timeout: 180,
suite: suites)
endforeach
endforeach
20 changes: 10 additions & 10 deletions tests/qemu-iotests/testenv.py
Expand Up @@ -170,14 +170,16 @@ def root(*names: str) -> str:
if not isxfile(b):
sys.exit('Not executable: ' + b)

def __init__(self, imgfmt: str, imgproto: str, aiomode: str,
def __init__(self, source_dir: str, build_dir: str,
imgfmt: str, imgproto: str, aiomode: str,
cachemode: Optional[str] = None,
imgopts: Optional[str] = None,
misalign: bool = False,
debug: bool = False,
valgrind: bool = False,
gdb: bool = False,
qprint: bool = False) -> None:
qprint: bool = False,
dry_run: bool = False) -> None:
self.imgfmt = imgfmt
self.imgproto = imgproto
self.aiomode = aiomode
Expand Down Expand Up @@ -211,18 +213,16 @@ def __init__(self, imgfmt: str, imgproto: str, aiomode: str,
# which are needed to initialize some environment variables. They are
# used by init_*() functions as well.

if os.path.islink(sys.argv[0]):
# called from the build tree
self.source_iotests = os.path.dirname(os.readlink(sys.argv[0]))
self.build_iotests = os.path.dirname(os.path.abspath(sys.argv[0]))
else:
# called from the source tree
self.source_iotests = os.getcwd()
self.build_iotests = self.source_iotests
self.source_iotests = source_dir
self.build_iotests = build_dir

self.build_root = os.path.join(self.build_iotests, '..', '..')

self.init_directories()

if dry_run:
return

self.init_binaries()

self.malloc_perturb_ = os.getenv('MALLOC_PERTURB_',
Expand Down
43 changes: 13 additions & 30 deletions tests/qemu-iotests/testrunner.py
Expand Up @@ -24,12 +24,10 @@
import subprocess
import contextlib
import json
import termios
import shutil
import sys
from multiprocessing import Pool
from contextlib import contextmanager
from typing import List, Optional, Iterator, Any, Sequence, Dict, \
from typing import List, Optional, Any, Sequence, Dict, \
ContextManager

from testenv import TestEnv
Expand All @@ -56,22 +54,6 @@ def file_diff(file1: str, file2: str) -> List[str]:
return res


# We want to save current tty settings during test run,
# since an aborting qemu call may leave things screwed up.
@contextmanager
def savetty() -> Iterator[None]:
isterm = sys.stdin.isatty()
if isterm:
fd = sys.stdin.fileno()
attr = termios.tcgetattr(fd)

try:
yield
finally:
if isterm:
termios.tcsetattr(fd, termios.TCSADRAIN, attr)


class LastElapsedTime(ContextManager['LastElapsedTime']):
""" Cache for elapsed time for tests, to show it during new test run
Expand Down Expand Up @@ -169,7 +151,6 @@ def __enter__(self) -> 'TestRunner':
self._stack = contextlib.ExitStack()
self._stack.enter_context(self.env)
self._stack.enter_context(self.last_elapsed)
self._stack.enter_context(savetty())
return self

def __exit__(self, exc_type: Any, exc_value: Any, traceback: Any) -> None:
Expand Down Expand Up @@ -247,13 +228,11 @@ def find_reference(self, test: str) -> str:

return f'{test}.out'

def do_run_test(self, test: str, mp: bool) -> TestResult:
def do_run_test(self, test: str) -> TestResult:
"""
Run one test
:param test: test file path
:param mp: if true, we are in a multiprocessing environment, use
personal subdirectories for test run
Note: this method may be called from subprocess, so it does not
change ``self`` object in any way!
Expand All @@ -276,12 +255,14 @@ def do_run_test(self, test: str, mp: bool) -> TestResult:

args = [str(f_test.resolve())]
env = self.env.prepare_subprocess(args)
if mp:
# Split test directories, so that tests running in parallel don't
# break each other.
for d in ['TEST_DIR', 'SOCK_DIR']:
env[d] = os.path.join(env[d], f_test.name)
Path(env[d]).mkdir(parents=True, exist_ok=True)

# Split test directories, so that tests running in parallel don't
# break each other.
for d in ['TEST_DIR', 'SOCK_DIR']:
env[d] = os.path.join(
env[d],
f"{self.env.imgfmt}-{self.env.imgproto}-{f_test.name}")
Path(env[d]).mkdir(parents=True, exist_ok=True)

test_dir = env['TEST_DIR']
f_bad = Path(test_dir, f_test.name + '.out.bad')
Expand All @@ -294,6 +275,7 @@ def do_run_test(self, test: str, mp: bool) -> TestResult:
t0 = time.time()
with f_bad.open('w', encoding="utf-8") as f:
with subprocess.Popen(args, cwd=str(f_test.parent), env=env,
stdin=subprocess.DEVNULL,
stdout=f, stderr=subprocess.STDOUT) as proc:
try:
proc.wait()
Expand Down Expand Up @@ -365,7 +347,7 @@ def run_test(self, test: str,
testname = os.path.basename(test)
print(f'# running {self.env.imgfmt} {testname}')

res = self.do_run_test(test, mp)
res = self.do_run_test(test)

end = datetime.datetime.now().strftime('%H:%M:%S')
self.test_print_one_line(test=test,
Expand All @@ -391,6 +373,7 @@ def run_tests(self, tests: List[str], jobs: int = 1) -> bool:
casenotrun = []

if self.tap:
print('TAP version 13')
self.env.print_env('# ')
print('1..%d' % len(tests))
else:
Expand Down
10 changes: 7 additions & 3 deletions tests/qtest/migration-test.c
Expand Up @@ -2462,14 +2462,18 @@ static bool kvm_dirty_ring_supported(void)

int main(int argc, char **argv)
{
const bool has_kvm = qtest_has_accel("kvm");
const bool has_uffd = ufd_version_check();
const char *arch = qtest_get_arch();
bool has_kvm;
bool has_uffd;
const char *arch;
g_autoptr(GError) err = NULL;
int ret;

g_test_init(&argc, &argv, NULL);

has_kvm = qtest_has_accel("kvm");
has_uffd = ufd_version_check();
arch = qtest_get_arch();

/*
* On ppc64, the test only works with kvm-hv, but not with kvm-pr and TCG
* is touchy due to race conditions on dirty bits (especially on PPC for
Expand Down
7 changes: 7 additions & 0 deletions tests/tcg/Makefile.target
Expand Up @@ -201,3 +201,10 @@ clean:

distclean:
rm -f config-cc.mak config-target.mak ../config-$(TARGET).mak

.PHONY: help
help:
@echo "TCG tests help $(TARGET_NAME)"
@echo "Built with $(CC)"
@echo "Available tests:"
@$(foreach t,$(RUN_TESTS),echo " $t";)
30 changes: 27 additions & 3 deletions tests/vm/openbsd
Expand Up @@ -106,8 +106,7 @@ class OpenBSDVM(basevm.BaseVM):
self.console_wait("Password for root account")
self.console_send("%s\n" % self._config["root_pass"])
self.console_wait_send("Start sshd(8)", "yes\n")
self.console_wait_send("X Window System", "\n")
self.console_wait_send("xenodm", "\n")
self.console_wait_send("X Window System", "no\n")
self.console_wait_send("console to com0", "\n")
self.console_wait_send("Which speed", "\n")

Expand All @@ -124,7 +123,32 @@ class OpenBSDVM(basevm.BaseVM):
self.console_wait_send("timezone", "UTC\n")
self.console_wait_send("root disk", "\n")
self.console_wait_send("(W)hole disk", "\n")
self.console_wait_send("(A)uto layout", "\n")
self.console_wait_send("(A)uto layout", "c\n")

# 4000 MB / as /dev/sd0a, at start of disk
self.console_wait_send("sd0>", "a a\n")
self.console_wait_send("offset:", "\n")
self.console_wait_send("size:", "4000M\n")
self.console_wait_send("FS type", "4.2BSD\n")
self.console_wait_send("mount point:", "/\n")

# 256 MB swap as /dev/sd0b
self.console_wait_send("sd0*>", "a b\n")
self.console_wait_send("offset:", "\n")
self.console_wait_send("size:", "256M\n")
self.console_wait_send("FS type", "swap\n")

# All remaining space for /home as /dev/sd0d
# NB, 'c' isn't allowed to be used.
self.console_wait_send("sd0*>", "a d\n")
self.console_wait_send("offset:", "\n")
self.console_wait_send("size:", "\n")
self.console_wait_send("FS type", "4.2BSD\n")
self.console_wait_send("mount point:", "/home\n")

self.console_wait_send("sd0*>", "q\n")
self.console_wait_send("Write new label?:", "y\n")

self.console_wait_send("Location of sets", "cd0\n")
self.console_wait_send("Pathname to the sets", "\n")
self.console_wait_send("Set name(s)", "\n")
Expand Down
1 change: 1 addition & 0 deletions ui/cocoa.m
Expand Up @@ -46,6 +46,7 @@
#include "qemu/cutils.h"
#include "qemu/main-loop.h"
#include "qemu/module.h"
#include "qemu/error-report.h"
#include <Carbon/Carbon.h>
#include "hw/core/cpu.h"

Expand Down