PKG_CONFIG_PATH: /opt/homebrew/curl/lib/pkgconfig:/opt/homebrew/ncurses/lib/pkgconfig:/opt/homebrew/readline/lib/pkgconfig
TEST_TARGETS: check-unit check-block check-qapi-schema check-softfloat check-qtest-x86_64
+aarch64-macos-14-base-build:
+ extends: .cirrus_build_job
+ variables:
+ NAME: macos-14
+ CIRRUS_VM_INSTANCE_TYPE: macos_instance
+ CIRRUS_VM_IMAGE_SELECTOR: image
+ CIRRUS_VM_IMAGE_NAME: ghcr.io/cirruslabs/macos-sonoma-base:latest
+ CIRRUS_VM_CPUS: 12
+ CIRRUS_VM_RAM: 24G
+ UPDATE_COMMAND: brew update
+ INSTALL_COMMAND: brew install
+ PATH_EXTRA: /opt/homebrew/ccache/libexec:/opt/homebrew/gettext/bin
+ PKG_CONFIG_PATH: /opt/homebrew/curl/lib/pkgconfig:/opt/homebrew/ncurses/lib/pkgconfig:/opt/homebrew/readline/lib/pkgconfig
+ TEST_TARGETS: check-unit check-block check-qapi-schema check-softfloat check-qtest-x86_64
+ QEMU_JOB_OPTIONAL: 1
+
# The following jobs run VM-based tests via KVM on a Linux-based Cirrus-CI job
.cirrus_kvm_job:
--- /dev/null
+# THIS FILE WAS AUTO-GENERATED
+#
+# $ lcitool variables macos-14 qemu
+#
+# https://gitlab.com/libvirt/libvirt-ci
+
+CCACHE='/opt/homebrew/bin/ccache'
+CPAN_PKGS=''
+CROSS_PKGS=''
+MAKE='/opt/homebrew/bin/gmake'
+NINJA='/opt/homebrew/bin/ninja'
+PACKAGING_COMMAND='brew'
+PIP3='/opt/homebrew/bin/pip3'
+PKGS='bash bc bison bzip2 capstone ccache cmocka ctags curl dbus diffutils dtc flex gcovr gettext git glib gnu-sed gnutls gtk+3 jemalloc jpeg-turbo json-c libepoxy libffi libgcrypt libiscsi libnfs libpng libslirp libssh libtasn1 libusb llvm lzo make meson mtools ncurses nettle ninja pixman pkg-config python3 rpm2cpio sdl2 sdl2_image snappy socat sparse spice-protocol swtpm tesseract usbredir vde vte3 xorriso zlib zstd'
+PYPI_PKGS='PyYAML numpy pillow sphinx sphinx-rtd-theme tomli'
+PYTHON='/opt/homebrew/bin/python3'
goto out;
}
s->dev = dev = e->dev;
+ QSIMPLEQ_REMOVE_HEAD(&default_audiodevs, next);
+ g_free(e);
drvname = AudiodevDriver_str(dev->driver);
driver = audio_driver_lookup(drvname);
if (!audio_driver_init(s, driver, dev, NULL)) {
break;
}
- QSIMPLEQ_REMOVE_HEAD(&default_audiodevs, next);
+ qapi_free_Audiodev(dev);
+ s->dev = NULL;
}
}
{
VuBlkExport *vexp = opaque;
+ vexp->vu_server.quiescing = true;
vhost_user_server_detach_aio_context(&vexp->vu_server);
}
{
VuBlkExport *vexp = opaque;
+ vexp->vu_server.quiescing = false;
vhost_user_server_attach_aio_context(&vexp->vu_server, vexp->export.ctx);
}
/*
- * Ensures that bdrv_drained_begin() waits until in-flight requests complete.
+ * Ensures that bdrv_drained_begin() waits until in-flight requests complete
+ * and the server->co_trip coroutine has terminated. It will be restarted in
+ * vhost_user_server_attach_aio_context().
*
* Called with vexp->export.ctx acquired.
*/
static bool vu_blk_drained_poll(void *opaque)
{
VuBlkExport *vexp = opaque;
+ VuServer *server = &vexp->vu_server;
- return vhost_user_server_has_in_flight(&vexp->vu_server);
+ return server->co_trip || vhost_user_server_has_in_flight(server);
}
static const BlockDevOps vu_blk_dev_ops = {
BDRVVmdkState *s = bs->opaque;
int ret = 0;
- desc = g_malloc0(DESC_SIZE);
- tmp_desc = g_malloc0(DESC_SIZE);
- ret = bdrv_co_pread(bs->file, s->desc_offset, DESC_SIZE, desc, 0);
+ size_t desc_buf_size;
+
+ if (s->desc_offset == 0) {
+ desc_buf_size = bdrv_getlength(bs->file->bs);
+ if (desc_buf_size > 16ULL << 20) {
+ error_report("VMDK description file too big");
+ return -EFBIG;
+ }
+ } else {
+ desc_buf_size = DESC_SIZE;
+ }
+
+ desc = g_malloc0(desc_buf_size);
+ tmp_desc = g_malloc0(desc_buf_size);
+ ret = bdrv_co_pread(bs->file, s->desc_offset, desc_buf_size, desc, 0);
if (ret < 0) {
goto out;
}
- desc[DESC_SIZE - 1] = '\0';
+ desc[desc_buf_size - 1] = '\0';
tmp_str = strstr(desc, "parentCID");
if (tmp_str == NULL) {
ret = -EINVAL;
goto out;
}
- pstrcpy(tmp_desc, DESC_SIZE, tmp_str);
+ pstrcpy(tmp_desc, desc_buf_size, tmp_str);
p_name = strstr(desc, "CID");
if (p_name != NULL) {
p_name += sizeof("CID");
- snprintf(p_name, DESC_SIZE - (p_name - desc), "%" PRIx32 "\n", cid);
- pstrcat(desc, DESC_SIZE, tmp_desc);
+ snprintf(p_name, desc_buf_size - (p_name - desc), "%" PRIx32 "\n", cid);
+ pstrcat(desc, desc_buf_size, tmp_desc);
}
- ret = bdrv_co_pwrite_sync(bs->file, s->desc_offset, DESC_SIZE, desc, 0);
+ ret = bdrv_co_pwrite_sync(bs->file, s->desc_offset, desc_buf_size, desc, 0);
out:
g_free(desc);
# This file is auto-generated by configure to support in-source tree
# 'make' command invocation
-ifeq ($(MAKECMDGOALS),)
-recurse: all
-endif
-
-.NOTPARALLEL: %
-%: force
+build:
@echo 'changing dir to build for $(MAKE) "$(MAKECMDGOALS)"...'
@$(MAKE) -C build -f Makefile $(MAKECMDGOALS)
@if test "$(MAKECMDGOALS)" = "distclean" && \
then \
rm -rf build GNUmakefile ; \
fi
-force: ;
-.PHONY: force
+%: build
+ @
+.PHONY: build
GNUmakefile: ;
EOF
# Conditionally ensure Sphinx is installed.
-mkvenv_flags=""
-if test "$download" = "enabled" -a "$docs" = "enabled" ; then
- mkvenv_flags="--online"
+mkvenv_online_flag=""
+if test "$download" = "enabled" ; then
+ mkvenv_online_flag=" --online"
fi
if test "$docs" != "disabled" ; then
if ! $mkvenv ensuregroup \
- $mkvenv_flags \
+ $(test "$docs" = "enabled" && echo "$mkvenv_online_flag") \
${source_path}/pythondeps.toml docs;
then
if test "$docs" = "enabled" ; then
fi
echo "SUBDIRS=$subdirs" >> $config_host_mak
echo "PYTHON=$python" >> $config_host_mak
+echo "MKVENV_ENSUREGROUP=$mkvenv ensuregroup $mkvenv_online_flag" >> $config_host_mak
echo "GENISOIMAGE=$genisoimage" >> $config_host_mak
echo "MESON=$meson" >> $config_host_mak
echo "NINJA=$ninja" >> $config_host_mak
unsigned (== 0). */
static char *
-format_dec (long number, char *outbuffer, int signedp)
+format_dec (long number, char *outbuffer, size_t outsize, int signedp)
{
last_immediate = number;
- sprintf (outbuffer, signedp ? "%ld" : "%lu", number);
+ snprintf (outbuffer, outsize, signedp ? "%ld" : "%lu", number);
return outbuffer + strlen (outbuffer);
}
return cp;
}
+#define FORMAT_DEC(number, tp, signedp) \
+ format_dec (number, tp, ({ \
+ assert(tp >= temp && tp <= temp + sizeof(temp)); \
+ temp + sizeof(temp) - tp; \
+ }), signedp)
+
/* Print out an insn with its operands, and update the info->insn_type
fields. The prefix_opcodep and the rest hold a prefix insn that is
supposed to be output as an address mode. */
if ((*cs == 'z' && (insn & 0x20))
|| (opcodep->match == BDAP_QUICK_OPCODE
&& (nbytes <= 2 || buffer[1 + nbytes] == 0)))
- tp = format_dec (number, tp, signedp);
+ tp = FORMAT_DEC (number, tp, signedp);
else
{
unsigned int highbyte = (number >> 24) & 0xff;
with_reg_prefix);
if (number >= 0)
*tp++ = '+';
- tp = format_dec (number, tp, 1);
+ tp = FORMAT_DEC (number, tp, 1);
info->flags |= CRIS_DIS_FLAG_MEM_TARGET_IS_REG;
info->target = (prefix_insn >> 12) & 15;
{
if (number >= 0)
*tp++ = '+';
- tp = format_dec (number, tp, 1);
+ tp = FORMAT_DEC (number, tp, 1);
}
}
else
break;
case 'I':
- tp = format_dec (insn & 63, tp, 0);
+ tp = FORMAT_DEC (insn & 63, tp, 0);
break;
case 'b':
break;
case 'c':
- tp = format_dec (insn & 31, tp, 0);
+ tp = FORMAT_DEC (insn & 31, tp, 0);
break;
case 'C':
- tp = format_dec (insn & 15, tp, 0);
+ tp = FORMAT_DEC (insn & 15, tp, 0);
break;
case 'o':
if (number > 127)
number = number - 256;
- tp = format_dec (number, tp, 1);
+ tp = FORMAT_DEC (number, tp, 1);
*tp++ = ',';
tp = format_reg (disdata, (insn >> 12) & 15, tp, with_reg_prefix);
}
break;
case 'i':
- tp = format_dec ((insn & 32) ? (insn & 31) | ~31L : insn & 31, tp, 1);
+ tp = FORMAT_DEC ((insn & 32) ? (insn & 31) | ~31L : insn & 31, tp, 1);
break;
case 'P':
indicated by $TMPC.
-Python virtual environments and the QEMU build system
------------------------------------------------------
+Python virtual environments and the build process
+-------------------------------------------------
+
+An important step in ``configure`` is to create a Python virtual
+environment (venv) during the configuration phase. The Python interpreter
+comes from the ``--python`` command line option, the ``$PYTHON`` variable
+from the environment, or the system PATH, in this order. The venv resides
+in the ``pyvenv`` directory in the build tree, and provides consistency
+in how the build process runs Python code.
+
+At this stage, ``configure`` also queries the chosen Python interpreter
+about QEMU's build dependencies. Note that the build process does *not*
+look for ``meson``, ``sphinx-build`` or ``avocado`` binaries in the PATH;
+likewise, there are no options such as ``--meson`` or ``--sphinx-build``.
+This avoids a potential mismatch, where Meson and Sphinx binaries on the
+PATH might operate in a different Python environment than the one chosen
+by the user during the build process. On the other hand, it introduces
+a potential source of confusion where the user installs a dependency but
+``configure`` is not able to find it. When this happens, the dependency
+was installed in the ``site-packages`` directory of another interpreter,
+or with the wrong ``pip`` program.
+
+If a package is available for the chosen interpreter, ``configure``
+prepares a small script that invokes it from the venv itself[#distlib]_.
+If not, ``configure`` can also optionally install dependencies in the
+virtual environment with ``pip``, either from wheels in ``python/wheels``
+or by downloading the package with PyPI. Downloading can be disabled with
+``--disable-download``; and anyway, it only happens when a ``configure``
+option (currently, only ``--enable-docs``) is explicitly enabled but
+the dependencies are not present[#pip]_.
+
+.. [#distlib] The scripts are created based on the package's metadata,
+ specifically the ``console_script`` entry points. This is the
+ same mechanism that ``pip`` uses when installing a package.
+ Currently, in all cases it would be possible to use ``python -m``
+ instead of an entry point script, which makes this approach a
+ bit overkill. On the other hand, creating the scripts is
+ future proof and it makes the contents of the ``pyvenv/bin``
+ directory more informative. Portability is also not an issue,
+ because the Python Packaging Authority provides a package
+ ``distlib.scripts`` to perform this task.
+
+.. [#pip] ``pip`` might also be used when running ``make check-avocado``
+ if downloading is enabled, to ensure that Avocado is
+ available.
+
+The required versions of the packages are stored in a configuration file
+``pythondeps.toml``. The format is custom to QEMU, but it is documented
+at the top of the file itself and it should be easy to understand. The
+requirements should make it possible to use the version that is packaged
+that is provided by supported distros.
+
+When dependencies are downloaded, instead, ``configure`` uses a "known
+good" version that is also listed in ``pythondeps.toml``. In this
+scenario, ``pythondeps.toml`` behaves like the "lock file" used by
+``cargo``, ``poetry`` or other dependency management systems.
+
+
+Bundled Python packages
+-----------------------
+
+Python packages that are **mandatory** dependencies to build QEMU,
+but are not available in all supported distros, are bundled with the
+QEMU sources. Currently this includes Meson (outdated in CentOS 8
+and derivatives, Ubuntu 20.04 and 22.04, and openSUSE Leap) and tomli
+(absent in Ubuntu 20.04).
+
+If you need to update these, please do so by modifying and rerunning
+``python/scripts/vendor.py``. This script embeds the sha256 hash of
+package sources and checks it. The pypi.org web site provides an easy
+way to retrieve the sha256 hash of the sources.
-TBD
Stage 2: Meson
==============
script, which may point to something other than the first python3
binary on the path.
+By the time Meson runs, Python dependencies are available in the virtual
+environment and should be invoked through the scripts that ``configure``
+places under ``pyvenv``. One way to do so is as follows, using Meson's
+``find_program`` function::
+
+ sphinx_build = find_program(
+ fs.parent(python.full_path()) / 'sphinx-build',
+ required: get_option('docs'))
+
Stage 3: Make
=============
executables. Build rules for various subdirectories are included in
other meson.build files spread throughout the QEMU source tree.
+``python/scripts/mkvenv.py``
+ A wrapper for the Python ``venv`` and ``distlib.scripts`` packages.
+ It handles creating the virtual environment, creating scripts in
+ ``pyvenv/bin``, and calling ``pip`` to install dependencies.
+
``tests/Makefile.include``
Rules for external test harnesses. These include the TCG tests
and the Avocado-based integration tests.
Property *prop = opaque;
uint32_t *alenptr = object_field_prop_ptr(obj, prop);
void **arrayptr = (void *)obj + prop->arrayoffset;
- char *elem = *arrayptr;
- GenericList *list;
- const size_t list_elem_size = sizeof(*list) + prop->arrayfieldsize;
+ char *elemptr = *arrayptr;
+ ArrayElementList *list = NULL, *elem;
+ ArrayElementList **tail = &list;
+ const size_t size = sizeof(*list);
int i;
bool ok;
- if (!visit_start_list(v, name, &list, list_elem_size, errp)) {
+ /* At least the string output visitor needs a real list */
+ for (i = 0; i < *alenptr; i++) {
+ elem = g_new0(ArrayElementList, 1);
+ elem->value = elemptr;
+ elemptr += prop->arrayfieldsize;
+
+ *tail = elem;
+ tail = &elem->next;
+ }
+
+ if (!visit_start_list(v, name, (GenericList **) &list, size, errp)) {
return;
}
- for (i = 0; i < *alenptr; i++) {
- Property elem_prop = array_elem_prop(obj, prop, name, elem);
+ elem = list;
+ while (elem) {
+ Property elem_prop = array_elem_prop(obj, prop, name, elem->value);
prop->arrayinfo->get(obj, v, NULL, &elem_prop, errp);
if (*errp) {
goto out_obj;
}
- elem += prop->arrayfieldsize;
+ elem = (ArrayElementList *) visit_next_list(v, (GenericList*) elem,
+ size);
}
/* visit_check_list() can only fail for input visitors */
out_obj:
visit_end_list(v, (void**) &list);
+
+ while (list) {
+ elem = list;
+ list = elem->next;
+ g_free(elem);
+ }
}
static void default_prop_array(ObjectProperty *op, const Property *prop)
uint32_t val = pci_default_read_config(pd, addr, len);
uint8_t mode = pd->config[PCI_CLASS_PROG];
- if ((mode & 0xf) == 0xa && ranges_overlap(addr, len,
- PCI_BASE_ADDRESS_0, 16)) {
- /* BARs always read back zero in legacy mode */
- for (int i = addr; i < addr + len; i++) {
- if (i >= PCI_BASE_ADDRESS_0 && i < PCI_BASE_ADDRESS_0 + 16) {
- val &= ~(0xffULL << ((i - addr) << 3));
+ if ((mode & 0xf) == 0xa) {
+ if (ranges_overlap(addr, len, PCI_BASE_ADDRESS_0, 16)) {
+ /* BARs 0-3 always read back zero in legacy mode */
+ for (int i = addr; i < addr + len; i++) {
+ if (i >= PCI_BASE_ADDRESS_0 && i < PCI_BASE_ADDRESS_0 + 16) {
+ val &= ~(0xffULL << ((i - addr) << 3));
+ }
}
}
+ if (addr == PCI_BASE_ADDRESS_4 && val == PCI_BASE_ADDRESS_SPACE_IO) {
+ /* BAR4 default value if unset */
+ val = 0xcc00 | PCI_BASE_ADDRESS_SPACE_IO;
+ }
}
return val;
/* Protected by ctx lock */
bool in_qio_channel_yield;
bool wait_idle;
+ bool quiescing;
VuDev vu_dev;
QIOChannel *ioc; /* The I/O channel with the client */
QIOChannelSocket *sioc; /* The underlying data channel with the client */
parser.parse_args()
packages = {
- "meson==0.63.3":
- "d677b809c4895dcbaac9bf6c43703fcb3609a4b24c6057c78f828590049cf43a",
+ "meson==1.2.3":
+ "4533a43c34548edd1f63a276a42690fce15bde9409bcf20c4b8fa3d7e4d7cac1",
"tomli==2.0.1":
"939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc",
# - accepted: accepted versions when using a system package
# - installed: fixed version to install in the virtual environment
# if a system package is not found; if not specified,
-# the minimum and maximum
+# defaults to the same as "accepted" or, if also missing,
+# to the newest version available on PyPI.
# - canary: if specified, use this program name to present more
# precise error diagnostics to the user. For example,
# 'sphinx-build' can be used as a bellwether for the
[meson]
# The install key should match the version in python/wheels/
-meson = { accepted = ">=0.63.0", installed = "0.63.3", canary = "meson" }
+meson = { accepted = ">=0.63.0", installed = "1.2.3", canary = "meson" }
[docs]
sphinx = { accepted = ">=1.6", installed = "5.3.0", canary = "sphinx-build" }
static void string_output_set(StringOutputVisitor *sov, char *string)
{
- if (sov->string) {
- g_string_free(sov->string, true);
+ switch (sov->list_mode) {
+ case LM_STARTED:
+ sov->list_mode = LM_IN_PROGRESS;
+ /* fall through */
+ case LM_NONE:
+ if (sov->string) {
+ g_string_free(sov->string, true);
+ }
+ sov->string = g_string_new(string);
+ g_free(string);
+ break;
+
+ case LM_IN_PROGRESS:
+ case LM_END:
+ g_string_append(sov->string, ", ");
+ g_string_append(sov->string, string);
+ break;
+
+ default:
+ abort();
}
- sov->string = g_string_new(string);
- g_free(string);
}
static void string_output_append(StringOutputVisitor *sov, int64_t a)
libpcre = 'libpcre2'
endif
qga_msi_version = get_option('qemu_ga_version') == '' \
- ? project.version() \
+ ? meson.project_version() \
: get_option('qemu_ga_version')
qga_msi = custom_target('QGA MSI',
input: files('installer/qemu-ga.wxs'),
-Subproject commit 1e1da7a963007d03a4e0e9a9e0ff17990bb1608d
+Subproject commit a6ed6b701f0a57db0569ab98b0661c12a6ec3ff8
typedef struct va_list_str *va_list;
-/* exec.c */
-
-typedef struct AddressSpace AddressSpace;
-typedef struct MemoryRegionCache MemoryRegionCache;
-typedef uint64_t hwaddr;
-typedef uint32_t MemTxResult;
-typedef struct MemTxAttrs {} MemTxAttrs;
-
-static void __bufwrite(uint8_t *buf, ssize_t len)
-{
- int first, last;
- __coverity_negative_sink__(len);
- if (len == 0) return;
- buf[0] = first;
- buf[len-1] = last;
- __coverity_writeall__(buf);
-}
-
-static void __bufread(uint8_t *buf, ssize_t len)
-{
- __coverity_negative_sink__(len);
- if (len == 0) return;
- int first = buf[0];
- int last = buf[len-1];
-}
-
-MemTxResult address_space_read_cached(MemoryRegionCache *cache, hwaddr addr,
- MemTxAttrs attrs,
- void *buf, int len)
-{
- MemTxResult result;
- // TODO: investigate impact of treating reads as producing
- // tainted data, with __coverity_tainted_data_argument__(buf).
- __bufwrite(buf, len);
- return result;
-}
-
-MemTxResult address_space_write_cached(MemoryRegionCache *cache, hwaddr addr,
- MemTxAttrs attrs,
- const void *buf, int len)
-{
- MemTxResult result;
- __bufread(buf, len);
- return result;
-}
-
-MemTxResult address_space_rw_cached(MemoryRegionCache *cache, hwaddr addr,
- MemTxAttrs attrs,
- void *buf, int len, bool is_write)
-{
- if (is_write) {
- return address_space_write_cached(cache, addr, attrs, buf, len);
- } else {
- return address_space_read_cached(cache, addr, attrs, buf, len);
- }
-}
-
-MemTxResult address_space_read(AddressSpace *as, hwaddr addr,
- MemTxAttrs attrs,
- void *buf, int len)
-{
- MemTxResult result;
- // TODO: investigate impact of treating reads as producing
- // tainted data, with __coverity_tainted_data_argument__(buf).
- __bufwrite(buf, len);
- return result;
-}
-
-MemTxResult address_space_write(AddressSpace *as, hwaddr addr,
- MemTxAttrs attrs,
- const void *buf, int len)
-{
- MemTxResult result;
- __bufread(buf, len);
- return result;
-}
-
-MemTxResult address_space_rw(AddressSpace *as, hwaddr addr,
- MemTxAttrs attrs,
- void *buf, int len, bool is_write)
-{
- if (is_write) {
- return address_space_write(as, addr, attrs, buf, len);
- } else {
- return address_space_read(as, addr, attrs, buf, len);
- }
-}
-
/* Tainting */
typedef struct {} name2keysym_t;
cd "$COVERITY_TOOL_BASE"
echo "Checking for new version of coverity build tools..."
- wget https://scan.coverity.com/download/linux64 --post-data "token=$COVERITY_TOKEN&project=$PROJNAME&md5=1" -O coverity_tool.md5.new
+ wget https://scan.coverity.com/download/cxx/linux64 --post-data "token=$COVERITY_TOKEN&project=$PROJNAME&md5=1" -O coverity_tool.md5.new
if ! cmp -s coverity_tool.md5 coverity_tool.md5.new; then
# out of date md5 or no md5: download new build tool
# blow away the old build tool
echo "Downloading coverity build tools..."
rm -rf coverity_tool coverity_tool.tgz
- wget https://scan.coverity.com/download/linux64 --post-data "token=$COVERITY_TOKEN&project=$PROJNAME" -O coverity_tool.tgz
+ wget https://scan.coverity.com/download/cxx/linux64 --post-data "token=$COVERITY_TOKEN&project=$PROJNAME" -O coverity_tool.tgz
if ! (cat coverity_tool.md5.new; echo " coverity_tool.tgz") | md5sum -c --status; then
echo "Downloaded tarball didn't match md5sum!"
exit 1
/* qemu_ram_alloc_from_ptr cannot fail with ptr != NULL. */
assert(ptr != NULL);
- mr->ram_block = qemu_ram_alloc_from_ptr(size, ptr, mr, &error_fatal);
+ mr->ram_block = qemu_ram_alloc_from_ptr(size, ptr, mr, &error_abort);
}
void memory_region_init_ram_device_ptr(MemoryRegion *mr,
/* qemu_ram_alloc_from_ptr cannot fail with ptr != NULL. */
assert(ptr != NULL);
- mr->ram_block = qemu_ram_alloc_from_ptr(size, ptr, mr, &error_fatal);
+ mr->ram_block = qemu_ram_alloc_from_ptr(size, ptr, mr, &error_abort);
}
void memory_region_init_alias(MemoryRegion *mr,
l = memory_access_size(mr, l, addr1);
/* XXX: could force current_cpu to NULL to avoid
potential bugs */
+
+ /*
+ * Assure Coverity (and ourselves) that we are not going to OVERRUN
+ * the buffer by following ldn_he_p().
+ */
+#ifdef QEMU_STATIC_ANALYSIS
+ assert((l == 1 && len >= 1) ||
+ (l == 2 && len >= 2) ||
+ (l == 4 && len >= 4) ||
+ (l == 8 && len >= 8));
+#endif
val = ldn_he_p(buf, l);
result |= memory_region_dispatch_write(mr, addr1, val,
size_memop(l), attrs);
l = memory_access_size(mr, l, addr1);
result |= memory_region_dispatch_read(mr, addr1, &val,
size_memop(l), attrs);
+
+ /*
+ * Assure Coverity (and ourselves) that we are not going to OVERRUN
+ * the buffer by following stn_he_p().
+ */
+#ifdef QEMU_STATIC_ANALYSIS
+ assert((l == 1 && len >= 1) ||
+ (l == 2 && len >= 2) ||
+ (l == 4 && len >= 4) ||
+ (l == 8 && len >= 8));
+#endif
stn_he_p(buf, l, val);
} else {
/* RAM case */
$(TESTS_VENV_TOKEN): $(SRC_PATH)/pythondeps.toml
$(call quiet-venv-pip,install -e "$(SRC_PATH)/python/")
- $(PYTHON) python/scripts/mkvenv.py ensuregroup --online $< avocado
+ $(MKVENV_ENSUREGROUP) $< avocado
$(call quiet-command, touch $@)
$(TESTS_RESULTS_DIR):
-Subproject commit 36bc517161c45ead20224d47f2dc4fa428af6724
+Subproject commit 77c800186f34b21be7660750577cc5582a914deb
#
generate_cirrus("freebsd-13")
generate_cirrus("macos-13")
+ generate_cirrus("macos-14")
#
# VM packages lists
echo "=== Testing big twoGbMaxExtentFlat ==="
_make_test_img -o "subformat=twoGbMaxExtentFlat" 1000G
_img_info --format-specific | _filter_img_info --format-specific
+$QEMU_IO -c "write 990G 512 -P 89" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "read 990G 512 -P 89" "$TEST_IMG" | _filter_qemu_io
_cleanup_test_img
echo
virtual size: 2147483648
filename: TEST_DIR/t-f500.IMGFMT
format: FLAT
+wrote 512/512 bytes at offset 1063004405760
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 1063004405760
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
=== Testing malformed VMFS extent description line ===
qemu-img: Could not open 'TEST_DIR/t.IMGFMT': Invalid extent line: RW 12582912 VMFS "dummy.IMGFMT" 1
machines = outp.split('\n')
try:
- default_machine = next(m for m in machines if m.endswith(' (default)'))
+ default_machine = next(m for m in machines if ' (default)' in m)
except StopIteration:
return ''
default_machine = default_machine.split(' ', 1)[0]
qio_channel_yield(ioc, G_IO_IN);
server->in_qio_channel_yield = false;
} else {
- /* Wait until attached to an AioContext again */
- qemu_coroutine_yield();
+ return false;
}
continue;
} else {
VuServer *server = opaque;
VuDev *vu_dev = &server->vu_dev;
- while (!vu_dev->broken && vu_dispatch(vu_dev)) {
- /* Keep running */
+ while (!vu_dev->broken) {
+ if (server->quiescing) {
+ server->co_trip = NULL;
+ aio_wait_kick();
+ return;
+ }
+ /* vu_dispatch() returns false if server->ctx went away */
+ if (!vu_dispatch(vu_dev) && server->ctx) {
+ break;
+ }
}
if (vhost_user_server_has_in_flight(server)) {
qio_channel_set_follow_coroutine_ctx(server->ioc, true);
- server->co_trip = qemu_coroutine_create(vu_client_trip, server);
-
+ /* Attaching the AioContext starts the vu_client_trip coroutine */
aio_context_acquire(server->ctx);
vhost_user_server_attach_aio_context(server, server->ctx);
aio_context_release(server->ctx);
NULL, NULL, vu_fd_watch);
}
- assert(!server->in_qio_channel_yield);
- aio_co_schedule(ctx, server->co_trip);
+ if (server->co_trip) {
+ /*
+ * The caller didn't fully shut down co_trip (this can happen on
+ * non-polling drains like in bdrv_graph_wrlock()). This is okay as long
+ * as it no longer tries to shut it down and we're guaranteed to still
+ * be in the same AioContext as before.
+ *
+ * co_ctx can still be NULL if we get multiple calls and only just
+ * scheduled a new coroutine in the else branch.
+ */
+ AioContext *co_ctx = qemu_coroutine_get_aio_context(server->co_trip);
+
+ assert(!server->quiescing);
+ assert(!co_ctx || co_ctx == ctx);
+ } else {
+ server->co_trip = qemu_coroutine_create(vu_client_trip, server);
+ assert(!server->in_qio_channel_yield);
+ aio_co_schedule(ctx, server->co_trip);
+ }
}
/* Called with server->ctx acquired */