!1044 [sync] PR-1040: QEMU update to version 8.2.0-24
From: @openeuler-sync-bot Reviewed-by: @imxcc Signed-off-by: @imxcc
This commit is contained in:
commit
d66a1d2fae
287
Consider-discard-option-when-writing-zeros.patch
Normal file
287
Consider-discard-option-when-writing-zeros.patch
Normal file
@ -0,0 +1,287 @@
|
||||
From 60b9463e35fe801e49db14539ccb8c9a6057e5c3 Mon Sep 17 00:00:00 2001
|
||||
From: dinglimin <dinglimin@cmss.chinamobile.com>
|
||||
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 <nsoffer@redhat.com>
|
||||
Message-id: 20240628202058.1964986-3-nsoffer@redhat.com
|
||||
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
|
||||
Signed-off-by: dinglimin <dinglimin@cmss.chinamobile.com>
|
||||
---
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
+#
|
||||
+
|
||||
+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
|
||||
|
||||
35
Fix-calculation-of-minimum-in-colo_compare_tcp.patch
Normal file
35
Fix-calculation-of-minimum-in-colo_compare_tcp.patch
Normal file
@ -0,0 +1,35 @@
|
||||
From f6ad72a5b215bc5b2d8df86cd537bf1c0f468108 Mon Sep 17 00:00:00 2001
|
||||
From: zhangchujun <zhangchujun@cmss.chinamobile.com>
|
||||
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 <sw@weilnetz.de>
|
||||
Cc: qemu-stable@nongnu.org
|
||||
Reviewed-by: Zhang Chen <chen.zhang@intel.com>
|
||||
Signed-off-by: Jason Wang <jasowang@redhat.com>
|
||||
Signed-off-by: zhangchujun <zhangchujun_yewu@cmss.chinamobile.com>
|
||||
---
|
||||
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
|
||||
|
||||
59
acpi-ged-Add-macro-for-acpi-sleep-control-register.patch
Normal file
59
acpi-ged-Add-macro-for-acpi-sleep-control-register.patch
Normal file
@ -0,0 +1,59 @@
|
||||
From 07fa80eacaa17d3cc3865050244b79d39cc61944 Mon Sep 17 00:00:00 2001
|
||||
From: Zhang Jiao <zhangjiao2_yewu@cmss.chinamobile.com>
|
||||
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 <maobibo@loongson.cn>
|
||||
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
|
||||
Message-Id: <20240918014206.2165821-2-maobibo@loongson.cn>
|
||||
Signed-off-by: Song Gao <gaosong@loongson.cn>
|
||||
Signed-off-by: Zhang Jiao <zhangjiao2_yewu@cmss.chinamobile.com>
|
||||
---
|
||||
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
|
||||
|
||||
899
audio-pw-Report-more-accurate-error-when-connecting--new.patch
Normal file
899
audio-pw-Report-more-accurate-error-when-connecting--new.patch
Normal file
@ -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?=
|
||||
<zhangchujun@cmss.chinamobile.com>
|
||||
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 <mprivozn@redhat.com>
|
||||
Reviewed-by: Manos Pitsidianakis <manos.pitsidianakis@linaro.org>
|
||||
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
|
||||
Message-ID: <3a78811ad5b0e87816b7616ab21d2eeef00b9c52.1726647033.git.mprivozn@redhat.com>
|
||||
Signed-off-by: Zhang Chujun <zhangchujun_yewu@cmss.chinamobile.com>
|
||||
---
|
||||
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 <dbassey@redhat.com>
|
||||
- *
|
||||
- * SPDX-License-Identifier: GPL-2.0-or-later
|
||||
- */
|
||||
-
|
||||
-#include "qemu/osdep.h"
|
||||
-#include "qemu/module.h"
|
||||
-#include "audio.h"
|
||||
-#include <errno.h>
|
||||
-#include "qemu/error-report.h"
|
||||
-#include "qapi/error.h"
|
||||
-#include <spa/param/audio/format-utils.h>
|
||||
-#include <spa/utils/ringbuffer.h>
|
||||
-#include <spa/utils/result.h>
|
||||
-#include <spa/param/props.h>
|
||||
-
|
||||
-#include <pipewire/pipewire.h>
|
||||
-#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
|
||||
|
||||
931
audio-pw-Report-more-accurate-error-when-connecting-.patch
Normal file
931
audio-pw-Report-more-accurate-error-when-connecting-.patch
Normal file
@ -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?=
|
||||
<zhangchujun@cmss.chinamobile.com>
|
||||
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 <mprivozn@redhat.com>
|
||||
Reviewed-by: Manos Pitsidianakis <manos.pitsidianakis@linaro.org>
|
||||
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
|
||||
Message-ID: <3a78811ad5b0e87816b7616ab21d2eeef00b9c52.1726647033.git.mprivozn@redhat.com>
|
||||
Signed-off-by: Zhang Chujun <zhangchujun_yewu@cmss.chinamobile.com>
|
||||
---
|
||||
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 <dbassey@redhat.com>
|
||||
+ *
|
||||
+ * SPDX-License-Identifier: GPL-2.0-or-later
|
||||
+ */
|
||||
+
|
||||
+#include "qemu/osdep.h"
|
||||
+#include "qemu/module.h"
|
||||
+#include "audio.h"
|
||||
+#include <errno.h>
|
||||
+#include "qemu/error-report.h"
|
||||
+#include "qapi/error.h"
|
||||
+#include <spa/param/audio/format-utils.h>
|
||||
+#include <spa/utils/ringbuffer.h>
|
||||
+#include <spa/utils/result.h>
|
||||
+#include <spa/param/props.h>
|
||||
+
|
||||
+#include <pipewire/pipewire.h>
|
||||
+#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
|
||||
|
||||
61
block-blkio-use-FUA-flag-on-write-zeroes-only-if-sup.patch
Normal file
61
block-blkio-use-FUA-flag-on-write-zeroes-only-if-sup.patch
Normal file
@ -0,0 +1,61 @@
|
||||
From 9daf2b936101d612a295217822791d323e908fc9 Mon Sep 17 00:00:00 2001
|
||||
From: Stefano Garzarella <sgarzare@redhat.com>
|
||||
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 <sgarzare@redhat.com>
|
||||
Reviewed-by: Eric Blake <eblake@redhat.com>
|
||||
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
|
||||
Message-id: 20240808080545.40744-1-sgarzare@redhat.com
|
||||
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
|
||||
(cherry picked from commit 547c4e50929ec6c091d9c16a7b280e829b12b463)
|
||||
Signed-off-by: zhujun2 <zhujun2_yewu@cmss.chinamobile.com>
|
||||
---
|
||||
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
|
||||
|
||||
57
crypto-drop-gnutls-debug-logging-support.patch
Normal file
57
crypto-drop-gnutls-debug-logging-support.patch
Normal file
@ -0,0 +1,57 @@
|
||||
From c64bd463b120056ff1e6c32e48fa24b6afd17f23 Mon Sep 17 00:00:00 2001
|
||||
From: dinglimin <dinglimin@cmss.chinamobile.com>
|
||||
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é <philmd@linaro.org>
|
||||
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
|
||||
Signed-off-by: dinglimin <dinglimin@cmss.chinamobile.com>
|
||||
---
|
||||
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
|
||||
|
||||
168
crypto-factor-out-conversion-of-QAPI-to-gcrypt-const.patch
Normal file
168
crypto-factor-out-conversion-of-QAPI-to-gcrypt-const.patch
Normal file
@ -0,0 +1,168 @@
|
||||
From e1aaa51fc2de072871cce45dd165e2cb38515978 Mon Sep 17 00:00:00 2001
|
||||
From: dinglimin <dinglimin@cmss.chinamobile.com>
|
||||
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é <philmd@linaro.org>
|
||||
Reviewed-by: Thomas Huth <thuth@redhat.com>
|
||||
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
|
||||
Signed-off-by: dinglimin <dinglimin@cmss.chinamobile.com>
|
||||
---
|
||||
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 <gcrypt.h>
|
||||
|
||||
+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
|
||||
|
||||
78
crypto-use-consistent-error-reporting-pattern-for-un.patch
Normal file
78
crypto-use-consistent-error-reporting-pattern-for-un.patch
Normal file
@ -0,0 +1,78 @@
|
||||
From 7bd04536327357a97206d8048f5d9341780bbe5a Mon Sep 17 00:00:00 2001
|
||||
From: dinglimin <dinglimin@cmss.chinamobile.com>
|
||||
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 <peter.maydell@linaro.org>
|
||||
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
|
||||
Signed-off-by: dinglimin <dinglimin@cmss.chinamobile.com>
|
||||
---
|
||||
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
|
||||
|
||||
61
dma-Fix-function-names-in-documentation.patch
Normal file
61
dma-Fix-function-names-in-documentation.patch
Normal file
@ -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?=
|
||||
<zhangchujun@cmss.chinamobile.com>
|
||||
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 <akihiko.odaki@daynix.com>
|
||||
Message-id: 20241012-dma-v2-1-6afddf5f3c8d@daynix.com
|
||||
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
|
||||
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
|
||||
Signed-off-by: Zhang Chujun <zhangchujun@cmss.chinamoile.com>
|
||||
---
|
||||
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
|
||||
|
||||
52
docs-sphinx-depfile.py-Handle-env.doc2path-returning.patch
Normal file
52
docs-sphinx-depfile.py-Handle-env.doc2path-returning.patch
Normal file
@ -0,0 +1,52 @@
|
||||
From e16c3aa63a203e376a40404314252a11e85a5bda Mon Sep 17 00:00:00 2001
|
||||
From: Peter Maydell <peter.maydell@linaro.org>
|
||||
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 <function write_depfile at 0x77a1775ff560> 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 <peter.maydell@linaro.org>
|
||||
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
|
||||
Message-ID: <20240729120533.2486427-1-peter.maydell@linaro.org>
|
||||
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
|
||||
(cherry picked from commit 48e5b5f994bccf161dd88a67fdd819d4bfb400f1)
|
||||
Signed-off-by: zhujun2 <zhujun2_yewu@cmss.chinamobile.com>
|
||||
---
|
||||
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
|
||||
|
||||
31
docs-tools-qemu-img.rst-fix-typo-sumarizes.patch
Normal file
31
docs-tools-qemu-img.rst-fix-typo-sumarizes.patch
Normal file
@ -0,0 +1,31 @@
|
||||
From ac7182ca1b9ed7dbb524da734a9f426b2ca07503 Mon Sep 17 00:00:00 2001
|
||||
From: Zhang Jiao <zhangjiao2_yewu@cmss.chinamobile.com>
|
||||
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 <sam@rfc1149.net>
|
||||
Reviewed-by: Zhao Liu <zhao1.liu@intel.com>
|
||||
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
|
||||
Signed-off-by: Zhang Jiao <zhangjiao2_yewu@cmss.chinamobile.com>
|
||||
---
|
||||
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
|
||||
|
||||
47
edu-fix-DMA-range-upper-bound-check.patch
Normal file
47
edu-fix-DMA-range-upper-bound-check.patch
Normal file
@ -0,0 +1,47 @@
|
||||
From edf3b2b0a9b9aa992592951a979d1b4642026fe5 Mon Sep 17 00:00:00 2001
|
||||
From: Zhang Jiao <zhangjiao2_yewu@cmss.chinamobile.com>
|
||||
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 <merenber@uwaterloo.ca>
|
||||
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
|
||||
Signed-off-by: Zhang Jiao <zhangjiao2_yewu@cmss.chinamobile.com>
|
||||
---
|
||||
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
|
||||
|
||||
37
hw-cxl-Ensure-there-is-enough-data-to-read-the-input.patch
Normal file
37
hw-cxl-Ensure-there-is-enough-data-to-read-the-input.patch
Normal file
@ -0,0 +1,37 @@
|
||||
From d96c34e132df55ca7be458095f23d81dfc14e0d5 Mon Sep 17 00:00:00 2001
|
||||
From: Jonathan Cameron <Jonathan.Cameron@huawei.com>
|
||||
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 <esifiel@gmail.com>
|
||||
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
|
||||
Message-Id: <20241101133917.27634-11-Jonathan.Cameron@huawei.com>
|
||||
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
|
||||
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
|
||||
Signed-off-by: Zhongrui Tang <tangzhongrui_yewu@cmss.chinamobile.com>
|
||||
---
|
||||
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
|
||||
|
||||
36
hw-gpio-aspeed_gpio-Avoid-shift-into-sign-bit.patch
Normal file
36
hw-gpio-aspeed_gpio-Avoid-shift-into-sign-bit.patch
Normal file
@ -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?=
|
||||
<zhangchujun@cmss.chinamobile.com>
|
||||
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 <peter.maydell@linaro.org>
|
||||
Reviewed-by: Cedric Le Goater <clg@redhat.com>
|
||||
Signed-off-by: zhangchujun <zhangchujun@cmss.chinamobile.com>
|
||||
---
|
||||
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
|
||||
|
||||
51
hw-intc-openpic-Improve-errors-for-out-of-bounds-pro.patch
Normal file
51
hw-intc-openpic-Improve-errors-for-out-of-bounds-pro.patch
Normal file
@ -0,0 +1,51 @@
|
||||
From 15b6c032ed2f92aa3210fe30376119eb468af039 Mon Sep 17 00:00:00 2001
|
||||
From: Zhang Jiao <zhangjiao2_yewu@cmss.chinamobile.com>
|
||||
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 <armbru@redhat.com>
|
||||
Message-ID: <20241010150144.986655-7-armbru@redhat.com>
|
||||
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
|
||||
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
|
||||
Signed-off-by: Zhang Jiao <zhangjiao2_yewu@cmss.chinamobile.com>
|
||||
---
|
||||
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
|
||||
|
||||
33
hw-loongarch-virt-Remove-unnecessary-cpu.h-inclusion.patch
Normal file
33
hw-loongarch-virt-Remove-unnecessary-cpu.h-inclusion.patch
Normal file
@ -0,0 +1,33 @@
|
||||
From cbd62b91ecdd0ec5f4ccb4c726e0adcdd2808270 Mon Sep 17 00:00:00 2001
|
||||
From: Susanooo <zhangchujun_yewu@cmss.chinamobile.com>
|
||||
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é <philmd@linaro.org>
|
||||
Reviewed-by: Song Gao <gaosong@loongson.cn>
|
||||
Reviewed-by: Thomas Huth <thuth@redhat.com>
|
||||
Message-Id: <20240927213254.17552-2-philmd@linaro.org>
|
||||
Signed-off-by: Song Gao <gaosong@loongson.cn>
|
||||
Signed-off-by: zhangchujun <zhangchujun_yewu@cmss.chinamobile.com>
|
||||
---
|
||||
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
|
||||
|
||||
43
hw-net-can-sja1000-fix-bug-for-single-acceptance-fil.patch
Normal file
43
hw-net-can-sja1000-fix-bug-for-single-acceptance-fil.patch
Normal file
@ -0,0 +1,43 @@
|
||||
From 0b89dd1ae05d17f0bacbd34218799f00d04c8174 Mon Sep 17 00:00:00 2001
|
||||
From: Zhang Jiao <zhangjiao2_yewu@cmss.chinamobile.com>
|
||||
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 <pisa@cmp.felk.cvut.cz>
|
||||
Reported-by: Grant Ramsay <gramsay@enphaseenergy.com>
|
||||
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 <zhangjiao2_yewu@cmss.chinamobile.com>
|
||||
---
|
||||
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
|
||||
|
||||
50
hw-pci-bridge-Add-a-Kconfig-switch-for-the-normal-PC.patch
Normal file
50
hw-pci-bridge-Add-a-Kconfig-switch-for-the-normal-PC.patch
Normal file
@ -0,0 +1,50 @@
|
||||
From 55ea1e473095ea5be692bb4ba2e44131a4a88e73 Mon Sep 17 00:00:00 2001
|
||||
From: Zhang Jiao <zhangjiao2_yewu@cmss.chinamobile.com>
|
||||
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é <philmd@linaro.org>
|
||||
Reviewed-by: Cédric Le Goater <clg@redhat.com>
|
||||
Signed-off-by: Thomas Huth <thuth@redhat.com>
|
||||
Signed-off-by: Zhang Jiao <zhangjiao2_yewu@cmss.chinamobile.com>
|
||||
---
|
||||
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
|
||||
|
||||
39
intel_iommu-Send-IQE-event-when-setting-reserved-bit.patch
Normal file
39
intel_iommu-Send-IQE-event-when-setting-reserved-bit.patch
Normal file
@ -0,0 +1,39 @@
|
||||
From 66eb68e54a521bc0dac015415a9eca25fe479543 Mon Sep 17 00:00:00 2001
|
||||
From: Zhenzhong Duan <zhenzhong.duan@intel.com>
|
||||
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 <yi.l.liu@intel.com>
|
||||
Signed-off-by: Zhenzhong Duan <zhenzhong.duan@intel.com>
|
||||
Message-Id: <20241104125536.1236118-2-zhenzhong.duan@intel.com>
|
||||
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
|
||||
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
|
||||
Signed-off-by: Zhongrui Tang <tangzhongrui_yewu@cmss.chinamobile.com>
|
||||
---
|
||||
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
|
||||
|
||||
35
linux-user-Clean-up-unused-header.patch
Normal file
35
linux-user-Clean-up-unused-header.patch
Normal file
@ -0,0 +1,35 @@
|
||||
From 34af051406f75bdef6f2ef598cde51e756ea8489 Mon Sep 17 00:00:00 2001
|
||||
From: Susanooo <zhangchujun_yewu@cmss.chinamobile.com>
|
||||
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 <gustavo.romero@linaro.org>
|
||||
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
|
||||
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
|
||||
Reviewed-by: Michael Tokarev <mjt@tls.msk.ru>
|
||||
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
|
||||
Signed-off-by: zhangchujun <zhangchujun_yewu@cmss.chinamobile.com>
|
||||
---
|
||||
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 <utime.h>
|
||||
#include <sys/sysinfo.h>
|
||||
#include <sys/signalfd.h>
|
||||
-//#include <sys/user.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/tcp.h>
|
||||
--
|
||||
2.41.0.windows.1
|
||||
|
||||
45
module-Prevent-crash-by-resetting-local_err-in-modul.patch
Normal file
45
module-Prevent-crash-by-resetting-local_err-in-modul.patch
Normal file
@ -0,0 +1,45 @@
|
||||
From 7187ed9e2010adfe937d6444eb79d8025c118c2c Mon Sep 17 00:00:00 2001
|
||||
From: Alexander Ivanov <alexander.ivanov@virtuozzo.com>
|
||||
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 <alexander.ivanov@virtuozzo.com>
|
||||
Reviewed-by: Claudio Fontana <cfontana@suse.de>
|
||||
Reviewed-by: Denis V. Lunev <den@openvz.org>
|
||||
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 <pbonzini@redhat.com>
|
||||
(cherry picked from commit 940d802b24e63650e0eacad3714e2ce171cba17c)
|
||||
Signed-off-by: zhujun2 <zhujun2_yewu@cmss.chinamobile.com>
|
||||
---
|
||||
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
|
||||
|
||||
42
platform-bus-fix-refcount-leak.patch
Normal file
42
platform-bus-fix-refcount-leak.patch
Normal file
@ -0,0 +1,42 @@
|
||||
From 0b23e1ad9e27fa60525b3d014da0425d2c24885f Mon Sep 17 00:00:00 2001
|
||||
From: Zhang Jiao <zhangjiao2_yewu@cmss.chinamobile.com>
|
||||
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 <zhangjiao2_yewu@cmss.chinamobile.com>
|
||||
---
|
||||
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
|
||||
|
||||
69
ppc-xive-Fix-ESB-length-overflow-on-32-bit-hosts.patch
Normal file
69
ppc-xive-Fix-ESB-length-overflow-on-32-bit-hosts.patch
Normal file
@ -0,0 +1,69 @@
|
||||
From c73b18ef8f2dd15934d90f65ba825bef19d11f73 Mon Sep 17 00:00:00 2001
|
||||
From: qihao_yewu <qihao_yewu@cmss.chinamobile.com>
|
||||
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 <npiggin@gmail.com>
|
||||
Signed-off-by: qihao_yewu <qihao_yewu@cmss.chinamobile.com>
|
||||
---
|
||||
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
|
||||
|
||||
76
qemu.spec
76
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 <fengjiabo1@huawei.com> - 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 <eric.fangyi@huawei.com> - 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
|
||||
|
||||
48
raw-format-Fix-error-message-for-invalid-offset-size.patch
Normal file
48
raw-format-Fix-error-message-for-invalid-offset-size.patch
Normal file
@ -0,0 +1,48 @@
|
||||
From 16fb3ec642af7ec7980b7ceff1b25abee3fecee2 Mon Sep 17 00:00:00 2001
|
||||
From: Susanooo <zhangchujun_yewu@cmss.chinamobile.com>
|
||||
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 <kwolf@redhat.com>
|
||||
Message-ID: <20240829185527.47152-1-kwolf@redhat.com>
|
||||
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
|
||||
Reviewed-by: Hanna Czenczek <hreitz@redhat.com>
|
||||
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
||||
Signed-off-by: zhangchujun <zhangchujun_yewu@cmss.chinamobile.com>
|
||||
---
|
||||
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
|
||||
|
||||
34
target-arm-Clear-high-SVE-elements-in-handle_vec_sim.patch
Normal file
34
target-arm-Clear-high-SVE-elements-in-handle_vec_sim.patch
Normal file
@ -0,0 +1,34 @@
|
||||
From 87ff72f354301147e35009dabdb8be68e9dfa30c Mon Sep 17 00:00:00 2001
|
||||
From: Richard Henderson <richard.henderson@linaro.org>
|
||||
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 <richard.henderson@linaro.org>
|
||||
Message-id: 20240717060903.205098-15-richard.henderson@linaro.org
|
||||
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
|
||||
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
|
||||
(cherry picked from commit 8e0c9a9efa21a16190cbac288e414bbf1d80f639)
|
||||
Signed-off-by: zhujun2 <zhujun2_yewu@cmss.chinamobile.com>
|
||||
---
|
||||
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
|
||||
|
||||
73
target-arm-Fix-SVE-SDOT-UDOT-USDOT-4-way-indexed.patch
Normal file
73
target-arm-Fix-SVE-SDOT-UDOT-USDOT-4-way-indexed.patch
Normal file
@ -0,0 +1,73 @@
|
||||
From 95f371c36858dd003c0c6a3d4f6ddfbc299dda9f Mon Sep 17 00:00:00 2001
|
||||
From: qihao_yewu <qihao_yewu@cmss.chinamobile.com>
|
||||
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 <peter.maydell@linaro.org>
|
||||
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
|
||||
Message-id: 20241101185544.2130972-1-peter.maydell@linaro.org
|
||||
Signed-off-by: qihao_yewu <qihao_yewu@cmss.chinamobile.com>
|
||||
---
|
||||
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
|
||||
|
||||
58
target-hppa-Fix-PSW-V-bit-packaging-in-cpu_hppa_get-.patch
Normal file
58
target-hppa-Fix-PSW-V-bit-packaging-in-cpu_hppa_get-.patch
Normal file
@ -0,0 +1,58 @@
|
||||
From b1a14fd9b59803a17626903c5fb54f1aa2655d00 Mon Sep 17 00:00:00 2001
|
||||
From: Helge Deller <deller@gmx.de>
|
||||
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 <linux@roeck-us.net>
|
||||
Signed-off-by: Helge Deller <deller@gmx.de>
|
||||
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
|
||||
Tested-by: Guenter Roeck <linux@roeck-us.net>
|
||||
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 <zhujun2_yewu@cmss.chinamobile.com>
|
||||
---
|
||||
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
|
||||
|
||||
55
target-ppc-Fix-migration-of-CPUs-with-TLB_EMB-TLB-ty.patch
Normal file
55
target-ppc-Fix-migration-of-CPUs-with-TLB_EMB-TLB-ty.patch
Normal file
@ -0,0 +1,55 @@
|
||||
From fa282d002c45e1cc1cca6a2541b75ab5889c8c01 Mon Sep 17 00:00:00 2001
|
||||
From: Arman Nabiev <nabiev.arman13@gmail.com>
|
||||
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 <peter.maydell@linaro.org>
|
||||
Signed-off-by: Arman Nabiev <nabiev.arman13@gmail.com>
|
||||
Signed-off-by: Fabiano Rosas <farosas@suse.de>
|
||||
(cherry picked from commit 203beb6f047467a4abfc8267c234393cea3f471c)
|
||||
Signed-off-by: zhujun2 <zhujun2_yewu@cmss.chinamobile.com>
|
||||
---
|
||||
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
|
||||
|
||||
52
target-riscv-csr.c-Fix-an-access-to-VXSAT.patch
Normal file
52
target-riscv-csr.c-Fix-an-access-to-VXSAT.patch
Normal file
@ -0,0 +1,52 @@
|
||||
From 6b1b8553ea3810e497d225d64e98dd6eac7b4e2c Mon Sep 17 00:00:00 2001
|
||||
From: qihao_yewu <qihao_yewu@cmss.chinamobile.com>
|
||||
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 <evgenii.prokopiev@syntacore.com>
|
||||
Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
|
||||
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
|
||||
Message-ID: <20241002084436.89347-1-evgenii.prokopiev@syntacore.com>
|
||||
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
|
||||
Signed-off-by: qihao_yewu <qihao_yewu@cmss.chinamobile.com>
|
||||
---
|
||||
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
|
||||
|
||||
44
tests-Wait-for-migration-completion-on-destination-Q.patch
Normal file
44
tests-Wait-for-migration-completion-on-destination-Q.patch
Normal file
@ -0,0 +1,44 @@
|
||||
From c4d618ea0dc507084d9c1e2b61e58691a73c2cf4 Mon Sep 17 00:00:00 2001
|
||||
From: Susanooo <zhangchujun_yewu@cmss.chinamobile.com>
|
||||
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: <qemu-stable@nongnu.org>
|
||||
Reported-by: Fabiano Rosas <farosas@suse.de>
|
||||
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
|
||||
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
|
||||
Signed-off-by: zhangchujun <zhangchujun_yewu@cmss.chinamobile.com>
|
||||
---
|
||||
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
|
||||
|
||||
36
tests-avocado-fix-typo-in-replay_linux.patch
Normal file
36
tests-avocado-fix-typo-in-replay_linux.patch
Normal file
@ -0,0 +1,36 @@
|
||||
From 0f62625a0f8b6244203fbd2838b8e9c29efc2eea Mon Sep 17 00:00:00 2001
|
||||
From: Zhang Jiao <zhangjiao2_yewu@cmss.chinamobile.com>
|
||||
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 <Pavel.Dovgalyuk@ispras.ru>
|
||||
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
|
||||
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
|
||||
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
|
||||
Message-Id: <20231211091346.14616-3-alex.bennee@linaro.org>
|
||||
Signed-off-by: Zhang Jiao <zhangjiao2_yewu@cmss.chinamobile.com>
|
||||
---
|
||||
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
|
||||
|
||||
154
tests-docker-update-debian-i686-and-mipsel-images-to.patch
Normal file
154
tests-docker-update-debian-i686-and-mipsel-images-to.patch
Normal file
@ -0,0 +1,154 @@
|
||||
From ea21c12b545ad6eecded5f34472d3f226f5a2e15 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Alex=20Benn=C3=A9e?= <alex.bennee@linaro.org>
|
||||
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 <pierrick.bouvier@linaro.org>
|
||||
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
|
||||
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
|
||||
Message-Id: <20240910173900.4154726-3-alex.bennee@linaro.org>
|
||||
(cherry picked from commit 19d2111059c87d3f58349f27b9be9dee81fc1681)
|
||||
Signed-off-by: zhujun2 <zhujun2_yewu@cmss.chinamobile.com>
|
||||
---
|
||||
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
|
||||
|
||||
71
util-userfaultfd-Remove-unused-uffd_poll_events.patch
Normal file
71
util-userfaultfd-Remove-unused-uffd_poll_events.patch
Normal file
@ -0,0 +1,71 @@
|
||||
From ef3d2918827d6c5204af06e1597dc4dbde22414a Mon Sep 17 00:00:00 2001
|
||||
From: Zhang Jiao <zhangjiao2_yewu@cmss.chinamobile.com>
|
||||
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 <dave@treblig.org>
|
||||
Reviewed-by: Peter Xu <peterx@redhat.com>
|
||||
Link: https://lore.kernel.org/r/20240919134626.166183-8-dave@treblig.org
|
||||
Signed-off-by: Peter Xu <peterx@redhat.com>
|
||||
Signed-off-by: Zhang Jiao <zhangjiao2_yewu@cmss.chinamobile.com>
|
||||
---
|
||||
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
|
||||
|
||||
48
virtio-net-Avoid-indirection_table_mask-overflow.patch
Normal file
48
virtio-net-Avoid-indirection_table_mask-overflow.patch
Normal file
@ -0,0 +1,48 @@
|
||||
From cc875acdbf0ab210ce467f27c621fe7dc2159110 Mon Sep 17 00:00:00 2001
|
||||
From: zhangchujun <zhangchujun@cmss.chinamobile.com>
|
||||
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 <akihiko.odaki@daynix.com>
|
||||
Signed-off-by: Jason Wang <jasowang@redhat.com>
|
||||
Signed-off-by: zhangchujun <zhangchujun_yewu@cmss.chinamobile.com>
|
||||
---
|
||||
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
|
||||
|
||||
80
virtio-pci-Fix-the-use-of-an-uninitialized-irqfd.patch
Normal file
80
virtio-pci-Fix-the-use-of-an-uninitialized-irqfd.patch
Normal file
@ -0,0 +1,80 @@
|
||||
From 9cd544b83ccd37b9dd7977717a245437533830cd Mon Sep 17 00:00:00 2001
|
||||
From: Cindy Lu <lulu@redhat.com>
|
||||
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 <lulu@redhat.com>
|
||||
Message-Id: <20240806093715.65105-1-lulu@redhat.com>
|
||||
Acked-by: Jason Wang <jasowang@redhat.com>
|
||||
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
|
||||
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
|
||||
(cherry picked from commit a8e63ff289d137197ad7a701a587cc432872d798)
|
||||
Signed-off-by: zhujun2 <zhujun2_yewu@cmss.chinamobile.com>
|
||||
---
|
||||
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
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user