From 7a169480636be494bf13ab487888eb7b1e2ab019 Mon Sep 17 00:00:00 2001 From: Jiabo Feng Date: Sat, 30 Nov 2024 08:36:49 +0800 Subject: [PATCH] QEMU update to version 8.2.0-24: - ppc/xive: Fix ESB length overflow on 32-bit hosts - target/hppa: Fix PSW V-bit packaging in cpu_hppa_get for hppa64 - target/ppc: Fix migration of CPUs with TLB_EMB TLB type - target/arm: Clear high SVE elements in handle_vec_simd_wshli - module: Prevent crash by resetting local_err in module_load_qom_all() - tests/docker: update debian i686 and mipsel images to bookworm - target/arm: Fix SVE SDOT/UDOT/USDOT (4-way, indexed) - docs/sphinx/depfile.py: Handle env.doc2path() returning a Path not a str - block/blkio: use FUA flag on write zeroes only if supported - virtio-pci: Fix the use of an uninitialized irqfd - hw/cxl: Ensure there is enough data to read the input header in cmd_get_physical_port_state() - intel_iommu: Send IQE event when setting reserved bit in IQT_TAIL - virtio-net: Avoid indirection_table_mask overflow - Fix calculation of minimum in colo_compare_tcp - target/riscv/csr.c: Fix an access to VXSAT - linux-user: Clean up unused header - raw-format: Fix error message for invalid offset/size - hw/loongarch/virt: Remove unnecessary 'cpu.h' inclusion - tests: Wait for migration completion on destination QEMU to avoid failures - acpi: ged: Add macro for acpi sleep control register - hw/intc/openpic: Improve errors for out of bounds property values - hw/pci-bridge: Add a Kconfig switch for the normal PCI bridge - docs/tools/qemu-img.rst: fix typo (sumarizes) - audio/pw: Report more accurate error when connecting to PipeWire fails - audio/pw: Report more accurate error when connecting to PipeWire fails - dma: Fix function names in documentation Ensure the function names match. - edu: fix DMA range upper bound check - platform-bus: fix refcount leak - hw/net/can/sja1000: fix bug for single acceptance filter and standard frame - tests/avocado: fix typo in replay_linux - util/userfaultfd: Remove unused uffd_poll_events - Consider discard option when writing zeros - crypto: factor out conversion of QAPI to gcrypt constants - crypto: drop gnutls debug logging support - crypto: use consistent error reporting pattern for unsupported cipher modes - hw/gpio/aspeed_gpio: Avoid shift into sign bit Signed-off-by: Jiabo Feng (cherry picked from commit b6e04df301d30895427ab41a1edff0f40149bdd9) --- ...er-discard-option-when-writing-zeros.patch | 287 ++++++ ...ation-of-minimum-in-colo_compare_tcp.patch | 35 + ...acro-for-acpi-sleep-control-register.patch | 59 ++ ...-accurate-error-when-connecting--new.patch | 899 +++++++++++++++++ ...more-accurate-error-when-connecting-.patch | 931 ++++++++++++++++++ ...FUA-flag-on-write-zeroes-only-if-sup.patch | 61 ++ ...to-drop-gnutls-debug-logging-support.patch | 57 ++ ...t-conversion-of-QAPI-to-gcrypt-const.patch | 168 ++++ ...stent-error-reporting-pattern-for-un.patch | 78 ++ dma-Fix-function-names-in-documentation.patch | 61 ++ ...ile.py-Handle-env.doc2path-returning.patch | 52 + ...ools-qemu-img.rst-fix-typo-sumarizes.patch | 31 + edu-fix-DMA-range-upper-bound-check.patch | 47 + ...ere-is-enough-data-to-read-the-input.patch | 37 + ...speed_gpio-Avoid-shift-into-sign-bit.patch | 36 + ...Improve-errors-for-out-of-bounds-pro.patch | 51 + ...t-Remove-unnecessary-cpu.h-inclusion.patch | 33 + ...00-fix-bug-for-single-acceptance-fil.patch | 43 + ...d-a-Kconfig-switch-for-the-normal-PC.patch | 50 + ...-IQE-event-when-setting-reserved-bit.patch | 39 + linux-user-Clean-up-unused-header.patch | 35 + ...rash-by-resetting-local_err-in-modul.patch | 45 + platform-bus-fix-refcount-leak.patch | 42 + ...-ESB-length-overflow-on-32-bit-hosts.patch | 69 ++ qemu.spec | 76 +- ...rror-message-for-invalid-offset-size.patch | 48 + ...-high-SVE-elements-in-handle_vec_sim.patch | 34 + ...ix-SVE-SDOT-UDOT-USDOT-4-way-indexed.patch | 73 ++ ...PSW-V-bit-packaging-in-cpu_hppa_get-.patch | 58 ++ ...igration-of-CPUs-with-TLB_EMB-TLB-ty.patch | 55 ++ ...t-riscv-csr.c-Fix-an-access-to-VXSAT.patch | 52 + ...igration-completion-on-destination-Q.patch | 44 + tests-avocado-fix-typo-in-replay_linux.patch | 36 + ...ate-debian-i686-and-mipsel-images-to.patch | 154 +++ ...ultfd-Remove-unused-uffd_poll_events.patch | 71 ++ ...void-indirection_table_mask-overflow.patch | 48 + ...ix-the-use-of-an-uninitialized-irqfd.patch | 80 ++ 37 files changed, 4074 insertions(+), 1 deletion(-) create mode 100644 Consider-discard-option-when-writing-zeros.patch create mode 100644 Fix-calculation-of-minimum-in-colo_compare_tcp.patch create mode 100644 acpi-ged-Add-macro-for-acpi-sleep-control-register.patch create mode 100644 audio-pw-Report-more-accurate-error-when-connecting--new.patch create mode 100644 audio-pw-Report-more-accurate-error-when-connecting-.patch create mode 100644 block-blkio-use-FUA-flag-on-write-zeroes-only-if-sup.patch create mode 100644 crypto-drop-gnutls-debug-logging-support.patch create mode 100644 crypto-factor-out-conversion-of-QAPI-to-gcrypt-const.patch create mode 100644 crypto-use-consistent-error-reporting-pattern-for-un.patch create mode 100644 dma-Fix-function-names-in-documentation.patch create mode 100644 docs-sphinx-depfile.py-Handle-env.doc2path-returning.patch create mode 100644 docs-tools-qemu-img.rst-fix-typo-sumarizes.patch create mode 100644 edu-fix-DMA-range-upper-bound-check.patch create mode 100644 hw-cxl-Ensure-there-is-enough-data-to-read-the-input.patch create mode 100644 hw-gpio-aspeed_gpio-Avoid-shift-into-sign-bit.patch create mode 100644 hw-intc-openpic-Improve-errors-for-out-of-bounds-pro.patch create mode 100644 hw-loongarch-virt-Remove-unnecessary-cpu.h-inclusion.patch create mode 100644 hw-net-can-sja1000-fix-bug-for-single-acceptance-fil.patch create mode 100644 hw-pci-bridge-Add-a-Kconfig-switch-for-the-normal-PC.patch create mode 100644 intel_iommu-Send-IQE-event-when-setting-reserved-bit.patch create mode 100644 linux-user-Clean-up-unused-header.patch create mode 100644 module-Prevent-crash-by-resetting-local_err-in-modul.patch create mode 100644 platform-bus-fix-refcount-leak.patch create mode 100644 ppc-xive-Fix-ESB-length-overflow-on-32-bit-hosts.patch create mode 100644 raw-format-Fix-error-message-for-invalid-offset-size.patch create mode 100644 target-arm-Clear-high-SVE-elements-in-handle_vec_sim.patch create mode 100644 target-arm-Fix-SVE-SDOT-UDOT-USDOT-4-way-indexed.patch create mode 100644 target-hppa-Fix-PSW-V-bit-packaging-in-cpu_hppa_get-.patch create mode 100644 target-ppc-Fix-migration-of-CPUs-with-TLB_EMB-TLB-ty.patch create mode 100644 target-riscv-csr.c-Fix-an-access-to-VXSAT.patch create mode 100644 tests-Wait-for-migration-completion-on-destination-Q.patch create mode 100644 tests-avocado-fix-typo-in-replay_linux.patch create mode 100644 tests-docker-update-debian-i686-and-mipsel-images-to.patch create mode 100644 util-userfaultfd-Remove-unused-uffd_poll_events.patch create mode 100644 virtio-net-Avoid-indirection_table_mask-overflow.patch create mode 100644 virtio-pci-Fix-the-use-of-an-uninitialized-irqfd.patch diff --git a/Consider-discard-option-when-writing-zeros.patch b/Consider-discard-option-when-writing-zeros.patch new file mode 100644 index 00000000..7649a823 --- /dev/null +++ b/Consider-discard-option-when-writing-zeros.patch @@ -0,0 +1,287 @@ +From 60b9463e35fe801e49db14539ccb8c9a6057e5c3 Mon Sep 17 00:00:00 2001 +From: dinglimin +Date: Sat, 12 Oct 2024 14:12:17 +0800 +Subject: [PATCH] Consider discard option when writing zeros + +When opening an image with discard=off, we punch hole in the image when +writing zeroes, making the image sparse. This breaks users that want to +ensure that writes cannot fail with ENOSPACE by using fully allocated +images[1]. + +bdrv_co_pwrite_zeroes() correctly disables BDRV_REQ_MAY_UNMAP if we +opened the child without discard=unmap or discard=on. But we don't go +through this function when accessing the top node. Move the check down +to bdrv_co_do_pwrite_zeroes() which seems to be used in all code paths. + +This change implements the documented behavior, punching holes only when +opening the image with discard=on or discard=unmap. This may not be the +best default but can improve it later. + +The test depends on a file system supporting discard, deallocating the +entire file when punching hole with the length of the entire file. +Tested with xfs, ext4, and tmpfs. + +[1] https://lists.nongnu.org/archive/html/qemu-discuss/2024-06/msg00003.html + +Signed-off-by: Nir Soffer +Message-id: 20240628202058.1964986-3-nsoffer@redhat.com +Signed-off-by: Stefan Hajnoczi +Signed-off-by: dinglimin +--- + block/io.c | 9 +- + tests/qemu-iotests/tests/write-zeroes-unmap | 127 ++++++++++++++++++ + .../qemu-iotests/tests/write-zeroes-unmap.out | 81 +++++++++++ + 3 files changed, 213 insertions(+), 4 deletions(-) + create mode 100644 tests/qemu-iotests/tests/write-zeroes-unmap + create mode 100644 tests/qemu-iotests/tests/write-zeroes-unmap.out + +diff --git a/block/io.c b/block/io.c +index 7e62fabbf5..a280a5a4c9 100644 +--- a/block/io.c ++++ b/block/io.c +@@ -1885,6 +1885,11 @@ bdrv_co_do_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int64_t bytes, + return -EINVAL; + } + ++ /* If opened with discard=off we should never unmap. */ ++ if (!(bs->open_flags & BDRV_O_UNMAP)) { ++ flags &= ~BDRV_REQ_MAY_UNMAP; ++ } ++ + /* Invalidate the cached block-status data range if this write overlaps */ + bdrv_bsc_invalidate_range(bs, offset, bytes); + +@@ -2338,10 +2343,6 @@ int coroutine_fn bdrv_co_pwrite_zeroes(BdrvChild *child, int64_t offset, + trace_bdrv_co_pwrite_zeroes(child->bs, offset, bytes, flags); + assert_bdrv_graph_readable(); + +- if (!(child->bs->open_flags & BDRV_O_UNMAP)) { +- flags &= ~BDRV_REQ_MAY_UNMAP; +- } +- + return bdrv_co_pwritev(child, offset, bytes, NULL, + BDRV_REQ_ZERO_WRITE | flags); + } +diff --git a/tests/qemu-iotests/tests/write-zeroes-unmap b/tests/qemu-iotests/tests/write-zeroes-unmap +new file mode 100644 +index 0000000000..7cfeeaf839 +--- /dev/null ++++ b/tests/qemu-iotests/tests/write-zeroes-unmap +@@ -0,0 +1,127 @@ ++#!/usr/bin/env bash ++# group: quick ++# ++# Test write zeros unmap. ++# ++# Copyright (C) Red Hat, Inc. ++# ++# This program is free software; you can redistribute it and/or modify ++# it under the terms of the GNU General Public License as published by ++# the Free Software Foundation; either version 2 of the License, or ++# (at your option) any later version. ++# ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++# ++# You should have received a copy of the GNU General Public License ++# along with this program. If not, see . ++# ++ ++seq="$(basename $0)" ++echo "QA output created by $seq" ++ ++trap _cleanup_test_img exit ++ ++# get standard environment, filters and checks ++cd .. ++. ./common.rc ++. ./common.filter ++ ++_supported_fmt raw ++_supported_proto file ++_supported_os Linux ++ ++create_test_image() { ++ _make_test_img -f $IMGFMT 1m ++} ++ ++filter_command() { ++ _filter_testdir | _filter_qemu_io | _filter_qemu | _filter_hmp ++} ++ ++print_disk_usage() { ++ du -sh $TEST_IMG | _filter_testdir ++} ++ ++echo ++echo "=== defaults - write zeros ===" ++echo ++ ++create_test_image ++echo -e 'qemu-io none0 "write -z 0 1m"\nquit' \ ++ | $QEMU -monitor stdio -drive if=none,file=$TEST_IMG,format=$IMGFMT \ ++ | filter_command ++print_disk_usage ++ ++echo ++echo "=== defaults - write zeros unmap ===" ++echo ++ ++create_test_image ++echo -e 'qemu-io none0 "write -zu 0 1m"\nquit' \ ++ | $QEMU -monitor stdio -drive if=none,file=$TEST_IMG,format=$IMGFMT \ ++ | filter_command ++print_disk_usage ++ ++ ++echo ++echo "=== defaults - write actual zeros ===" ++echo ++ ++create_test_image ++echo -e 'qemu-io none0 "write -P 0 0 1m"\nquit' \ ++ | $QEMU -monitor stdio -drive if=none,file=$TEST_IMG,format=$IMGFMT \ ++ | filter_command ++print_disk_usage ++ ++echo ++echo "=== discard=off - write zeroes unmap ===" ++echo ++ ++create_test_image ++echo -e 'qemu-io none0 "write -zu 0 1m"\nquit' \ ++ | $QEMU -monitor stdio -drive if=none,file=$TEST_IMG,format=$IMGFMT,discard=off \ ++ | filter_command ++print_disk_usage ++ ++echo ++echo "=== detect-zeroes=on - write actual zeros ===" ++echo ++ ++create_test_image ++echo -e 'qemu-io none0 "write -P 0 0 1m"\nquit' \ ++ | $QEMU -monitor stdio -drive if=none,file=$TEST_IMG,format=$IMGFMT,detect-zeroes=on \ ++ | filter_command ++print_disk_usage ++ ++echo ++echo "=== detect-zeroes=on,discard=on - write actual zeros ===" ++echo ++ ++create_test_image ++echo -e 'qemu-io none0 "write -P 0 0 1m"\nquit' \ ++ | $QEMU -monitor stdio -drive if=none,file=$TEST_IMG,format=$IMGFMT,detect-zeroes=on,discard=on \ ++ | filter_command ++print_disk_usage ++ ++echo ++echo "=== discard=on - write zeroes ===" ++echo ++ ++create_test_image ++echo -e 'qemu-io none0 "write -z 0 1m"\nquit' \ ++ | $QEMU -monitor stdio -drive if=none,file=$TEST_IMG,format=$IMGFMT,discard=on \ ++ | filter_command ++print_disk_usage ++ ++echo ++echo "=== discard=on - write zeroes unmap ===" ++echo ++ ++create_test_image ++echo -e 'qemu-io none0 "write -zu 0 1m"\nquit' \ ++ | $QEMU -monitor stdio -drive if=none,file=$TEST_IMG,format=$IMGFMT,discard=on \ ++ | filter_command ++print_disk_usage +diff --git a/tests/qemu-iotests/tests/write-zeroes-unmap.out b/tests/qemu-iotests/tests/write-zeroes-unmap.out +new file mode 100644 +index 0000000000..c931994897 +--- /dev/null ++++ b/tests/qemu-iotests/tests/write-zeroes-unmap.out +@@ -0,0 +1,81 @@ ++QA output created by write-zeroes-unmap ++ ++=== defaults - write zeros === ++ ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 ++QEMU X.Y.Z monitor - type 'help' for more information ++(qemu) qemu-io none0 "write -z 0 1m" ++wrote 1048576/1048576 bytes at offset 0 ++1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++(qemu) quit ++1.0M TEST_DIR/t.raw ++ ++=== defaults - write zeros unmap === ++ ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 ++QEMU X.Y.Z monitor - type 'help' for more information ++(qemu) qemu-io none0 "write -zu 0 1m" ++wrote 1048576/1048576 bytes at offset 0 ++1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++(qemu) quit ++1.0M TEST_DIR/t.raw ++ ++=== defaults - write actual zeros === ++ ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 ++QEMU X.Y.Z monitor - type 'help' for more information ++(qemu) qemu-io none0 "write -P 0 0 1m" ++wrote 1048576/1048576 bytes at offset 0 ++1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++(qemu) quit ++1.0M TEST_DIR/t.raw ++ ++=== discard=off - write zeroes unmap === ++ ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 ++QEMU X.Y.Z monitor - type 'help' for more information ++(qemu) qemu-io none0 "write -zu 0 1m" ++wrote 1048576/1048576 bytes at offset 0 ++1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++(qemu) quit ++1.0M TEST_DIR/t.raw ++ ++=== detect-zeroes=on - write actual zeros === ++ ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 ++QEMU X.Y.Z monitor - type 'help' for more information ++(qemu) qemu-io none0 "write -P 0 0 1m" ++wrote 1048576/1048576 bytes at offset 0 ++1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++(qemu) quit ++1.0M TEST_DIR/t.raw ++ ++=== detect-zeroes=on,discard=on - write actual zeros === ++ ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 ++QEMU X.Y.Z monitor - type 'help' for more information ++(qemu) qemu-io none0 "write -P 0 0 1m" ++wrote 1048576/1048576 bytes at offset 0 ++1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++(qemu) quit ++1.0M TEST_DIR/t.raw ++ ++=== discard=on - write zeroes === ++ ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 ++QEMU X.Y.Z monitor - type 'help' for more information ++(qemu) qemu-io none0 "write -z 0 1m" ++wrote 1048576/1048576 bytes at offset 0 ++1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++(qemu) quit ++1.0M TEST_DIR/t.raw ++ ++=== discard=on - write zeroes unmap === ++ ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 ++QEMU X.Y.Z monitor - type 'help' for more information ++(qemu) qemu-io none0 "write -zu 0 1m" ++wrote 1048576/1048576 bytes at offset 0 ++1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++(qemu) quit ++0 TEST_DIR/t.raw +-- +2.41.0.windows.1 + diff --git a/Fix-calculation-of-minimum-in-colo_compare_tcp.patch b/Fix-calculation-of-minimum-in-colo_compare_tcp.patch new file mode 100644 index 00000000..b0178f50 --- /dev/null +++ b/Fix-calculation-of-minimum-in-colo_compare_tcp.patch @@ -0,0 +1,35 @@ +From f6ad72a5b215bc5b2d8df86cd537bf1c0f468108 Mon Sep 17 00:00:00 2001 +From: zhangchujun +Date: Wed, 30 Oct 2024 13:33:58 +0800 +Subject: [PATCH] Fix calculation of minimum in colo_compare_tcp + +GitHub's CodeQL reports a critical error which is fixed by using the MIN macro: + + Unsigned difference expression compared to zero + +Signed-off-by: Stefan Weil +Cc: qemu-stable@nongnu.org +Reviewed-by: Zhang Chen +Signed-off-by: Jason Wang +Signed-off-by: zhangchujun +--- + net/colo-compare.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/net/colo-compare.c b/net/colo-compare.c +index 7f9e6f89ce..d4e51cb306 100644 +--- a/net/colo-compare.c ++++ b/net/colo-compare.c +@@ -413,8 +413,7 @@ static void colo_compare_tcp(CompareState *s, Connection *conn) + * can ensure that the packet's payload is acknowledged by + * primary and secondary. + */ +- uint32_t min_ack = conn->pack - conn->sack > 0 ? +- conn->sack : conn->pack; ++ uint32_t min_ack = MIN(conn->pack, conn->sack); + + pri: + if (g_queue_is_empty(&conn->primary_list)) { +-- +2.41.0.windows.1 + diff --git a/acpi-ged-Add-macro-for-acpi-sleep-control-register.patch b/acpi-ged-Add-macro-for-acpi-sleep-control-register.patch new file mode 100644 index 00000000..61ebd380 --- /dev/null +++ b/acpi-ged-Add-macro-for-acpi-sleep-control-register.patch @@ -0,0 +1,59 @@ +From 07fa80eacaa17d3cc3865050244b79d39cc61944 Mon Sep 17 00:00:00 2001 +From: Zhang Jiao +Date: Wed, 23 Oct 2024 14:34:56 +0800 +Subject: [PATCH] acpi: ged: Add macro for acpi sleep control register + +cheery-pick from edafc90ba481c586d0a649f34dcb8cd1f29c4259 + +Macro definition is added for acpi sleep control register, ged emulation +driver can use the macro , also it can be used in FDT table if ged is +exposed with FDT table. + +Signed-off-by: Bibo Mao +Reviewed-by: Igor Mammedov +Message-Id: <20240918014206.2165821-2-maobibo@loongson.cn> +Signed-off-by: Song Gao +Signed-off-by: Zhang Jiao +--- + hw/acpi/generic_event_device.c | 6 +++--- + include/hw/acpi/generic_event_device.h | 7 +++++-- + 2 files changed, 8 insertions(+), 5 deletions(-) + +diff --git a/hw/acpi/generic_event_device.c b/hw/acpi/generic_event_device.c +index 4731a614a3..2ce7031f1a 100644 +--- a/hw/acpi/generic_event_device.c ++++ b/hw/acpi/generic_event_device.c +@@ -203,9 +203,9 @@ static void ged_regs_write(void *opaque, hwaddr addr, uint64_t data, + + switch (addr) { + case ACPI_GED_REG_SLEEP_CTL: +- slp_typ = (data >> 2) & 0x07; +- slp_en = (data >> 5) & 0x01; +- if (slp_en && slp_typ == 5) { ++ slp_typ = (data >> ACPI_GED_SLP_TYP_POS) & ACPI_GED_SLP_TYP_MASK; ++ slp_en = !!(data & ACPI_GED_SLP_EN); ++ if (slp_en && slp_typ == ACPI_GED_SLP_TYP_S5) { + qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN); + } + return; +diff --git a/include/hw/acpi/generic_event_device.h b/include/hw/acpi/generic_event_device.h +index 90fc41cbb8..8ed9534c57 100644 +--- a/include/hw/acpi/generic_event_device.h ++++ b/include/hw/acpi/generic_event_device.h +@@ -81,8 +81,11 @@ OBJECT_DECLARE_SIMPLE_TYPE(AcpiGedState, ACPI_GED) + /* ACPI_GED_REG_RESET value for reset*/ + #define ACPI_GED_RESET_VALUE 0x42 + +-/* ACPI_GED_REG_SLEEP_CTL.SLP_TYP value for S5 (aka poweroff) */ +-#define ACPI_GED_SLP_TYP_S5 0x05 ++/* [ACPI 5.0 Chapter 4.8.3.7] Sleep Control and Status Register */ ++#define ACPI_GED_SLP_TYP_POS 0x2 /* SLP_TYPx Bit Offset */ ++#define ACPI_GED_SLP_TYP_MASK 0x07 /* SLP_TYPx 3-bit mask */ ++#define ACPI_GED_SLP_TYP_S5 0x05 /* System _S5 State (Soft Off) */ ++#define ACPI_GED_SLP_EN 0x20 /* SLP_EN write-only bit */ + + #define GED_DEVICE "GED" + #define AML_GED_EVT_REG "EREG" +-- +2.41.0.windows.1 + diff --git a/audio-pw-Report-more-accurate-error-when-connecting--new.patch b/audio-pw-Report-more-accurate-error-when-connecting--new.patch new file mode 100644 index 00000000..390c9658 --- /dev/null +++ b/audio-pw-Report-more-accurate-error-when-connecting--new.patch @@ -0,0 +1,899 @@ +From 6adb429abb287b3143ed447b334aa89c1a1c0d71 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?=E5=BC=A0=E6=A5=9A=E5=90=9B?= + +Date: Fri, 18 Oct 2024 10:29:16 +0800 +Subject: [PATCH] audio/pw: Report more accurate error when connecting to + PipeWire fails +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +According to its man page [1], pw_context_connect() sets errno on +failure: + + Returns a Core on success or NULL with errno set on error. + +It may be handy to see errno when figuring out why PipeWire +failed to connect. That leaves us with just one possible path to +reach 'fail_error' label which is then moved to that path and +also its error message is adjusted slightly. + +1: https://docs.pipewire.org/group__pw__core.html#ga5994e3a54e4ec718094ca02a1234815b + +Signed-off-by: Michal Privoznik +Reviewed-by: Manos Pitsidianakis +Reviewed-by: Marc-André Lureau +Message-ID: <3a78811ad5b0e87816b7616ab21d2eeef00b9c52.1726647033.git.mprivozn@redhat.com> +Signed-off-by: Zhang Chujun +--- + audio/pwaudio.c.orig | 858 ------------------------------------------- + 1 file changed, 858 deletions(-) + delete mode 100644 audio/pwaudio.c.orig + +diff --git a/audio/pwaudio.c.orig b/audio/pwaudio.c.orig +deleted file mode 100644 +index 3ce5f6507b..0000000000 +--- a/audio/pwaudio.c.orig ++++ /dev/null +@@ -1,858 +0,0 @@ +-/* +- * QEMU PipeWire audio driver +- * +- * Copyright (c) 2023 Red Hat Inc. +- * +- * Author: Dorinda Bassey +- * +- * SPDX-License-Identifier: GPL-2.0-or-later +- */ +- +-#include "qemu/osdep.h" +-#include "qemu/module.h" +-#include "audio.h" +-#include +-#include "qemu/error-report.h" +-#include "qapi/error.h" +-#include +-#include +-#include +-#include +- +-#include +-#include "trace.h" +- +-#define AUDIO_CAP "pipewire" +-#define RINGBUFFER_SIZE (1u << 22) +-#define RINGBUFFER_MASK (RINGBUFFER_SIZE - 1) +- +-#include "audio_int.h" +- +-typedef struct pwvolume { +- uint32_t channels; +- float values[SPA_AUDIO_MAX_CHANNELS]; +-} pwvolume; +- +-typedef struct pwaudio { +- Audiodev *dev; +- struct pw_thread_loop *thread_loop; +- struct pw_context *context; +- +- struct pw_core *core; +- struct spa_hook core_listener; +- int last_seq, pending_seq, error; +-} pwaudio; +- +-typedef struct PWVoice { +- pwaudio *g; +- struct pw_stream *stream; +- struct spa_hook stream_listener; +- struct spa_audio_info_raw info; +- uint32_t highwater_mark; +- uint32_t frame_size, req; +- struct spa_ringbuffer ring; +- uint8_t buffer[RINGBUFFER_SIZE]; +- +- pwvolume volume; +- bool muted; +-} PWVoice; +- +-typedef struct PWVoiceOut { +- HWVoiceOut hw; +- PWVoice v; +-} PWVoiceOut; +- +-typedef struct PWVoiceIn { +- HWVoiceIn hw; +- PWVoice v; +-} PWVoiceIn; +- +-#define PW_VOICE_IN(v) ((PWVoiceIn *)v) +-#define PW_VOICE_OUT(v) ((PWVoiceOut *)v) +- +-static void +-stream_destroy(void *data) +-{ +- PWVoice *v = (PWVoice *) data; +- spa_hook_remove(&v->stream_listener); +- v->stream = NULL; +-} +- +-/* output data processing function to read stuffs from the buffer */ +-static void +-playback_on_process(void *data) +-{ +- PWVoice *v = data; +- void *p; +- struct pw_buffer *b; +- struct spa_buffer *buf; +- uint32_t req, index, n_bytes; +- int32_t avail; +- +- assert(v->stream); +- +- /* obtain a buffer to read from */ +- b = pw_stream_dequeue_buffer(v->stream); +- if (b == NULL) { +- error_report("out of buffers: %s", strerror(errno)); +- return; +- } +- +- buf = b->buffer; +- p = buf->datas[0].data; +- if (p == NULL) { +- return; +- } +- /* calculate the total no of bytes to read data from buffer */ +- req = b->requested * v->frame_size; +- if (req == 0) { +- req = v->req; +- } +- n_bytes = SPA_MIN(req, buf->datas[0].maxsize); +- +- /* get no of available bytes to read data from buffer */ +- avail = spa_ringbuffer_get_read_index(&v->ring, &index); +- +- if (avail <= 0) { +- PWVoiceOut *vo = container_of(data, PWVoiceOut, v); +- audio_pcm_info_clear_buf(&vo->hw.info, p, n_bytes / v->frame_size); +- } else { +- if ((uint32_t) avail < n_bytes) { +- /* +- * PipeWire immediately calls this callback again if we provide +- * less than n_bytes. Then audio_pcm_info_clear_buf() fills the +- * rest of the buffer with silence. +- */ +- n_bytes = avail; +- } +- +- spa_ringbuffer_read_data(&v->ring, +- v->buffer, RINGBUFFER_SIZE, +- index & RINGBUFFER_MASK, p, n_bytes); +- +- index += n_bytes; +- spa_ringbuffer_read_update(&v->ring, index); +- +- } +- buf->datas[0].chunk->offset = 0; +- buf->datas[0].chunk->stride = v->frame_size; +- buf->datas[0].chunk->size = n_bytes; +- +- /* queue the buffer for playback */ +- pw_stream_queue_buffer(v->stream, b); +-} +- +-/* output data processing function to generate stuffs in the buffer */ +-static void +-capture_on_process(void *data) +-{ +- PWVoice *v = (PWVoice *) data; +- void *p; +- struct pw_buffer *b; +- struct spa_buffer *buf; +- int32_t filled; +- uint32_t index, offs, n_bytes; +- +- assert(v->stream); +- +- /* obtain a buffer */ +- b = pw_stream_dequeue_buffer(v->stream); +- if (b == NULL) { +- error_report("out of buffers: %s", strerror(errno)); +- return; +- } +- +- /* Write data into buffer */ +- buf = b->buffer; +- p = buf->datas[0].data; +- if (p == NULL) { +- return; +- } +- offs = SPA_MIN(buf->datas[0].chunk->offset, buf->datas[0].maxsize); +- n_bytes = SPA_MIN(buf->datas[0].chunk->size, buf->datas[0].maxsize - offs); +- +- filled = spa_ringbuffer_get_write_index(&v->ring, &index); +- +- +- if (filled < 0) { +- error_report("%p: underrun write:%u filled:%d", p, index, filled); +- } else { +- if ((uint32_t) filled + n_bytes > RINGBUFFER_SIZE) { +- error_report("%p: overrun write:%u filled:%d + size:%u > max:%u", +- p, index, filled, n_bytes, RINGBUFFER_SIZE); +- } +- } +- spa_ringbuffer_write_data(&v->ring, +- v->buffer, RINGBUFFER_SIZE, +- index & RINGBUFFER_MASK, +- SPA_PTROFF(p, offs, void), n_bytes); +- index += n_bytes; +- spa_ringbuffer_write_update(&v->ring, index); +- +- /* queue the buffer for playback */ +- pw_stream_queue_buffer(v->stream, b); +-} +- +-static void +-on_stream_state_changed(void *data, enum pw_stream_state old, +- enum pw_stream_state state, const char *error) +-{ +- PWVoice *v = (PWVoice *) data; +- +- trace_pw_state_changed(pw_stream_get_node_id(v->stream), +- pw_stream_state_as_string(state)); +-} +- +-static const struct pw_stream_events capture_stream_events = { +- PW_VERSION_STREAM_EVENTS, +- .destroy = stream_destroy, +- .state_changed = on_stream_state_changed, +- .process = capture_on_process +-}; +- +-static const struct pw_stream_events playback_stream_events = { +- PW_VERSION_STREAM_EVENTS, +- .destroy = stream_destroy, +- .state_changed = on_stream_state_changed, +- .process = playback_on_process +-}; +- +-static size_t +-qpw_read(HWVoiceIn *hw, void *data, size_t len) +-{ +- PWVoiceIn *pw = (PWVoiceIn *) hw; +- PWVoice *v = &pw->v; +- pwaudio *c = v->g; +- const char *error = NULL; +- size_t l; +- int32_t avail; +- uint32_t index; +- +- pw_thread_loop_lock(c->thread_loop); +- if (pw_stream_get_state(v->stream, &error) != PW_STREAM_STATE_STREAMING) { +- /* wait for stream to become ready */ +- l = 0; +- goto done_unlock; +- } +- /* get no of available bytes to read data from buffer */ +- avail = spa_ringbuffer_get_read_index(&v->ring, &index); +- +- trace_pw_read(avail, index, len); +- +- if (avail < (int32_t) len) { +- len = avail; +- } +- +- spa_ringbuffer_read_data(&v->ring, +- v->buffer, RINGBUFFER_SIZE, +- index & RINGBUFFER_MASK, data, len); +- index += len; +- spa_ringbuffer_read_update(&v->ring, index); +- l = len; +- +-done_unlock: +- pw_thread_loop_unlock(c->thread_loop); +- return l; +-} +- +-static size_t qpw_buffer_get_free(HWVoiceOut *hw) +-{ +- PWVoiceOut *pw = (PWVoiceOut *)hw; +- PWVoice *v = &pw->v; +- pwaudio *c = v->g; +- const char *error = NULL; +- int32_t filled, avail; +- uint32_t index; +- +- pw_thread_loop_lock(c->thread_loop); +- if (pw_stream_get_state(v->stream, &error) != PW_STREAM_STATE_STREAMING) { +- /* wait for stream to become ready */ +- avail = 0; +- goto done_unlock; +- } +- +- filled = spa_ringbuffer_get_write_index(&v->ring, &index); +- avail = v->highwater_mark - filled; +- +-done_unlock: +- pw_thread_loop_unlock(c->thread_loop); +- return avail; +-} +- +-static size_t +-qpw_write(HWVoiceOut *hw, void *data, size_t len) +-{ +- PWVoiceOut *pw = (PWVoiceOut *) hw; +- PWVoice *v = &pw->v; +- pwaudio *c = v->g; +- const char *error = NULL; +- int32_t filled, avail; +- uint32_t index; +- +- pw_thread_loop_lock(c->thread_loop); +- if (pw_stream_get_state(v->stream, &error) != PW_STREAM_STATE_STREAMING) { +- /* wait for stream to become ready */ +- len = 0; +- goto done_unlock; +- } +- filled = spa_ringbuffer_get_write_index(&v->ring, &index); +- avail = v->highwater_mark - filled; +- +- trace_pw_write(filled, avail, index, len); +- +- if (len > avail) { +- len = avail; +- } +- +- if (filled < 0) { +- error_report("%p: underrun write:%u filled:%d", pw, index, filled); +- } else { +- if ((uint32_t) filled + len > RINGBUFFER_SIZE) { +- error_report("%p: overrun write:%u filled:%d + size:%zu > max:%u", +- pw, index, filled, len, RINGBUFFER_SIZE); +- } +- } +- +- spa_ringbuffer_write_data(&v->ring, +- v->buffer, RINGBUFFER_SIZE, +- index & RINGBUFFER_MASK, data, len); +- index += len; +- spa_ringbuffer_write_update(&v->ring, index); +- +-done_unlock: +- pw_thread_loop_unlock(c->thread_loop); +- return len; +-} +- +-static int +-audfmt_to_pw(AudioFormat fmt, int endianness) +-{ +- int format; +- +- switch (fmt) { +- case AUDIO_FORMAT_S8: +- format = SPA_AUDIO_FORMAT_S8; +- break; +- case AUDIO_FORMAT_U8: +- format = SPA_AUDIO_FORMAT_U8; +- break; +- case AUDIO_FORMAT_S16: +- format = endianness ? SPA_AUDIO_FORMAT_S16_BE : SPA_AUDIO_FORMAT_S16_LE; +- break; +- case AUDIO_FORMAT_U16: +- format = endianness ? SPA_AUDIO_FORMAT_U16_BE : SPA_AUDIO_FORMAT_U16_LE; +- break; +- case AUDIO_FORMAT_S32: +- format = endianness ? SPA_AUDIO_FORMAT_S32_BE : SPA_AUDIO_FORMAT_S32_LE; +- break; +- case AUDIO_FORMAT_U32: +- format = endianness ? SPA_AUDIO_FORMAT_U32_BE : SPA_AUDIO_FORMAT_U32_LE; +- break; +- case AUDIO_FORMAT_F32: +- format = endianness ? SPA_AUDIO_FORMAT_F32_BE : SPA_AUDIO_FORMAT_F32_LE; +- break; +- default: +- dolog("Internal logic error: Bad audio format %d\n", fmt); +- format = SPA_AUDIO_FORMAT_U8; +- break; +- } +- return format; +-} +- +-static AudioFormat +-pw_to_audfmt(enum spa_audio_format fmt, int *endianness, +- uint32_t *sample_size) +-{ +- switch (fmt) { +- case SPA_AUDIO_FORMAT_S8: +- *sample_size = 1; +- return AUDIO_FORMAT_S8; +- case SPA_AUDIO_FORMAT_U8: +- *sample_size = 1; +- return AUDIO_FORMAT_U8; +- case SPA_AUDIO_FORMAT_S16_BE: +- *sample_size = 2; +- *endianness = 1; +- return AUDIO_FORMAT_S16; +- case SPA_AUDIO_FORMAT_S16_LE: +- *sample_size = 2; +- *endianness = 0; +- return AUDIO_FORMAT_S16; +- case SPA_AUDIO_FORMAT_U16_BE: +- *sample_size = 2; +- *endianness = 1; +- return AUDIO_FORMAT_U16; +- case SPA_AUDIO_FORMAT_U16_LE: +- *sample_size = 2; +- *endianness = 0; +- return AUDIO_FORMAT_U16; +- case SPA_AUDIO_FORMAT_S32_BE: +- *sample_size = 4; +- *endianness = 1; +- return AUDIO_FORMAT_S32; +- case SPA_AUDIO_FORMAT_S32_LE: +- *sample_size = 4; +- *endianness = 0; +- return AUDIO_FORMAT_S32; +- case SPA_AUDIO_FORMAT_U32_BE: +- *sample_size = 4; +- *endianness = 1; +- return AUDIO_FORMAT_U32; +- case SPA_AUDIO_FORMAT_U32_LE: +- *sample_size = 4; +- *endianness = 0; +- return AUDIO_FORMAT_U32; +- case SPA_AUDIO_FORMAT_F32_BE: +- *sample_size = 4; +- *endianness = 1; +- return AUDIO_FORMAT_F32; +- case SPA_AUDIO_FORMAT_F32_LE: +- *sample_size = 4; +- *endianness = 0; +- return AUDIO_FORMAT_F32; +- default: +- *sample_size = 1; +- dolog("Internal logic error: Bad spa_audio_format %d\n", fmt); +- return AUDIO_FORMAT_U8; +- } +-} +- +-static int +-qpw_stream_new(pwaudio *c, PWVoice *v, const char *stream_name, +- const char *name, enum spa_direction dir) +-{ +- int res; +- uint32_t n_params; +- const struct spa_pod *params[2]; +- uint8_t buffer[1024]; +- struct spa_pod_builder b; +- uint64_t buf_samples; +- struct pw_properties *props; +- +- props = pw_properties_new(NULL, NULL); +- if (!props) { +- error_report("Failed to create PW properties: %s", g_strerror(errno)); +- return -1; +- } +- +- /* 75% of the timer period for faster updates */ +- buf_samples = (uint64_t)v->g->dev->timer_period * v->info.rate +- * 3 / 4 / 1000000; +- pw_properties_setf(props, PW_KEY_NODE_LATENCY, "%" PRIu64 "/%u", +- buf_samples, v->info.rate); +- +- trace_pw_period(buf_samples, v->info.rate); +- if (name) { +- pw_properties_set(props, PW_KEY_TARGET_OBJECT, name); +- } +- v->stream = pw_stream_new(c->core, stream_name, props); +- if (v->stream == NULL) { +- error_report("Failed to create PW stream: %s", g_strerror(errno)); +- return -1; +- } +- +- if (dir == SPA_DIRECTION_INPUT) { +- pw_stream_add_listener(v->stream, +- &v->stream_listener, &capture_stream_events, v); +- } else { +- pw_stream_add_listener(v->stream, +- &v->stream_listener, &playback_stream_events, v); +- } +- +- n_params = 0; +- spa_pod_builder_init(&b, buffer, sizeof(buffer)); +- params[n_params++] = spa_format_audio_raw_build(&b, +- SPA_PARAM_EnumFormat, +- &v->info); +- +- /* connect the stream to a sink or source */ +- res = pw_stream_connect(v->stream, +- dir == +- SPA_DIRECTION_INPUT ? PW_DIRECTION_INPUT : +- PW_DIRECTION_OUTPUT, PW_ID_ANY, +- PW_STREAM_FLAG_AUTOCONNECT | +- PW_STREAM_FLAG_INACTIVE | +- PW_STREAM_FLAG_MAP_BUFFERS | +- PW_STREAM_FLAG_RT_PROCESS, params, n_params); +- if (res < 0) { +- error_report("Failed to connect PW stream: %s", g_strerror(errno)); +- pw_stream_destroy(v->stream); +- return -1; +- } +- +- return 0; +-} +- +-static void +-qpw_set_position(uint32_t channels, uint32_t position[SPA_AUDIO_MAX_CHANNELS]) +-{ +- memcpy(position, (uint32_t[SPA_AUDIO_MAX_CHANNELS]) { SPA_AUDIO_CHANNEL_UNKNOWN, }, +- sizeof(uint32_t) * SPA_AUDIO_MAX_CHANNELS); +- /* +- * TODO: This currently expects the only frontend supporting more than 2 +- * channels is the usb-audio. We will need some means to set channel +- * order when a new frontend gains multi-channel support. +- */ +- switch (channels) { +- case 8: +- position[6] = SPA_AUDIO_CHANNEL_SL; +- position[7] = SPA_AUDIO_CHANNEL_SR; +- /* fallthrough */ +- case 6: +- position[2] = SPA_AUDIO_CHANNEL_FC; +- position[3] = SPA_AUDIO_CHANNEL_LFE; +- position[4] = SPA_AUDIO_CHANNEL_RL; +- position[5] = SPA_AUDIO_CHANNEL_RR; +- /* fallthrough */ +- case 2: +- position[0] = SPA_AUDIO_CHANNEL_FL; +- position[1] = SPA_AUDIO_CHANNEL_FR; +- break; +- case 1: +- position[0] = SPA_AUDIO_CHANNEL_MONO; +- break; +- default: +- dolog("Internal error: unsupported channel count %d\n", channels); +- } +-} +- +-static int +-qpw_init_out(HWVoiceOut *hw, struct audsettings *as, void *drv_opaque) +-{ +- PWVoiceOut *pw = (PWVoiceOut *) hw; +- PWVoice *v = &pw->v; +- struct audsettings obt_as = *as; +- pwaudio *c = v->g = drv_opaque; +- AudiodevPipewireOptions *popts = &c->dev->u.pipewire; +- AudiodevPipewirePerDirectionOptions *ppdo = popts->out; +- int r; +- +- pw_thread_loop_lock(c->thread_loop); +- +- v->info.format = audfmt_to_pw(as->fmt, as->endianness); +- v->info.channels = as->nchannels; +- qpw_set_position(as->nchannels, v->info.position); +- v->info.rate = as->freq; +- +- obt_as.fmt = +- pw_to_audfmt(v->info.format, &obt_as.endianness, &v->frame_size); +- v->frame_size *= as->nchannels; +- +- v->req = (uint64_t)c->dev->timer_period * v->info.rate +- * 1 / 2 / 1000000 * v->frame_size; +- +- /* call the function that creates a new stream for playback */ +- r = qpw_stream_new(c, v, ppdo->stream_name ? : c->dev->id, +- ppdo->name, SPA_DIRECTION_OUTPUT); +- if (r < 0) { +- pw_thread_loop_unlock(c->thread_loop); +- return -1; +- } +- +- /* report the audio format we support */ +- audio_pcm_init_info(&hw->info, &obt_as); +- +- /* report the buffer size to qemu */ +- hw->samples = audio_buffer_frames( +- qapi_AudiodevPipewirePerDirectionOptions_base(ppdo), &obt_as, 46440); +- v->highwater_mark = MIN(RINGBUFFER_SIZE, +- (ppdo->has_latency ? ppdo->latency : 46440) +- * (uint64_t)v->info.rate / 1000000 * v->frame_size); +- +- pw_thread_loop_unlock(c->thread_loop); +- return 0; +-} +- +-static int +-qpw_init_in(HWVoiceIn *hw, struct audsettings *as, void *drv_opaque) +-{ +- PWVoiceIn *pw = (PWVoiceIn *) hw; +- PWVoice *v = &pw->v; +- struct audsettings obt_as = *as; +- pwaudio *c = v->g = drv_opaque; +- AudiodevPipewireOptions *popts = &c->dev->u.pipewire; +- AudiodevPipewirePerDirectionOptions *ppdo = popts->in; +- int r; +- +- pw_thread_loop_lock(c->thread_loop); +- +- v->info.format = audfmt_to_pw(as->fmt, as->endianness); +- v->info.channels = as->nchannels; +- qpw_set_position(as->nchannels, v->info.position); +- v->info.rate = as->freq; +- +- obt_as.fmt = +- pw_to_audfmt(v->info.format, &obt_as.endianness, &v->frame_size); +- v->frame_size *= as->nchannels; +- +- /* call the function that creates a new stream for recording */ +- r = qpw_stream_new(c, v, ppdo->stream_name ? : c->dev->id, +- ppdo->name, SPA_DIRECTION_INPUT); +- if (r < 0) { +- pw_thread_loop_unlock(c->thread_loop); +- return -1; +- } +- +- /* report the audio format we support */ +- audio_pcm_init_info(&hw->info, &obt_as); +- +- /* report the buffer size to qemu */ +- hw->samples = audio_buffer_frames( +- qapi_AudiodevPipewirePerDirectionOptions_base(ppdo), &obt_as, 46440); +- +- pw_thread_loop_unlock(c->thread_loop); +- return 0; +-} +- +-static void +-qpw_voice_fini(PWVoice *v) +-{ +- pwaudio *c = v->g; +- +- if (!v->stream) { +- return; +- } +- pw_thread_loop_lock(c->thread_loop); +- pw_stream_destroy(v->stream); +- v->stream = NULL; +- pw_thread_loop_unlock(c->thread_loop); +-} +- +-static void +-qpw_fini_out(HWVoiceOut *hw) +-{ +- qpw_voice_fini(&PW_VOICE_OUT(hw)->v); +-} +- +-static void +-qpw_fini_in(HWVoiceIn *hw) +-{ +- qpw_voice_fini(&PW_VOICE_IN(hw)->v); +-} +- +-static void +-qpw_voice_set_enabled(PWVoice *v, bool enable) +-{ +- pwaudio *c = v->g; +- pw_thread_loop_lock(c->thread_loop); +- pw_stream_set_active(v->stream, enable); +- pw_thread_loop_unlock(c->thread_loop); +-} +- +-static void +-qpw_enable_out(HWVoiceOut *hw, bool enable) +-{ +- qpw_voice_set_enabled(&PW_VOICE_OUT(hw)->v, enable); +-} +- +-static void +-qpw_enable_in(HWVoiceIn *hw, bool enable) +-{ +- qpw_voice_set_enabled(&PW_VOICE_IN(hw)->v, enable); +-} +- +-static void +-qpw_voice_set_volume(PWVoice *v, Volume *vol) +-{ +- pwaudio *c = v->g; +- int i, ret; +- +- pw_thread_loop_lock(c->thread_loop); +- v->volume.channels = vol->channels; +- +- for (i = 0; i < vol->channels; ++i) { +- v->volume.values[i] = (float)vol->vol[i] / 255; +- } +- +- ret = pw_stream_set_control(v->stream, +- SPA_PROP_channelVolumes, v->volume.channels, v->volume.values, 0); +- trace_pw_vol(ret == 0 ? "success" : "failed"); +- +- v->muted = vol->mute; +- float val = v->muted ? 1.f : 0.f; +- ret = pw_stream_set_control(v->stream, SPA_PROP_mute, 1, &val, 0); +- pw_thread_loop_unlock(c->thread_loop); +-} +- +-static void +-qpw_volume_out(HWVoiceOut *hw, Volume *vol) +-{ +- qpw_voice_set_volume(&PW_VOICE_OUT(hw)->v, vol); +-} +- +-static void +-qpw_volume_in(HWVoiceIn *hw, Volume *vol) +-{ +- qpw_voice_set_volume(&PW_VOICE_IN(hw)->v, vol); +-} +- +-static int wait_resync(pwaudio *pw) +-{ +- int res; +- pw->pending_seq = pw_core_sync(pw->core, PW_ID_CORE, pw->pending_seq); +- +- while (true) { +- pw_thread_loop_wait(pw->thread_loop); +- +- res = pw->error; +- if (res < 0) { +- pw->error = 0; +- return res; +- } +- if (pw->pending_seq == pw->last_seq) { +- break; +- } +- } +- return 0; +-} +- +-static void +-on_core_error(void *data, uint32_t id, int seq, int res, const char *message) +-{ +- pwaudio *pw = data; +- +- error_report("error id:%u seq:%d res:%d (%s): %s", +- id, seq, res, spa_strerror(res), message); +- +- /* stop and exit the thread loop */ +- pw_thread_loop_signal(pw->thread_loop, FALSE); +-} +- +-static void +-on_core_done(void *data, uint32_t id, int seq) +-{ +- pwaudio *pw = data; +- assert(id == PW_ID_CORE); +- pw->last_seq = seq; +- if (pw->pending_seq == seq) { +- /* stop and exit the thread loop */ +- pw_thread_loop_signal(pw->thread_loop, FALSE); +- } +-} +- +-static const struct pw_core_events core_events = { +- PW_VERSION_CORE_EVENTS, +- .done = on_core_done, +- .error = on_core_error, +-}; +- +-static void * +-qpw_audio_init(Audiodev *dev, Error **errp) +-{ +- g_autofree pwaudio *pw = g_new0(pwaudio, 1); +- +- assert(dev->driver == AUDIODEV_DRIVER_PIPEWIRE); +- trace_pw_audio_init(); +- +- pw_init(NULL, NULL); +- +- pw->dev = dev; +- pw->thread_loop = pw_thread_loop_new("PipeWire thread loop", NULL); +- if (pw->thread_loop == NULL) { +- error_setg_errno(errp, errno, "Could not create PipeWire loop"); +- goto fail; +- } +- +- pw->context = +- pw_context_new(pw_thread_loop_get_loop(pw->thread_loop), NULL, 0); +- if (pw->context == NULL) { +- error_setg_errno(errp, errno, "Could not create PipeWire context"); +- goto fail; +- } +- +- if (pw_thread_loop_start(pw->thread_loop) < 0) { +- error_setg_errno(errp, errno, "Could not start PipeWire loop"); +- goto fail; +- } +- +- pw_thread_loop_lock(pw->thread_loop); +- +- pw->core = pw_context_connect(pw->context, NULL, 0); +- if (pw->core == NULL) { +- pw_thread_loop_unlock(pw->thread_loop); +- goto fail_error; +- } +- +- if (pw_core_add_listener(pw->core, &pw->core_listener, +- &core_events, pw) < 0) { +- pw_thread_loop_unlock(pw->thread_loop); +- goto fail_error; +- } +- if (wait_resync(pw) < 0) { +- pw_thread_loop_unlock(pw->thread_loop); +- } +- +- pw_thread_loop_unlock(pw->thread_loop); +- +- return g_steal_pointer(&pw); +- +-fail_error: +- error_setg(errp, "Failed to initialize PW context"); +-fail: +- if (pw->thread_loop) { +- pw_thread_loop_stop(pw->thread_loop); +- } +- g_clear_pointer(&pw->context, pw_context_destroy); +- g_clear_pointer(&pw->thread_loop, pw_thread_loop_destroy); +- return NULL; +-} +- +-static void +-qpw_audio_fini(void *opaque) +-{ +- pwaudio *pw = opaque; +- +- if (pw->thread_loop) { +- pw_thread_loop_stop(pw->thread_loop); +- } +- +- if (pw->core) { +- spa_hook_remove(&pw->core_listener); +- spa_zero(pw->core_listener); +- pw_core_disconnect(pw->core); +- } +- +- if (pw->context) { +- pw_context_destroy(pw->context); +- } +- pw_thread_loop_destroy(pw->thread_loop); +- +- g_free(pw); +-} +- +-static struct audio_pcm_ops qpw_pcm_ops = { +- .init_out = qpw_init_out, +- .fini_out = qpw_fini_out, +- .write = qpw_write, +- .buffer_get_free = qpw_buffer_get_free, +- .run_buffer_out = audio_generic_run_buffer_out, +- .enable_out = qpw_enable_out, +- .volume_out = qpw_volume_out, +- .volume_in = qpw_volume_in, +- +- .init_in = qpw_init_in, +- .fini_in = qpw_fini_in, +- .read = qpw_read, +- .run_buffer_in = audio_generic_run_buffer_in, +- .enable_in = qpw_enable_in +-}; +- +-static struct audio_driver pw_audio_driver = { +- .name = "pipewire", +- .descr = "http://www.pipewire.org/", +- .init = qpw_audio_init, +- .fini = qpw_audio_fini, +- .pcm_ops = &qpw_pcm_ops, +- .max_voices_out = INT_MAX, +- .max_voices_in = INT_MAX, +- .voice_size_out = sizeof(PWVoiceOut), +- .voice_size_in = sizeof(PWVoiceIn), +-}; +- +-static void +-register_audio_pw(void) +-{ +- audio_driver_register(&pw_audio_driver); +-} +- +-type_init(register_audio_pw); +-- +2.41.0.windows.1 + diff --git a/audio-pw-Report-more-accurate-error-when-connecting-.patch b/audio-pw-Report-more-accurate-error-when-connecting-.patch new file mode 100644 index 00000000..20de4547 --- /dev/null +++ b/audio-pw-Report-more-accurate-error-when-connecting-.patch @@ -0,0 +1,931 @@ +From fab03a72da74e938a2a476f1824ac0acd4a1fee2 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?=E5=BC=A0=E6=A5=9A=E5=90=9B?= + +Date: Fri, 18 Oct 2024 10:17:10 +0800 +Subject: [PATCH] audio/pw: Report more accurate error when connecting to + PipeWire fails +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +According to its man page [1], pw_context_connect() sets errno on +failure: + + Returns a Core on success or NULL with errno set on error. + +It may be handy to see errno when figuring out why PipeWire +failed to connect. That leaves us with just one possible path to +reach 'fail_error' label which is then moved to that path and +also its error message is adjusted slightly. + +1: https://docs.pipewire.org/group__pw__core.html#ga5994e3a54e4ec718094ca02a1234815b + +Signed-off-by: Michal Privoznik +Reviewed-by: Manos Pitsidianakis +Reviewed-by: Marc-André Lureau +Message-ID: <3a78811ad5b0e87816b7616ab21d2eeef00b9c52.1726647033.git.mprivozn@redhat.com> +Signed-off-by: Zhang Chujun +--- + audio/pwaudio.c | 8 +- + audio/pwaudio.c.orig | 858 +++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 862 insertions(+), 4 deletions(-) + create mode 100644 audio/pwaudio.c.orig + +diff --git a/audio/pwaudio.c b/audio/pwaudio.c +index 3ce5f6507b..5d1c7126d3 100644 +--- a/audio/pwaudio.c ++++ b/audio/pwaudio.c +@@ -770,13 +770,15 @@ qpw_audio_init(Audiodev *dev, Error **errp) + pw->core = pw_context_connect(pw->context, NULL, 0); + if (pw->core == NULL) { + pw_thread_loop_unlock(pw->thread_loop); +- goto fail_error; ++ error_setg_errno(errp, errno, "Failed to connect to PipeWire instance"); ++ goto fail; + } + + if (pw_core_add_listener(pw->core, &pw->core_listener, + &core_events, pw) < 0) { + pw_thread_loop_unlock(pw->thread_loop); +- goto fail_error; ++ error_setg(errp, "Failed to add PipeWire listener"); ++ goto fail; + } + if (wait_resync(pw) < 0) { + pw_thread_loop_unlock(pw->thread_loop); +@@ -786,8 +788,6 @@ qpw_audio_init(Audiodev *dev, Error **errp) + + return g_steal_pointer(&pw); + +-fail_error: +- error_setg(errp, "Failed to initialize PW context"); + fail: + if (pw->thread_loop) { + pw_thread_loop_stop(pw->thread_loop); +diff --git a/audio/pwaudio.c.orig b/audio/pwaudio.c.orig +new file mode 100644 +index 0000000000..3ce5f6507b +--- /dev/null ++++ b/audio/pwaudio.c.orig +@@ -0,0 +1,858 @@ ++/* ++ * QEMU PipeWire audio driver ++ * ++ * Copyright (c) 2023 Red Hat Inc. ++ * ++ * Author: Dorinda Bassey ++ * ++ * SPDX-License-Identifier: GPL-2.0-or-later ++ */ ++ ++#include "qemu/osdep.h" ++#include "qemu/module.h" ++#include "audio.h" ++#include ++#include "qemu/error-report.h" ++#include "qapi/error.h" ++#include ++#include ++#include ++#include ++ ++#include ++#include "trace.h" ++ ++#define AUDIO_CAP "pipewire" ++#define RINGBUFFER_SIZE (1u << 22) ++#define RINGBUFFER_MASK (RINGBUFFER_SIZE - 1) ++ ++#include "audio_int.h" ++ ++typedef struct pwvolume { ++ uint32_t channels; ++ float values[SPA_AUDIO_MAX_CHANNELS]; ++} pwvolume; ++ ++typedef struct pwaudio { ++ Audiodev *dev; ++ struct pw_thread_loop *thread_loop; ++ struct pw_context *context; ++ ++ struct pw_core *core; ++ struct spa_hook core_listener; ++ int last_seq, pending_seq, error; ++} pwaudio; ++ ++typedef struct PWVoice { ++ pwaudio *g; ++ struct pw_stream *stream; ++ struct spa_hook stream_listener; ++ struct spa_audio_info_raw info; ++ uint32_t highwater_mark; ++ uint32_t frame_size, req; ++ struct spa_ringbuffer ring; ++ uint8_t buffer[RINGBUFFER_SIZE]; ++ ++ pwvolume volume; ++ bool muted; ++} PWVoice; ++ ++typedef struct PWVoiceOut { ++ HWVoiceOut hw; ++ PWVoice v; ++} PWVoiceOut; ++ ++typedef struct PWVoiceIn { ++ HWVoiceIn hw; ++ PWVoice v; ++} PWVoiceIn; ++ ++#define PW_VOICE_IN(v) ((PWVoiceIn *)v) ++#define PW_VOICE_OUT(v) ((PWVoiceOut *)v) ++ ++static void ++stream_destroy(void *data) ++{ ++ PWVoice *v = (PWVoice *) data; ++ spa_hook_remove(&v->stream_listener); ++ v->stream = NULL; ++} ++ ++/* output data processing function to read stuffs from the buffer */ ++static void ++playback_on_process(void *data) ++{ ++ PWVoice *v = data; ++ void *p; ++ struct pw_buffer *b; ++ struct spa_buffer *buf; ++ uint32_t req, index, n_bytes; ++ int32_t avail; ++ ++ assert(v->stream); ++ ++ /* obtain a buffer to read from */ ++ b = pw_stream_dequeue_buffer(v->stream); ++ if (b == NULL) { ++ error_report("out of buffers: %s", strerror(errno)); ++ return; ++ } ++ ++ buf = b->buffer; ++ p = buf->datas[0].data; ++ if (p == NULL) { ++ return; ++ } ++ /* calculate the total no of bytes to read data from buffer */ ++ req = b->requested * v->frame_size; ++ if (req == 0) { ++ req = v->req; ++ } ++ n_bytes = SPA_MIN(req, buf->datas[0].maxsize); ++ ++ /* get no of available bytes to read data from buffer */ ++ avail = spa_ringbuffer_get_read_index(&v->ring, &index); ++ ++ if (avail <= 0) { ++ PWVoiceOut *vo = container_of(data, PWVoiceOut, v); ++ audio_pcm_info_clear_buf(&vo->hw.info, p, n_bytes / v->frame_size); ++ } else { ++ if ((uint32_t) avail < n_bytes) { ++ /* ++ * PipeWire immediately calls this callback again if we provide ++ * less than n_bytes. Then audio_pcm_info_clear_buf() fills the ++ * rest of the buffer with silence. ++ */ ++ n_bytes = avail; ++ } ++ ++ spa_ringbuffer_read_data(&v->ring, ++ v->buffer, RINGBUFFER_SIZE, ++ index & RINGBUFFER_MASK, p, n_bytes); ++ ++ index += n_bytes; ++ spa_ringbuffer_read_update(&v->ring, index); ++ ++ } ++ buf->datas[0].chunk->offset = 0; ++ buf->datas[0].chunk->stride = v->frame_size; ++ buf->datas[0].chunk->size = n_bytes; ++ ++ /* queue the buffer for playback */ ++ pw_stream_queue_buffer(v->stream, b); ++} ++ ++/* output data processing function to generate stuffs in the buffer */ ++static void ++capture_on_process(void *data) ++{ ++ PWVoice *v = (PWVoice *) data; ++ void *p; ++ struct pw_buffer *b; ++ struct spa_buffer *buf; ++ int32_t filled; ++ uint32_t index, offs, n_bytes; ++ ++ assert(v->stream); ++ ++ /* obtain a buffer */ ++ b = pw_stream_dequeue_buffer(v->stream); ++ if (b == NULL) { ++ error_report("out of buffers: %s", strerror(errno)); ++ return; ++ } ++ ++ /* Write data into buffer */ ++ buf = b->buffer; ++ p = buf->datas[0].data; ++ if (p == NULL) { ++ return; ++ } ++ offs = SPA_MIN(buf->datas[0].chunk->offset, buf->datas[0].maxsize); ++ n_bytes = SPA_MIN(buf->datas[0].chunk->size, buf->datas[0].maxsize - offs); ++ ++ filled = spa_ringbuffer_get_write_index(&v->ring, &index); ++ ++ ++ if (filled < 0) { ++ error_report("%p: underrun write:%u filled:%d", p, index, filled); ++ } else { ++ if ((uint32_t) filled + n_bytes > RINGBUFFER_SIZE) { ++ error_report("%p: overrun write:%u filled:%d + size:%u > max:%u", ++ p, index, filled, n_bytes, RINGBUFFER_SIZE); ++ } ++ } ++ spa_ringbuffer_write_data(&v->ring, ++ v->buffer, RINGBUFFER_SIZE, ++ index & RINGBUFFER_MASK, ++ SPA_PTROFF(p, offs, void), n_bytes); ++ index += n_bytes; ++ spa_ringbuffer_write_update(&v->ring, index); ++ ++ /* queue the buffer for playback */ ++ pw_stream_queue_buffer(v->stream, b); ++} ++ ++static void ++on_stream_state_changed(void *data, enum pw_stream_state old, ++ enum pw_stream_state state, const char *error) ++{ ++ PWVoice *v = (PWVoice *) data; ++ ++ trace_pw_state_changed(pw_stream_get_node_id(v->stream), ++ pw_stream_state_as_string(state)); ++} ++ ++static const struct pw_stream_events capture_stream_events = { ++ PW_VERSION_STREAM_EVENTS, ++ .destroy = stream_destroy, ++ .state_changed = on_stream_state_changed, ++ .process = capture_on_process ++}; ++ ++static const struct pw_stream_events playback_stream_events = { ++ PW_VERSION_STREAM_EVENTS, ++ .destroy = stream_destroy, ++ .state_changed = on_stream_state_changed, ++ .process = playback_on_process ++}; ++ ++static size_t ++qpw_read(HWVoiceIn *hw, void *data, size_t len) ++{ ++ PWVoiceIn *pw = (PWVoiceIn *) hw; ++ PWVoice *v = &pw->v; ++ pwaudio *c = v->g; ++ const char *error = NULL; ++ size_t l; ++ int32_t avail; ++ uint32_t index; ++ ++ pw_thread_loop_lock(c->thread_loop); ++ if (pw_stream_get_state(v->stream, &error) != PW_STREAM_STATE_STREAMING) { ++ /* wait for stream to become ready */ ++ l = 0; ++ goto done_unlock; ++ } ++ /* get no of available bytes to read data from buffer */ ++ avail = spa_ringbuffer_get_read_index(&v->ring, &index); ++ ++ trace_pw_read(avail, index, len); ++ ++ if (avail < (int32_t) len) { ++ len = avail; ++ } ++ ++ spa_ringbuffer_read_data(&v->ring, ++ v->buffer, RINGBUFFER_SIZE, ++ index & RINGBUFFER_MASK, data, len); ++ index += len; ++ spa_ringbuffer_read_update(&v->ring, index); ++ l = len; ++ ++done_unlock: ++ pw_thread_loop_unlock(c->thread_loop); ++ return l; ++} ++ ++static size_t qpw_buffer_get_free(HWVoiceOut *hw) ++{ ++ PWVoiceOut *pw = (PWVoiceOut *)hw; ++ PWVoice *v = &pw->v; ++ pwaudio *c = v->g; ++ const char *error = NULL; ++ int32_t filled, avail; ++ uint32_t index; ++ ++ pw_thread_loop_lock(c->thread_loop); ++ if (pw_stream_get_state(v->stream, &error) != PW_STREAM_STATE_STREAMING) { ++ /* wait for stream to become ready */ ++ avail = 0; ++ goto done_unlock; ++ } ++ ++ filled = spa_ringbuffer_get_write_index(&v->ring, &index); ++ avail = v->highwater_mark - filled; ++ ++done_unlock: ++ pw_thread_loop_unlock(c->thread_loop); ++ return avail; ++} ++ ++static size_t ++qpw_write(HWVoiceOut *hw, void *data, size_t len) ++{ ++ PWVoiceOut *pw = (PWVoiceOut *) hw; ++ PWVoice *v = &pw->v; ++ pwaudio *c = v->g; ++ const char *error = NULL; ++ int32_t filled, avail; ++ uint32_t index; ++ ++ pw_thread_loop_lock(c->thread_loop); ++ if (pw_stream_get_state(v->stream, &error) != PW_STREAM_STATE_STREAMING) { ++ /* wait for stream to become ready */ ++ len = 0; ++ goto done_unlock; ++ } ++ filled = spa_ringbuffer_get_write_index(&v->ring, &index); ++ avail = v->highwater_mark - filled; ++ ++ trace_pw_write(filled, avail, index, len); ++ ++ if (len > avail) { ++ len = avail; ++ } ++ ++ if (filled < 0) { ++ error_report("%p: underrun write:%u filled:%d", pw, index, filled); ++ } else { ++ if ((uint32_t) filled + len > RINGBUFFER_SIZE) { ++ error_report("%p: overrun write:%u filled:%d + size:%zu > max:%u", ++ pw, index, filled, len, RINGBUFFER_SIZE); ++ } ++ } ++ ++ spa_ringbuffer_write_data(&v->ring, ++ v->buffer, RINGBUFFER_SIZE, ++ index & RINGBUFFER_MASK, data, len); ++ index += len; ++ spa_ringbuffer_write_update(&v->ring, index); ++ ++done_unlock: ++ pw_thread_loop_unlock(c->thread_loop); ++ return len; ++} ++ ++static int ++audfmt_to_pw(AudioFormat fmt, int endianness) ++{ ++ int format; ++ ++ switch (fmt) { ++ case AUDIO_FORMAT_S8: ++ format = SPA_AUDIO_FORMAT_S8; ++ break; ++ case AUDIO_FORMAT_U8: ++ format = SPA_AUDIO_FORMAT_U8; ++ break; ++ case AUDIO_FORMAT_S16: ++ format = endianness ? SPA_AUDIO_FORMAT_S16_BE : SPA_AUDIO_FORMAT_S16_LE; ++ break; ++ case AUDIO_FORMAT_U16: ++ format = endianness ? SPA_AUDIO_FORMAT_U16_BE : SPA_AUDIO_FORMAT_U16_LE; ++ break; ++ case AUDIO_FORMAT_S32: ++ format = endianness ? SPA_AUDIO_FORMAT_S32_BE : SPA_AUDIO_FORMAT_S32_LE; ++ break; ++ case AUDIO_FORMAT_U32: ++ format = endianness ? SPA_AUDIO_FORMAT_U32_BE : SPA_AUDIO_FORMAT_U32_LE; ++ break; ++ case AUDIO_FORMAT_F32: ++ format = endianness ? SPA_AUDIO_FORMAT_F32_BE : SPA_AUDIO_FORMAT_F32_LE; ++ break; ++ default: ++ dolog("Internal logic error: Bad audio format %d\n", fmt); ++ format = SPA_AUDIO_FORMAT_U8; ++ break; ++ } ++ return format; ++} ++ ++static AudioFormat ++pw_to_audfmt(enum spa_audio_format fmt, int *endianness, ++ uint32_t *sample_size) ++{ ++ switch (fmt) { ++ case SPA_AUDIO_FORMAT_S8: ++ *sample_size = 1; ++ return AUDIO_FORMAT_S8; ++ case SPA_AUDIO_FORMAT_U8: ++ *sample_size = 1; ++ return AUDIO_FORMAT_U8; ++ case SPA_AUDIO_FORMAT_S16_BE: ++ *sample_size = 2; ++ *endianness = 1; ++ return AUDIO_FORMAT_S16; ++ case SPA_AUDIO_FORMAT_S16_LE: ++ *sample_size = 2; ++ *endianness = 0; ++ return AUDIO_FORMAT_S16; ++ case SPA_AUDIO_FORMAT_U16_BE: ++ *sample_size = 2; ++ *endianness = 1; ++ return AUDIO_FORMAT_U16; ++ case SPA_AUDIO_FORMAT_U16_LE: ++ *sample_size = 2; ++ *endianness = 0; ++ return AUDIO_FORMAT_U16; ++ case SPA_AUDIO_FORMAT_S32_BE: ++ *sample_size = 4; ++ *endianness = 1; ++ return AUDIO_FORMAT_S32; ++ case SPA_AUDIO_FORMAT_S32_LE: ++ *sample_size = 4; ++ *endianness = 0; ++ return AUDIO_FORMAT_S32; ++ case SPA_AUDIO_FORMAT_U32_BE: ++ *sample_size = 4; ++ *endianness = 1; ++ return AUDIO_FORMAT_U32; ++ case SPA_AUDIO_FORMAT_U32_LE: ++ *sample_size = 4; ++ *endianness = 0; ++ return AUDIO_FORMAT_U32; ++ case SPA_AUDIO_FORMAT_F32_BE: ++ *sample_size = 4; ++ *endianness = 1; ++ return AUDIO_FORMAT_F32; ++ case SPA_AUDIO_FORMAT_F32_LE: ++ *sample_size = 4; ++ *endianness = 0; ++ return AUDIO_FORMAT_F32; ++ default: ++ *sample_size = 1; ++ dolog("Internal logic error: Bad spa_audio_format %d\n", fmt); ++ return AUDIO_FORMAT_U8; ++ } ++} ++ ++static int ++qpw_stream_new(pwaudio *c, PWVoice *v, const char *stream_name, ++ const char *name, enum spa_direction dir) ++{ ++ int res; ++ uint32_t n_params; ++ const struct spa_pod *params[2]; ++ uint8_t buffer[1024]; ++ struct spa_pod_builder b; ++ uint64_t buf_samples; ++ struct pw_properties *props; ++ ++ props = pw_properties_new(NULL, NULL); ++ if (!props) { ++ error_report("Failed to create PW properties: %s", g_strerror(errno)); ++ return -1; ++ } ++ ++ /* 75% of the timer period for faster updates */ ++ buf_samples = (uint64_t)v->g->dev->timer_period * v->info.rate ++ * 3 / 4 / 1000000; ++ pw_properties_setf(props, PW_KEY_NODE_LATENCY, "%" PRIu64 "/%u", ++ buf_samples, v->info.rate); ++ ++ trace_pw_period(buf_samples, v->info.rate); ++ if (name) { ++ pw_properties_set(props, PW_KEY_TARGET_OBJECT, name); ++ } ++ v->stream = pw_stream_new(c->core, stream_name, props); ++ if (v->stream == NULL) { ++ error_report("Failed to create PW stream: %s", g_strerror(errno)); ++ return -1; ++ } ++ ++ if (dir == SPA_DIRECTION_INPUT) { ++ pw_stream_add_listener(v->stream, ++ &v->stream_listener, &capture_stream_events, v); ++ } else { ++ pw_stream_add_listener(v->stream, ++ &v->stream_listener, &playback_stream_events, v); ++ } ++ ++ n_params = 0; ++ spa_pod_builder_init(&b, buffer, sizeof(buffer)); ++ params[n_params++] = spa_format_audio_raw_build(&b, ++ SPA_PARAM_EnumFormat, ++ &v->info); ++ ++ /* connect the stream to a sink or source */ ++ res = pw_stream_connect(v->stream, ++ dir == ++ SPA_DIRECTION_INPUT ? PW_DIRECTION_INPUT : ++ PW_DIRECTION_OUTPUT, PW_ID_ANY, ++ PW_STREAM_FLAG_AUTOCONNECT | ++ PW_STREAM_FLAG_INACTIVE | ++ PW_STREAM_FLAG_MAP_BUFFERS | ++ PW_STREAM_FLAG_RT_PROCESS, params, n_params); ++ if (res < 0) { ++ error_report("Failed to connect PW stream: %s", g_strerror(errno)); ++ pw_stream_destroy(v->stream); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++static void ++qpw_set_position(uint32_t channels, uint32_t position[SPA_AUDIO_MAX_CHANNELS]) ++{ ++ memcpy(position, (uint32_t[SPA_AUDIO_MAX_CHANNELS]) { SPA_AUDIO_CHANNEL_UNKNOWN, }, ++ sizeof(uint32_t) * SPA_AUDIO_MAX_CHANNELS); ++ /* ++ * TODO: This currently expects the only frontend supporting more than 2 ++ * channels is the usb-audio. We will need some means to set channel ++ * order when a new frontend gains multi-channel support. ++ */ ++ switch (channels) { ++ case 8: ++ position[6] = SPA_AUDIO_CHANNEL_SL; ++ position[7] = SPA_AUDIO_CHANNEL_SR; ++ /* fallthrough */ ++ case 6: ++ position[2] = SPA_AUDIO_CHANNEL_FC; ++ position[3] = SPA_AUDIO_CHANNEL_LFE; ++ position[4] = SPA_AUDIO_CHANNEL_RL; ++ position[5] = SPA_AUDIO_CHANNEL_RR; ++ /* fallthrough */ ++ case 2: ++ position[0] = SPA_AUDIO_CHANNEL_FL; ++ position[1] = SPA_AUDIO_CHANNEL_FR; ++ break; ++ case 1: ++ position[0] = SPA_AUDIO_CHANNEL_MONO; ++ break; ++ default: ++ dolog("Internal error: unsupported channel count %d\n", channels); ++ } ++} ++ ++static int ++qpw_init_out(HWVoiceOut *hw, struct audsettings *as, void *drv_opaque) ++{ ++ PWVoiceOut *pw = (PWVoiceOut *) hw; ++ PWVoice *v = &pw->v; ++ struct audsettings obt_as = *as; ++ pwaudio *c = v->g = drv_opaque; ++ AudiodevPipewireOptions *popts = &c->dev->u.pipewire; ++ AudiodevPipewirePerDirectionOptions *ppdo = popts->out; ++ int r; ++ ++ pw_thread_loop_lock(c->thread_loop); ++ ++ v->info.format = audfmt_to_pw(as->fmt, as->endianness); ++ v->info.channels = as->nchannels; ++ qpw_set_position(as->nchannels, v->info.position); ++ v->info.rate = as->freq; ++ ++ obt_as.fmt = ++ pw_to_audfmt(v->info.format, &obt_as.endianness, &v->frame_size); ++ v->frame_size *= as->nchannels; ++ ++ v->req = (uint64_t)c->dev->timer_period * v->info.rate ++ * 1 / 2 / 1000000 * v->frame_size; ++ ++ /* call the function that creates a new stream for playback */ ++ r = qpw_stream_new(c, v, ppdo->stream_name ? : c->dev->id, ++ ppdo->name, SPA_DIRECTION_OUTPUT); ++ if (r < 0) { ++ pw_thread_loop_unlock(c->thread_loop); ++ return -1; ++ } ++ ++ /* report the audio format we support */ ++ audio_pcm_init_info(&hw->info, &obt_as); ++ ++ /* report the buffer size to qemu */ ++ hw->samples = audio_buffer_frames( ++ qapi_AudiodevPipewirePerDirectionOptions_base(ppdo), &obt_as, 46440); ++ v->highwater_mark = MIN(RINGBUFFER_SIZE, ++ (ppdo->has_latency ? ppdo->latency : 46440) ++ * (uint64_t)v->info.rate / 1000000 * v->frame_size); ++ ++ pw_thread_loop_unlock(c->thread_loop); ++ return 0; ++} ++ ++static int ++qpw_init_in(HWVoiceIn *hw, struct audsettings *as, void *drv_opaque) ++{ ++ PWVoiceIn *pw = (PWVoiceIn *) hw; ++ PWVoice *v = &pw->v; ++ struct audsettings obt_as = *as; ++ pwaudio *c = v->g = drv_opaque; ++ AudiodevPipewireOptions *popts = &c->dev->u.pipewire; ++ AudiodevPipewirePerDirectionOptions *ppdo = popts->in; ++ int r; ++ ++ pw_thread_loop_lock(c->thread_loop); ++ ++ v->info.format = audfmt_to_pw(as->fmt, as->endianness); ++ v->info.channels = as->nchannels; ++ qpw_set_position(as->nchannels, v->info.position); ++ v->info.rate = as->freq; ++ ++ obt_as.fmt = ++ pw_to_audfmt(v->info.format, &obt_as.endianness, &v->frame_size); ++ v->frame_size *= as->nchannels; ++ ++ /* call the function that creates a new stream for recording */ ++ r = qpw_stream_new(c, v, ppdo->stream_name ? : c->dev->id, ++ ppdo->name, SPA_DIRECTION_INPUT); ++ if (r < 0) { ++ pw_thread_loop_unlock(c->thread_loop); ++ return -1; ++ } ++ ++ /* report the audio format we support */ ++ audio_pcm_init_info(&hw->info, &obt_as); ++ ++ /* report the buffer size to qemu */ ++ hw->samples = audio_buffer_frames( ++ qapi_AudiodevPipewirePerDirectionOptions_base(ppdo), &obt_as, 46440); ++ ++ pw_thread_loop_unlock(c->thread_loop); ++ return 0; ++} ++ ++static void ++qpw_voice_fini(PWVoice *v) ++{ ++ pwaudio *c = v->g; ++ ++ if (!v->stream) { ++ return; ++ } ++ pw_thread_loop_lock(c->thread_loop); ++ pw_stream_destroy(v->stream); ++ v->stream = NULL; ++ pw_thread_loop_unlock(c->thread_loop); ++} ++ ++static void ++qpw_fini_out(HWVoiceOut *hw) ++{ ++ qpw_voice_fini(&PW_VOICE_OUT(hw)->v); ++} ++ ++static void ++qpw_fini_in(HWVoiceIn *hw) ++{ ++ qpw_voice_fini(&PW_VOICE_IN(hw)->v); ++} ++ ++static void ++qpw_voice_set_enabled(PWVoice *v, bool enable) ++{ ++ pwaudio *c = v->g; ++ pw_thread_loop_lock(c->thread_loop); ++ pw_stream_set_active(v->stream, enable); ++ pw_thread_loop_unlock(c->thread_loop); ++} ++ ++static void ++qpw_enable_out(HWVoiceOut *hw, bool enable) ++{ ++ qpw_voice_set_enabled(&PW_VOICE_OUT(hw)->v, enable); ++} ++ ++static void ++qpw_enable_in(HWVoiceIn *hw, bool enable) ++{ ++ qpw_voice_set_enabled(&PW_VOICE_IN(hw)->v, enable); ++} ++ ++static void ++qpw_voice_set_volume(PWVoice *v, Volume *vol) ++{ ++ pwaudio *c = v->g; ++ int i, ret; ++ ++ pw_thread_loop_lock(c->thread_loop); ++ v->volume.channels = vol->channels; ++ ++ for (i = 0; i < vol->channels; ++i) { ++ v->volume.values[i] = (float)vol->vol[i] / 255; ++ } ++ ++ ret = pw_stream_set_control(v->stream, ++ SPA_PROP_channelVolumes, v->volume.channels, v->volume.values, 0); ++ trace_pw_vol(ret == 0 ? "success" : "failed"); ++ ++ v->muted = vol->mute; ++ float val = v->muted ? 1.f : 0.f; ++ ret = pw_stream_set_control(v->stream, SPA_PROP_mute, 1, &val, 0); ++ pw_thread_loop_unlock(c->thread_loop); ++} ++ ++static void ++qpw_volume_out(HWVoiceOut *hw, Volume *vol) ++{ ++ qpw_voice_set_volume(&PW_VOICE_OUT(hw)->v, vol); ++} ++ ++static void ++qpw_volume_in(HWVoiceIn *hw, Volume *vol) ++{ ++ qpw_voice_set_volume(&PW_VOICE_IN(hw)->v, vol); ++} ++ ++static int wait_resync(pwaudio *pw) ++{ ++ int res; ++ pw->pending_seq = pw_core_sync(pw->core, PW_ID_CORE, pw->pending_seq); ++ ++ while (true) { ++ pw_thread_loop_wait(pw->thread_loop); ++ ++ res = pw->error; ++ if (res < 0) { ++ pw->error = 0; ++ return res; ++ } ++ if (pw->pending_seq == pw->last_seq) { ++ break; ++ } ++ } ++ return 0; ++} ++ ++static void ++on_core_error(void *data, uint32_t id, int seq, int res, const char *message) ++{ ++ pwaudio *pw = data; ++ ++ error_report("error id:%u seq:%d res:%d (%s): %s", ++ id, seq, res, spa_strerror(res), message); ++ ++ /* stop and exit the thread loop */ ++ pw_thread_loop_signal(pw->thread_loop, FALSE); ++} ++ ++static void ++on_core_done(void *data, uint32_t id, int seq) ++{ ++ pwaudio *pw = data; ++ assert(id == PW_ID_CORE); ++ pw->last_seq = seq; ++ if (pw->pending_seq == seq) { ++ /* stop and exit the thread loop */ ++ pw_thread_loop_signal(pw->thread_loop, FALSE); ++ } ++} ++ ++static const struct pw_core_events core_events = { ++ PW_VERSION_CORE_EVENTS, ++ .done = on_core_done, ++ .error = on_core_error, ++}; ++ ++static void * ++qpw_audio_init(Audiodev *dev, Error **errp) ++{ ++ g_autofree pwaudio *pw = g_new0(pwaudio, 1); ++ ++ assert(dev->driver == AUDIODEV_DRIVER_PIPEWIRE); ++ trace_pw_audio_init(); ++ ++ pw_init(NULL, NULL); ++ ++ pw->dev = dev; ++ pw->thread_loop = pw_thread_loop_new("PipeWire thread loop", NULL); ++ if (pw->thread_loop == NULL) { ++ error_setg_errno(errp, errno, "Could not create PipeWire loop"); ++ goto fail; ++ } ++ ++ pw->context = ++ pw_context_new(pw_thread_loop_get_loop(pw->thread_loop), NULL, 0); ++ if (pw->context == NULL) { ++ error_setg_errno(errp, errno, "Could not create PipeWire context"); ++ goto fail; ++ } ++ ++ if (pw_thread_loop_start(pw->thread_loop) < 0) { ++ error_setg_errno(errp, errno, "Could not start PipeWire loop"); ++ goto fail; ++ } ++ ++ pw_thread_loop_lock(pw->thread_loop); ++ ++ pw->core = pw_context_connect(pw->context, NULL, 0); ++ if (pw->core == NULL) { ++ pw_thread_loop_unlock(pw->thread_loop); ++ goto fail_error; ++ } ++ ++ if (pw_core_add_listener(pw->core, &pw->core_listener, ++ &core_events, pw) < 0) { ++ pw_thread_loop_unlock(pw->thread_loop); ++ goto fail_error; ++ } ++ if (wait_resync(pw) < 0) { ++ pw_thread_loop_unlock(pw->thread_loop); ++ } ++ ++ pw_thread_loop_unlock(pw->thread_loop); ++ ++ return g_steal_pointer(&pw); ++ ++fail_error: ++ error_setg(errp, "Failed to initialize PW context"); ++fail: ++ if (pw->thread_loop) { ++ pw_thread_loop_stop(pw->thread_loop); ++ } ++ g_clear_pointer(&pw->context, pw_context_destroy); ++ g_clear_pointer(&pw->thread_loop, pw_thread_loop_destroy); ++ return NULL; ++} ++ ++static void ++qpw_audio_fini(void *opaque) ++{ ++ pwaudio *pw = opaque; ++ ++ if (pw->thread_loop) { ++ pw_thread_loop_stop(pw->thread_loop); ++ } ++ ++ if (pw->core) { ++ spa_hook_remove(&pw->core_listener); ++ spa_zero(pw->core_listener); ++ pw_core_disconnect(pw->core); ++ } ++ ++ if (pw->context) { ++ pw_context_destroy(pw->context); ++ } ++ pw_thread_loop_destroy(pw->thread_loop); ++ ++ g_free(pw); ++} ++ ++static struct audio_pcm_ops qpw_pcm_ops = { ++ .init_out = qpw_init_out, ++ .fini_out = qpw_fini_out, ++ .write = qpw_write, ++ .buffer_get_free = qpw_buffer_get_free, ++ .run_buffer_out = audio_generic_run_buffer_out, ++ .enable_out = qpw_enable_out, ++ .volume_out = qpw_volume_out, ++ .volume_in = qpw_volume_in, ++ ++ .init_in = qpw_init_in, ++ .fini_in = qpw_fini_in, ++ .read = qpw_read, ++ .run_buffer_in = audio_generic_run_buffer_in, ++ .enable_in = qpw_enable_in ++}; ++ ++static struct audio_driver pw_audio_driver = { ++ .name = "pipewire", ++ .descr = "http://www.pipewire.org/", ++ .init = qpw_audio_init, ++ .fini = qpw_audio_fini, ++ .pcm_ops = &qpw_pcm_ops, ++ .max_voices_out = INT_MAX, ++ .max_voices_in = INT_MAX, ++ .voice_size_out = sizeof(PWVoiceOut), ++ .voice_size_in = sizeof(PWVoiceIn), ++}; ++ ++static void ++register_audio_pw(void) ++{ ++ audio_driver_register(&pw_audio_driver); ++} ++ ++type_init(register_audio_pw); +-- +2.41.0.windows.1 + diff --git a/block-blkio-use-FUA-flag-on-write-zeroes-only-if-sup.patch b/block-blkio-use-FUA-flag-on-write-zeroes-only-if-sup.patch new file mode 100644 index 00000000..969fd30f --- /dev/null +++ b/block-blkio-use-FUA-flag-on-write-zeroes-only-if-sup.patch @@ -0,0 +1,61 @@ +From 9daf2b936101d612a295217822791d323e908fc9 Mon Sep 17 00:00:00 2001 +From: Stefano Garzarella +Date: Thu, 8 Aug 2024 10:05:45 +0200 +Subject: [PATCH] block/blkio: use FUA flag on write zeroes only if supported +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +libblkio supports BLKIO_REQ_FUA with write zeros requests only since +version 1.4.0, so let's inform the block layer that the blkio driver +supports it only in this case. Otherwise we can have runtime errors +as reported in https://issues.redhat.com/browse/RHEL-32878 + +Fixes: fd66dbd424 ("blkio: add libblkio block driver") +Cc: qemu-stable@nongnu.org +Buglink: https://issues.redhat.com/browse/RHEL-32878 +Signed-off-by: Stefano Garzarella +Reviewed-by: Eric Blake +Reviewed-by: Philippe Mathieu-Daudé +Message-id: 20240808080545.40744-1-sgarzare@redhat.com +Signed-off-by: Stefan Hajnoczi +(cherry picked from commit 547c4e50929ec6c091d9c16a7b280e829b12b463) +Signed-off-by: zhujun2 +--- + block/blkio.c | 6 ++++-- + meson.build | 2 ++ + 2 files changed, 6 insertions(+), 2 deletions(-) + +diff --git a/block/blkio.c b/block/blkio.c +index b989617608..027c16ceb6 100644 +--- a/block/blkio.c ++++ b/block/blkio.c +@@ -899,8 +899,10 @@ static int blkio_file_open(BlockDriverState *bs, QDict *options, int flags, + } + + bs->supported_write_flags = BDRV_REQ_FUA | BDRV_REQ_REGISTERED_BUF; +- bs->supported_zero_flags = BDRV_REQ_FUA | BDRV_REQ_MAY_UNMAP | +- BDRV_REQ_NO_FALLBACK; ++ bs->supported_zero_flags = BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK; ++#ifdef CONFIG_BLKIO_WRITE_ZEROS_FUA ++ bs->supported_zero_flags |= BDRV_REQ_FUA; ++#endif + + qemu_mutex_init(&s->blkio_lock); + qemu_co_mutex_init(&s->bounce_lock); +diff --git a/meson.build b/meson.build +index 4024f9a4bb..ce2fd07963 100644 +--- a/meson.build ++++ b/meson.build +@@ -2181,6 +2181,8 @@ config_host_data.set('CONFIG_BLKIO', blkio.found()) + if blkio.found() + config_host_data.set('CONFIG_BLKIO_VHOST_VDPA_FD', + blkio.version().version_compare('>=1.3.0')) ++ config_host_data.set('CONFIG_BLKIO_WRITE_ZEROS_FUA', ++ blkio.version().version_compare('>=1.4.0')) + endif + config_host_data.set('CONFIG_CURL', curl.found()) + config_host_data.set('CONFIG_CURSES', curses.found()) +-- +2.41.0.windows.1 + diff --git a/crypto-drop-gnutls-debug-logging-support.patch b/crypto-drop-gnutls-debug-logging-support.patch new file mode 100644 index 00000000..d097bfb6 --- /dev/null +++ b/crypto-drop-gnutls-debug-logging-support.patch @@ -0,0 +1,57 @@ +From c64bd463b120056ff1e6c32e48fa24b6afd17f23 Mon Sep 17 00:00:00 2001 +From: dinglimin +Date: Sat, 12 Oct 2024 13:47:25 +0800 +Subject: [PATCH] crypto: drop gnutls debug logging support MIME-Version: 1.0 + Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +GNUTLS already supports dynamically enabling its logging at runtime by +setting the env var 'GNUTLS_DEBUG_LEVEL=10', so there is no need to +re-invent this logic in QEMU in a way that requires a re-compile. + +Reviewed-by: Philippe Mathieu-Daudé +Signed-off-by: Daniel P. Berrangé +Signed-off-by: dinglimin +--- + crypto/init.c | 15 ++++----------- + 1 file changed, 4 insertions(+), 11 deletions(-) + +diff --git a/crypto/init.c b/crypto/init.c +index fb7f1bff10..674d237fa9 100644 +--- a/crypto/init.c ++++ b/crypto/init.c +@@ -34,14 +34,11 @@ + + #include "crypto/random.h" + +-/* #define DEBUG_GNUTLS */ +-#ifdef DEBUG_GNUTLS +-static void qcrypto_gnutls_log(int level, const char *str) +-{ +- fprintf(stderr, "%d: %s", level, str); +-} +-#endif + ++/* ++ * To debug GNUTLS see env vars listed in ++ * https://gnutls.org/manual/html_node/Debugging-and-auditing.html ++ */ + int qcrypto_init(Error **errp) + { + #ifdef CONFIG_GNUTLS +@@ -53,10 +50,6 @@ int qcrypto_init(Error **errp) + gnutls_strerror(ret)); + return -1; + } +-#ifdef DEBUG_GNUTLS +- gnutls_global_set_log_level(10); +- gnutls_global_set_log_function(qcrypto_gnutls_log); +-#endif + #endif + + #ifdef CONFIG_GCRYPT +-- +2.41.0.windows.1 + diff --git a/crypto-factor-out-conversion-of-QAPI-to-gcrypt-const.patch b/crypto-factor-out-conversion-of-QAPI-to-gcrypt-const.patch new file mode 100644 index 00000000..ebeeb593 --- /dev/null +++ b/crypto-factor-out-conversion-of-QAPI-to-gcrypt-const.patch @@ -0,0 +1,168 @@ +From e1aaa51fc2de072871cce45dd165e2cb38515978 Mon Sep 17 00:00:00 2001 +From: dinglimin +Date: Sat, 12 Oct 2024 14:00:08 +0800 +Subject: [PATCH] crypto: factor out conversion of QAPI to gcrypt constants + MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 + Content-Transfer-Encoding: 8bit +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The conversion of cipher mode will shortly be required in more +than one place. + +Reviewed-by: Philippe Mathieu-Daudé +Reviewed-by: Thomas Huth +Signed-off-by: Daniel P. Berrangé +Signed-off-by: dinglimin +--- + crypto/cipher-gcrypt.c.inc | 116 +++++++++++++++++++------------------ + 1 file changed, 60 insertions(+), 56 deletions(-) + +diff --git a/crypto/cipher-gcrypt.c.inc b/crypto/cipher-gcrypt.c.inc +index 1377cbaf14..6b82280f90 100644 +--- a/crypto/cipher-gcrypt.c.inc ++++ b/crypto/cipher-gcrypt.c.inc +@@ -20,6 +20,56 @@ + + #include + ++static int qcrypto_cipher_alg_to_gcry_alg(QCryptoCipherAlgorithm alg) ++{ ++ switch (alg) { ++ case QCRYPTO_CIPHER_ALG_DES: ++ return GCRY_CIPHER_DES; ++ case QCRYPTO_CIPHER_ALG_3DES: ++ return GCRY_CIPHER_3DES; ++ case QCRYPTO_CIPHER_ALG_AES_128: ++ return GCRY_CIPHER_AES128; ++ case QCRYPTO_CIPHER_ALG_AES_192: ++ return GCRY_CIPHER_AES192; ++ case QCRYPTO_CIPHER_ALG_AES_256: ++ return GCRY_CIPHER_AES256; ++ case QCRYPTO_CIPHER_ALG_CAST5_128: ++ return GCRY_CIPHER_CAST5; ++ case QCRYPTO_CIPHER_ALG_SERPENT_128: ++ return GCRY_CIPHER_SERPENT128; ++ case QCRYPTO_CIPHER_ALG_SERPENT_192: ++ return GCRY_CIPHER_SERPENT192; ++ case QCRYPTO_CIPHER_ALG_SERPENT_256: ++ return GCRY_CIPHER_SERPENT256; ++ case QCRYPTO_CIPHER_ALG_TWOFISH_128: ++ return GCRY_CIPHER_TWOFISH128; ++ case QCRYPTO_CIPHER_ALG_TWOFISH_256: ++ return GCRY_CIPHER_TWOFISH; ++#ifdef CONFIG_CRYPTO_SM4 ++ case QCRYPTO_CIPHER_ALG_SM4: ++ return GCRY_CIPHER_SM4; ++#endif ++ default: ++ return GCRY_CIPHER_NONE; ++ } ++} ++ ++static int qcrypto_cipher_mode_to_gcry_mode(QCryptoCipherMode mode) ++{ ++ switch (mode) { ++ case QCRYPTO_CIPHER_MODE_ECB: ++ return GCRY_CIPHER_MODE_ECB; ++ case QCRYPTO_CIPHER_MODE_XTS: ++ return GCRY_CIPHER_MODE_XTS; ++ case QCRYPTO_CIPHER_MODE_CBC: ++ return GCRY_CIPHER_MODE_CBC; ++ case QCRYPTO_CIPHER_MODE_CTR: ++ return GCRY_CIPHER_MODE_CTR; ++ default: ++ return GCRY_CIPHER_MODE_NONE; ++ } ++} ++ + bool qcrypto_cipher_supports(QCryptoCipherAlgorithm alg, + QCryptoCipherMode mode) + { +@@ -188,72 +238,26 @@ static QCryptoCipher *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg, + return NULL; + } + +- switch (alg) { +- case QCRYPTO_CIPHER_ALG_DES: +- gcryalg = GCRY_CIPHER_DES; +- break; +- case QCRYPTO_CIPHER_ALG_3DES: +- gcryalg = GCRY_CIPHER_3DES; +- break; +- case QCRYPTO_CIPHER_ALG_AES_128: +- gcryalg = GCRY_CIPHER_AES128; +- break; +- case QCRYPTO_CIPHER_ALG_AES_192: +- gcryalg = GCRY_CIPHER_AES192; +- break; +- case QCRYPTO_CIPHER_ALG_AES_256: +- gcryalg = GCRY_CIPHER_AES256; +- break; +- case QCRYPTO_CIPHER_ALG_CAST5_128: +- gcryalg = GCRY_CIPHER_CAST5; +- break; +- case QCRYPTO_CIPHER_ALG_SERPENT_128: +- gcryalg = GCRY_CIPHER_SERPENT128; +- break; +- case QCRYPTO_CIPHER_ALG_SERPENT_192: +- gcryalg = GCRY_CIPHER_SERPENT192; +- break; +- case QCRYPTO_CIPHER_ALG_SERPENT_256: +- gcryalg = GCRY_CIPHER_SERPENT256; +- break; +- case QCRYPTO_CIPHER_ALG_TWOFISH_128: +- gcryalg = GCRY_CIPHER_TWOFISH128; +- break; +- case QCRYPTO_CIPHER_ALG_TWOFISH_256: +- gcryalg = GCRY_CIPHER_TWOFISH; +- break; +-#ifdef CONFIG_CRYPTO_SM4 +- case QCRYPTO_CIPHER_ALG_SM4: +- gcryalg = GCRY_CIPHER_SM4; +- break; +-#endif +- default: ++ gcryalg = qcrypto_cipher_alg_to_gcry_alg(alg); ++ if (gcryalg == GCRY_CIPHER_NONE) { + error_setg(errp, "Unsupported cipher algorithm %s", + QCryptoCipherAlgorithm_str(alg)); + return NULL; + } + +- drv = &qcrypto_gcrypt_driver; +- switch (mode) { +- case QCRYPTO_CIPHER_MODE_ECB: +- gcrymode = GCRY_CIPHER_MODE_ECB; +- break; +- case QCRYPTO_CIPHER_MODE_XTS: +- gcrymode = GCRY_CIPHER_MODE_XTS; +- break; +- case QCRYPTO_CIPHER_MODE_CBC: +- gcrymode = GCRY_CIPHER_MODE_CBC; +- break; +- case QCRYPTO_CIPHER_MODE_CTR: +- drv = &qcrypto_gcrypt_ctr_driver; +- gcrymode = GCRY_CIPHER_MODE_CTR; +- break; +- default: ++ gcrymode = qcrypto_cipher_mode_to_gcry_mode(mode); ++ if (gcrymode == GCRY_CIPHER_MODE_NONE) { + error_setg(errp, "Unsupported cipher mode %s", + QCryptoCipherMode_str(mode)); + return NULL; + } + ++ if (mode == QCRYPTO_CIPHER_MODE_CTR) { ++ drv = &qcrypto_gcrypt_ctr_driver; ++ } else { ++ drv = &qcrypto_gcrypt_driver; ++ } ++ + ctx = g_new0(QCryptoCipherGcrypt, 1); + ctx->base.driver = drv; + +-- +2.41.0.windows.1 + diff --git a/crypto-use-consistent-error-reporting-pattern-for-un.patch b/crypto-use-consistent-error-reporting-pattern-for-un.patch new file mode 100644 index 00000000..835e2790 --- /dev/null +++ b/crypto-use-consistent-error-reporting-pattern-for-un.patch @@ -0,0 +1,78 @@ +From 7bd04536327357a97206d8048f5d9341780bbe5a Mon Sep 17 00:00:00 2001 +From: dinglimin +Date: Sat, 12 Oct 2024 11:26:16 +0800 +Subject: [PATCH] crypto: use consistent error reporting pattern for + unsupported cipher modes MIME-Version: 1.0 Content-Type: text/plain; + charset=UTF-8 Content-Transfer-Encoding: 8bit +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Not all paths in qcrypto_cipher_ctx_new() were correctly distinguishing +between valid user input for cipher mode (which should report a user +facing error), vs program logic errors (which should assert). + +Reported-by: Peter Maydell +Signed-off-by: Daniel P. Berrangé +Signed-off-by: dinglimin +--- + crypto/cipher-nettle.c.inc | 18 ++++++++++++++---- + 1 file changed, 14 insertions(+), 4 deletions(-) + +diff --git a/crypto/cipher-nettle.c.inc b/crypto/cipher-nettle.c.inc +index 766de036ba..2654b439c1 100644 +--- a/crypto/cipher-nettle.c.inc ++++ b/crypto/cipher-nettle.c.inc +@@ -525,8 +525,10 @@ static QCryptoCipher *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg, + case QCRYPTO_CIPHER_MODE_CTR: + drv = &qcrypto_nettle_des_driver_ctr; + break; +- default: ++ case QCRYPTO_CIPHER_MODE_XTS: + goto bad_cipher_mode; ++ default: ++ g_assert_not_reached(); + } + + ctx = g_new0(QCryptoNettleDES, 1); +@@ -551,8 +553,10 @@ static QCryptoCipher *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg, + case QCRYPTO_CIPHER_MODE_CTR: + drv = &qcrypto_nettle_des3_driver_ctr; + break; +- default: ++ case QCRYPTO_CIPHER_MODE_XTS: + goto bad_cipher_mode; ++ default: ++ g_assert_not_reached(); + } + + ctx = g_new0(QCryptoNettleDES3, 1); +@@ -663,8 +667,10 @@ static QCryptoCipher *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg, + case QCRYPTO_CIPHER_MODE_CTR: + drv = &qcrypto_nettle_cast128_driver_ctr; + break; +- default: ++ case QCRYPTO_CIPHER_MODE_XTS: + goto bad_cipher_mode; ++ default: ++ g_assert_not_reached(); + } + + ctx = g_new0(QCryptoNettleCAST128, 1); +@@ -741,8 +747,12 @@ static QCryptoCipher *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg, + case QCRYPTO_CIPHER_MODE_ECB: + drv = &qcrypto_nettle_sm4_driver_ecb; + break; +- default: ++ case QCRYPTO_CIPHER_MODE_CBC: ++ case QCRYPTO_CIPHER_MODE_CTR: ++ case QCRYPTO_CIPHER_MODE_XTS: + goto bad_cipher_mode; ++ default: ++ g_assert_not_reached(); + } + + ctx = g_new0(QCryptoNettleSm4, 1); +-- +2.41.0.windows.1 + diff --git a/dma-Fix-function-names-in-documentation.patch b/dma-Fix-function-names-in-documentation.patch new file mode 100644 index 00000000..ae47cb2e --- /dev/null +++ b/dma-Fix-function-names-in-documentation.patch @@ -0,0 +1,61 @@ +From d490ccc1254c7d4dbe8ab40dd78e189108155ae0 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?=E5=BC=A0=E6=A5=9A=E5=90=9B?= + +Date: Fri, 18 Oct 2024 10:10:17 +0800 +Subject: [PATCH] dma: Fix function names in documentation Ensure the function + names match. + +Signed-off-by: Akihiko Odaki +Message-id: 20241012-dma-v2-1-6afddf5f3c8d@daynix.com +Reviewed-by: Peter Maydell +Signed-off-by: Peter Maydell +Signed-off-by: Zhang Chujun +--- + include/sysemu/dma.h | 11 +++++------ + 1 file changed, 5 insertions(+), 6 deletions(-) + +diff --git a/include/sysemu/dma.h b/include/sysemu/dma.h +index a1ac5bc1b5..5a49a30628 100644 +--- a/include/sysemu/dma.h ++++ b/include/sysemu/dma.h +@@ -152,7 +152,7 @@ static inline MemTxResult dma_memory_read(AddressSpace *as, dma_addr_t addr, + } + + /** +- * address_space_write: Write to address space from DMA controller. ++ * dma_memory_write: Write to address space from DMA controller. + * + * Return a MemTxResult indicating whether the operation succeeded + * or failed (eg unassigned memory, device rejected the transaction, +@@ -189,7 +189,7 @@ MemTxResult dma_memory_set(AddressSpace *as, dma_addr_t addr, + uint8_t c, dma_addr_t len, MemTxAttrs attrs); + + /** +- * address_space_map: Map a physical memory region into a host virtual address. ++ * dma_memory_map: Map a physical memory region into a host virtual address. + * + * May map a subset of the requested range, given by and returned in @plen. + * May return %NULL and set *@plen to zero(0), if resources needed to perform +@@ -216,16 +216,15 @@ static inline void *dma_memory_map(AddressSpace *as, + } + + /** +- * address_space_unmap: Unmaps a memory region previously mapped +- * by dma_memory_map() ++ * dma_memory_unmap: Unmaps a memory region previously mapped by dma_memory_map() + * + * Will also mark the memory as dirty if @dir == %DMA_DIRECTION_FROM_DEVICE. + * @access_len gives the amount of memory that was actually read or written + * by the caller. + * + * @as: #AddressSpace used +- * @buffer: host pointer as returned by address_space_map() +- * @len: buffer length as returned by address_space_map() ++ * @buffer: host pointer as returned by dma_memory_map() ++ * @len: buffer length as returned by dma_memory_map() + * @dir: indicates the transfer direction + * @access_len: amount of data actually transferred + */ +-- +2.41.0.windows.1 + diff --git a/docs-sphinx-depfile.py-Handle-env.doc2path-returning.patch b/docs-sphinx-depfile.py-Handle-env.doc2path-returning.patch new file mode 100644 index 00000000..fb84a704 --- /dev/null +++ b/docs-sphinx-depfile.py-Handle-env.doc2path-returning.patch @@ -0,0 +1,52 @@ +From e16c3aa63a203e376a40404314252a11e85a5bda Mon Sep 17 00:00:00 2001 +From: Peter Maydell +Date: Mon, 29 Jul 2024 13:05:33 +0100 +Subject: [PATCH] docs/sphinx/depfile.py: Handle env.doc2path() returning a + Path not a str +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +In newer versions of Sphinx the env.doc2path() API is going to change +to return a Path object rather than a str. This was originally visible +in Sphinx 8.0.0rc1, but has been rolled back for the final 8.0.0 +release. However it will probably emit a deprecation warning and is +likely to change for good in 9.0: + https://github.com/sphinx-doc/sphinx/issues/12686 + +Our use in depfile.py assumes a str, and if it is passed a Path +it will fall over: + Handler for event 'build-finished' threw an exception (exception: unsupported operand type(s) for +: 'PosixPath' and 'str') + +Wrapping the env.doc2path() call in str() will coerce a Path object +to the str we expect, and have no effect in older Sphinx versions +that do return a str. + +Cc: qemu-stable@nongnu.org +Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2458 +Signed-off-by: Peter Maydell +Reviewed-by: Philippe Mathieu-Daudé +Message-ID: <20240729120533.2486427-1-peter.maydell@linaro.org> +Signed-off-by: Philippe Mathieu-Daudé +(cherry picked from commit 48e5b5f994bccf161dd88a67fdd819d4bfb400f1) +Signed-off-by: zhujun2 +--- + docs/sphinx/depfile.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/docs/sphinx/depfile.py b/docs/sphinx/depfile.py +index afdcbcec6e..e74be6af98 100644 +--- a/docs/sphinx/depfile.py ++++ b/docs/sphinx/depfile.py +@@ -19,7 +19,7 @@ + + def get_infiles(env): + for x in env.found_docs: +- yield env.doc2path(x) ++ yield str(env.doc2path(x)) + yield from ((os.path.join(env.srcdir, dep) + for dep in env.dependencies[x])) + for mod in sys.modules.values(): +-- +2.41.0.windows.1 + diff --git a/docs-tools-qemu-img.rst-fix-typo-sumarizes.patch b/docs-tools-qemu-img.rst-fix-typo-sumarizes.patch new file mode 100644 index 00000000..780af091 --- /dev/null +++ b/docs-tools-qemu-img.rst-fix-typo-sumarizes.patch @@ -0,0 +1,31 @@ +From ac7182ca1b9ed7dbb524da734a9f426b2ca07503 Mon Sep 17 00:00:00 2001 +From: Zhang Jiao +Date: Mon, 21 Oct 2024 09:48:30 +0800 +Subject: [PATCH] docs/tools/qemu-img.rst: fix typo (sumarizes) + +cheery-pick from 8a8be21dde814e7cef43acac8140a7ccd0c4f6fb + +Signed-off-by: Samuel Tardieu +Reviewed-by: Zhao Liu +Signed-off-by: Michael Tokarev +Signed-off-by: Zhang Jiao +--- + docs/tools/qemu-img.rst | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/docs/tools/qemu-img.rst b/docs/tools/qemu-img.rst +index 4459c065f1..3653adb963 100644 +--- a/docs/tools/qemu-img.rst ++++ b/docs/tools/qemu-img.rst +@@ -406,7 +406,7 @@ Command description: + Compare exits with ``0`` in case the images are equal and with ``1`` + in case the images differ. Other exit codes mean an error occurred during + execution and standard error output should contain an error message. +- The following table sumarizes all exit codes of the compare subcommand: ++ The following table summarizes all exit codes of the compare subcommand: + + 0 + Images are identical (or requested help was printed) +-- +2.41.0.windows.1 + diff --git a/edu-fix-DMA-range-upper-bound-check.patch b/edu-fix-DMA-range-upper-bound-check.patch new file mode 100644 index 00000000..60ab815e --- /dev/null +++ b/edu-fix-DMA-range-upper-bound-check.patch @@ -0,0 +1,47 @@ +From edf3b2b0a9b9aa992592951a979d1b4642026fe5 Mon Sep 17 00:00:00 2001 +From: Zhang Jiao +Date: Fri, 18 Oct 2024 09:12:50 +0800 +Subject: [PATCH] edu: fix DMA range upper bound check + +cheery-pick from 2c5107e1b455d4a157124f021826ead4e04b4aea + +The edu_check_range function checks that start <= end1 < end2, where +end1 is the upper bound (exclusive) of the guest-supplied DMA range and +end2 is the upper bound (exclusive) of the device's allowed DMA range. +When the guest tries to transfer exactly DMA_SIZE (4096) bytes, end1 +will be equal to end2, so the check fails and QEMU aborts with this +puzzling error message (newlines added for formatting): + + qemu: hardware error: EDU: DMA range + 0x0000000000040000-0x0000000000040fff out of bounds + (0x0000000000040000-0x0000000000040fff)! + +By checking end1 <= end2 instead, guests will be allowed to transfer +exactly 4096 bytes. It is not necessary to explicitly check for +start <= end1 because the previous two checks (within(addr, start, end2) +and end1 > addr) imply start < end1. + +Fixes: b30934cb52a7 ("hw: misc, add educational driver", 2015-01-21) +Signed-off-by: Max Erenberg +Signed-off-by: Michael Tokarev +Signed-off-by: Zhang Jiao +--- + hw/misc/edu.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/hw/misc/edu.c b/hw/misc/edu.c +index a1f8bc77e7..e64a246d3f 100644 +--- a/hw/misc/edu.c ++++ b/hw/misc/edu.c +@@ -115,7 +115,7 @@ static void edu_check_range(uint64_t addr, uint64_t size1, uint64_t start, + uint64_t end2 = start + size2; + + if (within(addr, start, end2) && +- end1 > addr && within(end1, start, end2)) { ++ end1 > addr && end1 <= end2) { + return; + } + +-- +2.41.0.windows.1 + diff --git a/hw-cxl-Ensure-there-is-enough-data-to-read-the-input.patch b/hw-cxl-Ensure-there-is-enough-data-to-read-the-input.patch new file mode 100644 index 00000000..9d59b7d9 --- /dev/null +++ b/hw-cxl-Ensure-there-is-enough-data-to-read-the-input.patch @@ -0,0 +1,37 @@ +From d96c34e132df55ca7be458095f23d81dfc14e0d5 Mon Sep 17 00:00:00 2001 +From: Jonathan Cameron +Date: Fri, 1 Nov 2024 13:39:17 +0000 +Subject: [PATCH] hw/cxl: Ensure there is enough data to read the input header + in cmd_get_physical_port_state() + +If len_in is smaller than the header length then the accessing the +number of ports will result in an out of bounds access. +Add a check to avoid this. + +Reported-by: Esifiel +Signed-off-by: Jonathan Cameron +Message-Id: <20241101133917.27634-11-Jonathan.Cameron@huawei.com> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Signed-off-by: Zhongrui Tang +--- + hw/cxl/cxl-mailbox-utils.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/hw/cxl/cxl-mailbox-utils.c b/hw/cxl/cxl-mailbox-utils.c +index 6eff56fb1b..11a26525a2 100644 +--- a/hw/cxl/cxl-mailbox-utils.c ++++ b/hw/cxl/cxl-mailbox-utils.c +@@ -505,6 +505,9 @@ static CXLRetCode cmd_get_physical_port_state(const struct cxl_cmd *cmd, + in = (struct cxl_fmapi_get_phys_port_state_req_pl *)payload_in; + out = (struct cxl_fmapi_get_phys_port_state_resp_pl *)payload_out; + ++ if (len_in < sizeof(*in)) { ++ return CXL_MBOX_INVALID_PAYLOAD_LENGTH; ++ } + /* Check if what was requested can fit */ + if (sizeof(*out) + sizeof(*out->ports) * in->num_ports > cci->payload_max) { + return CXL_MBOX_INVALID_INPUT; +-- +2.41.0.windows.1 + diff --git a/hw-gpio-aspeed_gpio-Avoid-shift-into-sign-bit.patch b/hw-gpio-aspeed_gpio-Avoid-shift-into-sign-bit.patch new file mode 100644 index 00000000..9edcfec6 --- /dev/null +++ b/hw-gpio-aspeed_gpio-Avoid-shift-into-sign-bit.patch @@ -0,0 +1,36 @@ +From 10794f7a9bc3c88c8a26f094e5d3ef42e9fd290f Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?=E5=BC=A0=E6=A5=9A=E5=90=9B?= + +Date: Fri, 11 Oct 2024 14:04:54 +0800 +Subject: [PATCH] hw/gpio/aspeed_gpio: Avoid shift into sign bit + +In aspeed_gpio_update() we calculate "mask = 1 << gpio", where gpio can be between 0 and 31. +Coverity complains about this beacuse 1 << 31 won't fit in a signed integer. + +For QEMU this isn't an error because we enable -fwrapv, but we can keep Coverity happy +by doing the shift on unsigned numbers. + +Resolves: Coverity CID 1547742 +Signed-off-by: Peter Maydell +Reviewed-by: Cedric Le Goater +Signed-off-by: zhangchujun +--- + hw/gpio/aspeed_gpio.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/hw/gpio/aspeed_gpio.c b/hw/gpio/aspeed_gpio.c +index 1e267dd482..0fc3d4c05f 100644 +--- a/hw/gpio/aspeed_gpio.c ++++ b/hw/gpio/aspeed_gpio.c +@@ -281,7 +281,7 @@ static void aspeed_gpio_update(AspeedGPIOState *s, GPIOSets *regs, + diff &= mode_mask; + if (diff) { + for (gpio = 0; gpio < ASPEED_GPIOS_PER_SET; gpio++) { +- uint32_t mask = 1 << gpio; ++ uint32_t mask = 1U << gpio; + + /* If the gpio needs to be updated... */ + if (!(diff & mask)) { +-- +2.41.0.windows.1 + diff --git a/hw-intc-openpic-Improve-errors-for-out-of-bounds-pro.patch b/hw-intc-openpic-Improve-errors-for-out-of-bounds-pro.patch new file mode 100644 index 00000000..e9e94c64 --- /dev/null +++ b/hw-intc-openpic-Improve-errors-for-out-of-bounds-pro.patch @@ -0,0 +1,51 @@ +From 15b6c032ed2f92aa3210fe30376119eb468af039 Mon Sep 17 00:00:00 2001 +From: Zhang Jiao +Date: Wed, 23 Oct 2024 14:19:00 +0800 +Subject: [PATCH] hw/intc/openpic: Improve errors for out of bounds property + values +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +cheery-pick from 627c1e012cb3f14745f9b7d991642894a4402d5c + +The error message doesn't matter much, as the "openpic" device isn't +user-creatable. But it's the last use of +QERR_PROPERTY_VALUE_OUT_OF_RANGE, which has to go. Change the message +just like the previous commit did for x86 CPUs. + +Signed-off-by: Markus Armbruster +Message-ID: <20241010150144.986655-7-armbru@redhat.com> +Reviewed-by: Daniel P. Berrangé +Reviewed-by: Philippe Mathieu-Daudé +Signed-off-by: Zhang Jiao +--- + hw/intc/openpic.c | 5 +---- + 1 file changed, 1 insertion(+), 4 deletions(-) + +diff --git a/hw/intc/openpic.c b/hw/intc/openpic.c +index a6f91d4bcd..0f99b77a17 100644 +--- a/hw/intc/openpic.c ++++ b/hw/intc/openpic.c +@@ -41,7 +41,6 @@ + #include "hw/pci/msi.h" + #include "qapi/error.h" + #include "qemu/bitops.h" +-#include "qapi/qmp/qerror.h" + #include "qemu/module.h" + #include "qemu/timer.h" + #include "qemu/error-report.h" +@@ -1535,9 +1534,7 @@ static void openpic_realize(DeviceState *dev, Error **errp) + }; + + if (opp->nb_cpus > MAX_CPU) { +- error_setg(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE, +- TYPE_OPENPIC, "nb_cpus", (uint64_t)opp->nb_cpus, +- (uint64_t)0, (uint64_t)MAX_CPU); ++ error_setg(errp, "property 'nb_cpus' can be at most %d", MAX_CPU); + return; + } + +-- +2.41.0.windows.1 + diff --git a/hw-loongarch-virt-Remove-unnecessary-cpu.h-inclusion.patch b/hw-loongarch-virt-Remove-unnecessary-cpu.h-inclusion.patch new file mode 100644 index 00000000..0b15c947 --- /dev/null +++ b/hw-loongarch-virt-Remove-unnecessary-cpu.h-inclusion.patch @@ -0,0 +1,33 @@ +From cbd62b91ecdd0ec5f4ccb4c726e0adcdd2808270 Mon Sep 17 00:00:00 2001 +From: Susanooo +Date: Thu, 24 Oct 2024 10:34:17 +0800 +Subject: [PATCH] hw/loongarch/virt: Remove unnecessary 'cpu.h' inclusion +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Philippe Mathieu-Daudé +Reviewed-by: Song Gao +Reviewed-by: Thomas Huth +Message-Id: <20240927213254.17552-2-philmd@linaro.org> +Signed-off-by: Song Gao +Signed-off-by: zhangchujun +--- + include/hw/loongarch/virt.h | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/include/hw/loongarch/virt.h b/include/hw/loongarch/virt.h +index 99447fd1d6..17a792e596 100644 +--- a/include/hw/loongarch/virt.h ++++ b/include/hw/loongarch/virt.h +@@ -8,7 +8,6 @@ + #ifndef HW_LOONGARCH_H + #define HW_LOONGARCH_H + +-#include "target/loongarch/cpu.h" + #include "hw/boards.h" + #include "qemu/queue.h" + #include "hw/intc/loongarch_ipi.h" +-- +2.41.0.windows.1 + diff --git a/hw-net-can-sja1000-fix-bug-for-single-acceptance-fil.patch b/hw-net-can-sja1000-fix-bug-for-single-acceptance-fil.patch new file mode 100644 index 00000000..57b12ad4 --- /dev/null +++ b/hw-net-can-sja1000-fix-bug-for-single-acceptance-fil.patch @@ -0,0 +1,43 @@ +From 0b89dd1ae05d17f0bacbd34218799f00d04c8174 Mon Sep 17 00:00:00 2001 +From: Zhang Jiao +Date: Thu, 17 Oct 2024 11:13:06 +0800 +Subject: [PATCH] hw/net/can/sja1000: fix bug for single acceptance filter and + standard frame + +cheery-pick from 25145a7d7735344a469551946fc2a7f19eb4aa3d + +A CAN sja1000 standard frame filter mask has been computed and applied +incorrectly for standard frames when single Acceptance Filter Mode +(MOD_AFM = 1) has been selected. The problem has not been found +by Linux kernel testing because it uses dual filter mode (MOD_AFM = 0) +and leaves falters fully open. + +The problem has been noticed by Grant Ramsay when testing with Zephyr +RTOS which uses single filter mode. + +Signed-off-by: Pavel Pisa +Reported-by: Grant Ramsay +Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2028 +Fixes: 733210e754 ("hw/net/can: SJA1000 chip register level emulation") +Message-ID: <20240103231426.5685-1-pisa@fel.cvut.cz> +Signed-off-by: Zhang Jiao +--- + hw/net/can/can_sja1000.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/hw/net/can/can_sja1000.c b/hw/net/can/can_sja1000.c +index 73201f9139..575df7d2f8 100644 +--- a/hw/net/can/can_sja1000.c ++++ b/hw/net/can/can_sja1000.c +@@ -108,7 +108,7 @@ void can_sja_single_filter(struct qemu_can_filter *filter, + } + + filter->can_mask = (uint32_t)amr[0] << 3; +- filter->can_mask |= (uint32_t)amr[1] << 5; ++ filter->can_mask |= (uint32_t)amr[1] >> 5; + filter->can_mask = ~filter->can_mask & QEMU_CAN_SFF_MASK; + if (!(amr[1] & 0x10)) { + filter->can_mask |= QEMU_CAN_RTR_FLAG; +-- +2.41.0.windows.1 + diff --git a/hw-pci-bridge-Add-a-Kconfig-switch-for-the-normal-PC.patch b/hw-pci-bridge-Add-a-Kconfig-switch-for-the-normal-PC.patch new file mode 100644 index 00000000..1a2be67d --- /dev/null +++ b/hw-pci-bridge-Add-a-Kconfig-switch-for-the-normal-PC.patch @@ -0,0 +1,50 @@ +From 55ea1e473095ea5be692bb4ba2e44131a4a88e73 Mon Sep 17 00:00:00 2001 +From: Zhang Jiao +Date: Wed, 23 Oct 2024 13:40:51 +0800 +Subject: [PATCH] hw/pci-bridge: Add a Kconfig switch for the normal PCI bridge +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +cheery-pick from e779e5c05ad5d8237e2a7d8ba8b432cd24c1708b + +The pci-bridge device is not usable on s390x, so introduce a Kconfig +switch that allows to disable it. + +Message-ID: <20240913144844.427899-1-thuth@redhat.com> +Reviewed-by: Philippe Mathieu-Daudé +Reviewed-by: Cédric Le Goater +Signed-off-by: Thomas Huth +Signed-off-by: Zhang Jiao +--- + hw/pci-bridge/Kconfig | 5 +++++ + hw/pci-bridge/meson.build | 2 +- + 2 files changed, 6 insertions(+), 1 deletion(-) + +diff --git a/hw/pci-bridge/Kconfig b/hw/pci-bridge/Kconfig +index 67077366cc..449ec98643 100644 +--- a/hw/pci-bridge/Kconfig ++++ b/hw/pci-bridge/Kconfig +@@ -1,3 +1,8 @@ ++config PCI_BRIDGE ++ bool ++ default y if PCI_DEVICES ++ depends on PCI ++ + config PCIE_PORT + bool + default y if PCI_DEVICES +diff --git a/hw/pci-bridge/meson.build b/hw/pci-bridge/meson.build +index 6d5ad9f37b..a8b88e9099 100644 +--- a/hw/pci-bridge/meson.build ++++ b/hw/pci-bridge/meson.build +@@ -1,5 +1,5 @@ + pci_ss = ss.source_set() +-pci_ss.add(files('pci_bridge_dev.c')) ++pci_ss.add(when: 'CONFIG_PCI_BRIDGE', if_true: files('pci_bridge_dev.c')) + pci_ss.add(when: 'CONFIG_I82801B11', if_true: files('i82801b11.c')) + pci_ss.add(when: 'CONFIG_IOH3420', if_true: files('ioh3420.c')) + pci_ss.add(when: 'CONFIG_PCIE_PORT', if_true: files('pcie_root_port.c', 'gen_pcie_root_port.c')) +-- +2.41.0.windows.1 + diff --git a/intel_iommu-Send-IQE-event-when-setting-reserved-bit.patch b/intel_iommu-Send-IQE-event-when-setting-reserved-bit.patch new file mode 100644 index 00000000..d1e8e093 --- /dev/null +++ b/intel_iommu-Send-IQE-event-when-setting-reserved-bit.patch @@ -0,0 +1,39 @@ +From 66eb68e54a521bc0dac015415a9eca25fe479543 Mon Sep 17 00:00:00 2001 +From: Zhenzhong Duan +Date: Mon, 4 Nov 2024 20:55:34 +0800 +Subject: [PATCH] intel_iommu: Send IQE event when setting reserved bit in + IQT_TAIL + +According to VTD spec, Figure 11-22, Invalidation Queue Tail Register, +"When Descriptor Width (DW) field in Invalidation Queue Address Register +(IQA_REG) is Set (256-bit descriptors), hardware treats bit-4 as reserved +and a value of 1 in the bit will result in invalidation queue error." + +Current code missed to send IQE event to guest, fix it. + +Fixes: c0c1d351849b ("intel_iommu: add 256 bits qi_desc support") +Suggested-by: Yi Liu +Signed-off-by: Zhenzhong Duan +Message-Id: <20241104125536.1236118-2-zhenzhong.duan@intel.com> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Signed-off-by: Zhongrui Tang +--- + hw/i386/intel_iommu.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c +index 5085a6fee3..3da56e439e 100644 +--- a/hw/i386/intel_iommu.c ++++ b/hw/i386/intel_iommu.c +@@ -2813,6 +2813,7 @@ static void vtd_handle_iqt_write(IntelIOMMUState *s) + if (s->iq_dw && (val & VTD_IQT_QT_256_RSV_BIT)) { + error_report_once("%s: RSV bit is set: val=0x%"PRIx64, + __func__, val); ++ vtd_handle_inv_queue_error(s); + return; + } + s->iq_tail = VTD_IQT_QT(s->iq_dw, val); +-- +2.41.0.windows.1 + diff --git a/linux-user-Clean-up-unused-header.patch b/linux-user-Clean-up-unused-header.patch new file mode 100644 index 00000000..45469212 --- /dev/null +++ b/linux-user-Clean-up-unused-header.patch @@ -0,0 +1,35 @@ +From 34af051406f75bdef6f2ef598cde51e756ea8489 Mon Sep 17 00:00:00 2001 +From: Susanooo +Date: Fri, 25 Oct 2024 09:26:25 +0800 +Subject: [PATCH] linux-user: Clean up unused header +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Clean up unused (already commented-out) header from syscall.c. + +Signed-off-by: Gustavo Romero +Reviewed-by: Philippe Mathieu-Daudé +Reviewed-by: Richard Henderson +Reviewed-by: Michael Tokarev +Signed-off-by: Michael Tokarev +Signed-off-by: zhangchujun +--- + linux-user/syscall.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/linux-user/syscall.c b/linux-user/syscall.c +index e384e14248..513996e6fa 100644 +--- a/linux-user/syscall.c ++++ b/linux-user/syscall.c +@@ -53,7 +53,6 @@ + #include + #include + #include +-//#include + #include + #include + #include +-- +2.41.0.windows.1 + diff --git a/module-Prevent-crash-by-resetting-local_err-in-modul.patch b/module-Prevent-crash-by-resetting-local_err-in-modul.patch new file mode 100644 index 00000000..8ad7270c --- /dev/null +++ b/module-Prevent-crash-by-resetting-local_err-in-modul.patch @@ -0,0 +1,45 @@ +From 7187ed9e2010adfe937d6444eb79d8025c118c2c Mon Sep 17 00:00:00 2001 +From: Alexander Ivanov +Date: Fri, 9 Aug 2024 14:13:40 +0200 +Subject: [PATCH] module: Prevent crash by resetting local_err in + module_load_qom_all() + +Set local_err to NULL after it has been freed in error_report_err(). This +avoids triggering assert(*errp == NULL) failure in error_setv() when +local_err is reused in the loop. + +Signed-off-by: Alexander Ivanov +Reviewed-by: Claudio Fontana +Reviewed-by: Denis V. Lunev +Link: https://lore.kernel.org/r/20240809121340.992049-2-alexander.ivanov@virtuozzo.com +[Do the same by moving the declaration instead. - Paolo] +Cc: qemu-stable@nongnu.org +Signed-off-by: Paolo Bonzini +(cherry picked from commit 940d802b24e63650e0eacad3714e2ce171cba17c) +Signed-off-by: zhujun2 +--- + util/module.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/util/module.c b/util/module.c +index 32e263163c..3eb0f06df1 100644 +--- a/util/module.c ++++ b/util/module.c +@@ -354,13 +354,13 @@ int module_load_qom(const char *type, Error **errp) + void module_load_qom_all(void) + { + const QemuModinfo *modinfo; +- Error *local_err = NULL; + + if (module_loaded_qom_all) { + return; + } + + for (modinfo = module_info; modinfo->name != NULL; modinfo++) { ++ Error *local_err = NULL; + if (!modinfo->objs) { + continue; + } +-- +2.41.0.windows.1 + diff --git a/platform-bus-fix-refcount-leak.patch b/platform-bus-fix-refcount-leak.patch new file mode 100644 index 00000000..750d84d2 --- /dev/null +++ b/platform-bus-fix-refcount-leak.patch @@ -0,0 +1,42 @@ +From 0b23e1ad9e27fa60525b3d014da0425d2c24885f Mon Sep 17 00:00:00 2001 +From: Zhang Jiao +Date: Thu, 17 Oct 2024 13:19:51 +0800 +Subject: [PATCH] platform-bus: fix refcount leak + +cheery-pick from 99ec7b440a1d6a6ef07450b68687d24d13a25fb5 + +memory_region_find() returns an MR which it is the caller's +responsibility to unref, but platform_bus_map_mmio() was +forgetting to do so, thus leaking the MR. + +Signed-off-by: Gao Shiyuan gaoshiyuan@baidu.com +Message-id: 20240829131005.9196-1-gaoshiyuan@baidu.com +Reviewed-by: Peter Maydell peter.maydell@linaro.org +[PMM: tweaked commit message] +Signed-off-by: Peter Maydell peter.maydell@linaro.org +Signed-off-by: Zhang Jiao +--- + hw/core/platform-bus.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/hw/core/platform-bus.c b/hw/core/platform-bus.c +index b8487b26b6..dc58bf505a 100644 +--- a/hw/core/platform-bus.c ++++ b/hw/core/platform-bus.c +@@ -145,9 +145,12 @@ static void platform_bus_map_mmio(PlatformBusDevice *pbus, SysBusDevice *sbdev, + * the target device's memory region + */ + for (off = 0; off < pbus->mmio_size; off += alignment) { +- if (!memory_region_find(&pbus->mmio, off, size).mr) { ++ MemoryRegion *mr = memory_region_find(&pbus->mmio, off, size).mr; ++ if (!mr) { + found_region = true; + break; ++ } else { ++ memory_region_unref(mr); + } + } + +-- +2.41.0.windows.1 + diff --git a/ppc-xive-Fix-ESB-length-overflow-on-32-bit-hosts.patch b/ppc-xive-Fix-ESB-length-overflow-on-32-bit-hosts.patch new file mode 100644 index 00000000..551df5a6 --- /dev/null +++ b/ppc-xive-Fix-ESB-length-overflow-on-32-bit-hosts.patch @@ -0,0 +1,69 @@ +From c73b18ef8f2dd15934d90f65ba825bef19d11f73 Mon Sep 17 00:00:00 2001 +From: qihao_yewu +Date: Thu, 7 Nov 2024 22:07:23 -0500 +Subject: [PATCH] ppc/xive: Fix ESB length overflow on 32-bit hosts + +cheery-pick from 07f2770503e24889720028ddf9ef54788ddf3b6d + +The length of this region can be > 32-bits, which overflows size_t on +32-bit hosts. Change to uint64_t. + +Signed-off-by: Nicholas Piggin +Signed-off-by: qihao_yewu +--- + hw/intc/spapr_xive_kvm.c | 4 ++-- + hw/intc/xive.c | 2 +- + include/hw/ppc/xive.h | 2 +- + 3 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/hw/intc/spapr_xive_kvm.c b/hw/intc/spapr_xive_kvm.c +index 5789062379..7a86197fc9 100644 +--- a/hw/intc/spapr_xive_kvm.c ++++ b/hw/intc/spapr_xive_kvm.c +@@ -720,7 +720,7 @@ int kvmppc_xive_connect(SpaprInterruptController *intc, uint32_t nr_servers, + { + SpaprXive *xive = SPAPR_XIVE(intc); + XiveSource *xsrc = &xive->source; +- size_t esb_len = xive_source_esb_len(xsrc); ++ uint64_t esb_len = xive_source_esb_len(xsrc); + size_t tima_len = 4ull << TM_SHIFT; + CPUState *cs; + int fd; +@@ -824,7 +824,7 @@ void kvmppc_xive_disconnect(SpaprInterruptController *intc) + { + SpaprXive *xive = SPAPR_XIVE(intc); + XiveSource *xsrc; +- size_t esb_len; ++ uint64_t esb_len; + + assert(xive->fd != -1); + +diff --git a/hw/intc/xive.c b/hw/intc/xive.c +index a3585593d8..0cfc172dd4 100644 +--- a/hw/intc/xive.c ++++ b/hw/intc/xive.c +@@ -1238,7 +1238,7 @@ static void xive_source_reset(void *dev) + static void xive_source_realize(DeviceState *dev, Error **errp) + { + XiveSource *xsrc = XIVE_SOURCE(dev); +- size_t esb_len = xive_source_esb_len(xsrc); ++ uint64_t esb_len = xive_source_esb_len(xsrc); + + assert(xsrc->xive); + +diff --git a/include/hw/ppc/xive.h b/include/hw/ppc/xive.h +index f120874e0f..00023c0233 100644 +--- a/include/hw/ppc/xive.h ++++ b/include/hw/ppc/xive.h +@@ -218,7 +218,7 @@ static inline bool xive_source_esb_has_2page(XiveSource *xsrc) + xsrc->esb_shift == XIVE_ESB_4K_2PAGE; + } + +-static inline size_t xive_source_esb_len(XiveSource *xsrc) ++static inline uint64_t xive_source_esb_len(XiveSource *xsrc) + { + return (1ull << xsrc->esb_shift) * xsrc->nr_irqs; + } +-- +2.41.0.windows.1 + diff --git a/qemu.spec b/qemu.spec index 69cd4304..58f12884 100644 --- a/qemu.spec +++ b/qemu.spec @@ -3,7 +3,7 @@ Name: qemu Version: 8.2.0 -Release: 23 +Release: 24 Epoch: 11 Summary: QEMU is a generic and open source machine emulator and virtualizer License: GPLv2 and BSD and MIT and CC-BY-SA-4.0 @@ -389,6 +389,42 @@ Patch0372: Revert-vdpa-add-vhost_vdpa_suspend.patch Patch0373: Revert-vdpa-add-vhost_vdpa-suspended-parameter.patch Patch0374: Revert-vdpa-block-migration-if-SVQ-does-not-admit-a-.patch Patch0375: vdpa-remove-memory-listener-unregister-in-vhost_vdpa.patch +Patch0376: hw-gpio-aspeed_gpio-Avoid-shift-into-sign-bit.patch +Patch0377: crypto-use-consistent-error-reporting-pattern-for-un.patch +Patch0378: crypto-drop-gnutls-debug-logging-support.patch +Patch0379: crypto-factor-out-conversion-of-QAPI-to-gcrypt-const.patch +Patch0380: Consider-discard-option-when-writing-zeros.patch +Patch0381: util-userfaultfd-Remove-unused-uffd_poll_events.patch +Patch0382: tests-avocado-fix-typo-in-replay_linux.patch +Patch0383: hw-net-can-sja1000-fix-bug-for-single-acceptance-fil.patch +Patch0384: platform-bus-fix-refcount-leak.patch +Patch0385: edu-fix-DMA-range-upper-bound-check.patch +Patch0386: dma-Fix-function-names-in-documentation.patch +Patch0387: audio-pw-Report-more-accurate-error-when-connecting-.patch +Patch0388: audio-pw-Report-more-accurate-error-when-connecting--new.patch +Patch0389: docs-tools-qemu-img.rst-fix-typo-sumarizes.patch +Patch0390: hw-pci-bridge-Add-a-Kconfig-switch-for-the-normal-PC.patch +Patch0391: hw-intc-openpic-Improve-errors-for-out-of-bounds-pro.patch +Patch0392: acpi-ged-Add-macro-for-acpi-sleep-control-register.patch +Patch0393: tests-Wait-for-migration-completion-on-destination-Q.patch +Patch0394: hw-loongarch-virt-Remove-unnecessary-cpu.h-inclusion.patch +Patch0395: raw-format-Fix-error-message-for-invalid-offset-size.patch +Patch0396: linux-user-Clean-up-unused-header.patch +Patch0397: target-riscv-csr.c-Fix-an-access-to-VXSAT.patch +Patch0398: Fix-calculation-of-minimum-in-colo_compare_tcp.patch +Patch0399: virtio-net-Avoid-indirection_table_mask-overflow.patch +Patch0400: intel_iommu-Send-IQE-event-when-setting-reserved-bit.patch +Patch0401: hw-cxl-Ensure-there-is-enough-data-to-read-the-input.patch +Patch0402: virtio-pci-Fix-the-use-of-an-uninitialized-irqfd.patch +Patch0403: block-blkio-use-FUA-flag-on-write-zeroes-only-if-sup.patch +Patch0404: docs-sphinx-depfile.py-Handle-env.doc2path-returning.patch +Patch0405: target-arm-Fix-SVE-SDOT-UDOT-USDOT-4-way-indexed.patch +Patch0406: tests-docker-update-debian-i686-and-mipsel-images-to.patch +Patch0407: module-Prevent-crash-by-resetting-local_err-in-modul.patch +Patch0408: target-arm-Clear-high-SVE-elements-in-handle_vec_sim.patch +Patch0409: target-ppc-Fix-migration-of-CPUs-with-TLB_EMB-TLB-ty.patch +Patch0410: target-hppa-Fix-PSW-V-bit-packaging-in-cpu_hppa_get-.patch +Patch0411: ppc-xive-Fix-ESB-length-overflow-on-32-bit-hosts.patch BuildRequires: flex BuildRequires: gcc @@ -986,6 +1022,44 @@ getent passwd qemu >/dev/null || \ %endif %changelog +* Sat Nov 30 2024 Jiabo Feng - 11:8.2.0-24 +- ppc/xive: Fix ESB length overflow on 32-bit hosts +- target/hppa: Fix PSW V-bit packaging in cpu_hppa_get for hppa64 +- target/ppc: Fix migration of CPUs with TLB_EMB TLB type +- target/arm: Clear high SVE elements in handle_vec_simd_wshli +- module: Prevent crash by resetting local_err in module_load_qom_all() +- tests/docker: update debian i686 and mipsel images to bookworm +- target/arm: Fix SVE SDOT/UDOT/USDOT (4-way, indexed) +- docs/sphinx/depfile.py: Handle env.doc2path() returning a Path not a str +- block/blkio: use FUA flag on write zeroes only if supported +- virtio-pci: Fix the use of an uninitialized irqfd +- hw/cxl: Ensure there is enough data to read the input header in cmd_get_physical_port_state() +- intel_iommu: Send IQE event when setting reserved bit in IQT_TAIL +- virtio-net: Avoid indirection_table_mask overflow +- Fix calculation of minimum in colo_compare_tcp +- target/riscv/csr.c: Fix an access to VXSAT +- linux-user: Clean up unused header +- raw-format: Fix error message for invalid offset/size +- hw/loongarch/virt: Remove unnecessary 'cpu.h' inclusion +- tests: Wait for migration completion on destination QEMU to avoid failures +- acpi: ged: Add macro for acpi sleep control register +- hw/intc/openpic: Improve errors for out of bounds property values +- hw/pci-bridge: Add a Kconfig switch for the normal PCI bridge +- docs/tools/qemu-img.rst: fix typo (sumarizes) +- audio/pw: Report more accurate error when connecting to PipeWire fails +- audio/pw: Report more accurate error when connecting to PipeWire fails +- dma: Fix function names in documentation Ensure the function names match. +- edu: fix DMA range upper bound check +- platform-bus: fix refcount leak +- hw/net/can/sja1000: fix bug for single acceptance filter and standard frame +- tests/avocado: fix typo in replay_linux +- util/userfaultfd: Remove unused uffd_poll_events +- Consider discard option when writing zeros +- crypto: factor out conversion of QAPI to gcrypt constants +- crypto: drop gnutls debug logging support +- crypto: use consistent error reporting pattern for unsupported cipher modes +- hw/gpio/aspeed_gpio: Avoid shift into sign bit + * Thu Nov 28 2024 fangyi - 11:8.2.0-23 - vdpa: fix vdpa device migrate rollback wrong when suspend device failed. - vdpa: support resizing virtio-blk capacity online for kernel vdpa diff --git a/raw-format-Fix-error-message-for-invalid-offset-size.patch b/raw-format-Fix-error-message-for-invalid-offset-size.patch new file mode 100644 index 00000000..723aee8a --- /dev/null +++ b/raw-format-Fix-error-message-for-invalid-offset-size.patch @@ -0,0 +1,48 @@ +From 16fb3ec642af7ec7980b7ceff1b25abee3fecee2 Mon Sep 17 00:00:00 2001 +From: Susanooo +Date: Fri, 25 Oct 2024 09:20:38 +0800 +Subject: [PATCH] raw-format: Fix error message for invalid offset/size +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +s->offset and s->size are only set at the end of the function and still +contain the old values when formatting the error message. Print the +parameters with the new values that we actually checked instead. + +Fixes: 500e243 ('raw-format: Split raw_read_options()') +Signed-off-by: Kevin Wolf +Message-ID: <20240829185527.47152-1-kwolf@redhat.com> +Reviewed-by: Daniel P. Berrangé +Reviewed-by: Hanna Czenczek +Signed-off-by: Kevin Wolf +Signed-off-by: zhangchujun +--- + block/raw-format.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/block/raw-format.c b/block/raw-format.c +index 1111dffd54..8195ed87cc 100644 +--- a/block/raw-format.c ++++ b/block/raw-format.c +@@ -111,7 +111,7 @@ raw_apply_options(BlockDriverState *bs, BDRVRawState *s, uint64_t offset, + if (offset > real_size) { + error_setg(errp, "Offset (%" PRIu64 ") cannot be greater than " + "size of the containing file (%" PRId64 ")", +- s->offset, real_size); ++ offset, real_size); + return -EINVAL; + } + +@@ -119,7 +119,7 @@ raw_apply_options(BlockDriverState *bs, BDRVRawState *s, uint64_t offset, + error_setg(errp, "The sum of offset (%" PRIu64 ") and size " + "(%" PRIu64 ") has to be smaller or equal to the " + " actual size of the containing file (%" PRId64 ")", +- s->offset, s->size, real_size); ++ offset, size, real_size); + return -EINVAL; + } + +-- +2.41.0.windows.1 + diff --git a/target-arm-Clear-high-SVE-elements-in-handle_vec_sim.patch b/target-arm-Clear-high-SVE-elements-in-handle_vec_sim.patch new file mode 100644 index 00000000..a3a17d2e --- /dev/null +++ b/target-arm-Clear-high-SVE-elements-in-handle_vec_sim.patch @@ -0,0 +1,34 @@ +From 87ff72f354301147e35009dabdb8be68e9dfa30c Mon Sep 17 00:00:00 2001 +From: Richard Henderson +Date: Tue, 13 Aug 2024 11:42:49 +0100 +Subject: [PATCH] target/arm: Clear high SVE elements in handle_vec_simd_wshli + +AdvSIMD instructions are supposed to zero bits beyond 128. +Affects SSHLL, USHLL, SSHLL2, USHLL2. + +Cc: qemu-stable@nongnu.org +Signed-off-by: Richard Henderson +Message-id: 20240717060903.205098-15-richard.henderson@linaro.org +Reviewed-by: Peter Maydell +Signed-off-by: Peter Maydell +(cherry picked from commit 8e0c9a9efa21a16190cbac288e414bbf1d80f639) +Signed-off-by: zhujun2 +--- + target/arm/tcg/translate-a64.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c +index a2e49c39f9..5560a53630 100644 +--- a/target/arm/tcg/translate-a64.c ++++ b/target/arm/tcg/translate-a64.c +@@ -10141,6 +10141,7 @@ static void handle_vec_simd_wshli(DisasContext *s, bool is_q, bool is_u, + tcg_gen_shli_i64(tcg_rd, tcg_rd, shift); + write_vec_element(s, tcg_rd, rd, i, size + 1); + } ++ clear_vec_high(s, true, rd); + } + + /* SHRN/RSHRN - Shift right with narrowing (and potential rounding) */ +-- +2.41.0.windows.1 + diff --git a/target-arm-Fix-SVE-SDOT-UDOT-USDOT-4-way-indexed.patch b/target-arm-Fix-SVE-SDOT-UDOT-USDOT-4-way-indexed.patch new file mode 100644 index 00000000..676faaa3 --- /dev/null +++ b/target-arm-Fix-SVE-SDOT-UDOT-USDOT-4-way-indexed.patch @@ -0,0 +1,73 @@ +From 95f371c36858dd003c0c6a3d4f6ddfbc299dda9f Mon Sep 17 00:00:00 2001 +From: qihao_yewu +Date: Thu, 7 Nov 2024 20:56:18 -0500 +Subject: [PATCH] target/arm: Fix SVE SDOT/UDOT/USDOT (4-way, indexed) + +cheery-pick from e6b2fa1b81ac6b05c4397237c846a295a9857920 + +Our implementation of the indexed version of SVE SDOT/UDOT/USDOT got +the calculation of the inner loop terminator wrong. Although we +correctly account for the element size when we calculate the +terminator for the first iteration: + intptr_t segend = MIN(16 / sizeof(TYPED), opr_sz_n); +we don't do that when we move it forward after the first inner loop +completes. The intention is that we process the vector in 128-bit +segments, which for a 64-bit element size should mean (1, 2), (3, 4), +(5, 6), etc. This bug meant that we would iterate (1, 2), (3, 4, 5, +6), (7, 8, 9, 10) etc and apply the wrong indexed element to some of +the operations, and also index off the end of the vector. + +You don't see this bug if the vector length is small enough that we +don't need to iterate the outer loop, i.e. if it is only 128 bits, +or if it is the 64-bit special case from AA32/AA64 AdvSIMD. If the +vector length is 256 bits then we calculate the right results for the +elements in the vector but do index off the end of the vector. Vector +lengths greater than 256 bits see wrong answers. The instructions +that produce 32-bit results behave correctly. + +Fix the recalculation of 'segend' for subsequent iterations, and +restore a version of the comment that was lost in the refactor of +commit 7020ffd656a5 that explains why we only need to clamp segend to +opr_sz_n for the first iteration, not the later ones. + +Cc: qemu-stable@nongnu.org +Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2595 +Fixes: 7020ffd656a5 ("target/arm: Macroize helper_gvec_{s,u}dot_idx_{b,h}") +Signed-off-by: Peter Maydell +Reviewed-by: Richard Henderson +Message-id: 20241101185544.2130972-1-peter.maydell@linaro.org +Signed-off-by: qihao_yewu +--- + target/arm/tcg/vec_helper.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/target/arm/tcg/vec_helper.c b/target/arm/tcg/vec_helper.c +index 1f93510b85..11e874c05a 100644 +--- a/target/arm/tcg/vec_helper.c ++++ b/target/arm/tcg/vec_helper.c +@@ -692,6 +692,13 @@ void HELPER(NAME)(void *vd, void *vn, void *vm, void *va, uint32_t desc) \ + { \ + intptr_t i = 0, opr_sz = simd_oprsz(desc); \ + intptr_t opr_sz_n = opr_sz / sizeof(TYPED); \ ++ /* \ ++ * Special case: opr_sz == 8 from AA64/AA32 advsimd means the \ ++ * first iteration might not be a full 16 byte segment. But \ ++ * for vector lengths beyond that this must be SVE and we know \ ++ * opr_sz is a multiple of 16, so we need not clamp segend \ ++ * to opr_sz_n when we advance it at the end of the loop. \ ++ */ \ + intptr_t segend = MIN(16 / sizeof(TYPED), opr_sz_n); \ + intptr_t index = simd_data(desc); \ + TYPED *d = vd, *a = va; \ +@@ -709,7 +716,7 @@ void HELPER(NAME)(void *vd, void *vn, void *vm, void *va, uint32_t desc) \ + n[i * 4 + 2] * m2 + \ + n[i * 4 + 3] * m3); \ + } while (++i < segend); \ +- segend = i + 4; \ ++ segend = i + (16 / sizeof(TYPED)); \ + } while (i < opr_sz_n); \ + clear_tail(d, opr_sz, simd_maxsz(desc)); \ + } +-- +2.41.0.windows.1 + diff --git a/target-hppa-Fix-PSW-V-bit-packaging-in-cpu_hppa_get-.patch b/target-hppa-Fix-PSW-V-bit-packaging-in-cpu_hppa_get-.patch new file mode 100644 index 00000000..1aa893ee --- /dev/null +++ b/target-hppa-Fix-PSW-V-bit-packaging-in-cpu_hppa_get-.patch @@ -0,0 +1,58 @@ +From b1a14fd9b59803a17626903c5fb54f1aa2655d00 Mon Sep 17 00:00:00 2001 +From: Helge Deller +Date: Tue, 3 Sep 2024 17:22:10 +0200 +Subject: [PATCH] target/hppa: Fix PSW V-bit packaging in cpu_hppa_get for + hppa64 + +While adding hppa64 support, the psw_v variable got extended from 32 to 64 +bits. So, when packaging the PSW-V bit from the psw_v variable for interrupt +processing, check bit 31 instead the 63th (sign) bit. + +This fixes a hard to find Linux kernel boot issue where the loss of the PSW-V +bit due to an ITLB interruption in the middle of a series of ds/addc +instructions (from the divU milicode library) generated the wrong division +result and thus triggered a Linux kernel crash. + +Link: https://lore.kernel.org/lkml/718b8afe-222f-4b3a-96d3-93af0e4ceff1@roeck-us.net/ +Reported-by: Guenter Roeck +Signed-off-by: Helge Deller +Reviewed-by: Richard Henderson +Tested-by: Guenter Roeck +Fixes: 931adff31478 ("target/hppa: Update cpu_hppa_get/put_psw for hppa64") +Cc: qemu-stable@nongnu.org # v8.2+ +(cherry picked from commit ead5078cf1a5f11d16e3e8462154c859620bcc7e) +Signed-off-by: zhujun2 +--- + target/hppa/cpu.h | 2 +- + target/hppa/helper.c | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/target/hppa/cpu.h b/target/hppa/cpu.h +index 8be45c69c9..ba100c21a2 100644 +--- a/target/hppa/cpu.h ++++ b/target/hppa/cpu.h +@@ -188,7 +188,7 @@ typedef struct CPUArchState { + + target_ulong psw; /* All psw bits except the following: */ + target_ulong psw_n; /* boolean */ +- target_long psw_v; /* in most significant bit */ ++ target_long psw_v; /* in bit 31 */ + + /* Splitting the carry-borrow field into the MSB and "the rest", allows + * for "the rest" to be deleted when it is unused, but the MSB is in use. +diff --git a/target/hppa/helper.c b/target/hppa/helper.c +index 859644c47a..9e35b65f29 100644 +--- a/target/hppa/helper.c ++++ b/target/hppa/helper.c +@@ -53,7 +53,7 @@ target_ulong cpu_hppa_get_psw(CPUHPPAState *env) + } + + psw |= env->psw_n * PSW_N; +- psw |= (env->psw_v < 0) * PSW_V; ++ psw |= ((env->psw_v >> 31) & 1) * PSW_V; + psw |= env->psw; + + return psw; +-- +2.41.0.windows.1 + diff --git a/target-ppc-Fix-migration-of-CPUs-with-TLB_EMB-TLB-ty.patch b/target-ppc-Fix-migration-of-CPUs-with-TLB_EMB-TLB-ty.patch new file mode 100644 index 00000000..e1b94fe0 --- /dev/null +++ b/target-ppc-Fix-migration-of-CPUs-with-TLB_EMB-TLB-ty.patch @@ -0,0 +1,55 @@ +From fa282d002c45e1cc1cca6a2541b75ab5889c8c01 Mon Sep 17 00:00:00 2001 +From: Arman Nabiev +Date: Thu, 22 Aug 2024 19:56:53 +0300 +Subject: [PATCH] target/ppc: Fix migration of CPUs with TLB_EMB TLB type + +In vmstate_tlbemb a cut-and-paste error meant we gave +this vmstate subsection the same "cpu/tlb6xx" name as +the vmstate_tlb6xx subsection. This breaks migration load +for any CPU using the TLB_EMB CPU type, because when we +see the "tlb6xx" name in the incoming data we try to +interpret it as a vmstate_tlb6xx subsection, which it +isn't the right format for: + + $ qemu-system-ppc -drive + if=none,format=qcow2,file=/home/petmay01/test-images/virt/dummy.qcow2 + -monitor stdio -M bamboo + QEMU 9.0.92 monitor - type 'help' for more information + (qemu) savevm foo + (qemu) loadvm foo + Missing section footer for cpu + Error: Error -22 while loading VM state + +Correct the incorrect vmstate section name. Since migration +for these CPU types was completely broken before, we don't +need to care that this is a migration compatibility break. + +This affects the PPC 405, 440, 460 and e200 CPU families. + +Cc: qemu-stable@nongnu.org +Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2522 +Reviewed-by: Peter Maydell +Signed-off-by: Arman Nabiev +Signed-off-by: Fabiano Rosas +(cherry picked from commit 203beb6f047467a4abfc8267c234393cea3f471c) +Signed-off-by: zhujun2 +--- + target/ppc/machine.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/target/ppc/machine.c b/target/ppc/machine.c +index 68cbdffecd..3e010f3a07 100644 +--- a/target/ppc/machine.c ++++ b/target/ppc/machine.c +@@ -621,7 +621,7 @@ static bool tlbemb_needed(void *opaque) + } + + static const VMStateDescription vmstate_tlbemb = { +- .name = "cpu/tlb6xx", ++ .name = "cpu/tlbemb", + .version_id = 1, + .minimum_version_id = 1, + .needed = tlbemb_needed, +-- +2.41.0.windows.1 + diff --git a/target-riscv-csr.c-Fix-an-access-to-VXSAT.patch b/target-riscv-csr.c-Fix-an-access-to-VXSAT.patch new file mode 100644 index 00000000..50e9e6ff --- /dev/null +++ b/target-riscv-csr.c-Fix-an-access-to-VXSAT.patch @@ -0,0 +1,52 @@ +From 6b1b8553ea3810e497d225d64e98dd6eac7b4e2c Mon Sep 17 00:00:00 2001 +From: qihao_yewu +Date: Tue, 5 Nov 2024 03:21:00 -0500 +Subject: [PATCH] target/riscv/csr.c: Fix an access to VXSAT + +cheery-pick from 5a60026cad4e9dba929cab4f63229e4b9110cf0a + +The register VXSAT should be RW only to the first bit. +The remaining bits should be 0. + +The RISC-V Instruction Set Manual Volume I: Unprivileged Architecture + +The vxsat CSR has a single read-write least-significant bit (vxsat[0]) +that indicates if a fixed-point instruction has had to saturate an output +value to fit into a destination format. Bits vxsat[XLEN-1:1] +should be written as zeros. + +Signed-off-by: Evgenii Prokopiev +Reviewed-by: Daniel Henrique Barboza +Reviewed-by: Alistair Francis +Message-ID: <20241002084436.89347-1-evgenii.prokopiev@syntacore.com> +Signed-off-by: Alistair Francis +Signed-off-by: qihao_yewu +--- + target/riscv/csr.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/target/riscv/csr.c b/target/riscv/csr.c +index fde7ce1a53..d1bb7bc0d3 100644 +--- a/target/riscv/csr.c ++++ b/target/riscv/csr.c +@@ -704,7 +704,7 @@ static RISCVException write_vxrm(CPURISCVState *env, int csrno, + static RISCVException read_vxsat(CPURISCVState *env, int csrno, + target_ulong *val) + { +- *val = env->vxsat; ++ *val = env->vxsat & BIT(0); + return RISCV_EXCP_NONE; + } + +@@ -714,7 +714,7 @@ static RISCVException write_vxsat(CPURISCVState *env, int csrno, + #if !defined(CONFIG_USER_ONLY) + env->mstatus |= MSTATUS_VS; + #endif +- env->vxsat = val; ++ env->vxsat = val & BIT(0); + return RISCV_EXCP_NONE; + } + +-- +2.41.0.windows.1 + diff --git a/tests-Wait-for-migration-completion-on-destination-Q.patch b/tests-Wait-for-migration-completion-on-destination-Q.patch new file mode 100644 index 00000000..f65d4f86 --- /dev/null +++ b/tests-Wait-for-migration-completion-on-destination-Q.patch @@ -0,0 +1,44 @@ +From c4d618ea0dc507084d9c1e2b61e58691a73c2cf4 Mon Sep 17 00:00:00 2001 +From: Susanooo +Date: Thu, 24 Oct 2024 10:10:34 +0800 +Subject: [PATCH] tests: Wait for migration completion on destination QEMU to + avoid failures +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Rather than waiting for the completion of migration on the source side, +wait for it on the destination QEMU side to avoid accessing the TPM TIS +memory mapped registers before QEMU could restore their state. This +error condition could be triggered on busy systems where the destination +QEMU did not have enough time to restore the TIS state while the test case +was already reading its registers. The test case was for example reading +the STS register and received an unexpected value (0xffffffff), whic +lead to a segmentation fault later on due to trying to read 0xffff bytes +from the TIS into a buffer. + +Cc: +Reported-by: Fabiano Rosas +Reviewed-by: Daniel P. Berrangé +Signed-off-by: Stefan Berger +Signed-off-by: zhangchujun +--- + tests/qtest/tpm-tests.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tests/qtest/tpm-tests.c b/tests/qtest/tpm-tests.c +index fb94496bbd..197714f8d9 100644 +--- a/tests/qtest/tpm-tests.c ++++ b/tests/qtest/tpm-tests.c +@@ -114,7 +114,7 @@ void tpm_test_swtpm_migration_test(const char *src_tpm_path, + sizeof(tpm_pcrread_resp)); + + tpm_util_migrate(src_qemu, uri); +- tpm_util_wait_for_migration_complete(src_qemu); ++ tpm_util_wait_for_migration_complete(dst_qemu); + + tpm_util_pcrread(dst_qemu, tx, tpm_pcrread_resp, + sizeof(tpm_pcrread_resp)); +-- +2.41.0.windows.1 + diff --git a/tests-avocado-fix-typo-in-replay_linux.patch b/tests-avocado-fix-typo-in-replay_linux.patch new file mode 100644 index 00000000..0a594963 --- /dev/null +++ b/tests-avocado-fix-typo-in-replay_linux.patch @@ -0,0 +1,36 @@ +From 0f62625a0f8b6244203fbd2838b8e9c29efc2eea Mon Sep 17 00:00:00 2001 +From: Zhang Jiao +Date: Thu, 17 Oct 2024 10:49:54 +0800 +Subject: [PATCH] tests/avocado: fix typo in replay_linux +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +cheery-pick from 2d8508bbab39bf342fe80e73c0b528eb3960fa37 + +Reviewed-by: Pavel Dovgalyuk +Reviewed-by: Philippe Mathieu-Daudé +Reviewed-by: Richard Henderson +Signed-off-by: Alex Bennée +Message-Id: <20231211091346.14616-3-alex.bennee@linaro.org> +Signed-off-by: Zhang Jiao +--- + tests/avocado/replay_linux.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tests/avocado/replay_linux.py b/tests/avocado/replay_linux.py +index 270ccc1eae..e95bff3299 100644 +--- a/tests/avocado/replay_linux.py ++++ b/tests/avocado/replay_linux.py +@@ -94,7 +94,7 @@ def launch_and_wait(self, record, args, shift): + else: + vm.event_wait('SHUTDOWN', self.timeout) + vm.wait() +- logger.info('successfully fihished the replay') ++ logger.info('successfully finished the replay') + elapsed = time.time() - start_time + logger.info('elapsed time %.2f sec' % elapsed) + return elapsed +-- +2.41.0.windows.1 + diff --git a/tests-docker-update-debian-i686-and-mipsel-images-to.patch b/tests-docker-update-debian-i686-and-mipsel-images-to.patch new file mode 100644 index 00000000..a06421b2 --- /dev/null +++ b/tests-docker-update-debian-i686-and-mipsel-images-to.patch @@ -0,0 +1,154 @@ +From ea21c12b545ad6eecded5f34472d3f226f5a2e15 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Alex=20Benn=C3=A9e?= +Date: Tue, 10 Sep 2024 18:38:52 +0100 +Subject: [PATCH] tests/docker: update debian i686 and mipsel images to + bookworm +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Whatever issues there were which stopped these being updates when the +rest were have now been resolved. However mips64el continues to be +broken so don't update it here. + +Reviewed-by: Pierrick Bouvier +Reviewed-by: Richard Henderson +Signed-off-by: Alex Bennée +Message-Id: <20240910173900.4154726-3-alex.bennee@linaro.org> +(cherry picked from commit 19d2111059c87d3f58349f27b9be9dee81fc1681) +Signed-off-by: zhujun2 +--- + tests/docker/dockerfiles/debian-i686-cross.docker | 10 ++++------ + tests/docker/dockerfiles/debian-mipsel-cross.docker | 10 ++++------ + tests/lcitool/refresh | 4 ++-- + 3 files changed, 10 insertions(+), 14 deletions(-) + +diff --git a/tests/docker/dockerfiles/debian-i686-cross.docker b/tests/docker/dockerfiles/debian-i686-cross.docker +index 3fc4e15acd..e1c8e2b494 100644 +--- a/tests/docker/dockerfiles/debian-i686-cross.docker ++++ b/tests/docker/dockerfiles/debian-i686-cross.docker +@@ -1,10 +1,10 @@ + # THIS FILE WAS AUTO-GENERATED + # +-# $ lcitool dockerfile --layers all --cross-arch i686 debian-11 qemu ++# $ lcitool dockerfile --layers all --cross-arch i686 debian-12 qemu + # + # https://gitlab.com/libvirt/libvirt-ci + +-FROM docker.io/library/debian:11-slim ++FROM docker.io/library/debian:12-slim + + RUN export DEBIAN_FRONTEND=noninteractive && \ + apt-get update && \ +@@ -47,16 +47,15 @@ RUN export DEBIAN_FRONTEND=noninteractive && \ + python3-opencv \ + python3-pillow \ + python3-pip \ +- python3-setuptools \ + python3-sphinx \ + python3-sphinx-rtd-theme \ + python3-venv \ +- python3-wheel \ + python3-yaml \ + rpm2cpio \ + sed \ + socat \ + sparse \ ++ swtpm \ + tar \ + tesseract-ocr \ + tesseract-ocr-eng \ +@@ -67,8 +66,6 @@ RUN export DEBIAN_FRONTEND=noninteractive && \ + sed -Ei 's,^# (en_US\.UTF-8 .*)$,\1,' /etc/locale.gen && \ + dpkg-reconfigure locales + +-RUN /usr/bin/pip3 install tomli +- + ENV CCACHE_WRAPPERSDIR "/usr/libexec/ccache-wrappers" + ENV LANG "en_US.UTF-8" + ENV MAKE "/usr/bin/make" +@@ -145,6 +142,7 @@ RUN export DEBIAN_FRONTEND=noninteractive && \ + libvdeplug-dev:i386 \ + libvirglrenderer-dev:i386 \ + libvte-2.91-dev:i386 \ ++ libxdp-dev:i386 \ + libzstd-dev:i386 \ + nettle-dev:i386 \ + systemtap-sdt-dev:i386 \ +diff --git a/tests/docker/dockerfiles/debian-mipsel-cross.docker b/tests/docker/dockerfiles/debian-mipsel-cross.docker +index 5fcd641f15..79ce4ae503 100644 +--- a/tests/docker/dockerfiles/debian-mipsel-cross.docker ++++ b/tests/docker/dockerfiles/debian-mipsel-cross.docker +@@ -1,10 +1,10 @@ + # THIS FILE WAS AUTO-GENERATED + # +-# $ lcitool dockerfile --layers all --cross-arch mipsel debian-11 qemu ++# $ lcitool dockerfile --layers all --cross-arch mipsel debian-12 qemu + # + # https://gitlab.com/libvirt/libvirt-ci + +-FROM docker.io/library/debian:11-slim ++FROM docker.io/library/debian:12-slim + + RUN export DEBIAN_FRONTEND=noninteractive && \ + apt-get update && \ +@@ -47,16 +47,15 @@ RUN export DEBIAN_FRONTEND=noninteractive && \ + python3-opencv \ + python3-pillow \ + python3-pip \ +- python3-setuptools \ + python3-sphinx \ + python3-sphinx-rtd-theme \ + python3-venv \ +- python3-wheel \ + python3-yaml \ + rpm2cpio \ + sed \ + socat \ + sparse \ ++ swtpm \ + tar \ + tesseract-ocr \ + tesseract-ocr-eng \ +@@ -67,8 +66,6 @@ RUN export DEBIAN_FRONTEND=noninteractive && \ + sed -Ei 's,^# (en_US\.UTF-8 .*)$,\1,' /etc/locale.gen && \ + dpkg-reconfigure locales + +-RUN /usr/bin/pip3 install tomli +- + ENV CCACHE_WRAPPERSDIR "/usr/libexec/ccache-wrappers" + ENV LANG "en_US.UTF-8" + ENV MAKE "/usr/bin/make" +@@ -143,6 +140,7 @@ RUN export DEBIAN_FRONTEND=noninteractive && \ + libvdeplug-dev:mipsel \ + libvirglrenderer-dev:mipsel \ + libvte-2.91-dev:mipsel \ ++ libxdp-dev:mipsel \ + libzstd-dev:mipsel \ + nettle-dev:mipsel \ + systemtap-sdt-dev:mipsel \ +diff --git a/tests/lcitool/refresh b/tests/lcitool/refresh +index 0c93557ad6..42ed7eba1d 100755 +--- a/tests/lcitool/refresh ++++ b/tests/lcitool/refresh +@@ -159,7 +159,7 @@ try: + trailer=cross_build("arm-linux-gnueabihf-", + "arm-softmmu,arm-linux-user")) + +- generate_dockerfile("debian-i686-cross", "debian-11", ++ generate_dockerfile("debian-i686-cross", "debian-12", + cross="i686", + trailer=cross_build("x86_64-linux-gnu-", + "x86_64-softmmu," +@@ -171,7 +171,7 @@ try: + trailer=cross_build("mips64el-linux-gnuabi64-", + "mips64el-softmmu,mips64el-linux-user")) + +- generate_dockerfile("debian-mipsel-cross", "debian-11", ++ generate_dockerfile("debian-mipsel-cross", "debian-12", + cross="mipsel", + trailer=cross_build("mipsel-linux-gnu-", + "mipsel-softmmu,mipsel-linux-user")) +-- +2.41.0.windows.1 + diff --git a/util-userfaultfd-Remove-unused-uffd_poll_events.patch b/util-userfaultfd-Remove-unused-uffd_poll_events.patch new file mode 100644 index 00000000..31b02840 --- /dev/null +++ b/util-userfaultfd-Remove-unused-uffd_poll_events.patch @@ -0,0 +1,71 @@ +From ef3d2918827d6c5204af06e1597dc4dbde22414a Mon Sep 17 00:00:00 2001 +From: Zhang Jiao +Date: Thu, 17 Oct 2024 09:43:01 +0800 +Subject: [PATCH] util/userfaultfd: Remove unused uffd_poll_events + +chery-pick from ccf6b78275816c9dec84d3a40e9aa3b6ba6ebc06 + +uffd_poll_events has been unused since it was added; it's also +just a wrapper around a plain old poll call, so doesn't add anything. + +Signed-off-by: Dr. David Alan Gilbert +Reviewed-by: Peter Xu +Link: https://lore.kernel.org/r/20240919134626.166183-8-dave@treblig.org +Signed-off-by: Peter Xu +Signed-off-by: Zhang Jiao +--- + include/qemu/userfaultfd.h | 1 - + util/userfaultfd.c | 28 ---------------------------- + 2 files changed, 29 deletions(-) + +diff --git a/include/qemu/userfaultfd.h b/include/qemu/userfaultfd.h +index 18a4314212..a1979308d7 100644 +--- a/include/qemu/userfaultfd.h ++++ b/include/qemu/userfaultfd.h +@@ -39,7 +39,6 @@ int uffd_copy_page(int uffd_fd, void *dst_addr, void *src_addr, + int uffd_zero_page(int uffd_fd, void *addr, uint64_t length, bool dont_wake); + int uffd_wakeup(int uffd_fd, void *addr, uint64_t length); + int uffd_read_events(int uffd_fd, struct uffd_msg *msgs, int count); +-bool uffd_poll_events(int uffd_fd, int tmo); + + #endif /* CONFIG_LINUX */ + +diff --git a/util/userfaultfd.c b/util/userfaultfd.c +index fdff4867e8..b7d320d0b1 100644 +--- a/util/userfaultfd.c ++++ b/util/userfaultfd.c +@@ -356,31 +356,3 @@ int uffd_read_events(int uffd_fd, struct uffd_msg *msgs, int count) + + return (int) (res / sizeof(struct uffd_msg)); + } +- +-/** +- * uffd_poll_events: poll UFFD file descriptor for read +- * +- * Returns true if events are available for read, false otherwise +- * +- * @uffd_fd: UFFD file descriptor +- * @tmo: timeout value +- */ +-bool uffd_poll_events(int uffd_fd, int tmo) +-{ +- int res; +- struct pollfd poll_fd = { .fd = uffd_fd, .events = POLLIN, .revents = 0 }; +- +- do { +- res = poll(&poll_fd, 1, tmo); +- } while (res < 0 && errno == EINTR); +- +- if (res == 0) { +- return false; +- } +- if (res < 0) { +- error_report("uffd_poll_events() failed: errno=%i", errno); +- return false; +- } +- +- return (poll_fd.revents & POLLIN) != 0; +-} +-- +2.41.0.windows.1 + diff --git a/virtio-net-Avoid-indirection_table_mask-overflow.patch b/virtio-net-Avoid-indirection_table_mask-overflow.patch new file mode 100644 index 00000000..6ac7af0b --- /dev/null +++ b/virtio-net-Avoid-indirection_table_mask-overflow.patch @@ -0,0 +1,48 @@ +From cc875acdbf0ab210ce467f27c621fe7dc2159110 Mon Sep 17 00:00:00 2001 +From: zhangchujun +Date: Wed, 30 Oct 2024 10:57:05 +0800 +Subject: [PATCH] virtio-net: Avoid indirection_table_mask overflow + +We computes indirections_len by adding 1 to indirection_table_mask, but +it may overflow indirection_table_mask is UINT16_MAX. Check if +indirection_table_mask is small enough before adding 1. + +Fixes: 5907902 ("virtio-net: implement RSS configuration command") +Signed-off-by: Akihiko Odaki +Signed-off-by: Jason Wang +Signed-off-by: zhangchujun +--- + hw/net/virtio-net.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c +index 432c433540..d5008b65ec 100644 +--- a/hw/net/virtio-net.c ++++ b/hw/net/virtio-net.c +@@ -1400,17 +1400,17 @@ static uint16_t virtio_net_handle_rss(VirtIONet *n, + n->rss_data.hash_types = virtio_ldl_p(vdev, &cfg.hash_types); + n->rss_data.indirections_len = + virtio_lduw_p(vdev, &cfg.indirection_table_mask); +- n->rss_data.indirections_len++; + if (!do_rss) { +- n->rss_data.indirections_len = 1; ++ n->rss_data.indirections_len = 0; + } +- if (!is_power_of_2(n->rss_data.indirections_len)) { +- err_msg = "Invalid size of indirection table"; ++ if (n->rss_data.indirections_len >= VIRTIO_NET_RSS_MAX_TABLE_LEN) { ++ err_msg = "Too large indirection table"; + err_value = n->rss_data.indirections_len; + goto error; + } +- if (n->rss_data.indirections_len > VIRTIO_NET_RSS_MAX_TABLE_LEN) { +- err_msg = "Too large indirection table"; ++ n->rss_data.indirections_len++; ++ if (!is_power_of_2(n->rss_data.indirections_len)) { ++ err_msg = "Invalid size of indirection table"; + err_value = n->rss_data.indirections_len; + goto error; + } +-- +2.41.0.windows.1 + diff --git a/virtio-pci-Fix-the-use-of-an-uninitialized-irqfd.patch b/virtio-pci-Fix-the-use-of-an-uninitialized-irqfd.patch new file mode 100644 index 00000000..bc84f247 --- /dev/null +++ b/virtio-pci-Fix-the-use-of-an-uninitialized-irqfd.patch @@ -0,0 +1,80 @@ +From 9cd544b83ccd37b9dd7977717a245437533830cd Mon Sep 17 00:00:00 2001 +From: Cindy Lu +Date: Tue, 6 Aug 2024 17:37:12 +0800 +Subject: [PATCH] virtio-pci: Fix the use of an uninitialized irqfd + +The crash was reported in MAC OS and NixOS, here is the link for this bug +https://gitlab.com/qemu-project/qemu/-/issues/2334 +https://gitlab.com/qemu-project/qemu/-/issues/2321 + +In this bug, they are using the virtio_input device. The guest notifier was +not supported for this device, The function virtio_pci_set_guest_notifiers() +was not called, and the vector_irqfd was not initialized. + +So the fix is adding the check for vector_irqfd in virtio_pci_get_notifier() + +The function virtio_pci_get_notifier() can be used in various devices. +It could also be called when VIRTIO_CONFIG_S_DRIVER_OK is not set. In this situation, +the vector_irqfd being NULL is acceptable. We can allow the device continue to boot + +If the vector_irqfd still hasn't been initialized after VIRTIO_CONFIG_S_DRIVER_OK +is set, it means that the function set_guest_notifiers was not called before the +driver started. This indicates that the device is not using the notifier. +At this point, we will let the check fail. + +This fix is verified in vyatta,MacOS,NixOS,fedora system. + +The bt tree for this bug is: +Thread 6 "CPU 0/KVM" received signal SIGSEGV, Segmentation fault. +[Switching to Thread 0x7c817be006c0 (LWP 1269146)] +kvm_virtio_pci_vq_vector_use () at ../qemu-9.0.0/hw/virtio/virtio-pci.c:817 +817 if (irqfd->users == 0) { +(gdb) thread apply all bt +... +Thread 6 (Thread 0x7c817be006c0 (LWP 1269146) "CPU 0/KVM"): +0 kvm_virtio_pci_vq_vector_use () at ../qemu-9.0.0/hw/virtio/virtio-pci.c:817 +1 kvm_virtio_pci_vector_use_one () at ../qemu-9.0.0/hw/virtio/virtio-pci.c:893 +2 0x00005983657045e2 in memory_region_write_accessor () at ../qemu-9.0.0/system/memory.c:497 +3 0x0000598365704ba6 in access_with_adjusted_size () at ../qemu-9.0.0/system/memory.c:573 +4 0x0000598365705059 in memory_region_dispatch_write () at ../qemu-9.0.0/system/memory.c:1528 +5 0x00005983659b8e1f in flatview_write_continue_step.isra.0 () at ../qemu-9.0.0/system/physmem.c:2713 +6 0x000059836570ba7d in flatview_write_continue () at ../qemu-9.0.0/system/physmem.c:2743 +7 flatview_write () at ../qemu-9.0.0/system/physmem.c:2774 +8 0x000059836570bb76 in address_space_write () at ../qemu-9.0.0/system/physmem.c:2894 +9 0x0000598365763afe in address_space_rw () at ../qemu-9.0.0/system/physmem.c:2904 +10 kvm_cpu_exec () at ../qemu-9.0.0/accel/kvm/kvm-all.c:2917 +11 0x000059836576656e in kvm_vcpu_thread_fn () at ../qemu-9.0.0/accel/kvm/kvm-accel-ops.c:50 +12 0x0000598365926ca8 in qemu_thread_start () at ../qemu-9.0.0/util/qemu-thread-posix.c:541 +13 0x00007c8185bcd1cf in ??? () at /usr/lib/libc.so.6 +14 0x00007c8185c4e504 in clone () at /usr/lib/libc.so.6 + +Fixes: 2ce6cff94d ("virtio-pci: fix use of a released vector") +Cc: qemu-stable@nongnu.org +Signed-off-by: Cindy Lu +Message-Id: <20240806093715.65105-1-lulu@redhat.com> +Acked-by: Jason Wang +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +(cherry picked from commit a8e63ff289d137197ad7a701a587cc432872d798) +Signed-off-by: zhujun2 +--- + hw/virtio/virtio-pci.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c +index 3ad7487411..06b125ec62 100644 +--- a/hw/virtio/virtio-pci.c ++++ b/hw/virtio/virtio-pci.c +@@ -860,6 +860,9 @@ static int virtio_pci_get_notifier(VirtIOPCIProxy *proxy, int queue_no, + VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); + VirtQueue *vq; + ++ if (!proxy->vector_irqfd && vdev->status & VIRTIO_CONFIG_S_DRIVER_OK) ++ return -1; ++ + if (queue_no == VIRTIO_CONFIG_IRQ_IDX) { + *n = virtio_config_get_guest_notifier(vdev); + *vector = vdev->config_vector; +-- +2.41.0.windows.1 + -- Gitee