6 changes: 3 additions & 3 deletions .gitlab-ci.d/buildtest.yml
Expand Up @@ -102,8 +102,8 @@ crash-test-debian:
IMAGE: debian-amd64
script:
- cd build
- make check-venv
- tests/venv/bin/python3 scripts/device-crash-test -q ./qemu-system-i386
- make NINJA=":" check-venv
- tests/venv/bin/python3 scripts/device-crash-test -q --tcg-only ./qemu-system-i386

build-system-fedora:
extends:
Expand Down Expand Up @@ -145,7 +145,7 @@ crash-test-fedora:
IMAGE: fedora
script:
- cd build
- make check-venv
- make NINJA=":" check-venv
- tests/venv/bin/python3 scripts/device-crash-test -q ./qemu-system-ppc
- tests/venv/bin/python3 scripts/device-crash-test -q ./qemu-system-riscv32

Expand Down
13 changes: 0 additions & 13 deletions .gitlab-ci.d/cirrus.yml
Expand Up @@ -44,19 +44,6 @@
variables:
QEMU_JOB_CIRRUS: 1

x64-freebsd-12-build:
extends: .cirrus_build_job
variables:
NAME: freebsd-12
CIRRUS_VM_INSTANCE_TYPE: freebsd_instance
CIRRUS_VM_IMAGE_SELECTOR: image_family
CIRRUS_VM_IMAGE_NAME: freebsd-12-4
CIRRUS_VM_CPUS: 8
CIRRUS_VM_RAM: 8G
UPDATE_COMMAND: pkg update; pkg upgrade -y
INSTALL_COMMAND: pkg install -y
TEST_TARGETS: check

x64-freebsd-13-build:
extends: .cirrus_build_job
variables:
Expand Down
16 changes: 0 additions & 16 deletions .gitlab-ci.d/cirrus/freebsd-12.vars

This file was deleted.

3 changes: 2 additions & 1 deletion MAINTAINERS
Expand Up @@ -943,6 +943,7 @@ L: qemu-arm@nongnu.org
S: Maintained
F: hw/arm/sbsa-ref.c
F: docs/system/arm/sbsa.rst
F: tests/avocado/machine_aarch64_sbsaref.py

Sharp SL-5500 (Collie) PDA
M: Peter Maydell <peter.maydell@linaro.org>
Expand Down Expand Up @@ -1112,7 +1113,7 @@ F: include/hw/misc/pca9552*.h
F: hw/net/ftgmac100.c
F: include/hw/net/ftgmac100.h
F: docs/system/arm/aspeed.rst
F: tests/qtest/*aspeed*
F: tests/*/*aspeed*
F: hw/arm/fby35.c

NRF51
Expand Down
2 changes: 2 additions & 0 deletions docs/devel/qom.rst
@@ -1,3 +1,5 @@
.. _qom:

===========================
The QEMU Object Model (QOM)
===========================
Expand Down
105 changes: 105 additions & 0 deletions docs/devel/style.rst
Expand Up @@ -300,6 +300,20 @@ putting those into qemu/typedefs.h instead of including the header.

Cyclic inclusion is forbidden.

Generative Includes
-------------------

QEMU makes fairly extensive use of the macro pre-processor to
instantiate multiple similar functions. While such abuse of the macro
processor isn't discouraged it can make debugging and code navigation
harder. You should consider carefully if the same effect can be
achieved by making it easy for the compiler to constant fold or using
python scripting to generate grep friendly code.

If you do use template header files they should be named with the
``.c.inc`` or ``.h.inc`` suffix to make it clear they are being
included for expansion.

C types
=======

Expand Down Expand Up @@ -614,6 +628,97 @@ are still some caveats to beware of
QEMU Specific Idioms
********************

QEMU Object Model Declarations
==============================

The QEMU Object Model (QOM) provides a framework for handling objects
in the base C language. The first declaration of a storage or class
structure should always be the parent and leave a visual space between
that declaration and the new code. It is also useful to separate
backing for properties (options driven by the user) and internal state
to make navigation easier.

For a storage structure the first declaration should always be called
"parent_obj" and for a class structure the first member should always
be called "parent_class" as below:

.. code-block:: c
struct MyDeviceState {
DeviceState parent_obj;
/* Properties */
int prop_a;
char *prop_b;
/* Other stuff */
int internal_state;
};
struct MyDeviceClass {
DeviceClass parent_class;
void (*new_fn1)(void);
bool (*new_fn2)(CPUState *);
};
Note that there is no need to provide typedefs for QOM structures
since these are generated automatically by the QOM declaration macros.
See :ref:`qom` for more details.

QEMU GUARD macros
=================

QEMU provides a number of ``_GUARD`` macros intended to make the
handling of multiple exit paths easier. For example using
``QEMU_LOCK_GUARD`` to take a lock will ensure the lock is released on
exit from the function.

.. code-block:: c
static int my_critical_function(SomeState *s, void *data)
{
QEMU_LOCK_GUARD(&s->lock);
do_thing1(data);
if (check_state2(data)) {
return -1;
}
do_thing3(data);
return 0;
}
will ensure s->lock is released however the function is exited. The
equivalent code without _GUARD macro makes us to carefully put
qemu_mutex_unlock() on all exit points:

.. code-block:: c
static int my_critical_function(SomeState *s, void *data)
{
qemu_mutex_lock(&s->lock);
do_thing1(data);
if (check_state2(data)) {
qemu_mutex_unlock(&s->lock);
return -1;
}
do_thing3(data);
qemu_mutex_unlock(&s->lock);
return 0;
}
There are often ``WITH_`` forms of macros which more easily wrap
around a block inside a function.

.. code-block:: c
WITH_RCU_READ_LOCK_GUARD() {
QTAILQ_FOREACH_RCU(kid, &bus->children, sibling) {
err = do_the_thing(kid->child);
if (err < 0) {
return err;
}
}
}
Error handling and reporting
============================

Expand Down
6 changes: 3 additions & 3 deletions docs/system/guest-loader.rst
Expand Up @@ -14,7 +14,7 @@ The guest loader does two things:
- load blobs (kernels and initial ram disks) into memory
- sets platform FDT data so hypervisors can find and boot them
This is what is typically done by a boot-loader like grub using it's
This is what is typically done by a boot-loader like grub using its
multi-boot capability. A typical example would look like:
.. parsed-literal::
Expand All @@ -25,9 +25,9 @@ multi-boot capability. A typical example would look like:
-device guest-loader,addr=0x47000000,initrd=rootfs.cpio
In the above example the Xen hypervisor is loaded by the -kernel
parameter and passed it's boot arguments via -append. The Dom0 guest
parameter and passed its boot arguments via -append. The Dom0 guest
is loaded into the areas of memory. Each blob will get
``/chosen/module@<addr>`` entry in the FDT to indicate it's location and
``/chosen/module@<addr>`` entry in the FDT to indicate its location and
size. Additional information can be passed with by using additional
arguments.
Expand Down
49 changes: 38 additions & 11 deletions qemu-options.hx
Expand Up @@ -405,15 +405,22 @@ SRST
-numa node,nodeid=0 -numa node,nodeid=1 \
-numa cpu,node-id=0,socket-id=0 -numa cpu,node-id=1,socket-id=1
Legacy '\ ``mem``\ ' assigns a given RAM amount to a node (not supported
for 5.1 and newer machine types). '\ ``memdev``\ ' assigns RAM from
a given memory backend device to a node. If '\ ``mem``\ ' and
'\ ``memdev``\ ' are omitted in all nodes, RAM is split equally between them.
'\ ``mem``\ ' and '\ ``memdev``\ ' are mutually exclusive.
Furthermore, if one node uses '\ ``memdev``\ ', all of them have to
use it.
'\ ``memdev``\ ' option assigns RAM from a given memory backend
device to a node. It is recommended to use '\ ``memdev``\ ' option
over legacy '\ ``mem``\ ' option. This is because '\ ``memdev``\ '
option provides better performance and more control over the
backend's RAM (e.g. '\ ``prealloc``\ ' parameter of
'\ ``-memory-backend-ram``\ ' allows memory preallocation).
For compatibility reasons, legacy '\ ``mem``\ ' option is
supported in 5.0 and older machine types. Note that '\ ``mem``\ '
and '\ ``memdev``\ ' are mutually exclusive. If one node uses
'\ ``memdev``\ ', the rest nodes have to use '\ ``memdev``\ '
option, and vice versa.
Users must specify memory for all NUMA nodes by '\ ``memdev``\ '
(or legacy '\ ``mem``\ ' if available). In QEMU 5.2, the support
for '\ ``-numa node``\ ' without memory specified was removed.
'\ ``initiator``\ ' is an additional option that points to an
initiator NUMA node that has best performance (the lowest latency or
Expand Down Expand Up @@ -1143,10 +1150,22 @@ have gone through several iterations as the feature set and complexity
of the block layer have grown. Many online guides to QEMU often
reference older and deprecated options, which can lead to confusion.

The recommended modern way to describe disks is to use a combination of
The most explicit way to describe disks is to use a combination of
``-device`` to specify the hardware device and ``-blockdev`` to
describe the backend. The device defines what the guest sees and the
backend describes how QEMU handles the data.
backend describes how QEMU handles the data. It is the only guaranteed
stable interface for describing block devices and as such is
recommended for management tools and scripting.

The ``-drive`` option combines the device and backend into a single
command line option which is a more human friendly. There is however no
interface stability guarantee although some older board models still
need updating to work with the modern blockdev forms.

Older options like ``-hda`` are essentially macros which expand into
``-drive`` options for various drive interfaces. The original forms
bake in a lot of assumptions from the days when QEMU was emulating a
legacy PC, they are not recommended for modern configurations.

ERST

Expand Down Expand Up @@ -1639,6 +1658,14 @@ SRST
the raw disk image you use is not written back. You can however
force the write back by pressing C-a s (see the :ref:`disk images`
chapter in the System Emulation Users Guide).

.. warning::
snapshot is incompatible with ``-blockdev`` (instead use qemu-img
to manually create snapshot images to attach to your blockdev).
If you have mixed ``-blockdev`` and ``-drive`` declarations you
can use the 'snapshot' property on your drive declarations
instead of this global option.

ERST

DEF("fsdev", HAS_ARG, QEMU_OPTION_fsdev,
Expand Down
4 changes: 3 additions & 1 deletion scripts/device-crash-test
Expand Up @@ -397,7 +397,7 @@ def binariesToTest(args, testcase):


def accelsToTest(args, testcase):
if getBinaryInfo(args, testcase['binary']).kvm_available:
if getBinaryInfo(args, testcase['binary']).kvm_available and not args.tcg_only:
yield 'kvm'
yield 'tcg'

Expand Down Expand Up @@ -510,6 +510,8 @@ def main():
help="Full mode: test cases that are expected to fail")
parser.add_argument('--strict', action='store_true', dest='strict',
help="Treat all warnings as fatal")
parser.add_argument('--tcg-only', action='store_true', dest='tcg_only',
help="Only test with TCG accelerator")
parser.add_argument('qemu', nargs='*', metavar='QEMU',
help='QEMU binary to run')
args = parser.parse_args()
Expand Down
18 changes: 11 additions & 7 deletions tests/Makefile.include
Expand Up @@ -138,14 +138,18 @@ get-vm-image-fedora-31-%: check-venv
# download all vm images, according to defined targets
get-vm-images: check-venv $(patsubst %,get-vm-image-fedora-31-%, $(FEDORA_31_DOWNLOAD))

JOBS_OPTION=$(lastword -j1 $(filter-out -j, $(filter -j%,$(MAKEFLAGS))))

check-avocado: check-venv $(TESTS_RESULTS_DIR) get-vm-images
$(call quiet-command, \
$(TESTS_PYTHON) -m avocado \
--show=$(AVOCADO_SHOW) run --job-results-dir=$(TESTS_RESULTS_DIR) \
$(if $(AVOCADO_TAGS),, --filter-by-tags-include-empty \
--filter-by-tags-include-empty-key) \
$(AVOCADO_CMDLINE_TAGS) \
$(if $(GITLAB_CI),,--failfast) $(AVOCADO_TESTS), \
$(call quiet-command, \
$(TESTS_PYTHON) -m avocado \
--show=$(AVOCADO_SHOW) run --job-results-dir=$(TESTS_RESULTS_DIR) \
$(if $(AVOCADO_TAGS),, \
--filter-by-tags-include-empty \
--filter-by-tags-include-empty-key) \
--max-parallel-tasks $(JOBS_OPTION:-j%=%) \
$(AVOCADO_CMDLINE_TAGS) \
$(if $(GITLAB_CI),,--failfast) $(AVOCADO_TESTS), \
"AVOCADO", "tests/avocado")

check-acceptance-deprecated-warning:
Expand Down
35 changes: 24 additions & 11 deletions tests/avocado/avocado_qemu/__init__.py
Expand Up @@ -330,6 +330,19 @@ def _new_vm(self, name, *args):
vm.add_args(*args)
return vm

def get_qemu_img(self):
self.log.debug('Looking for and selecting a qemu-img binary')

# If qemu-img has been built, use it, otherwise the system wide one
# will be used.
qemu_img = os.path.join(BUILD_DIR, 'qemu-img')
if not os.path.exists(qemu_img):
qemu_img = find_command('qemu-img', False)
if qemu_img is False:
self.cancel('Could not find "qemu-img"')

return qemu_img

@property
def vm(self):
return self.get_vm(name='default')
Expand Down Expand Up @@ -431,6 +444,14 @@ def ssh_command(self, command):
f'Guest command failed: {command}')
return stdout_lines, stderr_lines

def ssh_command_output_contains(self, cmd, exp):
stdout, _ = self.ssh_command(cmd)
for line in stdout:
if exp in line:
break
else:
self.fail('"%s" output does not contain "%s"' % (cmd, exp))

class LinuxDistro:
"""Represents a Linux distribution
Expand Down Expand Up @@ -594,17 +615,9 @@ def set_up_existing_ssh_keys(self):
return (ssh_public_key, ssh_private_key)

def download_boot(self):
self.log.debug('Looking for and selecting a qemu-img binary to be '
'used to create the bootable snapshot image')
# If qemu-img has been built, use it, otherwise the system wide one
# will be used. If none is available, the test will cancel.
qemu_img = os.path.join(BUILD_DIR, 'qemu-img')
if not os.path.exists(qemu_img):
qemu_img = find_command('qemu-img', False)
if qemu_img is False:
self.cancel('Could not find "qemu-img", which is required to '
'create the bootable image')
vmimage.QEMU_IMG = qemu_img
# Set the qemu-img binary.
# If none is available, the test will cancel.
vmimage.QEMU_IMG = super().get_qemu_img()

self.log.info('Downloading/preparing boot image')
# Fedora 31 only provides ppc64le images
Expand Down