From da38d5c28e20aa584793bf57606c8231adc96d60 Mon Sep 17 00:00:00 2001 From: Camilla Conte Date: Tue, 5 Jul 2022 10:49:23 +0000 Subject: [PATCH] * Tue Jul 05 2022 Camilla Conte - 7.0.0-8 - kvm-tests-avocado-update-aarch64_virt-test-to-exercise-c.patch [bz#2060839] - kvm-RHEL-only-tests-avocado-Switch-aarch64-tests-from-a5.patch [bz#2060839] - kvm-RHEL-only-AArch64-Drop-unsupported-CPU-types.patch [bz#2060839] - kvm-target-i386-deprecate-CPUs-older-than-x86_64-v2-ABI.patch [bz#2060839] - kvm-target-s390x-deprecate-CPUs-older-than-z14.patch [bz#2060839] - kvm-target-arm-deprecate-named-CPU-models.patch [bz#2060839] - kvm-meson.build-Fix-docker-test-build-alpine-when-includ.patch [bz#1968509] - kvm-QIOChannel-Add-flags-on-io_writev-and-introduce-io_f.patch [bz#1968509] - kvm-QIOChannelSocket-Implement-io_writev-zero-copy-flag-.patch [bz#1968509] - kvm-migration-Add-zero-copy-send-parameter-for-QMP-HMP-f.patch [bz#1968509] - kvm-migration-Add-migrate_use_tls-helper.patch [bz#1968509] - kvm-multifd-multifd_send_sync_main-now-returns-negative-.patch [bz#1968509] - kvm-multifd-Send-header-packet-without-flags-if-zero-cop.patch [bz#1968509] - kvm-multifd-Implement-zero-copy-write-in-multifd-migrati.patch [bz#1968509] - kvm-QIOChannelSocket-Introduce-assert-and-reduce-ifdefs-.patch [bz#1968509] - kvm-QIOChannelSocket-Fix-zero-copy-send-so-socket-flush-.patch [bz#1968509] - kvm-migration-Change-zero_copy_send-from-migration-param.patch [bz#1968509] - kvm-migration-Allow-migrate-recover-to-run-multiple-time.patch [bz#2096143] - Resolves: bz#2060839 (Consider deprecating CPU models like "kvm64" / "qemu64" on RHEL 9) - Resolves: bz#1968509 (Use MSG_ZEROCOPY on QEMU Live Migration) - Resolves: bz#2096143 (The migration port is not released if use it again for recovering postcopy migration) --- ...lags-on-io_writev-and-introduce-io_f.patch | 420 ++++++++++++++++++ ...-Fix-zero-copy-send-so-socket-flush-.patch | 58 +++ ...-Implement-io_writev-zero-copy-flag-.patch | 249 +++++++++++ ...-Introduce-assert-and-reduce-ifdefs-.patch | 82 ++++ ...y-AArch64-Drop-unsupported-CPU-types.patch | 237 ++++++++++ ...avocado-Switch-aarch64-tests-from-a5.patch | 95 ++++ ...docker-test-build-alpine-when-includ.patch | 87 ++++ ...migration-Add-migrate_use_tls-helper.patch | 106 +++++ ...ro-copy-send-parameter-for-QMP-HMP-f.patch | 250 +++++++++++ ...migrate-recover-to-run-multiple-time.patch | 98 ++++ ...-zero_copy_send-from-migration-param.patch | 289 ++++++++++++ ...t-zero-copy-write-in-multifd-migrati.patch | 182 ++++++++ ...der-packet-without-flags-if-zero-cop.patch | 102 +++++ ...send_sync_main-now-returns-negative-.patch | 163 +++++++ ...arget-arm-deprecate-named-CPU-models.patch | 129 ++++++ ...recate-CPUs-older-than-x86_64-v2-ABI.patch | 273 ++++++++++++ ...-s390x-deprecate-CPUs-older-than-z14.patch | 194 ++++++++ ...date-aarch64_virt-test-to-exercise-c.patch | 157 +++++++ qemu-kvm.spec | 64 ++- 19 files changed, 3234 insertions(+), 1 deletion(-) create mode 100644 kvm-QIOChannel-Add-flags-on-io_writev-and-introduce-io_f.patch create mode 100644 kvm-QIOChannelSocket-Fix-zero-copy-send-so-socket-flush-.patch create mode 100644 kvm-QIOChannelSocket-Implement-io_writev-zero-copy-flag-.patch create mode 100644 kvm-QIOChannelSocket-Introduce-assert-and-reduce-ifdefs-.patch create mode 100644 kvm-RHEL-only-AArch64-Drop-unsupported-CPU-types.patch create mode 100644 kvm-RHEL-only-tests-avocado-Switch-aarch64-tests-from-a5.patch create mode 100644 kvm-meson.build-Fix-docker-test-build-alpine-when-includ.patch create mode 100644 kvm-migration-Add-migrate_use_tls-helper.patch create mode 100644 kvm-migration-Add-zero-copy-send-parameter-for-QMP-HMP-f.patch create mode 100644 kvm-migration-Allow-migrate-recover-to-run-multiple-time.patch create mode 100644 kvm-migration-Change-zero_copy_send-from-migration-param.patch create mode 100644 kvm-multifd-Implement-zero-copy-write-in-multifd-migrati.patch create mode 100644 kvm-multifd-Send-header-packet-without-flags-if-zero-cop.patch create mode 100644 kvm-multifd-multifd_send_sync_main-now-returns-negative-.patch create mode 100644 kvm-target-arm-deprecate-named-CPU-models.patch create mode 100644 kvm-target-i386-deprecate-CPUs-older-than-x86_64-v2-ABI.patch create mode 100644 kvm-target-s390x-deprecate-CPUs-older-than-z14.patch create mode 100644 kvm-tests-avocado-update-aarch64_virt-test-to-exercise-c.patch diff --git a/kvm-QIOChannel-Add-flags-on-io_writev-and-introduce-io_f.patch b/kvm-QIOChannel-Add-flags-on-io_writev-and-introduce-io_f.patch new file mode 100644 index 0000000..c7b8898 --- /dev/null +++ b/kvm-QIOChannel-Add-flags-on-io_writev-and-introduce-io_f.patch @@ -0,0 +1,420 @@ +From cda3fcf14f2883fea633e25256f6c14a71271adf Mon Sep 17 00:00:00 2001 +From: Leonardo Bras +Date: Fri, 13 May 2022 03:28:31 -0300 +Subject: [PATCH 08/18] QIOChannel: Add flags on io_writev and introduce + io_flush callback +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Leonardo Brás +RH-MergeRequest: 95: MSG_ZEROCOPY + Multifd +RH-Commit: [2/11] 06acfb6b0cb2c25733c2eb198011f7623b5a7024 (LeoBras/centos-qemu-kvm) +RH-Bugzilla: 1968509 +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: Dr. David Alan Gilbert +RH-Acked-by: Peter Xu + +Add flags to io_writev and introduce io_flush as optional callback to +QIOChannelClass, allowing the implementation of zero copy writes by +subclasses. + +How to use them: +- Write data using qio_channel_writev*(...,QIO_CHANNEL_WRITE_FLAG_ZERO_COPY), +- Wait write completion with qio_channel_flush(). + +Notes: +As some zero copy write implementations work asynchronously, it's +recommended to keep the write buffer untouched until the return of +qio_channel_flush(), to avoid the risk of sending an updated buffer +instead of the buffer state during write. + +As io_flush callback is optional, if a subclass does not implement it, then: +- io_flush will return 0 without changing anything. + +Also, some functions like qio_channel_writev_full_all() were adapted to +receive a flag parameter. That allows shared code between zero copy and +non-zero copy writev, and also an easier implementation on new flags. + +Signed-off-by: Leonardo Bras +Reviewed-by: Daniel P. Berrangé +Reviewed-by: Peter Xu +Reviewed-by: Juan Quintela +Message-Id: <20220513062836.965425-3-leobras@redhat.com> +Signed-off-by: Dr. David Alan Gilbert +(cherry picked from commit b88651cb4d4fa416fdbb6afaf5b26ec8c035eaad) +Signed-off-by: Leonardo Bras +--- + chardev/char-io.c | 2 +- + hw/remote/mpqemu-link.c | 2 +- + include/io/channel.h | 38 +++++++++++++++++++++- + io/channel-buffer.c | 1 + + io/channel-command.c | 1 + + io/channel-file.c | 1 + + io/channel-socket.c | 2 ++ + io/channel-tls.c | 1 + + io/channel-websock.c | 1 + + io/channel.c | 49 +++++++++++++++++++++++------ + migration/rdma.c | 1 + + scsi/pr-manager-helper.c | 2 +- + tests/unit/test-io-channel-socket.c | 1 + + 13 files changed, 88 insertions(+), 14 deletions(-) + +diff --git a/chardev/char-io.c b/chardev/char-io.c +index 8ced184160..4451128cba 100644 +--- a/chardev/char-io.c ++++ b/chardev/char-io.c +@@ -122,7 +122,7 @@ int io_channel_send_full(QIOChannel *ioc, + + ret = qio_channel_writev_full( + ioc, &iov, 1, +- fds, nfds, NULL); ++ fds, nfds, 0, NULL); + if (ret == QIO_CHANNEL_ERR_BLOCK) { + if (offset) { + return offset; +diff --git a/hw/remote/mpqemu-link.c b/hw/remote/mpqemu-link.c +index 7e841820e5..e8f556bd27 100644 +--- a/hw/remote/mpqemu-link.c ++++ b/hw/remote/mpqemu-link.c +@@ -69,7 +69,7 @@ bool mpqemu_msg_send(MPQemuMsg *msg, QIOChannel *ioc, Error **errp) + } + + if (!qio_channel_writev_full_all(ioc, send, G_N_ELEMENTS(send), +- fds, nfds, errp)) { ++ fds, nfds, 0, errp)) { + ret = true; + } else { + trace_mpqemu_send_io_error(msg->cmd, msg->size, nfds); +diff --git a/include/io/channel.h b/include/io/channel.h +index 88988979f8..c680ee7480 100644 +--- a/include/io/channel.h ++++ b/include/io/channel.h +@@ -32,12 +32,15 @@ OBJECT_DECLARE_TYPE(QIOChannel, QIOChannelClass, + + #define QIO_CHANNEL_ERR_BLOCK -2 + ++#define QIO_CHANNEL_WRITE_FLAG_ZERO_COPY 0x1 ++ + typedef enum QIOChannelFeature QIOChannelFeature; + + enum QIOChannelFeature { + QIO_CHANNEL_FEATURE_FD_PASS, + QIO_CHANNEL_FEATURE_SHUTDOWN, + QIO_CHANNEL_FEATURE_LISTEN, ++ QIO_CHANNEL_FEATURE_WRITE_ZERO_COPY, + }; + + +@@ -104,6 +107,7 @@ struct QIOChannelClass { + size_t niov, + int *fds, + size_t nfds, ++ int flags, + Error **errp); + ssize_t (*io_readv)(QIOChannel *ioc, + const struct iovec *iov, +@@ -136,6 +140,8 @@ struct QIOChannelClass { + IOHandler *io_read, + IOHandler *io_write, + void *opaque); ++ int (*io_flush)(QIOChannel *ioc, ++ Error **errp); + }; + + /* General I/O handling functions */ +@@ -228,6 +234,7 @@ ssize_t qio_channel_readv_full(QIOChannel *ioc, + * @niov: the length of the @iov array + * @fds: an array of file handles to send + * @nfds: number of file handles in @fds ++ * @flags: write flags (QIO_CHANNEL_WRITE_FLAG_*) + * @errp: pointer to a NULL-initialized error object + * + * Write data to the IO channel, reading it from the +@@ -260,6 +267,7 @@ ssize_t qio_channel_writev_full(QIOChannel *ioc, + size_t niov, + int *fds, + size_t nfds, ++ int flags, + Error **errp); + + /** +@@ -837,6 +845,7 @@ int qio_channel_readv_full_all(QIOChannel *ioc, + * @niov: the length of the @iov array + * @fds: an array of file handles to send + * @nfds: number of file handles in @fds ++ * @flags: write flags (QIO_CHANNEL_WRITE_FLAG_*) + * @errp: pointer to a NULL-initialized error object + * + * +@@ -846,6 +855,14 @@ int qio_channel_readv_full_all(QIOChannel *ioc, + * to be written, yielding from the current coroutine + * if required. + * ++ * If QIO_CHANNEL_WRITE_FLAG_ZERO_COPY is passed in flags, ++ * instead of waiting for all requested data to be written, ++ * this function will wait until it's all queued for writing. ++ * In this case, if the buffer gets changed between queueing and ++ * sending, the updated buffer will be sent. If this is not a ++ * desired behavior, it's suggested to call qio_channel_flush() ++ * before reusing the buffer. ++ * + * Returns: 0 if all bytes were written, or -1 on error + */ + +@@ -853,6 +870,25 @@ int qio_channel_writev_full_all(QIOChannel *ioc, + const struct iovec *iov, + size_t niov, + int *fds, size_t nfds, +- Error **errp); ++ int flags, Error **errp); ++ ++/** ++ * qio_channel_flush: ++ * @ioc: the channel object ++ * @errp: pointer to a NULL-initialized error object ++ * ++ * Will block until every packet queued with ++ * qio_channel_writev_full() + QIO_CHANNEL_WRITE_FLAG_ZERO_COPY ++ * is sent, or return in case of any error. ++ * ++ * If not implemented, acts as a no-op, and returns 0. ++ * ++ * Returns -1 if any error is found, ++ * 1 if every send failed to use zero copy. ++ * 0 otherwise. ++ */ ++ ++int qio_channel_flush(QIOChannel *ioc, ++ Error **errp); + + #endif /* QIO_CHANNEL_H */ +diff --git a/io/channel-buffer.c b/io/channel-buffer.c +index baa4e2b089..bf52011be2 100644 +--- a/io/channel-buffer.c ++++ b/io/channel-buffer.c +@@ -81,6 +81,7 @@ static ssize_t qio_channel_buffer_writev(QIOChannel *ioc, + size_t niov, + int *fds, + size_t nfds, ++ int flags, + Error **errp) + { + QIOChannelBuffer *bioc = QIO_CHANNEL_BUFFER(ioc); +diff --git a/io/channel-command.c b/io/channel-command.c +index 338da73ade..54560464ae 100644 +--- a/io/channel-command.c ++++ b/io/channel-command.c +@@ -258,6 +258,7 @@ static ssize_t qio_channel_command_writev(QIOChannel *ioc, + size_t niov, + int *fds, + size_t nfds, ++ int flags, + Error **errp) + { + QIOChannelCommand *cioc = QIO_CHANNEL_COMMAND(ioc); +diff --git a/io/channel-file.c b/io/channel-file.c +index d7cf6d278f..ef6807a6be 100644 +--- a/io/channel-file.c ++++ b/io/channel-file.c +@@ -114,6 +114,7 @@ static ssize_t qio_channel_file_writev(QIOChannel *ioc, + size_t niov, + int *fds, + size_t nfds, ++ int flags, + Error **errp) + { + QIOChannelFile *fioc = QIO_CHANNEL_FILE(ioc); +diff --git a/io/channel-socket.c b/io/channel-socket.c +index 7a8d9f69c9..a1be2197ca 100644 +--- a/io/channel-socket.c ++++ b/io/channel-socket.c +@@ -525,6 +525,7 @@ static ssize_t qio_channel_socket_writev(QIOChannel *ioc, + size_t niov, + int *fds, + size_t nfds, ++ int flags, + Error **errp) + { + QIOChannelSocket *sioc = QIO_CHANNEL_SOCKET(ioc); +@@ -620,6 +621,7 @@ static ssize_t qio_channel_socket_writev(QIOChannel *ioc, + size_t niov, + int *fds, + size_t nfds, ++ int flags, + Error **errp) + { + QIOChannelSocket *sioc = QIO_CHANNEL_SOCKET(ioc); +diff --git a/io/channel-tls.c b/io/channel-tls.c +index 2ae1b92fc0..4ce890a538 100644 +--- a/io/channel-tls.c ++++ b/io/channel-tls.c +@@ -301,6 +301,7 @@ static ssize_t qio_channel_tls_writev(QIOChannel *ioc, + size_t niov, + int *fds, + size_t nfds, ++ int flags, + Error **errp) + { + QIOChannelTLS *tioc = QIO_CHANNEL_TLS(ioc); +diff --git a/io/channel-websock.c b/io/channel-websock.c +index 55145a6a8c..9619906ac3 100644 +--- a/io/channel-websock.c ++++ b/io/channel-websock.c +@@ -1127,6 +1127,7 @@ static ssize_t qio_channel_websock_writev(QIOChannel *ioc, + size_t niov, + int *fds, + size_t nfds, ++ int flags, + Error **errp) + { + QIOChannelWebsock *wioc = QIO_CHANNEL_WEBSOCK(ioc); +diff --git a/io/channel.c b/io/channel.c +index e8b019dc36..0640941ac5 100644 +--- a/io/channel.c ++++ b/io/channel.c +@@ -72,18 +72,32 @@ ssize_t qio_channel_writev_full(QIOChannel *ioc, + size_t niov, + int *fds, + size_t nfds, ++ int flags, + Error **errp) + { + QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc); + +- if ((fds || nfds) && +- !qio_channel_has_feature(ioc, QIO_CHANNEL_FEATURE_FD_PASS)) { ++ if (fds || nfds) { ++ if (!qio_channel_has_feature(ioc, QIO_CHANNEL_FEATURE_FD_PASS)) { ++ error_setg_errno(errp, EINVAL, ++ "Channel does not support file descriptor passing"); ++ return -1; ++ } ++ if (flags & QIO_CHANNEL_WRITE_FLAG_ZERO_COPY) { ++ error_setg_errno(errp, EINVAL, ++ "Zero Copy does not support file descriptor passing"); ++ return -1; ++ } ++ } ++ ++ if ((flags & QIO_CHANNEL_WRITE_FLAG_ZERO_COPY) && ++ !qio_channel_has_feature(ioc, QIO_CHANNEL_FEATURE_WRITE_ZERO_COPY)) { + error_setg_errno(errp, EINVAL, +- "Channel does not support file descriptor passing"); ++ "Requested Zero Copy feature is not available"); + return -1; + } + +- return klass->io_writev(ioc, iov, niov, fds, nfds, errp); ++ return klass->io_writev(ioc, iov, niov, fds, nfds, flags, errp); + } + + +@@ -217,14 +231,14 @@ int qio_channel_writev_all(QIOChannel *ioc, + size_t niov, + Error **errp) + { +- return qio_channel_writev_full_all(ioc, iov, niov, NULL, 0, errp); ++ return qio_channel_writev_full_all(ioc, iov, niov, NULL, 0, 0, errp); + } + + int qio_channel_writev_full_all(QIOChannel *ioc, + const struct iovec *iov, + size_t niov, + int *fds, size_t nfds, +- Error **errp) ++ int flags, Error **errp) + { + int ret = -1; + struct iovec *local_iov = g_new(struct iovec, niov); +@@ -237,8 +251,10 @@ int qio_channel_writev_full_all(QIOChannel *ioc, + + while (nlocal_iov > 0) { + ssize_t len; +- len = qio_channel_writev_full(ioc, local_iov, nlocal_iov, fds, nfds, +- errp); ++ ++ len = qio_channel_writev_full(ioc, local_iov, nlocal_iov, fds, ++ nfds, flags, errp); ++ + if (len == QIO_CHANNEL_ERR_BLOCK) { + if (qemu_in_coroutine()) { + qio_channel_yield(ioc, G_IO_OUT); +@@ -277,7 +293,7 @@ ssize_t qio_channel_writev(QIOChannel *ioc, + size_t niov, + Error **errp) + { +- return qio_channel_writev_full(ioc, iov, niov, NULL, 0, errp); ++ return qio_channel_writev_full(ioc, iov, niov, NULL, 0, 0, errp); + } + + +@@ -297,7 +313,7 @@ ssize_t qio_channel_write(QIOChannel *ioc, + Error **errp) + { + struct iovec iov = { .iov_base = (char *)buf, .iov_len = buflen }; +- return qio_channel_writev_full(ioc, &iov, 1, NULL, 0, errp); ++ return qio_channel_writev_full(ioc, &iov, 1, NULL, 0, 0, errp); + } + + +@@ -473,6 +489,19 @@ off_t qio_channel_io_seek(QIOChannel *ioc, + return klass->io_seek(ioc, offset, whence, errp); + } + ++int qio_channel_flush(QIOChannel *ioc, ++ Error **errp) ++{ ++ QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc); ++ ++ if (!klass->io_flush || ++ !qio_channel_has_feature(ioc, QIO_CHANNEL_FEATURE_WRITE_ZERO_COPY)) { ++ return 0; ++ } ++ ++ return klass->io_flush(ioc, errp); ++} ++ + + static void qio_channel_restart_read(void *opaque) + { +diff --git a/migration/rdma.c b/migration/rdma.c +index ef1e65ec36..672d1958a9 100644 +--- a/migration/rdma.c ++++ b/migration/rdma.c +@@ -2840,6 +2840,7 @@ static ssize_t qio_channel_rdma_writev(QIOChannel *ioc, + size_t niov, + int *fds, + size_t nfds, ++ int flags, + Error **errp) + { + QIOChannelRDMA *rioc = QIO_CHANNEL_RDMA(ioc); +diff --git a/scsi/pr-manager-helper.c b/scsi/pr-manager-helper.c +index 451c7631b7..3be52a98d5 100644 +--- a/scsi/pr-manager-helper.c ++++ b/scsi/pr-manager-helper.c +@@ -77,7 +77,7 @@ static int pr_manager_helper_write(PRManagerHelper *pr_mgr, + iov.iov_base = (void *)buf; + iov.iov_len = sz; + n_written = qio_channel_writev_full(QIO_CHANNEL(pr_mgr->ioc), &iov, 1, +- nfds ? &fd : NULL, nfds, errp); ++ nfds ? &fd : NULL, nfds, 0, errp); + + if (n_written <= 0) { + assert(n_written != QIO_CHANNEL_ERR_BLOCK); +diff --git a/tests/unit/test-io-channel-socket.c b/tests/unit/test-io-channel-socket.c +index c49eec1f03..6713886d02 100644 +--- a/tests/unit/test-io-channel-socket.c ++++ b/tests/unit/test-io-channel-socket.c +@@ -444,6 +444,7 @@ static void test_io_channel_unix_fd_pass(void) + G_N_ELEMENTS(iosend), + fdsend, + G_N_ELEMENTS(fdsend), ++ 0, + &error_abort); + + qio_channel_readv_full(dst, +-- +2.35.3 + diff --git a/kvm-QIOChannelSocket-Fix-zero-copy-send-so-socket-flush-.patch b/kvm-QIOChannelSocket-Fix-zero-copy-send-so-socket-flush-.patch new file mode 100644 index 0000000..9d134e6 --- /dev/null +++ b/kvm-QIOChannelSocket-Fix-zero-copy-send-so-socket-flush-.patch @@ -0,0 +1,58 @@ +From e70f01749addd7d0b7aa7fa4fdedb664f98e6b9b Mon Sep 17 00:00:00 2001 +From: Leonardo Bras +Date: Mon, 20 Jun 2022 02:39:43 -0300 +Subject: [PATCH 16/18] QIOChannelSocket: Fix zero-copy send so socket flush + works +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Leonardo Brás +RH-MergeRequest: 95: MSG_ZEROCOPY + Multifd +RH-Commit: [10/11] a2dfac987e24026b1a78e90b86234ca206b6401f (LeoBras/centos-qemu-kvm) +RH-Bugzilla: 1968509 +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: Dr. David Alan Gilbert +RH-Acked-by: Peter Xu + +Somewhere between v6 and v7 the of the zero-copy-send patchset a crucial +part of the flushing mechanism got missing: incrementing zero_copy_queued. + +Without that, the flushing interface becomes a no-op, and there is no +guarantee the buffer is really sent. + +This can go as bad as causing a corruption in RAM during migration. + +Fixes: 2bc58ffc2926 ("QIOChannelSocket: Implement io_writev zero copy flag & io_flush for CONFIG_LINUX") +Reported-by: 徐闯 +Signed-off-by: Leonardo Bras +Reviewed-by: Daniel P. Berrangé +Reviewed-by: Peter Xu +Reviewed-by: Juan Quintela +Signed-off-by: Juan Quintela +Signed-off-by: Dr. David Alan Gilbert +(cherry picked from commit 4f5a09714c983a3471fd12e3c7f3196e95c650c1) +Signed-off-by: Leonardo Bras +--- + io/channel-socket.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/io/channel-socket.c b/io/channel-socket.c +index 7490e5943d..8ae8b212cf 100644 +--- a/io/channel-socket.c ++++ b/io/channel-socket.c +@@ -612,6 +612,11 @@ static ssize_t qio_channel_socket_writev(QIOChannel *ioc, + "Unable to write to socket"); + return -1; + } ++ ++ if (flags & QIO_CHANNEL_WRITE_FLAG_ZERO_COPY) { ++ sioc->zero_copy_queued++; ++ } ++ + return ret; + } + #else /* WIN32 */ +-- +2.35.3 + diff --git a/kvm-QIOChannelSocket-Implement-io_writev-zero-copy-flag-.patch b/kvm-QIOChannelSocket-Implement-io_writev-zero-copy-flag-.patch new file mode 100644 index 0000000..89aa806 --- /dev/null +++ b/kvm-QIOChannelSocket-Implement-io_writev-zero-copy-flag-.patch @@ -0,0 +1,249 @@ +From 4aeba0365d30dabe2e70dc172683f0878a4a9621 Mon Sep 17 00:00:00 2001 +From: Leonardo Bras +Date: Fri, 13 May 2022 03:28:32 -0300 +Subject: [PATCH 09/18] QIOChannelSocket: Implement io_writev zero copy flag & + io_flush for CONFIG_LINUX +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Leonardo Brás +RH-MergeRequest: 95: MSG_ZEROCOPY + Multifd +RH-Commit: [3/11] 9afeac1f5ac7675624660a0281726c09c8321180 (LeoBras/centos-qemu-kvm) +RH-Bugzilla: 1968509 +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: Dr. David Alan Gilbert +RH-Acked-by: Peter Xu + +For CONFIG_LINUX, implement the new zero copy flag and the optional callback +io_flush on QIOChannelSocket, but enables it only when MSG_ZEROCOPY +feature is available in the host kernel, which is checked on +qio_channel_socket_connect_sync() + +qio_channel_socket_flush() was implemented by counting how many times +sendmsg(...,MSG_ZEROCOPY) was successfully called, and then reading the +socket's error queue, in order to find how many of them finished sending. +Flush will loop until those counters are the same, or until some error occurs. + +Notes on using writev() with QIO_CHANNEL_WRITE_FLAG_ZERO_COPY: +1: Buffer +- As MSG_ZEROCOPY tells the kernel to use the same user buffer to avoid copying, +some caution is necessary to avoid overwriting any buffer before it's sent. +If something like this happen, a newer version of the buffer may be sent instead. +- If this is a problem, it's recommended to call qio_channel_flush() before freeing +or re-using the buffer. + +2: Locked memory +- When using MSG_ZERCOCOPY, the buffer memory will be locked after queued, and +unlocked after it's sent. +- Depending on the size of each buffer, and how often it's sent, it may require +a larger amount of locked memory than usually available to non-root user. +- If the required amount of locked memory is not available, writev_zero_copy +will return an error, which can abort an operation like migration, +- Because of this, when an user code wants to add zero copy as a feature, it +requires a mechanism to disable it, so it can still be accessible to less +privileged users. + +Signed-off-by: Leonardo Bras +Reviewed-by: Peter Xu +Reviewed-by: Daniel P. Berrangé +Reviewed-by: Juan Quintela +Message-Id: <20220513062836.965425-4-leobras@redhat.com> +Signed-off-by: Dr. David Alan Gilbert +(cherry picked from commit 2bc58ffc2926a4efdd03edfb5909861fefc68c3d) +Signed-off-by: Leonardo Bras +--- + include/io/channel-socket.h | 2 + + io/channel-socket.c | 116 ++++++++++++++++++++++++++++++++++-- + 2 files changed, 114 insertions(+), 4 deletions(-) + +diff --git a/include/io/channel-socket.h b/include/io/channel-socket.h +index e747e63514..513c428fe4 100644 +--- a/include/io/channel-socket.h ++++ b/include/io/channel-socket.h +@@ -47,6 +47,8 @@ struct QIOChannelSocket { + socklen_t localAddrLen; + struct sockaddr_storage remoteAddr; + socklen_t remoteAddrLen; ++ ssize_t zero_copy_queued; ++ ssize_t zero_copy_sent; + }; + + +diff --git a/io/channel-socket.c b/io/channel-socket.c +index a1be2197ca..fbd2214d20 100644 +--- a/io/channel-socket.c ++++ b/io/channel-socket.c +@@ -26,6 +26,14 @@ + #include "io/channel-watch.h" + #include "trace.h" + #include "qapi/clone-visitor.h" ++#ifdef CONFIG_LINUX ++#include ++#include ++ ++#if (defined(MSG_ZEROCOPY) && defined(SO_ZEROCOPY)) ++#define QEMU_MSG_ZEROCOPY ++#endif ++#endif + + #define SOCKET_MAX_FDS 16 + +@@ -55,6 +63,8 @@ qio_channel_socket_new(void) + + sioc = QIO_CHANNEL_SOCKET(object_new(TYPE_QIO_CHANNEL_SOCKET)); + sioc->fd = -1; ++ sioc->zero_copy_queued = 0; ++ sioc->zero_copy_sent = 0; + + ioc = QIO_CHANNEL(sioc); + qio_channel_set_feature(ioc, QIO_CHANNEL_FEATURE_SHUTDOWN); +@@ -154,6 +164,16 @@ int qio_channel_socket_connect_sync(QIOChannelSocket *ioc, + return -1; + } + ++#ifdef QEMU_MSG_ZEROCOPY ++ int ret, v = 1; ++ ret = setsockopt(fd, SOL_SOCKET, SO_ZEROCOPY, &v, sizeof(v)); ++ if (ret == 0) { ++ /* Zero copy available on host */ ++ qio_channel_set_feature(QIO_CHANNEL(ioc), ++ QIO_CHANNEL_FEATURE_WRITE_ZERO_COPY); ++ } ++#endif ++ + return 0; + } + +@@ -534,6 +554,7 @@ static ssize_t qio_channel_socket_writev(QIOChannel *ioc, + char control[CMSG_SPACE(sizeof(int) * SOCKET_MAX_FDS)]; + size_t fdsize = sizeof(int) * nfds; + struct cmsghdr *cmsg; ++ int sflags = 0; + + memset(control, 0, CMSG_SPACE(sizeof(int) * SOCKET_MAX_FDS)); + +@@ -558,15 +579,31 @@ static ssize_t qio_channel_socket_writev(QIOChannel *ioc, + memcpy(CMSG_DATA(cmsg), fds, fdsize); + } + ++#ifdef QEMU_MSG_ZEROCOPY ++ if (flags & QIO_CHANNEL_WRITE_FLAG_ZERO_COPY) { ++ sflags = MSG_ZEROCOPY; ++ } ++#endif ++ + retry: +- ret = sendmsg(sioc->fd, &msg, 0); ++ ret = sendmsg(sioc->fd, &msg, sflags); + if (ret <= 0) { +- if (errno == EAGAIN) { ++ switch (errno) { ++ case EAGAIN: + return QIO_CHANNEL_ERR_BLOCK; +- } +- if (errno == EINTR) { ++ case EINTR: + goto retry; ++#ifdef QEMU_MSG_ZEROCOPY ++ case ENOBUFS: ++ if (sflags & MSG_ZEROCOPY) { ++ error_setg_errno(errp, errno, ++ "Process can't lock enough memory for using MSG_ZEROCOPY"); ++ return -1; ++ } ++ break; ++#endif + } ++ + error_setg_errno(errp, errno, + "Unable to write to socket"); + return -1; +@@ -660,6 +697,74 @@ static ssize_t qio_channel_socket_writev(QIOChannel *ioc, + } + #endif /* WIN32 */ + ++ ++#ifdef QEMU_MSG_ZEROCOPY ++static int qio_channel_socket_flush(QIOChannel *ioc, ++ Error **errp) ++{ ++ QIOChannelSocket *sioc = QIO_CHANNEL_SOCKET(ioc); ++ struct msghdr msg = {}; ++ struct sock_extended_err *serr; ++ struct cmsghdr *cm; ++ char control[CMSG_SPACE(sizeof(*serr))]; ++ int received; ++ int ret = 1; ++ ++ msg.msg_control = control; ++ msg.msg_controllen = sizeof(control); ++ memset(control, 0, sizeof(control)); ++ ++ while (sioc->zero_copy_sent < sioc->zero_copy_queued) { ++ received = recvmsg(sioc->fd, &msg, MSG_ERRQUEUE); ++ if (received < 0) { ++ switch (errno) { ++ case EAGAIN: ++ /* Nothing on errqueue, wait until something is available */ ++ qio_channel_wait(ioc, G_IO_ERR); ++ continue; ++ case EINTR: ++ continue; ++ default: ++ error_setg_errno(errp, errno, ++ "Unable to read errqueue"); ++ return -1; ++ } ++ } ++ ++ cm = CMSG_FIRSTHDR(&msg); ++ if (cm->cmsg_level != SOL_IP && ++ cm->cmsg_type != IP_RECVERR) { ++ error_setg_errno(errp, EPROTOTYPE, ++ "Wrong cmsg in errqueue"); ++ return -1; ++ } ++ ++ serr = (void *) CMSG_DATA(cm); ++ if (serr->ee_errno != SO_EE_ORIGIN_NONE) { ++ error_setg_errno(errp, serr->ee_errno, ++ "Error on socket"); ++ return -1; ++ } ++ if (serr->ee_origin != SO_EE_ORIGIN_ZEROCOPY) { ++ error_setg_errno(errp, serr->ee_origin, ++ "Error not from zero copy"); ++ return -1; ++ } ++ ++ /* No errors, count successfully finished sendmsg()*/ ++ sioc->zero_copy_sent += serr->ee_data - serr->ee_info + 1; ++ ++ /* If any sendmsg() succeeded using zero copy, return 0 at the end */ ++ if (serr->ee_code != SO_EE_CODE_ZEROCOPY_COPIED) { ++ ret = 0; ++ } ++ } ++ ++ return ret; ++} ++ ++#endif /* QEMU_MSG_ZEROCOPY */ ++ + static int + qio_channel_socket_set_blocking(QIOChannel *ioc, + bool enabled, +@@ -790,6 +895,9 @@ static void qio_channel_socket_class_init(ObjectClass *klass, + ioc_klass->io_set_delay = qio_channel_socket_set_delay; + ioc_klass->io_create_watch = qio_channel_socket_create_watch; + ioc_klass->io_set_aio_fd_handler = qio_channel_socket_set_aio_fd_handler; ++#ifdef QEMU_MSG_ZEROCOPY ++ ioc_klass->io_flush = qio_channel_socket_flush; ++#endif + } + + static const TypeInfo qio_channel_socket_info = { +-- +2.35.3 + diff --git a/kvm-QIOChannelSocket-Introduce-assert-and-reduce-ifdefs-.patch b/kvm-QIOChannelSocket-Introduce-assert-and-reduce-ifdefs-.patch new file mode 100644 index 0000000..6fc0c76 --- /dev/null +++ b/kvm-QIOChannelSocket-Introduce-assert-and-reduce-ifdefs-.patch @@ -0,0 +1,82 @@ +From 60bf942a58db12c821f2a6a49e2e0b04b99bec30 Mon Sep 17 00:00:00 2001 +From: Leonardo Bras +Date: Mon, 20 Jun 2022 02:39:42 -0300 +Subject: [PATCH 15/18] QIOChannelSocket: Introduce assert and reduce ifdefs to + improve readability +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Leonardo Brás +RH-MergeRequest: 95: MSG_ZEROCOPY + Multifd +RH-Commit: [9/11] eaa02d68301852ccc98bdacc7387d8d03be1cb05 (LeoBras/centos-qemu-kvm) +RH-Bugzilla: 1968509 +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: Dr. David Alan Gilbert +RH-Acked-by: Peter Xu + +During implementation of MSG_ZEROCOPY feature, a lot of #ifdefs were +introduced, particularly at qio_channel_socket_writev(). + +Rewrite some of those changes so it's easier to read. + +Also, introduce an assert to help detect incorrect zero-copy usage is when +it's disabled on build. + +Signed-off-by: Leonardo Bras +Reviewed-by: Daniel P. Berrangé +Reviewed-by: Juan Quintela +Reviewed-by: Peter Xu +Signed-off-by: Juan Quintela +Signed-off-by: Dr. David Alan Gilbert + dgilbert: Fixed up thinko'd g_assert_unreachable->g_assert_not_reached +(cherry picked from commit 803ca43e4c7fcf32f9f68c118301ccd0c83ece3f) +Signed-off-by: Leonardo Bras +--- + io/channel-socket.c | 14 +++++++++----- + 1 file changed, 9 insertions(+), 5 deletions(-) + +diff --git a/io/channel-socket.c b/io/channel-socket.c +index fbd2214d20..7490e5943d 100644 +--- a/io/channel-socket.c ++++ b/io/channel-socket.c +@@ -579,11 +579,17 @@ static ssize_t qio_channel_socket_writev(QIOChannel *ioc, + memcpy(CMSG_DATA(cmsg), fds, fdsize); + } + +-#ifdef QEMU_MSG_ZEROCOPY + if (flags & QIO_CHANNEL_WRITE_FLAG_ZERO_COPY) { ++#ifdef QEMU_MSG_ZEROCOPY + sflags = MSG_ZEROCOPY; +- } ++#else ++ /* ++ * We expect QIOChannel class entry point to have ++ * blocked this code path already ++ */ ++ g_assert_not_reached(); + #endif ++ } + + retry: + ret = sendmsg(sioc->fd, &msg, sflags); +@@ -593,15 +599,13 @@ static ssize_t qio_channel_socket_writev(QIOChannel *ioc, + return QIO_CHANNEL_ERR_BLOCK; + case EINTR: + goto retry; +-#ifdef QEMU_MSG_ZEROCOPY + case ENOBUFS: +- if (sflags & MSG_ZEROCOPY) { ++ if (flags & QIO_CHANNEL_WRITE_FLAG_ZERO_COPY) { + error_setg_errno(errp, errno, + "Process can't lock enough memory for using MSG_ZEROCOPY"); + return -1; + } + break; +-#endif + } + + error_setg_errno(errp, errno, +-- +2.35.3 + diff --git a/kvm-RHEL-only-AArch64-Drop-unsupported-CPU-types.patch b/kvm-RHEL-only-AArch64-Drop-unsupported-CPU-types.patch new file mode 100644 index 0000000..8a0aeb0 --- /dev/null +++ b/kvm-RHEL-only-AArch64-Drop-unsupported-CPU-types.patch @@ -0,0 +1,237 @@ +From 055edf068196622a3e1868c9e4c991d410272a6d Mon Sep 17 00:00:00 2001 +From: Andrew Jones +Date: Wed, 15 Jun 2022 15:28:27 +0200 +Subject: [PATCH 03/18] RHEL-only: AArch64: Drop unsupported CPU types +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Daniel P. Berrangé +RH-MergeRequest: 94: i386, aarch64, s390x: deprecate many named CPU models +RH-Commit: [3/6] 21f54c86dc87e5e75a64459b5a385686bc09640c (berrange/centos-src-qemu) +RH-Bugzilla: 2060839 +RH-Acked-by: Thomas Huth +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: Cornelia Huck + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2066824 +Upstream Status: RHEL only + +We only need to support AArch64 cpu types and we only need three +types: + 1) A base type to use with TCG, i.e. a cpu type with only base + features. 'cortex-a57' serves this role and is currently used + by libguestfs. + 2) The 'max' type, which is for both KVM and TCG and is good for + tests that just specify 'max' but run under both. 'max' with + TCG also provides the VM with all the CPU features TCG + supports, which is good for VMs that need features not + provided by the basic cortex-a57. + 3) The host type which is used with KVM. + +Signed-off-by: Andrew Jones +--- + hw/arm/virt.c | 4 ++++ + target/arm/cpu64.c | 6 ++++++ + target/arm/cpu_tcg.c | 12 ++---------- + tests/qtest/arm-cpu-features.c | 6 ++++++ + 4 files changed, 18 insertions(+), 10 deletions(-) + +diff --git a/hw/arm/virt.c b/hw/arm/virt.c +index 95d012d6eb..74119976d3 100644 +--- a/hw/arm/virt.c ++++ b/hw/arm/virt.c +@@ -239,12 +239,16 @@ static const int a15irqmap[] = { + }; + + static const char *valid_cpus[] = { ++#if 0 /* Disabled for Red Hat Enterprise Linux */ + ARM_CPU_TYPE_NAME("cortex-a7"), + ARM_CPU_TYPE_NAME("cortex-a15"), + ARM_CPU_TYPE_NAME("cortex-a53"), ++#endif /* disabled for RHEL */ + ARM_CPU_TYPE_NAME("cortex-a57"), ++#if 0 /* Disabled for Red Hat Enterprise Linux */ + ARM_CPU_TYPE_NAME("cortex-a72"), + ARM_CPU_TYPE_NAME("a64fx"), ++#endif /* disabled for RHEL */ + ARM_CPU_TYPE_NAME("host"), + ARM_CPU_TYPE_NAME("max"), + }; +diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c +index eb44c05822..e80b831073 100644 +--- a/target/arm/cpu64.c ++++ b/target/arm/cpu64.c +@@ -146,6 +146,7 @@ static void aarch64_a57_initfn(Object *obj) + define_arm_cp_regs(cpu, cortex_a72_a57_a53_cp_reginfo); + } + ++#if 0 /* Disabled for Red Hat Enterprise Linux */ + static void aarch64_a53_initfn(Object *obj) + { + ARMCPU *cpu = ARM_CPU(obj); +@@ -249,6 +250,7 @@ static void aarch64_a72_initfn(Object *obj) + cpu->gic_vprebits = 5; + define_arm_cp_regs(cpu, cortex_a72_a57_a53_cp_reginfo); + } ++#endif /* disabled for RHEL */ + + void arm_cpu_sve_finalize(ARMCPU *cpu, Error **errp) + { +@@ -923,6 +925,7 @@ static void aarch64_max_initfn(Object *obj) + qdev_property_add_static(DEVICE(obj), &arm_cpu_lpa2_property); + } + ++#if 0 /* Disabled for Red Hat Enterprise Linux */ + static void aarch64_a64fx_initfn(Object *obj) + { + ARMCPU *cpu = ARM_CPU(obj); +@@ -969,12 +972,15 @@ static void aarch64_a64fx_initfn(Object *obj) + + /* TODO: Add A64FX specific HPC extension registers */ + } ++#endif /* disabled for RHEL */ + + static const ARMCPUInfo aarch64_cpus[] = { + { .name = "cortex-a57", .initfn = aarch64_a57_initfn }, ++#if 0 /* Disabled for Red Hat Enterprise Linux */ + { .name = "cortex-a53", .initfn = aarch64_a53_initfn }, + { .name = "cortex-a72", .initfn = aarch64_a72_initfn }, + { .name = "a64fx", .initfn = aarch64_a64fx_initfn }, ++#endif /* disabled for RHEL */ + { .name = "max", .initfn = aarch64_max_initfn }, + #if defined(CONFIG_KVM) || defined(CONFIG_HVF) + { .name = "host", .initfn = aarch64_host_initfn }, +diff --git a/target/arm/cpu_tcg.c b/target/arm/cpu_tcg.c +index 3826fa5122..74727fc92c 100644 +--- a/target/arm/cpu_tcg.c ++++ b/target/arm/cpu_tcg.c +@@ -19,10 +19,10 @@ + #include "hw/boards.h" + #endif + ++#if 0 /* Disabled for Red Hat Enterprise Linux */ + /* CPU models. These are not needed for the AArch64 linux-user build. */ + #if !defined(CONFIG_USER_ONLY) || !defined(TARGET_AARCH64) + +-#if 0 /* Disabled for Red Hat Enterprise Linux */ + #if !defined(CONFIG_USER_ONLY) && defined(CONFIG_TCG) + static bool arm_v7m_cpu_exec_interrupt(CPUState *cs, int interrupt_request) + { +@@ -376,7 +376,6 @@ static void cortex_a9_initfn(Object *obj) + cpu->ccsidr[1] = 0x200fe019; /* 16k L1 icache. */ + define_arm_cp_regs(cpu, cortexa9_cp_reginfo); + } +-#endif /* disabled for RHEL */ + + #ifndef CONFIG_USER_ONLY + static uint64_t a15_l2ctlr_read(CPUARMState *env, const ARMCPRegInfo *ri) +@@ -402,7 +401,6 @@ static const ARMCPRegInfo cortexa15_cp_reginfo[] = { + REGINFO_SENTINEL + }; + +-#if 0 /* Disabled for Red Hat Enterprise Linux */ + static void cortex_a7_initfn(Object *obj) + { + ARMCPU *cpu = ARM_CPU(obj); +@@ -448,7 +446,6 @@ static void cortex_a7_initfn(Object *obj) + cpu->ccsidr[2] = 0x711fe07a; /* 4096K L2 unified cache */ + define_arm_cp_regs(cpu, cortexa15_cp_reginfo); /* Same as A15 */ + } +-#endif /* disabled for RHEL */ + + static void cortex_a15_initfn(Object *obj) + { +@@ -492,7 +489,6 @@ static void cortex_a15_initfn(Object *obj) + define_arm_cp_regs(cpu, cortexa15_cp_reginfo); + } + +-#if 0 /* Disabled for Red Hat Enterprise Linux */ + static void cortex_m0_initfn(Object *obj) + { + ARMCPU *cpu = ARM_CPU(obj); +@@ -933,7 +929,6 @@ static void arm_v7m_class_init(ObjectClass *oc, void *data) + + cc->gdb_core_xml_file = "arm-m-profile.xml"; + } +-#endif /* disabled for RHEL */ + + #ifndef TARGET_AARCH64 + /* +@@ -1013,7 +1008,6 @@ static void arm_max_initfn(Object *obj) + #endif /* !TARGET_AARCH64 */ + + static const ARMCPUInfo arm_tcg_cpus[] = { +-#if 0 /* Disabled for Red Hat Enterprise Linux */ + { .name = "arm926", .initfn = arm926_initfn }, + { .name = "arm946", .initfn = arm946_initfn }, + { .name = "arm1026", .initfn = arm1026_initfn }, +@@ -1029,9 +1023,7 @@ static const ARMCPUInfo arm_tcg_cpus[] = { + { .name = "cortex-a7", .initfn = cortex_a7_initfn }, + { .name = "cortex-a8", .initfn = cortex_a8_initfn }, + { .name = "cortex-a9", .initfn = cortex_a9_initfn }, +-#endif /* disabled for RHEL */ + { .name = "cortex-a15", .initfn = cortex_a15_initfn }, +-#if 0 /* Disabled for Red Hat Enterprise Linux */ + { .name = "cortex-m0", .initfn = cortex_m0_initfn, + .class_init = arm_v7m_class_init }, + { .name = "cortex-m3", .initfn = cortex_m3_initfn, +@@ -1062,7 +1054,6 @@ static const ARMCPUInfo arm_tcg_cpus[] = { + { .name = "pxa270-b1", .initfn = pxa270b1_initfn }, + { .name = "pxa270-c0", .initfn = pxa270c0_initfn }, + { .name = "pxa270-c5", .initfn = pxa270c5_initfn }, +-#endif /* disabled for RHEL */ + #ifndef TARGET_AARCH64 + { .name = "max", .initfn = arm_max_initfn }, + #endif +@@ -1090,3 +1081,4 @@ static void arm_tcg_cpu_register_types(void) + type_init(arm_tcg_cpu_register_types) + + #endif /* !CONFIG_USER_ONLY || !TARGET_AARCH64 */ ++#endif /* disabled for RHEL */ +diff --git a/tests/qtest/arm-cpu-features.c b/tests/qtest/arm-cpu-features.c +index f76652143a..fe2a0a070d 100644 +--- a/tests/qtest/arm-cpu-features.c ++++ b/tests/qtest/arm-cpu-features.c +@@ -440,8 +440,10 @@ static void test_query_cpu_model_expansion(const void *data) + assert_error(qts, "host", "The CPU type 'host' requires KVM", NULL); + + /* Test expected feature presence/absence for some cpu types */ ++#if 0 /* Disabled for Red Hat Enterprise Linux */ + assert_has_feature_enabled(qts, "cortex-a15", "pmu"); + assert_has_not_feature(qts, "cortex-a15", "aarch64"); ++#endif /* disabled for RHEL */ + + /* Enabling and disabling pmu should always work. */ + assert_has_feature_enabled(qts, "max", "pmu"); +@@ -458,6 +460,7 @@ static void test_query_cpu_model_expansion(const void *data) + assert_has_feature_enabled(qts, "cortex-a57", "pmu"); + assert_has_feature_enabled(qts, "cortex-a57", "aarch64"); + ++#if 0 /* Disabled for Red Hat Enterprise Linux */ + assert_has_feature_enabled(qts, "a64fx", "pmu"); + assert_has_feature_enabled(qts, "a64fx", "aarch64"); + /* +@@ -470,6 +473,7 @@ static void test_query_cpu_model_expansion(const void *data) + "{ 'sve384': true }"); + assert_error(qts, "a64fx", "cannot enable sve640", + "{ 'sve640': true }"); ++#endif /* disabled for RHEL */ + + sve_tests_default(qts, "max"); + pauth_tests_default(qts, "max"); +@@ -505,9 +509,11 @@ static void test_query_cpu_model_expansion_kvm(const void *data) + QDict *resp; + char *error; + ++#if 0 /* Disabled for Red Hat Enterprise Linux */ + assert_error(qts, "cortex-a15", + "We cannot guarantee the CPU type 'cortex-a15' works " + "with KVM on this host", NULL); ++#endif /* disabled for RHEL */ + + assert_has_feature_enabled(qts, "host", "aarch64"); + +-- +2.35.3 + diff --git a/kvm-RHEL-only-tests-avocado-Switch-aarch64-tests-from-a5.patch b/kvm-RHEL-only-tests-avocado-Switch-aarch64-tests-from-a5.patch new file mode 100644 index 0000000..a1cc4c7 --- /dev/null +++ b/kvm-RHEL-only-tests-avocado-Switch-aarch64-tests-from-a5.patch @@ -0,0 +1,95 @@ +From d710394f68eb0b6116dd8ac76f619c192e0d5972 Mon Sep 17 00:00:00 2001 +From: Andrew Jones +Date: Wed, 15 Jun 2022 15:28:27 +0200 +Subject: [PATCH 02/18] RHEL-only: tests/avocado: Switch aarch64 tests from a53 + to a57 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Daniel P. Berrangé +RH-MergeRequest: 94: i386, aarch64, s390x: deprecate many named CPU models +RH-Commit: [2/6] e85ef69b42c411a6997e4da10ba05176368769b3 (berrange/centos-src-qemu) +RH-Bugzilla: 2060839 +RH-Acked-by: Thomas Huth +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: Cornelia Huck + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2066824 +Upstream Status: RHEL only + +We plan to remove the cortex-a53 from the supported cpu types. Switch +all avocado tests that use it to the cortex-a57, which will work the +same and we intend to keep. We don't want to try and upstream this +change since the better upstream change would be to switch from the +a53 to 'max', but the upstream tests also need to use later guest +kernels to use 'max' (see qemu upstream commit 0942820408dc +("hw/arm/virt: Disable LPA2 for -machine virt-6.2") + +Signed-off-by: Andrew Jones +--- + tests/avocado/replay_kernel.py | 2 +- + tests/avocado/reverse_debugging.py | 2 +- + tests/avocado/tcg_plugins.py | 6 +++--- + 3 files changed, 5 insertions(+), 5 deletions(-) + +diff --git a/tests/avocado/replay_kernel.py b/tests/avocado/replay_kernel.py +index 0b2b0dc692..3a7b5f0748 100644 +--- a/tests/avocado/replay_kernel.py ++++ b/tests/avocado/replay_kernel.py +@@ -147,7 +147,7 @@ def test_aarch64_virt(self): + """ + :avocado: tags=arch:aarch64 + :avocado: tags=machine:virt +- :avocado: tags=cpu:cortex-a53 ++ :avocado: tags=cpu:cortex-a57 + """ + kernel_url = ('https://archives.fedoraproject.org/pub/archive/fedora' + '/linux/releases/29/Everything/aarch64/os/images/pxeboot' +diff --git a/tests/avocado/reverse_debugging.py b/tests/avocado/reverse_debugging.py +index d2921e70c3..66d185ed42 100644 +--- a/tests/avocado/reverse_debugging.py ++++ b/tests/avocado/reverse_debugging.py +@@ -198,7 +198,7 @@ def test_aarch64_virt(self): + """ + :avocado: tags=arch:aarch64 + :avocado: tags=machine:virt +- :avocado: tags=cpu:cortex-a53 ++ :avocado: tags=cpu:cortex-a57 + """ + kernel_url = ('https://archives.fedoraproject.org/pub/archive/fedora' + '/linux/releases/29/Everything/aarch64/os/images/pxeboot' +diff --git a/tests/avocado/tcg_plugins.py b/tests/avocado/tcg_plugins.py +index 642d2e49e3..93b3afd823 100644 +--- a/tests/avocado/tcg_plugins.py ++++ b/tests/avocado/tcg_plugins.py +@@ -68,7 +68,7 @@ def test_aarch64_virt_insn(self): + :avocado: tags=accel:tcg + :avocado: tags=arch:aarch64 + :avocado: tags=machine:virt +- :avocado: tags=cpu:cortex-a53 ++ :avocado: tags=cpu:cortex-a57 + """ + kernel_path = self._grab_aarch64_kernel() + kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + +@@ -94,7 +94,7 @@ def test_aarch64_virt_insn_icount(self): + :avocado: tags=accel:tcg + :avocado: tags=arch:aarch64 + :avocado: tags=machine:virt +- :avocado: tags=cpu:cortex-a53 ++ :avocado: tags=cpu:cortex-a57 + """ + kernel_path = self._grab_aarch64_kernel() + kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + +@@ -120,7 +120,7 @@ def test_aarch64_virt_mem_icount(self): + :avocado: tags=accel:tcg + :avocado: tags=arch:aarch64 + :avocado: tags=machine:virt +- :avocado: tags=cpu:cortex-a53 ++ :avocado: tags=cpu:cortex-a57 + """ + kernel_path = self._grab_aarch64_kernel() + kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + +-- +2.35.3 + diff --git a/kvm-meson.build-Fix-docker-test-build-alpine-when-includ.patch b/kvm-meson.build-Fix-docker-test-build-alpine-when-includ.patch new file mode 100644 index 0000000..0da63bf --- /dev/null +++ b/kvm-meson.build-Fix-docker-test-build-alpine-when-includ.patch @@ -0,0 +1,87 @@ +From 7c489b54b0bb33445113fbf16e88feb23be68013 Mon Sep 17 00:00:00 2001 +From: Leonardo Bras +Date: Fri, 13 May 2022 03:28:30 -0300 +Subject: [PATCH 07/18] meson.build: Fix docker-test-build@alpine when + including linux/errqueue.h +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Leonardo Brás +RH-MergeRequest: 95: MSG_ZEROCOPY + Multifd +RH-Commit: [1/11] f058eb846fcf611d527a1dd3b0cc399cdc17e3ee (LeoBras/centos-qemu-kvm) +RH-Bugzilla: 1968509 +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: Dr. David Alan Gilbert +RH-Acked-by: Peter Xu + +A build error happens in alpine CI when linux/errqueue.h is included +in io/channel-socket.c, due to redefining of 'struct __kernel_timespec': + +=== +ninja: job failed: [...] +In file included from /usr/include/linux/errqueue.h:6, + from ../io/channel-socket.c:29: +/usr/include/linux/time_types.h:7:8: error: redefinition of 'struct __kernel_timespec' + 7 | struct __kernel_timespec { + | ^~~~~~~~~~~~~~~~~ +In file included from /usr/include/liburing.h:19, + from /builds/user/qemu/include/block/aio.h:18, + from /builds/user/qemu/include/io/channel.h:26, + from /builds/user/qemu/include/io/channel-socket.h:24, + from ../io/channel-socket.c:24: +/usr/include/liburing/compat.h:9:8: note: originally defined here + 9 | struct __kernel_timespec { + | ^~~~~~~~~~~~~~~~~ +ninja: subcommand failed +=== + +As above error message suggests, 'struct __kernel_timespec' was already +defined by liburing/compat.h. + +Fix alpine CI by adding test to disable liburing in configure step if a +redefinition happens between linux/errqueue.h and liburing/compat.h. + +[dgilbert: This has been fixed in Alpine issue 13813 and liburing] + +Signed-off-by: Leonardo Bras +Message-Id: <20220513062836.965425-2-leobras@redhat.com> +Reviewed-by: Dr. David Alan Gilbert +Signed-off-by: Dr. David Alan Gilbert +(cherry picked from commit 354081d43de44ebd3497fe08f7f0121a5517d528) +Signed-off-by: Leonardo Bras +--- + meson.build | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/meson.build b/meson.build +index 5a7c10e639..13e3323380 100644 +--- a/meson.build ++++ b/meson.build +@@ -471,12 +471,23 @@ if not get_option('linux_aio').auto() or have_block + required: get_option('linux_aio'), + kwargs: static_kwargs) + endif ++ ++linux_io_uring_test = ''' ++ #include ++ #include ++ ++ int main(void) { return 0; }''' ++ + linux_io_uring = not_found + if not get_option('linux_io_uring').auto() or have_block + linux_io_uring = dependency('liburing', version: '>=0.3', + required: get_option('linux_io_uring'), + method: 'pkg-config', kwargs: static_kwargs) ++ if not cc.links(linux_io_uring_test) ++ linux_io_uring = not_found ++ endif + endif ++ + libnfs = not_found + if not get_option('libnfs').auto() or have_block + libnfs = dependency('libnfs', version: '>=1.9.3', +-- +2.35.3 + diff --git a/kvm-migration-Add-migrate_use_tls-helper.patch b/kvm-migration-Add-migrate_use_tls-helper.patch new file mode 100644 index 0000000..0fe0d91 --- /dev/null +++ b/kvm-migration-Add-migrate_use_tls-helper.patch @@ -0,0 +1,106 @@ +From 828f6c106eedcb7a48e551ffda15af56ff92a899 Mon Sep 17 00:00:00 2001 +From: Leonardo Bras +Date: Fri, 13 May 2022 03:28:34 -0300 +Subject: [PATCH 11/18] migration: Add migrate_use_tls() helper +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Leonardo Brás +RH-MergeRequest: 95: MSG_ZEROCOPY + Multifd +RH-Commit: [5/11] 06e945297c3b9c0ce5864885aafcdba1e5746bc2 (LeoBras/centos-qemu-kvm) +RH-Bugzilla: 1968509 +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: Dr. David Alan Gilbert +RH-Acked-by: Peter Xu + +A lot of places check parameters.tls_creds in order to evaluate if TLS is +in use, and sometimes call migrate_get_current() just for that test. + +Add new helper function migrate_use_tls() in order to simplify testing +for TLS usage. + +Signed-off-by: Leonardo Bras +Reviewed-by: Juan Quintela +Reviewed-by: Peter Xu +Reviewed-by: Daniel P. Berrangé +Message-Id: <20220513062836.965425-6-leobras@redhat.com> +Signed-off-by: Dr. David Alan Gilbert +(cherry picked from commit d2fafb6a6814a8998607d0baf691265032996a0f) +Signed-off-by: Leonardo Bras +--- + migration/channel.c | 3 +-- + migration/migration.c | 9 +++++++++ + migration/migration.h | 1 + + migration/multifd.c | 5 +---- + 4 files changed, 12 insertions(+), 6 deletions(-) + +diff --git a/migration/channel.c b/migration/channel.c +index c4fc000a1a..086b5c0d8b 100644 +--- a/migration/channel.c ++++ b/migration/channel.c +@@ -38,8 +38,7 @@ void migration_channel_process_incoming(QIOChannel *ioc) + trace_migration_set_incoming_channel( + ioc, object_get_typename(OBJECT(ioc))); + +- if (s->parameters.tls_creds && +- *s->parameters.tls_creds && ++ if (migrate_use_tls() && + !object_dynamic_cast(OBJECT(ioc), + TYPE_QIO_CHANNEL_TLS)) { + migration_tls_channel_process_incoming(s, ioc, &local_err); +diff --git a/migration/migration.c b/migration/migration.c +index 0a6b3b9f4d..d91efb66fe 100644 +--- a/migration/migration.c ++++ b/migration/migration.c +@@ -2582,6 +2582,15 @@ bool migrate_use_zero_copy_send(void) + } + #endif + ++int migrate_use_tls(void) ++{ ++ MigrationState *s; ++ ++ s = migrate_get_current(); ++ ++ return s->parameters.tls_creds && *s->parameters.tls_creds; ++} ++ + int migrate_use_xbzrle(void) + { + MigrationState *s; +diff --git a/migration/migration.h b/migration/migration.h +index 5bcb7628ef..c2cabb8a14 100644 +--- a/migration/migration.h ++++ b/migration/migration.h +@@ -381,6 +381,7 @@ bool migrate_use_zero_copy_send(void); + #else + #define migrate_use_zero_copy_send() (false) + #endif ++int migrate_use_tls(void); + int migrate_use_xbzrle(void); + uint64_t migrate_xbzrle_cache_size(void); + bool migrate_colo_enabled(void); +diff --git a/migration/multifd.c b/migration/multifd.c +index 76b57a7177..43998ad117 100644 +--- a/migration/multifd.c ++++ b/migration/multifd.c +@@ -784,14 +784,11 @@ static bool multifd_channel_connect(MultiFDSendParams *p, + QIOChannel *ioc, + Error *error) + { +- MigrationState *s = migrate_get_current(); +- + trace_multifd_set_outgoing_channel( + ioc, object_get_typename(OBJECT(ioc)), p->tls_hostname, error); + + if (!error) { +- if (s->parameters.tls_creds && +- *s->parameters.tls_creds && ++ if (migrate_use_tls() && + !object_dynamic_cast(OBJECT(ioc), + TYPE_QIO_CHANNEL_TLS)) { + multifd_tls_channel_connect(p, ioc, &error); +-- +2.35.3 + diff --git a/kvm-migration-Add-zero-copy-send-parameter-for-QMP-HMP-f.patch b/kvm-migration-Add-zero-copy-send-parameter-for-QMP-HMP-f.patch new file mode 100644 index 0000000..206ac3d --- /dev/null +++ b/kvm-migration-Add-zero-copy-send-parameter-for-QMP-HMP-f.patch @@ -0,0 +1,250 @@ +From d6500340dc3c1152b5efe04ef3daa50c17a55e30 Mon Sep 17 00:00:00 2001 +From: Leonardo Bras +Date: Fri, 13 May 2022 03:28:33 -0300 +Subject: [PATCH 10/18] migration: Add zero-copy-send parameter for QMP/HMP for + Linux +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Leonardo Brás +RH-MergeRequest: 95: MSG_ZEROCOPY + Multifd +RH-Commit: [4/11] 514d98d595992c53ff98de750035e080ded8972e (LeoBras/centos-qemu-kvm) +RH-Bugzilla: 1968509 +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: Dr. David Alan Gilbert +RH-Acked-by: Peter Xu + +Add property that allows zero-copy migration of memory pages +on the sending side, and also includes a helper function +migrate_use_zero_copy_send() to check if it's enabled. + +No code is introduced to actually do the migration, but it allow +future implementations to enable/disable this feature. + +On non-Linux builds this parameter is compiled-out. + +Signed-off-by: Leonardo Bras +Reviewed-by: Peter Xu +Reviewed-by: Daniel P. Berrangé +Reviewed-by: Juan Quintela +Acked-by: Markus Armbruster +Message-Id: <20220513062836.965425-5-leobras@redhat.com> +Signed-off-by: Dr. David Alan Gilbert +(cherry picked from commit abb6295b3ace5d17c3a65936913fc346616dbf14) +Signed-off-by: Leonardo Bras +--- + migration/migration.c | 32 ++++++++++++++++++++++++++++++++ + migration/migration.h | 5 +++++ + migration/socket.c | 11 +++++++++-- + monitor/hmp-cmds.c | 6 ++++++ + qapi/migration.json | 24 ++++++++++++++++++++++++ + 5 files changed, 76 insertions(+), 2 deletions(-) + +diff --git a/migration/migration.c b/migration/migration.c +index 695f0f2900..0a6b3b9f4d 100644 +--- a/migration/migration.c ++++ b/migration/migration.c +@@ -899,6 +899,10 @@ MigrationParameters *qmp_query_migrate_parameters(Error **errp) + params->multifd_zlib_level = s->parameters.multifd_zlib_level; + params->has_multifd_zstd_level = true; + params->multifd_zstd_level = s->parameters.multifd_zstd_level; ++#ifdef CONFIG_LINUX ++ params->has_zero_copy_send = true; ++ params->zero_copy_send = s->parameters.zero_copy_send; ++#endif + params->has_xbzrle_cache_size = true; + params->xbzrle_cache_size = s->parameters.xbzrle_cache_size; + params->has_max_postcopy_bandwidth = true; +@@ -1555,6 +1559,11 @@ static void migrate_params_test_apply(MigrateSetParameters *params, + if (params->has_multifd_compression) { + dest->multifd_compression = params->multifd_compression; + } ++#ifdef CONFIG_LINUX ++ if (params->has_zero_copy_send) { ++ dest->zero_copy_send = params->zero_copy_send; ++ } ++#endif + if (params->has_xbzrle_cache_size) { + dest->xbzrle_cache_size = params->xbzrle_cache_size; + } +@@ -1667,6 +1676,11 @@ static void migrate_params_apply(MigrateSetParameters *params, Error **errp) + if (params->has_multifd_compression) { + s->parameters.multifd_compression = params->multifd_compression; + } ++#ifdef CONFIG_LINUX ++ if (params->has_zero_copy_send) { ++ s->parameters.zero_copy_send = params->zero_copy_send; ++ } ++#endif + if (params->has_xbzrle_cache_size) { + s->parameters.xbzrle_cache_size = params->xbzrle_cache_size; + xbzrle_cache_resize(params->xbzrle_cache_size, errp); +@@ -2557,6 +2571,17 @@ int migrate_multifd_zstd_level(void) + return s->parameters.multifd_zstd_level; + } + ++#ifdef CONFIG_LINUX ++bool migrate_use_zero_copy_send(void) ++{ ++ MigrationState *s; ++ ++ s = migrate_get_current(); ++ ++ return s->parameters.zero_copy_send; ++} ++#endif ++ + int migrate_use_xbzrle(void) + { + MigrationState *s; +@@ -4200,6 +4225,10 @@ static Property migration_properties[] = { + DEFINE_PROP_UINT8("multifd-zstd-level", MigrationState, + parameters.multifd_zstd_level, + DEFAULT_MIGRATE_MULTIFD_ZSTD_LEVEL), ++#ifdef CONFIG_LINUX ++ DEFINE_PROP_BOOL("zero_copy_send", MigrationState, ++ parameters.zero_copy_send, false), ++#endif + DEFINE_PROP_SIZE("xbzrle-cache-size", MigrationState, + parameters.xbzrle_cache_size, + DEFAULT_MIGRATE_XBZRLE_CACHE_SIZE), +@@ -4297,6 +4326,9 @@ static void migration_instance_init(Object *obj) + params->has_multifd_compression = true; + params->has_multifd_zlib_level = true; + params->has_multifd_zstd_level = true; ++#ifdef CONFIG_LINUX ++ params->has_zero_copy_send = true; ++#endif + params->has_xbzrle_cache_size = true; + params->has_max_postcopy_bandwidth = true; + params->has_max_cpu_throttle = true; +diff --git a/migration/migration.h b/migration/migration.h +index 2de861df01..5bcb7628ef 100644 +--- a/migration/migration.h ++++ b/migration/migration.h +@@ -376,6 +376,11 @@ MultiFDCompression migrate_multifd_compression(void); + int migrate_multifd_zlib_level(void); + int migrate_multifd_zstd_level(void); + ++#ifdef CONFIG_LINUX ++bool migrate_use_zero_copy_send(void); ++#else ++#define migrate_use_zero_copy_send() (false) ++#endif + int migrate_use_xbzrle(void); + uint64_t migrate_xbzrle_cache_size(void); + bool migrate_colo_enabled(void); +diff --git a/migration/socket.c b/migration/socket.c +index 05705a32d8..3754d8f72c 100644 +--- a/migration/socket.c ++++ b/migration/socket.c +@@ -74,9 +74,16 @@ static void socket_outgoing_migration(QIOTask *task, + + if (qio_task_propagate_error(task, &err)) { + trace_migration_socket_outgoing_error(error_get_pretty(err)); +- } else { +- trace_migration_socket_outgoing_connected(data->hostname); ++ goto out; + } ++ ++ trace_migration_socket_outgoing_connected(data->hostname); ++ ++ if (migrate_use_zero_copy_send()) { ++ error_setg(&err, "Zero copy send not available in migration"); ++ } ++ ++out: + migration_channel_connect(data->s, sioc, data->hostname, err); + object_unref(OBJECT(sioc)); + } +diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c +index 634968498b..55b48d3733 100644 +--- a/monitor/hmp-cmds.c ++++ b/monitor/hmp-cmds.c +@@ -1309,6 +1309,12 @@ void hmp_migrate_set_parameter(Monitor *mon, const QDict *qdict) + p->has_multifd_zstd_level = true; + visit_type_uint8(v, param, &p->multifd_zstd_level, &err); + break; ++#ifdef CONFIG_LINUX ++ case MIGRATION_PARAMETER_ZERO_COPY_SEND: ++ p->has_zero_copy_send = true; ++ visit_type_bool(v, param, &p->zero_copy_send, &err); ++ break; ++#endif + case MIGRATION_PARAMETER_XBZRLE_CACHE_SIZE: + p->has_xbzrle_cache_size = true; + if (!visit_type_size(v, param, &cache_size, &err)) { +diff --git a/qapi/migration.json b/qapi/migration.json +index 27d7b28158..4d833ecdd6 100644 +--- a/qapi/migration.json ++++ b/qapi/migration.json +@@ -741,6 +741,13 @@ + # will consume more CPU. + # Defaults to 1. (Since 5.0) + # ++# @zero-copy-send: Controls behavior on sending memory pages on migration. ++# When true, enables a zero-copy mechanism for sending ++# memory pages, if host supports it. ++# Requires that QEMU be permitted to use locked memory ++# for guest RAM pages. ++# Defaults to false. (Since 7.1) ++# + # @block-bitmap-mapping: Maps block nodes and bitmaps on them to + # aliases for the purpose of dirty bitmap migration. Such + # aliases may for example be the corresponding names on the +@@ -780,6 +787,7 @@ + 'xbzrle-cache-size', 'max-postcopy-bandwidth', + 'max-cpu-throttle', 'multifd-compression', + 'multifd-zlib-level' ,'multifd-zstd-level', ++ { 'name': 'zero-copy-send', 'if' : 'CONFIG_LINUX'}, + 'block-bitmap-mapping' ] } + + ## +@@ -906,6 +914,13 @@ + # will consume more CPU. + # Defaults to 1. (Since 5.0) + # ++# @zero-copy-send: Controls behavior on sending memory pages on migration. ++# When true, enables a zero-copy mechanism for sending ++# memory pages, if host supports it. ++# Requires that QEMU be permitted to use locked memory ++# for guest RAM pages. ++# Defaults to false. (Since 7.1) ++# + # @block-bitmap-mapping: Maps block nodes and bitmaps on them to + # aliases for the purpose of dirty bitmap migration. Such + # aliases may for example be the corresponding names on the +@@ -960,6 +975,7 @@ + '*multifd-compression': 'MultiFDCompression', + '*multifd-zlib-level': 'uint8', + '*multifd-zstd-level': 'uint8', ++ '*zero-copy-send': { 'type': 'bool', 'if': 'CONFIG_LINUX' }, + '*block-bitmap-mapping': [ 'BitmapMigrationNodeAlias' ] } } + + ## +@@ -1106,6 +1122,13 @@ + # will consume more CPU. + # Defaults to 1. (Since 5.0) + # ++# @zero-copy-send: Controls behavior on sending memory pages on migration. ++# When true, enables a zero-copy mechanism for sending ++# memory pages, if host supports it. ++# Requires that QEMU be permitted to use locked memory ++# for guest RAM pages. ++# Defaults to false. (Since 7.1) ++# + # @block-bitmap-mapping: Maps block nodes and bitmaps on them to + # aliases for the purpose of dirty bitmap migration. Such + # aliases may for example be the corresponding names on the +@@ -1158,6 +1181,7 @@ + '*multifd-compression': 'MultiFDCompression', + '*multifd-zlib-level': 'uint8', + '*multifd-zstd-level': 'uint8', ++ '*zero-copy-send': { 'type': 'bool', 'if': 'CONFIG_LINUX' }, + '*block-bitmap-mapping': [ 'BitmapMigrationNodeAlias' ] } } + + ## +-- +2.35.3 + diff --git a/kvm-migration-Allow-migrate-recover-to-run-multiple-time.patch b/kvm-migration-Allow-migrate-recover-to-run-multiple-time.patch new file mode 100644 index 0000000..29dc0ea --- /dev/null +++ b/kvm-migration-Allow-migrate-recover-to-run-multiple-time.patch @@ -0,0 +1,98 @@ +From fd6f516a94e635bc42e58448f314db575814a834 Mon Sep 17 00:00:00 2001 +From: Peter Xu +Date: Thu, 31 Mar 2022 11:08:45 -0400 +Subject: [PATCH 18/18] migration: Allow migrate-recover to run multiple times +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Peter Xu +RH-MergeRequest: 104: migration: Allow migrate-recover to run multiple times +RH-Commit: [1/1] afd726e54c069ae800e2d01f34e768d6bac7dcb9 (peterx/qemu-kvm) +RH-Bugzilla: 2096143 +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: Hanna Reitz +RH-Acked-by: Dr. David Alan Gilbert + +Previously migration didn't have an easy way to cleanup the listening +transport, migrate recovery only allows to execute once. That's done with a +trick flag in postcopy_recover_triggered. + +Now the facility is already there. + +Drop postcopy_recover_triggered and instead allows a new migrate-recover to +release the previous listener transport. + +Reviewed-by: Dr. David Alan Gilbert +Signed-off-by: Peter Xu +Message-Id: <20220331150857.74406-8-peterx@redhat.com> +Reviewed-by: Daniel P. Berrangé +Signed-off-by: Dr. David Alan Gilbert +(cherry picked from commit 08401c0426bc1a5ce4609afd1cda5dd39abbf9fa) +Signed-off-by: Peter Xu +--- + migration/migration.c | 13 ++----------- + migration/migration.h | 1 - + migration/savevm.c | 3 --- + 3 files changed, 2 insertions(+), 15 deletions(-) + +diff --git a/migration/migration.c b/migration/migration.c +index 2a141bfaf3..8fb3eae910 100644 +--- a/migration/migration.c ++++ b/migration/migration.c +@@ -2166,11 +2166,8 @@ void qmp_migrate_recover(const char *uri, Error **errp) + return; + } + +- if (qatomic_cmpxchg(&mis->postcopy_recover_triggered, +- false, true) == true) { +- error_setg(errp, "Migrate recovery is triggered already"); +- return; +- } ++ /* If there's an existing transport, release it */ ++ migration_incoming_transport_cleanup(mis); + + /* + * Note that this call will never start a real migration; it will +@@ -2178,12 +2175,6 @@ void qmp_migrate_recover(const char *uri, Error **errp) + * to continue using that newly established channel. + */ + qemu_start_incoming_migration(uri, errp); +- +- /* Safe to dereference with the assert above */ +- if (*errp) { +- /* Reset the flag so user could still retry */ +- qatomic_set(&mis->postcopy_recover_triggered, false); +- } + } + + void qmp_migrate_pause(Error **errp) +diff --git a/migration/migration.h b/migration/migration.h +index c2cabb8a14..fbc8690ec8 100644 +--- a/migration/migration.h ++++ b/migration/migration.h +@@ -139,7 +139,6 @@ struct MigrationIncomingState { + struct PostcopyBlocktimeContext *blocktime_ctx; + + /* notify PAUSED postcopy incoming migrations to try to continue */ +- bool postcopy_recover_triggered; + QemuSemaphore postcopy_pause_sem_dst; + QemuSemaphore postcopy_pause_sem_fault; + +diff --git a/migration/savevm.c b/migration/savevm.c +index 02ed94c180..d9076897b8 100644 +--- a/migration/savevm.c ++++ b/migration/savevm.c +@@ -2589,9 +2589,6 @@ static bool postcopy_pause_incoming(MigrationIncomingState *mis) + + assert(migrate_postcopy_ram()); + +- /* Clear the triggered bit to allow one recovery */ +- mis->postcopy_recover_triggered = false; +- + /* + * Unregister yank with either from/to src would work, since ioc behind it + * is the same +-- +2.35.3 + diff --git a/kvm-migration-Change-zero_copy_send-from-migration-param.patch b/kvm-migration-Change-zero_copy_send-from-migration-param.patch new file mode 100644 index 0000000..abeeeb6 --- /dev/null +++ b/kvm-migration-Change-zero_copy_send-from-migration-param.patch @@ -0,0 +1,289 @@ +From 7e2a037f3f349c21201152cecce32d8c8ff0bea0 Mon Sep 17 00:00:00 2001 +From: Leonardo Bras +Date: Mon, 20 Jun 2022 02:39:45 -0300 +Subject: [PATCH 17/18] migration: Change zero_copy_send from migration + parameter to migration capability +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Leonardo Brás +RH-MergeRequest: 95: MSG_ZEROCOPY + Multifd +RH-Commit: [11/11] e4a955607947896a49398ac8400241a0adac51a1 (LeoBras/centos-qemu-kvm) +RH-Bugzilla: 1968509 +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: Dr. David Alan Gilbert +RH-Acked-by: Peter Xu + +When originally implemented, zero_copy_send was designed as a Migration +paramenter. + +But taking into account how is that supposed to work, and how +the difference between a capability and a parameter, it only makes sense +that zero-copy-send would work better as a capability. + +Taking into account how recently the change got merged, it was decided +that it's still time to make it right, and convert zero_copy_send into +a Migration capability. + +Signed-off-by: Leonardo Bras +Reviewed-by: Juan Quintela +Acked-by: Markus Armbruster +Acked-by: Peter Xu +Signed-off-by: Juan Quintela +Signed-off-by: Dr. David Alan Gilbert + dgilbert: always define the capability, even on non-Linux but error if +set; avoids build problems with the capability +(cherry picked from commit 1abaec9a1b2c23f7aa94709a422128d9e42c3e0b) +Signed-off-by: Leonardo Bras +--- + migration/migration.c | 58 +++++++++++++++++++------------------------ + monitor/hmp-cmds.c | 6 ----- + qapi/migration.json | 33 +++++++----------------- + 3 files changed, 34 insertions(+), 63 deletions(-) + +diff --git a/migration/migration.c b/migration/migration.c +index 102236fba0..2a141bfaf3 100644 +--- a/migration/migration.c ++++ b/migration/migration.c +@@ -163,7 +163,8 @@ INITIALIZE_MIGRATE_CAPS_SET(check_caps_background_snapshot, + MIGRATION_CAPABILITY_COMPRESS, + MIGRATION_CAPABILITY_XBZRLE, + MIGRATION_CAPABILITY_X_COLO, +- MIGRATION_CAPABILITY_VALIDATE_UUID); ++ MIGRATION_CAPABILITY_VALIDATE_UUID, ++ MIGRATION_CAPABILITY_ZERO_COPY_SEND); + + /* When we add fault tolerance, we could have several + migrations at once. For now we don't need to add +@@ -899,10 +900,6 @@ MigrationParameters *qmp_query_migrate_parameters(Error **errp) + params->multifd_zlib_level = s->parameters.multifd_zlib_level; + params->has_multifd_zstd_level = true; + params->multifd_zstd_level = s->parameters.multifd_zstd_level; +-#ifdef CONFIG_LINUX +- params->has_zero_copy_send = true; +- params->zero_copy_send = s->parameters.zero_copy_send; +-#endif + params->has_xbzrle_cache_size = true; + params->xbzrle_cache_size = s->parameters.xbzrle_cache_size; + params->has_max_postcopy_bandwidth = true; +@@ -1263,6 +1260,24 @@ static bool migrate_caps_check(bool *cap_list, + } + } + ++#ifdef CONFIG_LINUX ++ if (cap_list[MIGRATION_CAPABILITY_ZERO_COPY_SEND] && ++ (!cap_list[MIGRATION_CAPABILITY_MULTIFD] || ++ migrate_use_compression() || ++ migrate_use_tls())) { ++ error_setg(errp, ++ "Zero copy only available for non-compressed non-TLS multifd migration"); ++ return false; ++ } ++#else ++ if (cap_list[MIGRATION_CAPABILITY_ZERO_COPY_SEND]) { ++ error_setg(errp, ++ "Zero copy currently only available on Linux"); ++ return false; ++ } ++#endif ++ ++ + /* incoming side only */ + if (runstate_check(RUN_STATE_INMIGRATE) && + !migrate_multifd_is_allowed() && +@@ -1485,16 +1500,6 @@ static bool migrate_params_check(MigrationParameters *params, Error **errp) + error_prepend(errp, "Invalid mapping given for block-bitmap-mapping: "); + return false; + } +-#ifdef CONFIG_LINUX +- if (params->zero_copy_send && +- (!migrate_use_multifd() || +- params->multifd_compression != MULTIFD_COMPRESSION_NONE || +- (params->tls_creds && *params->tls_creds))) { +- error_setg(errp, +- "Zero copy only available for non-compressed non-TLS multifd migration"); +- return false; +- } +-#endif + return true; + } + +@@ -1568,11 +1573,6 @@ static void migrate_params_test_apply(MigrateSetParameters *params, + if (params->has_multifd_compression) { + dest->multifd_compression = params->multifd_compression; + } +-#ifdef CONFIG_LINUX +- if (params->has_zero_copy_send) { +- dest->zero_copy_send = params->zero_copy_send; +- } +-#endif + if (params->has_xbzrle_cache_size) { + dest->xbzrle_cache_size = params->xbzrle_cache_size; + } +@@ -1685,11 +1685,6 @@ static void migrate_params_apply(MigrateSetParameters *params, Error **errp) + if (params->has_multifd_compression) { + s->parameters.multifd_compression = params->multifd_compression; + } +-#ifdef CONFIG_LINUX +- if (params->has_zero_copy_send) { +- s->parameters.zero_copy_send = params->zero_copy_send; +- } +-#endif + if (params->has_xbzrle_cache_size) { + s->parameters.xbzrle_cache_size = params->xbzrle_cache_size; + xbzrle_cache_resize(params->xbzrle_cache_size, errp); +@@ -2587,7 +2582,7 @@ bool migrate_use_zero_copy_send(void) + + s = migrate_get_current(); + +- return s->parameters.zero_copy_send; ++ return s->enabled_capabilities[MIGRATION_CAPABILITY_ZERO_COPY_SEND]; + } + #endif + +@@ -4243,10 +4238,6 @@ static Property migration_properties[] = { + DEFINE_PROP_UINT8("multifd-zstd-level", MigrationState, + parameters.multifd_zstd_level, + DEFAULT_MIGRATE_MULTIFD_ZSTD_LEVEL), +-#ifdef CONFIG_LINUX +- DEFINE_PROP_BOOL("zero_copy_send", MigrationState, +- parameters.zero_copy_send, false), +-#endif + DEFINE_PROP_SIZE("xbzrle-cache-size", MigrationState, + parameters.xbzrle_cache_size, + DEFAULT_MIGRATE_XBZRLE_CACHE_SIZE), +@@ -4284,6 +4275,10 @@ static Property migration_properties[] = { + DEFINE_PROP_MIG_CAP("x-multifd", MIGRATION_CAPABILITY_MULTIFD), + DEFINE_PROP_MIG_CAP("x-background-snapshot", + MIGRATION_CAPABILITY_BACKGROUND_SNAPSHOT), ++#ifdef CONFIG_LINUX ++ DEFINE_PROP_MIG_CAP("x-zero-copy-send", ++ MIGRATION_CAPABILITY_ZERO_COPY_SEND), ++#endif + + DEFINE_PROP_END_OF_LIST(), + }; +@@ -4344,9 +4339,6 @@ static void migration_instance_init(Object *obj) + params->has_multifd_compression = true; + params->has_multifd_zlib_level = true; + params->has_multifd_zstd_level = true; +-#ifdef CONFIG_LINUX +- params->has_zero_copy_send = true; +-#endif + params->has_xbzrle_cache_size = true; + params->has_max_postcopy_bandwidth = true; + params->has_max_cpu_throttle = true; +diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c +index 55b48d3733..634968498b 100644 +--- a/monitor/hmp-cmds.c ++++ b/monitor/hmp-cmds.c +@@ -1309,12 +1309,6 @@ void hmp_migrate_set_parameter(Monitor *mon, const QDict *qdict) + p->has_multifd_zstd_level = true; + visit_type_uint8(v, param, &p->multifd_zstd_level, &err); + break; +-#ifdef CONFIG_LINUX +- case MIGRATION_PARAMETER_ZERO_COPY_SEND: +- p->has_zero_copy_send = true; +- visit_type_bool(v, param, &p->zero_copy_send, &err); +- break; +-#endif + case MIGRATION_PARAMETER_XBZRLE_CACHE_SIZE: + p->has_xbzrle_cache_size = true; + if (!visit_type_size(v, param, &cache_size, &err)) { +diff --git a/qapi/migration.json b/qapi/migration.json +index 4d833ecdd6..5105790cd0 100644 +--- a/qapi/migration.json ++++ b/qapi/migration.json +@@ -463,6 +463,13 @@ + # procedure starts. The VM RAM is saved with running VM. + # (since 6.0) + # ++# @zero-copy-send: Controls behavior on sending memory pages on migration. ++# When true, enables a zero-copy mechanism for sending ++# memory pages, if host supports it. ++# Requires that QEMU be permitted to use locked memory ++# for guest RAM pages. ++# (since 7.1) ++# + # Features: + # @unstable: Members @x-colo and @x-ignore-shared are experimental. + # +@@ -476,7 +483,8 @@ + 'block', 'return-path', 'pause-before-switchover', 'multifd', + 'dirty-bitmaps', 'postcopy-blocktime', 'late-block-activate', + { 'name': 'x-ignore-shared', 'features': [ 'unstable' ] }, +- 'validate-uuid', 'background-snapshot'] } ++ 'validate-uuid', 'background-snapshot', ++ 'zero-copy-send'] } + + ## + # @MigrationCapabilityStatus: +@@ -741,12 +749,6 @@ + # will consume more CPU. + # Defaults to 1. (Since 5.0) + # +-# @zero-copy-send: Controls behavior on sending memory pages on migration. +-# When true, enables a zero-copy mechanism for sending +-# memory pages, if host supports it. +-# Requires that QEMU be permitted to use locked memory +-# for guest RAM pages. +-# Defaults to false. (Since 7.1) + # + # @block-bitmap-mapping: Maps block nodes and bitmaps on them to + # aliases for the purpose of dirty bitmap migration. Such +@@ -787,7 +789,6 @@ + 'xbzrle-cache-size', 'max-postcopy-bandwidth', + 'max-cpu-throttle', 'multifd-compression', + 'multifd-zlib-level' ,'multifd-zstd-level', +- { 'name': 'zero-copy-send', 'if' : 'CONFIG_LINUX'}, + 'block-bitmap-mapping' ] } + + ## +@@ -914,13 +915,6 @@ + # will consume more CPU. + # Defaults to 1. (Since 5.0) + # +-# @zero-copy-send: Controls behavior on sending memory pages on migration. +-# When true, enables a zero-copy mechanism for sending +-# memory pages, if host supports it. +-# Requires that QEMU be permitted to use locked memory +-# for guest RAM pages. +-# Defaults to false. (Since 7.1) +-# + # @block-bitmap-mapping: Maps block nodes and bitmaps on them to + # aliases for the purpose of dirty bitmap migration. Such + # aliases may for example be the corresponding names on the +@@ -975,7 +969,6 @@ + '*multifd-compression': 'MultiFDCompression', + '*multifd-zlib-level': 'uint8', + '*multifd-zstd-level': 'uint8', +- '*zero-copy-send': { 'type': 'bool', 'if': 'CONFIG_LINUX' }, + '*block-bitmap-mapping': [ 'BitmapMigrationNodeAlias' ] } } + + ## +@@ -1122,13 +1115,6 @@ + # will consume more CPU. + # Defaults to 1. (Since 5.0) + # +-# @zero-copy-send: Controls behavior on sending memory pages on migration. +-# When true, enables a zero-copy mechanism for sending +-# memory pages, if host supports it. +-# Requires that QEMU be permitted to use locked memory +-# for guest RAM pages. +-# Defaults to false. (Since 7.1) +-# + # @block-bitmap-mapping: Maps block nodes and bitmaps on them to + # aliases for the purpose of dirty bitmap migration. Such + # aliases may for example be the corresponding names on the +@@ -1181,7 +1167,6 @@ + '*multifd-compression': 'MultiFDCompression', + '*multifd-zlib-level': 'uint8', + '*multifd-zstd-level': 'uint8', +- '*zero-copy-send': { 'type': 'bool', 'if': 'CONFIG_LINUX' }, + '*block-bitmap-mapping': [ 'BitmapMigrationNodeAlias' ] } } + + ## +-- +2.35.3 + diff --git a/kvm-multifd-Implement-zero-copy-write-in-multifd-migrati.patch b/kvm-multifd-Implement-zero-copy-write-in-multifd-migrati.patch new file mode 100644 index 0000000..c7159e1 --- /dev/null +++ b/kvm-multifd-Implement-zero-copy-write-in-multifd-migrati.patch @@ -0,0 +1,182 @@ +From c1a2866d158ac67179fa0d17f1710302eb9a3866 Mon Sep 17 00:00:00 2001 +From: Leonardo Bras +Date: Fri, 13 May 2022 03:28:37 -0300 +Subject: [PATCH 14/18] multifd: Implement zero copy write in multifd migration + (multifd-zero-copy) +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Leonardo Brás +RH-MergeRequest: 95: MSG_ZEROCOPY + Multifd +RH-Commit: [8/11] b93009cc94b2cc4b464b4f68ebfb37b870dd6f7d (LeoBras/centos-qemu-kvm) +RH-Bugzilla: 1968509 +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: Dr. David Alan Gilbert +RH-Acked-by: Peter Xu + +Implement zero copy send on nocomp_send_write(), by making use of QIOChannel +writev + flags & flush interface. + +Change multifd_send_sync_main() so flush_zero_copy() can be called +after each iteration in order to make sure all dirty pages are sent before +a new iteration is started. It will also flush at the beginning and at the +end of migration. + +Also make it return -1 if flush_zero_copy() fails, in order to cancel +the migration process, and avoid resuming the guest in the target host +without receiving all current RAM. + +This will work fine on RAM migration because the RAM pages are not usually freed, +and there is no problem on changing the pages content between writev_zero_copy() and +the actual sending of the buffer, because this change will dirty the page and +cause it to be re-sent on a next iteration anyway. + +A lot of locked memory may be needed in order to use multifd migration +with zero-copy enabled, so disabling the feature should be necessary for +low-privileged users trying to perform multifd migrations. + +Signed-off-by: Leonardo Bras +Reviewed-by: Peter Xu +Reviewed-by: Daniel P. Berrangé +Message-Id: <20220513062836.965425-9-leobras@redhat.com> +Signed-off-by: Dr. David Alan Gilbert +(cherry picked from commit 5b1d9bab2da4fca3a3caee97c430e5709cb32b7b) +Signed-off-by: Leonardo Bras +--- + migration/migration.c | 11 ++++++++++- + migration/multifd.c | 37 +++++++++++++++++++++++++++++++++++-- + migration/multifd.h | 2 ++ + migration/socket.c | 5 +++-- + 4 files changed, 50 insertions(+), 5 deletions(-) + +diff --git a/migration/migration.c b/migration/migration.c +index d91efb66fe..102236fba0 100644 +--- a/migration/migration.c ++++ b/migration/migration.c +@@ -1485,7 +1485,16 @@ static bool migrate_params_check(MigrationParameters *params, Error **errp) + error_prepend(errp, "Invalid mapping given for block-bitmap-mapping: "); + return false; + } +- ++#ifdef CONFIG_LINUX ++ if (params->zero_copy_send && ++ (!migrate_use_multifd() || ++ params->multifd_compression != MULTIFD_COMPRESSION_NONE || ++ (params->tls_creds && *params->tls_creds))) { ++ error_setg(errp, ++ "Zero copy only available for non-compressed non-TLS multifd migration"); ++ return false; ++ } ++#endif + return true; + } + +diff --git a/migration/multifd.c b/migration/multifd.c +index 8fca6c970e..0b5b41c53f 100644 +--- a/migration/multifd.c ++++ b/migration/multifd.c +@@ -571,6 +571,7 @@ void multifd_save_cleanup(void) + int multifd_send_sync_main(QEMUFile *f) + { + int i; ++ bool flush_zero_copy; + + if (!migrate_use_multifd()) { + return 0; +@@ -581,6 +582,20 @@ int multifd_send_sync_main(QEMUFile *f) + return -1; + } + } ++ ++ /* ++ * When using zero-copy, it's necessary to flush the pages before any of ++ * the pages can be sent again, so we'll make sure the new version of the ++ * pages will always arrive _later_ than the old pages. ++ * ++ * Currently we achieve this by flushing the zero-page requested writes ++ * per ram iteration, but in the future we could potentially optimize it ++ * to be less frequent, e.g. only after we finished one whole scanning of ++ * all the dirty bitmaps. ++ */ ++ ++ flush_zero_copy = migrate_use_zero_copy_send(); ++ + for (i = 0; i < migrate_multifd_channels(); i++) { + MultiFDSendParams *p = &multifd_send_state->params[i]; + +@@ -602,6 +617,17 @@ int multifd_send_sync_main(QEMUFile *f) + ram_counters.transferred += p->packet_len; + qemu_mutex_unlock(&p->mutex); + qemu_sem_post(&p->sem); ++ ++ if (flush_zero_copy && p->c) { ++ int ret; ++ Error *err = NULL; ++ ++ ret = qio_channel_flush(p->c, &err); ++ if (ret < 0) { ++ error_report_err(err); ++ return -1; ++ } ++ } + } + for (i = 0; i < migrate_multifd_channels(); i++) { + MultiFDSendParams *p = &multifd_send_state->params[i]; +@@ -686,8 +712,8 @@ static void *multifd_send_thread(void *opaque) + p->iov[0].iov_base = p->packet; + } + +- ret = qio_channel_writev_all(p->c, p->iov, p->iovs_num, +- &local_err); ++ ret = qio_channel_writev_full_all(p->c, p->iov, p->iovs_num, NULL, ++ 0, p->write_flags, &local_err); + if (ret != 0) { + break; + } +@@ -928,6 +954,13 @@ int multifd_save_setup(Error **errp) + /* We need one extra place for the packet header */ + p->iov = g_new0(struct iovec, page_count + 1); + p->normal = g_new0(ram_addr_t, page_count); ++ ++ if (migrate_use_zero_copy_send()) { ++ p->write_flags = QIO_CHANNEL_WRITE_FLAG_ZERO_COPY; ++ } else { ++ p->write_flags = 0; ++ } ++ + socket_send_channel_create(multifd_new_send_channel_async, p); + } + +diff --git a/migration/multifd.h b/migration/multifd.h +index cd495195ce..7ec688fb4f 100644 +--- a/migration/multifd.h ++++ b/migration/multifd.h +@@ -96,6 +96,8 @@ typedef struct { + uint32_t packet_len; + /* pointer to the packet */ + MultiFDPacket_t *packet; ++ /* multifd flags for sending ram */ ++ int write_flags; + /* multifd flags for each packet */ + uint32_t flags; + /* size of the next packet that contains pages */ +diff --git a/migration/socket.c b/migration/socket.c +index 3754d8f72c..4fd5e85f50 100644 +--- a/migration/socket.c ++++ b/migration/socket.c +@@ -79,8 +79,9 @@ static void socket_outgoing_migration(QIOTask *task, + + trace_migration_socket_outgoing_connected(data->hostname); + +- if (migrate_use_zero_copy_send()) { +- error_setg(&err, "Zero copy send not available in migration"); ++ if (migrate_use_zero_copy_send() && ++ !qio_channel_has_feature(sioc, QIO_CHANNEL_FEATURE_WRITE_ZERO_COPY)) { ++ error_setg(&err, "Zero copy send feature not detected in host kernel"); + } + + out: +-- +2.35.3 + diff --git a/kvm-multifd-Send-header-packet-without-flags-if-zero-cop.patch b/kvm-multifd-Send-header-packet-without-flags-if-zero-cop.patch new file mode 100644 index 0000000..415e3a9 --- /dev/null +++ b/kvm-multifd-Send-header-packet-without-flags-if-zero-cop.patch @@ -0,0 +1,102 @@ +From 63255c13492f42a3236d96e706e5f8e70bb4e219 Mon Sep 17 00:00:00 2001 +From: Leonardo Bras +Date: Fri, 13 May 2022 03:28:36 -0300 +Subject: [PATCH 13/18] multifd: Send header packet without flags if + zero-copy-send is enabled +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Leonardo Brás +RH-MergeRequest: 95: MSG_ZEROCOPY + Multifd +RH-Commit: [7/11] 137eea685e387d3d6aff187ec3fcac05bc16b6e3 (LeoBras/centos-qemu-kvm) +RH-Bugzilla: 1968509 +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: Dr. David Alan Gilbert +RH-Acked-by: Peter Xu + +Since d48c3a0445 ("multifd: Use a single writev on the send side"), +sending the header packet and the memory pages happens in the same +writev, which can potentially make the migration faster. + +Using channel-socket as example, this works well with the default copying +mechanism of sendmsg(), but with zero-copy-send=true, it will cause +the migration to often break. + +This happens because the header packet buffer gets reused quite often, +and there is a high chance that by the time the MSG_ZEROCOPY mechanism get +to send the buffer, it has already changed, sending the wrong data and +causing the migration to abort. + +It means that, as it is, the buffer for the header packet is not suitable +for sending with MSG_ZEROCOPY. + +In order to enable zero copy for multifd, send the header packet on an +individual write(), without any flags, and the remanining pages with a +writev(), as it was happening before. This only changes how a migration +with zero-copy-send=true works, not changing any current behavior for +migrations with zero-copy-send=false. + +Signed-off-by: Leonardo Bras +Reviewed-by: Peter Xu +Reviewed-by: Daniel P. Berrangé +Message-Id: <20220513062836.965425-8-leobras@redhat.com> +Signed-off-by: Dr. David Alan Gilbert +(cherry picked from commit b7dbdd8e76cd03453c234dbb9578d20969859d74) +Signed-off-by: Leonardo Bras +--- + migration/multifd.c | 22 +++++++++++++++++++--- + 1 file changed, 19 insertions(+), 3 deletions(-) + +diff --git a/migration/multifd.c b/migration/multifd.c +index cdb57439a7..8fca6c970e 100644 +--- a/migration/multifd.c ++++ b/migration/multifd.c +@@ -619,6 +619,7 @@ static void *multifd_send_thread(void *opaque) + MultiFDSendParams *p = opaque; + Error *local_err = NULL; + int ret = 0; ++ bool use_zero_copy_send = migrate_use_zero_copy_send(); + + trace_multifd_send_thread_start(p->id); + rcu_register_thread(); +@@ -641,9 +642,14 @@ static void *multifd_send_thread(void *opaque) + if (p->pending_job) { + uint64_t packet_num = p->packet_num; + uint32_t flags = p->flags; +- p->iovs_num = 1; + p->normal_num = 0; + ++ if (use_zero_copy_send) { ++ p->iovs_num = 0; ++ } else { ++ p->iovs_num = 1; ++ } ++ + for (int i = 0; i < p->pages->num; i++) { + p->normal[p->normal_num] = p->pages->offset[i]; + p->normal_num++; +@@ -667,8 +673,18 @@ static void *multifd_send_thread(void *opaque) + trace_multifd_send(p->id, packet_num, p->normal_num, flags, + p->next_packet_size); + +- p->iov[0].iov_len = p->packet_len; +- p->iov[0].iov_base = p->packet; ++ if (use_zero_copy_send) { ++ /* Send header first, without zerocopy */ ++ ret = qio_channel_write_all(p->c, (void *)p->packet, ++ p->packet_len, &local_err); ++ if (ret != 0) { ++ break; ++ } ++ } else { ++ /* Send header using the same writev call */ ++ p->iov[0].iov_len = p->packet_len; ++ p->iov[0].iov_base = p->packet; ++ } + + ret = qio_channel_writev_all(p->c, p->iov, p->iovs_num, + &local_err); +-- +2.35.3 + diff --git a/kvm-multifd-multifd_send_sync_main-now-returns-negative-.patch b/kvm-multifd-multifd_send_sync_main-now-returns-negative-.patch new file mode 100644 index 0000000..e6d726a --- /dev/null +++ b/kvm-multifd-multifd_send_sync_main-now-returns-negative-.patch @@ -0,0 +1,163 @@ +From 4ca5375a936bc87829c6e2b4620f56c73a5efc70 Mon Sep 17 00:00:00 2001 +From: Leonardo Bras +Date: Fri, 13 May 2022 03:28:35 -0300 +Subject: [PATCH 12/18] multifd: multifd_send_sync_main now returns negative on + error +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Leonardo Brás +RH-MergeRequest: 95: MSG_ZEROCOPY + Multifd +RH-Commit: [6/11] c8ebdee4327d463c74f4b2eeb42d3c964f314c94 (LeoBras/centos-qemu-kvm) +RH-Bugzilla: 1968509 +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: Dr. David Alan Gilbert +RH-Acked-by: Peter Xu + +Even though multifd_send_sync_main() currently emits error_reports, it's +callers don't really check it before continuing. + +Change multifd_send_sync_main() to return -1 on error and 0 on success. +Also change all it's callers to make use of this change and possibly fail +earlier. + +(This change is important to next patch on multifd zero copy +implementation, to make it sure an error in zero-copy flush does not go +unnoticed. + +Signed-off-by: Leonardo Bras +Reviewed-by: Daniel P. Berrangé +Reviewed-by: Peter Xu +Message-Id: <20220513062836.965425-7-leobras@redhat.com> +Signed-off-by: Dr. David Alan Gilbert +(cherry picked from commit 33d70973a3a6e8c6b62bcbc64d9e488961981007) +Signed-off-by: Leonardo Bras +--- + migration/multifd.c | 10 ++++++---- + migration/multifd.h | 2 +- + migration/ram.c | 29 ++++++++++++++++++++++------- + 3 files changed, 29 insertions(+), 12 deletions(-) + +diff --git a/migration/multifd.c b/migration/multifd.c +index 43998ad117..cdb57439a7 100644 +--- a/migration/multifd.c ++++ b/migration/multifd.c +@@ -568,17 +568,17 @@ void multifd_save_cleanup(void) + multifd_send_state = NULL; + } + +-void multifd_send_sync_main(QEMUFile *f) ++int multifd_send_sync_main(QEMUFile *f) + { + int i; + + if (!migrate_use_multifd()) { +- return; ++ return 0; + } + if (multifd_send_state->pages->num) { + if (multifd_send_pages(f) < 0) { + error_report("%s: multifd_send_pages fail", __func__); +- return; ++ return -1; + } + } + for (i = 0; i < migrate_multifd_channels(); i++) { +@@ -591,7 +591,7 @@ void multifd_send_sync_main(QEMUFile *f) + if (p->quit) { + error_report("%s: channel %d has already quit", __func__, i); + qemu_mutex_unlock(&p->mutex); +- return; ++ return -1; + } + + p->packet_num = multifd_send_state->packet_num++; +@@ -610,6 +610,8 @@ void multifd_send_sync_main(QEMUFile *f) + qemu_sem_wait(&p->sem_sync); + } + trace_multifd_send_sync_main(multifd_send_state->packet_num); ++ ++ return 0; + } + + static void *multifd_send_thread(void *opaque) +diff --git a/migration/multifd.h b/migration/multifd.h +index 4dda900a0b..cd495195ce 100644 +--- a/migration/multifd.h ++++ b/migration/multifd.h +@@ -22,7 +22,7 @@ int multifd_load_cleanup(Error **errp); + bool multifd_recv_all_channels_created(void); + bool multifd_recv_new_channel(QIOChannel *ioc, Error **errp); + void multifd_recv_sync_main(void); +-void multifd_send_sync_main(QEMUFile *f); ++int multifd_send_sync_main(QEMUFile *f); + int multifd_queue_page(QEMUFile *f, RAMBlock *block, ram_addr_t offset); + + /* Multifd Compression flags */ +diff --git a/migration/ram.c b/migration/ram.c +index 0ef4bd63eb..fb6db54642 100644 +--- a/migration/ram.c ++++ b/migration/ram.c +@@ -2903,6 +2903,7 @@ static int ram_save_setup(QEMUFile *f, void *opaque) + { + RAMState **rsp = opaque; + RAMBlock *block; ++ int ret; + + if (compress_threads_save_setup()) { + return -1; +@@ -2937,7 +2938,11 @@ static int ram_save_setup(QEMUFile *f, void *opaque) + ram_control_before_iterate(f, RAM_CONTROL_SETUP); + ram_control_after_iterate(f, RAM_CONTROL_SETUP); + +- multifd_send_sync_main(f); ++ ret = multifd_send_sync_main(f); ++ if (ret < 0) { ++ return ret; ++ } ++ + qemu_put_be64(f, RAM_SAVE_FLAG_EOS); + qemu_fflush(f); + +@@ -3046,7 +3051,11 @@ static int ram_save_iterate(QEMUFile *f, void *opaque) + out: + if (ret >= 0 + && migration_is_setup_or_active(migrate_get_current()->state)) { +- multifd_send_sync_main(rs->f); ++ ret = multifd_send_sync_main(rs->f); ++ if (ret < 0) { ++ return ret; ++ } ++ + qemu_put_be64(f, RAM_SAVE_FLAG_EOS); + qemu_fflush(f); + ram_transferred_add(8); +@@ -3106,13 +3115,19 @@ static int ram_save_complete(QEMUFile *f, void *opaque) + ram_control_after_iterate(f, RAM_CONTROL_FINISH); + } + +- if (ret >= 0) { +- multifd_send_sync_main(rs->f); +- qemu_put_be64(f, RAM_SAVE_FLAG_EOS); +- qemu_fflush(f); ++ if (ret < 0) { ++ return ret; + } + +- return ret; ++ ret = multifd_send_sync_main(rs->f); ++ if (ret < 0) { ++ return ret; ++ } ++ ++ qemu_put_be64(f, RAM_SAVE_FLAG_EOS); ++ qemu_fflush(f); ++ ++ return 0; + } + + static void ram_save_pending(QEMUFile *f, void *opaque, uint64_t max_size, +-- +2.35.3 + diff --git a/kvm-target-arm-deprecate-named-CPU-models.patch b/kvm-target-arm-deprecate-named-CPU-models.patch new file mode 100644 index 0000000..dbe8d24 --- /dev/null +++ b/kvm-target-arm-deprecate-named-CPU-models.patch @@ -0,0 +1,129 @@ +From 1f8528b71d96c01dd6106f11681f4a4e2776ef5f Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= +Date: Mon, 21 Mar 2022 12:05:42 +0000 +Subject: [PATCH 06/18] target/arm: deprecate named CPU models +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Daniel P. Berrangé +RH-MergeRequest: 94: i386, aarch64, s390x: deprecate many named CPU models +RH-Commit: [6/6] afddeb9e898206fd04499f01c48caf7dc1a8b8ef (berrange/centos-src-qemu) +RH-Bugzilla: 2060839 +RH-Acked-by: Thomas Huth +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: Cornelia Huck + +KVM requires use of the 'host' CPU model, so named CPU models are only +needed for TCG. Since we don't consider TCG to be supported we can +deprecate all the named CPU models. TCG users can rely on 'max' model. + +Note: this has the effect of deprecating the default built-in CPU +model 'cortex-a57'. Applications using QEMU are expected to make an +explicit choice about which CPU model they want, since no builtin +default can suit all purposes. + +https://bugzilla.redhat.com/show_bug.cgi?id=2060839 +Signed-off-by: Daniel P. Berrangé +--- + target/arm/cpu-qom.h | 1 + + target/arm/cpu.c | 5 +++++ + target/arm/cpu.h | 2 ++ + target/arm/cpu64.c | 8 +++++++- + target/arm/helper.c | 2 ++ + 5 files changed, 17 insertions(+), 1 deletion(-) + +diff --git a/target/arm/cpu-qom.h b/target/arm/cpu-qom.h +index 64c44cef2d..82e97249bc 100644 +--- a/target/arm/cpu-qom.h ++++ b/target/arm/cpu-qom.h +@@ -35,6 +35,7 @@ typedef struct ARMCPUInfo { + const char *name; + void (*initfn)(Object *obj); + void (*class_init)(ObjectClass *oc, void *data); ++ const char *deprecation_note; + } ARMCPUInfo; + + void arm_cpu_register(const ARMCPUInfo *info); +diff --git a/target/arm/cpu.c b/target/arm/cpu.c +index 5d4ca7a227..c74b0fb462 100644 +--- a/target/arm/cpu.c ++++ b/target/arm/cpu.c +@@ -2105,8 +2105,13 @@ static void arm_cpu_instance_init(Object *obj) + static void cpu_register_class_init(ObjectClass *oc, void *data) + { + ARMCPUClass *acc = ARM_CPU_CLASS(oc); ++ CPUClass *cc = CPU_CLASS(oc); + + acc->info = data; ++ ++ if (acc->info->deprecation_note) { ++ cc->deprecation_note = acc->info->deprecation_note; ++ } + } + + void arm_cpu_register(const ARMCPUInfo *info) +diff --git a/target/arm/cpu.h b/target/arm/cpu.h +index 23879de5fa..c0c9f680e5 100644 +--- a/target/arm/cpu.h ++++ b/target/arm/cpu.h +@@ -33,6 +33,8 @@ + #define KVM_HAVE_MCE_INJECTION 1 + #endif + ++#define RHEL_CPU_DEPRECATION "use 'host' / 'max'" ++ + #define EXCP_UDEF 1 /* undefined instruction */ + #define EXCP_SWI 2 /* software interrupt */ + #define EXCP_PREFETCH_ABORT 3 +diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c +index e80b831073..c8f152891c 100644 +--- a/target/arm/cpu64.c ++++ b/target/arm/cpu64.c +@@ -975,7 +975,8 @@ static void aarch64_a64fx_initfn(Object *obj) + #endif /* disabled for RHEL */ + + static const ARMCPUInfo aarch64_cpus[] = { +- { .name = "cortex-a57", .initfn = aarch64_a57_initfn }, ++ { .name = "cortex-a57", .initfn = aarch64_a57_initfn, ++ .deprecation_note = RHEL_CPU_DEPRECATION }, + #if 0 /* Disabled for Red Hat Enterprise Linux */ + { .name = "cortex-a53", .initfn = aarch64_a53_initfn }, + { .name = "cortex-a72", .initfn = aarch64_a72_initfn }, +@@ -1052,8 +1053,13 @@ static void aarch64_cpu_instance_init(Object *obj) + static void cpu_register_class_init(ObjectClass *oc, void *data) + { + ARMCPUClass *acc = ARM_CPU_CLASS(oc); ++ CPUClass *cc = CPU_CLASS(oc); + + acc->info = data; ++ ++ if (acc->info->deprecation_note) { ++ cc->deprecation_note = acc->info->deprecation_note; ++ } + } + + void aarch64_cpu_register(const ARMCPUInfo *info) +diff --git a/target/arm/helper.c b/target/arm/helper.c +index 7d14650615..3d34f63e49 100644 +--- a/target/arm/helper.c ++++ b/target/arm/helper.c +@@ -8560,6 +8560,7 @@ void arm_cpu_list(void) + static void arm_cpu_add_definition(gpointer data, gpointer user_data) + { + ObjectClass *oc = data; ++ CPUClass *cc = CPU_CLASS(oc); + CpuDefinitionInfoList **cpu_list = user_data; + CpuDefinitionInfo *info; + const char *typename; +@@ -8569,6 +8570,7 @@ static void arm_cpu_add_definition(gpointer data, gpointer user_data) + info->name = g_strndup(typename, + strlen(typename) - strlen("-" TYPE_ARM_CPU)); + info->q_typename = g_strdup(typename); ++ info->deprecated = !!cc->deprecation_note; + + QAPI_LIST_PREPEND(*cpu_list, info); + } +-- +2.35.3 + diff --git a/kvm-target-i386-deprecate-CPUs-older-than-x86_64-v2-ABI.patch b/kvm-target-i386-deprecate-CPUs-older-than-x86_64-v2-ABI.patch new file mode 100644 index 0000000..d63bfdb --- /dev/null +++ b/kvm-target-i386-deprecate-CPUs-older-than-x86_64-v2-ABI.patch @@ -0,0 +1,273 @@ +From 577b04770e47aed0f88acb4a415ed04ddbe087f1 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= +Date: Thu, 17 Mar 2022 17:59:22 +0000 +Subject: [PATCH 04/18] target/i386: deprecate CPUs older than x86_64-v2 ABI +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Daniel P. Berrangé +RH-MergeRequest: 94: i386, aarch64, s390x: deprecate many named CPU models +RH-Commit: [4/6] 71f6043f11b31ffa841a2e14d24972e571c18a9e (berrange/centos-src-qemu) +RH-Bugzilla: 2060839 +RH-Acked-by: Thomas Huth +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: Cornelia Huck + +RHEL-9 is compiled with the x86_64-v2 ABI. We use this as a baseline to +select which CPUs we want to support, such that there is at least one +supported guest CPU that can be launched for every physical machine +capable of running RHEL-9 KVM. + +Supported CPUs: + + * QEMU models + + base (QEMU internal) + host (host passthrough) + max (host passthrough for KVM, + all emulated features for TCG) + + * Intel models + + Icelake-Server + Icelake-Server-noTSX + Cascadelake-Server (2019) + Cascadelake-Server-noTSX (2019) + Skylake-Server (2016) + Skylake-Server-IBRS (2016) + Skylake-Server-noTSX-IBRS (2016) + Skylake-Client (2015) + Skylake-Client-IBRS (2015) + Skylake-Client-noTSX-IBRS (2015) + Broadwell (2014) + Broadwell-IBRS (2014) + Broadwell-noTSX (2014) + Broadwell-noTSX-IBRS (2014) + Haswell (2013) + Haswell-IBRS (2013) + Haswell-noTSX (2013) + Haswell-noTSX-IBRS (2013) + IvyBridge (2012) + IvyBridge-IBRS (2012) + SandyBridge (2011) + SandyBridge-IBRS (2011) + Westmere (2010) + Westmere-IBRS (2010) + Nehalem (2008) + Nehalem-IBRS (2008) + + Cooperlake (2020) + Snowridge (2019) + KnightsMill (2017) + Denverton (2016) + + * AMD models + + EPYC-Milan (2021) + EPYC-Rome (2019) + EPYC (2017) + EPYC-IBPB (2017) + Opteron_G5 (2012) + Opteron_G4 (2011) + + * Other + + Dhyana (2018) + +(I've omitted the many -vNNN versions for brevity) + +Deprecated CPUs: + + 486 + athlon + Conroe + core2duo + coreduo + Icelake-Client (already deprecated upstream) + Icelake-Client-noTSX (already deprecated upstream) + kvm32 + kvm64 + n270 + Opteron_G1 + Opteron_G2 + Opteron_G3 + Penryn + pentium2 + pentium3 + pentium + phenom + qemu32 + qemu64 + +The deprecated CPU models are subject to removal in a future +major version of RHEL. + +Note: this has the effect of deprecating the default built-in CPU +model 'qemu64'. Applications using QEMU are expected to make an +explicit choice about which CPU model they want, since no builtin +default can suit all purposes. + +https://bugzilla.redhat.com/show_bug.cgi?id=2060839 +Signed-off-by: Daniel P. Berrangé +--- + target/i386/cpu.c | 21 +++++++++++++++++++++ + 1 file changed, 21 insertions(+) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index cb6b5467d0..87cb641b5f 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -1780,9 +1780,13 @@ static const CPUCaches epyc_milan_cache_info = { + * PT in VMX operation + */ + ++#define RHEL_CPU_DEPRECATION \ ++ "use at least 'Nehalem' / 'Opteron_G4', or 'host' / 'max'" ++ + static const X86CPUDefinition builtin_x86_defs[] = { + { + .name = "qemu64", ++ .deprecation_note = RHEL_CPU_DEPRECATION, + .level = 0xd, + .vendor = CPUID_VENDOR_AMD, + .family = 15, +@@ -1803,6 +1807,7 @@ static const X86CPUDefinition builtin_x86_defs[] = { + }, + { + .name = "phenom", ++ .deprecation_note = RHEL_CPU_DEPRECATION, + .level = 5, + .vendor = CPUID_VENDOR_AMD, + .family = 16, +@@ -1835,6 +1840,7 @@ static const X86CPUDefinition builtin_x86_defs[] = { + }, + { + .name = "core2duo", ++ .deprecation_note = RHEL_CPU_DEPRECATION, + .level = 10, + .vendor = CPUID_VENDOR_INTEL, + .family = 6, +@@ -1877,6 +1883,7 @@ static const X86CPUDefinition builtin_x86_defs[] = { + }, + { + .name = "kvm64", ++ .deprecation_note = RHEL_CPU_DEPRECATION, + .level = 0xd, + .vendor = CPUID_VENDOR_INTEL, + .family = 15, +@@ -1918,6 +1925,7 @@ static const X86CPUDefinition builtin_x86_defs[] = { + }, + { + .name = "qemu32", ++ .deprecation_note = RHEL_CPU_DEPRECATION, + .level = 4, + .vendor = CPUID_VENDOR_INTEL, + .family = 6, +@@ -1932,6 +1940,7 @@ static const X86CPUDefinition builtin_x86_defs[] = { + }, + { + .name = "kvm32", ++ .deprecation_note = RHEL_CPU_DEPRECATION, + .level = 5, + .vendor = CPUID_VENDOR_INTEL, + .family = 15, +@@ -1962,6 +1971,7 @@ static const X86CPUDefinition builtin_x86_defs[] = { + }, + { + .name = "coreduo", ++ .deprecation_note = RHEL_CPU_DEPRECATION, + .level = 10, + .vendor = CPUID_VENDOR_INTEL, + .family = 6, +@@ -1995,6 +2005,7 @@ static const X86CPUDefinition builtin_x86_defs[] = { + }, + { + .name = "486", ++ .deprecation_note = RHEL_CPU_DEPRECATION, + .level = 1, + .vendor = CPUID_VENDOR_INTEL, + .family = 4, +@@ -2007,6 +2018,7 @@ static const X86CPUDefinition builtin_x86_defs[] = { + }, + { + .name = "pentium", ++ .deprecation_note = RHEL_CPU_DEPRECATION, + .level = 1, + .vendor = CPUID_VENDOR_INTEL, + .family = 5, +@@ -2019,6 +2031,7 @@ static const X86CPUDefinition builtin_x86_defs[] = { + }, + { + .name = "pentium2", ++ .deprecation_note = RHEL_CPU_DEPRECATION, + .level = 2, + .vendor = CPUID_VENDOR_INTEL, + .family = 6, +@@ -2031,6 +2044,7 @@ static const X86CPUDefinition builtin_x86_defs[] = { + }, + { + .name = "pentium3", ++ .deprecation_note = RHEL_CPU_DEPRECATION, + .level = 3, + .vendor = CPUID_VENDOR_INTEL, + .family = 6, +@@ -2043,6 +2057,7 @@ static const X86CPUDefinition builtin_x86_defs[] = { + }, + { + .name = "athlon", ++ .deprecation_note = RHEL_CPU_DEPRECATION, + .level = 2, + .vendor = CPUID_VENDOR_AMD, + .family = 6, +@@ -2058,6 +2073,7 @@ static const X86CPUDefinition builtin_x86_defs[] = { + }, + { + .name = "n270", ++ .deprecation_note = RHEL_CPU_DEPRECATION, + .level = 10, + .vendor = CPUID_VENDOR_INTEL, + .family = 6, +@@ -2083,6 +2099,7 @@ static const X86CPUDefinition builtin_x86_defs[] = { + }, + { + .name = "Conroe", ++ .deprecation_note = RHEL_CPU_DEPRECATION, + .level = 10, + .vendor = CPUID_VENDOR_INTEL, + .family = 6, +@@ -2123,6 +2140,7 @@ static const X86CPUDefinition builtin_x86_defs[] = { + }, + { + .name = "Penryn", ++ .deprecation_note = RHEL_CPU_DEPRECATION, + .level = 10, + .vendor = CPUID_VENDOR_INTEL, + .family = 6, +@@ -3832,6 +3850,7 @@ static const X86CPUDefinition builtin_x86_defs[] = { + }, + { + .name = "Opteron_G1", ++ .deprecation_note = RHEL_CPU_DEPRECATION, + .level = 5, + .vendor = CPUID_VENDOR_AMD, + .family = 15, +@@ -3852,6 +3871,7 @@ static const X86CPUDefinition builtin_x86_defs[] = { + }, + { + .name = "Opteron_G2", ++ .deprecation_note = RHEL_CPU_DEPRECATION, + .level = 5, + .vendor = CPUID_VENDOR_AMD, + .family = 15, +@@ -3874,6 +3894,7 @@ static const X86CPUDefinition builtin_x86_defs[] = { + }, + { + .name = "Opteron_G3", ++ .deprecation_note = RHEL_CPU_DEPRECATION, + .level = 5, + .vendor = CPUID_VENDOR_AMD, + .family = 16, +-- +2.35.3 + diff --git a/kvm-target-s390x-deprecate-CPUs-older-than-z14.patch b/kvm-target-s390x-deprecate-CPUs-older-than-z14.patch new file mode 100644 index 0000000..212900d --- /dev/null +++ b/kvm-target-s390x-deprecate-CPUs-older-than-z14.patch @@ -0,0 +1,194 @@ +From 8459c305914e2a7a19dcd1662d54a89def7acfa6 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= +Date: Thu, 17 Mar 2022 17:59:22 +0000 +Subject: [PATCH 05/18] target/s390x: deprecate CPUs older than z14 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Daniel P. Berrangé +RH-MergeRequest: 94: i386, aarch64, s390x: deprecate many named CPU models +RH-Commit: [5/6] 2da9e06cf452287673f94f880a7eb8b2b37b7278 (berrange/centos-src-qemu) +RH-Bugzilla: 2060839 +RH-Acked-by: Thomas Huth +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: Cornelia Huck + +RHEL-9 is compiled with the z14 ABI. We use this as a baseline to +select which CPUs we want to support, such that there is at least one +supported guest CPU that can be launched for every physical +machine capable of running RHEL-9 KVM. + +Supported CPUs: + + gen15a-base + gen15a + gen15b-base + gen15b + gen16a-base + gen16a + gen16b-base + gen16b + max + qemu + z14.2-base + z14.2 + z14-base + z14 + z14ZR1-base + z14ZR1 + +Deprecated CPUs: + + z10BC.2-base + z10BC.2 + z10BC-base + z10BC + z10EC.2-base + z10EC.2 + z10EC.3-base + z10EC.3 + z10EC-base + z10EC + z114-base + z114 + z13.2-base + z13.2 + z13-base + z13s-base + z13s + z13 + z196.2-base + z196.2 + z196-base + z196 + z800-base + z800 + z890.2-base + z890.2 + z890.3-base + z890.3 + z890-base + z890 + z900.2-base + z900.2 + z900.3-base + z900.3 + z900-base + z900 + z990.2-base + z990.2 + z990.3-base + z990.3 + z990.4-base + z990.4 + z990.5-base + z990.5 + z990-base + z990 + z9BC.2-base + z9BC.2 + z9BC-base + z9BC + z9EC.2-base + z9EC.2 + z9EC.3-base + z9EC.3 + z9EC-base + z9EC + zBC12-base + zBC12 + zEC12.2-base + zEC12.2 + zEC12-base + zEC12 + +https://bugzilla.redhat.com/show_bug.cgi?id=2060839 +Signed-off-by: Daniel P. Berrangé +--- + target/s390x/cpu_models.c | 11 +++++++++++ + target/s390x/cpu_models.h | 2 ++ + target/s390x/cpu_models_sysemu.c | 2 ++ + 3 files changed, 15 insertions(+) + +diff --git a/target/s390x/cpu_models.c b/target/s390x/cpu_models.c +index 6d71428056..9b9fc41676 100644 +--- a/target/s390x/cpu_models.c ++++ b/target/s390x/cpu_models.c +@@ -45,6 +45,9 @@ + * of a following release have been a superset of the previous release. With + * generation 15 one base feature and one optional feature have been deprecated. + */ ++ ++#define RHEL_CPU_DEPRECATION "use at least 'z14', or 'host' / 'qemu' / 'max'" ++ + static S390CPUDef s390_cpu_defs[] = { + CPUDEF_INIT(0x2064, 7, 1, 38, 0x00000000U, "z900", "IBM zSeries 900 GA1"), + CPUDEF_INIT(0x2064, 7, 2, 38, 0x00000000U, "z900.2", "IBM zSeries 900 GA2"), +@@ -852,22 +855,30 @@ static void s390_host_cpu_model_class_init(ObjectClass *oc, void *data) + static void s390_base_cpu_model_class_init(ObjectClass *oc, void *data) + { + S390CPUClass *xcc = S390_CPU_CLASS(oc); ++ CPUClass *cc = CPU_CLASS(oc); + + /* all base models are migration safe */ + xcc->cpu_def = (const S390CPUDef *) data; + xcc->is_migration_safe = true; + xcc->is_static = true; + xcc->desc = xcc->cpu_def->desc; ++ if (xcc->cpu_def->gen < 14) { ++ cc->deprecation_note = RHEL_CPU_DEPRECATION; ++ } + } + + static void s390_cpu_model_class_init(ObjectClass *oc, void *data) + { + S390CPUClass *xcc = S390_CPU_CLASS(oc); ++ CPUClass *cc = CPU_CLASS(oc); + + /* model that can change between QEMU versions */ + xcc->cpu_def = (const S390CPUDef *) data; + xcc->is_migration_safe = true; + xcc->desc = xcc->cpu_def->desc; ++ if (xcc->cpu_def->gen < 14) { ++ cc->deprecation_note = RHEL_CPU_DEPRECATION; ++ } + } + + static void s390_qemu_cpu_model_class_init(ObjectClass *oc, void *data) +diff --git a/target/s390x/cpu_models.h b/target/s390x/cpu_models.h +index 74d1f87e4f..372160bcd7 100644 +--- a/target/s390x/cpu_models.h ++++ b/target/s390x/cpu_models.h +@@ -38,6 +38,8 @@ struct S390CPUDef { + S390FeatBitmap full_feat; + /* used to init full_feat from generated data */ + S390FeatInit full_init; ++ /* if deprecated, provides a suggestion */ ++ const char *deprecation_note; + }; + + /* CPU model based on a CPU definition */ +diff --git a/target/s390x/cpu_models_sysemu.c b/target/s390x/cpu_models_sysemu.c +index 6a04ccab1b..f3b7c304ec 100644 +--- a/target/s390x/cpu_models_sysemu.c ++++ b/target/s390x/cpu_models_sysemu.c +@@ -61,6 +61,7 @@ static void create_cpu_model_list(ObjectClass *klass, void *opaque) + CpuDefinitionInfo *info; + char *name = g_strdup(object_class_get_name(klass)); + S390CPUClass *scc = S390_CPU_CLASS(klass); ++ CPUClass *cc = CPU_CLASS(klass); + + /* strip off the -s390x-cpu */ + g_strrstr(name, "-" TYPE_S390_CPU)[0] = 0; +@@ -70,6 +71,7 @@ static void create_cpu_model_list(ObjectClass *klass, void *opaque) + info->migration_safe = scc->is_migration_safe; + info->q_static = scc->is_static; + info->q_typename = g_strdup(object_class_get_name(klass)); ++ info->deprecated = !!cc->deprecation_note; + /* check for unavailable features */ + if (cpu_list_data->model) { + Object *obj; +-- +2.35.3 + diff --git a/kvm-tests-avocado-update-aarch64_virt-test-to-exercise-c.patch b/kvm-tests-avocado-update-aarch64_virt-test-to-exercise-c.patch new file mode 100644 index 0000000..4fcf786 --- /dev/null +++ b/kvm-tests-avocado-update-aarch64_virt-test-to-exercise-c.patch @@ -0,0 +1,157 @@ +From f52aa60217634c96fef59ce76b803a94610bf5c8 Mon Sep 17 00:00:00 2001 +From: Andrew Jones +Date: Wed, 15 Jun 2022 15:28:27 +0200 +Subject: [PATCH 01/18] tests/avocado: update aarch64_virt test to exercise + -cpu max +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Daniel P. Berrangé +RH-MergeRequest: 94: i386, aarch64, s390x: deprecate many named CPU models +RH-Commit: [1/6] df6839e567180a4c32afd98852f68b2279e00f7c (berrange/centos-src-qemu) +RH-Bugzilla: 2060839 +RH-Acked-by: Thomas Huth +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: Cornelia Huck + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2066824 + +commit 11593544df6f8febb3ce87015c22b429bf43c4c7 +Author: Alex Bennée +Date: Tue Apr 19 10:09:56 2022 +0100 + + tests/avocado: update aarch64_virt test to exercise -cpu max + + The Fedora 29 kernel is quite old and importantly fails when running + in LPA2 scenarios. As it's not really exercising much of the CPU space + replace it with a custom 5.16.12 kernel with all the architecture + options turned on. There is a minimal buildroot initramfs included in + the kernel which has a few tools for stress testing the memory + subsystem. The userspace also targets the Neoverse N1 processor so + would fail with a v8.0 cpu like cortex-a53. + + While we are at it move the test into its own file so it can have an + assigned maintainer. + + Signed-off-by: Alex Bennée + Acked-by: Richard Henderson + Tested-by: Richard Henderson + Message-Id: <20220419091020.3008144-2-alex.bennee@linaro.org> + +Signed-off-by: Andrew Jones +--- + MAINTAINERS | 1 + + tests/avocado/boot_linux_console.py | 25 ------------- + tests/avocado/machine_aarch64_virt.py | 51 +++++++++++++++++++++++++++ + 3 files changed, 52 insertions(+), 25 deletions(-) + create mode 100644 tests/avocado/machine_aarch64_virt.py + +diff --git a/MAINTAINERS b/MAINTAINERS +index 2fe20a49ab..bfe8806f60 100644 +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -942,6 +942,7 @@ S: Maintained + F: hw/arm/virt* + F: include/hw/arm/virt.h + F: docs/system/arm/virt.rst ++F: tests/avocado/machine_aarch64_virt.py + + Xilinx Zynq + M: Edgar E. Iglesias +diff --git a/tests/avocado/boot_linux_console.py b/tests/avocado/boot_linux_console.py +index b40a3abc81..45a2ceda22 100644 +--- a/tests/avocado/boot_linux_console.py ++++ b/tests/avocado/boot_linux_console.py +@@ -325,31 +325,6 @@ def test_mips_malta32el_nanomips_64k_dbg(self): + kernel_hash = '18d1c68f2e23429e266ca39ba5349ccd0aeb7180' + self.do_test_mips_malta32el_nanomips(kernel_url, kernel_hash) + +- def test_aarch64_virt(self): +- """ +- :avocado: tags=arch:aarch64 +- :avocado: tags=machine:virt +- :avocado: tags=accel:tcg +- :avocado: tags=cpu:cortex-a53 +- """ +- kernel_url = ('https://archives.fedoraproject.org/pub/archive/fedora' +- '/linux/releases/29/Everything/aarch64/os/images/pxeboot' +- '/vmlinuz') +- kernel_hash = '8c73e469fc6ea06a58dc83a628fc695b693b8493' +- kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash) +- +- self.vm.set_console() +- kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + +- 'console=ttyAMA0') +- self.require_accelerator("tcg") +- self.vm.add_args('-cpu', 'cortex-a53', +- '-accel', 'tcg', +- '-kernel', kernel_path, +- '-append', kernel_command_line) +- self.vm.launch() +- console_pattern = 'Kernel command line: %s' % kernel_command_line +- self.wait_for_console_pattern(console_pattern) +- + def test_aarch64_xlnx_versal_virt(self): + """ + :avocado: tags=arch:aarch64 +diff --git a/tests/avocado/machine_aarch64_virt.py b/tests/avocado/machine_aarch64_virt.py +new file mode 100644 +index 0000000000..21848cba70 +--- /dev/null ++++ b/tests/avocado/machine_aarch64_virt.py +@@ -0,0 +1,51 @@ ++# Functional test that boots a Linux kernel and checks the console ++# ++# Copyright (c) 2022 Linaro Ltd. ++# ++# Author: ++# Alex Bennée ++# ++# SPDX-License-Identifier: GPL-2.0-or-later ++ ++import time ++ ++from avocado_qemu import QemuSystemTest ++from avocado_qemu import wait_for_console_pattern ++from avocado_qemu import exec_command ++ ++class Aarch64VirtMachine(QemuSystemTest): ++ KERNEL_COMMON_COMMAND_LINE = 'printk.time=0 ' ++ ++ def wait_for_console_pattern(self, success_message, vm=None): ++ wait_for_console_pattern(self, success_message, ++ failure_message='Kernel panic - not syncing', ++ vm=vm) ++ ++ def test_aarch64_virt(self): ++ """ ++ :avocado: tags=arch:aarch64 ++ :avocado: tags=machine:virt ++ :avocado: tags=accel:tcg ++ :avocado: tags=cpu:max ++ """ ++ kernel_url = ('https://fileserver.linaro.org/s/' ++ 'z6B2ARM7DQT3HWN/download') ++ ++ kernel_hash = 'ed11daab50c151dde0e1e9c9cb8b2d9bd3215347' ++ kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash) ++ ++ self.vm.set_console() ++ kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + ++ 'console=ttyAMA0') ++ self.require_accelerator("tcg") ++ self.vm.add_args('-cpu', 'max,pauth-impdef=on', ++ '-accel', 'tcg', ++ '-kernel', kernel_path, ++ '-append', kernel_command_line) ++ self.vm.launch() ++ self.wait_for_console_pattern('Welcome to Buildroot') ++ time.sleep(0.1) ++ exec_command(self, 'root') ++ time.sleep(0.1) ++ exec_command(self, 'cat /proc/self/maps') ++ time.sleep(0.1) +-- +2.35.3 + diff --git a/qemu-kvm.spec b/qemu-kvm.spec index 901b08b..a8042fb 100644 --- a/qemu-kvm.spec +++ b/qemu-kvm.spec @@ -151,7 +151,7 @@ Obsoletes: %{name}-block-ssh <= %{epoch}:%{version} \ Summary: QEMU is a machine emulator and virtualizer Name: qemu-kvm Version: 7.0.0 -Release: 7%{?rcrel}%{?dist}%{?cc_suffix} +Release: 8%{?rcrel}%{?dist}%{?cc_suffix} # Epoch because we pushed a qemu-1.0 package. AIUI this can't ever be dropped # Epoch 15 used for RHEL 8 # Epoch 17 used for RHEL 9 (due to release versioning offset in RHEL 8.5) @@ -288,6 +288,42 @@ Patch66: kvm-Enable-virtio-iommu-pci-on-x86_64.patch Patch67: kvm-linux-aio-fix-unbalanced-plugged-counter-in-laio_io_.patch # For bz#2092788 - Stalled IO Operations in VM Patch68: kvm-linux-aio-explain-why-max-batch-is-checked-in-laio_i.patch +# For bz#2060839 - Consider deprecating CPU models like "kvm64" / "qemu64" on RHEL 9 +Patch69: kvm-tests-avocado-update-aarch64_virt-test-to-exercise-c.patch +# For bz#2060839 - Consider deprecating CPU models like "kvm64" / "qemu64" on RHEL 9 +Patch70: kvm-RHEL-only-tests-avocado-Switch-aarch64-tests-from-a5.patch +# For bz#2060839 - Consider deprecating CPU models like "kvm64" / "qemu64" on RHEL 9 +Patch71: kvm-RHEL-only-AArch64-Drop-unsupported-CPU-types.patch +# For bz#2060839 - Consider deprecating CPU models like "kvm64" / "qemu64" on RHEL 9 +Patch72: kvm-target-i386-deprecate-CPUs-older-than-x86_64-v2-ABI.patch +# For bz#2060839 - Consider deprecating CPU models like "kvm64" / "qemu64" on RHEL 9 +Patch73: kvm-target-s390x-deprecate-CPUs-older-than-z14.patch +# For bz#2060839 - Consider deprecating CPU models like "kvm64" / "qemu64" on RHEL 9 +Patch74: kvm-target-arm-deprecate-named-CPU-models.patch +# For bz#1968509 - Use MSG_ZEROCOPY on QEMU Live Migration +Patch75: kvm-meson.build-Fix-docker-test-build-alpine-when-includ.patch +# For bz#1968509 - Use MSG_ZEROCOPY on QEMU Live Migration +Patch76: kvm-QIOChannel-Add-flags-on-io_writev-and-introduce-io_f.patch +# For bz#1968509 - Use MSG_ZEROCOPY on QEMU Live Migration +Patch77: kvm-QIOChannelSocket-Implement-io_writev-zero-copy-flag-.patch +# For bz#1968509 - Use MSG_ZEROCOPY on QEMU Live Migration +Patch78: kvm-migration-Add-zero-copy-send-parameter-for-QMP-HMP-f.patch +# For bz#1968509 - Use MSG_ZEROCOPY on QEMU Live Migration +Patch79: kvm-migration-Add-migrate_use_tls-helper.patch +# For bz#1968509 - Use MSG_ZEROCOPY on QEMU Live Migration +Patch80: kvm-multifd-multifd_send_sync_main-now-returns-negative-.patch +# For bz#1968509 - Use MSG_ZEROCOPY on QEMU Live Migration +Patch81: kvm-multifd-Send-header-packet-without-flags-if-zero-cop.patch +# For bz#1968509 - Use MSG_ZEROCOPY on QEMU Live Migration +Patch82: kvm-multifd-Implement-zero-copy-write-in-multifd-migrati.patch +# For bz#1968509 - Use MSG_ZEROCOPY on QEMU Live Migration +Patch83: kvm-QIOChannelSocket-Introduce-assert-and-reduce-ifdefs-.patch +# For bz#1968509 - Use MSG_ZEROCOPY on QEMU Live Migration +Patch84: kvm-QIOChannelSocket-Fix-zero-copy-send-so-socket-flush-.patch +# For bz#1968509 - Use MSG_ZEROCOPY on QEMU Live Migration +Patch85: kvm-migration-Change-zero_copy_send-from-migration-param.patch +# For bz#2096143 - The migration port is not released if use it again for recovering postcopy migration +Patch86: kvm-migration-Allow-migrate-recover-to-run-multiple-time.patch # Source-git patches @@ -1323,6 +1359,32 @@ useradd -r -u 107 -g qemu -G kvm -d / -s /sbin/nologin \ %endif %changelog +* Tue Jul 05 2022 Camilla Conte - 7.0.0-8 +- kvm-tests-avocado-update-aarch64_virt-test-to-exercise-c.patch [bz#2060839] +- kvm-RHEL-only-tests-avocado-Switch-aarch64-tests-from-a5.patch [bz#2060839] +- kvm-RHEL-only-AArch64-Drop-unsupported-CPU-types.patch [bz#2060839] +- kvm-target-i386-deprecate-CPUs-older-than-x86_64-v2-ABI.patch [bz#2060839] +- kvm-target-s390x-deprecate-CPUs-older-than-z14.patch [bz#2060839] +- kvm-target-arm-deprecate-named-CPU-models.patch [bz#2060839] +- kvm-meson.build-Fix-docker-test-build-alpine-when-includ.patch [bz#1968509] +- kvm-QIOChannel-Add-flags-on-io_writev-and-introduce-io_f.patch [bz#1968509] +- kvm-QIOChannelSocket-Implement-io_writev-zero-copy-flag-.patch [bz#1968509] +- kvm-migration-Add-zero-copy-send-parameter-for-QMP-HMP-f.patch [bz#1968509] +- kvm-migration-Add-migrate_use_tls-helper.patch [bz#1968509] +- kvm-multifd-multifd_send_sync_main-now-returns-negative-.patch [bz#1968509] +- kvm-multifd-Send-header-packet-without-flags-if-zero-cop.patch [bz#1968509] +- kvm-multifd-Implement-zero-copy-write-in-multifd-migrati.patch [bz#1968509] +- kvm-QIOChannelSocket-Introduce-assert-and-reduce-ifdefs-.patch [bz#1968509] +- kvm-QIOChannelSocket-Fix-zero-copy-send-so-socket-flush-.patch [bz#1968509] +- kvm-migration-Change-zero_copy_send-from-migration-param.patch [bz#1968509] +- kvm-migration-Allow-migrate-recover-to-run-multiple-time.patch [bz#2096143] +- Resolves: bz#2060839 + (Consider deprecating CPU models like "kvm64" / "qemu64" on RHEL 9) +- Resolves: bz#1968509 + (Use MSG_ZEROCOPY on QEMU Live Migration) +- Resolves: bz#2096143 + (The migration port is not released if use it again for recovering postcopy migration) + * Mon Jun 27 2022 Miroslav Rezanina - 7.0.0-7 - kvm-coroutine-ucontext-use-QEMU_DEFINE_STATIC_CO_TLS.patch [bz#1952483] - kvm-coroutine-use-QEMU_DEFINE_STATIC_CO_TLS.patch [bz#1952483]