Merge tag 'misc-next-pull-request' of https://gitlab.com/berrange/qemu into staging * Update FreeBSD image to 14.4 * Fix inotify test for FreeBSD 15 * Fix crypt/nettle build option argument handling * Add tracking & reporting of GitLab account handles for maintainers # -----BEGIN PGP SIGNATURE----- # # iQIzBAABCAAdFiEEOSEivHoFu8YQee2OpU5XPKwd8GwFAmpflkgACgkQpU5XPKwd # 8GxlYhAAk0BsuWP3BW5MXcpNJ4qP3jVq4jIdNGKYove+9WgAUbItk50RSZ8duDgG # dccreY7VC9VDvdTc2FrIFZmmZSMsPKqWaUDx6BIqWXZAAd0qy+Ez2CtFBu4V1q++ # 6uu4YkBI3z1zwNszSxP9E80b2gufDTgfZhxAlCQT/Oj1OTPY/3YsxNOVBs6sETTY # FTMzBM7K5zjoPO0oC0Qj18Vd81/ifs2SKzRWFDqo/kZic3wJLI0fAWd2WMyzihwk # svIbbLBEvUhVlJyDcKyzOfTBzcUZYjbbXsOBmSkoqRCRvJUtAvRzW5Gb9amv25nq # A80rgTgA/ebUUwJQ/2cXJuuX/E3pUZL4+LfMBAFCANhM8DklWhVAy5bNz3smnWIq # WF4Pd75bcW/J0vzPbIH7rxkwAJKIO3UonZcvJM3IcjDX/VP9HkY491sn9aXyeJES # UaC/NA9FK/w1VMFefjXbInD7/Idza8uQWDtL/EQzkG28mc4SqZwrbKcQYL3kazlW # SRz+UxMvNh79D1MI2+0yCuFPDwkY8LVpIqlS0tutSCk6xc9MAukTLnCum+4m//5k # ZiP0HmIVUqaLnlzSVERrzD9mZEl92sLWwEvwrLxa7np/3A6ZJxSE+zarpJFbgEsB # 9JgNQZWa+4kWeoeJE93vgsvximsIyx3UMWuNQdi4Xy1lkSi8qcI= # =Jp4q # -----END PGP SIGNATURE----- # gpg: Signature made Tue 21 Jul 2026 11:54:48 EDT # gpg: using RSA key 392122BC7A05BBC61079ED8EA54E573CAC1DF06C # gpg: Good signature from "Daniel P. Berrange <dan@berrange.com>" [full] # gpg: aka "Daniel P. Berrange <berrange@redhat.com>" [full] # Primary key fingerprint: DAF3 A6FD B26B 6291 2D0E 8E3F BE86 EBB4 1510 4FDF # Subkey fingerprint: 3921 22BC 7A05 BBC6 1079 ED8E A54E 573C AC1D F06C * tag 'misc-next-pull-request' of https://gitlab.com/berrange/qemu: get_maintainer: add ability to report Git Lab handle gitlab: introduce files mapping GitLab accounts to real names meson.build: re-add explicit gcrypt/nettle request check tests/vm: update to FreeBSD 14.4 image test-util-filemonitor: Adapt to FreeBSD 15's native inotify semantics Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
diff --git a/.gitlab-ci.d/macos.yml b/.gitlab-ci.d/macos.yml index 53b6e6c..641a48b 100644 --- a/.gitlab-ci.d/macos.yml +++ b/.gitlab-ci.d/macos.yml
@@ -22,7 +22,7 @@ - export PKG_CONFIG_PATH="$PKG_CONFIG_PATH" - brew update - brew install $PKGS - - brew install gdb aarch64-elf-gcc i686-elf-gcc x86_64-elf-gcc + - brew install aarch64-elf-gcc i686-elf-gcc x86_64-elf-gcc - if test -n "$PYPI_PKGS" ; then PYLIB=$($PYTHON -c 'import sysconfig; print(sysconfig.get_path("stdlib"))'); rm -f $PYLIB/EXTERNALLY-MANAGED; $PIP3 install --break-system-packages $PYPI_PKGS ; fi script: - mkdir build
diff --git a/MAINTAINERS b/MAINTAINERS index 74fc43f..a28935c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS
@@ -2205,7 +2205,9 @@ L: qemu-arm@nongnu.org S: Odd Fixes F: hw/*/omap* +F: hw/dma/soc_dma.c F: include/hw/arm/omap.h +F: include/hw/dma/soc_dma.h F: docs/system/arm/sx1.rst F: tests/functional/arm/test_sx1.py
diff --git a/VERSION b/VERSION index a4efc32..f9e8608 100644 --- a/VERSION +++ b/VERSION
@@ -1 +1 @@ -11.0.90 +11.0.91
diff --git a/contrib/plugins/dlcall.c b/contrib/plugins/dlcall.c index 9d2230b..b624735 100644 --- a/contrib/plugins/dlcall.c +++ b/contrib/plugins/dlcall.c
@@ -10,7 +10,8 @@ * nothing about how a library is thunked. Any toolchain can implement the * userspace side. Lorelei is one end-to-end implementation (guest/host * runtimes plus a thunk compiler that generates thunks from a library's - * headers): + * headers), and how it handles argument marshalling, callbacks and variadic + * functions can serve as a reference: * https://github.com/rover2024/lorelei * * See docs/about/emulation.rst|Dynamic Linking Call for details and examples. @@ -20,12 +21,13 @@ * execution in the QEMU host process. It is NOT a sandbox and provides no * isolation; only load it for guests you fully trust. * - * WARNING: requires guest_base == 0, which is qemu-user's default. Pointer - * operands are dereferenced as host addresses directly, and the invoked host - * functions dereference guest pointers with no address translation, so guest - * and host must share a single address space. A non-zero guest_base (e.g. set - * via -B/-R) would make every pointer off by guest_base and hit unrelated - * host memory. + * WARNING: requires guest_base == 0, which is qemu-user's default, and a + * guest whose pointer width and endianness match the host's. Pointer operands + * are dereferenced as host addresses directly, and the invoked host functions + * dereference guest pointers with no address translation, so guest and host + * must share a single address space and agree on how a pointer is stored. A + * non-zero guest_base (e.g. set via -B/-R) would make every pointer off by + * guest_base and hit unrelated host memory. * * SPDX-License-Identifier: GPL-2.0-or-later */ @@ -46,8 +48,18 @@ * * It defaults to DLCALL_SYSCALL_DEFAULT and can be overridden at load time * with the "syscall_num=N" argument. To avoid hijacking a real syscall the - * guest might issue, N must be at least DLCALL_SYSCALL_MIN: every Linux ABI - * keeps its syscall numbers well below this; numbers from here up are free. + * guest might issue, N must be at least DLCALL_SYSCALL_MIN, which most Linux + * ABIs keep their syscall numbers well below. + * + * N also has to reach the filter at all, which bounds it from above in a + * target specific way: arm32 answers anything past ARM_NR_BASE (0xf0000) with + * ENOSYS or SIGILL before do_syscall() runs, while aarch64 has no such bound. + * + * MIPS O32 bases its numbering at 4000, so the default is a real syscall there + * (getpriority). Raising N does not help either, because O32 rejects numbers + * its table does not define, again before the filter runs, which leaves no + * number that is both free and reachable on that ABI. Its N32 and N64 ABIs + * base at 6000 and 5000 and have no such gate, so they are unaffected. */ enum { DLCALL_SYSCALL_DEFAULT = 4096, @@ -168,6 +180,7 @@ case DLCALL_ID_FREE_LIBRARY: { void *handle = (void *) a2; int *ret_ptr = (int *) a3; + assert(ret_ptr); *ret_ptr = dlclose(handle); *sysret = 0; break; @@ -176,6 +189,7 @@ /* Get the last error message for a library event. */ case DLCALL_ID_GET_LIBRARY_ERROR: { const char **error_ptr = (const char **) a2; + assert(error_ptr); *error_ptr = dlerror(); *sysret = 0; break;
diff --git a/docs/about/emulation.rst b/docs/about/emulation.rst index b861501..c581490 100644 --- a/docs/about/emulation.rst +++ b/docs/about/emulation.rst
@@ -1072,14 +1072,13 @@ Trusted guests only. The guest can load arbitrary host libraries and run arbitrary code in the QEMU host process. The plugin is not a sandbox and provides no isolation. It also requires ``guest_base == 0`` (qemu-user's - default), as guest pointers are dereferenced as host addresses with no - translation. + default) and a guest whose pointer width and endianness match the host's, as + guest pointers are dereferenced as host addresses with no translation. The plugin intentionally keeps the QEMU side lightweight and knows nothing -about any particular library or its calling convention. Turning a real library -into working thunks, including argument marshalling, callbacks and variadic -functions, is done entirely in userspace, and any toolchain can implement the -interface. +about any particular library or its calling convention. Producing the thunks +for a real library is done entirely in userspace, and any toolchain can +implement the interface. Loading the plugin is all that is required from QEMU's side: @@ -1087,11 +1086,21 @@ qemu-x86_64 -plugin contrib/plugins/libdlcall.so <guest-program> ... +If the default number does not suit the guest ABI, pick another one, and build +the userspace side to issue the same one: + +.. code-block:: shell + + qemu-x86_64 -plugin contrib/plugins/libdlcall.so,syscall_num=8192 \ + <guest-program> ... + `Lorelei <https://github.com/rover2024/lorelei>`_ is one end-to-end userspace implementation of this: it provides the guest and host runtimes and an automated toolchain that generates the thunks from a library's headers, so guest -library calls run on the host's native libraries. It supports an x86_64 guest -running on an x86_64, aarch64 or riscv64 host. +library calls run on the host's native libraries. How it handles the parts the +plugin leaves out, including argument marshalling, callbacks and variadic +functions, can serve as a reference. It supports an x86_64 guest running on an +x86_64, aarch64 or riscv64 host. A minimal end-to-end example uses a one-function library, ``libhello.so``, built two ways: the guest build tags its output ``(from the guest)`` and the host @@ -1201,8 +1210,10 @@ * - Option - Description * - syscall_num=N - - The magic syscall number the guest issues (default 4096). Must be high - enough not to clash with a real syscall. + - The magic syscall number the guest issues (default 4096). It must be a + number the guest ABI does not use for a real syscall, and does not + reject before the plugin sees it, which bounds the choice from both + sides. Other emulation features ------------------------
diff --git a/docs/meson.build b/docs/meson.build index a8d8936..4d8cc54 100644 --- a/docs/meson.build +++ b/docs/meson.build
@@ -4,7 +4,7 @@ # Check if tools are available to build documentation. build_docs = false if sphinx_build.found() - SPHINX_ARGS = ['env', 'CONFDIR=' + qemu_confdir, sphinx_build, '-q', '-j', 'auto'] + SPHINX_ARGS = ['env', 'CONFDIR=' + qemu_confdir, sphinx_build, '-q'] # If we're making warnings fatal, apply this to Sphinx runs as well if get_option('werror') SPHINX_ARGS += [ '-W', '-Dkerneldoc_werror=1' ]
diff --git a/hw/arm/omap1.c b/hw/arm/omap1.c index 44f9dd6..0f78cbd 100644 --- a/hw/arm/omap1.c +++ b/hw/arm/omap1.c
@@ -32,7 +32,7 @@ #include "hw/sd/sd.h" #include "system/blockdev.h" #include "system/system.h" -#include "hw/arm/soc_dma.h" +#include "hw/dma/soc_dma.h" #include "system/qtest.h" #include "system/reset.h" #include "system/runstate.h" @@ -3799,10 +3799,8 @@ s->port[tipb_mpui].addr_valid = omap_validate_tipb_mpui_addr; /* Register SDRAM and SRAM DMA ports for fast transfers. */ - soc_dma_port_add_mem(s->dma, memory_region_get_ram_ptr(dram), - OMAP_EMIFF_BASE, s->sdram_size); - soc_dma_port_add_mem(s->dma, memory_region_get_ram_ptr(&s->imif_ram), - OMAP_IMIF_BASE, s->sram_size); + soc_dma_port_add_mem(s->dma, OMAP_EMIFF_BASE, s->sdram_size); + soc_dma_port_add_mem(s->dma, OMAP_IMIF_BASE, s->sram_size); s->timer[0] = omap_mpu_timer_init(system_memory, 0xfffec500, qdev_get_gpio_in(s->ih[0], OMAP_INT_TIMER1),
diff --git a/hw/audio/intel-hda.c b/hw/audio/intel-hda.c index d7c2c3c..3d361a4 100644 --- a/hw/audio/intel-hda.c +++ b/hw/audio/intel-hda.c
@@ -305,6 +305,7 @@ static void intel_hda_corb_run(IntelHDAState *d) { + const MemTxAttrs attrs = { .memory = true }; hwaddr addr; uint32_t rp, verb; @@ -330,7 +331,7 @@ rp = (d->corb_rp + 1) & 0xff; addr = intel_hda_addr(d->corb_lbase, d->corb_ubase); - ldl_le_pci_dma(&d->pci, addr + 4 * rp, &verb, MEMTXATTRS_UNSPECIFIED); + ldl_le_pci_dma(&d->pci, addr + 4 * rp, &verb, attrs); d->corb_rp = rp; dprint(d, 2, "%s: [rp 0x%x] verb 0x%08x\n", __func__, rp, verb); @@ -395,7 +396,7 @@ static bool intel_hda_xfer(HDACodecDevice *dev, uint32_t stnr, bool output, uint8_t *buf, uint32_t len) { - const MemTxAttrs attrs = MEMTXATTRS_UNSPECIFIED; + const MemTxAttrs attrs = { .memory = true }; HDACodecBus *bus = HDA_BUS(dev->qdev.parent_bus); IntelHDAState *d = container_of(bus, IntelHDAState, codecs); hwaddr addr; @@ -466,6 +467,7 @@ static void intel_hda_parse_bdl(IntelHDAState *d, IntelHDAStream *st) { + const MemTxAttrs attrs = { .memory = true }; hwaddr addr; uint8_t buf[16]; uint32_t i; @@ -475,7 +477,8 @@ g_free(st->bpl); st->bpl = g_new(bpl, st->bentries); for (i = 0; i < st->bentries; i++, addr += 16) { - pci_dma_read(&d->pci, addr, buf, 16); + pci_dma_rw(&d->pci, addr, buf, 16, + DMA_DIRECTION_TO_DEVICE, attrs); st->bpl[i].addr = le64_to_cpu(*(uint64_t *)buf); st->bpl[i].len = le32_to_cpu(*(uint32_t *)(buf + 8)); st->bpl[i].flags = le32_to_cpu(*(uint32_t *)(buf + 12));
diff --git a/hw/char/imx_serial.c b/hw/char/imx_serial.c index 080b7f6..fb41ee2 100644 --- a/hw/char/imx_serial.c +++ b/hw/char/imx_serial.c
@@ -43,14 +43,15 @@ static const VMStateDescription vmstate_imx_serial = { .name = TYPE_IMX_SERIAL, - .version_id = 3, - .minimum_version_id = 3, + .version_id = 4, + .minimum_version_id = 4, .fields = (const VMStateField[]) { VMSTATE_FIFO32(rx_fifo, IMXSerialState), VMSTATE_TIMER(ageing_timer, IMXSerialState), VMSTATE_UINT32(usr1, IMXSerialState), VMSTATE_UINT32(usr2, IMXSerialState), VMSTATE_UINT32(ucr1, IMXSerialState), + VMSTATE_UINT32(ucr2, IMXSerialState), VMSTATE_UINT32(uts1, IMXSerialState), VMSTATE_UINT32(onems, IMXSerialState), VMSTATE_UINT32(ufcr, IMXSerialState),
diff --git a/hw/display/qxl.c b/hw/display/qxl.c index 74258af..3df7961 100644 --- a/hw/display/qxl.c +++ b/hw/display/qxl.c
@@ -270,7 +270,7 @@ } cfg = qxl_phys2virt(qxl, qxl->guest_monitors_config, MEMSLOT_GROUP_GUEST, - sizeof(QXLMonitorsConfig)); + sizeof(QXLMonitorsConfig) + sizeof(QXLHead)); if (cfg != NULL && cfg->count == 1) { qxl->guest_primary.resized = 1; qxl->guest_head0_width = cfg->heads[0].width;
diff --git a/hw/dma/omap_dma.c b/hw/dma/omap_dma.c index 77f1441..16575e7 100644 --- a/hw/dma/omap_dma.c +++ b/hw/dma/omap_dma.c
@@ -22,7 +22,7 @@ #include "qemu/timer.h" #include "hw/arm/omap.h" #include "hw/core/irq.h" -#include "hw/arm/soc_dma.h" +#include "hw/dma/soc_dma.h" #include "system/physmem.h" struct omap_dma_channel_s { @@ -391,7 +391,7 @@ struct omap_dma_reg_set_s *a; struct omap_dma_channel_s *ch = dma->opaque; struct omap_dma_s *s = dma->dma->opaque; - int frames, min_elems, elements[__omap_dma_intr_last]; + uint32_t frames, min_elems, elements[__omap_dma_intr_last]; a = &ch->active_set; @@ -403,7 +403,14 @@ __func__, dma->num); } - min_elems = INT_MAX; + /* + * The maximum frame count and maximum element count are both 0xffff, + * so our worst case possible number of elements to transfer is + * 0xffff * 0xffff == 0xfffe0001. We can therefore keep element + * counts in a uint32_t and use UINT_MAX as a sentinel value for + * "not set" / "condition does not occur". + */ + min_elems = UINT_MAX; /* Check all the conditions that terminate the transfer starting * with those that can occur the soonest. */ @@ -413,7 +420,7 @@ if (elements[id] < min_elems) \ min_elems = elements[id]; \ } else \ - elements[id] = INT_MAX; + elements[id] = UINT_MAX; /* Elements */ INTR_CHECK( @@ -465,7 +472,7 @@ (a->frames - a->frame - 1) * a->elements + (a->elements - a->element)) - dma->bytes = min_elems * ch->data_type; + dma->bytes = (uint64_t)min_elems * ch->data_type; /* Set appropriate interrupts and/or deactivate channels */ @@ -528,8 +535,9 @@ /* Update packet number */ if (ch->fs && ch->bs) { - a->pck_element += min_elems; - a->pck_element %= a->pck_elements; + /* Can't overflow: worst case min_elems 0xFFFE0001 + element 0xFFFF */ + uint32_t new_pck_element = a->pck_element + min_elems; + a->pck_element = new_pck_element % a->pck_elements; } /* @@ -537,23 +545,20 @@ * can skip part of this. */ if (dma->update) { + /* Can't overflow: worst case min_elems 0xFFFE0001 + element 0xFFFF */ + uint32_t new_element = a->element + min_elems; a->element += min_elems; - frames = a->element / a->elements; - a->element = a->element % a->elements; + frames = new_element / a->elements; + a->element = new_element % a->elements; a->frame += frames; - a->src += min_elems * a->elem_delta[0] + frames * a->frame_delta[0]; - a->dest += min_elems * a->elem_delta[1] + frames * a->frame_delta[1]; + a->src += (uint64_t)min_elems * a->elem_delta[0] + frames * a->frame_delta[0]; + a->dest += (uint64_t)min_elems * a->elem_delta[1] + frames * a->frame_delta[1]; /* If the channel is async, update cpc */ if (!ch->sync && frames) { ch->cpc = a->dest & 0xffff; } - - /* - * TODO: if the destination port is IMIF or EMIFF, set the dirty - * bits on it. - */ } omap_dma_interrupts_update(s);
diff --git a/hw/dma/soc_dma.c b/hw/dma/soc_dma.c index d5c52b8..4feb22e 100644 --- a/hw/dma/soc_dma.c +++ b/hw/dma/soc_dma.c
@@ -20,40 +20,58 @@ #include "qemu/osdep.h" #include "qemu/error-report.h" #include "qemu/timer.h" -#include "hw/arm/soc_dma.h" +#include "qemu/log.h" +#include "system/physmem.h" +#include "hw/dma/soc_dma.h" static void transfer_mem2mem(struct soc_dma_ch_s *ch) { - memcpy(ch->paddr[0], ch->paddr[1], ch->bytes); - ch->paddr[0] += ch->bytes; - ch->paddr[1] += ch->bytes; -} + /* + * Memory-to-memory transfer: do the whole thing in one go. The + * hardware spec says that it is invalid to program the OMAP DMA + * controller with addresses that don't match the port (i.e. to + * ask for a transfer to/from a memory port with a physaddr that + * isn't within that port range) and that if you do then the + * transfer continues and memory can be corrupted. So we can map + * both source and destination, and treat short mappings and + * failed mappings as a guest error. + */ + hwaddr srclen = ch->bytes; + hwaddr dstlen = ch->bytes; + hwaddr srcaddr = ch->vaddr[0]; + hwaddr dstaddr = ch->vaddr[1]; + void *srcmem, *dstmem; + hwaddr xferlen = 0; -static void transfer_mem2fifo(struct soc_dma_ch_s *ch) -{ - ch->io_fn[1](ch->io_opaque[1], ch->paddr[0], ch->bytes); - ch->paddr[0] += ch->bytes; -} + srcmem = physical_memory_map(srcaddr, &srclen, false); + if (!srcmem) { + qemu_log_mask(LOG_GUEST_ERROR, + "soc_dma mem2mem transfer: could not map source; " + "guest error programming source port/address\n"); + return; + } -static void transfer_fifo2mem(struct soc_dma_ch_s *ch) -{ - ch->io_fn[0](ch->io_opaque[0], ch->paddr[1], ch->bytes); - ch->paddr[1] += ch->bytes; -} + dstmem = physical_memory_map(dstaddr, &dstlen, true); + if (!dstmem) { + qemu_log_mask(LOG_GUEST_ERROR, + "soc_dma mem2mem transfer: could not map destination; " + "guest error programming destination port/address\n"); + goto unmap_src; + } -/* This is further optimisable but isn't very important because often - * DMA peripherals forbid this kind of transfers and even when they don't, - * oprating systems may not need to use them. */ -static void *fifo_buf; -static int fifo_size; -static void transfer_fifo2fifo(struct soc_dma_ch_s *ch) -{ - if (ch->bytes > fifo_size) - fifo_buf = g_realloc(fifo_buf, fifo_size = ch->bytes); + xferlen = MIN(srclen, dstlen); + if (xferlen < ch->bytes) { + qemu_log_mask(LOG_GUEST_ERROR, + "soc_dma mem2mem transfer: could not transfer all data; " + "guest error programming src or destination addresses\n"); + /* Continue to transfer whatever did fit in the port window */ + } - /* Implement as transfer_fifo2linear + transfer_linear2fifo. */ - ch->io_fn[0](ch->io_opaque[0], fifo_buf, ch->bytes); - ch->io_fn[1](ch->io_opaque[1], fifo_buf, ch->bytes); + memmove(dstmem, srcmem, xferlen); + + physical_memory_unmap(dstmem, dstlen, true, xferlen); +unmap_src: + physical_memory_unmap(srcmem, srclen, false, xferlen); } struct dma_s { @@ -66,28 +84,24 @@ struct memmap_entry_s { enum soc_dma_port_type type; hwaddr addr; - union { - struct { - void *opaque; - soc_dma_io_t fn; - int out; - } fifo; - struct { - void *base; - size_t size; - } mem; - } u; + struct { + size_t size; + } mem; } *memmap; int memmap_size; struct soc_dma_ch_s ch[]; }; -static void soc_dma_ch_schedule(struct soc_dma_ch_s *ch, int delay_bytes) +static void soc_dma_ch_schedule(struct soc_dma_ch_s *ch, uint64_t delay_bytes) { int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); struct dma_s *dma = (struct dma_s *) ch->dma; + /* + * Worst case delay bytes is only slightly larger than fits into + * a 32-bit integer, so this won't overflow. + */ timer_mod(ch->timer, now + delay_bytes / dma->channel_freq); } @@ -129,22 +143,9 @@ struct dma_s *dma = (struct dma_s *) ch->dma; struct memmap_entry_s *entry = soc_dma_lookup(dma, ch->vaddr[port]); - if (entry->type == soc_dma_port_fifo) { - while (entry < dma->memmap + dma->memmap_size && - entry->u.fifo.out != port) - entry ++; - if (entry->addr != ch->vaddr[port] || entry->u.fifo.out != port) - return soc_dma_port_other; - - if (ch->type[port] != soc_dma_access_const) - return soc_dma_port_other; - - ch->io_fn[port] = entry->u.fifo.fn; - ch->io_opaque[port] = entry->u.fifo.opaque; - return soc_dma_port_fifo; - } else if (entry->type == soc_dma_port_mem) { + if (entry->type == soc_dma_port_mem) { if (entry->addr > ch->vaddr[port] || - entry->addr + entry->u.mem.size <= ch->vaddr[port]) + entry->addr + entry->mem.size <= ch->vaddr[port]) return soc_dma_port_other; /* TODO: support constant memory address for source port as used for @@ -152,10 +153,6 @@ if (ch->type[port] != soc_dma_access_const) return soc_dma_port_other; - ch->paddr[port] = (uint8_t *) entry->u.mem.base + - (ch->vaddr[port] - entry->addr); - /* TODO: save bytes left to the end of the mapping somewhere so we - * can check we're not reading beyond it. */ return soc_dma_port_mem; } else return soc_dma_port_other; @@ -166,26 +163,14 @@ enum soc_dma_port_type src, dst; src = soc_dma_ch_update_type(ch, 0); - if (src == soc_dma_port_other) { + dst = soc_dma_ch_update_type(ch, 1); + if (src == soc_dma_port_other || dst == soc_dma_port_other) { ch->update = 0; ch->transfer_fn = ch->dma->transfer_fn; - return; - } - dst = soc_dma_ch_update_type(ch, 1); - - /* TODO: use src and dst as array indices. */ - if (src == soc_dma_port_mem && dst == soc_dma_port_mem) + } else { + ch->update = 1; ch->transfer_fn = transfer_mem2mem; - else if (src == soc_dma_port_mem && dst == soc_dma_port_fifo) - ch->transfer_fn = transfer_mem2fifo; - else if (src == soc_dma_port_fifo && dst == soc_dma_port_mem) - ch->transfer_fn = transfer_fifo2mem; - else if (src == soc_dma_port_fifo && dst == soc_dma_port_fifo) - ch->transfer_fn = transfer_fifo2fifo; - else - ch->transfer_fn = ch->dma->transfer_fn; - - ch->update = (dst != soc_dma_port_other); + } } static void soc_dma_ch_freq_update(struct dma_s *s) @@ -251,63 +236,11 @@ } soc_dma_reset(&s->soc); - fifo_size = 0; return &s->soc; } -void soc_dma_port_add_fifo(struct soc_dma_s *soc, hwaddr virt_base, - soc_dma_io_t fn, void *opaque, int out) -{ - struct memmap_entry_s *entry; - struct dma_s *dma = (struct dma_s *) soc; - - dma->memmap = g_realloc(dma->memmap, sizeof(*entry) * - (dma->memmap_size + 1)); - entry = soc_dma_lookup(dma, virt_base); - - if (dma->memmap_size) { - if (entry->type == soc_dma_port_mem) { - if (entry->addr <= virt_base && - entry->addr + entry->u.mem.size > virt_base) { - error_report("%s: FIFO at %"PRIx64 - " collides with RAM region at %"PRIx64 - "-%"PRIx64, __func__, - virt_base, entry->addr, - (entry->addr + entry->u.mem.size)); - exit(-1); - } - - if (entry->addr <= virt_base) - entry ++; - } else - while (entry < dma->memmap + dma->memmap_size && - entry->addr <= virt_base) { - if (entry->addr == virt_base && entry->u.fifo.out == out) { - error_report("%s: FIFO at %"PRIx64 - " collides FIFO at %"PRIx64, - __func__, virt_base, entry->addr); - exit(-1); - } - - entry ++; - } - - memmove(entry + 1, entry, - (uint8_t *) (dma->memmap + dma->memmap_size ++) - - (uint8_t *) entry); - } else - dma->memmap_size ++; - - entry->addr = virt_base; - entry->type = soc_dma_port_fifo; - entry->u.fifo.fn = fn; - entry->u.fifo.opaque = opaque; - entry->u.fifo.out = out; -} - -void soc_dma_port_add_mem(struct soc_dma_s *soc, uint8_t *phys_base, - hwaddr virt_base, size_t size) +void soc_dma_port_add_mem(struct soc_dma_s *soc, hwaddr virt_base, size_t size) { struct memmap_entry_s *entry; struct dma_s *dma = (struct dma_s *) soc; @@ -320,12 +253,12 @@ if (entry->type == soc_dma_port_mem) { if ((entry->addr >= virt_base && entry->addr < virt_base + size) || (entry->addr <= virt_base && - entry->addr + entry->u.mem.size > virt_base)) { + entry->addr + entry->mem.size > virt_base)) { error_report("%s: RAM at %"PRIx64 "-%"PRIx64 " collides with RAM region at %"PRIx64 "-%"PRIx64, __func__, virt_base, virt_base + size, - entry->addr, entry->addr + entry->u.mem.size); + entry->addr, entry->addr + entry->mem.size); exit(-1); } @@ -354,8 +287,7 @@ entry->addr = virt_base; entry->type = soc_dma_port_mem; - entry->u.mem.base = phys_base; - entry->u.mem.size = size; + entry->mem.size = size; } /* TODO: port removal for ports like PCMCIA memory */
diff --git a/hw/misc/applesmc.c b/hw/misc/applesmc.c index fd96f5f..d004e8b 100644 --- a/hw/misc/applesmc.c +++ b/hw/misc/applesmc.c
@@ -333,9 +333,9 @@ applesmc_add_key(s, "REV ", 6, "\x01\x13\x0f\x00\x00\x03"); applesmc_add_key(s, "OSK0", 32, s->osk); applesmc_add_key(s, "OSK1", 32, s->osk + 32); - applesmc_add_key(s, "NATJ", 1, "\0"); - applesmc_add_key(s, "MSSP", 1, "\0"); - applesmc_add_key(s, "MSSD", 1, "\0x3"); + applesmc_add_key(s, "NATJ", 1, "\x00"); + applesmc_add_key(s, "MSSP", 1, "\x00"); + applesmc_add_key(s, "MSSD", 1, "\x03"); } static void applesmc_unrealize(DeviceState *dev)
diff --git a/hw/net/cadence_gem.c b/hw/net/cadence_gem.c index b568fa3..39e3620 100644 --- a/hw/net/cadence_gem.c +++ b/hw/net/cadence_gem.c
@@ -1469,6 +1469,8 @@ /* Set post reset register values */ memset(&s->regs[0], 0, sizeof(s->regs)); + memset(&s->rx_desc_addr[0], 0, sizeof(s->rx_desc_addr)); + memset(&s->tx_desc_addr[0], 0, sizeof(s->tx_desc_addr)); s->regs[R_NWCFG] = 0x00080000; s->regs[R_NWSTATUS] = 0x00000006; s->regs[R_DMACFG] = 0x00020784; @@ -1593,9 +1595,22 @@ offset >>= 2; retval = s->regs[offset]; - DB_PRINT("offset: 0x%04x read: 0x%08x\n", (unsigned)offset*4, retval); + DB_PRINT("offset: 0x%04x read: 0x%08x\n", (unsigned)offset * 4, + retval); switch (offset) { + case R_RXQBASE: + retval = s->rx_desc_addr[0]; + break; + case R_TXQBASE: + retval = s->tx_desc_addr[0]; + break; + case R_TRANSMIT_Q1_PTR ... R_TRANSMIT_Q7_PTR: + retval = s->tx_desc_addr[offset - R_TRANSMIT_Q1_PTR + 1]; + break; + case R_RECEIVE_Q1_PTR ... R_RECEIVE_Q7_PTR: + retval = s->rx_desc_addr[offset - R_RECEIVE_Q1_PTR + 1]; + break; case R_ISR: DB_PRINT("lowering irqs on ISR read\n"); /* The interrupts get updated at the end of the function. */
diff --git a/hw/net/xilinx_axienet.c b/hw/net/xilinx_axienet.c index 970732b..9f5f65e 100644 --- a/hw/net/xilinx_axienet.c +++ b/hw/net/xilinx_axienet.c
@@ -103,6 +103,9 @@ case 17: /* Marvell PHY on many xilinx boards. */ r = 0x8000; /* 1000Mb */ + if (phy->link) { + r |= 0x0400; /* Link is up */ + } break; case 18: {
diff --git a/hw/sd/sd.c b/hw/sd/sd.c index 3360757..a30c541 100644 --- a/hw/sd/sd.c +++ b/hw/sd/sd.c
@@ -2860,7 +2860,8 @@ if (sd->data_offset == 0) { if (!address_in_range(sd, "READ_MULTIPLE_BLOCK", sd->data_start, io_len)) { - return dummy_byte; + *value = dummy_byte; + return length; } partition_access = sd->ext_csd[EXT_CSD_PART_CONFIG] & EXT_CSD_PART_CONFIG_ACC_MASK;
diff --git a/hw/vfio/listener.c b/hw/vfio/listener.c index c19600e..008f488 100644 --- a/hw/vfio/listener.c +++ b/hw/vfio/listener.c
@@ -20,7 +20,6 @@ #include "qemu/osdep.h" #include <sys/ioctl.h> -#include <linux/kvm.h> #include <linux/vfio.h> #include "exec/target_page.h"
diff --git a/include/hw/arm/soc_dma.h b/include/hw/dma/soc_dma.h similarity index 70% rename from include/hw/arm/soc_dma.h rename to include/hw/dma/soc_dma.h index bcdb914..fdae7a2 100644 --- a/include/hw/arm/soc_dma.h +++ b/include/hw/dma/soc_dma.h
@@ -25,12 +25,10 @@ struct soc_dma_s; struct soc_dma_ch_s; -typedef void (*soc_dma_io_t)(void *opaque, uint8_t *buf, int len); typedef void (*soc_dma_transfer_t)(struct soc_dma_ch_s *ch); enum soc_dma_port_type { soc_dma_port_mem, - soc_dma_port_fifo, soc_dma_port_other, }; @@ -51,14 +49,10 @@ int update; /* This should be set by dma->setup_fn(). */ - int bytes; + uint64_t bytes; /* Initialised by the DMA module, call soc_dma_ch_update after writing. */ enum soc_dma_access_type type[2]; hwaddr vaddr[2]; /* Updated by .transfer_fn(). */ - /* Private */ - void *paddr[2]; - soc_dma_io_t io_fn[2]; - void *io_opaque[2]; int running; soc_dma_transfer_t transfer_fn; @@ -82,33 +76,20 @@ /* Call to activate or stop a DMA channel. */ void soc_dma_set_request(struct soc_dma_ch_s *ch, int level); -/* Call after every write to one of the following fields and before +/* + * Call after every write to one of the following fields and before * calling soc_dma_set_request(ch, 1): * ch->type[0...1], * ch->vaddr[0...1], - * ch->paddr[0...1], - * or after a soc_dma_port_add_fifo() or soc_dma_port_add_mem(). */ + * or after a soc_dma_port_add_mem(). + */ void soc_dma_ch_update(struct soc_dma_ch_s *ch); /* The SoC should call this when the DMA module is being reset. */ void soc_dma_reset(struct soc_dma_s *s); struct soc_dma_s *soc_dma_init(int n); -void soc_dma_port_add_fifo(struct soc_dma_s *dma, hwaddr virt_base, - soc_dma_io_t fn, void *opaque, int out); -void soc_dma_port_add_mem(struct soc_dma_s *dma, uint8_t *phys_base, - hwaddr virt_base, size_t size); - -static inline void soc_dma_port_add_fifo_in(struct soc_dma_s *dma, - hwaddr virt_base, soc_dma_io_t fn, void *opaque) -{ - return soc_dma_port_add_fifo(dma, virt_base, fn, opaque, 0); -} - -static inline void soc_dma_port_add_fifo_out(struct soc_dma_s *dma, - hwaddr virt_base, soc_dma_io_t fn, void *opaque) -{ - return soc_dma_port_add_fifo(dma, virt_base, fn, opaque, 1); -} +void soc_dma_port_add_mem(struct soc_dma_s *dma, + hwaddr virt_base, size_t size); #endif
diff --git a/include/net/net.h b/include/net/net.h index 45bc86f..9edfacf 100644 --- a/include/net/net.h +++ b/include/net/net.h
@@ -349,9 +349,32 @@ .offset = vmstate_offset_macaddr(_state, _field), \ } +/** + * net_peer_needs_padding: Should we pad as we send out packets? + * @nc: NetClientState + * + * Return true if the peer of this NetClientState (i.e. the + * destination that qemu_send_packet() etc send to) requires us to pad + * out packets that are shorter than the minimum ethernet frame + * length. + */ static inline bool net_peer_needs_padding(NetClientState *nc) { return nc->peer && !nc->peer->do_not_pad; } +/** + * net_client_needs_padding: Should we pad as we queue packets to ourselves? + * @nc: NetClientState + * + * Return true if this NetClientState requires us to pad out packets + * that are shorter than the minimum ethernet frame length. This is + * the check to make in qemu_receive_packet() when we are queuing a + * packet back into ourselves (i.e. loopback). + */ +static inline bool net_client_needs_padding(NetClientState *nc) +{ + return !nc->do_not_pad; +} + #endif
diff --git a/include/user/guest-host.h b/include/user/guest-host.h index 506efc0..f136f81 100644 --- a/include/user/guest-host.h +++ b/include/user/guest-host.h
@@ -80,6 +80,7 @@ }) #ifdef COMPILING_PER_TARGET +#include "exec/abi_ptr.h" /* * These functions take the guest virtual address as an abi_ptr. This
diff --git a/net/net.c b/net/net.c index 5c39f8e..0a30579 100644 --- a/net/net.c +++ b/net/net.c
@@ -783,7 +783,7 @@ return 0; } - if (net_peer_needs_padding(nc)) { + if (net_client_needs_padding(nc)) { if (eth_pad_short_frame(min_pkt, &min_pktsz, buf, size)) { buf = min_pkt; size = min_pktsz;
diff --git a/replay/replay-debugging.c b/replay/replay-debugging.c index 1105364..7b904a1 100644 --- a/replay/replay-debugging.c +++ b/replay/replay-debugging.c
@@ -139,9 +139,8 @@ int64_t *snapshot_icount) { BlockDriverState *bs; - QEMUSnapshotInfo *sn_tab; + g_autofree QEMUSnapshotInfo *sn_tab = NULL; QEMUSnapshotInfo *nearest = NULL; - char *ret = NULL; int rv; int nb_sns, i; @@ -149,15 +148,19 @@ bs = bdrv_all_find_vmstate_bs(NULL, false, NULL, NULL); if (!bs) { - goto fail; + return NULL; } nb_sns = bdrv_snapshot_list(bs, &sn_tab); + if (nb_sns < 0) { + return NULL; + } for (i = 0; i < nb_sns; i++) { rv = bdrv_all_has_snapshot(sn_tab[i].name, false, NULL, NULL); - if (rv < 0) - goto fail; + if (rv < 0) { + return NULL; + } if (rv == 1) { if (sn_tab[i].icount != -1ULL && sn_tab[i].icount <= icount @@ -166,14 +169,12 @@ } } } - if (nearest) { - ret = g_strdup(nearest->name); - *snapshot_icount = nearest->icount; + if (!nearest) { + return NULL; } - g_free(sn_tab); -fail: - return ret; + *snapshot_icount = nearest->icount; + return g_strdup(nearest->name); } static void replay_seek(int64_t icount, QEMUTimerCB callback, Error **errp)
diff --git a/target/arm/tcg/cpu32-system.c b/target/arm/tcg/cpu32.c similarity index 98% rename from target/arm/tcg/cpu32-system.c rename to target/arm/tcg/cpu32.c index 6e98390..8220d78 100644 --- a/target/arm/tcg/cpu32-system.c +++ b/target/arm/tcg/cpu32.c
@@ -1,5 +1,5 @@ /* - * QEMU ARM TCG-only CPUs (not needed for the AArch64 linux-user build) + * QEMU ARM TCG-only CPUs. * * Copyright (c) 2012 SUSE LINUX Products GmbH * @@ -13,9 +13,15 @@ #include "cpu.h" #include "accel/tcg/cpu-ops.h" #include "internals.h" +#if !defined(CONFIG_USER_ONLY) #include "hw/core/boards.h" +#endif #include "cpregs.h" + +/* CPU models. These are not needed for the AArch64 linux-user build. */ +#if !defined(CONFIG_USER_ONLY) || !defined(TARGET_AARCH64) + static void arm926_initfn(Object *obj) { ARMCPU *cpu = ARM_CPU(obj); @@ -740,3 +746,5 @@ } type_init(arm_tcg_cpu_register_types) + +#endif /* !CONFIG_USER_ONLY || !TARGET_AARCH64 */
diff --git a/target/arm/tcg/gicv5-cpuif.c b/target/arm/tcg/gicv5-cpuif.c index 1cdd410..a6e6c44 100644 --- a/target/arm/tcg/gicv5-cpuif.c +++ b/target/arm/tcg/gicv5-cpuif.c
@@ -495,6 +495,7 @@ GICv5Domain domain = gicv5_logical_domain(env); value &= 0xffffffff; env->gicv5_cpuif.icc_apr[domain] = value; + gicv5_update_irq_fiq(env); } static uint64_t gic_icc_apr_el1_read(CPUARMState *env, const ARMCPRegInfo *ri) @@ -633,7 +634,8 @@ switch (type) { case GICV5_PPI: { - uint32_t ppireg, ppibit; + uint32_t ppireg; + uint64_t ppibit; assert(id < GICV5_NUM_PPIS); ppireg = id / 64;
diff --git a/target/arm/tcg/meson.build b/target/arm/tcg/meson.build index 573e8b5..227e674 100644 --- a/target/arm/tcg/meson.build +++ b/target/arm/tcg/meson.build
@@ -30,6 +30,10 @@ arm_ss.add(when: 'TARGET_AARCH64', if_true: gen_a64) arm_stubs_ss.add(files('stubs32.c')) +arm_ss.add(files( + 'cpu32.c', +)) + arm_ss.add(when: 'TARGET_AARCH64', if_true: files( 'gengvec64.c', 'translate-a64.c', @@ -82,7 +86,6 @@ arm_common_system_ss.add(files( 'cpregs-at.c', - 'cpu32-system.c', 'gicv5-cpuif.c', 'psci.c', 'tlb_helper.c',
diff --git a/target/arm/tcg/mte_helper.c b/target/arm/tcg/mte_helper.c index dca4ef5..ad4ad5b 100644 --- a/target/arm/tcg/mte_helper.c +++ b/target/arm/tcg/mte_helper.c
@@ -317,6 +317,12 @@ return extract32(*mem, ofs, 4); } +/* Like mtx_check, but simple mtx bit pair instead of MTEDESC. */ +static bool raw_mtx_check(unsigned mtx, unsigned bit55) +{ + return (mtx >> bit55) & 1; +} + uint64_t HELPER(ldg)(CPUARMState *env, uint64_t ptr, uint64_t xt, uint32_t mtx) { int mmu_idx = arm_env_mmu_index(env); @@ -330,9 +336,11 @@ /* Load if page supports tags. */ if (mem) { rtag = load_tag1(ptr, mem); - } else if (mtx) { - uint64_t bit55 = extract64(ptr, 55, 1); - rtag = 0xF * bit55; + } else { + bool bit55 = extract64(ptr, 55, 1); + if (raw_mtx_check(mtx, bit55)) { + rtag = 0xF * bit55; + } } return address_with_allocation_tag(xt, rtag); @@ -387,7 +395,7 @@ /* Store if page supports tags. */ if (mem) { store1(ptr, mem, allocation_tag_from_addr(xt)); - } else if (mtx) { + } else if (raw_mtx_check(mtx, extract64(ptr, 55, 1))) { canonical_tag_write_fail(env, ptr, ra); } } @@ -420,6 +428,7 @@ uint8_t *mem1, *mem2; check_tag_aligned(env, ptr, ra); + mtx = raw_mtx_check(mtx, extract64(ptr, 55, 1)); /* * Trap if accessing an invalid page(s). @@ -504,8 +513,8 @@ /* The tag is squashed to zero if the page does not support tags. */ if (!tag_mem) { /* Load canonical value if mtx is set (untagged memory region) */ - if (mtx) { - bool bit55 = extract64(ptr, 55, 1); + bool bit55 = extract64(ptr, 55, 1); + if (raw_mtx_check(mtx, bit55)) { ret = extract64(-bit55, 0, 1 << gm_bs); shift = extract64(ptr, LOG2_TAG_GRANULE, 4) * 4; return ret << shift; @@ -573,7 +582,7 @@ */ if (!tag_mem) { /* Storing tags to canonically tagged region: fault. */ - if (mtx) { + if (raw_mtx_check(mtx, extract64(ptr, 55, 1))) { canonical_tag_write_fail(env, ptr, ra); } return; @@ -630,7 +639,7 @@ if (mem) { int tag_pair = (val & 0xf) * 0x11; memset(mem, tag_pair, tag_bytes); - } else if (mtx) { + } else if (raw_mtx_check(mtx, extract64(ptr, 55, 1))) { canonical_tag_write_fail(env, ptr, ra); } }
diff --git a/target/ppc/helper.h b/target/ppc/helper.h index e99c8c8..6b2d19a 100644 --- a/target/ppc/helper.h +++ b/target/ppc/helper.h
@@ -54,7 +54,6 @@ #endif DEF_HELPER_FLAGS_2(icbi, TCG_CALL_NO_WG, void, env, tl) DEF_HELPER_FLAGS_2(icbiep, TCG_CALL_NO_WG, void, env, tl) -DEF_HELPER_5(lscbx, tl, env, tl, i32, i32, i32) #if defined(TARGET_PPC64) DEF_HELPER_4(DIVDEU, i64, env, i64, i64, i32)
diff --git a/target/ppc/mem_helper.c b/target/ppc/mem_helper.c index 119dc1d..787ba2c 100644 --- a/target/ppc/mem_helper.c +++ b/target/ppc/mem_helper.c
@@ -367,34 +367,6 @@ #endif } -/* XXX: to be tested */ -target_ulong helper_lscbx(CPUPPCState *env, target_ulong addr, uint32_t reg, - uint32_t ra, uint32_t rb) -{ - int i, c, d; - - d = 24; - for (i = 0; i < xer_bc; i++) { - c = cpu_ldub_data_ra(env, addr, GETPC()); - addr = addr_add(env, addr, 1); - /* ra (if not 0) and rb are never modified */ - if (likely(reg != rb && (ra == 0 || reg != ra))) { - env->gpr[reg] = (env->gpr[reg] & ~(0xFF << d)) | (c << d); - } - if (unlikely(c == xer_cmp)) { - break; - } - if (likely(d != 0)) { - d -= 8; - } else { - d = 24; - reg++; - reg = reg & 0x1F; - } - } - return i; -} - /*****************************************************************************/ /* Altivec extension helpers */ #if HOST_BIG_ENDIAN
diff --git a/tests/qemu-iotests/108 b/tests/qemu-iotests/108 index 54e935a..bf808b3 100755 --- a/tests/qemu-iotests/108 +++ b/tests/qemu-iotests/108
@@ -34,8 +34,8 @@ if [ -f "$TEST_DIR/qsd.pid" ]; then qsd_pid=$(cat "$TEST_DIR/qsd.pid") kill -KILL "$qsd_pid" - fusermount -u "$TEST_DIR/fuse-export" &>/dev/null fi + fusermount -u "$TEST_DIR/fuse-export" &>/dev/null rm -f "$TEST_DIR/fuse-export" } trap "_cleanup; exit \$status" 0 1 2 3 15
diff --git a/tests/tcg/multiarch/test-plugin-syscall-filter.c b/tests/tcg/multiarch/test-plugin-syscall-filter.c index 951e338..089fb2a 100644 --- a/tests/tcg/multiarch/test-plugin-syscall-filter.c +++ b/tests/tcg/multiarch/test-plugin-syscall-filter.c
@@ -23,9 +23,12 @@ * "linux-user/arm/cpu_loop.c:cpu_loop". * As well, some arch expect a minimum, like 4000 for mips 32 bits. * - * Therefore, we pick 4096 because, as of now, no ISA in Linux uses this - * number. This is just a test case; replace this number as needed in the - * future. + * Therefore, we pick 4096, which sits between those bounds. It is not + * unused everywhere though: mips 32 bits numbers from 4000, so 4096 is its + * getpriority. This test is unaffected because the filter also requires + * the first argument to be 0x66CCFF, so a real syscall carrying this + * number falls through untouched. This is just a test case, so replace + * this number as needed in the future. * * The corresponding syscall filter is implemented in * "tests/tcg/plugins/syscall.c".