!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:
openeuler-ci-bot 2024-11-30 03:06:25 +00:00 committed by Gitee
commit d66a1d2fae
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
37 changed files with 4074 additions and 1 deletions

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View File

@ -3,7 +3,7 @@
Name: qemu Name: qemu
Version: 8.2.0 Version: 8.2.0
Release: 23 Release: 24
Epoch: 11 Epoch: 11
Summary: QEMU is a generic and open source machine emulator and virtualizer Summary: QEMU is a generic and open source machine emulator and virtualizer
License: GPLv2 and BSD and MIT and CC-BY-SA-4.0 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 Patch0373: Revert-vdpa-add-vhost_vdpa-suspended-parameter.patch
Patch0374: Revert-vdpa-block-migration-if-SVQ-does-not-admit-a-.patch Patch0374: Revert-vdpa-block-migration-if-SVQ-does-not-admit-a-.patch
Patch0375: vdpa-remove-memory-listener-unregister-in-vhost_vdpa.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: flex
BuildRequires: gcc BuildRequires: gcc
@ -986,6 +1022,44 @@ getent passwd qemu >/dev/null || \
%endif %endif
%changelog %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 * 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: fix vdpa device migrate rollback wrong when suspend device failed.
- vdpa: support resizing virtio-blk capacity online for kernel vdpa - vdpa: support resizing virtio-blk capacity online for kernel vdpa

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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