diff options
82 files changed, 737 insertions, 448 deletions
@@ -67,6 +67,7 @@ Andrey Drobyshev <andrey.drobyshev@virtuozzo.com> Andrey Drobyshev via <qemu-blo BALATON Zoltan <balaton@eik.bme.hu> BALATON Zoltan via <qemu-ppc@nongnu.org> # Next, replace old addresses by a more recent one. +Akihiko Odaki <akihiko.odaki@daynix.com> <akihiko.odaki@gmail.com> Aleksandar Markovic <aleksandar.qemu.devel@gmail.com> <aleksandar.markovic@mips.com> Aleksandar Markovic <aleksandar.qemu.devel@gmail.com> <aleksandar.markovic@imgtec.com> Aleksandar Markovic <aleksandar.qemu.devel@gmail.com> <amarkovic@wavecomp.com> diff --git a/MAINTAINERS b/MAINTAINERS index 8f470a1..d54b557 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -319,6 +319,7 @@ L: qemu-riscv@nongnu.org S: Supported F: configs/targets/riscv* F: docs/system/target-riscv.rst +F: docs/specs/riscv-iommu.rst F: target/riscv/ F: hw/char/riscv_htif.c F: hw/riscv/ @@ -1018,7 +1019,7 @@ S: Maintained F: hw/arm/virt* F: include/hw/arm/virt.h F: docs/system/arm/virt.rst -F: tests/functional/test_aarch64_virt.py +F: tests/functional/test_aarch64_virt*.py F: tests/functional/test_aarch64_tuxrun.py F: tests/functional/test_arm_tuxrun.py @@ -207,10 +207,10 @@ clean: recurse-clean VERSION = $(shell cat $(SRC_PATH)/VERSION) -dist: qemu-$(VERSION).tar.bz2 +dist: qemu-$(VERSION).tar.xz -qemu-%.tar.bz2: - $(SRC_PATH)/scripts/make-release "$(SRC_PATH)" "$(patsubst qemu-%.tar.bz2,%,$@)" +qemu-%.tar.xz: + $(SRC_PATH)/scripts/make-release "$(SRC_PATH)" "$(patsubst qemu-%.tar.xz,%,$@)" distclean: clean recurse-distclean -$(quiet-@)test -f build.ninja && $(NINJA) $(NINJAFLAGS) -t clean -g || : @@ -1 +1 @@ -9.2.90 +9.2.91 diff --git a/backends/cryptodev-lkcf.c b/backends/cryptodev-lkcf.c index 41cf24b..352c3e8 100644 --- a/backends/cryptodev-lkcf.c +++ b/backends/cryptodev-lkcf.c @@ -330,6 +330,8 @@ static void cryptodev_lkcf_execute_task(CryptoDevLKCFTask *task) cryptodev_lkcf_set_op_desc(&session->akcipher_opts, op_desc, sizeof(op_desc), &local_error) != 0) { error_report_err(local_error); + status = -VIRTIO_CRYPTO_ERR; + goto out; } else { key_id = add_key(KCTL_KEY_TYPE_PKEY, "lkcf-backend-priv-key", p8info, p8info_len, KCTL_KEY_RING); @@ -346,6 +348,7 @@ static void cryptodev_lkcf_execute_task(CryptoDevLKCFTask *task) session->key, session->keylen, &local_error); if (!akcipher) { + error_report_err(local_error); status = -VIRTIO_CRYPTO_ERR; goto out; } diff --git a/docs/about/emulation.rst b/docs/about/emulation.rst index 3bc3579..a72591e 100644 --- a/docs/about/emulation.rst +++ b/docs/about/emulation.rst @@ -171,7 +171,7 @@ for that architecture. - Unified Hosting Interface (MD01069) * - RISC-V - System and User-mode - - https://github.com/riscv/riscv-semihosting-spec/blob/main/riscv-semihosting-spec.adoc + - https://github.com/riscv-non-isa/riscv-semihosting/blob/main/riscv-semihosting.adoc * - Xtensa - System - Tensilica ISS SIMCALL diff --git a/docs/devel/testing/functional.rst b/docs/devel/testing/functional.rst index a9fa45e..9bc9733 100644 --- a/docs/devel/testing/functional.rst +++ b/docs/devel/testing/functional.rst @@ -72,8 +72,26 @@ files around on disk by setting ```QEMU_TEST_KEEP_SCRATCH=1``` as an env variable. Any preserved files will be deleted the next time the test is run without this variable set. -Overview --------- +Logging +------- + +The framework collects log files for each test in the build directory +in the following subfolder:: + + <builddir>/tests/functional/<arch>/<fileid>.<classid>.<testname>/ + +There are usually three log files: + +* ``base.log`` contains the generic logging information that is written + by the calls to the logging functions in the test code (e.g. by calling + the ``self.log.info()`` or ``self.log.debug()`` functions). +* ``console.log`` contains the output of the serial console of the guest. +* ``default.log`` contains the output of QEMU. This file could be named + differently if the test chooses to use a different identifier for + the guest VM (e.g. when the test spins up multiple VMs). + +Introduction to writing tests +----------------------------- The ``tests/functional/qemu_test`` directory provides the ``qemu_test`` Python module, containing the ``qemu_test.QemuSystemTest`` class. diff --git a/docs/interop/firmware.json b/docs/interop/firmware.json index 57f55f6..745d21d 100644 --- a/docs/interop/firmware.json +++ b/docs/interop/firmware.json @@ -214,13 +214,23 @@ # PL011 UART. @verbose-static is mutually exclusive # with @verbose-dynamic. # +# @host-uefi-vars: The firmware expects the host to provide an uefi +# variable store. qemu supports that via +# "uefi-vars-sysbus" (aarch64, riscv64, loongarch64) +# or "uefi-vars-x64" (x86_64) devices. The firmware +# will not use flash for nvram. When loading the +# firmware into flash the 'stateless' setup should be +# used. It is recommened to load the firmware into +# memory though. +# # Since: 3.0 ## { 'enum' : 'FirmwareFeature', 'data' : [ 'acpi-s3', 'acpi-s4', 'amd-sev', 'amd-sev-es', 'amd-sev-snp', 'intel-tdx', - 'enrolled-keys', 'requires-smm', 'secure-boot', + 'enrolled-keys', 'requires-smm', + 'secure-boot', 'host-uefi-vars', 'verbose-dynamic', 'verbose-static' ] } ## diff --git a/docs/specs/riscv-iommu.rst b/docs/specs/riscv-iommu.rst index 000c7e1..991d376 100644 --- a/docs/specs/riscv-iommu.rst +++ b/docs/specs/riscv-iommu.rst @@ -4,7 +4,7 @@ RISC-V IOMMU support for RISC-V machines ======================================== QEMU implements a RISC-V IOMMU emulation based on the RISC-V IOMMU spec -version 1.0 `iommu1.0`_. +version 1.0 `iommu1.0.0`_. The emulation includes a PCI reference device (riscv-iommu-pci) and a platform bus device (riscv-iommu-sys) that QEMU RISC-V boards can use. The 'virt' @@ -14,7 +14,7 @@ riscv-iommu-pci reference device -------------------------------- This device implements the RISC-V IOMMU emulation as recommended by the section -"Integrating an IOMMU as a PCIe device" of `iommu1.0`_: a PCI device with base +"Integrating an IOMMU as a PCIe device" of `iommu1.0.0`_: a PCI device with base class 08h, sub-class 06h and programming interface 00h. As a reference device it doesn't implement anything outside of the specification, @@ -109,7 +109,7 @@ riscv-iommu options: - "s-stage": enabled - "g-stage": enabled -.. _iommu1.0: https://github.com/riscv-non-isa/riscv-iommu/releases/download/v1.0/riscv-iommu.pdf +.. _iommu1.0.0: https://github.com/riscv-non-isa/riscv-iommu/releases/download/v1.0.0/riscv-iommu.pdf .. _linux-v8: https://lore.kernel.org/linux-riscv/cover.1718388908.git.tjeznach@rivosinc.com/ diff --git a/docs/system/arm/bananapi_m2u.rst b/docs/system/arm/bananapi_m2u.rst index d30db8d..03cc561 100644 --- a/docs/system/arm/bananapi_m2u.rst +++ b/docs/system/arm/bananapi_m2u.rst @@ -125,10 +125,10 @@ And then boot it. $ qemu-system-arm -M bpim2u -nographic -sd sd.img -Banana Pi M2U integration tests -""""""""""""""""""""""""""""""" +Banana Pi M2U functional tests +"""""""""""""""""""""""""""""" -The Banana Pi M2U machine has several integration tests included. +The Banana Pi M2U machine has several functional tests included. To run the whole set of tests, build QEMU from source and simply provide the following command: @@ -136,4 +136,4 @@ provide the following command: $ cd qemu-build-dir $ QEMU_TEST_ALLOW_LARGE_STORAGE=1 \ - meson test --suite thorough func-arm-arm_bpim2u + pyvenv/bin/meson test --suite thorough func-arm-arm_bpim2u diff --git a/docs/system/arm/orangepi.rst b/docs/system/arm/orangepi.rst index 8b9448c..d81f6c3 100644 --- a/docs/system/arm/orangepi.rst +++ b/docs/system/arm/orangepi.rst @@ -252,14 +252,14 @@ and set the following environment variables before booting: Optionally you may save the environment variables to SD card with 'saveenv'. To continue booting simply give the 'boot' command and NetBSD boots. -Orange Pi PC integration tests -"""""""""""""""""""""""""""""" +Orange Pi PC functional tests +""""""""""""""""""""""""""""" -The Orange Pi PC machine has several integration tests included. +The Orange Pi PC machine has several functional tests included. To run the whole set of tests, build QEMU from source and simply provide the following command from the build directory: .. code-block:: bash $ QEMU_TEST_ALLOW_LARGE_STORAGE=1 \ - meson test --suite thorough func-arm-arm_orangepi + pyvenv/bin/meson test --suite thorough func-arm-arm_orangepi diff --git a/docs/system/devices/igb.rst b/docs/system/devices/igb.rst index 9145af5..71f31cb 100644 --- a/docs/system/devices/igb.rst +++ b/docs/system/devices/igb.rst @@ -57,11 +57,12 @@ directory: meson test qtest-x86_64/qos-test ethtool can test register accesses, interrupts, etc. It is automated as an -functional test and can be ran with the following command: +functional test and can be run from the build directory with the following +command: .. code:: shell - meson test --suite thorough func-x86_64-netdev_ethtool + pyvenv/bin/meson test --suite thorough func-x86_64-netdev_ethtool References ========== diff --git a/docs/system/devices/net.rst b/docs/system/devices/net.rst index 2ab516d..a3efbdc 100644 --- a/docs/system/devices/net.rst +++ b/docs/system/devices/net.rst @@ -77,6 +77,106 @@ When using the ``'-netdev user,hostfwd=...'`` option, TCP or UDP connections can be redirected from the host to the guest. It allows for example to redirect X11, telnet or SSH connections. +Using passt as the user mode network stack +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +passt_ can be used as a simple replacement for SLIRP (``-net user``). +passt doesn't require any capability or privilege. passt has +better performance than ``-net user``, full IPv6 support and better security +as it's a daemon that is not executed in QEMU context. + +passt can be connected to QEMU either by using a socket +(``-netdev stream``) or using the vhost-user interface (``-netdev vhost-user``). +See `passt(1)`_ for more details on passt. + +.. _passt: https://passt.top/ +.. _passt(1): https://passt.top/builds/latest/web/passt.1.html + +To use socket based passt interface: +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Start passt as a daemon:: + + passt --socket ~/passt.socket + +If ``--socket`` is not provided, passt will print the path of the UNIX domain socket QEMU can connect to (``/tmp/passt_1.socket``, ``/tmp/passt_2.socket``, +...). Then you can connect your QEMU instance to passt: + +.. parsed-literal:: + |qemu_system| [...OPTIONS...] -device virtio-net-pci,netdev=netdev0 -netdev stream,id=netdev0,server=off,addr.type=unix,addr.path=~/passt.socket + +Where ``~/passt.socket`` is the UNIX socket created by passt to +communicate with QEMU. + +To use vhost-based interface: +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Start passt with ``--vhost-user``:: + + passt --vhost-user --socket ~/passt.socket + +Then to connect QEMU: + +.. parsed-literal:: + |qemu_system| [...OPTIONS...] -m $RAMSIZE -chardev socket,id=chr0,path=~/passt.socket -netdev vhost-user,id=netdev0,chardev=chr0 -device virtio-net,netdev=netdev0 -object memory-backend-memfd,id=memfd0,share=on,size=$RAMSIZE -numa node,memdev=memfd0 + +Where ``$RAMSIZE`` is the memory size of your VM ``-m`` and ``-object memory-backend-memfd,size=`` must match. + +Migration of passt: +^^^^^^^^^^^^^^^^^^^ + +When passt is connected to QEMU using the vhost-user interface it can +be migrated with QEMU and the network connections are not interrupted. + +As passt runs with no privileges, it relies on passt-repair to save and +load the TCP connections state, using the TCP_REPAIR socket option. +The passt-repair helper needs to have the CAP_NET_ADMIN capability, or run as root. If passt-repair is not available, TCP connections will not be preserved. + +Example of migration of a guest on the same host +________________________________________________ + +Before being able to run passt-repair, the CAP_NET_ADMIN capability must be set +on the file, run as root:: + + setcap cap_net_admin+eip ./passt-repair + +Start passt for the source side:: + + passt --vhost-user --socket ~/passt_src.socket --repair-path ~/passt-repair_src.socket + +Where ``~/passt-repair_src.socket`` is the UNIX socket created by passt to +communicate with passt-repair. The default value is the ``--socket`` path +appended with ``.repair``. + +Start passt-repair:: + + passt-repair ~/passt-repair_src.socket + +Start source side QEMU with a monitor to be able to send the migrate command: + +.. parsed-literal:: + |qemu_system| [...OPTIONS...] [...VHOST USER OPTIONS...] -monitor stdio + +Start passt for the destination side:: + + passt --vhost-user --socket ~/passt_dst.socket --repair-path ~/passt-repair_dst.socket + +Start passt-repair:: + + passt-repair ~/passt-repair_dst.socket + +Start QEMU with the ``-incoming`` parameter: + +.. parsed-literal:: + |qemu_system| [...OPTIONS...] [...VHOST USER OPTIONS...] -incoming tcp:localhost:4444 + +Then in the source guest monitor the migration can be started:: + + (qemu) migrate tcp:localhost:4444 + +A separate passt-repair instance must be started for every migration. In the case of a failed migration, passt-repair also needs to be restarted before trying +again. + Hubs ~~~~ diff --git a/docs/system/loongarch/virt.rst b/docs/system/loongarch/virt.rst index 172fba0..7845878 100644 --- a/docs/system/loongarch/virt.rst +++ b/docs/system/loongarch/virt.rst @@ -12,14 +12,15 @@ Supported devices ----------------- The ``virt`` machine supports: -- Gpex host bridge -- Ls7a RTC device -- Ls7a IOAPIC device -- ACPI GED device -- Fw_cfg device -- PCI/PCIe devices -- Memory device -- CPU device. Type: la464. + +* Gpex host bridge +* Ls7a RTC device +* Ls7a IOAPIC device +* ACPI GED device +* Fw_cfg device +* PCI/PCIe devices +* Memory device +* CPU device. Type: la464. CPU and machine Type -------------------- @@ -39,13 +40,7 @@ can be accessed by following steps. .. code-block:: bash - ./configure --disable-rdma --prefix=/usr \ - --target-list="loongarch64-softmmu" \ - --disable-libiscsi --disable-libnfs --disable-libpmem \ - --disable-glusterfs --enable-libusb --enable-usb-redir \ - --disable-opengl --disable-xen --enable-spice \ - --enable-debug --disable-capstone --disable-kvm \ - --enable-profiler + ./configure --target-list="loongarch64-softmmu" make -j8 (2) Set cross tools: @@ -53,9 +48,7 @@ can be accessed by following steps. .. code-block:: bash wget https://github.com/loongson/build-tools/releases/download/2022.09.06/loongarch64-clfs-6.3-cross-tools-gcc-glibc.tar.xz - tar -vxf loongarch64-clfs-6.3-cross-tools-gcc-glibc.tar.xz -C /opt - export PATH=/opt/cross-tools/bin:$PATH export LD_LIBRARY_PATH=/opt/cross-tools/lib:$LD_LIBRARY_PATH export LD_LIBRARY_PATH=/opt/cross-tools/loongarch64-unknown-linux-gnu/lib/:$LD_LIBRARY_PATH @@ -74,13 +67,9 @@ Note: To build the release version of the bios, set --buildtarget=RELEASE, .. code-block:: bash git clone https://github.com/loongson/linux.git - cd linux - git checkout loongarch-next - make ARCH=loongarch CROSS_COMPILE=loongarch64-unknown-linux-gnu- loongson3_defconfig - make ARCH=loongarch CROSS_COMPILE=loongarch64-unknown-linux-gnu- -j32 Note: The branch of linux source code is loongarch-next. diff --git a/docs/system/target-loongarch.rst b/docs/system/target-loongarch.rst new file mode 100644 index 0000000..316c604 --- /dev/null +++ b/docs/system/target-loongarch.rst @@ -0,0 +1,19 @@ +.. _LoongArch-System-emulator: + +LoongArch System emulator +------------------------- + +QEMU can emulate loongArch 64 bit systems via the +``qemu-system-loongarch64`` binary. Only one machine type ``virt`` is +supported. + +When using KVM as accelerator, QEMU can emulate la464 cpu model. And when +using the default cpu model with TCG as accelerator, QEMU will emulate a +subset of la464 cpu features that should be enough to run distributions +built for the la464. + +Board-specific documentation +============================ + +.. toctree:: + loongarch/virt diff --git a/docs/system/targets.rst b/docs/system/targets.rst index 224fada..38e2418 100644 --- a/docs/system/targets.rst +++ b/docs/system/targets.rst @@ -18,6 +18,7 @@ Contents: target-arm target-avr + target-loongarch target-m68k target-mips target-ppc diff --git a/host/include/loongarch64/host/atomic128-ldst.h.inc b/host/include/loongarch64/host/atomic128-ldst.h.inc index 9a4a8f8..754d214 100644 --- a/host/include/loongarch64/host/atomic128-ldst.h.inc +++ b/host/include/loongarch64/host/atomic128-ldst.h.inc @@ -28,7 +28,7 @@ static inline Int128 atomic16_read_ro(const Int128 *ptr) asm("vld $vr0, %2, 0\n\t" "vpickve2gr.d %0, $vr0, 0\n\t" "vpickve2gr.d %1, $vr0, 1" - : "=r"(l), "=r"(h) : "r"(ptr), "m"(*ptr) : "f0"); + : "=r"(l), "=r"(h) : "r"(ptr), "m"(*ptr) : "$f0"); return int128_make128(l, h); } @@ -46,7 +46,7 @@ static inline void atomic16_set(Int128 *ptr, Int128 val) asm("vinsgr2vr.d $vr0, %1, 0\n\t" "vinsgr2vr.d $vr0, %2, 1\n\t" "vst $vr0, %3, 0" - : "=m"(*ptr) : "r"(l), "r"(h), "r"(ptr) : "f0"); + : "=m"(*ptr) : "r"(l), "r"(h), "r"(ptr) : "$f0"); } #endif /* LOONGARCH_ATOMIC128_LDST_H */ diff --git a/host/include/loongarch64/host/bufferiszero.c.inc b/host/include/loongarch64/host/bufferiszero.c.inc index 69891ea..bb2598f 100644 --- a/host/include/loongarch64/host/bufferiszero.c.inc +++ b/host/include/loongarch64/host/bufferiszero.c.inc @@ -61,7 +61,8 @@ static bool buffer_is_zero_lsx(const void *buf, size_t len) "2:" : "=&r"(ret), "+r"(p) : "r"(buf), "r"(e), "r"(l) - : "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "fcc0"); + : "$f0", "$f1", "$f2", "$f3", "$f4", "$f5", "$f6", "$f7", "$f8", + "$fcc0"); return ret; } @@ -119,7 +120,8 @@ static bool buffer_is_zero_lasx(const void *buf, size_t len) "3:" : "=&r"(ret), "+r"(p) : "r"(buf), "r"(e), "r"(l) - : "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "fcc0"); + : "$f0", "$f1", "$f2", "$f3", "$f4", "$f5", "$f6", "$f7", "$f8", + "$fcc0"); return ret; } diff --git a/host/include/loongarch64/host/load-extract-al16-al8.h.inc b/host/include/loongarch64/host/load-extract-al16-al8.h.inc index d1fb59d..9528521 100644 --- a/host/include/loongarch64/host/load-extract-al16-al8.h.inc +++ b/host/include/loongarch64/host/load-extract-al16-al8.h.inc @@ -31,7 +31,7 @@ static inline uint64_t load_atom_extract_al16_or_al8(void *pv, int s) asm("vld $vr0, %2, 0\n\t" "vpickve2gr.d %0, $vr0, 0\n\t" "vpickve2gr.d %1, $vr0, 1" - : "=r"(l), "=r"(h) : "r"(ptr_align), "m"(*ptr_align) : "f0"); + : "=r"(l), "=r"(h) : "r"(ptr_align), "m"(*ptr_align) : "$f0"); return (l >> shr) | (h << (-shr & 63)); } diff --git a/hw/intc/aspeed_intc.c b/hw/intc/aspeed_intc.c index 3fd4170..f17bf43 100644 --- a/hw/intc/aspeed_intc.c +++ b/hw/intc/aspeed_intc.c @@ -111,7 +111,7 @@ static void aspeed_intc_set_irq_handler(AspeedINTCState *s, outpin_idx = intc_irq->outpin_idx; inpin_idx = intc_irq->inpin_idx; - if (s->mask[inpin_idx] || s->regs[status_reg]) { + if ((s->mask[inpin_idx] & select) || (s->regs[status_reg] & select)) { /* * a. mask is not 0 means in ISR mode * sources interrupt routine are executing. diff --git a/hw/intc/xive.c b/hw/intc/xive.c index c77df2c..3eb28c2 100644 --- a/hw/intc/xive.c +++ b/hw/intc/xive.c @@ -1662,12 +1662,20 @@ uint32_t xive_get_vpgroup_size(uint32_t nvp_index) * (starting with the least significant bits) in the NVP index * gives the size of the group. */ - return 1 << (ctz32(~nvp_index) + 1); + int first_zero = cto32(nvp_index); + if (first_zero >= 31) { + qemu_log_mask(LOG_GUEST_ERROR, "XIVE: Invalid group index 0x%08x", + nvp_index); + return 0; + } + + return 1U << (first_zero + 1); } static uint8_t xive_get_group_level(bool crowd, bool ignore, uint32_t nvp_blk, uint32_t nvp_index) { + int first_zero; uint8_t level; if (!ignore) { @@ -1675,18 +1683,31 @@ static uint8_t xive_get_group_level(bool crowd, bool ignore, return 0; } - level = (ctz32(~nvp_index) + 1) & 0b1111; + first_zero = cto32(nvp_index); + if (first_zero >= 31) { + qemu_log_mask(LOG_GUEST_ERROR, "XIVE: Invalid group index 0x%08x", + nvp_index); + return 0; + } + + level = (first_zero + 1) & 0b1111; if (crowd) { uint32_t blk; /* crowd level is bit position of first 0 from the right in nvp_blk */ - blk = ctz32(~nvp_blk) + 1; + first_zero = cto32(nvp_blk); + if (first_zero >= 31) { + qemu_log_mask(LOG_GUEST_ERROR, "XIVE: Invalid crowd block 0x%08x", + nvp_blk); + return 0; + } + blk = first_zero + 1; /* * Supported crowd sizes are 2^1, 2^2, and 2^4. 2^3 is not supported. * HW will encode level 4 as the value 3. See xive2_pgofnext(). */ - switch (level) { + switch (blk) { case 1: case 2: break; diff --git a/hw/intc/xive2.c b/hw/intc/xive2.c index f8ef615..7d584df 100644 --- a/hw/intc/xive2.c +++ b/hw/intc/xive2.c @@ -1153,13 +1153,15 @@ static bool xive2_vp_match_mask(uint32_t cam1, uint32_t cam2, static uint8_t xive2_get_vp_block_mask(uint32_t nvt_blk, bool crowd) { - uint8_t size, block_mask = 0b1111; + uint8_t block_mask = 0b1111; /* 3 supported crowd sizes: 2, 4, 16 */ if (crowd) { - size = xive_get_vpgroup_size(nvt_blk); - if (size == 8) { - qemu_log_mask(LOG_GUEST_ERROR, "XIVE: Invalid crowd size of 8n"); + uint32_t size = xive_get_vpgroup_size(nvt_blk); + + if (size != 2 && size != 4 && size != 16) { + qemu_log_mask(LOG_GUEST_ERROR, "XIVE: Invalid crowd size of %d", + size); return block_mask; } block_mask &= ~(size - 1); @@ -1172,7 +1174,14 @@ static uint32_t xive2_get_vp_index_mask(uint32_t nvt_index, bool cam_ignore) uint32_t index_mask = 0xFFFFFF; /* 24 bits */ if (cam_ignore) { - index_mask &= ~(xive_get_vpgroup_size(nvt_index) - 1); + uint32_t size = xive_get_vpgroup_size(nvt_index); + + if (size < 2) { + qemu_log_mask(LOG_GUEST_ERROR, "XIVE: Invalid group size of %d", + size); + return index_mask; + } + index_mask &= ~(size - 1); } return index_mask; } @@ -1335,7 +1344,7 @@ static void xive2_router_end_notify(Xive2Router *xrtr, uint8_t end_blk, return; } - if (xive2_end_is_crowd(&end) & !xive2_end_is_ignore(&end)) { + if (xive2_end_is_crowd(&end) && !xive2_end_is_ignore(&end)) { qemu_log_mask(LOG_GUEST_ERROR, "XIVE: invalid END, 'crowd' bit requires 'ignore' bit\n"); return; diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c index a5840ff..e258642 100644 --- a/hw/loongarch/virt.c +++ b/hw/loongarch/virt.c @@ -38,6 +38,7 @@ #include "hw/mem/nvdimm.h" #include "hw/platform-bus.h" #include "hw/display/ramfb.h" +#include "hw/uefi/var-service-api.h" #include "hw/mem/pc-dimm.h" #include "system/tpm.h" #include "system/block-backend.h" @@ -327,7 +328,6 @@ static void virt_cpu_irq_init(LoongArchVirtMachineState *lvms) MachineClass *mc = MACHINE_GET_CLASS(ms); const CPUArchIdList *possible_cpus; CPUState *cs; - Error *err = NULL; /* cpu nodes */ possible_cpus = mc->possible_cpu_arch_ids(ms); @@ -337,8 +337,10 @@ static void virt_cpu_irq_init(LoongArchVirtMachineState *lvms) continue; } - hotplug_handler_plug(HOTPLUG_HANDLER(lvms->ipi), DEVICE(cs), &err); - hotplug_handler_plug(HOTPLUG_HANDLER(lvms->extioi), DEVICE(cs), &err); + hotplug_handler_plug(HOTPLUG_HANDLER(lvms->ipi), DEVICE(cs), + &error_abort); + hotplug_handler_plug(HOTPLUG_HANDLER(lvms->extioi), DEVICE(cs), + &error_abort); } } @@ -859,30 +861,29 @@ static void virt_cpu_pre_plug(HotplugHandler *hotplug_dev, LoongArchCPU *cpu = LOONGARCH_CPU(dev); CPUState *cs = CPU(dev); CPUArchId *cpu_slot; - Error *err = NULL; LoongArchCPUTopo topo; int arch_id; if (lvms->acpi_ged) { if ((cpu->thread_id < 0) || (cpu->thread_id >= ms->smp.threads)) { - error_setg(&err, + error_setg(errp, "Invalid thread-id %u specified, must be in range 1:%u", cpu->thread_id, ms->smp.threads - 1); - goto out; + return; } if ((cpu->core_id < 0) || (cpu->core_id >= ms->smp.cores)) { - error_setg(&err, + error_setg(errp, "Invalid core-id %u specified, must be in range 1:%u", cpu->core_id, ms->smp.cores - 1); - goto out; + return; } if ((cpu->socket_id < 0) || (cpu->socket_id >= ms->smp.sockets)) { - error_setg(&err, + error_setg(errp, "Invalid socket-id %u specified, must be in range 1:%u", cpu->socket_id, ms->smp.sockets - 1); - goto out; + return; } topo.socket_id = cpu->socket_id; @@ -891,11 +892,11 @@ static void virt_cpu_pre_plug(HotplugHandler *hotplug_dev, arch_id = virt_get_arch_id_from_topo(ms, &topo); cpu_slot = virt_find_cpu_slot(ms, arch_id); if (CPU(cpu_slot->cpu)) { - error_setg(&err, + error_setg(errp, "cpu(id%d=%d:%d:%d) with arch-id %" PRIu64 " exists", cs->cpu_index, cpu->socket_id, cpu->core_id, cpu->thread_id, cpu_slot->arch_id); - goto out; + return; } } else { /* For cold-add cpu, find empty cpu slot */ @@ -911,33 +912,24 @@ static void virt_cpu_pre_plug(HotplugHandler *hotplug_dev, cpu->env.address_space_iocsr = &lvms->as_iocsr; cpu->phy_id = cpu_slot->arch_id; cs->cpu_index = cpu_slot - ms->possible_cpus->cpus; - numa_cpu_pre_plug(cpu_slot, dev, &err); -out: - if (err) { - error_propagate(errp, err); - } + numa_cpu_pre_plug(cpu_slot, dev, errp); } static void virt_cpu_unplug_request(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp) { LoongArchVirtMachineState *lvms = LOONGARCH_VIRT_MACHINE(hotplug_dev); - Error *err = NULL; LoongArchCPU *cpu = LOONGARCH_CPU(dev); CPUState *cs = CPU(dev); if (cs->cpu_index == 0) { - error_setg(&err, "hot-unplug of boot cpu(id%d=%d:%d:%d) not supported", + error_setg(errp, "hot-unplug of boot cpu(id%d=%d:%d:%d) not supported", cs->cpu_index, cpu->socket_id, cpu->core_id, cpu->thread_id); - error_propagate(errp, err); return; } - hotplug_handler_unplug_request(HOTPLUG_HANDLER(lvms->acpi_ged), dev, &err); - if (err) { - error_propagate(errp, err); - } + hotplug_handler_unplug_request(HOTPLUG_HANDLER(lvms->acpi_ged), dev, errp); } static void virt_cpu_unplug(HotplugHandler *hotplug_dev, @@ -1207,6 +1199,7 @@ static void virt_class_init(ObjectClass *oc, void *data) object_class_property_set_description(oc, "v-eiointc", "Enable Virt Extend I/O Interrupt Controller."); machine_class_allow_dynamic_sysbus_dev(mc, TYPE_RAMFB_DEVICE); + machine_class_allow_dynamic_sysbus_dev(mc, TYPE_UEFI_VARS_SYSBUS); #ifdef CONFIG_TPM machine_class_allow_dynamic_sysbus_dev(mc, TYPE_TPM_TIS_SYSBUS); #endif diff --git a/hw/misc/aspeed_hace.c b/hw/misc/aspeed_hace.c index 32a5dbd..d75da33 100644 --- a/hw/misc/aspeed_hace.c +++ b/hw/misc/aspeed_hace.c @@ -128,6 +128,11 @@ static bool has_padding(AspeedHACEState *s, struct iovec *iov, if (*total_msg_len <= s->total_req_len) { uint32_t padding_size = s->total_req_len - *total_msg_len; uint8_t *padding = iov->iov_base; + + if (padding_size > req_len) { + return false; + } + *pad_offset = req_len - padding_size; if (padding[*pad_offset] == 0x80) { return true; diff --git a/hw/ppc/amigaone.c b/hw/ppc/amigaone.c index 4835121..e9407a5 100644 --- a/hw/ppc/amigaone.c +++ b/hw/ppc/amigaone.c @@ -63,7 +63,7 @@ static const char dummy_fw[] = { #define NVRAM_ADDR 0xfd0e0000 #define NVRAM_SIZE (4 * KiB) -static char default_env[] = +static const char default_env[] = "baudrate=115200\0" "stdout=vga\0" "stdin=ps2kbd\0" @@ -108,8 +108,8 @@ static void nvram_write(void *opaque, hwaddr addr, uint64_t val, uint8_t *p = memory_region_get_ram_ptr(&s->mr); p[addr] = val; - if (s->blk) { - blk_pwrite(s->blk, addr, 1, &val, 0); + if (s->blk && blk_pwrite(s->blk, addr, 1, &val, 0) < 0) { + error_report("%s: could not write %s", __func__, blk_name(s->blk)); } } @@ -151,15 +151,17 @@ static void nvram_realize(DeviceState *dev, Error **errp) *c = cpu_to_be32(CRC32_DEFAULT_ENV); /* Also copies terminating \0 as env is terminated by \0\0 */ memcpy(p + 4, default_env, sizeof(default_env)); - if (s->blk) { - blk_pwrite(s->blk, 0, sizeof(crc) + sizeof(default_env), p, 0); + if (s->blk && + blk_pwrite(s->blk, 0, sizeof(crc) + sizeof(default_env), p, 0) < 0 + ) { + error_report("%s: could not write %s", __func__, blk_name(s->blk)); } return; } if (*c == 0) { *c = cpu_to_be32(crc32(0, p + 4, NVRAM_SIZE - 4)); - if (s->blk) { - blk_pwrite(s->blk, 0, 4, p, 0); + if (s->blk && blk_pwrite(s->blk, 0, 4, p, 0) < 0) { + error_report("%s: could not write %s", __func__, blk_name(s->blk)); } } if (be32_to_cpu(*c) != crc) { diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c index 5936537..63f2232 100644 --- a/hw/ppc/pnv.c +++ b/hw/ppc/pnv.c @@ -1191,7 +1191,7 @@ static void pnv_init(MachineState *machine) * Since we can not reach the remote BMC machine with LPC memops, * map it always for now. */ - memory_region_add_subregion(pnv->chips[0]->fw_mr, PNOR_SPI_OFFSET, + memory_region_add_subregion(pnv->chips[0]->fw_mr, pnv->pnor->lpc_address, &pnv->pnor->mmio); /* diff --git a/hw/ppc/pnv_bmc.c b/hw/ppc/pnv_bmc.c index 811ba3d..fb70a8c 100644 --- a/hw/ppc/pnv_bmc.c +++ b/hw/ppc/pnv_bmc.c @@ -174,8 +174,8 @@ static void hiomap_cmd(IPMIBmcSim *ibs, uint8_t *cmd, unsigned int cmd_len, { PnvPnor *pnor = PNV_PNOR(object_property_get_link(OBJECT(ibs), "pnor", &error_abort)); + uint32_t pnor_addr = pnor->lpc_address; uint32_t pnor_size = pnor->size; - uint32_t pnor_addr = PNOR_SPI_OFFSET; bool readonly = false; rsp_buffer_push(rsp, cmd[2]); @@ -251,8 +251,8 @@ static const IPMINetfn hiomap_netfn = { void pnv_bmc_set_pnor(IPMIBmc *bmc, PnvPnor *pnor) { + uint32_t pnor_addr = pnor->lpc_address; uint32_t pnor_size = pnor->size; - uint32_t pnor_addr = PNOR_SPI_OFFSET; if (!pnv_bmc_is_simulator(bmc)) { return; diff --git a/hw/ppc/pnv_core.c b/hw/ppc/pnv_core.c index 99d9644..a33977d 100644 --- a/hw/ppc/pnv_core.c +++ b/hw/ppc/pnv_core.c @@ -248,21 +248,25 @@ static void pnv_core_power10_xscom_write(void *opaque, hwaddr addr, if (val & PPC_BIT(7 + 8 * i)) { /* stop */ val &= ~PPC_BIT(7 + 8 * i); - cpu_pause(cs); env->quiesced = true; + ppc_maybe_interrupt(env); + cpu_pause(cs); } if (val & PPC_BIT(6 + 8 * i)) { /* start */ val &= ~PPC_BIT(6 + 8 * i); env->quiesced = false; + ppc_maybe_interrupt(env); cpu_resume(cs); } if (val & PPC_BIT(4 + 8 * i)) { /* sreset */ val &= ~PPC_BIT(4 + 8 * i); env->quiesced = false; + ppc_maybe_interrupt(env); pnv_cpu_do_nmi_resume(cs); } if (val & PPC_BIT(3 + 8 * i)) { /* clear maint */ env->quiesced = false; + ppc_maybe_interrupt(env); /* * Hardware has very particular cases for where clear maint * must be used and where start must be used to resume a diff --git a/hw/ppc/pnv_occ.c b/hw/ppc/pnv_occ.c index bda6b23..177c5e5 100644 --- a/hw/ppc/pnv_occ.c +++ b/hw/ppc/pnv_occ.c @@ -364,7 +364,12 @@ static void pnv_occ_register_types(void) type_init(pnv_occ_register_types); -/* From skiboot/hw/occ.c with tab to space conversion */ +/* + * From skiboot/hw/occ.c with following changes: + * - tab to space conversion + * - Type conversions u8->uint8_t s8->int8_t __be16->uint16_t etc + * - __packed -> QEMU_PACKED + */ /* OCC Communication Area for PStates */ #define OPAL_DYNAMIC_DATA_OFFSET 0x0B80 @@ -384,20 +389,6 @@ type_init(pnv_occ_register_types); #define FREQ_MAX_IN_DOMAIN 0 #define FREQ_MOST_RECENTLY_SET 1 -#define u8 uint8_t -#define s8 int8_t -#define u16 uint16_t -#define s16 int16_t -#define u32 uint32_t -#define s32 int32_t -#define u64 uint64_t -#define s64 int64_t -#define __be16 uint16_t -#define __be32 uint32_t -#ifndef __packed -#define __packed QEMU_PACKED -#endif /* !__packed */ - /** * OCC-OPAL Shared Memory Region * @@ -434,69 +425,69 @@ type_init(pnv_occ_register_types); * @spare/reserved/pad: Unused data */ struct occ_pstate_table { - u8 valid; - u8 version; - union __packed { - struct __packed { /* Version 0x01 and 0x02 */ - u8 throttle; - s8 pstate_min; - s8 pstate_nom; - s8 pstate_turbo; - s8 pstate_ultra_turbo; - u8 spare; - u64 reserved; - struct __packed { - s8 id; - u8 flags; - u8 vdd; - u8 vcs; - __be32 freq_khz; + uint8_t valid; + uint8_t version; + union QEMU_PACKED { + struct QEMU_PACKED { /* Version 0x01 and 0x02 */ + uint8_t throttle; + int8_t pstate_min; + int8_t pstate_nom; + int8_t pstate_turbo; + int8_t pstate_ultra_turbo; + uint8_t spare; + uint64_t reserved; + struct QEMU_PACKED { + int8_t id; + uint8_t flags; + uint8_t vdd; + uint8_t vcs; + uint32_t freq_khz; } pstates[MAX_PSTATES]; - s8 core_max[MAX_P8_CORES]; - u8 pad[100]; + int8_t core_max[MAX_P8_CORES]; + uint8_t pad[100]; } v2; - struct __packed { /* Version 0x90 */ - u8 occ_role; - u8 pstate_min; - u8 pstate_nom; - u8 pstate_turbo; - u8 pstate_ultra_turbo; - u8 spare; - u64 reserved1; - u64 reserved2; - struct __packed { - u8 id; - u8 flags; - u16 reserved; - __be32 freq_khz; + struct QEMU_PACKED { /* Version 0x90 */ + uint8_t occ_role; + uint8_t pstate_min; + uint8_t pstate_nom; + uint8_t pstate_turbo; + uint8_t pstate_ultra_turbo; + uint8_t spare; + uint64_t reserved1; + uint64_t reserved2; + struct QEMU_PACKED { + uint8_t id; + uint8_t flags; + uint16_t reserved; + uint32_t freq_khz; } pstates[MAX_PSTATES]; - u8 core_max[MAX_P9_CORES]; - u8 pad[56]; + uint8_t core_max[MAX_P9_CORES]; + uint8_t pad[56]; } v9; - struct __packed { /* Version 0xA0 */ - u8 occ_role; - u8 pstate_min; - u8 pstate_fixed_freq; - u8 pstate_base; - u8 pstate_ultra_turbo; - u8 pstate_fmax; - u8 minor; - u8 pstate_bottom_throttle; - u8 spare; - u8 spare1; - u32 reserved_32; - u64 reserved_64; - struct __packed { - u8 id; - u8 valid; - u16 reserved; - __be32 freq_khz; + struct QEMU_PACKED { /* Version 0xA0 */ + uint8_t occ_role; + uint8_t pstate_min; + uint8_t pstate_fixed_freq; + uint8_t pstate_base; + uint8_t pstate_ultra_turbo; + uint8_t pstate_fmax; + uint8_t minor; + uint8_t pstate_bottom_throttle; + uint8_t spare; + uint8_t spare1; + uint32_t reserved_32; + uint64_t reserved_64; + struct QEMU_PACKED { + uint8_t id; + uint8_t valid; + uint16_t reserved; + uint32_t freq_khz; } pstates[MAX_PSTATES]; - u8 core_max[MAX_P10_CORES]; - u8 pad[48]; + uint8_t core_max[MAX_P10_CORES]; + uint8_t pad[48]; } v10; }; -} __packed; +} QEMU_PACKED; /** * OPAL-OCC Command Response Interface @@ -531,13 +522,13 @@ struct occ_pstate_table { * @spare: Unused byte */ struct opal_command_buffer { - u8 flag; - u8 request_id; - u8 cmd; - u8 spare; - __be16 data_size; - u8 data[MAX_OPAL_CMD_DATA_LENGTH]; -} __packed; + uint8_t flag; + uint8_t request_id; + uint8_t cmd; + uint8_t spare; + uint16_t data_size; + uint8_t data[MAX_OPAL_CMD_DATA_LENGTH]; +} QEMU_PACKED; /** * OPAL-OCC Response Buffer @@ -571,13 +562,13 @@ struct opal_command_buffer { * @data: Response specific data */ struct occ_response_buffer { - u8 flag; - u8 request_id; - u8 cmd; - u8 status; - __be16 data_size; - u8 data[MAX_OCC_RSP_DATA_LENGTH]; -} __packed; + uint8_t flag; + uint8_t request_id; + uint8_t cmd; + uint8_t status; + uint16_t data_size; + uint8_t data[MAX_OCC_RSP_DATA_LENGTH]; +} QEMU_PACKED; /** * OCC-OPAL Shared Memory Interface Dynamic Data Vx90 @@ -608,31 +599,31 @@ struct occ_response_buffer { * @rsp: OCC Response Buffer */ struct occ_dynamic_data { - u8 occ_state; - u8 major_version; - u8 minor_version; - u8 gpus_present; - union __packed { - struct __packed { /* Version 0x90 */ - u8 spare1; + uint8_t occ_state; + uint8_t major_version; + uint8_t minor_version; + uint8_t gpus_present; + union QEMU_PACKED { + struct QEMU_PACKED { /* Version 0x90 */ + uint8_t spare1; } v9; - struct __packed { /* Version 0xA0 */ - u8 wof_enabled; + struct QEMU_PACKED { /* Version 0xA0 */ + uint8_t wof_enabled; } v10; }; - u8 cpu_throttle; - u8 mem_throttle; - u8 quick_pwr_drop; - u8 pwr_shifting_ratio; - u8 pwr_cap_type; - __be16 hard_min_pwr_cap; - __be16 max_pwr_cap; - __be16 cur_pwr_cap; - __be16 soft_min_pwr_cap; - u8 pad[110]; + uint8_t cpu_throttle; + uint8_t mem_throttle; + uint8_t quick_pwr_drop; + uint8_t pwr_shifting_ratio; + uint8_t pwr_cap_type; + uint16_t hard_min_pwr_cap; + uint16_t max_pwr_cap; + uint16_t cur_pwr_cap; + uint16_t soft_min_pwr_cap; + uint8_t pad[110]; struct opal_command_buffer cmd; struct occ_response_buffer rsp; -} __packed; +} QEMU_PACKED; enum occ_response_status { OCC_RSP_SUCCESS = 0x00, diff --git a/hw/ppc/pnv_pnor.c b/hw/ppc/pnv_pnor.c index 863e2e7..9db44ca 100644 --- a/hw/ppc/pnv_pnor.c +++ b/hw/ppc/pnv_pnor.c @@ -108,6 +108,8 @@ static void pnv_pnor_realize(DeviceState *dev, Error **errp) memset(s->storage, 0xFF, s->size); } + s->lpc_address = PNOR_SPI_OFFSET; + memory_region_init_io(&s->mmio, OBJECT(s), &pnv_pnor_ops, s, TYPE_PNV_PNOR, s->size); } diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index a415e51..b0a0f8c 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -296,6 +296,7 @@ static void spapr_dt_pa_features(SpaprMachineState *spapr, pa_features[40 + 2] &= ~0x80; /* Radix MMU */ } if (spapr_get_cap(spapr, SPAPR_CAP_DAWR1)) { + g_assert(pa_size > 66); pa_features[66] |= 0x80; } @@ -4815,6 +4816,7 @@ static void spapr_machine_8_2_class_options(MachineClass *mc) { spapr_machine_9_0_class_options(mc); compat_props_add(mc->compat_props, hw_compat_8_2, hw_compat_8_2_len); + mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power9_v2.2"); } DEFINE_SPAPR_MACHINE(8, 2); diff --git a/hw/ppc/spapr_cpu_core.c b/hw/ppc/spapr_cpu_core.c index 0671d9e..faf9170 100644 --- a/hw/ppc/spapr_cpu_core.c +++ b/hw/ppc/spapr_cpu_core.c @@ -37,6 +37,9 @@ static void spapr_reset_vcpu(PowerPCCPU *cpu) cpu_reset(cs); + env->quiesced = true; /* set "RTAS stopped" state. */ + ppc_maybe_interrupt(env); + /* * "PowerPC Processor binding to IEEE 1275" defines the initial MSR state * as 32bit (MSR_SF=0) with MSR_ME=1 and MSR_FP=1 in "8.2.1. Initial @@ -98,6 +101,9 @@ void spapr_cpu_set_entry_state(PowerPCCPU *cpu, target_ulong nip, CPU(cpu)->halted = 0; /* Enable Power-saving mode Exit Cause exceptions */ ppc_store_lpcr(cpu, env->spr[SPR_LPCR] | pcc->lpcr_pm); + + env->quiesced = false; /* clear "RTAS stopped" state. */ + ppc_maybe_interrupt(env); } /* diff --git a/hw/ppc/spapr_rtas.c b/hw/ppc/spapr_rtas.c index 503d441..78309db 100644 --- a/hw/ppc/spapr_rtas.c +++ b/hw/ppc/spapr_rtas.c @@ -110,7 +110,8 @@ static void rtas_query_cpu_stopped_state(PowerPCCPU *cpu_, id = rtas_ld(args, 0); cpu = spapr_find_cpu(id); if (cpu != NULL) { - if (CPU(cpu)->halted) { + CPUPPCState *env = &cpu->env; + if (env->quiesced) { rtas_st(rets, 1, 0); } else { rtas_st(rets, 1, 2); @@ -215,6 +216,8 @@ static void rtas_stop_self(PowerPCCPU *cpu, SpaprMachineState *spapr, * For the same reason, set PSSCR_EC. */ env->spr[SPR_PSSCR] |= PSSCR_EC; + env->quiesced = true; /* set "RTAS stopped" state. */ + ppc_maybe_interrupt(env); cs->halted = 1; ppc_store_lpcr(cpu, env->spr[SPR_LPCR] & ~pcc->lpcr_pm); kvmppc_set_reg_ppc_online(cpu, 0); diff --git a/hw/riscv/riscv-iommu-bits.h b/hw/riscv/riscv-iommu-bits.h index b7cb1bc..1017d73 100644 --- a/hw/riscv/riscv-iommu-bits.h +++ b/hw/riscv/riscv-iommu-bits.h @@ -415,12 +415,16 @@ enum riscv_iommu_fq_causes { #define RISCV_IOMMU_DC_MSIPTP_MODE_OFF 0 #define RISCV_IOMMU_DC_MSIPTP_MODE_FLAT 1 +/* 2.2 Process Directory Table */ +#define RISCV_IOMMU_PDTE_VALID BIT_ULL(0) +#define RISCV_IOMMU_PDTE_PPN RISCV_IOMMU_PPN_FIELD + /* Translation attributes fields */ #define RISCV_IOMMU_PC_TA_V BIT_ULL(0) #define RISCV_IOMMU_PC_TA_RESERVED GENMASK_ULL(63, 32) /* First stage context fields */ -#define RISCV_IOMMU_PC_FSC_PPN GENMASK_ULL(43, 0) +#define RISCV_IOMMU_PC_FSC_PPN RISCV_IOMMU_ATP_PPN_FIELD #define RISCV_IOMMU_PC_FSC_RESERVED GENMASK_ULL(59, 44) enum riscv_iommu_fq_ttypes { diff --git a/hw/riscv/riscv-iommu.c b/hw/riscv/riscv-iommu.c index d46beb2..76e0fcd 100644 --- a/hw/riscv/riscv-iommu.c +++ b/hw/riscv/riscv-iommu.c @@ -1042,10 +1042,10 @@ static int riscv_iommu_ctx_fetch(RISCVIOMMUState *s, RISCVIOMMUContext *ctx) return RISCV_IOMMU_FQ_CAUSE_PDT_LOAD_FAULT; } le64_to_cpus(&de); - if (!(de & RISCV_IOMMU_PC_TA_V)) { + if (!(de & RISCV_IOMMU_PDTE_VALID)) { return RISCV_IOMMU_FQ_CAUSE_PDT_INVALID; } - addr = PPN_PHYS(get_field(de, RISCV_IOMMU_PC_FSC_PPN)); + addr = PPN_PHYS(get_field(de, RISCV_IOMMU_PDTE_PPN)); } riscv_iommu_hpm_incr_ctr(s, ctx, RISCV_IOMMU_HPMEVENT_PD_WALK); diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c index dae46f4..e517002 100644 --- a/hw/riscv/virt.c +++ b/hw/riscv/virt.c @@ -57,6 +57,7 @@ #include "hw/acpi/aml-build.h" #include "qapi/qapi-visit-common.h" #include "hw/virtio/virtio-iommu.h" +#include "hw/uefi/var-service-api.h" /* KVM AIA only supports APLIC MSI. APLIC Wired is always emulated by QEMU. */ static bool virt_use_kvm_aia_aplic_imsic(RISCVVirtAIAType aia_type) @@ -1935,6 +1936,7 @@ static void virt_machine_class_init(ObjectClass *oc, void *data) hc->plug = virt_machine_device_plug_cb; machine_class_allow_dynamic_sysbus_dev(mc, TYPE_RAMFB_DEVICE); + machine_class_allow_dynamic_sysbus_dev(mc, TYPE_UEFI_VARS_SYSBUS); #ifdef CONFIG_TPM machine_class_allow_dynamic_sysbus_dev(mc, TYPE_TPM_TIS_SYSBUS); #endif diff --git a/hw/uefi/Kconfig b/hw/uefi/Kconfig index ca6c2bc..046d553 100644 --- a/hw/uefi/Kconfig +++ b/hw/uefi/Kconfig @@ -1,3 +1,3 @@ config UEFI_VARS bool - default y if X86_64 || AARCH64 + default y if X86_64 || AARCH64 || RISCV64 || LOONGARCH64 diff --git a/hw/uefi/var-service-core.c b/hw/uefi/var-service-core.c index 8ed8378..4836a0c 100644 --- a/hw/uefi/var-service-core.c +++ b/hw/uefi/var-service-core.c @@ -29,6 +29,7 @@ static int uefi_vars_post_load(void *opaque, int version_id) uefi_vars_state *uv = opaque; uefi_vars_update_storage(uv); + uefi_vars_json_save(uv); uv->buffer = g_malloc(uv->buf_size); return 0; } diff --git a/hw/uefi/var-service-json.c b/hw/uefi/var-service-json.c index 761082c..ad3462c 100644 --- a/hw/uefi/var-service-json.c +++ b/hw/uefi/var-service-json.c @@ -178,7 +178,7 @@ void uefi_vars_json_init(uefi_vars_state *uv, Error **errp) void uefi_vars_json_save(uefi_vars_state *uv) { - GString *gstr; + g_autoptr(GString) gstr = NULL; int rc; if (uv->jsonfd == -1) { @@ -187,18 +187,25 @@ void uefi_vars_json_save(uefi_vars_state *uv) gstr = uefi_vars_to_json(uv); - lseek(uv->jsonfd, 0, SEEK_SET); + rc = lseek(uv->jsonfd, 0, SEEK_SET); + if (rc < 0) { + warn_report("%s: lseek error", __func__); + return; + } + rc = ftruncate(uv->jsonfd, 0); if (rc != 0) { warn_report("%s: ftruncate error", __func__); + return; } + rc = write(uv->jsonfd, gstr->str, gstr->len); if (rc != gstr->len) { warn_report("%s: write error", __func__); + return; } - fsync(uv->jsonfd); - g_string_free(gstr, true); + fsync(uv->jsonfd); } void uefi_vars_json_load(uefi_vars_state *uv, Error **errp) @@ -207,7 +214,7 @@ void uefi_vars_json_load(uefi_vars_state *uv, Error **errp) QObject *qobj; Visitor *v; char *str; - size_t len; + ssize_t len; int rc; if (uv->jsonfd == -1) { @@ -215,7 +222,12 @@ void uefi_vars_json_load(uefi_vars_state *uv, Error **errp) } len = lseek(uv->jsonfd, 0, SEEK_END); + if (len < 0) { + warn_report("%s: lseek error", __func__); + return; + } if (len == 0) { + /* empty file */ return; } @@ -224,6 +236,8 @@ void uefi_vars_json_load(uefi_vars_state *uv, Error **errp) rc = read(uv->jsonfd, str, len); if (rc != len) { warn_report("%s: read error", __func__); + g_free(str); + return; } str[len] = 0; diff --git a/hw/virtio/meson.build b/hw/virtio/meson.build index 19b04c4..164f6fd 100644 --- a/hw/virtio/meson.build +++ b/hw/virtio/meson.build @@ -90,7 +90,8 @@ specific_virtio_ss.add_all(when: 'CONFIG_VIRTIO_PCI', if_true: virtio_pci_ss) system_ss.add_all(when: 'CONFIG_VIRTIO', if_true: system_virtio_ss) system_ss.add(when: 'CONFIG_VIRTIO', if_false: files('vhost-stub.c')) system_ss.add(when: 'CONFIG_VIRTIO', if_false: files('virtio-stub.c')) -system_ss.add(when: 'CONFIG_VIRTIO_MD', if_false: files('virtio-md-stubs.c')) +system_ss.add(when: ['CONFIG_VIRTIO_MD', 'CONFIG_VIRTIO_PCI'], + if_false: files('virtio-md-stubs.c')) system_ss.add(files('virtio-hmp-cmds.c')) diff --git a/hw/xen/xen-bus.c b/hw/xen/xen-bus.c index 8260f1e..f808a01 100644 --- a/hw/xen/xen-bus.c +++ b/hw/xen/xen-bus.c @@ -353,10 +353,10 @@ static void xen_bus_realize(BusState *bus, Error **errp) xs_node_watch(xenbus->xsh, node, key, xen_bus_backend_changed, xenbus, &local_err); if (local_err) { - /* This need not be treated as a hard error so don't propagate */ - error_reportf_err(local_err, - "failed to set up '%s' enumeration watch: ", - type[i]); + warn_reportf_err(local_err, + "failed to set up '%s' enumeration watch: ", + type[i]); + local_err = NULL; } g_free(node); diff --git a/include/hw/arm/aspeed_soc.h b/include/hw/arm/aspeed_soc.h index f899356..f069d17 100644 --- a/include/hw/arm/aspeed_soc.h +++ b/include/hw/arm/aspeed_soc.h @@ -42,7 +42,7 @@ #include "hw/char/serial-mm.h" #include "hw/intc/arm_gicv3.h" -#define ASPEED_SPIS_NUM 2 +#define ASPEED_SPIS_NUM 3 #define ASPEED_EHCIS_NUM 2 #define ASPEED_WDTS_NUM 8 #define ASPEED_CPUS_NUM 4 diff --git a/include/hw/ppc/pnv_pnor.h b/include/hw/ppc/pnv_pnor.h index 19c2d64..b44cafe 100644 --- a/include/hw/ppc/pnv_pnor.h +++ b/include/hw/ppc/pnv_pnor.h @@ -28,6 +28,7 @@ struct PnvPnor { BlockBackend *blk; uint8_t *storage; + uint32_t lpc_address; /* Offset within LPC FW space */ int64_t size; MemoryRegion mmio; }; diff --git a/linux-user/syscall.c b/linux-user/syscall.c index b32de76..8bfe491 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -9119,35 +9119,38 @@ static void risc_hwprobe_fill_pairs(CPURISCVState *env, } } -static int cpu_set_valid(abi_long arg3, abi_long arg4) +/* + * If the cpumask_t of (target_cpus, cpusetsize) cannot be read: -EFAULT. + * If the cpumast_t has no bits set: -EINVAL. + * Otherwise the cpumask_t contains some bit set: 0. + * Unlike the kernel, we do not mask cpumask_t by the set of online cpus, + * nor bound the search by cpumask_size(). + */ +static int nonempty_cpu_set(abi_ulong cpusetsize, abi_ptr target_cpus) { - int ret, i, tmp; - size_t host_mask_size, target_mask_size; - unsigned long *host_mask; - - /* - * cpu_set_t represent CPU masks as bit masks of type unsigned long *. - * arg3 contains the cpu count. - */ - tmp = (8 * sizeof(abi_ulong)); - target_mask_size = ((arg3 + tmp - 1) / tmp) * sizeof(abi_ulong); - host_mask_size = (target_mask_size + (sizeof(*host_mask) - 1)) & - ~(sizeof(*host_mask) - 1); - - host_mask = alloca(host_mask_size); - - ret = target_to_host_cpu_mask(host_mask, host_mask_size, - arg4, target_mask_size); - if (ret != 0) { - return ret; - } + unsigned char *p = lock_user(VERIFY_READ, target_cpus, cpusetsize, 1); + int ret = -TARGET_EFAULT; - for (i = 0 ; i < host_mask_size / sizeof(*host_mask); i++) { - if (host_mask[i] != 0) { - return 0; + if (p) { + ret = -TARGET_EINVAL; + /* + * Since we only care about the empty/non-empty state of the cpumask_t + * not the individual bits, we do not need to repartition the bits + * from target abi_ulong to host unsigned long. + * + * Note that the kernel does not round up cpusetsize to a multiple of + * sizeof(abi_ulong). After bounding cpusetsize by cpumask_size(), + * it copies exactly cpusetsize bytes into a zeroed buffer. + */ + for (abi_ulong i = 0; i < cpusetsize; ++i) { + if (p[i]) { + ret = 0; + break; + } } + unlock_user(p, target_cpus, 0); } - return -TARGET_EINVAL; + return ret; } static abi_long do_riscv_hwprobe(CPUArchState *cpu_env, abi_long arg1, @@ -9164,7 +9167,7 @@ static abi_long do_riscv_hwprobe(CPUArchState *cpu_env, abi_long arg1, /* check cpu_set */ if (arg3 != 0) { - ret = cpu_set_valid(arg3, arg4); + ret = nonempty_cpu_set(arg3, arg4); if (ret != 0) { return ret; } diff --git a/net/vmnet-common.m b/net/vmnet-common.m index 54d900b..ab33ce2 100644 --- a/net/vmnet-common.m +++ b/net/vmnet-common.m @@ -94,7 +94,7 @@ ssize_t vmnet_receive_common(NetClientState *nc, if_status = vmnet_write(s->vmnet_if, &packet, &pkt_cnt); if (if_status != VMNET_SUCCESS) { - error_report("vmnet: write error: %s\n", + error_report("vmnet: write error: %s", vmnet_status_map_str(if_status)); return -1; } diff --git a/system/physmem.c b/system/physmem.c index e97de3e..333a5eb 100644 --- a/system/physmem.c +++ b/system/physmem.c @@ -158,6 +158,7 @@ static void io_mem_init(void); static void memory_map_init(void); static void tcg_log_global_after_sync(MemoryListener *listener); static void tcg_commit(MemoryListener *listener); +static bool ram_is_cpr_compatible(RAMBlock *rb); /** * CPUAddressSpace: all the information a CPU needs about an AddressSpace @@ -1908,13 +1909,18 @@ static void ram_block_add(RAMBlock *new_block, Error **errp) goto out_free; } - error_setg(&new_block->cpr_blocker, - "Memory region %s uses guest_memfd, " - "which is not supported with CPR.", - memory_region_name(new_block->mr)); - migrate_add_blocker_modes(&new_block->cpr_blocker, errp, - MIG_MODE_CPR_TRANSFER, - -1); + /* + * Add a specific guest_memfd blocker if a generic one would not be + * added by ram_block_add_cpr_blocker. + */ + if (ram_is_cpr_compatible(new_block)) { + error_setg(&new_block->cpr_blocker, + "Memory region %s uses guest_memfd, " + "which is not supported with CPR.", + memory_region_name(new_block->mr)); + migrate_add_blocker_modes(&new_block->cpr_blocker, errp, + MIG_MODE_CPR_TRANSFER, -1); + } } ram_size = (new_block->offset + new_block->max_length) >> TARGET_PAGE_BITS; diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h index eae874c..254e4fb 100644 --- a/target/loongarch/cpu.h +++ b/target/loongarch/cpu.h @@ -426,6 +426,7 @@ struct ArchCPU { const char *dtb_compatible; /* used by KVM_REG_LOONGARCH_COUNTER ioctl to access guest time counters */ uint64_t kvm_state_counter; + VMChangeStateEntry *vmsentry; }; /** diff --git a/target/loongarch/internals.h b/target/loongarch/internals.h index 1cd959a..9fdc305 100644 --- a/target/loongarch/internals.h +++ b/target/loongarch/internals.h @@ -43,7 +43,7 @@ enum { TLBRET_PE = 7, }; -bool check_ps(CPULoongArchState *ent, int ps); +bool check_ps(CPULoongArchState *ent, uint8_t ps); extern const VMStateDescription vmstate_loongarch_cpu; diff --git a/target/loongarch/kvm/kvm.c b/target/loongarch/kvm/kvm.c index 28735c8..f0e3cfe 100644 --- a/target/loongarch/kvm/kvm.c +++ b/target/loongarch/kvm/kvm.c @@ -1080,9 +1080,10 @@ int kvm_arch_init_vcpu(CPUState *cs) uint64_t val; int ret; Error *local_err = NULL; + LoongArchCPU *cpu = LOONGARCH_CPU(cs); - ret = 0; - qemu_add_vm_change_state_handler(kvm_loongarch_vm_stage_change, cs); + cpu->vmsentry = qemu_add_vm_change_state_handler( + kvm_loongarch_vm_stage_change, cs); if (!kvm_get_one_reg(cs, KVM_REG_LOONGARCH_DEBUG_INST, &val)) { brk_insn = val; @@ -1091,29 +1092,34 @@ int kvm_arch_init_vcpu(CPUState *cs) ret = kvm_cpu_check_lsx(cs, &local_err); if (ret < 0) { error_report_err(local_err); + return ret; } ret = kvm_cpu_check_lasx(cs, &local_err); if (ret < 0) { error_report_err(local_err); + return ret; } ret = kvm_cpu_check_lbt(cs, &local_err); if (ret < 0) { error_report_err(local_err); + return ret; } ret = kvm_cpu_check_pmu(cs, &local_err); if (ret < 0) { error_report_err(local_err); + return ret; } ret = kvm_cpu_check_pv_features(cs, &local_err); if (ret < 0) { error_report_err(local_err); + return ret; } - return ret; + return 0; } static bool loongarch_get_lbt(Object *obj, Error **errp) @@ -1193,6 +1199,9 @@ void kvm_loongarch_cpu_post_init(LoongArchCPU *cpu) int kvm_arch_destroy_vcpu(CPUState *cs) { + LoongArchCPU *cpu = LOONGARCH_CPU(cs); + + qemu_del_vm_change_state_handler(cpu->vmsentry); return 0; } diff --git a/target/loongarch/tcg/csr_helper.c b/target/loongarch/tcg/csr_helper.c index 379c71e..6a7a65c 100644 --- a/target/loongarch/tcg/csr_helper.c +++ b/target/loongarch/tcg/csr_helper.c @@ -115,7 +115,7 @@ target_ulong helper_csrwr_ticlr(CPULoongArchState *env, target_ulong val) target_ulong helper_csrwr_pwcl(CPULoongArchState *env, target_ulong val) { - int shift, ptbase; + uint8_t shift, ptbase; int64_t old_v = env->CSR_PWCL; /* diff --git a/target/loongarch/tcg/tlb_helper.c b/target/loongarch/tcg/tlb_helper.c index 646dbf5..70d1b5c 100644 --- a/target/loongarch/tcg/tlb_helper.c +++ b/target/loongarch/tcg/tlb_helper.c @@ -19,12 +19,12 @@ #include "exec/log.h" #include "cpu-csr.h" -bool check_ps(CPULoongArchState *env, int tlb_ps) +bool check_ps(CPULoongArchState *env, uint8_t tlb_ps) { - if (tlb_ps > 64) { - return false; - } - return BIT_ULL(tlb_ps) & (env->CSR_PRCFG2); + if (tlb_ps >= 64) { + return false; + } + return BIT_ULL(tlb_ps) & (env->CSR_PRCFG2); } void get_dir_base_width(CPULoongArchState *env, uint64_t *dir_base, @@ -543,7 +543,7 @@ target_ulong helper_lddir(CPULoongArchState *env, target_ulong base, target_ulong level, uint32_t mem_idx) { CPUState *cs = env_cpu(env); - target_ulong badvaddr, index, phys, ret; + target_ulong badvaddr, index, phys; uint64_t dir_base, dir_width; if (unlikely((level == 0) || (level > 4))) { @@ -571,8 +571,7 @@ target_ulong helper_lddir(CPULoongArchState *env, target_ulong base, get_dir_base_width(env, &dir_base, &dir_width, level); index = (badvaddr >> dir_base) & ((1 << dir_width) - 1); phys = base | index << 3; - ret = ldq_phys(cs->as, phys) & TARGET_PHYS_MASK; - return ret; + return ldq_phys(cs->as, phys) & TARGET_PHYS_MASK; } void helper_ldpte(CPULoongArchState *env, target_ulong base, target_ulong odd, diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h index efab54a..3ee8351 100644 --- a/target/ppc/cpu.h +++ b/target/ppc/cpu.h @@ -1356,6 +1356,17 @@ struct CPUArchState { * special way (such as routing some resume causes to 0x100, i.e. sreset). */ bool resume_as_sreset; + + /* + * On powernv, quiesced means the CPU has been stopped using PC direct + * control xscom registers. + * + * On spapr, quiesced means it is in the "RTAS stopped" state. + * + * The core halted/stopped variables aren't sufficient for this, because + * they can be changed with various side-band operations like qmp cont, + * powersave interrupts, etc. + */ bool quiesced; #endif diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c index 8b590e7..7decc09 100644 --- a/target/ppc/cpu_init.c +++ b/target/ppc/cpu_init.c @@ -2744,14 +2744,6 @@ static void init_proc_e200(CPUPPCState *env) SPR_NOACCESS, SPR_NOACCESS, &spr_read_generic, &spr_write_generic, 0x00000000); /* TOFIX */ - spr_register(env, SPR_BOOKE_DSRR0, "DSRR0", - SPR_NOACCESS, SPR_NOACCESS, - &spr_read_generic, &spr_write_generic, - 0x00000000); - spr_register(env, SPR_BOOKE_DSRR1, "DSRR1", - SPR_NOACCESS, SPR_NOACCESS, - &spr_read_generic, &spr_write_generic, - 0x00000000); init_tlbs_emb(env); init_excp_e200(env, 0xFFFF0000UL); diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c index 44e19aa..c941c89 100644 --- a/target/ppc/excp_helper.c +++ b/target/ppc/excp_helper.c @@ -1951,6 +1951,10 @@ static int ppc_next_unmasked_interrupt(CPUPPCState *env) target_ulong lpcr = env->spr[SPR_LPCR]; bool async_deliver; + if (unlikely(env->quiesced)) { + return 0; + } + #ifdef TARGET_PPC64 switch (env->excp_model) { case POWERPC_EXCP_POWER7: diff --git a/target/ppc/translate/vmx-impl.c.inc b/target/ppc/translate/vmx-impl.c.inc index 70d0ad2..92d6e8c 100644 --- a/target/ppc/translate/vmx-impl.c.inc +++ b/target/ppc/translate/vmx-impl.c.inc @@ -994,8 +994,8 @@ static bool do_vector_rotl_quad(DisasContext *ctx, arg_VX *a, bool mask, { TCGv_i64 ah, al, vrb, n, t0, t1, zero = tcg_constant_i64(0); - REQUIRE_VECTOR(ctx); REQUIRE_INSNS_FLAGS2(ctx, ISA310); + REQUIRE_VECTOR(ctx); ah = tcg_temp_new_i64(); al = tcg_temp_new_i64(); diff --git a/target/ppc/translate/vsx-impl.c.inc b/target/ppc/translate/vsx-impl.c.inc index a869f30..00ad57c 100644 --- a/target/ppc/translate/vsx-impl.c.inc +++ b/target/ppc/translate/vsx-impl.c.inc @@ -61,8 +61,8 @@ static bool trans_LXVD2X(DisasContext *ctx, arg_LXVD2X *a) TCGv EA; TCGv_i64 t0; - REQUIRE_VSX(ctx); REQUIRE_INSNS_FLAGS2(ctx, VSX); + REQUIRE_VSX(ctx); t0 = tcg_temp_new_i64(); gen_set_access_type(ctx, ACCESS_INT); @@ -80,8 +80,8 @@ static bool trans_LXVW4X(DisasContext *ctx, arg_LXVW4X *a) TCGv EA; TCGv_i64 xth, xtl; - REQUIRE_VSX(ctx); REQUIRE_INSNS_FLAGS2(ctx, VSX); + REQUIRE_VSX(ctx); xth = tcg_temp_new_i64(); xtl = tcg_temp_new_i64(); @@ -113,12 +113,12 @@ static bool trans_LXVWSX(DisasContext *ctx, arg_LXVWSX *a) TCGv EA; TCGv_i32 data; + REQUIRE_INSNS_FLAGS2(ctx, ISA300); if (a->rt < 32) { REQUIRE_VSX(ctx); } else { REQUIRE_VECTOR(ctx); } - REQUIRE_INSNS_FLAGS2(ctx, ISA300); gen_set_access_type(ctx, ACCESS_INT); EA = do_ea_calc(ctx, a->ra, cpu_gpr[a->rb]); @@ -133,8 +133,8 @@ static bool trans_LXVDSX(DisasContext *ctx, arg_LXVDSX *a) TCGv EA; TCGv_i64 data; - REQUIRE_VSX(ctx); REQUIRE_INSNS_FLAGS2(ctx, VSX); + REQUIRE_VSX(ctx); gen_set_access_type(ctx, ACCESS_INT); EA = do_ea_calc(ctx, a->ra, cpu_gpr[a->rb]); @@ -185,8 +185,8 @@ static bool trans_LXVH8X(DisasContext *ctx, arg_LXVH8X *a) TCGv EA; TCGv_i64 xth, xtl; - REQUIRE_VSX(ctx); REQUIRE_INSNS_FLAGS2(ctx, ISA300); + REQUIRE_VSX(ctx); xth = tcg_temp_new_i64(); xtl = tcg_temp_new_i64(); @@ -208,8 +208,8 @@ static bool trans_LXVB16X(DisasContext *ctx, arg_LXVB16X *a) TCGv EA; TCGv_i128 data; - REQUIRE_VSX(ctx); REQUIRE_INSNS_FLAGS2(ctx, ISA300); + REQUIRE_VSX(ctx); data = tcg_temp_new_i128(); gen_set_access_type(ctx, ACCESS_INT); @@ -312,8 +312,8 @@ static bool trans_STXVD2X(DisasContext *ctx, arg_STXVD2X *a) TCGv EA; TCGv_i64 t0; - REQUIRE_VSX(ctx); REQUIRE_INSNS_FLAGS2(ctx, VSX); + REQUIRE_VSX(ctx); t0 = tcg_temp_new_i64(); gen_set_access_type(ctx, ACCESS_INT); @@ -331,8 +331,8 @@ static bool trans_STXVW4X(DisasContext *ctx, arg_STXVW4X *a) TCGv EA; TCGv_i64 xsh, xsl; - REQUIRE_VSX(ctx); REQUIRE_INSNS_FLAGS2(ctx, VSX); + REQUIRE_VSX(ctx); xsh = tcg_temp_new_i64(); xsl = tcg_temp_new_i64(); @@ -364,8 +364,8 @@ static bool trans_STXVH8X(DisasContext *ctx, arg_STXVH8X *a) TCGv EA; TCGv_i64 xsh, xsl; - REQUIRE_VSX(ctx); REQUIRE_INSNS_FLAGS2(ctx, ISA300); + REQUIRE_VSX(ctx); xsh = tcg_temp_new_i64(); xsl = tcg_temp_new_i64(); @@ -394,8 +394,8 @@ static bool trans_STXVB16X(DisasContext *ctx, arg_STXVB16X *a) TCGv EA; TCGv_i128 data; - REQUIRE_VSX(ctx); REQUIRE_INSNS_FLAGS2(ctx, ISA300); + REQUIRE_VSX(ctx); data = tcg_temp_new_i128(); gen_set_access_type(ctx, ACCESS_INT); diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index 7de19b4..51e49e0 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -765,6 +765,18 @@ static inline RISCVMXL riscv_cpu_sxl(CPURISCVState *env) } #endif +static inline bool riscv_cpu_allow_16bit_insn(const RISCVCPUConfig *cfg, + target_long priv_ver, + uint32_t misa_ext) +{ + /* In priv spec version 1.12 or newer, C always implies Zca */ + if (priv_ver >= PRIV_VERSION_1_12_0) { + return cfg->ext_zca; + } else { + return misa_ext & RVC; + } +} + /* * Encode LMUL to lmul as follows: * LMUL vlmul lmul diff --git a/target/riscv/csr.c b/target/riscv/csr.c index 49566d3..7948188 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -192,6 +192,11 @@ static RISCVException cfi_ss(CPURISCVState *env, int csrno) return RISCV_EXCP_ILLEGAL_INST; } + /* If ext implemented, M-mode always have access to SSP CSR */ + if (env->priv == PRV_M) { + return RISCV_EXCP_NONE; + } + /* if bcfi not active for current env, access to csr is illegal */ if (!cpu_get_bcfien(env)) { #if !defined(CONFIG_USER_ONLY) @@ -4297,7 +4302,7 @@ static RISCVException rmw_sctrdepth(CPURISCVState *env, int csrno, } /* Update sctrstatus.WRPTR with a legal value */ - depth = 16 << depth; + depth = 16ULL << depth; env->sctrstatus = env->sctrstatus & (~SCTRSTATUS_WRPTR_MASK | (depth - 1)); } diff --git a/target/riscv/insn_trans/trans_rvi.c.inc b/target/riscv/insn_trans/trans_rvi.c.inc index b55f56a..b9c7160 100644 --- a/target/riscv/insn_trans/trans_rvi.c.inc +++ b/target/riscv/insn_trans/trans_rvi.c.inc @@ -151,7 +151,9 @@ static bool trans_jalr(DisasContext *ctx, arg_jalr *a) tcg_gen_ext32s_tl(target_pc, target_pc); } - if (!has_ext(ctx, RVC) && !ctx->cfg_ptr->ext_zca) { + if (!riscv_cpu_allow_16bit_insn(ctx->cfg_ptr, + ctx->priv_ver, + ctx->misa_ext)) { TCGv t0 = tcg_temp_new(); misaligned = gen_new_label(); @@ -300,7 +302,9 @@ static bool gen_branch(DisasContext *ctx, arg_b *a, TCGCond cond) gen_set_label(l); /* branch taken */ - if (!has_ext(ctx, RVC) && !ctx->cfg_ptr->ext_zca && + if (!riscv_cpu_allow_16bit_insn(ctx->cfg_ptr, + ctx->priv_ver, + ctx->misa_ext) && (a->imm & 0x3)) { /* misaligned */ TCGv target_pc = tcg_temp_new(); diff --git a/target/riscv/insn_trans/trans_rvzicfiss.c.inc b/target/riscv/insn_trans/trans_rvzicfiss.c.inc index e3ebc49..b0096ad 100644 --- a/target/riscv/insn_trans/trans_rvzicfiss.c.inc +++ b/target/riscv/insn_trans/trans_rvzicfiss.c.inc @@ -15,6 +15,13 @@ * You should have received a copy of the GNU General Public License along with * this program. If not, see <http://www.gnu.org/licenses/>. */ + +#define REQUIRE_ZICFISS(ctx) do { \ + if (!ctx->cfg_ptr->ext_zicfiss) { \ + return false; \ + } \ +} while (0) + static bool trans_sspopchk(DisasContext *ctx, arg_sspopchk *a) { if (!ctx->bcfi_enabled) { @@ -77,6 +84,11 @@ static bool trans_ssrdp(DisasContext *ctx, arg_ssrdp *a) static bool trans_ssamoswap_w(DisasContext *ctx, arg_amoswap_w *a) { REQUIRE_A_OR_ZAAMO(ctx); + REQUIRE_ZICFISS(ctx); + if (ctx->priv == PRV_M) { + generate_exception(ctx, RISCV_EXCP_STORE_AMO_ACCESS_FAULT); + } + if (!ctx->bcfi_enabled) { return false; } @@ -97,6 +109,11 @@ static bool trans_ssamoswap_d(DisasContext *ctx, arg_amoswap_w *a) { REQUIRE_64BIT(ctx); REQUIRE_A_OR_ZAAMO(ctx); + REQUIRE_ZICFISS(ctx); + if (ctx->priv == PRV_M) { + generate_exception(ctx, RISCV_EXCP_STORE_AMO_ACCESS_FAULT); + } + if (!ctx->bcfi_enabled) { return false; } diff --git a/target/riscv/kvm/kvm-cpu.c b/target/riscv/kvm/kvm-cpu.c index 4ffeeaa..0f4997a 100644 --- a/target/riscv/kvm/kvm-cpu.c +++ b/target/riscv/kvm/kvm-cpu.c @@ -624,8 +624,6 @@ static void kvm_riscv_reset_regs_csr(CPURISCVState *env) env->stval = 0; env->mip = 0; env->satp = 0; - env->scounteren = 0; - env->senvcfg = 0; } static int kvm_riscv_get_regs_csr(CPUState *cs) @@ -641,8 +639,6 @@ static int kvm_riscv_get_regs_csr(CPUState *cs) KVM_RISCV_GET_CSR(cs, env, stval, env->stval); KVM_RISCV_GET_CSR(cs, env, sip, env->mip); KVM_RISCV_GET_CSR(cs, env, satp, env->satp); - KVM_RISCV_GET_CSR(cs, env, scounteren, env->scounteren); - KVM_RISCV_GET_CSR(cs, env, senvcfg, env->senvcfg); return 0; } @@ -660,8 +656,6 @@ static int kvm_riscv_put_regs_csr(CPUState *cs) KVM_RISCV_SET_CSR(cs, env, stval, env->stval); KVM_RISCV_SET_CSR(cs, env, sip, env->mip); KVM_RISCV_SET_CSR(cs, env, satp, env->satp); - KVM_RISCV_SET_CSR(cs, env, scounteren, env->scounteren); - KVM_RISCV_SET_CSR(cs, env, senvcfg, env->senvcfg); return 0; } diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c index 0d4220b..72dc48e 100644 --- a/target/riscv/op_helper.c +++ b/target/riscv/op_helper.c @@ -279,7 +279,9 @@ target_ulong helper_sret(CPURISCVState *env) } target_ulong retpc = env->sepc; - if (!riscv_has_ext(env, RVC) && (retpc & 0x3)) { + if (!riscv_cpu_allow_16bit_insn(&env_archcpu(env)->cfg, + env->priv_ver, + env->misa_ext) && (retpc & 0x3)) { riscv_raise_exception(env, RISCV_EXCP_INST_ADDR_MIS, GETPC()); } @@ -357,7 +359,9 @@ static void check_ret_from_m_mode(CPURISCVState *env, target_ulong retpc, riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC()); } - if (!riscv_has_ext(env, RVC) && (retpc & 0x3)) { + if (!riscv_cpu_allow_16bit_insn(&env_archcpu(env)->cfg, + env->priv_ver, + env->misa_ext) && (retpc & 0x3)) { riscv_raise_exception(env, RISCV_EXCP_INST_ADDR_MIS, GETPC()); } diff --git a/target/riscv/translate.c b/target/riscv/translate.c index eaa5d86..d6651f2 100644 --- a/target/riscv/translate.c +++ b/target/riscv/translate.c @@ -606,7 +606,9 @@ static void gen_jal(DisasContext *ctx, int rd, target_ulong imm) TCGv succ_pc = dest_gpr(ctx, rd); /* check misaligned: */ - if (!has_ext(ctx, RVC) && !ctx->cfg_ptr->ext_zca) { + if (!riscv_cpu_allow_16bit_insn(ctx->cfg_ptr, + ctx->priv_ver, + ctx->misa_ext)) { if ((imm & 0x3) != 0) { TCGv target_pc = tcg_temp_new(); gen_pc_plus_diff(target_pc, ctx, imm); diff --git a/target/riscv/vcrypto_helper.c b/target/riscv/vcrypto_helper.c index f7423df..1526de9 100644 --- a/target/riscv/vcrypto_helper.c +++ b/target/riscv/vcrypto_helper.c @@ -222,7 +222,7 @@ static inline void xor_round_key(AESState *round_state, AESState *round_key) uint32_t total_elems = vext_get_total_elems(env, desc, 4); \ uint32_t vta = vext_vta(desc); \ \ - VSTART_CHECK_EARLY_EXIT(env); \ + VSTART_CHECK_EARLY_EXIT(env, vl); \ \ for (uint32_t i = env->vstart / 4; i < env->vl / 4; i++) { \ AESState round_key; \ @@ -248,7 +248,7 @@ static inline void xor_round_key(AESState *round_state, AESState *round_key) uint32_t total_elems = vext_get_total_elems(env, desc, 4); \ uint32_t vta = vext_vta(desc); \ \ - VSTART_CHECK_EARLY_EXIT(env); \ + VSTART_CHECK_EARLY_EXIT(env, vl); \ \ for (uint32_t i = env->vstart / 4; i < env->vl / 4; i++) { \ AESState round_key; \ @@ -309,7 +309,7 @@ void HELPER(vaeskf1_vi)(void *vd_vptr, void *vs2_vptr, uint32_t uimm, uint32_t total_elems = vext_get_total_elems(env, desc, 4); uint32_t vta = vext_vta(desc); - VSTART_CHECK_EARLY_EXIT(env); + VSTART_CHECK_EARLY_EXIT(env, vl); uimm &= 0b1111; if (uimm > 10 || uimm == 0) { @@ -357,7 +357,7 @@ void HELPER(vaeskf2_vi)(void *vd_vptr, void *vs2_vptr, uint32_t uimm, uint32_t total_elems = vext_get_total_elems(env, desc, 4); uint32_t vta = vext_vta(desc); - VSTART_CHECK_EARLY_EXIT(env); + VSTART_CHECK_EARLY_EXIT(env, vl); uimm &= 0b1111; if (uimm > 14 || uimm < 2) { @@ -465,7 +465,7 @@ void HELPER(vsha2ms_vv)(void *vd, void *vs1, void *vs2, CPURISCVState *env, uint32_t total_elems; uint32_t vta = vext_vta(desc); - VSTART_CHECK_EARLY_EXIT(env); + VSTART_CHECK_EARLY_EXIT(env, env->vl); for (uint32_t i = env->vstart / 4; i < env->vl / 4; i++) { if (sew == MO_32) { @@ -582,7 +582,7 @@ void HELPER(vsha2ch32_vv)(void *vd, void *vs1, void *vs2, CPURISCVState *env, uint32_t total_elems; uint32_t vta = vext_vta(desc); - VSTART_CHECK_EARLY_EXIT(env); + VSTART_CHECK_EARLY_EXIT(env, env->vl); for (uint32_t i = env->vstart / 4; i < env->vl / 4; i++) { vsha2c_32(((uint32_t *)vs2) + 4 * i, ((uint32_t *)vd) + 4 * i, @@ -602,7 +602,7 @@ void HELPER(vsha2ch64_vv)(void *vd, void *vs1, void *vs2, CPURISCVState *env, uint32_t total_elems; uint32_t vta = vext_vta(desc); - VSTART_CHECK_EARLY_EXIT(env); + VSTART_CHECK_EARLY_EXIT(env, env->vl); for (uint32_t i = env->vstart / 4; i < env->vl / 4; i++) { vsha2c_64(((uint64_t *)vs2) + 4 * i, ((uint64_t *)vd) + 4 * i, @@ -622,7 +622,7 @@ void HELPER(vsha2cl32_vv)(void *vd, void *vs1, void *vs2, CPURISCVState *env, uint32_t total_elems; uint32_t vta = vext_vta(desc); - VSTART_CHECK_EARLY_EXIT(env); + VSTART_CHECK_EARLY_EXIT(env, env->vl); for (uint32_t i = env->vstart / 4; i < env->vl / 4; i++) { vsha2c_32(((uint32_t *)vs2) + 4 * i, ((uint32_t *)vd) + 4 * i, @@ -642,7 +642,7 @@ void HELPER(vsha2cl64_vv)(void *vd, void *vs1, void *vs2, CPURISCVState *env, uint32_t total_elems; uint32_t vta = vext_vta(desc); - VSTART_CHECK_EARLY_EXIT(env); + VSTART_CHECK_EARLY_EXIT(env, env->vl); for (uint32_t i = env->vstart / 4; i < env->vl / 4; i++) { vsha2c_64(((uint64_t *)vs2) + 4 * i, ((uint64_t *)vd) + 4 * i, @@ -676,7 +676,7 @@ void HELPER(vsm3me_vv)(void *vd_vptr, void *vs1_vptr, void *vs2_vptr, uint32_t *vs1 = vs1_vptr; uint32_t *vs2 = vs2_vptr; - VSTART_CHECK_EARLY_EXIT(env); + VSTART_CHECK_EARLY_EXIT(env, env->vl); for (int i = env->vstart / 8; i < env->vl / 8; i++) { uint32_t w[24]; @@ -777,7 +777,7 @@ void HELPER(vsm3c_vi)(void *vd_vptr, void *vs2_vptr, uint32_t uimm, uint32_t *vs2 = vs2_vptr; uint32_t v1[8], v2[8], v3[8]; - VSTART_CHECK_EARLY_EXIT(env); + VSTART_CHECK_EARLY_EXIT(env, env->vl); for (int i = env->vstart / 8; i < env->vl / 8; i++) { for (int k = 0; k < 8; k++) { @@ -802,7 +802,7 @@ void HELPER(vghsh_vv)(void *vd_vptr, void *vs1_vptr, void *vs2_vptr, uint32_t vta = vext_vta(desc); uint32_t total_elems = vext_get_total_elems(env, desc, 4); - VSTART_CHECK_EARLY_EXIT(env); + VSTART_CHECK_EARLY_EXIT(env, env->vl); for (uint32_t i = env->vstart / 4; i < env->vl / 4; i++) { uint64_t Y[2] = {vd[i * 2 + 0], vd[i * 2 + 1]}; @@ -841,7 +841,7 @@ void HELPER(vgmul_vv)(void *vd_vptr, void *vs2_vptr, CPURISCVState *env, uint32_t vta = vext_vta(desc); uint32_t total_elems = vext_get_total_elems(env, desc, 4); - VSTART_CHECK_EARLY_EXIT(env); + VSTART_CHECK_EARLY_EXIT(env, env->vl); for (uint32_t i = env->vstart / 4; i < env->vl / 4; i++) { uint64_t Y[2] = {brev8(vd[i * 2 + 0]), brev8(vd[i * 2 + 1])}; @@ -879,7 +879,7 @@ void HELPER(vsm4k_vi)(void *vd, void *vs2, uint32_t uimm5, CPURISCVState *env, uint32_t esz = sizeof(uint32_t); uint32_t total_elems = vext_get_total_elems(env, desc, esz); - VSTART_CHECK_EARLY_EXIT(env); + VSTART_CHECK_EARLY_EXIT(env, env->vl); for (uint32_t i = group_start; i < group_end; ++i) { uint32_t vstart = i * egs; @@ -937,7 +937,7 @@ void HELPER(vsm4r_vv)(void *vd, void *vs2, CPURISCVState *env, uint32_t desc) uint32_t esz = sizeof(uint32_t); uint32_t total_elems = vext_get_total_elems(env, desc, esz); - VSTART_CHECK_EARLY_EXIT(env); + VSTART_CHECK_EARLY_EXIT(env, env->vl); for (uint32_t i = group_start; i < group_end; ++i) { uint32_t vstart = i * egs; @@ -973,7 +973,7 @@ void HELPER(vsm4r_vs)(void *vd, void *vs2, CPURISCVState *env, uint32_t desc) uint32_t esz = sizeof(uint32_t); uint32_t total_elems = vext_get_total_elems(env, desc, esz); - VSTART_CHECK_EARLY_EXIT(env); + VSTART_CHECK_EARLY_EXIT(env, env->vl); for (uint32_t i = group_start; i < group_end; ++i) { uint32_t vstart = i * egs; diff --git a/target/riscv/vector_helper.c b/target/riscv/vector_helper.c index 7773df6..67b3baf 100644 --- a/target/riscv/vector_helper.c +++ b/target/riscv/vector_helper.c @@ -260,7 +260,7 @@ vext_ldst_stride(void *vd, void *v0, target_ulong base, target_ulong stride, uint32_t esz = 1 << log2_esz; uint32_t vma = vext_vma(desc); - VSTART_CHECK_EARLY_EXIT(env); + VSTART_CHECK_EARLY_EXIT(env, env->vl); for (i = env->vstart; i < env->vl; env->vstart = ++i) { k = 0; @@ -383,10 +383,7 @@ vext_ldst_us(void *vd, target_ulong base, CPURISCVState *env, uint32_t desc, uint32_t msize = nf * esz; int mmu_index = riscv_env_mmu_index(env, false); - if (env->vstart >= evl) { - env->vstart = 0; - return; - } + VSTART_CHECK_EARLY_EXIT(env, evl); #if defined(CONFIG_USER_ONLY) /* @@ -544,7 +541,7 @@ vext_ldst_index(void *vd, void *v0, target_ulong base, uint32_t esz = 1 << log2_esz; uint32_t vma = vext_vma(desc); - VSTART_CHECK_EARLY_EXIT(env); + VSTART_CHECK_EARLY_EXIT(env, env->vl); /* load bytes from guest memory */ for (i = env->vstart; i < env->vl; env->vstart = ++i) { @@ -633,47 +630,69 @@ vext_ldff(void *vd, void *v0, target_ulong base, CPURISCVState *env, uint32_t esz = 1 << log2_esz; uint32_t msize = nf * esz; uint32_t vma = vext_vma(desc); - target_ulong addr, offset, remain, page_split, elems; + target_ulong addr, addr_probe, addr_i, offset, remain, page_split, elems; int mmu_index = riscv_env_mmu_index(env, false); + int flags; + void *host; - VSTART_CHECK_EARLY_EXIT(env); + VSTART_CHECK_EARLY_EXIT(env, env->vl); - /* probe every access */ - for (i = env->vstart; i < env->vl; i++) { - if (!vm && !vext_elem_mask(v0, i)) { - continue; - } - addr = adjust_addr(env, base + i * (nf << log2_esz)); - if (i == 0) { - /* Allow fault on first element. */ - probe_pages(env, addr, nf << log2_esz, ra, MMU_DATA_LOAD); - } else { - remain = nf << log2_esz; - while (remain > 0) { - void *host; - int flags; - - offset = -(addr | TARGET_PAGE_MASK); - - /* Probe nonfault on subsequent elements. */ - flags = probe_access_flags(env, addr, offset, MMU_DATA_LOAD, - mmu_index, true, &host, 0); - - /* - * Stop if invalid (unmapped) or mmio (transaction may fail). - * Do not stop if watchpoint, as the spec says that - * first-fault should continue to access the same - * elements regardless of any watchpoint. - */ - if (flags & ~TLB_WATCHPOINT) { - vl = i; - goto ProbeSuccess; - } - if (remain <= offset) { - break; + addr = base + ((env->vstart * nf) << log2_esz); + page_split = -(addr | TARGET_PAGE_MASK); + /* Get number of elements */ + elems = page_split / msize; + if (unlikely(env->vstart + elems >= env->vl)) { + elems = env->vl - env->vstart; + } + + /* Check page permission/pmp/watchpoint/etc. */ + flags = probe_access_flags(env, adjust_addr(env, addr), elems * msize, + MMU_DATA_LOAD, mmu_index, true, &host, ra); + + /* If we are crossing a page check also the second page. */ + if (env->vl > elems) { + addr_probe = addr + (elems << log2_esz); + flags |= probe_access_flags(env, adjust_addr(env, addr_probe), + elems * msize, MMU_DATA_LOAD, mmu_index, + true, &host, ra); + } + + if (flags & ~TLB_WATCHPOINT) { + /* probe every access */ + for (i = env->vstart; i < env->vl; i++) { + if (!vm && !vext_elem_mask(v0, i)) { + continue; + } + addr_i = adjust_addr(env, base + i * (nf << log2_esz)); + if (i == 0) { + /* Allow fault on first element. */ + probe_pages(env, addr_i, nf << log2_esz, ra, MMU_DATA_LOAD); + } else { + remain = nf << log2_esz; + while (remain > 0) { + offset = -(addr_i | TARGET_PAGE_MASK); + + /* Probe nonfault on subsequent elements. */ + flags = probe_access_flags(env, addr_i, offset, + MMU_DATA_LOAD, mmu_index, true, + &host, 0); + + /* + * Stop if invalid (unmapped) or mmio (transaction may + * fail). Do not stop if watchpoint, as the spec says that + * first-fault should continue to access the same + * elements regardless of any watchpoint. + */ + if (flags & ~TLB_WATCHPOINT) { + vl = i; + goto ProbeSuccess; + } + if (remain <= offset) { + break; + } + remain -= offset; + addr_i = adjust_addr(env, addr_i + offset); } - remain -= offset; - addr = adjust_addr(env, addr + offset); } } } @@ -685,15 +704,6 @@ ProbeSuccess: if (env->vstart < env->vl) { if (vm) { - /* Calculate the page range of first page */ - addr = base + ((env->vstart * nf) << log2_esz); - page_split = -(addr | TARGET_PAGE_MASK); - /* Get number of elements */ - elems = page_split / msize; - if (unlikely(env->vstart + elems >= env->vl)) { - elems = env->vl - env->vstart; - } - /* Load/store elements in the first page */ if (likely(elems)) { vext_page_ldst_us(env, vd, addr, elems, nf, max_elems, @@ -1103,7 +1113,7 @@ void HELPER(NAME)(void *vd, void *v0, void *vs1, void *vs2, \ uint32_t vta = vext_vta(desc); \ uint32_t i; \ \ - VSTART_CHECK_EARLY_EXIT(env); \ + VSTART_CHECK_EARLY_EXIT(env, vl); \ \ for (i = env->vstart; i < vl; i++) { \ ETYPE s1 = *((ETYPE *)vs1 + H(i)); \ @@ -1137,7 +1147,7 @@ void HELPER(NAME)(void *vd, void *v0, target_ulong s1, void *vs2, \ uint32_t vta = vext_vta(desc); \ uint32_t i; \ \ - VSTART_CHECK_EARLY_EXIT(env); \ + VSTART_CHECK_EARLY_EXIT(env, vl); \ \ for (i = env->vstart; i < vl; i++) { \ ETYPE s2 = *((ETYPE *)vs2 + H(i)); \ @@ -1174,7 +1184,7 @@ void HELPER(NAME)(void *vd, void *v0, void *vs1, void *vs2, \ uint32_t vta_all_1s = vext_vta_all_1s(desc); \ uint32_t i; \ \ - VSTART_CHECK_EARLY_EXIT(env); \ + VSTART_CHECK_EARLY_EXIT(env, vl); \ \ for (i = env->vstart; i < vl; i++) { \ ETYPE s1 = *((ETYPE *)vs1 + H(i)); \ @@ -1214,7 +1224,7 @@ void HELPER(NAME)(void *vd, void *v0, target_ulong s1, \ uint32_t vta_all_1s = vext_vta_all_1s(desc); \ uint32_t i; \ \ - VSTART_CHECK_EARLY_EXIT(env); \ + VSTART_CHECK_EARLY_EXIT(env, vl); \ \ for (i = env->vstart; i < vl; i++) { \ ETYPE s2 = *((ETYPE *)vs2 + H(i)); \ @@ -1312,7 +1322,7 @@ void HELPER(NAME)(void *vd, void *v0, void *vs1, \ uint32_t vma = vext_vma(desc); \ uint32_t i; \ \ - VSTART_CHECK_EARLY_EXIT(env); \ + VSTART_CHECK_EARLY_EXIT(env, vl); \ \ for (i = env->vstart; i < vl; i++) { \ if (!vm && !vext_elem_mask(v0, i)) { \ @@ -1361,7 +1371,7 @@ void HELPER(NAME)(void *vd, void *v0, target_ulong s1, \ uint32_t vma = vext_vma(desc); \ uint32_t i; \ \ - VSTART_CHECK_EARLY_EXIT(env); \ + VSTART_CHECK_EARLY_EXIT(env, vl); \ \ for (i = env->vstart; i < vl; i++) { \ if (!vm && !vext_elem_mask(v0, i)) { \ @@ -1425,7 +1435,7 @@ void HELPER(NAME)(void *vd, void *v0, void *vs1, void *vs2, \ uint32_t vma = vext_vma(desc); \ uint32_t i; \ \ - VSTART_CHECK_EARLY_EXIT(env); \ + VSTART_CHECK_EARLY_EXIT(env, vl); \ \ for (i = env->vstart; i < vl; i++) { \ ETYPE s1 = *((ETYPE *)vs1 + H(i)); \ @@ -1492,7 +1502,7 @@ void HELPER(NAME)(void *vd, void *v0, target_ulong s1, void *vs2, \ uint32_t vma = vext_vma(desc); \ uint32_t i; \ \ - VSTART_CHECK_EARLY_EXIT(env); \ + VSTART_CHECK_EARLY_EXIT(env, vl); \ \ for (i = env->vstart; i < vl; i++) { \ ETYPE s2 = *((ETYPE *)vs2 + H(i)); \ @@ -2041,7 +2051,7 @@ void HELPER(NAME)(void *vd, void *vs1, CPURISCVState *env, \ uint32_t vta = vext_vta(desc); \ uint32_t i; \ \ - VSTART_CHECK_EARLY_EXIT(env); \ + VSTART_CHECK_EARLY_EXIT(env, vl); \ \ for (i = env->vstart; i < vl; i++) { \ ETYPE s1 = *((ETYPE *)vs1 + H(i)); \ @@ -2067,7 +2077,7 @@ void HELPER(NAME)(void *vd, uint64_t s1, CPURISCVState *env, \ uint32_t vta = vext_vta(desc); \ uint32_t i; \ \ - VSTART_CHECK_EARLY_EXIT(env); \ + VSTART_CHECK_EARLY_EXIT(env, vl); \ \ for (i = env->vstart; i < vl; i++) { \ *((ETYPE *)vd + H(i)) = (ETYPE)s1; \ @@ -2092,7 +2102,7 @@ void HELPER(NAME)(void *vd, void *v0, void *vs1, void *vs2, \ uint32_t vta = vext_vta(desc); \ uint32_t i; \ \ - VSTART_CHECK_EARLY_EXIT(env); \ + VSTART_CHECK_EARLY_EXIT(env, vl); \ \ for (i = env->vstart; i < vl; i++) { \ ETYPE *vt = (!vext_elem_mask(v0, i) ? vs2 : vs1); \ @@ -2118,7 +2128,7 @@ void HELPER(NAME)(void *vd, void *v0, target_ulong s1, \ uint32_t vta = vext_vta(desc); \ uint32_t i; \ \ - VSTART_CHECK_EARLY_EXIT(env); \ + VSTART_CHECK_EARLY_EXIT(env, vl); \ \ for (i = env->vstart; i < vl; i++) { \ ETYPE s2 = *((ETYPE *)vs2 + H(i)); \ @@ -2165,8 +2175,6 @@ vext_vv_rm_1(void *vd, void *v0, void *vs1, void *vs2, uint32_t vl, uint32_t vm, int vxrm, opivv2_rm_fn *fn, uint32_t vma, uint32_t esz) { - VSTART_CHECK_EARLY_EXIT(env); - for (uint32_t i = env->vstart; i < vl; i++) { if (!vm && !vext_elem_mask(v0, i)) { /* set masked-off elements to 1s */ @@ -2190,6 +2198,8 @@ vext_vv_rm_2(void *vd, void *v0, void *vs1, void *vs2, uint32_t vta = vext_vta(desc); uint32_t vma = vext_vma(desc); + VSTART_CHECK_EARLY_EXIT(env, vl); + switch (env->vxrm) { case 0: /* rnu */ vext_vv_rm_1(vd, v0, vs1, vs2, @@ -2292,8 +2302,6 @@ vext_vx_rm_1(void *vd, void *v0, target_long s1, void *vs2, uint32_t vl, uint32_t vm, int vxrm, opivx2_rm_fn *fn, uint32_t vma, uint32_t esz) { - VSTART_CHECK_EARLY_EXIT(env); - for (uint32_t i = env->vstart; i < vl; i++) { if (!vm && !vext_elem_mask(v0, i)) { /* set masked-off elements to 1s */ @@ -2317,6 +2325,8 @@ vext_vx_rm_2(void *vd, void *v0, target_long s1, void *vs2, uint32_t vta = vext_vta(desc); uint32_t vma = vext_vma(desc); + VSTART_CHECK_EARLY_EXIT(env, vl); + switch (env->vxrm) { case 0: /* rnu */ vext_vx_rm_1(vd, v0, s1, vs2, @@ -3091,7 +3101,7 @@ void HELPER(NAME)(void *vd, void *v0, void *vs1, \ uint32_t vma = vext_vma(desc); \ uint32_t i; \ \ - VSTART_CHECK_EARLY_EXIT(env); \ + VSTART_CHECK_EARLY_EXIT(env, vl); \ \ for (i = env->vstart; i < vl; i++) { \ if (!vm && !vext_elem_mask(v0, i)) { \ @@ -3136,7 +3146,7 @@ void HELPER(NAME)(void *vd, void *v0, uint64_t s1, \ uint32_t vma = vext_vma(desc); \ uint32_t i; \ \ - VSTART_CHECK_EARLY_EXIT(env); \ + VSTART_CHECK_EARLY_EXIT(env, vl); \ \ for (i = env->vstart; i < vl; i++) { \ if (!vm && !vext_elem_mask(v0, i)) { \ @@ -3724,7 +3734,7 @@ void HELPER(NAME)(void *vd, void *v0, void *vs2, \ uint32_t vma = vext_vma(desc); \ uint32_t i; \ \ - VSTART_CHECK_EARLY_EXIT(env); \ + VSTART_CHECK_EARLY_EXIT(env, vl); \ \ if (vl == 0) { \ return; \ @@ -4247,7 +4257,7 @@ void HELPER(NAME)(void *vd, void *v0, void *vs1, void *vs2, \ uint32_t vma = vext_vma(desc); \ uint32_t i; \ \ - VSTART_CHECK_EARLY_EXIT(env); \ + VSTART_CHECK_EARLY_EXIT(env, vl); \ \ for (i = env->vstart; i < vl; i++) { \ ETYPE s1 = *((ETYPE *)vs1 + H(i)); \ @@ -4289,7 +4299,7 @@ void HELPER(NAME)(void *vd, void *v0, uint64_t s1, void *vs2, \ uint32_t vma = vext_vma(desc); \ uint32_t i; \ \ - VSTART_CHECK_EARLY_EXIT(env); \ + VSTART_CHECK_EARLY_EXIT(env, vl); \ \ for (i = env->vstart; i < vl; i++) { \ ETYPE s2 = *((ETYPE *)vs2 + H(i)); \ @@ -4484,7 +4494,7 @@ void HELPER(NAME)(void *vd, void *v0, uint64_t s1, void *vs2, \ uint32_t vta = vext_vta(desc); \ uint32_t i; \ \ - VSTART_CHECK_EARLY_EXIT(env); \ + VSTART_CHECK_EARLY_EXIT(env, vl); \ \ for (i = env->vstart; i < vl; i++) { \ ETYPE s2 = *((ETYPE *)vs2 + H(i)); \ @@ -4652,6 +4662,8 @@ void HELPER(NAME)(void *vd, void *v0, void *vs1, \ uint32_t i; \ TD s1 = *((TD *)vs1 + HD(0)); \ \ + VSTART_CHECK_EARLY_EXIT(env, vl); \ + \ for (i = env->vstart; i < vl; i++) { \ TS2 s2 = *((TS2 *)vs2 + HS2(i)); \ if (!vm && !vext_elem_mask(v0, i)) { \ @@ -4740,6 +4752,8 @@ void HELPER(NAME)(void *vd, void *v0, void *vs1, \ uint32_t i; \ TD s1 = *((TD *)vs1 + HD(0)); \ \ + VSTART_CHECK_EARLY_EXIT(env, vl); \ + \ for (i = env->vstart; i < vl; i++) { \ TS2 s2 = *((TS2 *)vs2 + HS2(i)); \ if (!vm && !vext_elem_mask(v0, i)) { \ @@ -4814,7 +4828,7 @@ void HELPER(NAME)(void *vd, void *v0, void *vs1, \ uint32_t i; \ int a, b; \ \ - VSTART_CHECK_EARLY_EXIT(env); \ + VSTART_CHECK_EARLY_EXIT(env, vl); \ \ for (i = env->vstart; i < vl; i++) { \ a = vext_elem_mask(vs1, i); \ @@ -4904,6 +4918,8 @@ static void vmsetm(void *vd, void *v0, void *vs2, CPURISCVState *env, int i; bool first_mask_bit = false; + VSTART_CHECK_EARLY_EXIT(env, vl); + for (i = env->vstart; i < vl; i++) { if (!vm && !vext_elem_mask(v0, i)) { /* set masked-off elements to 1s */ @@ -4976,6 +4992,8 @@ void HELPER(NAME)(void *vd, void *v0, void *vs2, CPURISCVState *env, \ uint32_t sum = 0; \ int i; \ \ + VSTART_CHECK_EARLY_EXIT(env, vl); \ + \ for (i = env->vstart; i < vl; i++) { \ if (!vm && !vext_elem_mask(v0, i)) { \ /* set masked-off elements to 1s */ \ @@ -5009,7 +5027,7 @@ void HELPER(NAME)(void *vd, void *v0, CPURISCVState *env, uint32_t desc) \ uint32_t vma = vext_vma(desc); \ int i; \ \ - VSTART_CHECK_EARLY_EXIT(env); \ + VSTART_CHECK_EARLY_EXIT(env, vl); \ \ for (i = env->vstart; i < vl; i++) { \ if (!vm && !vext_elem_mask(v0, i)) { \ @@ -5046,7 +5064,7 @@ void HELPER(NAME)(void *vd, void *v0, target_ulong s1, void *vs2, \ uint32_t vma = vext_vma(desc); \ target_ulong offset = s1, i_min, i; \ \ - VSTART_CHECK_EARLY_EXIT(env); \ + VSTART_CHECK_EARLY_EXIT(env, vl); \ \ i_min = MAX(env->vstart, offset); \ for (i = i_min; i < vl; i++) { \ @@ -5081,7 +5099,7 @@ void HELPER(NAME)(void *vd, void *v0, target_ulong s1, void *vs2, \ uint32_t vma = vext_vma(desc); \ target_ulong i_max, i_min, i; \ \ - VSTART_CHECK_EARLY_EXIT(env); \ + VSTART_CHECK_EARLY_EXIT(env, vl); \ \ i_min = MIN(s1 < vlmax ? vlmax - s1 : 0, vl); \ i_max = MAX(i_min, env->vstart); \ @@ -5125,7 +5143,7 @@ static void vslide1up_##BITWIDTH(void *vd, void *v0, uint64_t s1, \ uint32_t vma = vext_vma(desc); \ uint32_t i; \ \ - VSTART_CHECK_EARLY_EXIT(env); \ + VSTART_CHECK_EARLY_EXIT(env, vl); \ \ for (i = env->vstart; i < vl; i++) { \ if (!vm && !vext_elem_mask(v0, i)) { \ @@ -5176,7 +5194,7 @@ static void vslide1down_##BITWIDTH(void *vd, void *v0, uint64_t s1, \ uint32_t vma = vext_vma(desc); \ uint32_t i; \ \ - VSTART_CHECK_EARLY_EXIT(env); \ + VSTART_CHECK_EARLY_EXIT(env, vl); \ \ for (i = env->vstart; i < vl; i++) { \ if (!vm && !vext_elem_mask(v0, i)) { \ @@ -5253,7 +5271,7 @@ void HELPER(NAME)(void *vd, void *v0, void *vs1, void *vs2, \ uint64_t index; \ uint32_t i; \ \ - VSTART_CHECK_EARLY_EXIT(env); \ + VSTART_CHECK_EARLY_EXIT(env, vl); \ \ for (i = env->vstart; i < vl; i++) { \ if (!vm && !vext_elem_mask(v0, i)) { \ @@ -5298,7 +5316,7 @@ void HELPER(NAME)(void *vd, void *v0, target_ulong s1, void *vs2, \ uint64_t index = s1; \ uint32_t i; \ \ - VSTART_CHECK_EARLY_EXIT(env); \ + VSTART_CHECK_EARLY_EXIT(env, vl); \ \ for (i = env->vstart; i < vl; i++) { \ if (!vm && !vext_elem_mask(v0, i)) { \ @@ -5334,6 +5352,8 @@ void HELPER(NAME)(void *vd, void *v0, void *vs1, void *vs2, \ uint32_t vta = vext_vta(desc); \ uint32_t num = 0, i; \ \ + VSTART_CHECK_EARLY_EXIT(env, vl); \ + \ for (i = env->vstart; i < vl; i++) { \ if (!vext_elem_mask(vs1, i)) { \ continue; \ @@ -5394,7 +5414,7 @@ void HELPER(NAME)(void *vd, void *v0, void *vs2, \ uint32_t vma = vext_vma(desc); \ uint32_t i; \ \ - VSTART_CHECK_EARLY_EXIT(env); \ + VSTART_CHECK_EARLY_EXIT(env, vl); \ \ for (i = env->vstart; i < vl; i++) { \ if (!vm && !vext_elem_mask(v0, i)) { \ diff --git a/target/riscv/vector_internals.c b/target/riscv/vector_internals.c index 05b2d01..b490b1d 100644 --- a/target/riscv/vector_internals.c +++ b/target/riscv/vector_internals.c @@ -66,7 +66,7 @@ void do_vext_vv(void *vd, void *v0, void *vs1, void *vs2, uint32_t vma = vext_vma(desc); uint32_t i; - VSTART_CHECK_EARLY_EXIT(env); + VSTART_CHECK_EARLY_EXIT(env, vl); for (i = env->vstart; i < vl; i++) { if (!vm && !vext_elem_mask(v0, i)) { @@ -92,7 +92,7 @@ void do_vext_vx(void *vd, void *v0, target_long s1, void *vs2, uint32_t vma = vext_vma(desc); uint32_t i; - VSTART_CHECK_EARLY_EXIT(env); + VSTART_CHECK_EARLY_EXIT(env, vl); for (i = env->vstart; i < vl; i++) { if (!vm && !vext_elem_mask(v0, i)) { diff --git a/target/riscv/vector_internals.h b/target/riscv/vector_internals.h index a11cc83..8eee7e5 100644 --- a/target/riscv/vector_internals.h +++ b/target/riscv/vector_internals.h @@ -25,11 +25,11 @@ #include "tcg/tcg-gvec-desc.h" #include "internals.h" -#define VSTART_CHECK_EARLY_EXIT(env) do { \ - if (env->vstart >= env->vl) { \ - env->vstart = 0; \ - return; \ - } \ +#define VSTART_CHECK_EARLY_EXIT(env, vl) do { \ + if (env->vstart >= vl) { \ + env->vstart = 0; \ + return; \ + } \ } while (0) static inline uint32_t vext_nf(uint32_t desc) @@ -159,7 +159,7 @@ void HELPER(NAME)(void *vd, void *v0, void *vs2, \ uint32_t vma = vext_vma(desc); \ uint32_t i; \ \ - VSTART_CHECK_EARLY_EXIT(env); \ + VSTART_CHECK_EARLY_EXIT(env, vl); \ \ for (i = env->vstart; i < vl; i++) { \ if (!vm && !vext_elem_mask(v0, i)) { \ diff --git a/target/s390x/cpu.c b/target/s390x/cpu.c index d731426..1f75629 100644 --- a/target/s390x/cpu.c +++ b/target/s390x/cpu.c @@ -377,7 +377,7 @@ static void s390_cpu_class_init(ObjectClass *oc, void *data) resettable_class_set_parent_phases(rc, NULL, s390_cpu_reset_hold, NULL, &scc->parent_phases); - cc->class_by_name = s390_cpu_class_by_name, + cc->class_by_name = s390_cpu_class_by_name; cc->mmu_index = s390x_cpu_mmu_index; cc->dump_state = s390_cpu_dump_state; cc->query_cpu_fast = s390_query_cpu_fast; diff --git a/tests/functional/meson.build b/tests/functional/meson.build index 96d2828..0f8be30 100644 --- a/tests/functional/meson.build +++ b/tests/functional/meson.build @@ -26,7 +26,7 @@ test_timeouts = { 'arm_aspeed_witherspoon' : 120, 'arm_aspeed_ast2500' : 720, 'arm_aspeed_ast2600' : 1200, - 'arm_aspeed_bletchley' : 120, + 'arm_aspeed_bletchley' : 480, 'arm_aspeed_rainier' : 480, 'arm_bpim2u' : 500, 'arm_collie' : 180, diff --git a/tests/functional/qemu_test/testcase.py b/tests/functional/qemu_test/testcase.py index 50d232a..50c401b 100644 --- a/tests/functional/qemu_test/testcase.py +++ b/tests/functional/qemu_test/testcase.py @@ -33,12 +33,6 @@ from .uncompress import uncompress class QemuBaseTest(unittest.TestCase): - arch = None - - workdir = None - log = None - logdir = None - ''' @params compressed: filename, Asset, or file-like object to uncompress @params format: optional compression format (gzip, lzma) diff --git a/tests/functional/test_aarch64_rme_sbsaref.py b/tests/functional/test_aarch64_rme_sbsaref.py index ddcc949..0f4f610 100755 --- a/tests/functional/test_aarch64_rme_sbsaref.py +++ b/tests/functional/test_aarch64_rme_sbsaref.py @@ -33,6 +33,7 @@ class Aarch64RMESbsaRefMachine(QemuSystemTest): def test_aarch64_rme_sbsaref(self): self.set_machine('sbsa-ref') self.require_accelerator('tcg') + self.require_netdev('user') self.vm.set_console() diff --git a/tests/functional/test_aarch64_rme_virt.py b/tests/functional/test_aarch64_rme_virt.py index 38e0172..f4ad4d3 100755 --- a/tests/functional/test_aarch64_rme_virt.py +++ b/tests/functional/test_aarch64_rme_virt.py @@ -60,8 +60,10 @@ class Aarch64RMEVirtMachine(QemuSystemTest): # and launching a nested VM using it. def test_aarch64_rme_virt(self): self.set_machine('virt') - self.vm.set_console() self.require_accelerator('tcg') + self.require_netdev('user') + + self.vm.set_console() stack_path_tar_gz = self.ASSET_RME_STACK_VIRT.fetch() self.archive_extract(stack_path_tar_gz, format="tar") diff --git a/tests/functional/test_aarch64_virt_gpu.py b/tests/functional/test_aarch64_virt_gpu.py index 314d994..3844727 100755 --- a/tests/functional/test_aarch64_virt_gpu.py +++ b/tests/functional/test_aarch64_virt_gpu.py @@ -74,6 +74,8 @@ class Aarch64VirtGPUMachine(LinuxKernelTest): self.skipTest("Can't access host DRM render node") elif "'type' does not accept value 'egl-headless'" in excp.output: self.skipTest("egl-headless support is not available") + elif "'type' does not accept value 'dbus'" in excp.output: + self.skipTest("dbus display support is not available") else: self.log.info("unhandled launch failure: %s", excp.output) raise excp diff --git a/tests/functional/test_acpi_bits.py b/tests/functional/test_acpi_bits.py index 20da435..8e0563a 100755 --- a/tests/functional/test_acpi_bits.py +++ b/tests/functional/test_acpi_bits.py @@ -119,7 +119,6 @@ class AcpiBitsTest(QemuSystemTest): #pylint: disable=too-many-instance-attribute self._debugcon_addr = '0x403' self._debugcon_log = 'debugcon-log.txt' - self.logger = self.log def _print_log(self, log): self.logger.info('\nlogs from biosbits follows:') diff --git a/tests/functional/test_arm_bpim2u.py b/tests/functional/test_arm_bpim2u.py index 12cd359..8de6ccb 100755 --- a/tests/functional/test_arm_bpim2u.py +++ b/tests/functional/test_arm_bpim2u.py @@ -140,6 +140,8 @@ class BananaPiMachine(LinuxKernelTest): @skipBigDataTest() def test_arm_bpim2u_openwrt_22_03_3(self): self.set_machine('bpim2u') + self.require_netdev('user') + # This test download a 8.9 MiB compressed image and expand it # to 127 MiB. image_path = self.uncompress(self.ASSET_SD_IMAGE) diff --git a/tests/functional/test_arm_cubieboard.py b/tests/functional/test_arm_cubieboard.py index 423db71..b87a281 100755 --- a/tests/functional/test_arm_cubieboard.py +++ b/tests/functional/test_arm_cubieboard.py @@ -107,6 +107,8 @@ class CubieboardMachine(LinuxKernelTest): # This test download a 7.5 MiB compressed image and expand it # to 126 MiB. self.set_machine('cubieboard') + self.require_netdev('user') + image_path = self.uncompress(self.ASSET_OPENWRT) image_pow2ceil_expand(image_path) diff --git a/tests/functional/test_arm_orangepi.py b/tests/functional/test_arm_orangepi.py index 18ee502..1815f56 100755 --- a/tests/functional/test_arm_orangepi.py +++ b/tests/functional/test_arm_orangepi.py @@ -14,7 +14,7 @@ from qemu_test import wait_for_console_pattern, skipBigDataTest from qemu_test.utils import image_pow2ceil_expand -class BananaPiMachine(LinuxKernelTest): +class OrangePiMachine(LinuxKernelTest): ASSET_DEB = Asset( ('https://apt.armbian.com/pool/main/l/linux-6.6.16/' @@ -147,6 +147,8 @@ class BananaPiMachine(LinuxKernelTest): @skipBigDataTest() def test_arm_orangepi_armbian(self): self.set_machine('orangepi-pc') + self.require_netdev('user') + # This test download a 275 MiB compressed image and expand it # to 1036 MiB, but the underlying filesystem is 1552 MiB... # As we expand it to 2 GiB we are safe. @@ -181,6 +183,8 @@ class BananaPiMachine(LinuxKernelTest): @skipBigDataTest() def test_arm_orangepi_uboot_netbsd9(self): self.set_machine('orangepi-pc') + self.require_netdev('user') + # This test download a 304MB compressed image and expand it to 2GB # We use the common OrangePi PC 'plus' build of U-Boot for our secondary # program loader (SPL). We will then set the path to the more specific diff --git a/tests/functional/test_migration.py b/tests/functional/test_migration.py index 4480411..181223a 100755 --- a/tests/functional/test_migration.py +++ b/tests/functional/test_migration.py @@ -87,13 +87,12 @@ class MigrationTest(QemuSystemTest): dest_uri = 'unix:%s/qemu-test.sock' % socket_path self.do_migrate(dest_uri) - @skipIfMissingCommands('nc') + @skipIfMissingCommands('ncat') def test_migration_with_exec(self): - """The test works for both netcat-traditional and netcat-openbsd packages.""" with Ports() as ports: free_port = self._get_free_port(ports) - dest_uri = 'exec:nc -l localhost %u' % free_port - src_uri = 'exec:nc localhost %u' % free_port + dest_uri = 'exec:ncat -l localhost %u' % free_port + src_uri = 'exec:ncat localhost %u' % free_port self.do_migrate(dest_uri, src_uri) if __name__ == '__main__': diff --git a/tests/functional/test_ppc64_hv.py b/tests/functional/test_ppc64_hv.py index 62f996a..1920e91 100755 --- a/tests/functional/test_ppc64_hv.py +++ b/tests/functional/test_ppc64_hv.py @@ -125,6 +125,7 @@ class HypervisorTest(QemuSystemTest): def test_hv_pseries(self): self.require_accelerator("tcg") + self.require_netdev('user') self.set_machine('pseries') self.vm.add_args("-accel", "tcg,thread=multi") self.vm.add_args('-device', 'nvme,serial=1234,drive=drive0') @@ -136,6 +137,7 @@ class HypervisorTest(QemuSystemTest): def test_hv_pseries_kvm(self): self.require_accelerator("kvm") + self.require_netdev('user') self.set_machine('pseries') self.vm.add_args("-accel", "kvm") self.vm.add_args('-device', 'nvme,serial=1234,drive=drive0') @@ -147,6 +149,7 @@ class HypervisorTest(QemuSystemTest): def test_hv_powernv(self): self.require_accelerator("tcg") + self.require_netdev('user') self.set_machine('powernv') self.vm.add_args("-accel", "tcg,thread=multi") self.vm.add_args('-device', 'nvme,bus=pcie.2,addr=0x0,serial=1234,drive=drive0', diff --git a/tests/functional/test_ppc64_replay.py b/tests/functional/test_ppc64_replay.py index 48ce1b7..e8c9c4b 100755 --- a/tests/functional/test_ppc64_replay.py +++ b/tests/functional/test_ppc64_replay.py @@ -5,7 +5,7 @@ # # SPDX-License-Identifier: GPL-2.0-or-later -from qemu_test import Asset +from qemu_test import Asset, skipFlakyTest from replay_kernel import ReplayKernelBase @@ -16,6 +16,7 @@ class Ppc64Replay(ReplayKernelBase): 'day19.tar.xz'), '20b1bb5a8488c664defbb5d283addc91a05335a936c63b3f5ff7eee74b725755') + @skipFlakyTest('https://gitlab.com/qemu-project/qemu/-/issues/2523') def test_ppc64_e500(self): self.set_machine('ppce500') self.cpu = 'e5500' diff --git a/tests/functional/test_vnc.py b/tests/functional/test_vnc.py index 1916be0..8c9953b 100755 --- a/tests/functional/test_vnc.py +++ b/tests/functional/test_vnc.py @@ -12,6 +12,7 @@ import socket from typing import List +from qemu.machine.machine import VMLaunchFailure from qemu_test import QemuSystemTest from qemu_test.ports import Ports @@ -32,7 +33,14 @@ class Vnc(QemuSystemTest): def test_no_vnc_change_password(self): self.vm.add_args('-nodefaults', '-S') self.vm.launch() - self.assertFalse(self.vm.qmp('query-vnc')['return']['enabled']) + + query_vnc_response = self.vm.qmp('query-vnc') + if 'error' in query_vnc_response: + self.assertEqual(query_vnc_response['error']['class'], + 'CommandNotFound') + self.skipTest('VNC support not available') + self.assertFalse(query_vnc_response['return']['enabled']) + set_password_response = self.vm.qmp('change-vnc-password', password='new_password') self.assertIn('error', set_password_response) @@ -41,9 +49,19 @@ class Vnc(QemuSystemTest): self.assertEqual(set_password_response['error']['desc'], 'Could not set password') + def launch_guarded(self): + try: + self.vm.launch() + except VMLaunchFailure as excp: + if "-vnc: invalid option" in excp.output: + self.skipTest("VNC support not available") + else: + self.log.info("unhandled launch failure: %s", excp.output) + raise excp + def test_change_password_requires_a_password(self): self.vm.add_args('-nodefaults', '-S', '-vnc', ':1,to=999') - self.vm.launch() + self.launch_guarded() self.assertTrue(self.vm.qmp('query-vnc')['return']['enabled']) set_password_response = self.vm.qmp('change-vnc-password', password='new_password') @@ -55,7 +73,7 @@ class Vnc(QemuSystemTest): def test_change_password(self): self.vm.add_args('-nodefaults', '-S', '-vnc', ':1,to=999,password=on') - self.vm.launch() + self.launch_guarded() self.assertTrue(self.vm.qmp('query-vnc')['return']['enabled']) self.vm.cmd('change-vnc-password', password='new_password') @@ -66,7 +84,7 @@ class Vnc(QemuSystemTest): self.assertFalse(check_connect(c)) self.vm.add_args('-nodefaults', '-S', '-vnc', f'{VNC_ADDR}:{a - 5900}') - self.vm.launch() + self.launch_guarded() self.assertEqual(self.vm.qmp('query-vnc')['return']['service'], str(a)) self.assertTrue(check_connect(a)) self.assertFalse(check_connect(b)) diff --git a/tests/functional/test_x86_64_kvm_xen.py b/tests/functional/test_x86_64_kvm_xen.py index 0298c96..c6abf6b 100755 --- a/tests/functional/test_x86_64_kvm_xen.py +++ b/tests/functional/test_x86_64_kvm_xen.py @@ -41,6 +41,7 @@ class KVMXenGuest(QemuSystemTest): def common_vm_setup(self): # We also catch lack of KVM_XEN support if we fail to launch self.require_accelerator("kvm") + self.require_netdev('user') self.vm.set_console() @@ -80,10 +81,6 @@ class KVMXenGuest(QemuSystemTest): wait_for_console_pattern(self, '#', 'Oops') def test_kvm_xen_guest(self): - """ - :avocado: tags=kvm_xen_guest - """ - self.common_vm_setup() self.kernel_params = (self.KERNEL_DEFAULT + @@ -94,10 +91,6 @@ class KVMXenGuest(QemuSystemTest): 'virtio0-output') def test_kvm_xen_guest_nomsi(self): - """ - :avocado: tags=kvm_xen_guest_nomsi - """ - self.common_vm_setup() self.kernel_params = (self.KERNEL_DEFAULT + @@ -108,10 +101,6 @@ class KVMXenGuest(QemuSystemTest): 'virtio0') def test_kvm_xen_guest_noapic_nomsi(self): - """ - :avocado: tags=kvm_xen_guest_noapic_nomsi - """ - self.common_vm_setup() self.kernel_params = (self.KERNEL_DEFAULT + @@ -122,10 +111,6 @@ class KVMXenGuest(QemuSystemTest): 'virtio0') def test_kvm_xen_guest_vapic(self): - """ - :avocado: tags=kvm_xen_guest_vapic - """ - self.common_vm_setup() self.vm.add_args('-cpu', 'host,+xen-vapic') self.kernel_params = (self.KERNEL_DEFAULT + @@ -140,10 +125,6 @@ class KVMXenGuest(QemuSystemTest): 'virtio0-output') def test_kvm_xen_guest_novector(self): - """ - :avocado: tags=kvm_xen_guest_novector - """ - self.common_vm_setup() self.kernel_params = (self.KERNEL_DEFAULT + ' xen_emul_unplug=ide-disks' + @@ -154,10 +135,6 @@ class KVMXenGuest(QemuSystemTest): 'fasteoi') def test_kvm_xen_guest_novector_nomsi(self): - """ - :avocado: tags=kvm_xen_guest_novector_nomsi - """ - self.common_vm_setup() self.kernel_params = (self.KERNEL_DEFAULT + @@ -169,10 +146,6 @@ class KVMXenGuest(QemuSystemTest): 'IO-APIC') def test_kvm_xen_guest_novector_noapic(self): - """ - :avocado: tags=kvm_xen_guest_novector_noapic - """ - self.common_vm_setup() self.kernel_params = (self.KERNEL_DEFAULT + ' xen_emul_unplug=ide-disks' + |