From 6baefc8b5e03e58d0c0989c495a20fa468477944 Mon Sep 17 00:00:00 2001 From: Jiabo Feng Date: Tue, 28 Nov 2023 15:57:41 +0800 Subject: [PATCH 01/19] QEMU update to version 6.2.0-84(master) - hw/arm/fsl-imx: Do not ignore Error argument - hw/net/cadence_gem.c: spelling fixes: Octects - tests/qtest: check the return value - libvhost-user: Fix VHOST_USER_GET_MAX_MEM_SLOTS reply mainline inclusion commit 69a5daec06f423843ce1bb9be5fb049314996f78 category: bugfix - io_uring: fix short read slow path mainline inclusion commit c06fc7ce147e57ab493bad9263f1601b8298484b category: bugfix - libvhost-user: Fix VHOST_USER_ADD_MEM_REG reply mainline inclusion commit 7f27d20ded2f480f3e66d03f90ea71507b834276 category: bugfix - qsd: Unlink absolute PID file path mainline inclusion commit 9d8f8233b9fa525a7e37350fbc18877051128c5d category: bugfix - net: Fix a misleading error message - vdpa: stop all svq on device deletion - vhost: release virtqueue objects in error path - vhost: fix the fd leak - virtio: i2c: Check notifier helpers for VIRTIO_CONFIG_IRQ_IDX - hw/virtio: fix typo in VIRTIO_CONFIG_IRQ_IDX comments - virtio-net: clear guest_announce feature if no cvq backend - vdpa: fix VHOST_BACKEND_F_IOTLB_ASID flag check - vdpa: do not block migration if device has cvq and x-svq=on - vdpa net: block migration if the device has CVQ - vdpa: Return -EIO if device ack is VIRTIO_NET_ERR in _load_mq() - vdpa: Return -EIO if device ack is VIRTIO_NET_ERR in _load_mac() - vdpa: fix not using CVQ buffer in case of error - vdpa: Fix possible use-after-free for VirtQueueElement - hw/virtio: fix vhost_user_read tracepoint - vhost: Fix false positive out-of-bounds - vhost: fix possible wrap in SVQ descriptor ring - vhost: move iova_tree set to vhost_svq_start - vhost: Always store new kick fd on vhost_svq_set_svq_kick_fd - virtio-crypto: verify src&dst buffer length for sym request - vdpa: commit all host notifier MRs in a single MR transaction - vdpa: harden the error path if get_iova_range failed - vdpa-dev: get iova range explicitly - virtio-pci: add support for configure interrupt - virtio-mmio: add support for configure interrupt - virtio-net: add support for configure interrupt - vhost: add support for configure interrupt - virtio: add support for configure interrupt - vhost-vdpa: add support for config interrupt - vhost: introduce new VhostOps vhost_set_config_call - virtio-pci: decouple the single vector from the interrupt process - virtio-pci: decouple notifier from interrupt process - virtio: introduce macro VIRTIO_CONFIG_IRQ_IDX - vdpa: do not handle VIRTIO_NET_F_GUEST_ANNOUNCE in vhost-vdpa - vdpa: handle VIRTIO_NET_CTRL_ANNOUNCE in vhost_vdpa_net_handle_ctrl_avail - vhost: fix vq dirty bitmap syncing when vIOMMU is enabled - hw/virtio: gracefully handle unset vhost_dev vdev - hw/virtio/vhost: Fix typo in comment. - vdpa: always start CVQ in SVQ mode if possible - vdpa: add shadow_data to vhost_vdpa - vdpa: store x-svq parameter in VhostVDPAState - vdpa: add asid parameter to vhost_vdpa_dma_map/unmap - vdpa: allocate SVQ array unconditionally - vdpa: move SVQ vring features check to net/ - vdpa: request iova_range only once - vdpa: add vhost_vdpa_net_valid_svq_features - vhost: allocate SVQ device file descriptors at device start - vhost: set SVQ device call handler at SVQ start - vdpa: use v->shadow_vqs_enabled in vhost_vdpa_svqs_start & stop - vhost: enable vrings in vhost_dev_start() for vhost-user devices - vhost-vdpa: fix assert !virtio_net_get_subqueue(nc)->async_tx.elem in virtio_net_reset - net/vhost-vdpa.c: Fix clang compilation failure - vhost-vdpa: allow passing opened vhostfd to vhost-vdpa - vdpa: Remove shadow CVQ command check - vdpa: Delete duplicated vdpa_feature_bits entry - hw/virtio: add some vhost-user trace events - vdpa: Allow MQ feature in SVQ - virtio-net: Update virtio-net curr_queue_pairs in vdpa backends - vdpa: validate MQ CVQ commands - vdpa: Add vhost_vdpa_net_load_mq - vdpa: extract vhost_vdpa_net_load_mac from vhost_vdpa_net_load - vdpa: Make VhostVDPAState cvq_cmd_in_buffer control ack type - vdpa: Delete CVQ migration blocker - vdpa: Add virtio-net mac address via CVQ at start - vhost_net: add NetClientState->load() callback - vdpa: extract vhost_vdpa_net_cvq_add from vhost_vdpa_net_handle_ctrl_avail - vdpa: Move command buffers map to start of net device - vdpa: add net_vhost_vdpa_cvq_info NetClientInfo - vhost_net: Add NetClientInfo stop callback - vhost_net: Add NetClientInfo start callback - vdpa: Use ring hwaddr at vhost_vdpa_svq_unmap_ring - vdpa: Make SVQ vring unmapping return void - vdpa: Remove SVQ vring from iova_tree at shutdown - util: accept iova_tree_remove_parameter by value - vdpa: do not save failed dma maps in SVQ iova tree - vdpa: Skip the maps not in the iova tree - vdpa: Fix file descriptor leak on get features error - vdpa: Fix memory listener deletions of iova tree - vhost: Get vring base from vq, not svq - vdpa: Add x-svq to NetdevVhostVDPAOptions - vdpa: Add device migration blocker - vdpa: Extract get features part from vhost_vdpa_get_max_queue_pairs - vdpa: Buffer CVQ support on shadow virtqueue - vdpa: manual forward CVQ buffers - vdpa: Export vhost_vdpa_dma_map and unmap calls - vhost: Add svq avail_handler callback - vhost: add vhost_svq_poll - vhost: Expose vhost_svq_add - vhost: add vhost_svq_push_elem - vhost: Track number of descs in SVQDescState - vhost: Add SVQDescState - vhost: Decouple vhost_svq_add from VirtQueueElement - vhost: Check for queue full at vhost_svq_add - vhost: Move vhost_svq_kick call to vhost_svq_add - vhost: Reorder vhost_svq_kick - vdpa: Avoid compiler to squash reads to used idx - virtio-net: Expose ctrl virtqueue logic - virtio-net: Expose MAC_TABLE_ENTRIES - vhost: move descriptor translation to vhost_svq_vring_write_descs - util: Return void on iova_tree_remove - virtio-net: don't handle mq request in userspace handler for vhost-vdpa - vhost-vdpa: change name and polarity for vhost_vdpa_one_time_request() - vhost-vdpa: backend feature should set only once - vhost-vdpa: fix improper cleanup in net_init_vhost_vdpa - virtio-net: align ctrl_vq index for non-mq guest for vhost_vdpa - virtio: add vhost support for virtio devices - include/hw: start documenting the vhost API - hw/virtio: add vhost_user_[read|write] trace points - vhost: Fix element in vhost_svq_add failure - vdpa: Fix index calculus at vhost_vdpa_svqs_start - vdpa: Fix bad index calculus at vhost_vdpa_get_vring_base - vhost: Fix device's used descriptor dequeue - vhost: Track descriptor chain in private at SVQ - vdpa: Add missing tracing to batch mapping functions - vhost-vdpa: fix typo in a comment - virtio: fix --enable-vhost-user build on non-Linux - vdpa: Expose VHOST_F_LOG_ALL on SVQ - vdpa: Never set log_base addr if SVQ is enabled - vdpa: Adapt vhost_vdpa_get_vring_base to SVQ - vdpa: Add custom IOTLB translations to SVQ - vhost: Add VhostIOVATree - util: add iova_tree_find_iova - util: Add iova_tree_alloc_map - vhost: Shadow virtqueue buffers forwarding - vdpa: adapt vhost_ops callbacks to svq - virtio: Add vhost_svq_get_vring_addr - vhost: Add vhost_svq_valid_features to shadow vq - vhost: Add Shadow VirtQueue call forwarding capabilities - vhost: Add Shadow VirtQueue kick forwarding capabilities - vhost: Add VhostShadowVirtqueue - vdpa: Make ncs autofree - Revert "virtio: introduce macro IRTIO_CONFIG_IRQ_IDX" - Revert "virtio-pci: decouple notifier from interrupt process" - Revert "virtio-pci: decouple the single vector from the interrupt process" - Revert "vhost-vdpa: add support for config interrupt" - Revert "virtio: add support for configure interrupt" - Revert "vhost: add support for configure interrupt" - Revert "virtio-net: add support for configure interrupt" - Revert "virtio-mmio: add support for configure interrupt" - Revert "virtio-pci: add support for configure interrupt" - Revert "vhost: introduce new VhostOps vhost_set_config_call" - virtio: signal after wrapping packed used_idx - target/i386: Adjust feature level according to FEAT_7_1_EDX - target/i386: Add new CPU model GraniteRapids - target/i386: Add support for PREFETCHIT0/1 in CPUID enumeration - target/i386: Add support for AVX-NE-CONVERT in CPUID enumeration - target/i386: Add support for AVX-VNNI-INT8 in CPUID enumeration - target/i386: Add support for AVX-IFMA in CPUID enumeration - target/i386: Add support for AMX-FP16 in CPUID enumeration - target/i386: Add support for CMPCCXADD in CPUID enumeration - tracetool: avoid invalid escape in Python string - hw/pvrdma: Protect against buggy or malicious guest driver - vga: avoid crash if no default vga card mainline inclusion commit 6985d8ede92494f3b791de01e8ee9306eb6d5e4a category: bugfix - qom/object: Remove circular include dependency mainline inclusion commit 5bba9bcfbb42e7c016626420e148a1bf1b080835 category: bugfix - artist: set memory region owners for buffers to the artist device mainline inclusion commit 39fbaeca096a9bf6cbe2af88572c1cb2aa62aa8c category: bugfix - virtio-iommu: Fix the partial copy of probe request mainline inclusion commit 45461aace83d961e933b27519b81d17b4c690514 category: bugfix - e1000: set RX descriptor status in a separate operation mainline inclusion commit 034d00d4858161e1d4cff82d8d230bce874a04d3 category: bugfix - vhost: introduce new VhostOps vhost_set_config_call - vhost: stick to -errno error return convention - vhost-user: stick to -errno error return convention - vhost-vdpa: stick to -errno error return convention - virtio-pci: add support for configure interrupt - virtio-mmio: add support for configure interrupt - virtio-net: add support for configure interrupt - vhost: add support for configure interrupt - virtio: add support for configure interrupt - vhost-vdpa: add support for config interrupt - virtio-pci: decouple the single vector from the interrupt process - virtio-pci: decouple notifier from interrupt process - virtio: introduce macro IRTIO_CONFIG_IRQ_IDX - pci: Fix the update of interrupt disable bit in PCI_COMMAND register - hw/timer/npcm7xx_timer: Prevent timer from counting down past zero - tpm_crb: mark command buffer as dirty on request completion mainline inclusion commit e37a0ef4605e5d2041785ff3fc89ca6021faf7a0 category: bugfix - pci: fix overflow in snprintf string formatting mainline inclusion commit 36f18c6989a3d1ff1d7a0e50b0868ef3958299b4 category: bugfix - hw/usb/hcd-ehci: fix writeback order mainline inclusion commit f471e8b060798f26a7fc339c6152f82f22a7b33d category: bugfix - qemu-timer: Skip empty timer lists before locking in qemu_clock_deadline_ns_all mainline inclusion commit 3f42906c9ab2c777a895b48b87b8107167e4a275 category: bugfix - semihosting/config: Merge --semihosting-config option groups mainline inclusion commit 90c072e063737e9e8f431489bbd334452f89056e category: bugfix - semihosting: fix memleak at semihosting_arg_fallback - target/i386: Export GDS_NO bit to guests Signed-off-by: Jiabo Feng (cherry picked from commit 946c69b8875ed50024bc4bab1bed8c4c0cac2ac3) --- ...-add-support-for-configure-interrupt.patch | 163 +++ ...roduce-new-VhostOps-vhost_set_config.patch | 36 + ...dpa-add-support-for-config-interrupt.patch | 56 + ...-add-support-for-configure-interrupt.patch | 101 ++ ...introduce-macro-IRTIO_CONFIG_IRQ_IDX.patch | 161 +++ ...io-add-support-for-configure-interru.patch | 64 + ...t-add-support-for-configure-interrup.patch | 52 + ...i-add-support-for-configure-interrup.patch | 215 ++++ ...i-decouple-notifier-from-interrupt-p.patch | 255 ++++ ...i-decouple-the-single-vector-from-th.patch | 192 +++ ...y-region-owners-for-buffers-to-the-a.patch | 37 + ...criptor-status-in-a-separate-operati.patch | 89 ++ ...fsl-imx-Do-not-ignore-Error-argument.patch | 62 + ...cadence_gem.c-spelling-fixes-Octects.patch | 39 + ...inst-buggy-or-malicious-guest-driver.patch | 65 + ..._timer-Prevent-timer-from-counting-d.patch | 38 + hw-usb-hcd-ehci-fix-writeback-order.patch | 64 + ...tio-add-some-vhost-user-trace-events.patch | 70 ++ ...-vhost_user_-read-write-trace-points.patch | 62 + ...po-in-VIRTIO_CONFIG_IRQ_IDX-comments.patch | 135 ++ ...irtio-fix-vhost_user_read-tracepoint.patch | 48 + ...acefully-handle-unset-vhost_dev-vdev.patch | 52 + hw-virtio-vhost-Fix-typo-in-comment.patch | 34 + ...e-hw-start-documenting-the-vhost-API.patch | 192 +++ io_uring-fix-short-read-slow-path.patch | 55 + ...ser-Fix-VHOST_USER_ADD_MEM_REG-reply.patch | 48 + ...x-VHOST_USER_GET_MAX_MEM_SLOTS-reply.patch | 53 + net-Fix-a-misleading-error-message.patch | 50 + ...vdpa.c-Fix-clang-compilation-failure.patch | 62 + ...te-of-interrupt-disable-bit-in-PCI_C.patch | 53 + ...erflow-in-snprintf-string-formatting.patch | 106 ++ ...empty-timer-lists-before-locking-in-.patch | 39 + qemu.spec | 376 +++++- ...t-Remove-circular-include-dependency.patch | 41 + qsd-Unlink-absolute-PID-file-path.patch | 81 ++ ...ig-Merge-semihosting-config-option-g.patch | 54 + ...-memleak-at-semihosting_arg_fallback.patch | 47 + ...i386-Add-new-CPU-model-GraniteRapids.patch | 183 +++ ...support-for-AMX-FP16-in-CPUID-enumer.patch | 62 + ...support-for-AVX-IFMA-in-CPUID-enumer.patch | 60 + ...support-for-AVX-NE-CONVERT-in-CPUID-.patch | 62 + ...support-for-AVX-VNNI-INT8-in-CPUID-e.patch | 110 ++ ...support-for-CMPCCXADD-in-CPUID-enume.patch | 61 + ...support-for-PREFETCHIT0-1-in-CPUID-e.patch | 61 + ...st-feature-level-according-to-FEAT_7.patch | 46 + target-i386-Export-GDS_NO-bit-to-guests.patch | 46 + tests-qtest-check-the-return-value.patch | 62 + ...mand-buffer-as-dirty-on-request-comp.patch | 43 + ...void-invalid-escape-in-Python-string.patch | 38 + util-Add-iova_tree_alloc_map.patch | 219 ++++ util-Return-void-on-iova_tree_remove.patch | 61 + ...-iova_tree_remove_parameter-by-value.patch | 173 +++ util-add-iova_tree_find_iova.patch | 116 ++ ...apt-vhost_vdpa_get_vring_base-to-SVQ.patch | 59 + ...Add-custom-IOTLB-translations-to-SVQ.patch | 415 +++++++ vdpa-Add-device-migration-blocker.patch | 87 ++ ...g-tracing-to-batch-mapping-functions.patch | 58 + vdpa-Add-vhost_vdpa_net_load_mq.patch | 65 + ...tio-net-mac-address-via-CVQ-at-start.patch | 78 ++ ...-Add-x-svq-to-NetdevVhostVDPAOptions.patch | 208 ++++ vdpa-Allow-MQ-feature-in-SVQ.patch | 32 + ...compiler-to-squash-reads-to-used-idx.patch | 46 + ...ffer-CVQ-support-on-shadow-virtqueue.patch | 305 +++++ vdpa-Delete-CVQ-migration-blocker.patch | 89 ++ ...e-duplicated-vdpa_feature_bits-entry.patch | 34 + ...t-vhost_vdpa_dma_map-and-unmap-calls.patch | 65 + vdpa-Expose-VHOST_F_LOG_ALL-on-SVQ.patch | 120 ++ ...-features-part-from-vhost_vdpa_get_m.patch | 89 ++ ...ex-calculus-at-vhost_vdpa_get_vring_.patch | 41 + ...escriptor-leak-on-get-features-error.patch | 50 + ...ex-calculus-at-vhost_vdpa_svqs_start.patch | 37 + ...mory-listener-deletions-of-iova-tree.patch | 53 + ...e-use-after-free-for-VirtQueueElemen.patch | 63 + ...Make-SVQ-vring-unmapping-return-void.patch | 124 ++ ...DPAState-cvq_cmd_in_buffer-control-a.patch | 103 ++ vdpa-Make-ncs-autofree.patch | 54 + ...d-buffers-map-to-start-of-net-device.patch | 242 ++++ ...-set-log_base-addr-if-SVQ-is-enabled.patch | 36 + ...SVQ-vring-from-iova_tree-at-shutdown.patch | 40 + vdpa-Remove-shadow-CVQ-command-check.patch | 94 ++ ...evice-ack-is-VIRTIO_NET_ERR-in-_-new.patch | 63 + ...if-device-ack-is-VIRTIO_NET_ERR-in-_.patch | 62 + vdpa-Skip-the-maps-not-in-the-iova-tree.patch | 39 + ...-hwaddr-at-vhost_vdpa_svq_unmap_ring.patch | 70 ++ vdpa-adapt-vhost_ops-callbacks-to-svq.patch | 104 ++ ...arameter-to-vhost_vdpa_dma_map-unmap.patch | 227 ++++ ...et_vhost_vdpa_cvq_info-NetClientInfo.patch | 53 + vdpa-add-shadow_data-to-vhost_vdpa.patch | 86 ++ ...dd-vhost_vdpa_net_valid_svq_features.patch | 68 + vdpa-allocate-SVQ-array-unconditionally.patch | 42 + ...ys-start-CVQ-in-SVQ-mode-if-possible.patch | 224 ++++ ...host-notifier-MRs-in-a-single-MR-tra.patch | 79 ++ vdpa-dev-get-iova-range-explicitly.patch | 104 ++ ...k-migration-if-device-has-cvq-and-x-.patch | 52 + ...le-VIRTIO_NET_F_GUEST_ANNOUNCE-in-vh.patch | 35 + ...ave-failed-dma-maps-in-SVQ-iova-tree.patch | 74 ++ ...st_vdpa_net_cvq_add-from-vhost_vdpa_.patch | 144 +++ ...st_vdpa_net_load_mac-from-vhost_vdpa.patch | 106 ++ ...HOST_BACKEND_F_IOTLB_ASID-flag-check.patch | 38 + ...ot-using-CVQ-buffer-in-case-of-error.patch | 39 + ...IO_NET_CTRL_ANNOUNCE-in-vhost_vdpa_n.patch | 51 + ...-error-path-if-get_iova_range-failed.patch | 39 + vdpa-manual-forward-CVQ-buffers.patch | 146 +++ ...move-SVQ-vring-features-check-to-net.patch | 110 ++ ...lock-migration-if-the-device-has-CVQ.patch | 70 ++ vdpa-request-iova_range-only-once.patch | 137 ++ vdpa-stop-all-svq-on-device-deletion.patch | 73 ++ ...re-x-svq-parameter-in-VhostVDPAState.patch | 54 + ...w_vqs_enabled-in-vhost_vdpa_svqs_sta.patch | 50 + vdpa-validate-MQ-CVQ-commands.patch | 41 + vga-avoid-crash-if-no-default-vga-card.patch | 41 + vhost-Add-SVQDescState.patch | 116 ++ ...-VirtQueue-call-forwarding-capabilit.patch | 168 +++ ...-VirtQueue-kick-forwarding-capabilit.patch | 395 ++++++ vhost-Add-VhostIOVATree.patch | 200 +++ vhost-Add-VhostShadowVirtqueue.patch | 147 +++ vhost-Add-svq-avail_handler-callback.patch | 145 +++ ...host_svq_valid_features-to-shadow-vq.patch | 133 ++ ...re-new-kick-fd-on-vhost_svq_set_svq_.patch | 57 + ...heck-for-queue-full-at-vhost_svq_add.patch | 115 ++ ...-vhost_svq_add-from-VirtQueueElement.patch | 119 ++ vhost-Expose-vhost_svq_add.patch | 54 + ...Fix-device-s-used-descriptor-dequeue.patch | 64 + ...Fix-element-in-vhost_svq_add-failure.patch | 49 + vhost-Fix-false-positive-out-of-bounds.patch | 49 + vhost-Get-vring-base-from-vq-not-svq.patch | 78 ++ ...vhost_svq_kick-call-to-vhost_svq_add.patch | 42 + vhost-Reorder-vhost_svq_kick.patch | 69 ++ ...-Shadow-virtqueue-buffers-forwarding.patch | 684 ++++++++++ ...k-descriptor-chain-in-private-at-SVQ.patch | 104 ++ ...rack-number-of-descs-in-SVQDescState.patch | 62 + ...-support-for-configure-interrupt-new.patch | 172 +++ ...-add-support-for-configure-interrupt.patch | 170 +++ vhost-add-vhost_svq_poll.patch | 73 ++ vhost-add-vhost_svq_push_elem.patch | 64 + ...VQ-device-file-descriptors-at-device.patch | 162 +++ ...ngs-in-vhost_dev_start-for-vhost-use.patch | 453 +++++++ ...possible-wrap-in-SVQ-descriptor-ring.patch | 108 ++ vhost-fix-the-fd-leak.patch | 37 + ...ty-bitmap-syncing-when-vIOMMU-is-ena.patch | 143 +++ ...w-VhostOps-vhost_set_config_call-new.patch | 42 + ...e-new-VhostOps-vhost_set_config_call.patch | 41 + ...iptor-translation-to-vhost_svq_vring.patch | 101 ++ ...ove-iova_tree-set-to-vhost_svq_start.patch | 114 ++ ...ease-virtqueue-objects-in-error-path.patch | 39 + ...SVQ-device-call-handler-at-SVQ-start.patch | 65 + ...ick-to-errno-error-return-convention.patch | 349 ++++++ ...ick-to-errno-error-return-convention.patch | 1100 +++++++++++++++++ ...add-support-for-config-interrupt-new.patch | 62 + ...dpa-add-support-for-config-interrupt.patch | 59 + ...-passing-opened-vhostfd-to-vhost-vdp.patch | 114 ++ ...backend-feature-should-set-only-once.patch | 49 + ...e-name-and-polarity-for-vhost_vdpa_o.patch | 111 ++ ...ssert-virtio_net_get_subqueue-nc-asy.patch | 75 ++ ...mproper-cleanup-in-net_init_vhost_vd.patch | 36 + vhost-vdpa-fix-typo-in-a-comment.patch | 35 + ...ick-to-errno-error-return-convention.patch | 107 ++ ...net-Add-NetClientInfo-start-callback.patch | 64 + ..._net-Add-NetClientInfo-stop-callback.patch | 59 + ...net-add-NetClientState-load-callback.patch | 64 + virtio-Add-vhost_svq_get_vring_addr.patch | 96 ++ ...-support-for-configure-interrupt-new.patch | 102 ++ ...-add-support-for-configure-interrupt.patch | 106 ++ ...add-vhost-support-for-virtio-devices.patch | 336 +++++ ...rc-dst-buffer-length-for-sym-request.patch | 46 + ...enable-vhost-user-build-on-non-Linux.patch | 39 + ...-notifier-helpers-for-VIRTIO_CONFIG_.patch | 55 + ...introduce-macro-IRTIO_CONFIG_IRQ_IDX.patch | 166 +++ ...ntroduce-macro-VIRTIO_CONFIG_IRQ_IDX.patch | 227 ++++ ...ix-the-partial-copy-of-probe-request.patch | 60 + ...-support-for-configure-interrupt-new.patch | 67 + ...-add-support-for-configure-interrupt.patch | 66 + virtio-net-Expose-MAC_TABLE_ENTRIES.patch | 50 + virtio-net-Expose-ctrl-virtqueue-logic.patch | 149 +++ ...e-virtio-net-curr_queue_pairs-in-vdp.patch | 53 + ...-support-for-configure-interrupt-new.patch | 102 ++ ...-add-support-for-configure-interrupt.patch | 56 + ...-ctrl_vq-index-for-non-mq-guest-for-.patch | 131 ++ ...-guest_announce-feature-if-no-cvq-ba.patch | 67 + ...-handle-mq-request-in-userspace-hand.patch | 97 ++ ...-support-for-configure-interrupt-new.patch | 261 ++++ ...-add-support-for-configure-interrupt.patch | 218 ++++ ...-notifier-from-interrupt-process-new.patch | 259 ++++ ...uple-notifier-from-interrupt-process.patch | 259 ++++ ...the-single-vector-from-the-inter-new.patch | 198 +++ ...ple-the-single-vector-from-the-inter.patch | 196 +++ ...ignal-after-wrapping-packed-used_idx.patch | 51 + 187 files changed, 20388 insertions(+), 1 deletion(-) create mode 100644 Revert-vhost-add-support-for-configure-interrupt.patch create mode 100644 Revert-vhost-introduce-new-VhostOps-vhost_set_config.patch create mode 100644 Revert-vhost-vdpa-add-support-for-config-interrupt.patch create mode 100644 Revert-virtio-add-support-for-configure-interrupt.patch create mode 100644 Revert-virtio-introduce-macro-IRTIO_CONFIG_IRQ_IDX.patch create mode 100644 Revert-virtio-mmio-add-support-for-configure-interru.patch create mode 100644 Revert-virtio-net-add-support-for-configure-interrup.patch create mode 100644 Revert-virtio-pci-add-support-for-configure-interrup.patch create mode 100644 Revert-virtio-pci-decouple-notifier-from-interrupt-p.patch create mode 100644 Revert-virtio-pci-decouple-the-single-vector-from-th.patch create mode 100644 artist-set-memory-region-owners-for-buffers-to-the-a.patch create mode 100644 e1000-set-RX-descriptor-status-in-a-separate-operati.patch create mode 100644 hw-arm-fsl-imx-Do-not-ignore-Error-argument.patch create mode 100644 hw-net-cadence_gem.c-spelling-fixes-Octects.patch create mode 100644 hw-pvrdma-Protect-against-buggy-or-malicious-guest-driver.patch create mode 100644 hw-timer-npcm7xx_timer-Prevent-timer-from-counting-d.patch create mode 100644 hw-usb-hcd-ehci-fix-writeback-order.patch create mode 100644 hw-virtio-add-some-vhost-user-trace-events.patch create mode 100644 hw-virtio-add-vhost_user_-read-write-trace-points.patch create mode 100644 hw-virtio-fix-typo-in-VIRTIO_CONFIG_IRQ_IDX-comments.patch create mode 100644 hw-virtio-fix-vhost_user_read-tracepoint.patch create mode 100644 hw-virtio-gracefully-handle-unset-vhost_dev-vdev.patch create mode 100644 hw-virtio-vhost-Fix-typo-in-comment.patch create mode 100644 include-hw-start-documenting-the-vhost-API.patch create mode 100644 io_uring-fix-short-read-slow-path.patch create mode 100644 libvhost-user-Fix-VHOST_USER_ADD_MEM_REG-reply.patch create mode 100644 libvhost-user-Fix-VHOST_USER_GET_MAX_MEM_SLOTS-reply.patch create mode 100644 net-Fix-a-misleading-error-message.patch create mode 100644 net-vhost-vdpa.c-Fix-clang-compilation-failure.patch create mode 100644 pci-Fix-the-update-of-interrupt-disable-bit-in-PCI_C.patch create mode 100644 pci-fix-overflow-in-snprintf-string-formatting.patch create mode 100644 qemu-timer-Skip-empty-timer-lists-before-locking-in-.patch create mode 100644 qom-object-Remove-circular-include-dependency.patch create mode 100644 qsd-Unlink-absolute-PID-file-path.patch create mode 100644 semihosting-config-Merge-semihosting-config-option-g.patch create mode 100644 semihosting-fix-memleak-at-semihosting_arg_fallback.patch create mode 100644 target-i386-Add-new-CPU-model-GraniteRapids.patch create mode 100644 target-i386-Add-support-for-AMX-FP16-in-CPUID-enumer.patch create mode 100644 target-i386-Add-support-for-AVX-IFMA-in-CPUID-enumer.patch create mode 100644 target-i386-Add-support-for-AVX-NE-CONVERT-in-CPUID-.patch create mode 100644 target-i386-Add-support-for-AVX-VNNI-INT8-in-CPUID-e.patch create mode 100644 target-i386-Add-support-for-CMPCCXADD-in-CPUID-enume.patch create mode 100644 target-i386-Add-support-for-PREFETCHIT0-1-in-CPUID-e.patch create mode 100644 target-i386-Adjust-feature-level-according-to-FEAT_7.patch create mode 100644 target-i386-Export-GDS_NO-bit-to-guests.patch create mode 100644 tests-qtest-check-the-return-value.patch create mode 100644 tpm_crb-mark-command-buffer-as-dirty-on-request-comp.patch create mode 100644 tracetool-avoid-invalid-escape-in-Python-string.patch create mode 100644 util-Add-iova_tree_alloc_map.patch create mode 100644 util-Return-void-on-iova_tree_remove.patch create mode 100644 util-accept-iova_tree_remove_parameter-by-value.patch create mode 100644 util-add-iova_tree_find_iova.patch create mode 100644 vdpa-Adapt-vhost_vdpa_get_vring_base-to-SVQ.patch create mode 100644 vdpa-Add-custom-IOTLB-translations-to-SVQ.patch create mode 100644 vdpa-Add-device-migration-blocker.patch create mode 100644 vdpa-Add-missing-tracing-to-batch-mapping-functions.patch create mode 100644 vdpa-Add-vhost_vdpa_net_load_mq.patch create mode 100644 vdpa-Add-virtio-net-mac-address-via-CVQ-at-start.patch create mode 100644 vdpa-Add-x-svq-to-NetdevVhostVDPAOptions.patch create mode 100644 vdpa-Allow-MQ-feature-in-SVQ.patch create mode 100644 vdpa-Avoid-compiler-to-squash-reads-to-used-idx.patch create mode 100644 vdpa-Buffer-CVQ-support-on-shadow-virtqueue.patch create mode 100644 vdpa-Delete-CVQ-migration-blocker.patch create mode 100644 vdpa-Delete-duplicated-vdpa_feature_bits-entry.patch create mode 100644 vdpa-Export-vhost_vdpa_dma_map-and-unmap-calls.patch create mode 100644 vdpa-Expose-VHOST_F_LOG_ALL-on-SVQ.patch create mode 100644 vdpa-Extract-get-features-part-from-vhost_vdpa_get_m.patch create mode 100644 vdpa-Fix-bad-index-calculus-at-vhost_vdpa_get_vring_.patch create mode 100644 vdpa-Fix-file-descriptor-leak-on-get-features-error.patch create mode 100644 vdpa-Fix-index-calculus-at-vhost_vdpa_svqs_start.patch create mode 100644 vdpa-Fix-memory-listener-deletions-of-iova-tree.patch create mode 100644 vdpa-Fix-possible-use-after-free-for-VirtQueueElemen.patch create mode 100644 vdpa-Make-SVQ-vring-unmapping-return-void.patch create mode 100644 vdpa-Make-VhostVDPAState-cvq_cmd_in_buffer-control-a.patch create mode 100644 vdpa-Make-ncs-autofree.patch create mode 100644 vdpa-Move-command-buffers-map-to-start-of-net-device.patch create mode 100644 vdpa-Never-set-log_base-addr-if-SVQ-is-enabled.patch create mode 100644 vdpa-Remove-SVQ-vring-from-iova_tree-at-shutdown.patch create mode 100644 vdpa-Remove-shadow-CVQ-command-check.patch create mode 100644 vdpa-Return-EIO-if-device-ack-is-VIRTIO_NET_ERR-in-_-new.patch create mode 100644 vdpa-Return-EIO-if-device-ack-is-VIRTIO_NET_ERR-in-_.patch create mode 100644 vdpa-Skip-the-maps-not-in-the-iova-tree.patch create mode 100644 vdpa-Use-ring-hwaddr-at-vhost_vdpa_svq_unmap_ring.patch create mode 100644 vdpa-adapt-vhost_ops-callbacks-to-svq.patch create mode 100644 vdpa-add-asid-parameter-to-vhost_vdpa_dma_map-unmap.patch create mode 100644 vdpa-add-net_vhost_vdpa_cvq_info-NetClientInfo.patch create mode 100644 vdpa-add-shadow_data-to-vhost_vdpa.patch create mode 100644 vdpa-add-vhost_vdpa_net_valid_svq_features.patch create mode 100644 vdpa-allocate-SVQ-array-unconditionally.patch create mode 100644 vdpa-always-start-CVQ-in-SVQ-mode-if-possible.patch create mode 100644 vdpa-commit-all-host-notifier-MRs-in-a-single-MR-tra.patch create mode 100644 vdpa-dev-get-iova-range-explicitly.patch create mode 100644 vdpa-do-not-block-migration-if-device-has-cvq-and-x-.patch create mode 100644 vdpa-do-not-handle-VIRTIO_NET_F_GUEST_ANNOUNCE-in-vh.patch create mode 100644 vdpa-do-not-save-failed-dma-maps-in-SVQ-iova-tree.patch create mode 100644 vdpa-extract-vhost_vdpa_net_cvq_add-from-vhost_vdpa_.patch create mode 100644 vdpa-extract-vhost_vdpa_net_load_mac-from-vhost_vdpa.patch create mode 100644 vdpa-fix-VHOST_BACKEND_F_IOTLB_ASID-flag-check.patch create mode 100644 vdpa-fix-not-using-CVQ-buffer-in-case-of-error.patch create mode 100644 vdpa-handle-VIRTIO_NET_CTRL_ANNOUNCE-in-vhost_vdpa_n.patch create mode 100644 vdpa-harden-the-error-path-if-get_iova_range-failed.patch create mode 100644 vdpa-manual-forward-CVQ-buffers.patch create mode 100644 vdpa-move-SVQ-vring-features-check-to-net.patch create mode 100644 vdpa-net-block-migration-if-the-device-has-CVQ.patch create mode 100644 vdpa-request-iova_range-only-once.patch create mode 100644 vdpa-stop-all-svq-on-device-deletion.patch create mode 100644 vdpa-store-x-svq-parameter-in-VhostVDPAState.patch create mode 100644 vdpa-use-v-shadow_vqs_enabled-in-vhost_vdpa_svqs_sta.patch create mode 100644 vdpa-validate-MQ-CVQ-commands.patch create mode 100644 vga-avoid-crash-if-no-default-vga-card.patch create mode 100644 vhost-Add-SVQDescState.patch create mode 100644 vhost-Add-Shadow-VirtQueue-call-forwarding-capabilit.patch create mode 100644 vhost-Add-Shadow-VirtQueue-kick-forwarding-capabilit.patch create mode 100644 vhost-Add-VhostIOVATree.patch create mode 100644 vhost-Add-VhostShadowVirtqueue.patch create mode 100644 vhost-Add-svq-avail_handler-callback.patch create mode 100644 vhost-Add-vhost_svq_valid_features-to-shadow-vq.patch create mode 100644 vhost-Always-store-new-kick-fd-on-vhost_svq_set_svq_.patch create mode 100644 vhost-Check-for-queue-full-at-vhost_svq_add.patch create mode 100644 vhost-Decouple-vhost_svq_add-from-VirtQueueElement.patch create mode 100644 vhost-Expose-vhost_svq_add.patch create mode 100644 vhost-Fix-device-s-used-descriptor-dequeue.patch create mode 100644 vhost-Fix-element-in-vhost_svq_add-failure.patch create mode 100644 vhost-Fix-false-positive-out-of-bounds.patch create mode 100644 vhost-Get-vring-base-from-vq-not-svq.patch create mode 100644 vhost-Move-vhost_svq_kick-call-to-vhost_svq_add.patch create mode 100644 vhost-Reorder-vhost_svq_kick.patch create mode 100644 vhost-Shadow-virtqueue-buffers-forwarding.patch create mode 100644 vhost-Track-descriptor-chain-in-private-at-SVQ.patch create mode 100644 vhost-Track-number-of-descs-in-SVQDescState.patch create mode 100644 vhost-add-support-for-configure-interrupt-new.patch create mode 100644 vhost-add-support-for-configure-interrupt.patch create mode 100644 vhost-add-vhost_svq_poll.patch create mode 100644 vhost-add-vhost_svq_push_elem.patch create mode 100644 vhost-allocate-SVQ-device-file-descriptors-at-device.patch create mode 100644 vhost-enable-vrings-in-vhost_dev_start-for-vhost-use.patch create mode 100644 vhost-fix-possible-wrap-in-SVQ-descriptor-ring.patch create mode 100644 vhost-fix-the-fd-leak.patch create mode 100644 vhost-fix-vq-dirty-bitmap-syncing-when-vIOMMU-is-ena.patch create mode 100644 vhost-introduce-new-VhostOps-vhost_set_config_call-new.patch create mode 100644 vhost-introduce-new-VhostOps-vhost_set_config_call.patch create mode 100644 vhost-move-descriptor-translation-to-vhost_svq_vring.patch create mode 100644 vhost-move-iova_tree-set-to-vhost_svq_start.patch create mode 100644 vhost-release-virtqueue-objects-in-error-path.patch create mode 100644 vhost-set-SVQ-device-call-handler-at-SVQ-start.patch create mode 100644 vhost-stick-to-errno-error-return-convention.patch create mode 100644 vhost-user-stick-to-errno-error-return-convention.patch create mode 100644 vhost-vdpa-add-support-for-config-interrupt-new.patch create mode 100644 vhost-vdpa-add-support-for-config-interrupt.patch create mode 100644 vhost-vdpa-allow-passing-opened-vhostfd-to-vhost-vdp.patch create mode 100644 vhost-vdpa-backend-feature-should-set-only-once.patch create mode 100644 vhost-vdpa-change-name-and-polarity-for-vhost_vdpa_o.patch create mode 100644 vhost-vdpa-fix-assert-virtio_net_get_subqueue-nc-asy.patch create mode 100644 vhost-vdpa-fix-improper-cleanup-in-net_init_vhost_vd.patch create mode 100644 vhost-vdpa-fix-typo-in-a-comment.patch create mode 100644 vhost-vdpa-stick-to-errno-error-return-convention.patch create mode 100644 vhost_net-Add-NetClientInfo-start-callback.patch create mode 100644 vhost_net-Add-NetClientInfo-stop-callback.patch create mode 100644 vhost_net-add-NetClientState-load-callback.patch create mode 100644 virtio-Add-vhost_svq_get_vring_addr.patch create mode 100644 virtio-add-support-for-configure-interrupt-new.patch create mode 100644 virtio-add-support-for-configure-interrupt.patch create mode 100644 virtio-add-vhost-support-for-virtio-devices.patch create mode 100644 virtio-crypto-verify-src-dst-buffer-length-for-sym-request.patch create mode 100644 virtio-fix-enable-vhost-user-build-on-non-Linux.patch create mode 100644 virtio-i2c-Check-notifier-helpers-for-VIRTIO_CONFIG_.patch create mode 100644 virtio-introduce-macro-IRTIO_CONFIG_IRQ_IDX.patch create mode 100644 virtio-introduce-macro-VIRTIO_CONFIG_IRQ_IDX.patch create mode 100644 virtio-iommu-Fix-the-partial-copy-of-probe-request.patch create mode 100644 virtio-mmio-add-support-for-configure-interrupt-new.patch create mode 100644 virtio-mmio-add-support-for-configure-interrupt.patch create mode 100644 virtio-net-Expose-MAC_TABLE_ENTRIES.patch create mode 100644 virtio-net-Expose-ctrl-virtqueue-logic.patch create mode 100644 virtio-net-Update-virtio-net-curr_queue_pairs-in-vdp.patch create mode 100644 virtio-net-add-support-for-configure-interrupt-new.patch create mode 100644 virtio-net-add-support-for-configure-interrupt.patch create mode 100644 virtio-net-align-ctrl_vq-index-for-non-mq-guest-for-.patch create mode 100644 virtio-net-clear-guest_announce-feature-if-no-cvq-ba.patch create mode 100644 virtio-net-don-t-handle-mq-request-in-userspace-hand.patch create mode 100644 virtio-pci-add-support-for-configure-interrupt-new.patch create mode 100644 virtio-pci-add-support-for-configure-interrupt.patch create mode 100644 virtio-pci-decouple-notifier-from-interrupt-process-new.patch create mode 100644 virtio-pci-decouple-notifier-from-interrupt-process.patch create mode 100644 virtio-pci-decouple-the-single-vector-from-the-inter-new.patch create mode 100644 virtio-pci-decouple-the-single-vector-from-the-inter.patch create mode 100644 virtio-signal-after-wrapping-packed-used_idx.patch diff --git a/Revert-vhost-add-support-for-configure-interrupt.patch b/Revert-vhost-add-support-for-configure-interrupt.patch new file mode 100644 index 00000000..e3306923 --- /dev/null +++ b/Revert-vhost-add-support-for-configure-interrupt.patch @@ -0,0 +1,163 @@ +From 529074fd45a543a9259441e02652c3ac60673d07 Mon Sep 17 00:00:00 2001 +From: fangyi +Date: Wed, 22 Nov 2023 09:53:34 +0800 +Subject: [PATCH] Revert "vhost: add support for configure interrupt" + +This reverts commit f7220a7ce21604a4bc6260ccca4dc9068c1f27f2. + +Fixes: f7220a7ce2 ("vhost: add support for configure interrupt") +Cc: "Cindy Lu" +Signed-off-by: Michael S. Tsirkin +Signed-off-by: fangyi +--- + hw/virtio/vhost.c | 76 --------------------------------------- + include/hw/virtio/vhost.h | 4 --- + 2 files changed, 80 deletions(-) + +diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c +index caa53443ab..2f9bb96d63 100644 +--- a/hw/virtio/vhost.c ++++ b/hw/virtio/vhost.c +@@ -1581,67 +1581,6 @@ void vhost_virtqueue_mask(struct vhost_dev *hdev, VirtIODevice *vdev, int n, + } + } + +-bool vhost_config_pending(struct vhost_dev *hdev) +-{ +- assert(hdev->vhost_ops); +- if ((hdev->started == false) || +- (hdev->vhost_ops->vhost_set_config_call == NULL)) { +- return false; +- } +- +- EventNotifier *notifier = +- &hdev->vqs[VHOST_QUEUE_NUM_CONFIG_INR].masked_config_notifier; +- return event_notifier_test_and_clear(notifier); +-} +- +-void vhost_config_mask(struct vhost_dev *hdev, VirtIODevice *vdev, bool mask) +-{ +- int fd; +- int r; +- EventNotifier *notifier = +- &hdev->vqs[VHOST_QUEUE_NUM_CONFIG_INR].masked_config_notifier; +- EventNotifier *config_notifier = &vdev->config_notifier; +- assert(hdev->vhost_ops); +- +- if ((hdev->started == false) || +- (hdev->vhost_ops->vhost_set_config_call == NULL)) { +- return; +- } +- if (mask) { +- assert(vdev->use_guest_notifier_mask); +- fd = event_notifier_get_fd(notifier); +- } else { +- fd = event_notifier_get_fd(config_notifier); +- } +- r = hdev->vhost_ops->vhost_set_config_call(hdev, fd); +- if (r < 0) { +- VHOST_OPS_DEBUG(r, "vhost_set_config_call failed"); +- } +-} +- +-static void vhost_stop_config_intr(struct vhost_dev *dev) +-{ +- int fd = -1; +- assert(dev->vhost_ops); +- if (dev->vhost_ops->vhost_set_config_call) { +- dev->vhost_ops->vhost_set_config_call(dev, fd); +- } +-} +- +-static void vhost_start_config_intr(struct vhost_dev *dev) +-{ +- int r; +- +- assert(dev->vhost_ops); +- int fd = event_notifier_get_fd(&dev->vdev->config_notifier); +- if (dev->vhost_ops->vhost_set_config_call) { +- r = dev->vhost_ops->vhost_set_config_call(dev, fd); +- if (!r) { +- event_notifier_set(&dev->vdev->config_notifier); +- } +- } +-} +- + uint64_t vhost_get_features(struct vhost_dev *hdev, const int *feature_bits, + uint64_t features) + { +@@ -1854,16 +1793,6 @@ int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev) + } + } + +- r = event_notifier_init( +- &hdev->vqs[VHOST_QUEUE_NUM_CONFIG_INR].masked_config_notifier, 0); +- if (r < 0) { +- return r; +- } +- event_notifier_test_and_clear( +- &hdev->vqs[VHOST_QUEUE_NUM_CONFIG_INR].masked_config_notifier); +- if (!vdev->use_guest_notifier_mask) { +- vhost_config_mask(hdev, vdev, true); +- } + if (hdev->log_enabled) { + uint64_t log_base; + +@@ -1896,7 +1825,6 @@ int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev) + vhost_device_iotlb_miss(hdev, vq->used_phys, true); + } + } +- vhost_start_config_intr(hdev); + return 0; + fail_log: + vhost_log_put(hdev, false); +@@ -1922,9 +1850,6 @@ void vhost_dev_stop(struct vhost_dev *hdev, VirtIODevice *vdev) + + /* should only be called after backend is connected */ + assert(hdev->vhost_ops); +- event_notifier_test_and_clear( +- &hdev->vqs[VHOST_QUEUE_NUM_CONFIG_INR].masked_config_notifier); +- event_notifier_test_and_clear(&vdev->config_notifier); + + if (hdev->vhost_ops->vhost_dev_start) { + hdev->vhost_ops->vhost_dev_start(hdev, false); +@@ -1942,7 +1867,6 @@ void vhost_dev_stop(struct vhost_dev *hdev, VirtIODevice *vdev) + } + memory_listener_unregister(&hdev->iommu_listener); + } +- vhost_stop_config_intr(hdev); + vhost_log_put(hdev, true); + hdev->started = false; + hdev->vdev = NULL; +diff --git a/include/hw/virtio/vhost.h b/include/hw/virtio/vhost.h +index 2ae5c3bfd8..86f36f0106 100644 +--- a/include/hw/virtio/vhost.h ++++ b/include/hw/virtio/vhost.h +@@ -29,7 +29,6 @@ struct vhost_virtqueue { + unsigned long long used_phys; + unsigned used_size; + EventNotifier masked_notifier; +- EventNotifier masked_config_notifier; + struct vhost_dev *dev; + }; + +@@ -38,7 +37,6 @@ typedef unsigned long vhost_log_chunk_t; + #define VHOST_LOG_BITS (8 * sizeof(vhost_log_chunk_t)) + #define VHOST_LOG_CHUNK (VHOST_LOG_PAGE * VHOST_LOG_BITS) + #define VHOST_INVALID_FEATURE_BIT (0xff) +-#define VHOST_QUEUE_NUM_CONFIG_INR 0 + + struct vhost_log { + unsigned long long size; +@@ -118,8 +116,6 @@ int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev); + void vhost_dev_stop(struct vhost_dev *hdev, VirtIODevice *vdev); + int vhost_dev_enable_notifiers(struct vhost_dev *hdev, VirtIODevice *vdev); + void vhost_dev_disable_notifiers(struct vhost_dev *hdev, VirtIODevice *vdev); +-bool vhost_config_pending(struct vhost_dev *hdev); +-void vhost_config_mask(struct vhost_dev *hdev, VirtIODevice *vdev, bool mask); + + /* Test and clear masked event pending status. + * Should be called after unmask to avoid losing events. +-- +2.27.0 + diff --git a/Revert-vhost-introduce-new-VhostOps-vhost_set_config.patch b/Revert-vhost-introduce-new-VhostOps-vhost_set_config.patch new file mode 100644 index 00000000..7a33b479 --- /dev/null +++ b/Revert-vhost-introduce-new-VhostOps-vhost_set_config.patch @@ -0,0 +1,36 @@ +From 0ad1ce1ff54a4d654c00e4a3b95361b519f4fd37 Mon Sep 17 00:00:00 2001 +From: fangyi +Date: Wed, 22 Nov 2023 09:43:37 +0800 +Subject: [PATCH] Revert "vhost: introduce new VhostOps vhost_set_config_call" + +This reverts commit af8377d0e9437401ad30d80a27ab1fcf8252fad1. + +Signed-off-by: fangyi +--- + include/hw/virtio/vhost-backend.h | 3 --- + 1 file changed, 3 deletions(-) + +diff --git a/include/hw/virtio/vhost-backend.h b/include/hw/virtio/vhost-backend.h +index bd1c7dfe4f..a64708f456 100644 +--- a/include/hw/virtio/vhost-backend.h ++++ b/include/hw/virtio/vhost-backend.h +@@ -125,8 +125,6 @@ typedef int (*vhost_vq_get_addr_op)(struct vhost_dev *dev, + typedef int (*vhost_get_device_id_op)(struct vhost_dev *dev, uint32_t *dev_id); + + typedef bool (*vhost_force_iommu_op)(struct vhost_dev *dev); +-typedef int (*vhost_set_config_call_op)(struct vhost_dev *dev, +- int fd); + typedef void (*vhost_set_used_memslots_op)(struct vhost_dev *dev); + typedef unsigned int (*vhost_get_used_memslots_op)(void); + +@@ -175,7 +173,6 @@ typedef struct VhostOps { + vhost_vq_get_addr_op vhost_vq_get_addr; + vhost_get_device_id_op vhost_get_device_id; + vhost_force_iommu_op vhost_force_iommu; +- vhost_set_config_call_op vhost_set_config_call; + vhost_set_used_memslots_op vhost_set_used_memslots; + vhost_get_used_memslots_op vhost_get_used_memslots; + } VhostOps; +-- +2.27.0 + diff --git a/Revert-vhost-vdpa-add-support-for-config-interrupt.patch b/Revert-vhost-vdpa-add-support-for-config-interrupt.patch new file mode 100644 index 00000000..725ea3bb --- /dev/null +++ b/Revert-vhost-vdpa-add-support-for-config-interrupt.patch @@ -0,0 +1,56 @@ +From 92df45517567838512512f093f418067c857e8dc Mon Sep 17 00:00:00 2001 +From: fangyi +Date: Wed, 22 Nov 2023 09:58:20 +0800 +Subject: [PATCH] Revert "vhost-vdpa: add support for config interrupt" + +This reverts commit 634f7c89fbd78f57d00d5d6b39c0ade9df1fe27f. + +Fixes: 634f7c89fb ("vhost-vdpa: add support for config interrupt") +Cc: "Cindy Lu" +Signed-off-by: Michael S. Tsirkin +Signed-off-by: fangyi +--- + hw/virtio/trace-events | 1 - + hw/virtio/vhost-vdpa.c | 7 ------- + 2 files changed, 8 deletions(-) + +diff --git a/hw/virtio/trace-events b/hw/virtio/trace-events +index 39c36ff7a6..650e521e35 100644 +--- a/hw/virtio/trace-events ++++ b/hw/virtio/trace-events +@@ -53,7 +53,6 @@ vhost_vdpa_get_features(void *dev, uint64_t features) "dev: %p features: 0x%"PRI + vhost_vdpa_set_owner(void *dev) "dev: %p" + vhost_vdpa_vq_get_addr(void *dev, void *vq, uint64_t desc_user_addr, uint64_t avail_user_addr, uint64_t used_user_addr) "dev: %p vq: %p desc_user_addr: 0x%"PRIx64" avail_user_addr: 0x%"PRIx64" used_user_addr: 0x%"PRIx64 + vhost_vdpa_get_iova_range(void *dev, uint64_t first, uint64_t last) "dev: %p first: 0x%"PRIx64" last: 0x%"PRIx64 +-vhost_vdpa_set_config_call(void *dev, int fd)"dev: %p fd: %d" + + # virtio.c + virtqueue_alloc_element(void *elem, size_t sz, unsigned in_num, unsigned out_num) "elem %p size %zd in_num %u out_num %u" +diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c +index d8fba0b714..25a2f570a2 100644 +--- a/hw/virtio/vhost-vdpa.c ++++ b/hw/virtio/vhost-vdpa.c +@@ -737,12 +737,6 @@ static int vhost_vdpa_set_vring_call(struct vhost_dev *dev, + trace_vhost_vdpa_set_vring_call(dev, file->index, file->fd); + return vhost_vdpa_call(dev, VHOST_SET_VRING_CALL, file); + } +-static int vhost_vdpa_set_config_call(struct vhost_dev *dev, +- int fd) +-{ +- trace_vhost_vdpa_set_config_call(dev, fd); +- return vhost_vdpa_call(dev, VHOST_VDPA_SET_CONFIG_CALL, &fd); +-} + + static int vhost_vdpa_get_features(struct vhost_dev *dev, + uint64_t *features) +@@ -823,7 +817,6 @@ const VhostOps vdpa_ops = { + .vhost_get_device_id = vhost_vdpa_get_device_id, + .vhost_vq_get_addr = vhost_vdpa_vq_get_addr, + .vhost_force_iommu = vhost_vdpa_force_iommu, +- .vhost_set_config_call = vhost_vdpa_set_config_call, + .vhost_set_used_memslots = vhost_vdpa_set_used_memslots, + .vhost_get_used_memslots = vhost_vdpa_get_used_memslots, + }; +-- +2.27.0 + diff --git a/Revert-virtio-add-support-for-configure-interrupt.patch b/Revert-virtio-add-support-for-configure-interrupt.patch new file mode 100644 index 00000000..41dfe165 --- /dev/null +++ b/Revert-virtio-add-support-for-configure-interrupt.patch @@ -0,0 +1,101 @@ +From 3ee9abc7cdd10ccb7057a523326fec21fb01a7bb Mon Sep 17 00:00:00 2001 +From: fangyi +Date: Wed, 22 Nov 2023 09:55:19 +0800 +Subject: [PATCH] Revert "virtio: add support for configure interrupt" + +This reverts commit 081f864f56307551f59c5e934e3f30a7290d0faa. + +Fixes: 081f864f56 ("virtio: add support for configure interrupt") +Cc: "Cindy Lu" +Signed-off-by: Michael S. Tsirkin +Signed-off-by: fangyi +--- + hw/virtio/virtio.c | 29 ----------------------------- + include/hw/virtio/virtio.h | 4 ---- + 2 files changed, 33 deletions(-) + +diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c +index 05409b84d1..c1497f59aa 100644 +--- a/hw/virtio/virtio.c ++++ b/hw/virtio/virtio.c +@@ -3547,14 +3547,7 @@ static void virtio_queue_guest_notifier_read(EventNotifier *n) + virtio_irq(vq); + } + } +-static void virtio_config_guest_notifier_read(EventNotifier *n) +-{ +- VirtIODevice *vdev = container_of(n, VirtIODevice, config_notifier); + +- if (event_notifier_test_and_clear(n)) { +- virtio_notify_config(vdev); +- } +-} + void virtio_queue_set_guest_notifier_fd_handler(VirtQueue *vq, bool assign, + bool with_irqfd) + { +@@ -3571,23 +3564,6 @@ void virtio_queue_set_guest_notifier_fd_handler(VirtQueue *vq, bool assign, + } + } + +-void virtio_config_set_guest_notifier_fd_handler(VirtIODevice *vdev, +- bool assign, bool with_irqfd) +-{ +- EventNotifier *n; +- n = &vdev->config_notifier; +- if (assign && !with_irqfd) { +- event_notifier_set_handler(n, virtio_config_guest_notifier_read); +- } else { +- event_notifier_set_handler(n, NULL); +- } +- if (!assign) { +- /* Test and clear notifier before closing it,*/ +- /* in case poll callback didn't have time to run. */ +- virtio_config_guest_notifier_read(n); +- } +-} +- + EventNotifier *virtio_queue_get_guest_notifier(VirtQueue *vq) + { + return &vq->guest_notifier; +@@ -3661,11 +3637,6 @@ EventNotifier *virtio_queue_get_host_notifier(VirtQueue *vq) + return &vq->host_notifier; + } + +-EventNotifier *virtio_config_get_guest_notifier(VirtIODevice *vdev) +-{ +- return &vdev->config_notifier; +-} +- + void virtio_queue_set_host_notifier_enabled(VirtQueue *vq, bool enabled) + { + vq->host_notifier_enabled = enabled; +diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h +index 8788ccd1f3..c113a5b864 100644 +--- a/include/hw/virtio/virtio.h ++++ b/include/hw/virtio/virtio.h +@@ -112,7 +112,6 @@ struct VirtIODevice + bool use_guest_notifier_mask; + AddressSpace *dma_as; + QLIST_HEAD(, VirtQueue) *vector_queues; +- EventNotifier config_notifier; + }; + + struct VirtioDeviceClass { +@@ -316,14 +315,11 @@ uint16_t virtio_get_queue_index(VirtQueue *vq); + EventNotifier *virtio_queue_get_guest_notifier(VirtQueue *vq); + void virtio_queue_set_guest_notifier_fd_handler(VirtQueue *vq, bool assign, + bool with_irqfd); +-void virtio_config_set_guest_notifier_fd_handler(VirtIODevice *vdev, +- bool assign, bool with_irqfd); + int virtio_device_start_ioeventfd(VirtIODevice *vdev); + int virtio_device_grab_ioeventfd(VirtIODevice *vdev); + void virtio_device_release_ioeventfd(VirtIODevice *vdev); + bool virtio_device_ioeventfd_enabled(VirtIODevice *vdev); + EventNotifier *virtio_queue_get_host_notifier(VirtQueue *vq); +-EventNotifier *virtio_config_get_guest_notifier(VirtIODevice *vdev); + void virtio_queue_set_host_notifier_enabled(VirtQueue *vq, bool enabled); + void virtio_queue_host_notifier_read(EventNotifier *n); + void virtio_queue_aio_set_host_notifier_handler(VirtQueue *vq, AioContext *ctx, +-- +2.27.0 + diff --git a/Revert-virtio-introduce-macro-IRTIO_CONFIG_IRQ_IDX.patch b/Revert-virtio-introduce-macro-IRTIO_CONFIG_IRQ_IDX.patch new file mode 100644 index 00000000..b87ac137 --- /dev/null +++ b/Revert-virtio-introduce-macro-IRTIO_CONFIG_IRQ_IDX.patch @@ -0,0 +1,161 @@ +From 01e4e3aa5f2e2e44b72e81e76a74821edf2debd3 Mon Sep 17 00:00:00 2001 +From: fangyi +Date: Wed, 22 Nov 2023 10:05:16 +0800 +Subject: [PATCH] Revert "virtio: introduce macro IRTIO_CONFIG_IRQ_IDX" + +This reverts commit bf1d85c166c19af95dbd27b1faba1d2909732323. + +Fixes: bf1d85c166 ("virtio: introduce macro IRTIO_CONFIG_IRQ_IDX") +Cc: "Cindy Lu" +Signed-off-by: Michael S. Tsirkin +Signed-off-by: fangyi +--- + hw/display/vhost-user-gpu.c | 6 ------ + hw/net/virtio-net.c | 10 ++-------- + hw/virtio/vhost-user-fs.c | 6 ------ + hw/virtio/vhost-vsock-common.c | 6 ------ + hw/virtio/virtio-crypto.c | 6 ------ + include/hw/virtio/virtio.h | 3 --- + 6 files changed, 2 insertions(+), 35 deletions(-) + +diff --git a/hw/display/vhost-user-gpu.c b/hw/display/vhost-user-gpu.c +index 73ad3d84c9..49df56cd14 100644 +--- a/hw/display/vhost-user-gpu.c ++++ b/hw/display/vhost-user-gpu.c +@@ -485,9 +485,6 @@ vhost_user_gpu_guest_notifier_pending(VirtIODevice *vdev, int idx) + { + VhostUserGPU *g = VHOST_USER_GPU(vdev); + +- if (idx == VIRTIO_CONFIG_IRQ_IDX) { +- return false; +- } + return vhost_virtqueue_pending(&g->vhost->dev, idx); + } + +@@ -496,9 +493,6 @@ vhost_user_gpu_guest_notifier_mask(VirtIODevice *vdev, int idx, bool mask) + { + VhostUserGPU *g = VHOST_USER_GPU(vdev); + +- if (idx == VIRTIO_CONFIG_IRQ_IDX) { +- return; +- } + vhost_virtqueue_mask(&g->vhost->dev, vdev, idx, mask); + } + +diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c +index 7537f44d10..3bd786cc22 100644 +--- a/hw/net/virtio-net.c ++++ b/hw/net/virtio-net.c +@@ -3195,9 +3195,6 @@ static bool virtio_net_guest_notifier_pending(VirtIODevice *vdev, int idx) + VirtIONet *n = VIRTIO_NET(vdev); + NetClientState *nc = qemu_get_subqueue(n->nic, vq2q(idx)); + assert(n->vhost_started); +- if (idx == VIRTIO_CONFIG_IRQ_IDX) { +- return false; +- } + return vhost_net_virtqueue_pending(get_vhost_net(nc->peer), idx); + } + +@@ -3207,11 +3204,8 @@ static void virtio_net_guest_notifier_mask(VirtIODevice *vdev, int idx, + VirtIONet *n = VIRTIO_NET(vdev); + NetClientState *nc = qemu_get_subqueue(n->nic, vq2q(idx)); + assert(n->vhost_started); +- if (idx == VIRTIO_CONFIG_IRQ_IDX) { +- return; +- } +- +- vhost_net_virtqueue_mask(get_vhost_net(nc->peer), vdev, idx, mask); ++ vhost_net_virtqueue_mask(get_vhost_net(nc->peer), ++ vdev, idx, mask); + } + + static void virtio_net_set_config_size(VirtIONet *n, uint64_t host_features) +diff --git a/hw/virtio/vhost-user-fs.c b/hw/virtio/vhost-user-fs.c +index 90c2bc9c5d..fc7dcc96ef 100644 +--- a/hw/virtio/vhost-user-fs.c ++++ b/hw/virtio/vhost-user-fs.c +@@ -161,9 +161,6 @@ static void vuf_guest_notifier_mask(VirtIODevice *vdev, int idx, + { + VHostUserFS *fs = VHOST_USER_FS(vdev); + +- if (idx == VIRTIO_CONFIG_IRQ_IDX) { +- return; +- } + vhost_virtqueue_mask(&fs->vhost_dev, vdev, idx, mask); + } + +@@ -171,9 +168,6 @@ static bool vuf_guest_notifier_pending(VirtIODevice *vdev, int idx) + { + VHostUserFS *fs = VHOST_USER_FS(vdev); + +- if (idx == VIRTIO_CONFIG_IRQ_IDX) { +- return false; +- } + return vhost_virtqueue_pending(&fs->vhost_dev, idx); + } + +diff --git a/hw/virtio/vhost-vsock-common.c b/hw/virtio/vhost-vsock-common.c +index b1f0d46209..ed706681ac 100644 +--- a/hw/virtio/vhost-vsock-common.c ++++ b/hw/virtio/vhost-vsock-common.c +@@ -125,9 +125,6 @@ static void vhost_vsock_common_guest_notifier_mask(VirtIODevice *vdev, int idx, + { + VHostVSockCommon *vvc = VHOST_VSOCK_COMMON(vdev); + +- if (idx == VIRTIO_CONFIG_IRQ_IDX) { +- return; +- } + vhost_virtqueue_mask(&vvc->vhost_dev, vdev, idx, mask); + } + +@@ -136,9 +133,6 @@ static bool vhost_vsock_common_guest_notifier_pending(VirtIODevice *vdev, + { + VHostVSockCommon *vvc = VHOST_VSOCK_COMMON(vdev); + +- if (idx == VIRTIO_CONFIG_IRQ_IDX) { +- return false; +- } + return vhost_virtqueue_pending(&vvc->vhost_dev, idx); + } + +diff --git a/hw/virtio/virtio-crypto.c b/hw/virtio/virtio-crypto.c +index 52ba34ef1e..274c7b4dea 100644 +--- a/hw/virtio/virtio-crypto.c ++++ b/hw/virtio/virtio-crypto.c +@@ -953,9 +953,6 @@ static void virtio_crypto_guest_notifier_mask(VirtIODevice *vdev, int idx, + + assert(vcrypto->vhost_started); + +- if (idx == VIRTIO_CONFIG_IRQ_IDX) { +- return; +- } + cryptodev_vhost_virtqueue_mask(vdev, queue, idx, mask); + } + +@@ -966,9 +963,6 @@ static bool virtio_crypto_guest_notifier_pending(VirtIODevice *vdev, int idx) + + assert(vcrypto->vhost_started); + +- if (idx == VIRTIO_CONFIG_IRQ_IDX) { +- return false; +- } + return cryptodev_vhost_virtqueue_pending(vdev, queue, idx); + } + +diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h +index c113a5b864..7472145821 100644 +--- a/include/hw/virtio/virtio.h ++++ b/include/hw/virtio/virtio.h +@@ -68,9 +68,6 @@ typedef struct VirtQueueElement + + #define VIRTIO_NO_VECTOR 0xffff + +-/* special index value used internally for config irqs */ +-#define VIRTIO_CONFIG_IRQ_IDX -1 +- + #define TYPE_VIRTIO_DEVICE "virtio-device" + OBJECT_DECLARE_TYPE(VirtIODevice, VirtioDeviceClass, VIRTIO_DEVICE) + +-- +2.27.0 + diff --git a/Revert-virtio-mmio-add-support-for-configure-interru.patch b/Revert-virtio-mmio-add-support-for-configure-interru.patch new file mode 100644 index 00000000..b87a9798 --- /dev/null +++ b/Revert-virtio-mmio-add-support-for-configure-interru.patch @@ -0,0 +1,64 @@ +From 9633634fe4395000e88c8ab829ec756c7132d3bf Mon Sep 17 00:00:00 2001 +From: fangyi +Date: Wed, 22 Nov 2023 09:48:17 +0800 +Subject: [PATCH] Revert "virtio-mmio: add support for configure interrupt" + +This reverts commit d48185f1a40d4e4ed2fa2873a42b2a5eb8748256. + +Fixes: d48185f1a4 ("virtio-mmio: add support for configure interrupt") +Cc: "Cindy Lu" +Signed-off-by: Michael S. Tsirkin +Signed-off-by: fangyi +--- + hw/virtio/virtio-mmio.c | 27 --------------------------- + 1 file changed, 27 deletions(-) + +diff --git a/hw/virtio/virtio-mmio.c b/hw/virtio/virtio-mmio.c +index 809132018b..72da12fea5 100644 +--- a/hw/virtio/virtio-mmio.c ++++ b/hw/virtio/virtio-mmio.c +@@ -673,30 +673,7 @@ static int virtio_mmio_set_guest_notifier(DeviceState *d, int n, bool assign, + + return 0; + } +-static int virtio_mmio_set_config_guest_notifier(DeviceState *d, bool assign) +-{ +- VirtIOMMIOProxy *proxy = VIRTIO_MMIO(d); +- VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); +- VirtioDeviceClass *vdc = VIRTIO_DEVICE_GET_CLASS(vdev); +- bool with_irqfd = false; +- EventNotifier *notifier = virtio_config_get_guest_notifier(vdev); +- int r = 0; + +- if (assign) { +- r = event_notifier_init(notifier, 0); +- if (r < 0) { +- return r; +- } +- virtio_config_set_guest_notifier_fd_handler(vdev, assign, with_irqfd); +- } else { +- virtio_config_set_guest_notifier_fd_handler(vdev, assign, with_irqfd); +- event_notifier_cleanup(notifier); +- } +- if (vdc->guest_notifier_mask && vdev->use_guest_notifier_mask) { +- vdc->guest_notifier_mask(vdev, VIRTIO_CONFIG_IRQ_IDX, !assign); +- } +- return r; +-} + static int virtio_mmio_set_guest_notifiers(DeviceState *d, int nvqs, + bool assign) + { +@@ -718,10 +695,6 @@ static int virtio_mmio_set_guest_notifiers(DeviceState *d, int nvqs, + goto assign_error; + } + } +- r = virtio_mmio_set_config_guest_notifier(d, assign); +- if (r < 0) { +- goto assign_error; +- } + + return 0; + +-- +2.27.0 + diff --git a/Revert-virtio-net-add-support-for-configure-interrup.patch b/Revert-virtio-net-add-support-for-configure-interrup.patch new file mode 100644 index 00000000..845af47c --- /dev/null +++ b/Revert-virtio-net-add-support-for-configure-interrup.patch @@ -0,0 +1,52 @@ +From 4f6f9e62214a008523b054c82d663d14d82a2c86 Mon Sep 17 00:00:00 2001 +From: fangyi +Date: Wed, 22 Nov 2023 09:50:43 +0800 +Subject: [PATCH] Revert "virtio-net: add support for configure interrupt" + +This reverts commit 497679d51087090d5a22fd265d1b96cf92d49d9d. + +Fixes: 497679d510 ("virtio-net: add support for configure interrupt") +Cc: "Cindy Lu" +Signed-off-by: Michael S. Tsirkin +Signed-off-by: fangyi +--- + hw/net/vhost_net.c | 9 --------- + include/net/vhost_net.h | 2 -- + 2 files changed, 11 deletions(-) + +diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c +index d5a92144bb..bea053a742 100644 +--- a/hw/net/vhost_net.c ++++ b/hw/net/vhost_net.c +@@ -524,15 +524,6 @@ void vhost_net_virtqueue_mask(VHostNetState *net, VirtIODevice *dev, + vhost_virtqueue_mask(&net->dev, dev, idx, mask); + } + +-bool vhost_net_config_pending(VHostNetState *net) +-{ +- return vhost_config_pending(&net->dev); +-} +- +-void vhost_net_config_mask(VHostNetState *net, VirtIODevice *dev, bool mask) +-{ +- vhost_config_mask(&net->dev, dev, mask); +-} + VHostNetState *get_vhost_net(NetClientState *nc) + { + VHostNetState *vhost_net = 0; +diff --git a/include/net/vhost_net.h b/include/net/vhost_net.h +index 1844f0ed46..7bdbf484e4 100644 +--- a/include/net/vhost_net.h ++++ b/include/net/vhost_net.h +@@ -39,8 +39,6 @@ int vhost_net_set_config(struct vhost_net *net, const uint8_t *data, + bool vhost_net_virtqueue_pending(VHostNetState *net, int n); + void vhost_net_virtqueue_mask(VHostNetState *net, VirtIODevice *dev, + int idx, bool mask); +-bool vhost_net_config_pending(VHostNetState *net); +-void vhost_net_config_mask(VHostNetState *net, VirtIODevice *dev, bool mask); + int vhost_net_notify_migration_done(VHostNetState *net, char* mac_addr); + VHostNetState *get_vhost_net(NetClientState *nc); + +-- +2.27.0 + diff --git a/Revert-virtio-pci-add-support-for-configure-interrup.patch b/Revert-virtio-pci-add-support-for-configure-interrup.patch new file mode 100644 index 00000000..0ce8a4be --- /dev/null +++ b/Revert-virtio-pci-add-support-for-configure-interrup.patch @@ -0,0 +1,215 @@ +From b97597030e537248f3986589cfc4a32a3e7eb8f5 Mon Sep 17 00:00:00 2001 +From: fangyi +Date: Wed, 22 Nov 2023 09:46:06 +0800 +Subject: [PATCH] Revert "virtio-pci: add support for configure interrupt" + +This reverts commit d5d24d859c3957ea1674d0e102f96439cdbfe93a. + +Fixes: d5d24d859c ("virtio-pci: add support for configure interrupt") +Cc: "Cindy Lu" +Signed-off-by: Michael S. Tsirkin +Signed-off-by: fangyi +--- + hw/virtio/virtio-pci.c | 92 ++++++------------------------------------ + hw/virtio/virtio-pci.h | 4 +- + 2 files changed, 13 insertions(+), 83 deletions(-) + +diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c +index 90237f523e..75be770971 100644 +--- a/hw/virtio/virtio-pci.c ++++ b/hw/virtio/virtio-pci.c +@@ -812,8 +812,7 @@ static int virtio_pci_get_notifier(VirtIOPCIProxy *proxy, int queue_no, + VirtQueue *vq; + + if (queue_no == VIRTIO_CONFIG_IRQ_IDX) { +- *n = virtio_config_get_guest_notifier(vdev); +- *vector = vdev->config_vector; ++ return -1; + } else { + if (!virtio_queue_get_num(vdev, queue_no)) { + return -1; +@@ -888,10 +887,6 @@ static int kvm_virtio_pci_vector_use(VirtIOPCIProxy *proxy, int nvqs) + return ret; + } + +-static int kvm_virtio_pci_vector_config_use(VirtIOPCIProxy *proxy) +-{ +- return kvm_virtio_pci_vector_use_one(proxy, VIRTIO_CONFIG_IRQ_IDX); +-} + + static void kvm_virtio_pci_vector_release_one(VirtIOPCIProxy *proxy, + int queue_no) +@@ -929,11 +924,6 @@ static void kvm_virtio_pci_vector_release(VirtIOPCIProxy *proxy, int nvqs) + } + } + +-static void kvm_virtio_pci_vector_config_release(VirtIOPCIProxy *proxy) +-{ +- kvm_virtio_pci_vector_release_one(proxy, VIRTIO_CONFIG_IRQ_IDX); +-} +- + static int virtio_pci_one_vector_unmask(VirtIOPCIProxy *proxy, + unsigned int queue_no, + unsigned int vector, +@@ -1015,17 +1005,9 @@ static int virtio_pci_vector_unmask(PCIDevice *dev, unsigned vector, + } + vq = virtio_vector_next_queue(vq); + } +- /* unmask config intr */ +- n = virtio_config_get_guest_notifier(vdev); +- ret = virtio_pci_one_vector_unmask(proxy, VIRTIO_CONFIG_IRQ_IDX, vector, +- msg, n); +- if (ret < 0) { +- goto undo_config; +- } ++ + return 0; +-undo_config: +- n = virtio_config_get_guest_notifier(vdev); +- virtio_pci_one_vector_mask(proxy, VIRTIO_CONFIG_IRQ_IDX, vector, n); ++ + undo: + vq = virtio_vector_first_queue(vdev, vector); + while (vq && unmasked >= 0) { +@@ -1059,8 +1041,6 @@ static void virtio_pci_vector_mask(PCIDevice *dev, unsigned vector) + } + vq = virtio_vector_next_queue(vq); + } +- n = virtio_config_get_guest_notifier(vdev); +- virtio_pci_one_vector_mask(proxy, VIRTIO_CONFIG_IRQ_IDX, vector, n); + } + + static void virtio_pci_vector_poll(PCIDevice *dev, +@@ -1092,34 +1072,6 @@ static void virtio_pci_vector_poll(PCIDevice *dev, + msix_set_pending(dev, vector); + } + } +- /* poll the config intr */ +- ret = virtio_pci_get_notifier(proxy, VIRTIO_CONFIG_IRQ_IDX, ¬ifier, +- &vector); +- if (ret < 0) { +- return; +- } +- if (vector < vector_start || vector >= vector_end || +- !msix_is_masked(dev, vector)) { +- return; +- } +- if (k->guest_notifier_pending) { +- if (k->guest_notifier_pending(vdev, VIRTIO_CONFIG_IRQ_IDX)) { +- msix_set_pending(dev, vector); +- } +- } else if (event_notifier_test_and_clear(notifier)) { +- msix_set_pending(dev, vector); +- } +-} +- +-void virtio_pci_set_guest_notifier_fd_handler(VirtIODevice *vdev, VirtQueue *vq, +- int n, bool assign, +- bool with_irqfd) +-{ +- if (n == VIRTIO_CONFIG_IRQ_IDX) { +- virtio_config_set_guest_notifier_fd_handler(vdev, assign, with_irqfd); +- } else { +- virtio_queue_set_guest_notifier_fd_handler(vq, assign, with_irqfd); +- } + } + + static int virtio_pci_set_guest_notifier(DeviceState *d, int n, bool assign, +@@ -1128,25 +1080,17 @@ static int virtio_pci_set_guest_notifier(DeviceState *d, int n, bool assign, + VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d); + VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); + VirtioDeviceClass *vdc = VIRTIO_DEVICE_GET_CLASS(vdev); +- VirtQueue *vq = NULL; +- EventNotifier *notifier = NULL; +- +- if (n == VIRTIO_CONFIG_IRQ_IDX) { +- notifier = virtio_config_get_guest_notifier(vdev); +- } else { +- vq = virtio_get_queue(vdev, n); +- notifier = virtio_queue_get_guest_notifier(vq); +- } ++ VirtQueue *vq = virtio_get_queue(vdev, n); ++ EventNotifier *notifier = virtio_queue_get_guest_notifier(vq); + + if (assign) { + int r = event_notifier_init(notifier, 0); + if (r < 0) { + return r; + } +- virtio_pci_set_guest_notifier_fd_handler(vdev, vq, n, true, with_irqfd); ++ virtio_queue_set_guest_notifier_fd_handler(vq, true, with_irqfd); + } else { +- virtio_pci_set_guest_notifier_fd_handler(vdev, vq, n, false, +- with_irqfd); ++ virtio_queue_set_guest_notifier_fd_handler(vq, false, with_irqfd); + event_notifier_cleanup(notifier); + } + +@@ -1188,7 +1132,6 @@ static int virtio_pci_set_guest_notifiers(DeviceState *d, int nvqs, bool assign) + msix_unset_vector_notifiers(&proxy->pci_dev); + if (proxy->vector_irqfd) { + kvm_virtio_pci_vector_release(proxy, nvqs); +- kvm_virtio_pci_vector_config_release(proxy); + g_free(proxy->vector_irqfd); + proxy->vector_irqfd = NULL; + } +@@ -1204,11 +1147,7 @@ static int virtio_pci_set_guest_notifiers(DeviceState *d, int nvqs, bool assign) + goto assign_error; + } + } +- r = virtio_pci_set_guest_notifier(d, VIRTIO_CONFIG_IRQ_IDX, assign, +- with_irqfd); +- if (r < 0) { +- goto config_assign_error; +- } ++ + /* Must set vector notifier after guest notifier has been assigned */ + if ((with_irqfd || k->guest_notifier_mask) && assign) { + if (with_irqfd) { +@@ -1217,14 +1156,11 @@ static int virtio_pci_set_guest_notifiers(DeviceState *d, int nvqs, bool assign) + msix_nr_vectors_allocated(&proxy->pci_dev)); + r = kvm_virtio_pci_vector_use(proxy, nvqs); + if (r < 0) { +- goto config_assign_error; ++ goto assign_error; + } + } +- r = kvm_virtio_pci_vector_config_use(proxy); +- if (r < 0) { +- goto config_error; +- } +- r = msix_set_vector_notifiers(&proxy->pci_dev, virtio_pci_vector_unmask, ++ r = msix_set_vector_notifiers(&proxy->pci_dev, ++ virtio_pci_vector_unmask, + virtio_pci_vector_mask, + virtio_pci_vector_poll); + if (r < 0) { +@@ -1239,11 +1175,7 @@ notifiers_error: + assert(assign); + kvm_virtio_pci_vector_release(proxy, nvqs); + } +-config_error: +- kvm_virtio_pci_vector_config_release(proxy); +-config_assign_error: +- virtio_pci_set_guest_notifier(d, VIRTIO_CONFIG_IRQ_IDX, !assign, +- with_irqfd); ++ + assign_error: + /* We get here on assignment failure. Recover by undoing for VQs 0 .. n. */ + assert(assign); +diff --git a/hw/virtio/virtio-pci.h b/hw/virtio/virtio-pci.h +index 6d8e071d8d..d95b1a13a5 100644 +--- a/hw/virtio/virtio-pci.h ++++ b/hw/virtio/virtio-pci.h +@@ -256,7 +256,5 @@ void virtio_pci_types_register(const VirtioPCIDeviceTypeInfo *t); + * @fixed_queues. + */ + unsigned virtio_pci_optimal_num_queues(unsigned fixed_queues); +-void virtio_pci_set_guest_notifier_fd_handler(VirtIODevice *vdev, VirtQueue *vq, +- int n, bool assign, +- bool with_irqfd); ++ + #endif +-- +2.27.0 + diff --git a/Revert-virtio-pci-decouple-notifier-from-interrupt-p.patch b/Revert-virtio-pci-decouple-notifier-from-interrupt-p.patch new file mode 100644 index 00000000..deda743b --- /dev/null +++ b/Revert-virtio-pci-decouple-notifier-from-interrupt-p.patch @@ -0,0 +1,255 @@ +From 38c0a07985c6616c43ee98caf7054ddd49dcd34e Mon Sep 17 00:00:00 2001 +From: fangyi +Date: Wed, 22 Nov 2023 10:02:59 +0800 +Subject: [PATCH] Revert "virtio-pci: decouple notifier from interrupt process" + +This reverts commit e3480ef81f6fb61cc9c04e3b5be8b7e84484fc05. + +Fixes: e3480ef81f ("virtio-pci: decouple notifier from interrupt process") +Cc: "Cindy Lu" +Signed-off-by: Michael S. Tsirkin +Signed-off-by: fangyi +--- + hw/virtio/virtio-pci.c | 88 +++++++++++++++--------------------------- + 1 file changed, 31 insertions(+), 57 deletions(-) + +diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c +index 85d7357f66..21c0ec3b1b 100644 +--- a/hw/virtio/virtio-pci.c ++++ b/hw/virtio/virtio-pci.c +@@ -789,41 +789,29 @@ static void kvm_virtio_pci_vq_vector_release(VirtIOPCIProxy *proxy, + } + + static int kvm_virtio_pci_irqfd_use(VirtIOPCIProxy *proxy, +- EventNotifier *n, ++ unsigned int queue_no, + unsigned int vector) + { + VirtIOIRQFD *irqfd = &proxy->vector_irqfd[vector]; ++ VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); ++ VirtQueue *vq = virtio_get_queue(vdev, queue_no); ++ EventNotifier *n = virtio_queue_get_guest_notifier(vq); + return kvm_irqchip_add_irqfd_notifier_gsi(kvm_state, n, NULL, irqfd->virq); + } + + static void kvm_virtio_pci_irqfd_release(VirtIOPCIProxy *proxy, +- EventNotifier *n , ++ unsigned int queue_no, + unsigned int vector) + { ++ VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); ++ VirtQueue *vq = virtio_get_queue(vdev, queue_no); ++ EventNotifier *n = virtio_queue_get_guest_notifier(vq); + VirtIOIRQFD *irqfd = &proxy->vector_irqfd[vector]; + int ret; + + ret = kvm_irqchip_remove_irqfd_notifier_gsi(kvm_state, n, irqfd->virq); + assert(ret == 0); + } +-static int virtio_pci_get_notifier(VirtIOPCIProxy *proxy, int queue_no, +- EventNotifier **n, unsigned int *vector) +-{ +- VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); +- VirtQueue *vq; +- +- if (queue_no == VIRTIO_CONFIG_IRQ_IDX) { +- return -1; +- } else { +- if (!virtio_queue_get_num(vdev, queue_no)) { +- return -1; +- } +- *vector = virtio_queue_vector(vdev, queue_no); +- vq = virtio_get_queue(vdev, queue_no); +- *n = virtio_queue_get_guest_notifier(vq); +- } +- return 0; +-} + + static int kvm_virtio_pci_vector_use(VirtIOPCIProxy *proxy, int nvqs) + { +@@ -832,15 +820,12 @@ static int kvm_virtio_pci_vector_use(VirtIOPCIProxy *proxy, int nvqs) + VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev); + unsigned int vector; + int ret, queue_no; +- EventNotifier *n; ++ + for (queue_no = 0; queue_no < nvqs; queue_no++) { + if (!virtio_queue_get_num(vdev, queue_no)) { + break; + } +- ret = virtio_pci_get_notifier(proxy, queue_no, &n, &vector); +- if (ret < 0) { +- break; +- } ++ vector = virtio_queue_vector(vdev, queue_no); + if (vector >= msix_nr_vectors_allocated(dev)) { + continue; + } +@@ -852,7 +837,7 @@ static int kvm_virtio_pci_vector_use(VirtIOPCIProxy *proxy, int nvqs) + * Otherwise, delay until unmasked in the frontend. + */ + if (vdev->use_guest_notifier_mask && k->guest_notifier_mask) { +- ret = kvm_virtio_pci_irqfd_use(proxy, n, vector); ++ ret = kvm_virtio_pci_irqfd_use(proxy, queue_no, vector); + if (ret < 0) { + kvm_virtio_pci_vq_vector_release(proxy, vector); + goto undo; +@@ -868,11 +853,7 @@ undo: + continue; + } + if (vdev->use_guest_notifier_mask && k->guest_notifier_mask) { +- ret = virtio_pci_get_notifier(proxy, queue_no, &n, &vector); +- if (ret < 0) { +- break; +- } +- kvm_virtio_pci_irqfd_release(proxy, n, vector); ++ kvm_virtio_pci_irqfd_release(proxy, queue_no, vector); + } + kvm_virtio_pci_vq_vector_release(proxy, vector); + } +@@ -886,16 +867,12 @@ static void kvm_virtio_pci_vector_release(VirtIOPCIProxy *proxy, int nvqs) + unsigned int vector; + int queue_no; + VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev); +- EventNotifier *n; +- int ret ; ++ + for (queue_no = 0; queue_no < nvqs; queue_no++) { + if (!virtio_queue_get_num(vdev, queue_no)) { + break; + } +- ret = virtio_pci_get_notifier(proxy, queue_no, &n, &vector); +- if (ret < 0) { +- break; +- } ++ vector = virtio_queue_vector(vdev, queue_no); + if (vector >= msix_nr_vectors_allocated(dev)) { + continue; + } +@@ -903,20 +880,21 @@ static void kvm_virtio_pci_vector_release(VirtIOPCIProxy *proxy, int nvqs) + * Otherwise, it was cleaned when masked in the frontend. + */ + if (vdev->use_guest_notifier_mask && k->guest_notifier_mask) { +- kvm_virtio_pci_irqfd_release(proxy, n, vector); ++ kvm_virtio_pci_irqfd_release(proxy, queue_no, vector); + } + kvm_virtio_pci_vq_vector_release(proxy, vector); + } + } + +-static int virtio_pci_one_vector_unmask(VirtIOPCIProxy *proxy, ++static int virtio_pci_vq_vector_unmask(VirtIOPCIProxy *proxy, + unsigned int queue_no, + unsigned int vector, +- MSIMessage msg, +- EventNotifier *n) ++ MSIMessage msg) + { + VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); + VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev); ++ VirtQueue *vq = virtio_get_queue(vdev, queue_no); ++ EventNotifier *n = virtio_queue_get_guest_notifier(vq); + VirtIOIRQFD *irqfd; + int ret = 0; + +@@ -943,15 +921,14 @@ static int virtio_pci_one_vector_unmask(VirtIOPCIProxy *proxy, + event_notifier_set(n); + } + } else { +- ret = kvm_virtio_pci_irqfd_use(proxy, n, vector); ++ ret = kvm_virtio_pci_irqfd_use(proxy, queue_no, vector); + } + return ret; + } + +-static void virtio_pci_one_vector_mask(VirtIOPCIProxy *proxy, ++static void virtio_pci_vq_vector_mask(VirtIOPCIProxy *proxy, + unsigned int queue_no, +- unsigned int vector, +- EventNotifier *n) ++ unsigned int vector) + { + VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); + VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev); +@@ -962,7 +939,7 @@ static void virtio_pci_one_vector_mask(VirtIOPCIProxy *proxy, + if (vdev->use_guest_notifier_mask && k->guest_notifier_mask) { + k->guest_notifier_mask(vdev, queue_no, true); + } else { +- kvm_virtio_pci_irqfd_release(proxy, n, vector); ++ kvm_virtio_pci_irqfd_release(proxy, queue_no, vector); + } + } + +@@ -972,7 +949,6 @@ static int virtio_pci_vector_unmask(PCIDevice *dev, unsigned vector, + VirtIOPCIProxy *proxy = container_of(dev, VirtIOPCIProxy, pci_dev); + VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); + VirtQueue *vq = virtio_vector_first_queue(vdev, vector); +- EventNotifier *n; + int ret, index, unmasked = 0; + + while (vq) { +@@ -981,8 +957,7 @@ static int virtio_pci_vector_unmask(PCIDevice *dev, unsigned vector, + break; + } + if (index < proxy->nvqs_with_notifiers) { +- n = virtio_queue_get_guest_notifier(vq); +- ret = virtio_pci_one_vector_unmask(proxy, index, vector, msg, n); ++ ret = virtio_pci_vq_vector_unmask(proxy, index, vector, msg); + if (ret < 0) { + goto undo; + } +@@ -998,8 +973,7 @@ undo: + while (vq && unmasked >= 0) { + index = virtio_get_queue_index(vq); + if (index < proxy->nvqs_with_notifiers) { +- n = virtio_queue_get_guest_notifier(vq); +- virtio_pci_one_vector_mask(proxy, index, vector, n); ++ virtio_pci_vq_vector_mask(proxy, index, vector); + --unmasked; + } + vq = virtio_vector_next_queue(vq); +@@ -1012,17 +986,15 @@ static void virtio_pci_vector_mask(PCIDevice *dev, unsigned vector) + VirtIOPCIProxy *proxy = container_of(dev, VirtIOPCIProxy, pci_dev); + VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); + VirtQueue *vq = virtio_vector_first_queue(vdev, vector); +- EventNotifier *n; + int index; + + while (vq) { + index = virtio_get_queue_index(vq); +- n = virtio_queue_get_guest_notifier(vq); + if (!virtio_queue_get_num(vdev, index)) { + break; + } + if (index < proxy->nvqs_with_notifiers) { +- virtio_pci_one_vector_mask(proxy, index, vector, n); ++ virtio_pci_vq_vector_mask(proxy, index, vector); + } + vq = virtio_vector_next_queue(vq); + } +@@ -1038,17 +1010,19 @@ static void virtio_pci_vector_poll(PCIDevice *dev, + int queue_no; + unsigned int vector; + EventNotifier *notifier; +- int ret; ++ VirtQueue *vq; + + for (queue_no = 0; queue_no < proxy->nvqs_with_notifiers; queue_no++) { +- ret = virtio_pci_get_notifier(proxy, queue_no, ¬ifier, &vector); +- if (ret < 0) { ++ if (!virtio_queue_get_num(vdev, queue_no)) { + break; + } ++ vector = virtio_queue_vector(vdev, queue_no); + if (vector < vector_start || vector >= vector_end || + !msix_is_masked(dev, vector)) { + continue; + } ++ vq = virtio_get_queue(vdev, queue_no); ++ notifier = virtio_queue_get_guest_notifier(vq); + if (k->guest_notifier_pending) { + if (k->guest_notifier_pending(vdev, queue_no)) { + msix_set_pending(dev, vector); +-- +2.27.0 + diff --git a/Revert-virtio-pci-decouple-the-single-vector-from-th.patch b/Revert-virtio-pci-decouple-the-single-vector-from-th.patch new file mode 100644 index 00000000..45fa977a --- /dev/null +++ b/Revert-virtio-pci-decouple-the-single-vector-from-th.patch @@ -0,0 +1,192 @@ +From 074043d5d6c2610a320d2bc7d8649b7eff9c806e Mon Sep 17 00:00:00 2001 +From: fangyi +Date: Wed, 22 Nov 2023 10:01:17 +0800 +Subject: [PATCH] Revert "virtio-pci: decouple the single vector from the + interrupt process" + +This reverts commit 316011b8a74e777eb3ba03171cd701a291c28867. + +Fixes: 316011b8a7 ("virtio-pci: decouple the single vector from the interrupt process") +Cc: "Cindy Lu" +Signed-off-by: Michael S. Tsirkin +Signed-off-by: fangyi +--- + hw/virtio/virtio-pci.c | 131 ++++++++++++++++++----------------------- + 1 file changed, 58 insertions(+), 73 deletions(-) + +diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c +index 75be770971..85d7357f66 100644 +--- a/hw/virtio/virtio-pci.c ++++ b/hw/virtio/virtio-pci.c +@@ -762,6 +762,7 @@ static uint32_t virtio_read_config(PCIDevice *pci_dev, + } + + static int kvm_virtio_pci_vq_vector_use(VirtIOPCIProxy *proxy, ++ unsigned int queue_no, + unsigned int vector) + { + VirtIOIRQFD *irqfd = &proxy->vector_irqfd[vector]; +@@ -824,103 +825,87 @@ static int virtio_pci_get_notifier(VirtIOPCIProxy *proxy, int queue_no, + return 0; + } + +-static int kvm_virtio_pci_vector_use_one(VirtIOPCIProxy *proxy, int queue_no) ++static int kvm_virtio_pci_vector_use(VirtIOPCIProxy *proxy, int nvqs) + { +- unsigned int vector; +- int ret; +- EventNotifier *n; + PCIDevice *dev = &proxy->pci_dev; + VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); + VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev); +- +- ret = virtio_pci_get_notifier(proxy, queue_no, &n, &vector); +- if (ret < 0) { +- return ret; +- } +- if (vector >= msix_nr_vectors_allocated(dev)) { +- return 0; +- } +- ret = kvm_virtio_pci_vq_vector_use(proxy, vector); +- if (ret < 0) { +- goto undo; +- } +- /* +- * If guest supports masking, set up irqfd now. +- * Otherwise, delay until unmasked in the frontend. +- */ +- if (vdev->use_guest_notifier_mask && k->guest_notifier_mask) { +- ret = kvm_virtio_pci_irqfd_use(proxy, n, vector); ++ unsigned int vector; ++ int ret, queue_no; ++ EventNotifier *n; ++ for (queue_no = 0; queue_no < nvqs; queue_no++) { ++ if (!virtio_queue_get_num(vdev, queue_no)) { ++ break; ++ } ++ ret = virtio_pci_get_notifier(proxy, queue_no, &n, &vector); ++ if (ret < 0) { ++ break; ++ } ++ if (vector >= msix_nr_vectors_allocated(dev)) { ++ continue; ++ } ++ ret = kvm_virtio_pci_vq_vector_use(proxy, queue_no, vector); + if (ret < 0) { +- kvm_virtio_pci_vq_vector_release(proxy, vector); + goto undo; + } ++ /* If guest supports masking, set up irqfd now. ++ * Otherwise, delay until unmasked in the frontend. ++ */ ++ if (vdev->use_guest_notifier_mask && k->guest_notifier_mask) { ++ ret = kvm_virtio_pci_irqfd_use(proxy, n, vector); ++ if (ret < 0) { ++ kvm_virtio_pci_vq_vector_release(proxy, vector); ++ goto undo; ++ } ++ } + } +- + return 0; +-undo: + +- vector = virtio_queue_vector(vdev, queue_no); +- if (vector >= msix_nr_vectors_allocated(dev)) { +- return ret; +- } +- if (vdev->use_guest_notifier_mask && k->guest_notifier_mask) { +- ret = virtio_pci_get_notifier(proxy, queue_no, &n, &vector); +- if (ret < 0) { +- return ret; ++undo: ++ while (--queue_no >= 0) { ++ vector = virtio_queue_vector(vdev, queue_no); ++ if (vector >= msix_nr_vectors_allocated(dev)) { ++ continue; + } +- kvm_virtio_pci_irqfd_release(proxy, n, vector); +- } +- return ret; +-} +-static int kvm_virtio_pci_vector_use(VirtIOPCIProxy *proxy, int nvqs) +-{ +- int queue_no; +- int ret = 0; +- VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); +- +- for (queue_no = 0; queue_no < nvqs; queue_no++) { +- if (!virtio_queue_get_num(vdev, queue_no)) { +- return -1; ++ if (vdev->use_guest_notifier_mask && k->guest_notifier_mask) { ++ ret = virtio_pci_get_notifier(proxy, queue_no, &n, &vector); ++ if (ret < 0) { ++ break; ++ } ++ kvm_virtio_pci_irqfd_release(proxy, n, vector); + } +- ret = kvm_virtio_pci_vector_use_one(proxy, queue_no); ++ kvm_virtio_pci_vq_vector_release(proxy, vector); + } + return ret; + } + +- +-static void kvm_virtio_pci_vector_release_one(VirtIOPCIProxy *proxy, +- int queue_no) ++static void kvm_virtio_pci_vector_release(VirtIOPCIProxy *proxy, int nvqs) + { ++ PCIDevice *dev = &proxy->pci_dev; + VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); + unsigned int vector; +- EventNotifier *n; +- int ret; +- VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev); +- PCIDevice *dev = &proxy->pci_dev; +- +- ret = virtio_pci_get_notifier(proxy, queue_no, &n, &vector); +- if (ret < 0) { +- return; +- } +- if (vector >= msix_nr_vectors_allocated(dev)) { +- return; +- } +- if (vdev->use_guest_notifier_mask && k->guest_notifier_mask) { +- kvm_virtio_pci_irqfd_release(proxy, n, vector); +- } +- kvm_virtio_pci_vq_vector_release(proxy, vector); +-} +- +-static void kvm_virtio_pci_vector_release(VirtIOPCIProxy *proxy, int nvqs) +-{ + int queue_no; +- VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); +- ++ VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev); ++ EventNotifier *n; ++ int ret ; + for (queue_no = 0; queue_no < nvqs; queue_no++) { + if (!virtio_queue_get_num(vdev, queue_no)) { + break; + } +- kvm_virtio_pci_vector_release_one(proxy, queue_no); ++ ret = virtio_pci_get_notifier(proxy, queue_no, &n, &vector); ++ if (ret < 0) { ++ break; ++ } ++ if (vector >= msix_nr_vectors_allocated(dev)) { ++ continue; ++ } ++ /* If guest supports masking, clean up irqfd now. ++ * Otherwise, it was cleaned when masked in the frontend. ++ */ ++ if (vdev->use_guest_notifier_mask && k->guest_notifier_mask) { ++ kvm_virtio_pci_irqfd_release(proxy, n, vector); ++ } ++ kvm_virtio_pci_vq_vector_release(proxy, vector); + } + } + +-- +2.27.0 + diff --git a/artist-set-memory-region-owners-for-buffers-to-the-a.patch b/artist-set-memory-region-owners-for-buffers-to-the-a.patch new file mode 100644 index 00000000..4513e1e2 --- /dev/null +++ b/artist-set-memory-region-owners-for-buffers-to-the-a.patch @@ -0,0 +1,37 @@ +From db2e1d340763e23180e4709e4ddf33390f2e49ea Mon Sep 17 00:00:00 2001 +From: tangbinzy +Date: Fri, 17 Nov 2023 09:00:01 +0000 +Subject: [PATCH] artist: set memory region owners for buffers to the artist + device mainline inclusion commit 39fbaeca096a9bf6cbe2af88572c1cb2aa62aa8c + category: bugfix + +--------------------------------------------------------------- + +This fixes the output of "info qom-tree" so that the buffers appear as children +of the artist device, rather than underneath the "unattached" container. + +Signed-off-by: Mark Cave-Ayland +Message-Id: <20220624160839.886649-1-mark.cave-ayland@ilande.co.uk> +Reviewed-by: Helge Deller + +Signed-off-by: tangbinzy +--- + hw/display/artist.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/hw/display/artist.c b/hw/display/artist.c +index 21b7fd1b44..1767203477 100644 +--- a/hw/display/artist.c ++++ b/hw/display/artist.c +@@ -1359,7 +1359,7 @@ static void artist_create_buffer(ARTISTState *s, const char *name, + { + struct vram_buffer *buf = s->vram_buffer + idx; + +- memory_region_init_ram(&buf->mr, NULL, name, width * height, ++ memory_region_init_ram(&buf->mr, OBJECT(s), name, width * height, + &error_fatal); + memory_region_add_subregion_overlap(&s->mem_as_root, *offset, &buf->mr, 0); + +-- +2.27.0 + diff --git a/e1000-set-RX-descriptor-status-in-a-separate-operati.patch b/e1000-set-RX-descriptor-status-in-a-separate-operati.patch new file mode 100644 index 00000000..ffa0f965 --- /dev/null +++ b/e1000-set-RX-descriptor-status-in-a-separate-operati.patch @@ -0,0 +1,89 @@ +From dcebeb0f7acf549620faff1badf73baba04b2068 Mon Sep 17 00:00:00 2001 +From: tangbinzy +Date: Fri, 17 Nov 2023 10:15:09 +0000 +Subject: [PATCH] e1000: set RX descriptor status in a separate operation + mainline inclusion commit 034d00d4858161e1d4cff82d8d230bce874a04d3 category: + bugfix + +--------------------------------------------------------------- + +The code of setting RX descriptor status field maybe work fine in +previously, however with the update of glibc version, it shows two +issues when guest using dpdk receive packets: + + 1. The dpdk has a certain probability getting wrong buffer_addr + + this impact may be not obvious, such as lost a packet once in + a while + + 2. The dpdk may consume a packet twice when scan the RX desc queue + over again + + this impact will lead a infinite wait in Qemu, since the RDT + (tail pointer) be inscreased to equal to RDH by unexpected, + which regard as the RX desc queue is full + +Write a whole of RX desc with DD flag on is not quite correct, because +when the underlying implementation of memcpy using XMM registers to +copy e1000_rx_desc (when AVX or something else CPU feature is usable), +the bytes order of desc writing to memory is indeterminacy + +We can use full-scale test case to reproduce the issue-2 by +https://github.com/BASM/qemu_dpdk_e1000_test (thanks to Leonid Myravjev) + +I also write a POC test case at https://github.com/cdkey/e1000_poc +which can reproduce both of them, and easy to verify the patch effect. + +The hw watchpoint also shows that, when Qemu using XMM related instructions +writing 16 bytes e1000_rx_desc, concurrent with DPDK using movb +writing 1 byte status, the final result of writing to memory will be one +of them, if it made by Qemu which DD flag is on, DPDK will consume it +again. + +Setting DD status in a separate operation, can prevent the impact of +disorder memory writing by memcpy, also avoid unexpected data when +concurrent writing status by qemu and guest dpdk. + +Links: https://lore.kernel.org/qemu-devel/20200102110504.GG121208@stefanha-x1.localdomain/T/ + +Reported-by: Leonid Myravjev +Cc: Stefan Hajnoczi +Cc: Paolo Bonzini +Cc: Michael S. Tsirkin +Cc: qemu-stable@nongnu.org +Tested-by: Jing Zhang +Reviewed-by: Frank Lee +Signed-off-by: Ding Hui +Signed-off-by: Jason Wang + +Signed-off-by: tangbinzy +--- + hw/net/e1000.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/hw/net/e1000.c b/hw/net/e1000.c +index f5bc81296d..e26e0a64c1 100644 +--- a/hw/net/e1000.c ++++ b/hw/net/e1000.c +@@ -979,7 +979,7 @@ e1000_receive_iov(NetClientState *nc, const struct iovec *iov, int iovcnt) + base = rx_desc_base(s) + sizeof(desc) * s->mac_reg[RDH]; + pci_dma_read(d, base, &desc, sizeof(desc)); + desc.special = vlan_special; +- desc.status |= (vlan_status | E1000_RXD_STAT_DD); ++ desc.status &= ~E1000_RXD_STAT_DD; + if (desc.buffer_addr) { + if (desc_offset < size) { + size_t iov_copy; +@@ -1013,6 +1013,9 @@ e1000_receive_iov(NetClientState *nc, const struct iovec *iov, int iovcnt) + DBGOUT(RX, "Null RX descriptor!!\n"); + } + pci_dma_write(d, base, &desc, sizeof(desc)); ++ desc.status |= (vlan_status | E1000_RXD_STAT_DD); ++ pci_dma_write(d, base + offsetof(struct e1000_rx_desc, status), ++ &desc.status, sizeof(desc.status)); + + if (++s->mac_reg[RDH] * sizeof(desc) >= s->mac_reg[RDLEN]) + s->mac_reg[RDH] = 0; +-- +2.27.0 + diff --git a/hw-arm-fsl-imx-Do-not-ignore-Error-argument.patch b/hw-arm-fsl-imx-Do-not-ignore-Error-argument.patch new file mode 100644 index 00000000..8cc37891 --- /dev/null +++ b/hw-arm-fsl-imx-Do-not-ignore-Error-argument.patch @@ -0,0 +1,62 @@ +From 81c2b665d9ea6670677f35aa1ab2ad68d6e73aa4 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Mon, 20 Nov 2023 12:51:15 +0100 +Subject: [PATCH] hw/arm/fsl-imx: Do not ignore Error argument +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +mainline inclusion +commit 0cbb56c236a4a28f5149eed227d74bb737321cfc +category: bugfix + +-------------------------------------------------------- + +Both i.MX25 and i.MX6 SoC models ignore the Error argument when +setting the PHY number. Pick &error_abort which is the error +used by the i.MX7 SoC (see commit 1f7197deb0 "ability to change +the FEC PHY on i.MX7 processor"). + +Fixes: 74c1330582 ("ability to change the FEC PHY on i.MX25 processor") +Fixes: a9c167a3c4 ("ability to change the FEC PHY on i.MX6 processor") +Signed-off-by: Philippe Mathieu-Daudé +Message-id: 20231120115116.76858-1-philmd@linaro.org +Reviewed-by: Peter Maydell +Signed-off-by: Peter Maydell +Signed-off-by: zhujun2 +--- + hw/arm/fsl-imx25.c | 3 ++- + hw/arm/fsl-imx6.c | 3 ++- + 2 files changed, 4 insertions(+), 2 deletions(-) + +diff --git a/hw/arm/fsl-imx25.c b/hw/arm/fsl-imx25.c +index 24c4374590..9aabbf7f58 100644 +--- a/hw/arm/fsl-imx25.c ++++ b/hw/arm/fsl-imx25.c +@@ -169,7 +169,8 @@ static void fsl_imx25_realize(DeviceState *dev, Error **errp) + epit_table[i].irq)); + } + +- object_property_set_uint(OBJECT(&s->fec), "phy-num", s->phy_num, &err); ++ object_property_set_uint(OBJECT(&s->fec), "phy-num", s->phy_num, ++ &error_abort); + qdev_set_nic_properties(DEVICE(&s->fec), &nd_table[0]); + + if (!sysbus_realize(SYS_BUS_DEVICE(&s->fec), errp)) { +diff --git a/hw/arm/fsl-imx6.c b/hw/arm/fsl-imx6.c +index 00dafe3f62..c4b95dc7a7 100644 +--- a/hw/arm/fsl-imx6.c ++++ b/hw/arm/fsl-imx6.c +@@ -377,7 +377,8 @@ static void fsl_imx6_realize(DeviceState *dev, Error **errp) + spi_table[i].irq)); + } + +- object_property_set_uint(OBJECT(&s->eth), "phy-num", s->phy_num, &err); ++ object_property_set_uint(OBJECT(&s->eth), "phy-num", s->phy_num, ++ &error_abort); + qdev_set_nic_properties(DEVICE(&s->eth), &nd_table[0]); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->eth), errp)) { + return; +-- +2.27.0 + diff --git a/hw-net-cadence_gem.c-spelling-fixes-Octects.patch b/hw-net-cadence_gem.c-spelling-fixes-Octects.patch new file mode 100644 index 00000000..31ebc99f --- /dev/null +++ b/hw-net-cadence_gem.c-spelling-fixes-Octects.patch @@ -0,0 +1,39 @@ +From 2e37d6ac7713c9962cb006900d18e83df54e8e0f Mon Sep 17 00:00:00 2001 +From: zhujun2 +Date: Fri, 24 Nov 2023 00:21:31 -0800 +Subject: [PATCH] hw/net/cadence_gem.c: spelling fixes: Octects + +Signed-off-by: zhujun2 +--- + hw/net/cadence_gem.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/hw/net/cadence_gem.c b/hw/net/cadence_gem.c +index 24b3a0ff66..21e1bd091f 100644 +--- a/hw/net/cadence_gem.c ++++ b/hw/net/cadence_gem.c +@@ -81,8 +81,8 @@ + #define GEM_IPGSTRETCH (0x000000BC / 4) /* IPG Stretch reg */ + #define GEM_SVLAN (0x000000C0 / 4) /* Stacked VLAN reg */ + #define GEM_MODID (0x000000FC / 4) /* Module ID reg */ +-#define GEM_OCTTXLO (0x00000100 / 4) /* Octects transmitted Low reg */ +-#define GEM_OCTTXHI (0x00000104 / 4) /* Octects transmitted High reg */ ++#define GEM_OCTTXLO (0x00000100 / 4) /* Octets transmitted Low reg */ ++#define GEM_OCTTXHI (0x00000104 / 4) /* Octets transmitted High reg */ + #define GEM_TXCNT (0x00000108 / 4) /* Error-free Frames transmitted */ + #define GEM_TXBCNT (0x0000010C / 4) /* Error-free Broadcast Frames */ + #define GEM_TXMCNT (0x00000110 / 4) /* Error-free Multicast Frame */ +@@ -101,8 +101,8 @@ + #define GEM_LATECOLLCNT (0x00000144 / 4) /* Late Collision Frames */ + #define GEM_DEFERTXCNT (0x00000148 / 4) /* Deferred Transmission Frames */ + #define GEM_CSENSECNT (0x0000014C / 4) /* Carrier Sense Error Counter */ +-#define GEM_OCTRXLO (0x00000150 / 4) /* Octects Received register Low */ +-#define GEM_OCTRXHI (0x00000154 / 4) /* Octects Received register High */ ++#define GEM_OCTRXLO (0x00000150 / 4) /* Octets Received register Low */ ++#define GEM_OCTRXHI (0x00000154 / 4) /* Octets Received register High */ + #define GEM_RXCNT (0x00000158 / 4) /* Error-free Frames Received */ + #define GEM_RXBROADCNT (0x0000015C / 4) /* Error-free Broadcast Frames RX */ + #define GEM_RXMULTICNT (0x00000160 / 4) /* Error-free Multicast Frames RX */ +-- +2.27.0 + diff --git a/hw-pvrdma-Protect-against-buggy-or-malicious-guest-driver.patch b/hw-pvrdma-Protect-against-buggy-or-malicious-guest-driver.patch new file mode 100644 index 00000000..edc0d62f --- /dev/null +++ b/hw-pvrdma-Protect-against-buggy-or-malicious-guest-driver.patch @@ -0,0 +1,65 @@ +From 6532f02449e7a001bc74ea43690d6e1a87a7e3fc Mon Sep 17 00:00:00 2001 +From: Yuval Shaia +Date: Wed, 1 Mar 2023 16:29:26 +0200 +Subject: [PATCH] hw/pvrdma: Protect against buggy or malicious guest driver + +Guest driver allocates and initialize page tables to be used as a ring +of descriptors for CQ and async events. +The page table that represents the ring, along with the number of pages +in the page table is passed to the device. +Currently our device supports only one page table for a ring. + +Let's make sure that the number of page table entries the driver +reports, do not exceeds the one page table size. + +Reported-by: Soul Chen +Signed-off-by: Yuval Shaia +Fixes: CVE-2023-1544 +Message-ID: <20230301142926.18686-1-yuval.shaia.ml@gmail.com> +Signed-off-by: Thomas Huth +--- + hw/rdma/vmw/pvrdma_main.c | 16 +++++++++++++++- + 1 file changed, 15 insertions(+), 1 deletion(-) + +diff --git a/hw/rdma/vmw/pvrdma_main.c b/hw/rdma/vmw/pvrdma_main.c +index 91206dbb8e..f99b12a592 100644 +--- a/hw/rdma/vmw/pvrdma_main.c ++++ b/hw/rdma/vmw/pvrdma_main.c +@@ -91,19 +91,33 @@ static int init_dev_ring(PvrdmaRing *ring, PvrdmaRingState **ring_state, + dma_addr_t dir_addr, uint32_t num_pages) + { + uint64_t *dir, *tbl; +- int rc = 0; ++ int max_pages, rc = 0; + + if (!num_pages) { + rdma_error_report("Ring pages count must be strictly positive"); + return -EINVAL; + } + ++ /* ++ * Make sure we can satisfy the requested number of pages in a single ++ * TARGET_PAGE_SIZE sized page table (taking into account that first entry ++ * is reserved for ring-state) ++ */ ++ max_pages = TARGET_PAGE_SIZE / sizeof(dma_addr_t) - 1; ++ if (num_pages > max_pages) { ++ rdma_error_report("Maximum pages on a single directory must not exceed %d\n", ++ max_pages); ++ return -EINVAL; ++ } ++ + dir = rdma_pci_dma_map(pci_dev, dir_addr, TARGET_PAGE_SIZE); + if (!dir) { + rdma_error_report("Failed to map to page directory (ring %s)", name); + rc = -ENOMEM; + goto out; + } ++ ++ /* We support only one page table for a ring */ + tbl = rdma_pci_dma_map(pci_dev, dir[0], TARGET_PAGE_SIZE); + if (!tbl) { + rdma_error_report("Failed to map to page table (ring %s)", name); +-- +2.27.0 + diff --git a/hw-timer-npcm7xx_timer-Prevent-timer-from-counting-d.patch b/hw-timer-npcm7xx_timer-Prevent-timer-from-counting-d.patch new file mode 100644 index 00000000..c554bb4c --- /dev/null +++ b/hw-timer-npcm7xx_timer-Prevent-timer-from-counting-d.patch @@ -0,0 +1,38 @@ +From 7f5cf2958ee5d178d058470031b96a82d3002a5c Mon Sep 17 00:00:00 2001 +From: qihao +Date: Wed, 1 Nov 2023 19:00:34 +0800 +Subject: [PATCH] hw/timer/npcm7xx_timer: Prevent timer from counting down past + zero + +cheery-pick from 9ef2629712680e70cbf39d8b6cb1ec0e0e2e72fa + +The counter register is only 24-bits and counts down. If the timer is +running but the qtimer to reset it hasn't fired off yet, there is a chance +the regster read can return an invalid result. + +Signed-off-by: Chris Rauer +Message-id: 20230922181411.2697135-1-crauer@google.com +Reviewed-by: Peter Maydell +Signed-off-by: Peter Maydell +Signed-off-by: qihao_yewu +--- + hw/timer/npcm7xx_timer.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/hw/timer/npcm7xx_timer.c b/hw/timer/npcm7xx_timer.c +index 32f5e021f8..a8bd93aeb2 100644 +--- a/hw/timer/npcm7xx_timer.c ++++ b/hw/timer/npcm7xx_timer.c +@@ -138,6 +138,9 @@ static int64_t npcm7xx_timer_count_to_ns(NPCM7xxTimer *t, uint32_t count) + /* Convert a time interval in nanoseconds to a timer cycle count. */ + static uint32_t npcm7xx_timer_ns_to_count(NPCM7xxTimer *t, int64_t ns) + { ++ if (ns < 0) { ++ return 0; ++ } + return clock_ns_to_ticks(t->ctrl->clock, ns) / + npcm7xx_tcsr_prescaler(t->tcsr); + } +-- +2.27.0 + diff --git a/hw-usb-hcd-ehci-fix-writeback-order.patch b/hw-usb-hcd-ehci-fix-writeback-order.patch new file mode 100644 index 00000000..8d0d6118 --- /dev/null +++ b/hw-usb-hcd-ehci-fix-writeback-order.patch @@ -0,0 +1,64 @@ +From fc52088f7aa8a1be3b3c7d135a2aebd28ba4c673 Mon Sep 17 00:00:00 2001 +From: tangbinzy +Date: Mon, 6 Nov 2023 06:57:46 +0000 +Subject: [PATCH] hw/usb/hcd-ehci: fix writeback order mainline inclusion + commit f471e8b060798f26a7fc339c6152f82f22a7b33d category: bugfix + +--------------------------------------------------------------- + +The 'active' bit passes control over a qTD between the guest and the +controller: set to 1 by guest to enable execution by the controller, +and the controller sets it to '0' to hand back control to the guest. + +ehci_state_writeback write two dwords to main memory using DMA: +the third dword of the qTD (containing dt, total bytes to transfer, +cpage, cerr and status) and the fourth dword of the qTD (containing +the offset). + +This commit makes sure the fourth dword is written before the third, +avoiding a race condition where a new offset written into the qTD +by the guest after it observed the status going to go to '0' gets +overwritten by a 'late' DMA writeback of the previous offset. + +This race condition could lead to 'cpage out of range (5)' errors, +and reproduced by: + +./qemu-system-x86_64 -enable-kvm -bios $SEABIOS/bios.bin -m 4096 -device usb-ehci -blockdev driver=file,read-only=on,filename=/home/aengelen/Downloads/openSUSE-Tumbleweed-DVD-i586-Snapshot20220428-Media.iso,node-name=iso -device usb-storage,drive=iso,bootindex=0 -chardev pipe,id=shell,path=/tmp/pipe -device virtio-serial -device virtconsole,chardev=shell -device virtio-rng-pci -serial mon:stdio -nographic + +(press a key, select 'Installation' (2), and accept the default +values. On my machine the 'cpage out of range' is reproduced while +loading the Linux Kernel about once per 7 attempts. With the fix in +this commit it no longer fails) + +This problem was previously reported as a seabios problem in +https://mail.coreboot.org/hyperkitty/list/seabios@seabios.org/thread/OUTHT5ISSQJGXPNTUPY3O5E5EPZJCHM3/ +and as a nixos CI build failure in +https://github.com/NixOS/nixpkgs/issues/170803 + +Signed-off-by: Arnout Engelen +Signed-off-by: Gerd Hoffmann + +Signed-off-by: tangbinzy +--- + hw/usb/hcd-ehci.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c +index 0289b3696d..f9aa567f5d 100644 +--- a/hw/usb/hcd-ehci.c ++++ b/hw/usb/hcd-ehci.c +@@ -2013,7 +2013,10 @@ static int ehci_state_writeback(EHCIQueue *q) + ehci_trace_qtd(q, NLPTR_GET(p->qtdaddr), (EHCIqtd *) &q->qh.next_qtd); + qtd = (uint32_t *) &q->qh.next_qtd; + addr = NLPTR_GET(p->qtdaddr); +- put_dwords(q->ehci, addr + 2 * sizeof(uint32_t), qtd + 2, 2); ++ /* First write back the offset */ ++ put_dwords(q->ehci, addr + 3 * sizeof(uint32_t), qtd + 3, 1); ++ /* Then write back the token, clearing the 'active' bit */ ++ put_dwords(q->ehci, addr + 2 * sizeof(uint32_t), qtd + 2, 1); + ehci_free_packet(p); + + /* +-- +2.27.0 + diff --git a/hw-virtio-add-some-vhost-user-trace-events.patch b/hw-virtio-add-some-vhost-user-trace-events.patch new file mode 100644 index 00000000..5979d625 --- /dev/null +++ b/hw-virtio-add-some-vhost-user-trace-events.patch @@ -0,0 +1,70 @@ +From f5b5cba0b86caacdea334725bedcdfb689504b3a Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Alex=20Benn=C3=A9e?= +Date: Tue, 2 Aug 2022 10:49:57 +0100 +Subject: [PATCH] hw/virtio: add some vhost-user trace events +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +These are useful for tracing the lifetime of vhost-user connections. + +Signed-off-by: Alex Bennée +Message-Id: <20220802095010.3330793-10-alex.bennee@linaro.org> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Reviewed-by: Philippe Mathieu-Daudé +Signed-off-by: fangyi +--- + hw/virtio/trace-events | 4 ++++ + hw/virtio/vhost.c | 6 ++++++ + 2 files changed, 10 insertions(+) + +diff --git a/hw/virtio/trace-events b/hw/virtio/trace-events +index 63c7668e5b..b8a33b2a83 100644 +--- a/hw/virtio/trace-events ++++ b/hw/virtio/trace-events +@@ -8,6 +8,10 @@ vhost_region_add_section_aligned(const char *name, uint64_t gpa, uint64_t size, + vhost_section(const char *name) "%s" + vhost_reject_section(const char *name, int d) "%s:%d" + vhost_iotlb_miss(void *dev, int step) "%p step %d" ++vhost_dev_cleanup(void *dev) "%p" ++vhost_dev_start(void *dev, const char *name) "%p:%s" ++vhost_dev_stop(void *dev, const char *name) "%p:%s" ++ + + # vhost-user.c + vhost_user_postcopy_end_entry(void) "" +diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c +index c1f5cb5b91..86c727d2ab 100644 +--- a/hw/virtio/vhost.c ++++ b/hw/virtio/vhost.c +@@ -1460,6 +1460,8 @@ void vhost_dev_cleanup(struct vhost_dev *hdev) + { + int i; + ++ trace_vhost_dev_cleanup(hdev); ++ + for (i = 0; i < hdev->nvqs; ++i) { + vhost_virtqueue_cleanup(hdev->vqs + i); + } +@@ -1766,6 +1768,8 @@ int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev) + /* should only be called after backend is connected */ + assert(hdev->vhost_ops); + ++ trace_vhost_dev_start(hdev, vdev->name); ++ + vdev->vhost_started = true; + hdev->started = true; + hdev->vdev = vdev; +@@ -1852,6 +1856,8 @@ void vhost_dev_stop(struct vhost_dev *hdev, VirtIODevice *vdev) + /* should only be called after backend is connected */ + assert(hdev->vhost_ops); + ++ trace_vhost_dev_stop(hdev, vdev->name); ++ + if (hdev->vhost_ops->vhost_dev_start) { + hdev->vhost_ops->vhost_dev_start(hdev, false); + } +-- +2.27.0 + diff --git a/hw-virtio-add-vhost_user_-read-write-trace-points.patch b/hw-virtio-add-vhost_user_-read-write-trace-points.patch new file mode 100644 index 00000000..ca9de060 --- /dev/null +++ b/hw-virtio-add-vhost_user_-read-write-trace-points.patch @@ -0,0 +1,62 @@ +From 57451ee8e278827ef0ab592d565c14076dd62fd0 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Alex=20Benn=C3=A9e?= +Date: Mon, 21 Mar 2022 15:30:27 +0000 +Subject: [PATCH] hw/virtio: add vhost_user_[read|write] trace points +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +These are useful when trying to debug the initial vhost-user +negotiation, especially when it hard to get logging from the low level +library on the other side. + +Signed-off-by: Alex Bennée + +Message-Id: <20220321153037.3622127-4-alex.bennee@linaro.org> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Reviewed-by: Philippe Mathieu-Daudé +Signed-off-by: fangyi +--- + hw/virtio/trace-events | 2 ++ + hw/virtio/vhost-user.c | 4 ++++ + 2 files changed, 6 insertions(+) + +diff --git a/hw/virtio/trace-events b/hw/virtio/trace-events +index 37c1555330..63c7668e5b 100644 +--- a/hw/virtio/trace-events ++++ b/hw/virtio/trace-events +@@ -21,6 +21,8 @@ vhost_user_set_mem_table_withfd(int index, const char *name, uint64_t memory_siz + vhost_user_postcopy_waker(const char *rb, uint64_t rb_offset) "%s + 0x%"PRIx64 + vhost_user_postcopy_waker_found(uint64_t client_addr) "0x%"PRIx64 + vhost_user_postcopy_waker_nomatch(const char *rb, uint64_t rb_offset) "%s + 0x%"PRIx64 ++vhost_user_read(uint32_t req, uint32_t flags) "req:%d flags:0x%"PRIx32"" ++vhost_user_write(uint32_t req, uint32_t flags) "req:%d flags:0x%"PRIx32"" + + # vhost-vdpa.c + vhost_vdpa_dma_map(void *vdpa, int fd, uint32_t msg_type, uint64_t iova, uint64_t size, uint64_t uaddr, uint8_t perm, uint8_t type) "vdpa:%p fd: %d msg_type: %"PRIu32" iova: 0x%"PRIx64" size: 0x%"PRIx64" uaddr: 0x%"PRIx64" perm: 0x%"PRIx8" type: %"PRIu8 +diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c +index 358dc82010..ea6d40eb5f 100644 +--- a/hw/virtio/vhost-user.c ++++ b/hw/virtio/vhost-user.c +@@ -491,6 +491,8 @@ static int vhost_user_write(struct vhost_dev *dev, VhostUserMsg *msg, + return ret < 0 ? -saved_errno : -EIO; + } + ++ trace_vhost_user_write(msg->hdr.request, msg->hdr.flags); ++ + return 0; + } + +@@ -544,6 +546,8 @@ static int vhost_user_set_log_base(struct vhost_dev *dev, uint64_t base, + } + } + ++ trace_vhost_user_read(msg.hdr.request, msg.hdr.flags); ++ + return 0; + } + +-- +2.27.0 + diff --git a/hw-virtio-fix-typo-in-VIRTIO_CONFIG_IRQ_IDX-comments.patch b/hw-virtio-fix-typo-in-VIRTIO_CONFIG_IRQ_IDX-comments.patch new file mode 100644 index 00000000..76a7d1c9 --- /dev/null +++ b/hw-virtio-fix-typo-in-VIRTIO_CONFIG_IRQ_IDX-comments.patch @@ -0,0 +1,135 @@ +From 6cbac9f34c67e2a2e28109152957f5eca35b6e73 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Alex=20Benn=C3=A9e?= +Date: Mon, 10 Jul 2023 16:35:05 +0100 +Subject: [PATCH] hw/virtio: fix typo in VIRTIO_CONFIG_IRQ_IDX comments +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Fixes: 544f0278af (virtio: introduce macro VIRTIO_CONFIG_IRQ_IDX) +Signed-off-by: Alex Bennée +Message-Id: <20230710153522.3469097-4-alex.bennee@linaro.org> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Signed-off-by: fangyi +--- + hw/display/vhost-user-gpu.c | 4 ++-- + hw/net/virtio-net.c | 4 ++-- + hw/virtio/vhost-user-fs.c | 4 ++-- + hw/virtio/vhost-vsock-common.c | 4 ++-- + hw/virtio/virtio-crypto.c | 4 ++-- + 5 files changed, 10 insertions(+), 10 deletions(-) + +diff --git a/hw/display/vhost-user-gpu.c b/hw/display/vhost-user-gpu.c +index 1c78272a83..4363e34db1 100644 +--- a/hw/display/vhost-user-gpu.c ++++ b/hw/display/vhost-user-gpu.c +@@ -487,7 +487,7 @@ vhost_user_gpu_guest_notifier_pending(VirtIODevice *vdev, int idx) + + /* + * Add the check for configure interrupt, Use VIRTIO_CONFIG_IRQ_IDX -1 +- * as the Marco of configure interrupt's IDX, If this driver does not ++ * as the macro of configure interrupt's IDX, If this driver does not + * support, the function will return + */ + +@@ -504,7 +504,7 @@ vhost_user_gpu_guest_notifier_mask(VirtIODevice *vdev, int idx, bool mask) + + /* + * Add the check for configure interrupt, Use VIRTIO_CONFIG_IRQ_IDX -1 +- * as the Marco of configure interrupt's IDX, If this driver does not ++ * as the macro of configure interrupt's IDX, If this driver does not + * support, the function will return + */ + +diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c +index ae37b3461b..3e1fa6adf3 100644 +--- a/hw/net/virtio-net.c ++++ b/hw/net/virtio-net.c +@@ -3249,7 +3249,7 @@ static bool virtio_net_guest_notifier_pending(VirtIODevice *vdev, int idx) + } + /* + * Add the check for configure interrupt, Use VIRTIO_CONFIG_IRQ_IDX -1 +- * as the Marco of configure interrupt's IDX, If this driver does not ++ * as the macro of configure interrupt's IDX, If this driver does not + * support, the function will return false + */ + +@@ -3281,7 +3281,7 @@ static void virtio_net_guest_notifier_mask(VirtIODevice *vdev, int idx, + } + /* + *Add the check for configure interrupt, Use VIRTIO_CONFIG_IRQ_IDX -1 +- * as the Marco of configure interrupt's IDX, If this driver does not ++ * as the macro of configure interrupt's IDX, If this driver does not + * support, the function will return + */ + +diff --git a/hw/virtio/vhost-user-fs.c b/hw/virtio/vhost-user-fs.c +index 0c6ecd3b4f..5ac5dcce49 100644 +--- a/hw/virtio/vhost-user-fs.c ++++ b/hw/virtio/vhost-user-fs.c +@@ -163,7 +163,7 @@ static void vuf_guest_notifier_mask(VirtIODevice *vdev, int idx, + + /* + * Add the check for configure interrupt, Use VIRTIO_CONFIG_IRQ_IDX -1 +- * as the Marco of configure interrupt's IDX, If this driver does not ++ * as the macro of configure interrupt's IDX, If this driver does not + * support, the function will return + */ + +@@ -179,7 +179,7 @@ static bool vuf_guest_notifier_pending(VirtIODevice *vdev, int idx) + + /* + * Add the check for configure interrupt, Use VIRTIO_CONFIG_IRQ_IDX -1 +- * as the Marco of configure interrupt's IDX, If this driver does not ++ * as the macro of configure interrupt's IDX, If this driver does not + * support, the function will return + */ + +diff --git a/hw/virtio/vhost-vsock-common.c b/hw/virtio/vhost-vsock-common.c +index e4a8d90f4c..b9cf5f3f29 100644 +--- a/hw/virtio/vhost-vsock-common.c ++++ b/hw/virtio/vhost-vsock-common.c +@@ -127,7 +127,7 @@ static void vhost_vsock_common_guest_notifier_mask(VirtIODevice *vdev, int idx, + + /* + * Add the check for configure interrupt, Use VIRTIO_CONFIG_IRQ_IDX -1 +- * as the Marco of configure interrupt's IDX, If this driver does not ++ * as the macro of configure interrupt's IDX, If this driver does not + * support, the function will return + */ + +@@ -144,7 +144,7 @@ static bool vhost_vsock_common_guest_notifier_pending(VirtIODevice *vdev, + + /* + * Add the check for configure interrupt, Use VIRTIO_CONFIG_IRQ_IDX -1 +- * as the Marco of configure interrupt's IDX, If this driver does not ++ * as the macro of configure interrupt's IDX, If this driver does not + * support, the function will return + */ + +diff --git a/hw/virtio/virtio-crypto.c b/hw/virtio/virtio-crypto.c +index 9f7dcc88ba..61b421aab3 100644 +--- a/hw/virtio/virtio-crypto.c ++++ b/hw/virtio/virtio-crypto.c +@@ -960,7 +960,7 @@ static void virtio_crypto_guest_notifier_mask(VirtIODevice *vdev, int idx, + + /* + * Add the check for configure interrupt, Use VIRTIO_CONFIG_IRQ_IDX -1 +- * as the Marco of configure interrupt's IDX, If this driver does not ++ * as the macro of configure interrupt's IDX, If this driver does not + * support, the function will return + */ + +@@ -979,7 +979,7 @@ static bool virtio_crypto_guest_notifier_pending(VirtIODevice *vdev, int idx) + + /* + * Add the check for configure interrupt, Use VIRTIO_CONFIG_IRQ_IDX -1 +- * as the Marco of configure interrupt's IDX, If this driver does not ++ * as the macro of configure interrupt's IDX, If this driver does not + * support, the function will return + */ + +-- +2.27.0 + diff --git a/hw-virtio-fix-vhost_user_read-tracepoint.patch b/hw-virtio-fix-vhost_user_read-tracepoint.patch new file mode 100644 index 00000000..6185ae48 --- /dev/null +++ b/hw-virtio-fix-vhost_user_read-tracepoint.patch @@ -0,0 +1,48 @@ +From 09081b494d4aad3137fd375f5f18edc63c7e5d10 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Alex=20Benn=C3=A9e?= +Date: Thu, 28 Jul 2022 14:55:03 +0100 +Subject: [PATCH] hw/virtio: fix vhost_user_read tracepoint +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +As reads happen in the callback we were never seeing them. We only +really care about the header so move the tracepoint to when the header +is complete. + +Fixes: 6ca6d8ee9d (hw/virtio: add vhost_user_[read|write] trace points) +Signed-off-by: Alex Bennée +Acked-by: Jason Wang +Message-Id: <20220728135503.1060062-5-alex.bennee@linaro.org> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Signed-off-by: fangyi +--- + hw/virtio/vhost-user.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c +index ea6d40eb5f..937b3021e9 100644 +--- a/hw/virtio/vhost-user.c ++++ b/hw/virtio/vhost-user.c +@@ -297,6 +297,8 @@ static int vhost_user_read_header(struct vhost_dev *dev, VhostUserMsg *msg) + return -EPROTO; + } + ++ trace_vhost_user_read(msg->hdr.request, msg->hdr.flags); ++ + return 0; + } + +@@ -546,8 +548,6 @@ static int vhost_user_set_log_base(struct vhost_dev *dev, uint64_t base, + } + } + +- trace_vhost_user_read(msg.hdr.request, msg.hdr.flags); +- + return 0; + } + +-- +2.27.0 + diff --git a/hw-virtio-gracefully-handle-unset-vhost_dev-vdev.patch b/hw-virtio-gracefully-handle-unset-vhost_dev-vdev.patch new file mode 100644 index 00000000..b2dea4b5 --- /dev/null +++ b/hw-virtio-gracefully-handle-unset-vhost_dev-vdev.patch @@ -0,0 +1,52 @@ +From edbbc82bdf7cdb21604bb1c8b4a222691b3c3665 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Alex=20Benn=C3=A9e?= +Date: Thu, 28 Jul 2022 14:55:01 +0100 +Subject: [PATCH] hw/virtio: gracefully handle unset vhost_dev vdev +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +I've noticed asserts firing because we query the status of vdev after +a vhost connection is closed down. Rather than faulting on the NULL +indirect just quietly reply false. + +Signed-off-by: Alex Bennée +Message-Id: <20220728135503.1060062-3-alex.bennee@linaro.org> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Signed-off-by: fangyi +--- + hw/virtio/vhost.c | 10 +++++++--- + 1 file changed, 7 insertions(+), 3 deletions(-) + +diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c +index 2f0ddd35d6..8e8657fb0d 100644 +--- a/hw/virtio/vhost.c ++++ b/hw/virtio/vhost.c +@@ -310,7 +310,7 @@ static inline void vhost_dev_log_resize(struct vhost_dev *dev, uint64_t size) + dev->log_size = size; + } + +-static int vhost_dev_has_iommu(struct vhost_dev *dev) ++static bool vhost_dev_has_iommu(struct vhost_dev *dev) + { + VirtIODevice *vdev = dev->vdev; + +@@ -320,8 +320,12 @@ static int vhost_dev_has_iommu(struct vhost_dev *dev) + * does not have IOMMU, there's no need to enable this feature + * which may cause unnecessary IOTLB miss/update transactions. + */ +- return virtio_bus_device_iommu_enabled(vdev) && +- virtio_host_has_feature(vdev, VIRTIO_F_IOMMU_PLATFORM); ++ if (vdev) { ++ return virtio_bus_device_iommu_enabled(vdev) && ++ virtio_host_has_feature(vdev, VIRTIO_F_IOMMU_PLATFORM); ++ } else { ++ return false; ++ } + } + + static void *vhost_memory_map(struct vhost_dev *dev, hwaddr addr, +-- +2.27.0 + diff --git a/hw-virtio-vhost-Fix-typo-in-comment.patch b/hw-virtio-vhost-Fix-typo-in-comment.patch new file mode 100644 index 00000000..e3da1d04 --- /dev/null +++ b/hw-virtio-vhost-Fix-typo-in-comment.patch @@ -0,0 +1,34 @@ +From 7c0b752e2bfd9c6e12570d7a9229a6f733d9ca59 Mon Sep 17 00:00:00 2001 +From: Leonardo Garcia +Date: Tue, 23 Nov 2021 08:48:31 -0300 +Subject: [PATCH] hw/virtio/vhost: Fix typo in comment. +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Leonardo Garcia +Reviewed-by: Laurent Vivier +Reviewed-by: Philippe Mathieu-Daudé +Message-Id: +Signed-off-by: Laurent Vivier +Signed-off-by: fangyi +--- + hw/virtio/vhost.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c +index 22ec9e1ef7..2f0ddd35d6 100644 +--- a/hw/virtio/vhost.c ++++ b/hw/virtio/vhost.c +@@ -318,7 +318,7 @@ static int vhost_dev_has_iommu(struct vhost_dev *dev) + * For vhost, VIRTIO_F_IOMMU_PLATFORM means the backend support + * incremental memory mapping API via IOTLB API. For platform that + * does not have IOMMU, there's no need to enable this feature +- * which may cause unnecessary IOTLB miss/update trnasactions. ++ * which may cause unnecessary IOTLB miss/update transactions. + */ + return virtio_bus_device_iommu_enabled(vdev) && + virtio_host_has_feature(vdev, VIRTIO_F_IOMMU_PLATFORM); +-- +2.27.0 + diff --git a/include-hw-start-documenting-the-vhost-API.patch b/include-hw-start-documenting-the-vhost-API.patch new file mode 100644 index 00000000..f53f07c1 --- /dev/null +++ b/include-hw-start-documenting-the-vhost-API.patch @@ -0,0 +1,192 @@ +From 6e43246f43753030a247c23cd6082792a588817b Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Alex=20Benn=C3=A9e?= +Date: Mon, 21 Mar 2022 15:30:34 +0000 +Subject: [PATCH] include/hw: start documenting the vhost API +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +While trying to get my head around the nest of interactions for vhost +devices I though I could start by documenting the key API functions. +This patch documents the main API hooks for creating and starting a +vhost device as well as how the configuration changes are handled. + +Signed-off-by: Alex Bennée +Cc: Michael S. Tsirkin +Cc: Stefan Hajnoczi +Cc: Marc-André Lureau +Message-Id: <20220321153037.3622127-11-alex.bennee@linaro.org> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Signed-off-by: fangyi +--- + include/hw/virtio/vhost.h | 132 +++++++++++++++++++++++++++++++++++--- + 1 file changed, 122 insertions(+), 10 deletions(-) + +diff --git a/include/hw/virtio/vhost.h b/include/hw/virtio/vhost.h +index 86f36f0106..d7ab2579ff 100644 +--- a/include/hw/virtio/vhost.h ++++ b/include/hw/virtio/vhost.h +@@ -61,6 +61,12 @@ typedef struct VhostDevConfigOps { + } VhostDevConfigOps; + + struct vhost_memory; ++ ++/** ++ * struct vhost_dev - common vhost_dev structure ++ * @vhost_ops: backend specific ops ++ * @config_ops: ops for config changes (see @vhost_dev_set_config_notifier) ++ */ + struct vhost_dev { + VirtIODevice *vdev; + MemoryListener memory_listener; +@@ -108,15 +114,129 @@ struct vhost_net { + NetClientState *nc; + }; + ++/** ++ * vhost_dev_init() - initialise the vhost interface ++ * @hdev: the common vhost_dev structure ++ * @opaque: opaque ptr passed to backend (vhost/vhost-user/vdpa) ++ * @backend_type: type of backend ++ * @busyloop_timeout: timeout for polling virtqueue ++ * @errp: error handle ++ * ++ * The initialisation of the vhost device will trigger the ++ * initialisation of the backend and potentially capability ++ * negotiation of backend interface. Configuration of the VirtIO ++ * itself won't happen until the interface is started. ++ * ++ * Return: 0 on success, non-zero on error while setting errp. ++ */ + int vhost_dev_init(struct vhost_dev *hdev, void *opaque, + VhostBackendType backend_type, + uint32_t busyloop_timeout, Error **errp); ++ ++/** ++ * vhost_dev_cleanup() - tear down and cleanup vhost interface ++ * @hdev: the common vhost_dev structure ++ */ + void vhost_dev_cleanup(struct vhost_dev *hdev); +-int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev); +-void vhost_dev_stop(struct vhost_dev *hdev, VirtIODevice *vdev); ++ ++/** ++ * vhost_dev_enable_notifiers() - enable event notifiers ++ * @hdev: common vhost_dev structure ++ * @vdev: the VirtIODevice structure ++ * ++ * Enable notifications directly to the vhost device rather than being ++ * triggered by QEMU itself. Notifications should be enabled before ++ * the vhost device is started via @vhost_dev_start. ++ * ++ * Return: 0 on success, < 0 on error. ++ */ + int vhost_dev_enable_notifiers(struct vhost_dev *hdev, VirtIODevice *vdev); ++ ++/** ++ * vhost_dev_disable_notifiers - disable event notifications ++ * @hdev: common vhost_dev structure ++ * @vdev: the VirtIODevice structure ++ * ++ * Disable direct notifications to vhost device. ++ */ + void vhost_dev_disable_notifiers(struct vhost_dev *hdev, VirtIODevice *vdev); + ++/** ++ * vhost_dev_start() - start the vhost device ++ * @hdev: common vhost_dev structure ++ * @vdev: the VirtIODevice structure ++ * ++ * Starts the vhost device. From this point VirtIO feature negotiation ++ * can start and the device can start processing VirtIO transactions. ++ * ++ * Return: 0 on success, < 0 on error. ++ */ ++int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev); ++ ++/** ++ * vhost_dev_stop() - stop the vhost device ++ * @hdev: common vhost_dev structure ++ * @vdev: the VirtIODevice structure ++ * ++ * Stop the vhost device. After the device is stopped the notifiers ++ * can be disabled (@vhost_dev_disable_notifiers) and the device can ++ * be torn down (@vhost_dev_cleanup). ++ */ ++void vhost_dev_stop(struct vhost_dev *hdev, VirtIODevice *vdev); ++ ++/** ++ * DOC: vhost device configuration handling ++ * ++ * The VirtIO device configuration space is used for rarely changing ++ * or initialisation time parameters. The configuration can be updated ++ * by either the guest driver or the device itself. If the device can ++ * change the configuration over time the vhost handler should ++ * register a @VhostDevConfigOps structure with ++ * @vhost_dev_set_config_notifier so the guest can be notified. Some ++ * devices register a handler anyway and will signal an error if an ++ * unexpected config change happens. ++ */ ++ ++/** ++ * vhost_dev_get_config() - fetch device configuration ++ * @hdev: common vhost_dev_structure ++ * @config: pointer to device appropriate config structure ++ * @config_len: size of device appropriate config structure ++ * ++ * Return: 0 on success, < 0 on error while setting errp ++ */ ++int vhost_dev_get_config(struct vhost_dev *hdev, uint8_t *config, ++ uint32_t config_len, Error **errp); ++ ++/** ++ * vhost_dev_set_config() - set device configuration ++ * @hdev: common vhost_dev_structure ++ * @data: pointer to data to set ++ * @offset: offset into configuration space ++ * @size: length of set ++ * @flags: @VhostSetConfigType flags ++ * ++ * By use of @offset/@size a subset of the configuration space can be ++ * written to. The @flags are used to indicate if it is a normal ++ * transaction or related to migration. ++ * ++ * Return: 0 on success, non-zero on error ++ */ ++int vhost_dev_set_config(struct vhost_dev *dev, const uint8_t *data, ++ uint32_t offset, uint32_t size, uint32_t flags); ++ ++/** ++ * vhost_dev_set_config_notifier() - register VhostDevConfigOps ++ * @hdev: common vhost_dev_structure ++ * @ops: notifier ops ++ * ++ * If the device is expected to change configuration a notifier can be ++ * setup to handle the case. ++ */ ++void vhost_dev_set_config_notifier(struct vhost_dev *dev, ++ const VhostDevConfigOps *ops); ++ ++ + /* Test and clear masked event pending status. + * Should be called after unmask to avoid losing events. + */ +@@ -136,14 +256,6 @@ int vhost_net_set_backend(struct vhost_dev *hdev, + struct vhost_vring_file *file); + + int vhost_device_iotlb_miss(struct vhost_dev *dev, uint64_t iova, int write); +-int vhost_dev_get_config(struct vhost_dev *hdev, uint8_t *config, +- uint32_t config_len, Error **errp); +-int vhost_dev_set_config(struct vhost_dev *dev, const uint8_t *data, +- uint32_t offset, uint32_t size, uint32_t flags); +-/* notifier callback in case vhost device config space changed +- */ +-void vhost_dev_set_config_notifier(struct vhost_dev *dev, +- const VhostDevConfigOps *ops); + + void vhost_dev_reset_inflight(struct vhost_inflight *inflight); + void vhost_dev_free_inflight(struct vhost_inflight *inflight); +-- +2.27.0 + diff --git a/io_uring-fix-short-read-slow-path.patch b/io_uring-fix-short-read-slow-path.patch new file mode 100644 index 00000000..9a0722be --- /dev/null +++ b/io_uring-fix-short-read-slow-path.patch @@ -0,0 +1,55 @@ +From 78cb2c9c218155d048e566c5ac6d59961703b5d3 Mon Sep 17 00:00:00 2001 +From: tangbinzy +Date: Tue, 21 Nov 2023 06:14:40 +0000 +Subject: [PATCH] io_uring: fix short read slow path mainline inclusion commit + c06fc7ce147e57ab493bad9263f1601b8298484b category: bugfix + +--------------------------------------------------------------- + +sqeq.off here is the offset to read within the disk image, so obviously +not 'nread' (the amount we just read), but as the author meant to write +its current value incremented by the amount we just read. + +Normally recent versions of linux will not issue short reads, +but it can happen so we should fix this. + +This lead to weird image corruptions when short read happened + +Fixes: 6663a0a33764 ("block/io_uring: implements interfaces for io_uring") +Link: https://lkml.kernel.org/r/YrrFGO4A1jS0GI0G@atmark-techno.com +Signed-off-by: Dominique Martinet +Message-Id: <20220630010137.2518851-1-dominique.martinet@atmark-techno.com> +Reviewed-by: Hanna Reitz +Reviewed-by: Stefano Garzarella +Signed-off-by: Stefan Hajnoczi + +Signed-off-by: tangbinzy +--- + block/io_uring.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/block/io_uring.c b/block/io_uring.c +index dfa475cc87..e88d75d462 100644 +--- a/block/io_uring.c ++++ b/block/io_uring.c +@@ -89,7 +89,7 @@ static void luring_resubmit_short_read(LuringState *s, LuringAIOCB *luringcb, + trace_luring_resubmit_short_read(s, luringcb, nread); + + /* Update read position */ +- luringcb->total_read = nread; ++ luringcb->total_read += nread; + remaining = luringcb->qiov->size - luringcb->total_read; + + /* Shorten qiov */ +@@ -103,7 +103,7 @@ static void luring_resubmit_short_read(LuringState *s, LuringAIOCB *luringcb, + remaining); + + /* Update sqe */ +- luringcb->sqeq.off = nread; ++ luringcb->sqeq.off += nread; + luringcb->sqeq.addr = (__u64)(uintptr_t)luringcb->resubmit_qiov.iov; + luringcb->sqeq.len = luringcb->resubmit_qiov.niov; + +-- +2.27.0 + diff --git a/libvhost-user-Fix-VHOST_USER_ADD_MEM_REG-reply.patch b/libvhost-user-Fix-VHOST_USER_ADD_MEM_REG-reply.patch new file mode 100644 index 00000000..23cde54c --- /dev/null +++ b/libvhost-user-Fix-VHOST_USER_ADD_MEM_REG-reply.patch @@ -0,0 +1,48 @@ +From c2353941d94a5aeb8364dc5204c29a4fbb09437f Mon Sep 17 00:00:00 2001 +From: tangbinzy +Date: Tue, 21 Nov 2023 06:47:43 +0000 +Subject: [PATCH] libvhost-user: Fix VHOST_USER_ADD_MEM_REG reply mainline + inclusion commit 7f27d20ded2f480f3e66d03f90ea71507b834276 category: bugfix + +--------------------------------------------------------------- + +With REPLY_NEEDED, libvhost-user sends both the acutal result and an +additional ACK reply for VHOST_USER_ADD_MEM_REG. This is incorrect, the +spec mandates that it behave the same with and without REPLY_NEEDED +because it always sends a reply. + +Fixes: ec94c8e621de96c50c2d381c8c9ec94f5beec7c1 +Signed-off-by: Kevin Wolf +Message-Id: <20220627134500.94842-4-kwolf@redhat.com> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin + +Signed-off-by: tangbinzy +--- + subprojects/libvhost-user/libvhost-user.c | 8 +------- + 1 file changed, 1 insertion(+), 7 deletions(-) + +diff --git a/subprojects/libvhost-user/libvhost-user.c b/subprojects/libvhost-user/libvhost-user.c +index 787f4d2d4f..8ab20138f4 100644 +--- a/subprojects/libvhost-user/libvhost-user.c ++++ b/subprojects/libvhost-user/libvhost-user.c +@@ -756,15 +756,9 @@ vu_add_mem_reg(VuDev *dev, VhostUserMsg *vmsg) { + + /* Send the message back to qemu with the addresses filled in. */ + vmsg->fd_num = 0; +- if (!vu_send_reply(dev, dev->sock, vmsg)) { +- vu_panic(dev, "failed to respond to add-mem-region for postcopy"); +- return false; +- } +- + DPRINT("Successfully added new region in postcopy\n"); + dev->nregions++; +- return false; +- ++ return true; + } else { + for (i = 0; i < dev->max_queues; i++) { + if (dev->vq[i].vring.desc) { +-- +2.27.0 + diff --git a/libvhost-user-Fix-VHOST_USER_GET_MAX_MEM_SLOTS-reply.patch b/libvhost-user-Fix-VHOST_USER_GET_MAX_MEM_SLOTS-reply.patch new file mode 100644 index 00000000..fac41915 --- /dev/null +++ b/libvhost-user-Fix-VHOST_USER_GET_MAX_MEM_SLOTS-reply.patch @@ -0,0 +1,53 @@ +From 3e2df0133efdf3e3aea63f413b42e37bc6c87112 Mon Sep 17 00:00:00 2001 +From: tangbinzy +Date: Tue, 21 Nov 2023 06:36:05 +0000 +Subject: [PATCH] libvhost-user: Fix VHOST_USER_GET_MAX_MEM_SLOTS reply + mainline inclusion commit 69a5daec06f423843ce1bb9be5fb049314996f78 category: + bugfix + +--------------------------------------------------------------- + +With REPLY_NEEDED, libvhost-user sends both the acutal result and an +additional ACK reply for VHOST_USER_GET_MAX_MEM_SLOTS. This is +incorrect, the spec mandates that it behave the same with and without +REPLY_NEEDED because it always sends a reply. + +Fixes: 6fb2e173d20c9bbb5466183d33a3ad7dcd0375fa +Signed-off-by: Kevin Wolf +Message-Id: <20220627134500.94842-3-kwolf@redhat.com> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin + +Signed-off-by: tangbinzy +--- + subprojects/libvhost-user/libvhost-user.c | 11 ++--------- + 1 file changed, 2 insertions(+), 9 deletions(-) + +diff --git a/subprojects/libvhost-user/libvhost-user.c b/subprojects/libvhost-user/libvhost-user.c +index 787f4d2d4f..27e7799262 100644 +--- a/subprojects/libvhost-user/libvhost-user.c ++++ b/subprojects/libvhost-user/libvhost-user.c +@@ -1788,18 +1788,11 @@ vu_handle_vring_kick(VuDev *dev, VhostUserMsg *vmsg) + + static bool vu_handle_get_max_memslots(VuDev *dev, VhostUserMsg *vmsg) + { +- vmsg->flags = VHOST_USER_REPLY_MASK | VHOST_USER_VERSION; +- vmsg->size = sizeof(vmsg->payload.u64); +- vmsg->payload.u64 = VHOST_USER_MAX_RAM_SLOTS; +- vmsg->fd_num = 0; +- +- if (!vu_message_write(dev, dev->sock, vmsg)) { +- vu_panic(dev, "Failed to send max ram slots: %s\n", strerror(errno)); +- } ++ vmsg_set_reply_u64(vmsg, VHOST_USER_MAX_RAM_SLOTS); + + DPRINT("u64: 0x%016"PRIx64"\n", (uint64_t) VHOST_USER_MAX_RAM_SLOTS); + +- return false; ++ return true; + } + + static bool +-- +2.27.0 + diff --git a/net-Fix-a-misleading-error-message.patch b/net-Fix-a-misleading-error-message.patch new file mode 100644 index 00000000..75a49b12 --- /dev/null +++ b/net-Fix-a-misleading-error-message.patch @@ -0,0 +1,50 @@ +From 1cc7783df04674ff375905cc9a8ec23f71617408 Mon Sep 17 00:00:00 2001 +From: qihao +Date: Tue, 21 Nov 2023 20:40:24 +0800 +Subject: [PATCH] net: Fix a misleading error message + +cheery-pick from 0a4a1512e01228fc59b00d68e86f7099b6439773 + +The error message + + $ qemu-system-x86_64 -netdev user,id=net0,ipv6-net=fec0::0/ + qemu-system-x86_64: -netdev user,id=net0,ipv6-net=fec0::0/: Parameter 'ipv6-prefixlen' expects a number + +points to ipv6-prefixlen instead of ipv6-net. Fix: + + qemu-system-x86_64: -netdev user,id=net0,ipv6-net=fec0::0/: parameter 'ipv6-net' expects a number after '/' + +Signed-off-by: Markus Armbruster +Message-ID: <20231031111059.3407803-6-armbru@redhat.com> +Signed-off-by: qihao_yewu +--- + net/net.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/net/net.c b/net/net.c +index ed4b1c1740..daad8784ec 100644 +--- a/net/net.c ++++ b/net/net.c +@@ -1122,7 +1122,7 @@ static int net_client_init(QemuOpts *opts, bool is_netdev, Error **errp) + int ret = -1; + Visitor *v = opts_visitor_new(opts); + +- /* Parse convenience option format ip6-net=fec0::0[/64] */ ++ /* Parse convenience option format ipv6-net=fec0::0[/64] */ + const char *ip6_net = qemu_opt_get(opts, "ipv6-net"); + + if (ip6_net) { +@@ -1142,8 +1142,8 @@ static int net_client_init(QemuOpts *opts, bool is_netdev, Error **errp) + if (substrings[1] && + qemu_strtoul(substrings[1], NULL, 10, &prefix_len)) + { +- error_setg(errp, QERR_INVALID_PARAMETER_VALUE, +- "ipv6-prefixlen", "a number"); ++ error_setg(errp, ++ "parameter 'ipv6-net' expects a number after '/'"); + goto out; + } + +-- +2.27.0 + diff --git a/net-vhost-vdpa.c-Fix-clang-compilation-failure.patch b/net-vhost-vdpa.c-Fix-clang-compilation-failure.patch new file mode 100644 index 00000000..47ea2c8c --- /dev/null +++ b/net-vhost-vdpa.c-Fix-clang-compilation-failure.patch @@ -0,0 +1,62 @@ +From 02c67ab8c1f1e29bf8274d9b460dc2f07b8e195b Mon Sep 17 00:00:00 2001 +From: Peter Maydell +Date: Mon, 31 Oct 2022 13:29:01 +0000 +Subject: [PATCH] net/vhost-vdpa.c: Fix clang compilation failure + +Commit 8801ccd0500437 introduced a compilation failure with clang +version 10.0.0-4ubuntu1: + +../../net/vhost-vdpa.c:654:16: error: variable 'vdpa_device_fd' is +used uninitialized whenever 'if' condition is false +[-Werror,-Wsometimes-uninitialized] + } else if (opts->has_vhostfd) { + ^~~~~~~~~~~~~~~~~ +../../net/vhost-vdpa.c:662:33: note: uninitialized use occurs here + r = vhost_vdpa_get_features(vdpa_device_fd, &features, errp); + ^~~~~~~~~~~~~~ +../../net/vhost-vdpa.c:654:12: note: remove the 'if' if its condition +is always true + } else if (opts->has_vhostfd) { + ^~~~~~~~~~~~~~~~~~~~~~~ +../../net/vhost-vdpa.c:629:23: note: initialize the variable +'vdpa_device_fd' to silence this warning + int vdpa_device_fd; + ^ + = 0 +1 error generated. + +It's a false positive -- the compiler doesn't manage to figure out +that the error checks further up mean that there's no code path where +vdpa_device_fd isn't initialized. Put another way, the problem is +that we check "if (opts->has_vhostfd)" when in fact that condition +must always be true. A cleverer static analyser would probably warn +that we were checking an always-true condition. + +Fix the compilation failure by removing the unnecessary if(). + +Fixes: 8801ccd0500437 ("vhost-vdpa: allow passing opened vhostfd to vhost-vdpa") +Signed-off-by: Peter Maydell +Message-Id: <20221031132901.1277150-1-peter.maydell@linaro.org> +Signed-off-by: Stefan Hajnoczi +Signed-off-by: fangyi +--- + net/vhost-vdpa.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c +index 58225649f9..c89f9d1243 100644 +--- a/net/vhost-vdpa.c ++++ b/net/vhost-vdpa.c +@@ -659,7 +659,8 @@ int net_init_vhost_vdpa(const Netdev *netdev, const char *name, + if (vdpa_device_fd == -1) { + return -errno; + } +- } else if (opts->has_vhostfd) { ++ } else { ++ /* has_vhostfd */ + vdpa_device_fd = monitor_fd_param(monitor_cur(), opts->vhostfd, errp); + if (vdpa_device_fd == -1) { + error_prepend(errp, "vhost-vdpa: unable to parse vhostfd: "); +-- +2.27.0 + diff --git a/pci-Fix-the-update-of-interrupt-disable-bit-in-PCI_C.patch b/pci-Fix-the-update-of-interrupt-disable-bit-in-PCI_C.patch new file mode 100644 index 00000000..e2b162c0 --- /dev/null +++ b/pci-Fix-the-update-of-interrupt-disable-bit-in-PCI_C.patch @@ -0,0 +1,53 @@ +From d81bf8c86e2b024f85d90e199181ae048134d4ee Mon Sep 17 00:00:00 2001 +From: Guoyi Tu +Date: Fri, 11 Aug 2023 22:46:51 +0800 +Subject: [PATCH] pci: Fix the update of interrupt disable bit in PCI_COMMAND + register + +The PCI_COMMAND register is located at offset 4 within +the PCI configuration space and occupies 2 bytes. The +interrupt disable bit is at the 10th bit, which corresponds +to the byte at offset 5 in the PCI configuration space. + +In our testing environment, the guest driver may directly +updates the byte at offset 5 in the PCI configuration space. +The backtrace looks like as following: + at hw/pci/pci.c:1442 + at hw/virtio/virtio-pci.c:605 + val=5, len=1) at hw/pci/pci_host.c:81 + +In this situation, the range_covers_byte function called +by the pci_default_write_config function will return false, +resulting in the inability to handle the interrupt disable +update event. + +To fix this issue, we can use the ranges_overlap function +instead of range_covers_byte to determine whether the interrupt +bit has been updated. + +Signed-off-by: Guoyi Tu +Signed-off-by: yuanminghao +Message-Id: +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Fixes: b6981cb57be5 ("pci: interrupt disable bit support") +--- + hw/pci/pci.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/hw/pci/pci.c b/hw/pci/pci.c +index 3e6805d54a..3a4619e2a5 100644 +--- a/hw/pci/pci.c ++++ b/hw/pci/pci.c +@@ -1471,7 +1471,7 @@ void pci_default_write_config(PCIDevice *d, uint32_t addr, uint32_t val_in, int + range_covers_byte(addr, l, PCI_COMMAND)) + pci_update_mappings(d); + +- if (range_covers_byte(addr, l, PCI_COMMAND)) { ++ if (ranges_overlap(addr, l, PCI_COMMAND, 2)) { + pci_update_irq_disabled(d, was_irq_disabled); + memory_region_set_enabled(&d->bus_master_enable_region, + (pci_get_word(d->config + PCI_COMMAND) +-- +2.27.0 + diff --git a/pci-fix-overflow-in-snprintf-string-formatting.patch b/pci-fix-overflow-in-snprintf-string-formatting.patch new file mode 100644 index 00000000..e1e2e1b6 --- /dev/null +++ b/pci-fix-overflow-in-snprintf-string-formatting.patch @@ -0,0 +1,106 @@ +From b2d665abb4dbd3c91c0ceceebe537cf411f6c650 Mon Sep 17 00:00:00 2001 +From: tangbinzy +Date: Mon, 6 Nov 2023 06:35:28 +0000 +Subject: [PATCH] pci: fix overflow in snprintf string formatting mainline + inclusion commit 36f18c6989a3d1ff1d7a0e50b0868ef3958299b4 category: bugfix +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +--------------------------------------------------------------- + +the code in pcibus_get_fw_dev_path contained the potential for a +stack buffer overflow of 1 byte, potentially writing to the stack an +extra NUL byte. + +This overflow could happen if the PCI slot is >= 0x10000000, +and the PCI function is >= 0x10000000, due to the size parameter +of snprintf being incorrectly calculated in the call: + + if (PCI_FUNC(d->devfn)) + snprintf(path + off, sizeof(path) + off, ",%x", PCI_FUNC(d->devfn)); + +since the off obtained from a previous call to snprintf is added +instead of subtracted from the total available size of the buffer. + +Without the accurate size guard from snprintf, we end up writing in the +worst case: + +name (32) + "@" (1) + SLOT (8) + "," (1) + FUNC (8) + term NUL (1) = 51 bytes + +In order to provide something more robust, replace all of the code in +pcibus_get_fw_dev_path with a single call to g_strdup_printf, +so there is no need to rely on manual calculations. + +Found by compiling QEMU with FORTIFY_SOURCE=3 as the error: + +*** buffer overflow detected ***: terminated + +Thread 1 "qemu-system-x86" received signal SIGABRT, Aborted. +[Switching to Thread 0x7ffff642c380 (LWP 121307)] +0x00007ffff71ff55c in __pthread_kill_implementation () from /lib64/libc.so.6 +(gdb) bt + #0 0x00007ffff71ff55c in __pthread_kill_implementation () at /lib64/libc.so.6 + #1 0x00007ffff71ac6f6 in raise () at /lib64/libc.so.6 + #2 0x00007ffff7195814 in abort () at /lib64/libc.so.6 + #3 0x00007ffff71f279e in __libc_message () at /lib64/libc.so.6 + #4 0x00007ffff729767a in __fortify_fail () at /lib64/libc.so.6 + #5 0x00007ffff7295c36 in () at /lib64/libc.so.6 + #6 0x00007ffff72957f5 in __snprintf_chk () at /lib64/libc.so.6 + #7 0x0000555555b1c1fd in pcibus_get_fw_dev_path () + #8 0x0000555555f2bde4 in qdev_get_fw_dev_path_helper.constprop () + #9 0x0000555555f2bd86 in qdev_get_fw_dev_path_helper.constprop () + #10 0x00005555559a6e5d in get_boot_device_path () + #11 0x00005555559a712c in get_boot_devices_list () + #12 0x0000555555b1a3d0 in fw_cfg_machine_reset () + #13 0x0000555555bf4c2d in pc_machine_reset () + #14 0x0000555555c66988 in qemu_system_reset () + #15 0x0000555555a6dff6 in qdev_machine_creation_done () + #16 0x0000555555c79186 in qmp_x_exit_preconfig.part () + #17 0x0000555555c7b459 in qemu_init () + #18 0x0000555555960a29 in main () + +Found-by: Dario Faggioli +Found-by: Martin Liška +Cc: qemu-stable@nongnu.org +Signed-off-by: Claudio Fontana +Message-Id: <20220531114707.18830-1-cfontana@suse.de> +Reviewed-by: Ani Sinha + +Signed-off-by: tangbinzy +--- + hw/pci/pci.c | 18 +++++++++--------- + 1 file changed, 9 insertions(+), 9 deletions(-) + +diff --git a/hw/pci/pci.c b/hw/pci/pci.c +index 3e6805d54a..6a5e8a3654 100644 +--- a/hw/pci/pci.c ++++ b/hw/pci/pci.c +@@ -2588,15 +2588,15 @@ static char *pci_dev_fw_name(DeviceState *dev, char *buf, int len) + static char *pcibus_get_fw_dev_path(DeviceState *dev) + { + PCIDevice *d = (PCIDevice *)dev; +- char path[50], name[33]; +- int off; +- +- off = snprintf(path, sizeof(path), "%s@%x", +- pci_dev_fw_name(dev, name, sizeof name), +- PCI_SLOT(d->devfn)); +- if (PCI_FUNC(d->devfn)) +- snprintf(path + off, sizeof(path) + off, ",%x", PCI_FUNC(d->devfn)); +- return g_strdup(path); ++ char name[33]; ++ int has_func = !!PCI_FUNC(d->devfn); ++ ++ return g_strdup_printf("%s@%x%s%.*x", ++ pci_dev_fw_name(dev, name, sizeof(name)), ++ PCI_SLOT(d->devfn), ++ has_func ? "," : "", ++ has_func, ++ PCI_FUNC(d->devfn)); + } + + static char *pcibus_get_dev_path(DeviceState *dev) +-- +2.27.0 + diff --git a/qemu-timer-Skip-empty-timer-lists-before-locking-in-.patch b/qemu-timer-Skip-empty-timer-lists-before-locking-in-.patch new file mode 100644 index 00000000..2578891b --- /dev/null +++ b/qemu-timer-Skip-empty-timer-lists-before-locking-in-.patch @@ -0,0 +1,39 @@ +From 274dd10230eef97714a2a283ecd8a8ce2ecbf687 Mon Sep 17 00:00:00 2001 +From: tangbinzy +Date: Mon, 6 Nov 2023 07:28:31 +0000 +Subject: [PATCH] qemu-timer: Skip empty timer lists before locking in + qemu_clock_deadline_ns_all mainline inclusion commit + 3f42906c9ab2c777a895b48b87b8107167e4a275 category: bugfix + +--------------------------------------------------------------- + +This decreases qemu_clock_deadline_ns_all's share from 23.2% to 13% in a +profile of icount-enabled aarch64-softmmu. + +Signed-off-by: Idan Horowitz +Reviewed-by: Richard Henderson +Message-Id: <20220114004358.299534-2-idan.horowitz@gmail.com> +Signed-off-by: Richard Henderson + +Signed-off-by: tangbinzy +--- + util/qemu-timer.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/util/qemu-timer.c b/util/qemu-timer.c +index 40e8c83722..c5b6dc987c 100644 +--- a/util/qemu-timer.c ++++ b/util/qemu-timer.c +@@ -330,6 +330,9 @@ int64_t qemu_clock_deadline_ns_all(QEMUClockType type, int attr_mask) + } + + QLIST_FOREACH(timer_list, &clock->timerlists, list) { ++ if (!qatomic_read(&timer_list->active_timers)) { ++ continue; ++ } + qemu_mutex_lock(&timer_list->active_timers_lock); + ts = timer_list->active_timers; + /* Skip all external timers */ +-- +2.27.0 + diff --git a/qemu.spec b/qemu.spec index 7e42c71b..be323000 100644 --- a/qemu.spec +++ b/qemu.spec @@ -3,7 +3,7 @@ Name: qemu Version: 6.2.0 -Release: 83 +Release: 84 Epoch: 10 Summary: QEMU is a generic and open source machine emulator and virtualizer License: GPLv2 and BSD and MIT and CC-BY-SA-4.0 @@ -599,6 +599,192 @@ Patch0584: disas-riscv-Fix-the-typo-of-inverted-order-of-pmpadd.patch Patch0585: softmmu-dirtylimit-Add-parameter-check-for-hmp-set_v.patch Patch0586: tests-Fix-printf-format-string-in-acpi-utils.c.patch Patch0587: hw-virtio-virtio-pmem-Replace-impossible-check-by-as.patch +Patch0588: target-i386-Export-GDS_NO-bit-to-guests.patch +Patch0589: semihosting-fix-memleak-at-semihosting_arg_fallback.patch +Patch0590: semihosting-config-Merge-semihosting-config-option-g.patch +Patch0591: qemu-timer-Skip-empty-timer-lists-before-locking-in-.patch +Patch0592: hw-usb-hcd-ehci-fix-writeback-order.patch +Patch0593: pci-fix-overflow-in-snprintf-string-formatting.patch +Patch0594: tpm_crb-mark-command-buffer-as-dirty-on-request-comp.patch +Patch0595: hw-timer-npcm7xx_timer-Prevent-timer-from-counting-d.patch +Patch0596: pci-Fix-the-update-of-interrupt-disable-bit-in-PCI_C.patch +Patch0597: virtio-introduce-macro-IRTIO_CONFIG_IRQ_IDX.patch +Patch0598: virtio-pci-decouple-notifier-from-interrupt-process.patch +Patch0599: virtio-pci-decouple-the-single-vector-from-the-inter.patch +Patch0600: vhost-vdpa-add-support-for-config-interrupt.patch +Patch0601: virtio-add-support-for-configure-interrupt.patch +Patch0602: vhost-add-support-for-configure-interrupt.patch +Patch0603: virtio-net-add-support-for-configure-interrupt.patch +Patch0604: virtio-mmio-add-support-for-configure-interrupt.patch +Patch0605: virtio-pci-add-support-for-configure-interrupt.patch +Patch0606: vhost-vdpa-stick-to-errno-error-return-convention.patch +Patch0607: vhost-user-stick-to-errno-error-return-convention.patch +Patch0608: vhost-stick-to-errno-error-return-convention.patch +Patch0609: vhost-introduce-new-VhostOps-vhost_set_config_call.patch +Patch0610: e1000-set-RX-descriptor-status-in-a-separate-operati.patch +Patch0611: virtio-iommu-Fix-the-partial-copy-of-probe-request.patch +Patch0612: artist-set-memory-region-owners-for-buffers-to-the-a.patch +Patch0613: qom-object-Remove-circular-include-dependency.patch +Patch0614: vga-avoid-crash-if-no-default-vga-card.patch +Patch0615: hw-pvrdma-Protect-against-buggy-or-malicious-guest-driver.patch +Patch0616: tracetool-avoid-invalid-escape-in-Python-string.patch +Patch0617: target-i386-Add-support-for-CMPCCXADD-in-CPUID-enume.patch +Patch0618: target-i386-Add-support-for-AMX-FP16-in-CPUID-enumer.patch +Patch0619: target-i386-Add-support-for-AVX-IFMA-in-CPUID-enumer.patch +Patch0620: target-i386-Add-support-for-AVX-VNNI-INT8-in-CPUID-e.patch +Patch0621: target-i386-Add-support-for-AVX-NE-CONVERT-in-CPUID-.patch +Patch0622: target-i386-Add-support-for-PREFETCHIT0-1-in-CPUID-e.patch +Patch0623: target-i386-Add-new-CPU-model-GraniteRapids.patch +Patch0624: target-i386-Adjust-feature-level-according-to-FEAT_7.patch +Patch0625: virtio-signal-after-wrapping-packed-used_idx.patch +Patch0626: Revert-vhost-introduce-new-VhostOps-vhost_set_config.patch +Patch0627: Revert-virtio-pci-add-support-for-configure-interrup.patch +Patch0628: Revert-virtio-mmio-add-support-for-configure-interru.patch +Patch0629: Revert-virtio-net-add-support-for-configure-interrup.patch +Patch0630: Revert-vhost-add-support-for-configure-interrupt.patch +Patch0631: Revert-virtio-add-support-for-configure-interrupt.patch +Patch0632: Revert-vhost-vdpa-add-support-for-config-interrupt.patch +Patch0633: Revert-virtio-pci-decouple-the-single-vector-from-th.patch +Patch0634: Revert-virtio-pci-decouple-notifier-from-interrupt-p.patch +Patch0635: Revert-virtio-introduce-macro-IRTIO_CONFIG_IRQ_IDX.patch +Patch0636: vdpa-Make-ncs-autofree.patch +Patch0637: vhost-Add-VhostShadowVirtqueue.patch +Patch0638: vhost-Add-Shadow-VirtQueue-kick-forwarding-capabilit.patch +Patch0639: vhost-Add-Shadow-VirtQueue-call-forwarding-capabilit.patch +Patch0640: vhost-Add-vhost_svq_valid_features-to-shadow-vq.patch +Patch0641: virtio-Add-vhost_svq_get_vring_addr.patch +Patch0642: vdpa-adapt-vhost_ops-callbacks-to-svq.patch +Patch0643: vhost-Shadow-virtqueue-buffers-forwarding.patch +Patch0644: util-Add-iova_tree_alloc_map.patch +Patch0645: util-add-iova_tree_find_iova.patch +Patch0646: vhost-Add-VhostIOVATree.patch +Patch0647: vdpa-Add-custom-IOTLB-translations-to-SVQ.patch +Patch0648: vdpa-Adapt-vhost_vdpa_get_vring_base-to-SVQ.patch +Patch0649: vdpa-Never-set-log_base-addr-if-SVQ-is-enabled.patch +Patch0650: vdpa-Expose-VHOST_F_LOG_ALL-on-SVQ.patch +Patch0651: virtio-fix-enable-vhost-user-build-on-non-Linux.patch +Patch0652: vhost-vdpa-fix-typo-in-a-comment.patch +Patch0653: vdpa-Add-missing-tracing-to-batch-mapping-functions.patch +Patch0654: vhost-Track-descriptor-chain-in-private-at-SVQ.patch +Patch0655: vhost-Fix-device-s-used-descriptor-dequeue.patch +Patch0656: vdpa-Fix-bad-index-calculus-at-vhost_vdpa_get_vring_.patch +Patch0657: vdpa-Fix-index-calculus-at-vhost_vdpa_svqs_start.patch +Patch0658: vhost-Fix-element-in-vhost_svq_add-failure.patch +Patch0659: hw-virtio-add-vhost_user_-read-write-trace-points.patch +Patch0660: include-hw-start-documenting-the-vhost-API.patch +Patch0661: virtio-add-vhost-support-for-virtio-devices.patch +Patch0662: virtio-net-align-ctrl_vq-index-for-non-mq-guest-for-.patch +Patch0663: vhost-vdpa-fix-improper-cleanup-in-net_init_vhost_vd.patch +Patch0664: vhost-vdpa-backend-feature-should-set-only-once.patch +Patch0665: vhost-vdpa-change-name-and-polarity-for-vhost_vdpa_o.patch +Patch0666: virtio-net-don-t-handle-mq-request-in-userspace-hand.patch +Patch0667: util-Return-void-on-iova_tree_remove.patch +Patch0668: vhost-move-descriptor-translation-to-vhost_svq_vring.patch +Patch0669: virtio-net-Expose-MAC_TABLE_ENTRIES.patch +Patch0670: virtio-net-Expose-ctrl-virtqueue-logic.patch +Patch0671: vdpa-Avoid-compiler-to-squash-reads-to-used-idx.patch +Patch0672: vhost-Reorder-vhost_svq_kick.patch +Patch0673: vhost-Move-vhost_svq_kick-call-to-vhost_svq_add.patch +Patch0674: vhost-Check-for-queue-full-at-vhost_svq_add.patch +Patch0675: vhost-Decouple-vhost_svq_add-from-VirtQueueElement.patch +Patch0676: vhost-Add-SVQDescState.patch +Patch0677: vhost-Track-number-of-descs-in-SVQDescState.patch +Patch0678: vhost-add-vhost_svq_push_elem.patch +Patch0679: vhost-Expose-vhost_svq_add.patch +Patch0680: vhost-add-vhost_svq_poll.patch +Patch0681: vhost-Add-svq-avail_handler-callback.patch +Patch0682: vdpa-Export-vhost_vdpa_dma_map-and-unmap-calls.patch +Patch0683: vdpa-manual-forward-CVQ-buffers.patch +Patch0684: vdpa-Buffer-CVQ-support-on-shadow-virtqueue.patch +Patch0685: vdpa-Extract-get-features-part-from-vhost_vdpa_get_m.patch +Patch0686: vdpa-Add-device-migration-blocker.patch +Patch0687: vdpa-Add-x-svq-to-NetdevVhostVDPAOptions.patch +Patch0688: vhost-Get-vring-base-from-vq-not-svq.patch +Patch0689: vdpa-Fix-memory-listener-deletions-of-iova-tree.patch +Patch0690: vdpa-Fix-file-descriptor-leak-on-get-features-error.patch +Patch0691: vdpa-Skip-the-maps-not-in-the-iova-tree.patch +Patch0692: vdpa-do-not-save-failed-dma-maps-in-SVQ-iova-tree.patch +Patch0693: util-accept-iova_tree_remove_parameter-by-value.patch +Patch0694: vdpa-Remove-SVQ-vring-from-iova_tree-at-shutdown.patch +Patch0695: vdpa-Make-SVQ-vring-unmapping-return-void.patch +Patch0696: vdpa-Use-ring-hwaddr-at-vhost_vdpa_svq_unmap_ring.patch +Patch0697: vhost_net-Add-NetClientInfo-start-callback.patch +Patch0698: vhost_net-Add-NetClientInfo-stop-callback.patch +Patch0699: vdpa-add-net_vhost_vdpa_cvq_info-NetClientInfo.patch +Patch0700: vdpa-Move-command-buffers-map-to-start-of-net-device.patch +Patch0701: vdpa-extract-vhost_vdpa_net_cvq_add-from-vhost_vdpa_.patch +Patch0702: vhost_net-add-NetClientState-load-callback.patch +Patch0703: vdpa-Add-virtio-net-mac-address-via-CVQ-at-start.patch +Patch0704: vdpa-Delete-CVQ-migration-blocker.patch +Patch0705: vdpa-Make-VhostVDPAState-cvq_cmd_in_buffer-control-a.patch +Patch0706: vdpa-extract-vhost_vdpa_net_load_mac-from-vhost_vdpa.patch +Patch0707: vdpa-Add-vhost_vdpa_net_load_mq.patch +Patch0708: vdpa-validate-MQ-CVQ-commands.patch +Patch0709: virtio-net-Update-virtio-net-curr_queue_pairs-in-vdp.patch +Patch0710: vdpa-Allow-MQ-feature-in-SVQ.patch +Patch0711: hw-virtio-add-some-vhost-user-trace-events.patch +Patch0712: vdpa-Delete-duplicated-vdpa_feature_bits-entry.patch +Patch0713: vdpa-Remove-shadow-CVQ-command-check.patch +Patch0714: vhost-vdpa-allow-passing-opened-vhostfd-to-vhost-vdp.patch +Patch0715: net-vhost-vdpa.c-Fix-clang-compilation-failure.patch +Patch0716: vhost-vdpa-fix-assert-virtio_net_get_subqueue-nc-asy.patch +Patch0717: vhost-enable-vrings-in-vhost_dev_start-for-vhost-use.patch +Patch0718: vdpa-use-v-shadow_vqs_enabled-in-vhost_vdpa_svqs_sta.patch +Patch0719: vhost-set-SVQ-device-call-handler-at-SVQ-start.patch +Patch0720: vhost-allocate-SVQ-device-file-descriptors-at-device.patch +Patch0721: vdpa-add-vhost_vdpa_net_valid_svq_features.patch +Patch0722: vdpa-request-iova_range-only-once.patch +Patch0723: vdpa-move-SVQ-vring-features-check-to-net.patch +Patch0724: vdpa-allocate-SVQ-array-unconditionally.patch +Patch0725: vdpa-add-asid-parameter-to-vhost_vdpa_dma_map-unmap.patch +Patch0726: vdpa-store-x-svq-parameter-in-VhostVDPAState.patch +Patch0727: vdpa-add-shadow_data-to-vhost_vdpa.patch +Patch0728: vdpa-always-start-CVQ-in-SVQ-mode-if-possible.patch +Patch0729: hw-virtio-vhost-Fix-typo-in-comment.patch +Patch0730: hw-virtio-gracefully-handle-unset-vhost_dev-vdev.patch +Patch0731: vhost-fix-vq-dirty-bitmap-syncing-when-vIOMMU-is-ena.patch +Patch0732: vdpa-handle-VIRTIO_NET_CTRL_ANNOUNCE-in-vhost_vdpa_n.patch +Patch0733: vdpa-do-not-handle-VIRTIO_NET_F_GUEST_ANNOUNCE-in-vh.patch +Patch0734: virtio-introduce-macro-VIRTIO_CONFIG_IRQ_IDX.patch +Patch0735: virtio-pci-decouple-notifier-from-interrupt-process-new.patch +Patch0736: virtio-pci-decouple-the-single-vector-from-the-inter-new.patch +Patch0737: vhost-introduce-new-VhostOps-vhost_set_config_call-new.patch +Patch0738: vhost-vdpa-add-support-for-config-interrupt-new.patch +Patch0739: virtio-add-support-for-configure-interrupt-new.patch +Patch0740: vhost-add-support-for-configure-interrupt-new.patch +Patch0741: virtio-net-add-support-for-configure-interrupt-new.patch +Patch0742: virtio-mmio-add-support-for-configure-interrupt-new.patch +Patch0743: virtio-pci-add-support-for-configure-interrupt-new.patch +Patch0744: vdpa-dev-get-iova-range-explicitly.patch +Patch0745: vdpa-harden-the-error-path-if-get_iova_range-failed.patch +Patch0746: vdpa-commit-all-host-notifier-MRs-in-a-single-MR-tra.patch +Patch0747: virtio-crypto-verify-src-dst-buffer-length-for-sym-request.patch +Patch0748: vhost-Always-store-new-kick-fd-on-vhost_svq_set_svq_.patch +Patch0749: vhost-move-iova_tree-set-to-vhost_svq_start.patch +Patch0750: vhost-fix-possible-wrap-in-SVQ-descriptor-ring.patch +Patch0751: vhost-Fix-false-positive-out-of-bounds.patch +Patch0752: hw-virtio-fix-vhost_user_read-tracepoint.patch +Patch0753: vdpa-Fix-possible-use-after-free-for-VirtQueueElemen.patch +Patch0754: vdpa-fix-not-using-CVQ-buffer-in-case-of-error.patch +Patch0755: vdpa-Return-EIO-if-device-ack-is-VIRTIO_NET_ERR-in-_.patch +Patch0756: vdpa-Return-EIO-if-device-ack-is-VIRTIO_NET_ERR-in-_-new.patch +Patch0757: vdpa-net-block-migration-if-the-device-has-CVQ.patch +Patch0758: vdpa-do-not-block-migration-if-device-has-cvq-and-x-.patch +Patch0759: vdpa-fix-VHOST_BACKEND_F_IOTLB_ASID-flag-check.patch +Patch0760: virtio-net-clear-guest_announce-feature-if-no-cvq-ba.patch +Patch0761: hw-virtio-fix-typo-in-VIRTIO_CONFIG_IRQ_IDX-comments.patch +Patch0762: virtio-i2c-Check-notifier-helpers-for-VIRTIO_CONFIG_.patch +Patch0763: vhost-fix-the-fd-leak.patch +Patch0764: vhost-release-virtqueue-objects-in-error-path.patch +Patch0765: vdpa-stop-all-svq-on-device-deletion.patch +Patch0766: net-Fix-a-misleading-error-message.patch +Patch0767: qsd-Unlink-absolute-PID-file-path.patch +Patch0768: libvhost-user-Fix-VHOST_USER_ADD_MEM_REG-reply.patch +Patch0769: io_uring-fix-short-read-slow-path.patch +Patch0770: libvhost-user-Fix-VHOST_USER_GET_MAX_MEM_SLOTS-reply.patch +Patch0771: tests-qtest-check-the-return-value.patch +Patch0772: hw-net-cadence_gem.c-spelling-fixes-Octects.patch +Patch0773: hw-arm-fsl-imx-Do-not-ignore-Error-argument.patch BuildRequires: flex BuildRequires: gcc @@ -1172,6 +1358,194 @@ getent passwd qemu >/dev/null || \ %endif %changelog +* Tue Nov 28 2023 - 10:6.2.0-84 +- hw/arm/fsl-imx: Do not ignore Error argument +- hw/net/cadence_gem.c: spelling fixes: Octects +- tests/qtest: check the return value +- libvhost-user: Fix VHOST_USER_GET_MAX_MEM_SLOTS reply mainline inclusion commit 69a5daec06f423843ce1bb9be5fb049314996f78 category: bugfix +- io_uring: fix short read slow path mainline inclusion commit c06fc7ce147e57ab493bad9263f1601b8298484b category: bugfix +- libvhost-user: Fix VHOST_USER_ADD_MEM_REG reply mainline inclusion commit 7f27d20ded2f480f3e66d03f90ea71507b834276 category: bugfix +- qsd: Unlink absolute PID file path mainline inclusion commit 9d8f8233b9fa525a7e37350fbc18877051128c5d category: bugfix +- net: Fix a misleading error message +- vdpa: stop all svq on device deletion +- vhost: release virtqueue objects in error path +- vhost: fix the fd leak +- virtio: i2c: Check notifier helpers for VIRTIO_CONFIG_IRQ_IDX +- hw/virtio: fix typo in VIRTIO_CONFIG_IRQ_IDX comments +- virtio-net: clear guest_announce feature if no cvq backend +- vdpa: fix VHOST_BACKEND_F_IOTLB_ASID flag check +- vdpa: do not block migration if device has cvq and x-svq=on +- vdpa net: block migration if the device has CVQ +- vdpa: Return -EIO if device ack is VIRTIO_NET_ERR in _load_mq() +- vdpa: Return -EIO if device ack is VIRTIO_NET_ERR in _load_mac() +- vdpa: fix not using CVQ buffer in case of error +- vdpa: Fix possible use-after-free for VirtQueueElement +- hw/virtio: fix vhost_user_read tracepoint +- vhost: Fix false positive out-of-bounds +- vhost: fix possible wrap in SVQ descriptor ring +- vhost: move iova_tree set to vhost_svq_start +- vhost: Always store new kick fd on vhost_svq_set_svq_kick_fd +- virtio-crypto: verify src&dst buffer length for sym request +- vdpa: commit all host notifier MRs in a single MR transaction +- vdpa: harden the error path if get_iova_range failed +- vdpa-dev: get iova range explicitly +- virtio-pci: add support for configure interrupt +- virtio-mmio: add support for configure interrupt +- virtio-net: add support for configure interrupt +- vhost: add support for configure interrupt +- virtio: add support for configure interrupt +- vhost-vdpa: add support for config interrupt +- vhost: introduce new VhostOps vhost_set_config_call +- virtio-pci: decouple the single vector from the interrupt process +- virtio-pci: decouple notifier from interrupt process +- virtio: introduce macro VIRTIO_CONFIG_IRQ_IDX +- vdpa: do not handle VIRTIO_NET_F_GUEST_ANNOUNCE in vhost-vdpa +- vdpa: handle VIRTIO_NET_CTRL_ANNOUNCE in vhost_vdpa_net_handle_ctrl_avail +- vhost: fix vq dirty bitmap syncing when vIOMMU is enabled +- hw/virtio: gracefully handle unset vhost_dev vdev +- hw/virtio/vhost: Fix typo in comment. +- vdpa: always start CVQ in SVQ mode if possible +- vdpa: add shadow_data to vhost_vdpa +- vdpa: store x-svq parameter in VhostVDPAState +- vdpa: add asid parameter to vhost_vdpa_dma_map/unmap +- vdpa: allocate SVQ array unconditionally +- vdpa: move SVQ vring features check to net/ +- vdpa: request iova_range only once +- vdpa: add vhost_vdpa_net_valid_svq_features +- vhost: allocate SVQ device file descriptors at device start +- vhost: set SVQ device call handler at SVQ start +- vdpa: use v->shadow_vqs_enabled in vhost_vdpa_svqs_start & stop +- vhost: enable vrings in vhost_dev_start() for vhost-user devices +- vhost-vdpa: fix assert !virtio_net_get_subqueue(nc)->async_tx.elem in virtio_net_reset +- net/vhost-vdpa.c: Fix clang compilation failure +- vhost-vdpa: allow passing opened vhostfd to vhost-vdpa +- vdpa: Remove shadow CVQ command check +- vdpa: Delete duplicated vdpa_feature_bits entry +- hw/virtio: add some vhost-user trace events +- vdpa: Allow MQ feature in SVQ +- virtio-net: Update virtio-net curr_queue_pairs in vdpa backends +- vdpa: validate MQ CVQ commands +- vdpa: Add vhost_vdpa_net_load_mq +- vdpa: extract vhost_vdpa_net_load_mac from vhost_vdpa_net_load +- vdpa: Make VhostVDPAState cvq_cmd_in_buffer control ack type +- vdpa: Delete CVQ migration blocker +- vdpa: Add virtio-net mac address via CVQ at start +- vhost_net: add NetClientState->load() callback +- vdpa: extract vhost_vdpa_net_cvq_add from vhost_vdpa_net_handle_ctrl_avail +- vdpa: Move command buffers map to start of net device +- vdpa: add net_vhost_vdpa_cvq_info NetClientInfo +- vhost_net: Add NetClientInfo stop callback +- vhost_net: Add NetClientInfo start callback +- vdpa: Use ring hwaddr at vhost_vdpa_svq_unmap_ring +- vdpa: Make SVQ vring unmapping return void +- vdpa: Remove SVQ vring from iova_tree at shutdown +- util: accept iova_tree_remove_parameter by value +- vdpa: do not save failed dma maps in SVQ iova tree +- vdpa: Skip the maps not in the iova tree +- vdpa: Fix file descriptor leak on get features error +- vdpa: Fix memory listener deletions of iova tree +- vhost: Get vring base from vq, not svq +- vdpa: Add x-svq to NetdevVhostVDPAOptions +- vdpa: Add device migration blocker +- vdpa: Extract get features part from vhost_vdpa_get_max_queue_pairs +- vdpa: Buffer CVQ support on shadow virtqueue +- vdpa: manual forward CVQ buffers +- vdpa: Export vhost_vdpa_dma_map and unmap calls +- vhost: Add svq avail_handler callback +- vhost: add vhost_svq_poll +- vhost: Expose vhost_svq_add +- vhost: add vhost_svq_push_elem +- vhost: Track number of descs in SVQDescState +- vhost: Add SVQDescState +- vhost: Decouple vhost_svq_add from VirtQueueElement +- vhost: Check for queue full at vhost_svq_add +- vhost: Move vhost_svq_kick call to vhost_svq_add +- vhost: Reorder vhost_svq_kick +- vdpa: Avoid compiler to squash reads to used idx +- virtio-net: Expose ctrl virtqueue logic +- virtio-net: Expose MAC_TABLE_ENTRIES +- vhost: move descriptor translation to vhost_svq_vring_write_descs +- util: Return void on iova_tree_remove +- virtio-net: don't handle mq request in userspace handler for vhost-vdpa +- vhost-vdpa: change name and polarity for vhost_vdpa_one_time_request() +- vhost-vdpa: backend feature should set only once +- vhost-vdpa: fix improper cleanup in net_init_vhost_vdpa +- virtio-net: align ctrl_vq index for non-mq guest for vhost_vdpa +- virtio: add vhost support for virtio devices +- include/hw: start documenting the vhost API +- hw/virtio: add vhost_user_[read|write] trace points +- vhost: Fix element in vhost_svq_add failure +- vdpa: Fix index calculus at vhost_vdpa_svqs_start +- vdpa: Fix bad index calculus at vhost_vdpa_get_vring_base +- vhost: Fix device's used descriptor dequeue +- vhost: Track descriptor chain in private at SVQ +- vdpa: Add missing tracing to batch mapping functions +- vhost-vdpa: fix typo in a comment +- virtio: fix --enable-vhost-user build on non-Linux +- vdpa: Expose VHOST_F_LOG_ALL on SVQ +- vdpa: Never set log_base addr if SVQ is enabled +- vdpa: Adapt vhost_vdpa_get_vring_base to SVQ +- vdpa: Add custom IOTLB translations to SVQ +- vhost: Add VhostIOVATree +- util: add iova_tree_find_iova +- util: Add iova_tree_alloc_map +- vhost: Shadow virtqueue buffers forwarding +- vdpa: adapt vhost_ops callbacks to svq +- virtio: Add vhost_svq_get_vring_addr +- vhost: Add vhost_svq_valid_features to shadow vq +- vhost: Add Shadow VirtQueue call forwarding capabilities +- vhost: Add Shadow VirtQueue kick forwarding capabilities +- vhost: Add VhostShadowVirtqueue +- vdpa: Make ncs autofree +- Revert "virtio: introduce macro IRTIO_CONFIG_IRQ_IDX" +- Revert "virtio-pci: decouple notifier from interrupt process" +- Revert "virtio-pci: decouple the single vector from the interrupt process" +- Revert "vhost-vdpa: add support for config interrupt" +- Revert "virtio: add support for configure interrupt" +- Revert "vhost: add support for configure interrupt" +- Revert "virtio-net: add support for configure interrupt" +- Revert "virtio-mmio: add support for configure interrupt" +- Revert "virtio-pci: add support for configure interrupt" +- Revert "vhost: introduce new VhostOps vhost_set_config_call" +- virtio: signal after wrapping packed used_idx +- target/i386: Adjust feature level according to FEAT_7_1_EDX +- target/i386: Add new CPU model GraniteRapids +- target/i386: Add support for PREFETCHIT0/1 in CPUID enumeration +- target/i386: Add support for AVX-NE-CONVERT in CPUID enumeration +- target/i386: Add support for AVX-VNNI-INT8 in CPUID enumeration +- target/i386: Add support for AVX-IFMA in CPUID enumeration +- target/i386: Add support for AMX-FP16 in CPUID enumeration +- target/i386: Add support for CMPCCXADD in CPUID enumeration +- tracetool: avoid invalid escape in Python string +- hw/pvrdma: Protect against buggy or malicious guest driver +- vga: avoid crash if no default vga card mainline inclusion commit 6985d8ede92494f3b791de01e8ee9306eb6d5e4a category: bugfix +- qom/object: Remove circular include dependency mainline inclusion commit 5bba9bcfbb42e7c016626420e148a1bf1b080835 category: bugfix +- artist: set memory region owners for buffers to the artist device mainline inclusion commit 39fbaeca096a9bf6cbe2af88572c1cb2aa62aa8c category: bugfix +- virtio-iommu: Fix the partial copy of probe request mainline inclusion commit 45461aace83d961e933b27519b81d17b4c690514 category: bugfix +- e1000: set RX descriptor status in a separate operation mainline inclusion commit 034d00d4858161e1d4cff82d8d230bce874a04d3 category: bugfix +- vhost: introduce new VhostOps vhost_set_config_call +- vhost: stick to -errno error return convention +- vhost-user: stick to -errno error return convention +- vhost-vdpa: stick to -errno error return convention +- virtio-pci: add support for configure interrupt +- virtio-mmio: add support for configure interrupt +- virtio-net: add support for configure interrupt +- vhost: add support for configure interrupt +- virtio: add support for configure interrupt +- vhost-vdpa: add support for config interrupt +- virtio-pci: decouple the single vector from the interrupt process +- virtio-pci: decouple notifier from interrupt process +- virtio: introduce macro IRTIO_CONFIG_IRQ_IDX +- pci: Fix the update of interrupt disable bit in PCI_COMMAND register +- hw/timer/npcm7xx_timer: Prevent timer from counting down past zero +- tpm_crb: mark command buffer as dirty on request completion mainline inclusion commit e37a0ef4605e5d2041785ff3fc89ca6021faf7a0 category: bugfix +- pci: fix overflow in snprintf string formatting mainline inclusion commit 36f18c6989a3d1ff1d7a0e50b0868ef3958299b4 category: bugfix +- hw/usb/hcd-ehci: fix writeback order mainline inclusion commit f471e8b060798f26a7fc339c6152f82f22a7b33d category: bugfix +- qemu-timer: Skip empty timer lists before locking in qemu_clock_deadline_ns_all mainline inclusion commit 3f42906c9ab2c777a895b48b87b8107167e4a275 category: bugfix +- semihosting/config: Merge --semihosting-config option groups mainline inclusion commit 90c072e063737e9e8f431489bbd334452f89056e category: bugfix +- semihosting: fix memleak at semihosting_arg_fallback +- target/i386: Export GDS_NO bit to guests + * Mon Oct 30 2023 - 10:6.2.0-83 - hw/virtio/virtio-pmem: Replace impossible check by assertion - tests: Fix printf format string in acpi-utils.c diff --git a/qom-object-Remove-circular-include-dependency.patch b/qom-object-Remove-circular-include-dependency.patch new file mode 100644 index 00000000..f527a3b0 --- /dev/null +++ b/qom-object-Remove-circular-include-dependency.patch @@ -0,0 +1,41 @@ +From e4393667e45bdcf04150ada3840a6d87e3188d36 Mon Sep 17 00:00:00 2001 +From: tangbinzy +Date: Fri, 17 Nov 2023 09:13:07 +0000 +Subject: [PATCH] qom/object: Remove circular include dependency mainline + inclusion commit 5bba9bcfbb42e7c016626420e148a1bf1b080835 category: bugfix +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +--------------------------------------------------------------- + +"qom/object.h" doesn't need to include itself. + +Fixes: db1015e92e04 ("Move QOM typedefs and add missing includes") +Signed-off-by: Philippe Mathieu-Daudé +Reviewed-by: Damien Hedde +Reviewed-by: Peter Maydell +Reviewed-by: Markus Armbruster +Message-Id: <20220509084659.52076-1-philippe.mathieu.daude@gmail.com> +Signed-off-by: Laurent Vivier + +Signed-off-by: tangbinzy +--- + include/qom/object.h | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/include/qom/object.h b/include/qom/object.h +index fae096f51c..f658e1e0a0 100644 +--- a/include/qom/object.h ++++ b/include/qom/object.h +@@ -16,7 +16,6 @@ + + #include "qapi/qapi-builtin-types.h" + #include "qemu/module.h" +-#include "qom/object.h" + + struct TypeImpl; + typedef struct TypeImpl *Type; +-- +2.27.0 + diff --git a/qsd-Unlink-absolute-PID-file-path.patch b/qsd-Unlink-absolute-PID-file-path.patch new file mode 100644 index 00000000..7c5138ad --- /dev/null +++ b/qsd-Unlink-absolute-PID-file-path.patch @@ -0,0 +1,81 @@ +From 43668bdb7ebaa64536277d4b5b47875e58a3452a Mon Sep 17 00:00:00 2001 +From: tangbinzy +Date: Tue, 21 Nov 2023 07:00:39 +0000 +Subject: [PATCH] qsd: Unlink absolute PID file path mainline inclusion commit + 9d8f8233b9fa525a7e37350fbc18877051128c5d category: bugfix +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +--------------------------------------------------------------- + +After writing the PID file, we register an atexit() handler to unlink it +when the process terminates. However, if the process has changed its +working directory in the meantime (e.g. in os_setup_post() when +daemonizing), this will not work when the PID file path was relative. +Therefore, pass the absolute path (created with realpath()) to the +unlink() call in the atexit() handler. + +(realpath() needs a path pointing to an existing file, so we cannot use +it before qemu_write_pidfile().) + +Reproducer: +$ cd /tmp +$ qemu-storage-daemon --daemonize --pidfile qsd.pid +$ file qsd.pid +qsd.pid: ASCII text +$ kill $(cat qsd.pid) +$ file qsd.pid +qsd.pid: ASCII text + +(qsd.pid should be gone after the process has terminated.) + +Buglink: https://bugzilla.redhat.com/show_bug.cgi?id=2092322 +Signed-off-by: Hanna Reitz +Message-Id: <20220609122701.17172-2-hreitz@redhat.com> +Reviewed-by: Daniel P. Berrangé + +Signed-off-by: tangbinzy +--- + storage-daemon/qemu-storage-daemon.c | 11 ++++++++++- + 1 file changed, 10 insertions(+), 1 deletion(-) + +diff --git a/storage-daemon/qemu-storage-daemon.c b/storage-daemon/qemu-storage-daemon.c +index 52cf17e8ac..f3d8c4ca11 100644 +--- a/storage-daemon/qemu-storage-daemon.c ++++ b/storage-daemon/qemu-storage-daemon.c +@@ -60,6 +60,7 @@ + #include "trace/control.h" + + static const char *pid_file; ++static char *pid_file_realpath; + static volatile bool exit_requested = false; + + void qemu_system_killed(int signal, pid_t pid) +@@ -292,7 +293,7 @@ static void process_options(int argc, char *argv[]) + + static void pid_file_cleanup(void) + { +- unlink(pid_file); ++ unlink(pid_file_realpath); + } + + static void pid_file_init(void) +@@ -308,6 +309,14 @@ static void pid_file_init(void) + exit(EXIT_FAILURE); + } + ++ pid_file_realpath = g_malloc(PATH_MAX); ++ if (!realpath(pid_file, pid_file_realpath)) { ++ error_report("cannot resolve PID file path: %s: %s", ++ pid_file, strerror(errno)); ++ unlink(pid_file); ++ exit(EXIT_FAILURE); ++ } ++ + atexit(pid_file_cleanup); + } + +-- +2.27.0 + diff --git a/semihosting-config-Merge-semihosting-config-option-g.patch b/semihosting-config-Merge-semihosting-config-option-g.patch new file mode 100644 index 00000000..c7c9e59b --- /dev/null +++ b/semihosting-config-Merge-semihosting-config-option-g.patch @@ -0,0 +1,54 @@ +From ff7918646e3c696d13732fb22f032d7d78c34fe1 Mon Sep 17 00:00:00 2001 +From: tangbinzy +Date: Mon, 6 Nov 2023 08:15:13 +0000 +Subject: [PATCH] semihosting/config: Merge --semihosting-config option groups + mainline inclusion commit 90c072e063737e9e8f431489bbd334452f89056e category: + bugfix + +--------------------------------------------------------------- + +Currently we mishandle the --semihosting-config option if the +user specifies it on the command line more than once. For +example with: + --semihosting-config target=gdb --semihosting-config arg=foo,arg=bar + +the function qemu_semihosting_config_options() is called twice, once +for each argument. But that function expects to be called only once, +and it always unconditionally sets the semihosting.enabled, +semihost_chardev and semihosting.target variables. This means that +if any of those options were set anywhere except the last +--semihosting-config option on the command line, those settings are +ignored. In the example above, 'target=gdb' in the first option is +overridden by an implied default 'target=auto' in the second. + +The QemuOptsList machinery has a flag for handling this kind of +"option group is setting global state": by setting + .merge_lists = true; +we make the machinery merge all the --semihosting-config arguments +the user passes into a single set of options and call our +qemu_semihosting_config_options() just once. + +Signed-off-by: Peter Maydell +Reviewed-by: Luc Michel +Message-id: 20220526190053.521505-3-peter.maydell@linaro.org + +Signed-off-by: tangbinzy +--- + semihosting/config.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/semihosting/config.c b/semihosting/config.c +index 137171b717..ba3e310a61 100644 +--- a/semihosting/config.c ++++ b/semihosting/config.c +@@ -27,6 +27,7 @@ + + QemuOptsList qemu_semihosting_config_opts = { + .name = "semihosting-config", ++ .merge_lists = true, + .implied_opt_name = "enable", + .head = QTAILQ_HEAD_INITIALIZER(qemu_semihosting_config_opts.head), + .desc = { +-- +2.27.0 + diff --git a/semihosting-fix-memleak-at-semihosting_arg_fallback.patch b/semihosting-fix-memleak-at-semihosting_arg_fallback.patch new file mode 100644 index 00000000..ccee1a5b --- /dev/null +++ b/semihosting-fix-memleak-at-semihosting_arg_fallback.patch @@ -0,0 +1,47 @@ +From 47a24e233e335025ed37ab0ba4a4e728719a2ad3 Mon Sep 17 00:00:00 2001 +From: qihao +Date: Mon, 6 Nov 2023 18:14:06 +0800 +Subject: [PATCH] semihosting: fix memleak at semihosting_arg_fallback +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +cheery-pick from 2eb71a0c20a6a77be128a76c1ef8fb5dc7028a8b + +We duplicate "cmd" as strtok may modify its argument, but we forgot +to free it later. Furthermore, add_semihosting_arg doesn't take +responsibility for this memory either (it strdup's the argument). + +Signed-off-by: Matheus Tavares Bernardino +Reviewed-by: Philippe Mathieu-Daudé +Message-Id: <03d81c56bfc3d08224e4106efca5949d8894cfa5.1697801632.git.quic_mathbern@quicinc.com> +Reviewed-by: Richard Henderson +Signed-off-by: Alex Bennée +Message-Id: <20231029145033.592566-18-alex.bennee@linaro.org> +Signed-off-by: qihao_yewu +--- + semihosting/config.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/semihosting/config.c b/semihosting/config.c +index 137171b717..303338f647 100644 +--- a/semihosting/config.c ++++ b/semihosting/config.c +@@ -109,12 +109,13 @@ static int add_semihosting_arg(void *opaque, + void semihosting_arg_fallback(const char *file, const char *cmd) + { + char *cmd_token; ++ g_autofree char *cmd_dup = g_strdup(cmd); + + /* argv[0] */ + add_semihosting_arg(&semihosting, "arg", file, NULL); + + /* split -append and initialize argv[1..n] */ +- cmd_token = strtok(g_strdup(cmd), " "); ++ cmd_token = strtok(cmd_dup, " "); + while (cmd_token) { + add_semihosting_arg(&semihosting, "arg", cmd_token, NULL); + cmd_token = strtok(NULL, " "); +-- +2.27.0 + diff --git a/target-i386-Add-new-CPU-model-GraniteRapids.patch b/target-i386-Add-new-CPU-model-GraniteRapids.patch new file mode 100644 index 00000000..24672e94 --- /dev/null +++ b/target-i386-Add-new-CPU-model-GraniteRapids.patch @@ -0,0 +1,183 @@ +From 7ebcbfb9ac1d53ea46bfd86fa7f0a90a4012412e Mon Sep 17 00:00:00 2001 +From: Tao Su +Date: Thu, 6 Jul 2023 13:49:49 +0800 +Subject: [PATCH] target/i386: Add new CPU model GraniteRapids + +commit 6d5e9694ef374159072984c0958c3eaab6dd1d52 upstream. + +The GraniteRapids CPU model mainly adds the following new features +based on SapphireRapids: +- PREFETCHITI CPUID.(EAX=7,ECX=1):EDX[bit 14] +- AMX-FP16 CPUID.(EAX=7,ECX=1):EAX[bit 21] + +And adds the following security fix for corresponding vulnerabilities: +- MCDT_NO CPUID.(EAX=7,ECX=2):EDX[bit 5] +- SBDR_SSDP_NO MSR_IA32_ARCH_CAPABILITIES[bit 13] +- FBSDP_NO MSR_IA32_ARCH_CAPABILITIES[bit 14] +- PSDP_NO MSR_IA32_ARCH_CAPABILITIES[bit 15] +- PBRSB_NO MSR_IA32_ARCH_CAPABILITIES[bit 24] + +Intel-SIG: commit 6d5e9694ef37 target/i386: Add new CPU model GraniteRapids. +Backport GNR and SRF ISA into QEMU-6.2 + +Signed-off-by: Tao Su +Tested-by: Xuelian Guo +Reviewed-by: Xiaoyao Li +Message-ID: <20230706054949.66556-7-tao1.su@linux.intel.com> +Signed-off-by: Paolo Bonzini +[ Quanxian Wang: amend commit log ] +Signed-off-by: Quanxian Wang +--- + target/i386/cpu.c | 136 ++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 136 insertions(+) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index ee243693e3..efe0c2b46c 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -3707,6 +3707,142 @@ static const X86CPUDefinition builtin_x86_defs[] = { + { /* end of list */ } + } + }, ++ { ++ .name = "GraniteRapids", ++ .level = 0x20, ++ .vendor = CPUID_VENDOR_INTEL, ++ .family = 6, ++ .model = 173, ++ .stepping = 0, ++ /* ++ * please keep the ascending order so that we can have a clear view of ++ * bit position of each feature. ++ */ ++ .features[FEAT_1_EDX] = ++ CPUID_FP87 | CPUID_VME | CPUID_DE | CPUID_PSE | CPUID_TSC | ++ CPUID_MSR | CPUID_PAE | CPUID_MCE | CPUID_CX8 | CPUID_APIC | ++ CPUID_SEP | CPUID_MTRR | CPUID_PGE | CPUID_MCA | CPUID_CMOV | ++ CPUID_PAT | CPUID_PSE36 | CPUID_CLFLUSH | CPUID_MMX | CPUID_FXSR | ++ CPUID_SSE | CPUID_SSE2, ++ .features[FEAT_1_ECX] = ++ CPUID_EXT_SSE3 | CPUID_EXT_PCLMULQDQ | CPUID_EXT_SSSE3 | ++ CPUID_EXT_FMA | CPUID_EXT_CX16 | CPUID_EXT_PCID | CPUID_EXT_SSE41 | ++ CPUID_EXT_SSE42 | CPUID_EXT_X2APIC | CPUID_EXT_MOVBE | ++ CPUID_EXT_POPCNT | CPUID_EXT_TSC_DEADLINE_TIMER | CPUID_EXT_AES | ++ CPUID_EXT_XSAVE | CPUID_EXT_AVX | CPUID_EXT_F16C | CPUID_EXT_RDRAND, ++ .features[FEAT_8000_0001_EDX] = ++ CPUID_EXT2_SYSCALL | CPUID_EXT2_NX | CPUID_EXT2_PDPE1GB | ++ CPUID_EXT2_RDTSCP | CPUID_EXT2_LM, ++ .features[FEAT_8000_0001_ECX] = ++ CPUID_EXT3_LAHF_LM | CPUID_EXT3_ABM | CPUID_EXT3_3DNOWPREFETCH, ++ .features[FEAT_8000_0008_EBX] = ++ CPUID_8000_0008_EBX_WBNOINVD, ++ .features[FEAT_7_0_EBX] = ++ CPUID_7_0_EBX_FSGSBASE | CPUID_7_0_EBX_BMI1 | CPUID_7_0_EBX_HLE | ++ CPUID_7_0_EBX_AVX2 | CPUID_7_0_EBX_SMEP | CPUID_7_0_EBX_BMI2 | ++ CPUID_7_0_EBX_ERMS | CPUID_7_0_EBX_INVPCID | CPUID_7_0_EBX_RTM | ++ CPUID_7_0_EBX_AVX512F | CPUID_7_0_EBX_AVX512DQ | ++ CPUID_7_0_EBX_RDSEED | CPUID_7_0_EBX_ADX | CPUID_7_0_EBX_SMAP | ++ CPUID_7_0_EBX_AVX512IFMA | CPUID_7_0_EBX_CLFLUSHOPT | ++ CPUID_7_0_EBX_CLWB | CPUID_7_0_EBX_AVX512CD | CPUID_7_0_EBX_SHA_NI | ++ CPUID_7_0_EBX_AVX512BW | CPUID_7_0_EBX_AVX512VL, ++ .features[FEAT_7_0_ECX] = ++ CPUID_7_0_ECX_AVX512_VBMI | CPUID_7_0_ECX_UMIP | CPUID_7_0_ECX_PKU | ++ CPUID_7_0_ECX_AVX512_VBMI2 | CPUID_7_0_ECX_GFNI | ++ CPUID_7_0_ECX_VAES | CPUID_7_0_ECX_VPCLMULQDQ | ++ CPUID_7_0_ECX_AVX512VNNI | CPUID_7_0_ECX_AVX512BITALG | ++ CPUID_7_0_ECX_AVX512_VPOPCNTDQ | CPUID_7_0_ECX_LA57 | ++ CPUID_7_0_ECX_RDPID | CPUID_7_0_ECX_BUS_LOCK_DETECT, ++ .features[FEAT_7_0_EDX] = ++ CPUID_7_0_EDX_FSRM | CPUID_7_0_EDX_SERIALIZE | ++ CPUID_7_0_EDX_TSX_LDTRK | CPUID_7_0_EDX_AMX_BF16 | ++ CPUID_7_0_EDX_AVX512_FP16 | CPUID_7_0_EDX_AMX_TILE | ++ CPUID_7_0_EDX_AMX_INT8 | CPUID_7_0_EDX_SPEC_CTRL | ++ CPUID_7_0_EDX_ARCH_CAPABILITIES | CPUID_7_0_EDX_SPEC_CTRL_SSBD, ++ .features[FEAT_ARCH_CAPABILITIES] = ++ MSR_ARCH_CAP_RDCL_NO | MSR_ARCH_CAP_IBRS_ALL | ++ MSR_ARCH_CAP_SKIP_L1DFL_VMENTRY | MSR_ARCH_CAP_MDS_NO | ++ MSR_ARCH_CAP_PSCHANGE_MC_NO | MSR_ARCH_CAP_TAA_NO | ++ MSR_ARCH_CAP_SBDR_SSDP_NO | MSR_ARCH_CAP_FBSDP_NO | ++ MSR_ARCH_CAP_PSDP_NO | MSR_ARCH_CAP_PBRSB_NO, ++ .features[FEAT_XSAVE] = ++ CPUID_XSAVE_XSAVEOPT | CPUID_XSAVE_XSAVEC | ++ CPUID_XSAVE_XGETBV1 | CPUID_XSAVE_XSAVES | CPUID_D_1_EAX_XFD, ++ .features[FEAT_6_EAX] = ++ CPUID_6_EAX_ARAT, ++ .features[FEAT_7_1_EAX] = ++ CPUID_7_1_EAX_AVX_VNNI | CPUID_7_1_EAX_AVX512_BF16 | ++ CPUID_7_1_EAX_FZRM | CPUID_7_1_EAX_FSRS | CPUID_7_1_EAX_FSRC | ++ CPUID_7_1_EAX_AMX_FP16, ++ .features[FEAT_7_1_EDX] = ++ CPUID_7_1_EDX_PREFETCHITI, ++ .features[FEAT_7_2_EDX] = ++ CPUID_7_2_EDX_MCDT_NO, ++ .features[FEAT_VMX_BASIC] = ++ MSR_VMX_BASIC_INS_OUTS | MSR_VMX_BASIC_TRUE_CTLS, ++ .features[FEAT_VMX_ENTRY_CTLS] = ++ VMX_VM_ENTRY_LOAD_DEBUG_CONTROLS | VMX_VM_ENTRY_IA32E_MODE | ++ VMX_VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL | ++ VMX_VM_ENTRY_LOAD_IA32_PAT | VMX_VM_ENTRY_LOAD_IA32_EFER, ++ .features[FEAT_VMX_EPT_VPID_CAPS] = ++ MSR_VMX_EPT_EXECONLY | ++ MSR_VMX_EPT_PAGE_WALK_LENGTH_4 | MSR_VMX_EPT_PAGE_WALK_LENGTH_5 | ++ MSR_VMX_EPT_WB | MSR_VMX_EPT_2MB | MSR_VMX_EPT_1GB | ++ MSR_VMX_EPT_INVEPT | MSR_VMX_EPT_AD_BITS | ++ MSR_VMX_EPT_INVEPT_SINGLE_CONTEXT | MSR_VMX_EPT_INVEPT_ALL_CONTEXT | ++ MSR_VMX_EPT_INVVPID | MSR_VMX_EPT_INVVPID_SINGLE_ADDR | ++ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT | ++ MSR_VMX_EPT_INVVPID_ALL_CONTEXT | ++ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT_NOGLOBALS, ++ .features[FEAT_VMX_EXIT_CTLS] = ++ VMX_VM_EXIT_SAVE_DEBUG_CONTROLS | ++ VMX_VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL | ++ VMX_VM_EXIT_ACK_INTR_ON_EXIT | VMX_VM_EXIT_SAVE_IA32_PAT | ++ VMX_VM_EXIT_LOAD_IA32_PAT | VMX_VM_EXIT_SAVE_IA32_EFER | ++ VMX_VM_EXIT_LOAD_IA32_EFER | VMX_VM_EXIT_SAVE_VMX_PREEMPTION_TIMER, ++ .features[FEAT_VMX_MISC] = ++ MSR_VMX_MISC_STORE_LMA | MSR_VMX_MISC_ACTIVITY_HLT | ++ MSR_VMX_MISC_VMWRITE_VMEXIT, ++ .features[FEAT_VMX_PINBASED_CTLS] = ++ VMX_PIN_BASED_EXT_INTR_MASK | VMX_PIN_BASED_NMI_EXITING | ++ VMX_PIN_BASED_VIRTUAL_NMIS | VMX_PIN_BASED_VMX_PREEMPTION_TIMER | ++ VMX_PIN_BASED_POSTED_INTR, ++ .features[FEAT_VMX_PROCBASED_CTLS] = ++ VMX_CPU_BASED_VIRTUAL_INTR_PENDING | ++ VMX_CPU_BASED_USE_TSC_OFFSETING | VMX_CPU_BASED_HLT_EXITING | ++ VMX_CPU_BASED_INVLPG_EXITING | VMX_CPU_BASED_MWAIT_EXITING | ++ VMX_CPU_BASED_RDPMC_EXITING | VMX_CPU_BASED_RDTSC_EXITING | ++ VMX_CPU_BASED_CR3_LOAD_EXITING | VMX_CPU_BASED_CR3_STORE_EXITING | ++ VMX_CPU_BASED_CR8_LOAD_EXITING | VMX_CPU_BASED_CR8_STORE_EXITING | ++ VMX_CPU_BASED_TPR_SHADOW | VMX_CPU_BASED_VIRTUAL_NMI_PENDING | ++ VMX_CPU_BASED_MOV_DR_EXITING | VMX_CPU_BASED_UNCOND_IO_EXITING | ++ VMX_CPU_BASED_USE_IO_BITMAPS | VMX_CPU_BASED_MONITOR_TRAP_FLAG | ++ VMX_CPU_BASED_USE_MSR_BITMAPS | VMX_CPU_BASED_MONITOR_EXITING | ++ VMX_CPU_BASED_PAUSE_EXITING | ++ VMX_CPU_BASED_ACTIVATE_SECONDARY_CONTROLS, ++ .features[FEAT_VMX_SECONDARY_CTLS] = ++ VMX_SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES | ++ VMX_SECONDARY_EXEC_ENABLE_EPT | VMX_SECONDARY_EXEC_DESC | ++ VMX_SECONDARY_EXEC_RDTSCP | ++ VMX_SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE | ++ VMX_SECONDARY_EXEC_ENABLE_VPID | VMX_SECONDARY_EXEC_WBINVD_EXITING | ++ VMX_SECONDARY_EXEC_UNRESTRICTED_GUEST | ++ VMX_SECONDARY_EXEC_APIC_REGISTER_VIRT | ++ VMX_SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY | ++ VMX_SECONDARY_EXEC_RDRAND_EXITING | ++ VMX_SECONDARY_EXEC_ENABLE_INVPCID | ++ VMX_SECONDARY_EXEC_ENABLE_VMFUNC | VMX_SECONDARY_EXEC_SHADOW_VMCS | ++ VMX_SECONDARY_EXEC_RDSEED_EXITING | VMX_SECONDARY_EXEC_ENABLE_PML | ++ VMX_SECONDARY_EXEC_XSAVES, ++ .features[FEAT_VMX_VMFUNC] = ++ MSR_VMX_VMFUNC_EPT_SWITCHING, ++ .xlevel = 0x80000008, ++ .model_id = "Intel Xeon Processor (GraniteRapids)", ++ .versions = (X86CPUVersionDefinition[]) { ++ { .version = 1 }, ++ { /* end of list */ }, ++ }, ++ }, + { + .name = "Denverton", + .level = 21, +-- +2.27.0 + diff --git a/target-i386-Add-support-for-AMX-FP16-in-CPUID-enumer.patch b/target-i386-Add-support-for-AMX-FP16-in-CPUID-enumer.patch new file mode 100644 index 00000000..27cdfaf2 --- /dev/null +++ b/target-i386-Add-support-for-AMX-FP16-in-CPUID-enumer.patch @@ -0,0 +1,62 @@ +From c362956eb88558991bee59e43d7db52c8bc7e5f5 Mon Sep 17 00:00:00 2001 +From: Jiaxi Chen +Date: Fri, 3 Mar 2023 14:59:09 +0800 +Subject: [PATCH] target/i386: Add support for AMX-FP16 in CPUID enumeration + +commit 99ed8445ea27742a4df40f51a3a5fbd6f8e76fa5 upstream. + +Latest Intel platform Granite Rapids has introduced a new instruction - +AMX-FP16, which performs dot-products of two FP16 tiles and accumulates +the results into a packed single precision tile. AMX-FP16 adds FP16 +capability and allows a FP16 GPU trained model to run faster without +loss of accuracy or added SW overhead. + +The bit definition: +CPUID.(EAX=7,ECX=1):EAX[bit 21] + +Add CPUID definition for AMX-FP16. + +Intel-SIG: commit 99ed8445ea27 target/i386: Add support for AMX-FP16 in CPUID enumeration. +Backport GNR and SRF ISA into QEMU-6.2 + +Signed-off-by: Jiaxi Chen +Signed-off-by: Tao Su +Reviewed-by: Xiaoyao Li +Message-Id: <20230303065913.1246327-3-tao1.su@linux.intel.com> +Signed-off-by: Paolo Bonzini +[ Quanxian Wang: amend commit log ] +Signed-off-by: Quanxian Wang +--- + target/i386/cpu.c | 2 +- + target/i386/cpu.h | 2 ++ + 2 files changed, 3 insertions(+), 1 deletion(-) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index 47c2d9da80..3fc3b8041a 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -876,7 +876,7 @@ FeatureWordInfo feature_word_info[FEATURE_WORDS] = { + NULL, NULL, "fzrm", "fsrs", + "fsrc", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, +- NULL, NULL, NULL, NULL, ++ NULL, "amx-fp16", NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + }, +diff --git a/target/i386/cpu.h b/target/i386/cpu.h +index 4a7362ee07..c747e68a7a 100644 +--- a/target/i386/cpu.h ++++ b/target/i386/cpu.h +@@ -891,6 +891,8 @@ uint64_t x86_cpu_get_supported_feature_word(FeatureWord w, + #define CPUID_7_1_EAX_FSRS (1U << 11) + /* Fast Short REP CMPS/SCAS */ + #define CPUID_7_1_EAX_FSRC (1U << 12) ++/* Support Tile Computational Operations on FP16 Numbers */ ++#define CPUID_7_1_EAX_AMX_FP16 (1U << 21) + + /* Do not exhibit MXCSR Configuration Dependent Timing (MCDT) behavior */ + #define CPUID_7_2_EDX_MCDT_NO (1U << 5) +-- +2.27.0 + diff --git a/target-i386-Add-support-for-AVX-IFMA-in-CPUID-enumer.patch b/target-i386-Add-support-for-AVX-IFMA-in-CPUID-enumer.patch new file mode 100644 index 00000000..8b99815a --- /dev/null +++ b/target-i386-Add-support-for-AVX-IFMA-in-CPUID-enumer.patch @@ -0,0 +1,60 @@ +From 8fe9899c39d86f9e0baf832744a7cfe19642a3fd Mon Sep 17 00:00:00 2001 +From: Jiaxi Chen +Date: Fri, 3 Mar 2023 14:59:10 +0800 +Subject: [PATCH] target/i386: Add support for AVX-IFMA in CPUID enumeration + +commit a957a88416ecbec51e147cba9fe89b93f6646b3b upstream. + +AVX-IFMA is a new instruction in the latest Intel platform Sierra +Forest. This instruction packed multiplies unsigned 52-bit integers and +adds the low/high 52-bit products to Qword Accumulators. + +The bit definition: +CPUID.(EAX=7,ECX=1):EAX[bit 23] + +Add CPUID definition for AVX-IFMA. + +Intel-SIG: commit a957a88416ec target/i386: Add support for AVX-IFMA in CPUID enumeration. +Backport GNR and SRF ISA into QEMU-6.2 + +Signed-off-by: Jiaxi Chen +Signed-off-by: Tao Su +Reviewed-by: Xiaoyao Li +Message-Id: <20230303065913.1246327-4-tao1.su@linux.intel.com> +Signed-off-by: Paolo Bonzini +[ Quanxian Wang: amend commit log ] +Signed-off-by: Quanxian Wang +--- + target/i386/cpu.c | 2 +- + target/i386/cpu.h | 2 ++ + 2 files changed, 3 insertions(+), 1 deletion(-) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index 3fc3b8041a..b19fb0cf87 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -876,7 +876,7 @@ FeatureWordInfo feature_word_info[FEATURE_WORDS] = { + NULL, NULL, "fzrm", "fsrs", + "fsrc", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, +- NULL, "amx-fp16", NULL, NULL, ++ NULL, "amx-fp16", NULL, "avx-ifma", + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + }, +diff --git a/target/i386/cpu.h b/target/i386/cpu.h +index c747e68a7a..2bcc127fac 100644 +--- a/target/i386/cpu.h ++++ b/target/i386/cpu.h +@@ -893,6 +893,8 @@ uint64_t x86_cpu_get_supported_feature_word(FeatureWord w, + #define CPUID_7_1_EAX_FSRC (1U << 12) + /* Support Tile Computational Operations on FP16 Numbers */ + #define CPUID_7_1_EAX_AMX_FP16 (1U << 21) ++/* Support for VPMADD52[H,L]UQ */ ++#define CPUID_7_1_EAX_AVX_IFMA (1U << 23) + + /* Do not exhibit MXCSR Configuration Dependent Timing (MCDT) behavior */ + #define CPUID_7_2_EDX_MCDT_NO (1U << 5) +-- +2.27.0 + diff --git a/target-i386-Add-support-for-AVX-NE-CONVERT-in-CPUID-.patch b/target-i386-Add-support-for-AVX-NE-CONVERT-in-CPUID-.patch new file mode 100644 index 00000000..0eb1635b --- /dev/null +++ b/target-i386-Add-support-for-AVX-NE-CONVERT-in-CPUID-.patch @@ -0,0 +1,62 @@ +From 165d587b52f7c8459d9a9deca389610f9165b33a Mon Sep 17 00:00:00 2001 +From: Quanxian Wang +Date: Wed, 8 Nov 2023 12:44:56 +0800 +Subject: [PATCH] target/i386: Add support for AVX-NE-CONVERT in CPUID + enumeration + +commit ecd2e6ca037d7bf3673c5478590d686d5cd6135a upstream. + +AVX-NE-CONVERT is a new set of instructions which can convert low +precision floating point like BF16/FP16 to high precision floating point +FP32, as well as convert FP32 elements to BF16. This instruction allows +the platform to have improved AI capabilities and better compatibility. + +The bit definition: +CPUID.(EAX=7,ECX=1):EDX[bit 5] + +Add CPUID definition for AVX-NE-CONVERT. + +Intel-SIG: commit ecd2e6ca037d target/i386: Add support for AVX-NE-CONVERT in CPUID enumeration. +Backport GNR and SRF ISA into QEMU-6.2 + +Signed-off-by: Jiaxi Chen +Signed-off-by: Tao Su +Reviewed-by: Xiaoyao Li +Message-Id: <20230303065913.1246327-6-tao1.su@linux.intel.com> +Signed-off-by: Paolo Bonzini +[ Quanxian Wang: amend commit log ] +Signed-off-by: Quanxian Wang +--- + target/i386/cpu.c | 2 +- + target/i386/cpu.h | 2 ++ + 2 files changed, 3 insertions(+), 1 deletion(-) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index a14284a81b..d36174d689 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -911,7 +911,7 @@ FeatureWordInfo feature_word_info[FEATURE_WORDS] = { + .type = CPUID_FEATURE_WORD, + .feat_names = { + NULL, NULL, NULL, NULL, +- "avx-vnni-int8", NULL, NULL, NULL, ++ "avx-vnni-int8", "avx-ne-convert", NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, +diff --git a/target/i386/cpu.h b/target/i386/cpu.h +index b81d77084c..93c8bd6a13 100644 +--- a/target/i386/cpu.h ++++ b/target/i386/cpu.h +@@ -898,6 +898,8 @@ uint64_t x86_cpu_get_supported_feature_word(FeatureWord w, + #define CPUID_7_1_EAX_AVX_IFMA (1U << 23) + /* Support for VPDPB[SU,UU,SS]D[,S] */ + #define CPUID_7_1_EDX_AVX_VNNI_INT8 (1U << 4) ++/* AVX NE CONVERT Instructions */ ++#define CPUID_7_1_EDX_AVX_NE_CONVERT (1U << 5) + + /* Do not exhibit MXCSR Configuration Dependent Timing (MCDT) behavior */ + #define CPUID_7_2_EDX_MCDT_NO (1U << 5) +-- +2.27.0 + diff --git a/target-i386-Add-support-for-AVX-VNNI-INT8-in-CPUID-e.patch b/target-i386-Add-support-for-AVX-VNNI-INT8-in-CPUID-e.patch new file mode 100644 index 00000000..b6fc1d0e --- /dev/null +++ b/target-i386-Add-support-for-AVX-VNNI-INT8-in-CPUID-e.patch @@ -0,0 +1,110 @@ +From 71b820dc04fbe04342d5a05be3d774c704b682ec Mon Sep 17 00:00:00 2001 +From: Quanxian Wang +Date: Wed, 8 Nov 2023 12:43:11 +0800 +Subject: [PATCH] target/i386: Add support for AVX-VNNI-INT8 in CPUID + enumeration + +commit eaaa197d5b112ea2758b54df58881a2626de3af5 upstream. + +AVX-VNNI-INT8 is a new set of instructions in the latest Intel platform +Sierra Forest, aims for the platform to have superior AI capabilities. +This instruction multiplies the individual bytes of two unsigned or +unsigned source operands, then adds and accumulates the results into the +destination dword element size operand. + +The bit definition: +CPUID.(EAX=7,ECX=1):EDX[bit 4] + +AVX-VNNI-INT8 is on a new feature bits leaf. Add a CPUID feature word +FEAT_7_1_EDX for this leaf. + +Add CPUID definition for AVX-VNNI-INT8. + +Intel-SIG: commit eaaa197d5b11 target/i386: Add support for AVX-VNNI-INT8 in CPUID enumeration. +Backport GNR and SRF ISA into QEMU-6.2 + +Signed-off-by: Jiaxi Chen +Signed-off-by: Tao Su +Reviewed-by: Xiaoyao Li +Message-Id: <20230303065913.1246327-5-tao1.su@linux.intel.com> +Signed-off-by: Paolo Bonzini +[ Quanxian Wang: amend commit log ] +Signed-off-by: Quanxian Wang +--- + target/i386/cpu.c | 22 +++++++++++++++++++++- + target/i386/cpu.h | 3 +++ + 2 files changed, 24 insertions(+), 1 deletion(-) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index b19fb0cf87..a14284a81b 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -663,6 +663,7 @@ void x86_cpu_vendor_words2str(char *dst, uint32_t vendor1, + #define TCG_7_0_EDX_FEATURES CPUID_7_0_EDX_FSRM + #define TCG_7_1_EAX_FEATURES (CPUID_7_1_EAX_FZRM | CPUID_7_1_EAX_FSRS | \ + CPUID_7_1_EAX_FSRC) ++#define TCG_7_1_EDX_FEATURES 0 + #define TCG_7_2_EDX_FEATURES 0 + #define TCG_APM_FEATURES 0 + #define TCG_6_EAX_FEATURES CPUID_6_EAX_ARAT +@@ -906,6 +907,25 @@ FeatureWordInfo feature_word_info[FEATURE_WORDS] = { + }, + .tcg_features = TCG_7_2_EDX_FEATURES, + }, ++ [FEAT_7_1_EDX] = { ++ .type = CPUID_FEATURE_WORD, ++ .feat_names = { ++ NULL, NULL, NULL, NULL, ++ "avx-vnni-int8", NULL, NULL, NULL, ++ NULL, NULL, NULL, NULL, ++ NULL, NULL, NULL, NULL, ++ NULL, NULL, NULL, NULL, ++ NULL, NULL, NULL, NULL, ++ NULL, NULL, NULL, NULL, ++ NULL, NULL, NULL, NULL, ++ }, ++ .cpuid = { ++ .eax = 7, ++ .needs_ecx = true, .ecx = 1, ++ .reg = R_EDX, ++ }, ++ .tcg_features = TCG_7_1_EDX_FEATURES, ++ }, + [FEAT_8000_0007_EDX] = { + .type = CPUID_FEATURE_WORD, + .feat_names = { +@@ -5557,9 +5577,9 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, + } + } else if (count == 1) { + *eax = env->features[FEAT_7_1_EAX]; ++ *edx = env->features[FEAT_7_1_EDX]; + *ebx = 0; + *ecx = 0; +- *edx = 0; + } else if (count == 2) { + *edx = env->features[FEAT_7_2_EDX]; + *eax = 0; +diff --git a/target/i386/cpu.h b/target/i386/cpu.h +index 2bcc127fac..b81d77084c 100644 +--- a/target/i386/cpu.h ++++ b/target/i386/cpu.h +@@ -601,6 +601,7 @@ typedef enum FeatureWord { + FEAT_SGX_12_0_EAX, /* CPUID[EAX=0x12,ECX=0].EAX (SGX) */ + FEAT_SGX_12_0_EBX, /* CPUID[EAX=0x12,ECX=0].EBX (SGX MISCSELECT[31:0]) */ + FEAT_SGX_12_1_EAX, /* CPUID[EAX=0x12,ECX=1].EAX (SGX ATTRIBUTES[31:0]) */ ++ FEAT_7_1_EDX, /* CPUID[EAX=7,ECX=1].EDX */ + FEAT_7_2_EDX, /* CPUID[EAX=7,ECX=2].EDX */ + FEATURE_WORDS, + } FeatureWord; +@@ -895,6 +896,8 @@ uint64_t x86_cpu_get_supported_feature_word(FeatureWord w, + #define CPUID_7_1_EAX_AMX_FP16 (1U << 21) + /* Support for VPMADD52[H,L]UQ */ + #define CPUID_7_1_EAX_AVX_IFMA (1U << 23) ++/* Support for VPDPB[SU,UU,SS]D[,S] */ ++#define CPUID_7_1_EDX_AVX_VNNI_INT8 (1U << 4) + + /* Do not exhibit MXCSR Configuration Dependent Timing (MCDT) behavior */ + #define CPUID_7_2_EDX_MCDT_NO (1U << 5) +-- +2.27.0 + diff --git a/target-i386-Add-support-for-CMPCCXADD-in-CPUID-enume.patch b/target-i386-Add-support-for-CMPCCXADD-in-CPUID-enume.patch new file mode 100644 index 00000000..d1633122 --- /dev/null +++ b/target-i386-Add-support-for-CMPCCXADD-in-CPUID-enume.patch @@ -0,0 +1,61 @@ +From 25d08629eab566f5a47bf915a86e20318ee1cf08 Mon Sep 17 00:00:00 2001 +From: Jiaxi Chen +Date: Fri, 3 Mar 2023 14:59:08 +0800 +Subject: [PATCH] target/i386: Add support for CMPCCXADD in CPUID enumeration + +commit a9ce107fd0f2017af84255a9cf6542fa3eb3e214 upstream. + +CMPccXADD is a new set of instructions in the latest Intel platform +Sierra Forest. This new instruction set includes a semaphore operation +that can compare and add the operands if condition is met, which can +improve database performance. + +The bit definition: +CPUID.(EAX=7,ECX=1):EAX[bit 7] + +Add CPUID definition for CMPCCXADD. + +Intel-SIG: commit a9ce107fd0f2 target/i386: Add support for CMPCCXADD in CPUID enumeration. +Backport GNR and SRF ISA into QEMU-6.2 + +Signed-off-by: Jiaxi Chen +Signed-off-by: Tao Su +Reviewed-by: Xiaoyao Li +Message-Id: <20230303065913.1246327-2-tao1.su@linux.intel.com> +Signed-off-by: Paolo Bonzini +[ Quanxian Wang: amend commit log ] +Signed-off-by: Quanxian Wang +--- + target/i386/cpu.c | 2 +- + target/i386/cpu.h | 2 ++ + 2 files changed, 3 insertions(+), 1 deletion(-) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index 58124071da..47c2d9da80 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -872,7 +872,7 @@ FeatureWordInfo feature_word_info[FEATURE_WORDS] = { + .type = CPUID_FEATURE_WORD, + .feat_names = { + NULL, NULL, NULL, NULL, +- "avx-vnni", "avx512-bf16", NULL, NULL, ++ "avx-vnni", "avx512-bf16", NULL, "cmpccxadd", + NULL, NULL, "fzrm", "fsrs", + "fsrc", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, +diff --git a/target/i386/cpu.h b/target/i386/cpu.h +index 37c687d4d8..4a7362ee07 100644 +--- a/target/i386/cpu.h ++++ b/target/i386/cpu.h +@@ -883,6 +883,8 @@ uint64_t x86_cpu_get_supported_feature_word(FeatureWord w, + #define CPUID_7_1_EAX_AVX_VNNI (1U << 4) + /* AVX512 BFloat16 Instruction */ + #define CPUID_7_1_EAX_AVX512_BF16 (1U << 5) ++/* CMPCCXADD Instructions */ ++#define CPUID_7_1_EAX_CMPCCXADD (1U << 7) + /* Fast Zero REP MOVS */ + #define CPUID_7_1_EAX_FZRM (1U << 10) + /* Fast Short REP STOS */ +-- +2.27.0 + diff --git a/target-i386-Add-support-for-PREFETCHIT0-1-in-CPUID-e.patch b/target-i386-Add-support-for-PREFETCHIT0-1-in-CPUID-e.patch new file mode 100644 index 00000000..59053fd7 --- /dev/null +++ b/target-i386-Add-support-for-PREFETCHIT0-1-in-CPUID-e.patch @@ -0,0 +1,61 @@ +From 9a56c714caaf3bf31430a769befdf92e79388dda Mon Sep 17 00:00:00 2001 +From: Quanxian Wang +Date: Wed, 8 Nov 2023 12:46:00 +0800 +Subject: [PATCH] target/i386: Add support for PREFETCHIT0/1 in CPUID + enumeration + +commit d1a1111514333e46a98b136235f71eef90d610fa upstream. + +Latest Intel platform Granite Rapids has introduced a new instruction - +PREFETCHIT0/1, which moves code to memory (cache) closer to the +processor depending on specific hints. + +The bit definition: +CPUID.(EAX=7,ECX=1):EDX[bit 14] + +Add CPUID definition for PREFETCHIT0/1. + +Intel-SIG: commit d1a111151433 target/i386: Add support for PREFETCHIT0/1 in CPUID enumeration. +Backport GNR and SRF ISA into QEMU-6.2 + +Signed-off-by: Jiaxi Chen +Signed-off-by: Tao Su +Reviewed-by: Xiaoyao Li +Message-Id: <20230303065913.1246327-7-tao1.su@linux.intel.com> +Signed-off-by: Paolo Bonzini +[ Quanxian Wang: amend commit log ] +Signed-off-by: Quanxian Wang +--- + target/i386/cpu.c | 2 +- + target/i386/cpu.h | 2 ++ + 2 files changed, 3 insertions(+), 1 deletion(-) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index d36174d689..ee243693e3 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -913,7 +913,7 @@ FeatureWordInfo feature_word_info[FEATURE_WORDS] = { + NULL, NULL, NULL, NULL, + "avx-vnni-int8", "avx-ne-convert", NULL, NULL, + NULL, NULL, NULL, NULL, +- NULL, NULL, NULL, NULL, ++ NULL, NULL, "prefetchiti", NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, +diff --git a/target/i386/cpu.h b/target/i386/cpu.h +index 93c8bd6a13..32ecec5fa7 100644 +--- a/target/i386/cpu.h ++++ b/target/i386/cpu.h +@@ -900,6 +900,8 @@ uint64_t x86_cpu_get_supported_feature_word(FeatureWord w, + #define CPUID_7_1_EDX_AVX_VNNI_INT8 (1U << 4) + /* AVX NE CONVERT Instructions */ + #define CPUID_7_1_EDX_AVX_NE_CONVERT (1U << 5) ++/* PREFETCHIT0/1 Instructions */ ++#define CPUID_7_1_EDX_PREFETCHITI (1U << 14) + + /* Do not exhibit MXCSR Configuration Dependent Timing (MCDT) behavior */ + #define CPUID_7_2_EDX_MCDT_NO (1U << 5) +-- +2.27.0 + diff --git a/target-i386-Adjust-feature-level-according-to-FEAT_7.patch b/target-i386-Adjust-feature-level-according-to-FEAT_7.patch new file mode 100644 index 00000000..3c238c62 --- /dev/null +++ b/target-i386-Adjust-feature-level-according-to-FEAT_7.patch @@ -0,0 +1,46 @@ +From 52d000a4043f3000f880bb5c75a298f57b8e0fe0 Mon Sep 17 00:00:00 2001 +From: Tao Su +Date: Thu, 6 Jul 2023 13:49:44 +0800 +Subject: [PATCH] target/i386: Adjust feature level according to FEAT_7_1_EDX + +commit 8731336e90dea3dd04948127e775c9f087f97a4c upstream. + +If FEAT_7_1_EAX is 0 and FEAT_7_1_EDX is non-zero, as is the case +with a Granite Rapids host and +'-cpu host,-avx-vnni,-avx512-bf16,-fzrm,-fsrs,-fsrc,-amx-fp16', we can't +get CPUID_7_1 leaf even though CPUID_7_1_EDX has non-zero value. + +Update cpuid_level_func7 according to CPUID_7_1_EDX, otherwise +guest may report wrong maximum number sub-leaves in leaf 07H. + +Fixes: eaaa197d5b11 ("target/i386: Add support for AVX-VNNI-INT8 in CPUID enumeration") + +Intel-SIG: commit 8731336e90de target/i386: Adjust feature level according to FEAT_7_1_EDX. +Backport GNR and SRF ISA into QEMU-6.2 + +Cc: qemu-stable@nongnu.org +Signed-off-by: Tao Su +Reviewed-by: Xiaoyao Li +Message-ID: <20230706054949.66556-2-tao1.su@linux.intel.com> +Signed-off-by: Paolo Bonzini +[ Quanxian Wang: amend commit log ] +Signed-off-by: Quanxian Wang +--- + target/i386/cpu.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index efe0c2b46c..6aaa730a0d 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -6551,6 +6551,7 @@ void x86_cpu_expand_features(X86CPU *cpu, Error **errp) + x86_cpu_adjust_feat_level(cpu, FEAT_6_EAX); + x86_cpu_adjust_feat_level(cpu, FEAT_7_0_ECX); + x86_cpu_adjust_feat_level(cpu, FEAT_7_1_EAX); ++ x86_cpu_adjust_feat_level(cpu, FEAT_7_1_EDX); + x86_cpu_adjust_feat_level(cpu, FEAT_7_2_EDX); + x86_cpu_adjust_feat_level(cpu, FEAT_8000_0001_EDX); + x86_cpu_adjust_feat_level(cpu, FEAT_8000_0001_ECX); +-- +2.27.0 + diff --git a/target-i386-Export-GDS_NO-bit-to-guests.patch b/target-i386-Export-GDS_NO-bit-to-guests.patch new file mode 100644 index 00000000..5b6e5f10 --- /dev/null +++ b/target-i386-Export-GDS_NO-bit-to-guests.patch @@ -0,0 +1,46 @@ +From 3cea2c36571b39a6fa956abe66507c04283ad614 Mon Sep 17 00:00:00 2001 +From: Pawan Gupta +Date: Mon, 14 Aug 2023 21:54:27 -0700 +Subject: [PATCH] target/i386: Export GDS_NO bit to guests + +commit 3a2a1f97ea349745094e789e6b0768dbd92d0dcd upstream. + +Gather Data Sampling (GDS) is a side-channel attack using Gather +instructions. Some Intel processors will set ARCH_CAP_GDS_NO bit in +MSR IA32_ARCH_CAPABILITIES to report that they are not vulnerable to +GDS. + +Make this bit available to guests. + +Intel-SIG: commit 3a2a1f97ea34 ("target/i386: Export GDS_NO bit to guests") +Backport to export GDS_NO bit to guests(CVE-2022-40982). + +Closes: https://lore.kernel.org/qemu-devel/CAMGffEmG6TNq0n3+4OJAgXc8J0OevY60KHZekXCBs3LoK9vehA@mail.gmail.com/ +Reported-by: Jack Wang +Signed-off-by: Pawan Gupta +Tested-by: Jack Wang +Tested-by: Daniel Sneddon +Message-ID: +Signed-off-by: Paolo Bonzini +[ Aichun Shi: amend commit log ] +Signed-off-by: Aichun Shi +--- + target/i386/cpu.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index eb911b12fa..58124071da 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -1004,7 +1004,7 @@ FeatureWordInfo feature_word_info[FEATURE_WORDS] = { + NULL, "sbdr-ssdp-no", "fbsdp-no", "psdp-no", + NULL, "fb-clear", NULL, NULL, + NULL, NULL, NULL, NULL, +- "pbrsb-no", NULL, NULL, NULL, ++ "pbrsb-no", NULL, "gds-no", NULL, + NULL, NULL, NULL, NULL, + }, + .msr = { +-- +2.27.0 + diff --git a/tests-qtest-check-the-return-value.patch b/tests-qtest-check-the-return-value.patch new file mode 100644 index 00000000..ada8e4a3 --- /dev/null +++ b/tests-qtest-check-the-return-value.patch @@ -0,0 +1,62 @@ +From 53e0242318e838013504688307af44e80ab36c70 Mon Sep 17 00:00:00 2001 +From: zhujun2 +Date: Tue, 21 Nov 2023 18:03:25 -0800 +Subject: [PATCH] tests/qtest: check the return value + +These variables "ret" are never referenced in the code, thus +add check logic for the "ret" + +Signed-off-by: zhujun2 +--- + tests/qtest/test-filter-mirror.c | 1 + + tests/qtest/test-filter-redirector.c | 2 ++ + tests/qtest/virtio-net-test.c | 1 + + 3 files changed, 4 insertions(+) + +diff --git a/tests/qtest/test-filter-mirror.c b/tests/qtest/test-filter-mirror.c +index bc0dee64dd..40f736734a 100644 +--- a/tests/qtest/test-filter-mirror.c ++++ b/tests/qtest/test-filter-mirror.c +@@ -71,6 +71,7 @@ static void test_mirror(void) + g_assert_cmpint(len, ==, sizeof(send_buf)); + recv_buf = g_malloc(len); + ret = qemu_recv(recv_sock[0], recv_buf, len, 0); ++ g_assert_cmpint(ret, ==, len); + g_assert_cmpstr(recv_buf, ==, send_buf); + + g_free(recv_buf); +diff --git a/tests/qtest/test-filter-redirector.c b/tests/qtest/test-filter-redirector.c +index 4269b2cdd9..f802c94f54 100644 +--- a/tests/qtest/test-filter-redirector.c ++++ b/tests/qtest/test-filter-redirector.c +@@ -133,6 +133,7 @@ static void test_redirector_tx(void) + g_assert_cmpint(len, ==, sizeof(send_buf)); + recv_buf = g_malloc(len); + ret = qemu_recv(recv_sock, recv_buf, len, 0); ++ g_assert_cmpint(ret, ==, len); + g_assert_cmpstr(recv_buf, ==, send_buf); + + g_free(recv_buf); +@@ -201,6 +202,7 @@ static void test_redirector_rx(void) + g_assert_cmpint(len, ==, sizeof(send_buf)); + recv_buf = g_malloc(len); + ret = qemu_recv(backend_sock[0], recv_buf, len, 0); ++ g_assert_cmpint(ret, ==, len); + g_assert_cmpstr(recv_buf, ==, send_buf); + + close(send_sock); +diff --git a/tests/qtest/virtio-net-test.c b/tests/qtest/virtio-net-test.c +index 8bf74e516c..aab4480fb0 100644 +--- a/tests/qtest/virtio-net-test.c ++++ b/tests/qtest/virtio-net-test.c +@@ -92,6 +92,7 @@ static void tx_test(QVirtioDevice *dev, + len = ntohl(len); + + ret = qemu_recv(socket, buffer, len, 0); ++ g_assert_cmpint(ret, ==, len); + g_assert_cmpstr(buffer, ==, "TEST"); + } + +-- +2.27.0 + diff --git a/tpm_crb-mark-command-buffer-as-dirty-on-request-comp.patch b/tpm_crb-mark-command-buffer-as-dirty-on-request-comp.patch new file mode 100644 index 00000000..c989e26e --- /dev/null +++ b/tpm_crb-mark-command-buffer-as-dirty-on-request-comp.patch @@ -0,0 +1,43 @@ +From 1e32685272ff1932b9ca022db8717720fc901d0e Mon Sep 17 00:00:00 2001 +From: tangbinzy +Date: Mon, 6 Nov 2023 06:17:47 +0000 +Subject: [PATCH] tpm_crb: mark command buffer as dirty on request completion + mainline inclusion commit e37a0ef4605e5d2041785ff3fc89ca6021faf7a0 category: + bugfix + +--------------------------------------------------------------- + +At the moment, there doesn't seems to be any way to know that QEMU +made modification to the command buffer. This is potentially an issue +on Xen while migrating a guest, as modification to the buffer after +the migration as started could be ignored and not transfered to the +destination. + +Mark the memory region of the command buffer as dirty once a request +is completed. + +Signed-off-by: Anthony PERARD +Reviewed-by: Stefan Berger +Signed-off-by: Stefan Berger +Message-id: 20220411144749.47185-1-anthony.perard@citrix.com + +Signed-off-by: tangbinzy +--- + hw/tpm/tpm_crb.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/hw/tpm/tpm_crb.c b/hw/tpm/tpm_crb.c +index 58ebd1469c..c05972736a 100644 +--- a/hw/tpm/tpm_crb.c ++++ b/hw/tpm/tpm_crb.c +@@ -196,6 +196,7 @@ static void tpm_crb_request_completed(TPMIf *ti, int ret) + ARRAY_FIELD_DP32(s->regs, CRB_CTRL_STS, + tpmSts, 1); /* fatal error */ + } ++ memory_region_set_dirty(&s->cmdmem, 0, CRB_CTRL_CMD_SIZE); + } + + static enum TPMVersion tpm_crb_get_version(TPMIf *ti) +-- +2.27.0 + diff --git a/tracetool-avoid-invalid-escape-in-Python-string.patch b/tracetool-avoid-invalid-escape-in-Python-string.patch new file mode 100644 index 00000000..ffd30a2c --- /dev/null +++ b/tracetool-avoid-invalid-escape-in-Python-string.patch @@ -0,0 +1,38 @@ +From cb5e4e55c489462a2ff11143a5768b5c096bf1ad Mon Sep 17 00:00:00 2001 +From: qihao +Date: Wed, 15 Nov 2023 14:49:44 +0800 +Subject: [PATCH] tracetool: avoid invalid escape in Python string +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +cheery-pick from 4d96307c5b4fac40c6ca25f38318b4b65d315de0 + +This is an error in Python 3.12; fix it by using a raw string literal. + +Cc: +Signed-off-by: Marc-André Lureau +Reviewed-by: Philippe Mathieu-Daudé +Signed-off-by: Stefan Hajnoczi +Message-ID: <20231108105649.60453-1-marcandre.lureau@redhat.com> +Signed-off-by: qihao_yewu +--- + scripts/tracetool/__init__.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/scripts/tracetool/__init__.py b/scripts/tracetool/__init__.py +index 5bc94d95cf..630e85a5d6 100644 +--- a/scripts/tracetool/__init__.py ++++ b/scripts/tracetool/__init__.py +@@ -94,7 +94,7 @@ def out(*lines, **kwargs): + def validate_type(name): + bits = name.split(" ") + for bit in bits: +- bit = re.sub("\*", "", bit) ++ bit = re.sub(r"\*", "", bit) + if bit == "": + continue + if bit == "const": +-- +2.27.0 + diff --git a/util-Add-iova_tree_alloc_map.patch b/util-Add-iova_tree_alloc_map.patch new file mode 100644 index 00000000..c1ab3f7c --- /dev/null +++ b/util-Add-iova_tree_alloc_map.patch @@ -0,0 +1,219 @@ +From 6dac473fb3f4f98ef67c63a38b00465299519132 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= +Date: Mon, 14 Mar 2022 18:34:48 +0100 +Subject: [PATCH] util: Add iova_tree_alloc_map +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This iova tree function allows it to look for a hole in allocated +regions and return a totally new translation for a given translated +address. + +It's usage is mainly to allow devices to access qemu address space, +remapping guest's one into a new iova space where qemu can add chunks of +addresses. + +Signed-off-by: Eugenio Pérez +Reviewed-by: Peter Xu +Acked-by: Michael S. Tsirkin +Signed-off-by: Jason Wang +Signed-off-by: fangyi +--- + include/qemu/iova-tree.h | 18 ++++++ + util/iova-tree.c | 136 +++++++++++++++++++++++++++++++++++++++ + 2 files changed, 154 insertions(+) + +diff --git a/include/qemu/iova-tree.h b/include/qemu/iova-tree.h +index 8249edd764..d066400f09 100644 +--- a/include/qemu/iova-tree.h ++++ b/include/qemu/iova-tree.h +@@ -29,6 +29,7 @@ + #define IOVA_OK (0) + #define IOVA_ERR_INVALID (-1) /* Invalid parameters */ + #define IOVA_ERR_OVERLAP (-2) /* IOVA range overlapped */ ++#define IOVA_ERR_NOMEM (-3) /* Cannot allocate */ + + typedef struct IOVATree IOVATree; + typedef struct DMAMap { +@@ -119,6 +120,23 @@ const DMAMap *iova_tree_find_address(const IOVATree *tree, hwaddr iova); + */ + void iova_tree_foreach(IOVATree *tree, iova_tree_iterator iterator); + ++/** ++ * iova_tree_alloc_map: ++ * ++ * @tree: the iova tree to allocate from ++ * @map: the new map (as translated addr & size) to allocate in the iova region ++ * @iova_begin: the minimum address of the allocation ++ * @iova_end: the maximum addressable direction of the allocation ++ * ++ * Allocates a new region of a given size, between iova_min and iova_max. ++ * ++ * Return: Same as iova_tree_insert, but cannot overlap and can return error if ++ * iova tree is out of free contiguous range. The caller gets the assigned iova ++ * in map->iova. ++ */ ++int iova_tree_alloc_map(IOVATree *tree, DMAMap *map, hwaddr iova_begin, ++ hwaddr iova_end); ++ + /** + * iova_tree_destroy: + * +diff --git a/util/iova-tree.c b/util/iova-tree.c +index 23ea35b7a4..139626b46f 100644 +--- a/util/iova-tree.c ++++ b/util/iova-tree.c +@@ -16,6 +16,40 @@ struct IOVATree { + GTree *tree; + }; + ++/* Args to pass to iova_tree_alloc foreach function. */ ++struct IOVATreeAllocArgs { ++ /* Size of the desired allocation */ ++ size_t new_size; ++ ++ /* The minimum address allowed in the allocation */ ++ hwaddr iova_begin; ++ ++ /* Map at the left of the hole, can be NULL if "this" is first one */ ++ const DMAMap *prev; ++ ++ /* Map at the right of the hole, can be NULL if "prev" is the last one */ ++ const DMAMap *this; ++ ++ /* If found, we fill in the IOVA here */ ++ hwaddr iova_result; ++ ++ /* Whether have we found a valid IOVA */ ++ bool iova_found; ++}; ++ ++/** ++ * Iterate args to the next hole ++ * ++ * @args: The alloc arguments ++ * @next: The next mapping in the tree. Can be NULL to signal the last one ++ */ ++static void iova_tree_alloc_args_iterate(struct IOVATreeAllocArgs *args, ++ const DMAMap *next) ++{ ++ args->prev = args->this; ++ args->this = next; ++} ++ + static int iova_tree_compare(gconstpointer a, gconstpointer b, gpointer data) + { + const DMAMap *m1 = a, *m2 = b; +@@ -107,6 +141,108 @@ int iova_tree_remove(IOVATree *tree, const DMAMap *map) + return IOVA_OK; + } + ++/** ++ * Try to find an unallocated IOVA range between prev and this elements. ++ * ++ * @args: Arguments to allocation ++ * ++ * Cases: ++ * ++ * (1) !prev, !this: No entries allocated, always succeed ++ * ++ * (2) !prev, this: We're iterating at the 1st element. ++ * ++ * (3) prev, !this: We're iterating at the last element. ++ * ++ * (4) prev, this: this is the most common case, we'll try to find a hole ++ * between "prev" and "this" mapping. ++ * ++ * Note that this function assumes the last valid iova is HWADDR_MAX, but it ++ * searches linearly so it's easy to discard the result if it's not the case. ++ */ ++static void iova_tree_alloc_map_in_hole(struct IOVATreeAllocArgs *args) ++{ ++ const DMAMap *prev = args->prev, *this = args->this; ++ uint64_t hole_start, hole_last; ++ ++ if (this && this->iova + this->size < args->iova_begin) { ++ return; ++ } ++ ++ hole_start = MAX(prev ? prev->iova + prev->size + 1 : 0, args->iova_begin); ++ hole_last = this ? this->iova : HWADDR_MAX; ++ ++ if (hole_last - hole_start > args->new_size) { ++ args->iova_result = hole_start; ++ args->iova_found = true; ++ } ++} ++ ++/** ++ * Foreach dma node in the tree, compare if there is a hole with its previous ++ * node (or minimum iova address allowed) and the node. ++ * ++ * @key: Node iterating ++ * @value: Node iterating ++ * @pargs: Struct to communicate with the outside world ++ * ++ * Return: false to keep iterating, true if needs break. ++ */ ++static gboolean iova_tree_alloc_traverse(gpointer key, gpointer value, ++ gpointer pargs) ++{ ++ struct IOVATreeAllocArgs *args = pargs; ++ DMAMap *node = value; ++ ++ assert(key == value); ++ ++ iova_tree_alloc_args_iterate(args, node); ++ iova_tree_alloc_map_in_hole(args); ++ return args->iova_found; ++} ++ ++int iova_tree_alloc_map(IOVATree *tree, DMAMap *map, hwaddr iova_begin, ++ hwaddr iova_last) ++{ ++ struct IOVATreeAllocArgs args = { ++ .new_size = map->size, ++ .iova_begin = iova_begin, ++ }; ++ ++ if (unlikely(iova_last < iova_begin)) { ++ return IOVA_ERR_INVALID; ++ } ++ ++ /* ++ * Find a valid hole for the mapping ++ * ++ * Assuming low iova_begin, so no need to do a binary search to ++ * locate the first node. ++ * ++ * TODO: Replace all this with g_tree_node_first/next/last when available ++ * (from glib since 2.68). To do it with g_tree_foreach complicates the ++ * code a lot. ++ * ++ */ ++ g_tree_foreach(tree->tree, iova_tree_alloc_traverse, &args); ++ if (!args.iova_found) { ++ /* ++ * Either tree is empty or the last hole is still not checked. ++ * g_tree_foreach does not compare (last, iova_last] range, so we check ++ * it here. ++ */ ++ iova_tree_alloc_args_iterate(&args, NULL); ++ iova_tree_alloc_map_in_hole(&args); ++ } ++ ++ if (!args.iova_found || args.iova_result + map->size > iova_last) { ++ return IOVA_ERR_NOMEM; ++ } ++ ++ map->iova = args.iova_result; ++ return iova_tree_insert(tree, map); ++} ++ + void iova_tree_destroy(IOVATree *tree) + { + g_tree_destroy(tree->tree); +-- +2.27.0 + diff --git a/util-Return-void-on-iova_tree_remove.patch b/util-Return-void-on-iova_tree_remove.patch new file mode 100644 index 00000000..a38c7c3d --- /dev/null +++ b/util-Return-void-on-iova_tree_remove.patch @@ -0,0 +1,61 @@ +From b4c0eb3ad95c5c9a32cf87d30647d63ec9c193a9 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= +Date: Wed, 27 Apr 2022 17:49:31 +0200 +Subject: [PATCH] util: Return void on iova_tree_remove +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +It always returns IOVA_OK so nobody uses it. + +Acked-by: Jason Wang +Reviewed-by: Peter Xu +Signed-off-by: Eugenio Pérez +Message-Id: <20220427154931.3166388-1-eperezma@redhat.com> +Signed-off-by: Laurent Vivier +Signed-off-by: fangyi +--- + include/qemu/iova-tree.h | 4 +--- + util/iova-tree.c | 4 +--- + 2 files changed, 2 insertions(+), 6 deletions(-) + +diff --git a/include/qemu/iova-tree.h b/include/qemu/iova-tree.h +index c938fb0793..16bbfdf5f8 100644 +--- a/include/qemu/iova-tree.h ++++ b/include/qemu/iova-tree.h +@@ -72,10 +72,8 @@ int iova_tree_insert(IOVATree *tree, const DMAMap *map); + * provided. The range does not need to be exactly what has inserted, + * all the mappings that are included in the provided range will be + * removed from the tree. Here map->translated_addr is meaningless. +- * +- * Return: 0 if succeeded, or <0 if error. + */ +-int iova_tree_remove(IOVATree *tree, const DMAMap *map); ++void iova_tree_remove(IOVATree *tree, const DMAMap *map); + + /** + * iova_tree_find: +diff --git a/util/iova-tree.c b/util/iova-tree.c +index 6dff29c1f6..fee530a579 100644 +--- a/util/iova-tree.c ++++ b/util/iova-tree.c +@@ -164,15 +164,13 @@ void iova_tree_foreach(IOVATree *tree, iova_tree_iterator iterator) + g_tree_foreach(tree->tree, iova_tree_traverse, iterator); + } + +-int iova_tree_remove(IOVATree *tree, const DMAMap *map) ++void iova_tree_remove(IOVATree *tree, const DMAMap *map) + { + const DMAMap *overlap; + + while ((overlap = iova_tree_find(tree, map))) { + g_tree_remove(tree->tree, overlap); + } +- +- return IOVA_OK; + } + + /** +-- +2.27.0 + diff --git a/util-accept-iova_tree_remove_parameter-by-value.patch b/util-accept-iova_tree_remove_parameter-by-value.patch new file mode 100644 index 00000000..6ee10593 --- /dev/null +++ b/util-accept-iova_tree_remove_parameter-by-value.patch @@ -0,0 +1,173 @@ +From 4ac2c0c847ffee0fb6aa92a9735be9448c62c107 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= +Date: Tue, 23 Aug 2022 20:20:04 +0200 +Subject: [PATCH] util: accept iova_tree_remove_parameter by value +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +It's convenient to call iova_tree_remove from a map returned from +iova_tree_find or iova_tree_find_iova. With the current code this is not +possible, since we will free it, and then we will try to search for it +again. + +Fix it making accepting the map by value, forcing a copy of the +argument. Not applying a fixes tag, since there is no use like that at +the moment. + +Signed-off-by: Eugenio Pérez +Signed-off-by: Jason Wang +Signed-off-by: fangyi +--- + hw/i386/intel_iommu.c | 6 +++--- + hw/virtio/vhost-iova-tree.c | 2 +- + hw/virtio/vhost-iova-tree.h | 2 +- + hw/virtio/vhost-vdpa.c | 6 +++--- + include/qemu/iova-tree.h | 2 +- + net/vhost-vdpa.c | 4 ++-- + util/iova-tree.c | 4 ++-- + 7 files changed, 13 insertions(+), 13 deletions(-) + +diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c +index 5b865ac08c..2d5ad84149 100644 +--- a/hw/i386/intel_iommu.c ++++ b/hw/i386/intel_iommu.c +@@ -1157,7 +1157,7 @@ static int vtd_page_walk_one(IOMMUTLBEvent *event, vtd_page_walk_info *info) + return ret; + } + /* Drop any existing mapping */ +- iova_tree_remove(as->iova_tree, &target); ++ iova_tree_remove(as->iova_tree, target); + /* Recover the correct type */ + event->type = IOMMU_NOTIFIER_MAP; + entry->perm = cache_perm; +@@ -1170,7 +1170,7 @@ static int vtd_page_walk_one(IOMMUTLBEvent *event, vtd_page_walk_info *info) + trace_vtd_page_walk_one_skip_unmap(entry->iova, entry->addr_mask); + return 0; + } +- iova_tree_remove(as->iova_tree, &target); ++ iova_tree_remove(as->iova_tree, target); + } + + trace_vtd_page_walk_one(info->domain_id, entry->iova, +@@ -3516,7 +3516,7 @@ static void vtd_address_space_unmap(VTDAddressSpace *as, IOMMUNotifier *n) + + map.iova = n->start; + map.size = size; +- iova_tree_remove(as->iova_tree, &map); ++ iova_tree_remove(as->iova_tree, map); + } + + static void vtd_address_space_unmap_all(IntelIOMMUState *s) +diff --git a/hw/virtio/vhost-iova-tree.c b/hw/virtio/vhost-iova-tree.c +index 55fed1fefb..1339a4de8b 100644 +--- a/hw/virtio/vhost-iova-tree.c ++++ b/hw/virtio/vhost-iova-tree.c +@@ -104,7 +104,7 @@ int vhost_iova_tree_map_alloc(VhostIOVATree *tree, DMAMap *map) + * @iova_tree: The vhost iova tree + * @map: The map to remove + */ +-void vhost_iova_tree_remove(VhostIOVATree *iova_tree, const DMAMap *map) ++void vhost_iova_tree_remove(VhostIOVATree *iova_tree, DMAMap map) + { + iova_tree_remove(iova_tree->iova_taddr_map, map); + } +diff --git a/hw/virtio/vhost-iova-tree.h b/hw/virtio/vhost-iova-tree.h +index 6a4f24e0f9..4adfd79ff0 100644 +--- a/hw/virtio/vhost-iova-tree.h ++++ b/hw/virtio/vhost-iova-tree.h +@@ -22,6 +22,6 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC(VhostIOVATree, vhost_iova_tree_delete); + const DMAMap *vhost_iova_tree_find_iova(const VhostIOVATree *iova_tree, + const DMAMap *map); + int vhost_iova_tree_map_alloc(VhostIOVATree *iova_tree, DMAMap *map); +-void vhost_iova_tree_remove(VhostIOVATree *iova_tree, const DMAMap *map); ++void vhost_iova_tree_remove(VhostIOVATree *iova_tree, DMAMap map); + + #endif +diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c +index 02dab41c42..0f640f670b 100644 +--- a/hw/virtio/vhost-vdpa.c ++++ b/hw/virtio/vhost-vdpa.c +@@ -242,7 +242,7 @@ static void vhost_vdpa_listener_region_add(MemoryListener *listener, + + fail_map: + if (v->shadow_vqs_enabled) { +- vhost_iova_tree_remove(v->iova_tree, &mem_region); ++ vhost_iova_tree_remove(v->iova_tree, mem_region); + } + + fail: +@@ -302,7 +302,7 @@ static void vhost_vdpa_listener_region_del(MemoryListener *listener, + return; + } + iova = result->iova; +- vhost_iova_tree_remove(v->iova_tree, result); ++ vhost_iova_tree_remove(v->iova_tree, *result); + } + vhost_vdpa_iotlb_batch_begin_once(v); + ret = vhost_vdpa_dma_unmap(v, iova, int128_get64(llsize)); +@@ -946,7 +946,7 @@ static bool vhost_vdpa_svq_map_ring(struct vhost_vdpa *v, DMAMap *needle, + needle->perm == IOMMU_RO); + if (unlikely(r != 0)) { + error_setg_errno(errp, -r, "Cannot map region to device"); +- vhost_iova_tree_remove(v->iova_tree, needle); ++ vhost_iova_tree_remove(v->iova_tree, *needle); + } + + return r == 0; +diff --git a/include/qemu/iova-tree.h b/include/qemu/iova-tree.h +index 16bbfdf5f8..8528e5c98f 100644 +--- a/include/qemu/iova-tree.h ++++ b/include/qemu/iova-tree.h +@@ -73,7 +73,7 @@ int iova_tree_insert(IOVATree *tree, const DMAMap *map); + * all the mappings that are included in the provided range will be + * removed from the tree. Here map->translated_addr is meaningless. + */ +-void iova_tree_remove(IOVATree *tree, const DMAMap *map); ++void iova_tree_remove(IOVATree *tree, DMAMap map); + + /** + * iova_tree_find: +diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c +index 0f75aa6080..8cfd086639 100644 +--- a/net/vhost-vdpa.c ++++ b/net/vhost-vdpa.c +@@ -252,7 +252,7 @@ static void vhost_vdpa_cvq_unmap_buf(struct vhost_vdpa *v, void *addr) + error_report("Device cannot unmap: %s(%d)", g_strerror(r), r); + } + +- vhost_iova_tree_remove(tree, map); ++ vhost_iova_tree_remove(tree, *map); + } + + static size_t vhost_vdpa_net_cvq_cmd_len(void) +@@ -305,7 +305,7 @@ static bool vhost_vdpa_cvq_map_buf(struct vhost_vdpa *v, + return true; + + dma_map_err: +- vhost_iova_tree_remove(v->iova_tree, &map); ++ vhost_iova_tree_remove(v->iova_tree, map); + return false; + } + +diff --git a/util/iova-tree.c b/util/iova-tree.c +index fee530a579..536789797e 100644 +--- a/util/iova-tree.c ++++ b/util/iova-tree.c +@@ -164,11 +164,11 @@ void iova_tree_foreach(IOVATree *tree, iova_tree_iterator iterator) + g_tree_foreach(tree->tree, iova_tree_traverse, iterator); + } + +-void iova_tree_remove(IOVATree *tree, const DMAMap *map) ++void iova_tree_remove(IOVATree *tree, DMAMap map) + { + const DMAMap *overlap; + +- while ((overlap = iova_tree_find(tree, map))) { ++ while ((overlap = iova_tree_find(tree, &map))) { + g_tree_remove(tree->tree, overlap); + } + } +-- +2.27.0 + diff --git a/util-add-iova_tree_find_iova.patch b/util-add-iova_tree_find_iova.patch new file mode 100644 index 00000000..fd935fe9 --- /dev/null +++ b/util-add-iova_tree_find_iova.patch @@ -0,0 +1,116 @@ +From 087ef4f1cfef58eadcb157585b70cf716c567305 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= +Date: Mon, 14 Mar 2022 18:34:49 +0100 +Subject: [PATCH] util: add iova_tree_find_iova +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This function does the reverse operation of iova_tree_find: To look for +a mapping that match a translated address so we can do the reverse. + +This have linear complexity instead of logarithmic, but it supports +overlapping HVA. Future developments could reduce it. + +Signed-off-by: Eugenio Pérez +Acked-by: Michael S. Tsirkin +Signed-off-by: Jason Wang +Signed-off-by: fangyi +--- + include/qemu/iova-tree.h | 20 +++++++++++++++++++- + util/iova-tree.c | 34 ++++++++++++++++++++++++++++++++++ + 2 files changed, 53 insertions(+), 1 deletion(-) + +diff --git a/include/qemu/iova-tree.h b/include/qemu/iova-tree.h +index d066400f09..c938fb0793 100644 +--- a/include/qemu/iova-tree.h ++++ b/include/qemu/iova-tree.h +@@ -83,7 +83,7 @@ int iova_tree_remove(IOVATree *tree, const DMAMap *map); + * @tree: the iova tree to search from + * @map: the mapping to search + * +- * Search for a mapping in the iova tree that overlaps with the ++ * Search for a mapping in the iova tree that iova overlaps with the + * mapping range specified. Only the first found mapping will be + * returned. + * +@@ -95,6 +95,24 @@ int iova_tree_remove(IOVATree *tree, const DMAMap *map); + */ + const DMAMap *iova_tree_find(const IOVATree *tree, const DMAMap *map); + ++/** ++ * iova_tree_find_iova: ++ * ++ * @tree: the iova tree to search from ++ * @map: the mapping to search ++ * ++ * Search for a mapping in the iova tree that translated_addr overlaps with the ++ * mapping range specified. Only the first found mapping will be ++ * returned. ++ * ++ * Return: DMAMap pointer if found, or NULL if not found. Note that ++ * the returned DMAMap pointer is maintained internally. User should ++ * only read the content but never modify or free the content. Also, ++ * user is responsible to make sure the pointer is valid (say, no ++ * concurrent deletion in progress). ++ */ ++const DMAMap *iova_tree_find_iova(const IOVATree *tree, const DMAMap *map); ++ + /** + * iova_tree_find_address: + * +diff --git a/util/iova-tree.c b/util/iova-tree.c +index 139626b46f..6dff29c1f6 100644 +--- a/util/iova-tree.c ++++ b/util/iova-tree.c +@@ -37,6 +37,11 @@ struct IOVATreeAllocArgs { + bool iova_found; + }; + ++typedef struct IOVATreeFindIOVAArgs { ++ const DMAMap *needle; ++ const DMAMap *result; ++} IOVATreeFindIOVAArgs; ++ + /** + * Iterate args to the next hole + * +@@ -81,6 +86,35 @@ const DMAMap *iova_tree_find(const IOVATree *tree, const DMAMap *map) + return g_tree_lookup(tree->tree, map); + } + ++static gboolean iova_tree_find_address_iterator(gpointer key, gpointer value, ++ gpointer data) ++{ ++ const DMAMap *map = key; ++ IOVATreeFindIOVAArgs *args = data; ++ const DMAMap *needle; ++ ++ g_assert(key == value); ++ ++ needle = args->needle; ++ if (map->translated_addr + map->size < needle->translated_addr || ++ needle->translated_addr + needle->size < map->translated_addr) { ++ return false; ++ } ++ ++ args->result = map; ++ return true; ++} ++ ++const DMAMap *iova_tree_find_iova(const IOVATree *tree, const DMAMap *map) ++{ ++ IOVATreeFindIOVAArgs args = { ++ .needle = map, ++ }; ++ ++ g_tree_foreach(tree->tree, iova_tree_find_address_iterator, &args); ++ return args.result; ++} ++ + const DMAMap *iova_tree_find_address(const IOVATree *tree, hwaddr iova) + { + const DMAMap map = { .iova = iova, .size = 0 }; +-- +2.27.0 + diff --git a/vdpa-Adapt-vhost_vdpa_get_vring_base-to-SVQ.patch b/vdpa-Adapt-vhost_vdpa_get_vring_base-to-SVQ.patch new file mode 100644 index 00000000..cd93861b --- /dev/null +++ b/vdpa-Adapt-vhost_vdpa_get_vring_base-to-SVQ.patch @@ -0,0 +1,59 @@ +From d42fea8a40c4a5d8909103910d86da8e674d1fb2 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= +Date: Mon, 14 Mar 2022 18:34:52 +0100 +Subject: [PATCH] vdpa: Adapt vhost_vdpa_get_vring_base to SVQ +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This is needed to achieve migration, so the destination can restore its +index. + +Setting base as last used idx, so destination will see as available all +the entries that the device did not use, including the in-flight +processing ones. + +This is ok for networking, but other kinds of devices might have +problems with these retransmissions. + +Signed-off-by: Eugenio Pérez +Acked-by: Michael S. Tsirkin +Signed-off-by: Jason Wang +Signed-off-by: fangyi +--- + hw/virtio/vhost-vdpa.c | 17 +++++++++++++++++ + 1 file changed, 17 insertions(+) + +diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c +index 8245345bcd..428137f654 100644 +--- a/hw/virtio/vhost-vdpa.c ++++ b/hw/virtio/vhost-vdpa.c +@@ -1143,8 +1143,25 @@ static int vhost_vdpa_set_vring_base(struct vhost_dev *dev, + static int vhost_vdpa_get_vring_base(struct vhost_dev *dev, + struct vhost_vring_state *ring) + { ++ struct vhost_vdpa *v = dev->opaque; + int ret; + ++ if (v->shadow_vqs_enabled) { ++ VhostShadowVirtqueue *svq = g_ptr_array_index(v->shadow_vqs, ++ ring->index); ++ ++ /* ++ * Setting base as last used idx, so destination will see as available ++ * all the entries that the device did not use, including the in-flight ++ * processing ones. ++ * ++ * TODO: This is ok for networking, but other kinds of devices might ++ * have problems with these retransmissions. ++ */ ++ ring->num = svq->last_used_idx; ++ return 0; ++ } ++ + ret = vhost_vdpa_call(dev, VHOST_GET_VRING_BASE, ring); + trace_vhost_vdpa_get_vring_base(dev, ring->index, ring->num); + return ret; +-- +2.27.0 + diff --git a/vdpa-Add-custom-IOTLB-translations-to-SVQ.patch b/vdpa-Add-custom-IOTLB-translations-to-SVQ.patch new file mode 100644 index 00000000..4f6c1272 --- /dev/null +++ b/vdpa-Add-custom-IOTLB-translations-to-SVQ.patch @@ -0,0 +1,415 @@ +From 649e277b6ec0d2cd798f6d43776ea38b00450db9 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= +Date: Mon, 14 Mar 2022 18:34:51 +0100 +Subject: [PATCH] vdpa: Add custom IOTLB translations to SVQ +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Use translations added in VhostIOVATree in SVQ. + +Only introduce usage here, not allocation and deallocation. As with +previous patches, we use the dead code paths of shadow_vqs_enabled to +avoid commiting too many changes at once. These are impossible to take +at the moment. + +Signed-off-by: Eugenio Pérez +Acked-by: Michael S. Tsirkin +Signed-off-by: Jason Wang +Signed-off-by: fangyi +--- + hw/virtio/vhost-shadow-virtqueue.c | 86 +++++++++++++++++--- + hw/virtio/vhost-shadow-virtqueue.h | 6 +- + hw/virtio/vhost-vdpa.c | 122 ++++++++++++++++++++++++----- + include/hw/virtio/vhost-vdpa.h | 3 + + 4 files changed, 187 insertions(+), 30 deletions(-) + +diff --git a/hw/virtio/vhost-shadow-virtqueue.c b/hw/virtio/vhost-shadow-virtqueue.c +index 46e94f0861..c38b6b6ab5 100644 +--- a/hw/virtio/vhost-shadow-virtqueue.c ++++ b/hw/virtio/vhost-shadow-virtqueue.c +@@ -69,7 +69,59 @@ static uint16_t vhost_svq_available_slots(const VhostShadowVirtqueue *svq) + return svq->vring.num - (svq->shadow_avail_idx - svq->shadow_used_idx); + } + +-static void vhost_vring_write_descs(VhostShadowVirtqueue *svq, ++/** ++ * Translate addresses between the qemu's virtual address and the SVQ IOVA ++ * ++ * @svq: Shadow VirtQueue ++ * @vaddr: Translated IOVA addresses ++ * @iovec: Source qemu's VA addresses ++ * @num: Length of iovec and minimum length of vaddr ++ */ ++static bool vhost_svq_translate_addr(const VhostShadowVirtqueue *svq, ++ hwaddr *addrs, const struct iovec *iovec, ++ size_t num) ++{ ++ if (num == 0) { ++ return true; ++ } ++ ++ for (size_t i = 0; i < num; ++i) { ++ DMAMap needle = { ++ .translated_addr = (hwaddr)(uintptr_t)iovec[i].iov_base, ++ .size = iovec[i].iov_len, ++ }; ++ Int128 needle_last, map_last; ++ size_t off; ++ ++ const DMAMap *map = vhost_iova_tree_find_iova(svq->iova_tree, &needle); ++ /* ++ * Map cannot be NULL since iova map contains all guest space and ++ * qemu already has a physical address mapped ++ */ ++ if (unlikely(!map)) { ++ qemu_log_mask(LOG_GUEST_ERROR, ++ "Invalid address 0x%"HWADDR_PRIx" given by guest", ++ needle.translated_addr); ++ return false; ++ } ++ ++ off = needle.translated_addr - map->translated_addr; ++ addrs[i] = map->iova + off; ++ ++ needle_last = int128_add(int128_make64(needle.translated_addr), ++ int128_make64(iovec[i].iov_len)); ++ map_last = int128_make64(map->translated_addr + map->size); ++ if (unlikely(int128_gt(needle_last, map_last))) { ++ qemu_log_mask(LOG_GUEST_ERROR, ++ "Guest buffer expands over iova range"); ++ return false; ++ } ++ } ++ ++ return true; ++} ++ ++static void vhost_vring_write_descs(VhostShadowVirtqueue *svq, hwaddr *sg, + const struct iovec *iovec, size_t num, + bool more_descs, bool write) + { +@@ -88,7 +140,7 @@ static void vhost_vring_write_descs(VhostShadowVirtqueue *svq, + } else { + descs[i].flags = flags; + } +- descs[i].addr = cpu_to_le64((hwaddr)(intptr_t)iovec[n].iov_base); ++ descs[i].addr = cpu_to_le64(sg[n]); + descs[i].len = cpu_to_le32(iovec[n].iov_len); + + last = i; +@@ -103,6 +155,8 @@ static bool vhost_svq_add_split(VhostShadowVirtqueue *svq, + { + unsigned avail_idx; + vring_avail_t *avail = svq->vring.avail; ++ bool ok; ++ g_autofree hwaddr *sgs = g_new(hwaddr, MAX(elem->out_num, elem->in_num)); + + *head = svq->free_head; + +@@ -113,9 +167,20 @@ static bool vhost_svq_add_split(VhostShadowVirtqueue *svq, + return false; + } + +- vhost_vring_write_descs(svq, elem->out_sg, elem->out_num, elem->in_num > 0, +- false); +- vhost_vring_write_descs(svq, elem->in_sg, elem->in_num, false, true); ++ ok = vhost_svq_translate_addr(svq, sgs, elem->out_sg, elem->out_num); ++ if (unlikely(!ok)) { ++ return false; ++ } ++ vhost_vring_write_descs(svq, sgs, elem->out_sg, elem->out_num, ++ elem->in_num > 0, false); ++ ++ ++ ok = vhost_svq_translate_addr(svq, sgs, elem->in_sg, elem->in_num); ++ if (unlikely(!ok)) { ++ return false; ++ } ++ ++ vhost_vring_write_descs(svq, sgs, elem->in_sg, elem->in_num, false, true); + + /* + * Put the entry in the available array (but don't update avail->idx until +@@ -394,9 +459,9 @@ void vhost_svq_set_svq_call_fd(VhostShadowVirtqueue *svq, int call_fd) + void vhost_svq_get_vring_addr(const VhostShadowVirtqueue *svq, + struct vhost_vring_addr *addr) + { +- addr->desc_user_addr = (uint64_t)(intptr_t)svq->vring.desc; +- addr->avail_user_addr = (uint64_t)(intptr_t)svq->vring.avail; +- addr->used_user_addr = (uint64_t)(intptr_t)svq->vring.used; ++ addr->desc_user_addr = (uint64_t)(uintptr_t)svq->vring.desc; ++ addr->avail_user_addr = (uint64_t)(uintptr_t)svq->vring.avail; ++ addr->used_user_addr = (uint64_t)(uintptr_t)svq->vring.used; + } + + size_t vhost_svq_driver_area_size(const VhostShadowVirtqueue *svq) +@@ -517,11 +582,13 @@ void vhost_svq_stop(VhostShadowVirtqueue *svq) + * Creates vhost shadow virtqueue, and instructs the vhost device to use the + * shadow methods and file descriptors. + * ++ * @iova_tree: Tree to perform descriptors translations ++ * + * Returns the new virtqueue or NULL. + * + * In case of error, reason is reported through error_report. + */ +-VhostShadowVirtqueue *vhost_svq_new(void) ++VhostShadowVirtqueue *vhost_svq_new(VhostIOVATree *iova_tree) + { + g_autofree VhostShadowVirtqueue *svq = g_new0(VhostShadowVirtqueue, 1); + int r; +@@ -542,6 +609,7 @@ VhostShadowVirtqueue *vhost_svq_new(void) + + event_notifier_init_fd(&svq->svq_kick, VHOST_FILE_UNBIND); + event_notifier_set_handler(&svq->hdev_call, vhost_svq_handle_call); ++ svq->iova_tree = iova_tree; + return g_steal_pointer(&svq); + + err_init_hdev_call: +diff --git a/hw/virtio/vhost-shadow-virtqueue.h b/hw/virtio/vhost-shadow-virtqueue.h +index 38b3b91ca7..e5e24c536d 100644 +--- a/hw/virtio/vhost-shadow-virtqueue.h ++++ b/hw/virtio/vhost-shadow-virtqueue.h +@@ -13,6 +13,7 @@ + #include "qemu/event_notifier.h" + #include "hw/virtio/virtio.h" + #include "standard-headers/linux/vhost_types.h" ++#include "hw/virtio/vhost-iova-tree.h" + + /* Shadow virtqueue to relay notifications */ + typedef struct VhostShadowVirtqueue { +@@ -43,6 +44,9 @@ typedef struct VhostShadowVirtqueue { + /* Virtio device */ + VirtIODevice *vdev; + ++ /* IOVA mapping */ ++ VhostIOVATree *iova_tree; ++ + /* Map for use the guest's descriptors */ + VirtQueueElement **ring_id_maps; + +@@ -75,7 +79,7 @@ void vhost_svq_start(VhostShadowVirtqueue *svq, VirtIODevice *vdev, + VirtQueue *vq); + void vhost_svq_stop(VhostShadowVirtqueue *svq); + +-VhostShadowVirtqueue *vhost_svq_new(void); ++VhostShadowVirtqueue *vhost_svq_new(VhostIOVATree *iova_tree); + + void vhost_svq_free(gpointer vq); + G_DEFINE_AUTOPTR_CLEANUP_FUNC(VhostShadowVirtqueue, vhost_svq_free); +diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c +index db34f26246..8245345bcd 100644 +--- a/hw/virtio/vhost-vdpa.c ++++ b/hw/virtio/vhost-vdpa.c +@@ -211,6 +211,21 @@ static void vhost_vdpa_listener_region_add(MemoryListener *listener, + vaddr, section->readonly); + + llsize = int128_sub(llend, int128_make64(iova)); ++ if (v->shadow_vqs_enabled) { ++ DMAMap mem_region = { ++ .translated_addr = (hwaddr)(uintptr_t)vaddr, ++ .size = int128_get64(llsize) - 1, ++ .perm = IOMMU_ACCESS_FLAG(true, section->readonly), ++ }; ++ ++ int r = vhost_iova_tree_map_alloc(v->iova_tree, &mem_region); ++ if (unlikely(r != IOVA_OK)) { ++ error_report("Can't allocate a mapping (%d)", r); ++ goto fail; ++ } ++ ++ iova = mem_region.iova; ++ } + + vhost_vdpa_iotlb_batch_begin_once(v); + ret = vhost_vdpa_dma_map(v, iova, int128_get64(llsize), +@@ -263,6 +278,20 @@ static void vhost_vdpa_listener_region_del(MemoryListener *listener, + + llsize = int128_sub(llend, int128_make64(iova)); + ++ if (v->shadow_vqs_enabled) { ++ const DMAMap *result; ++ const void *vaddr = memory_region_get_ram_ptr(section->mr) + ++ section->offset_within_region + ++ (iova - section->offset_within_address_space); ++ DMAMap mem_region = { ++ .translated_addr = (hwaddr)(uintptr_t)vaddr, ++ .size = int128_get64(llsize) - 1, ++ }; ++ ++ result = vhost_iova_tree_find_iova(v->iova_tree, &mem_region); ++ iova = result->iova; ++ vhost_iova_tree_remove(v->iova_tree, &mem_region); ++ } + vhost_vdpa_iotlb_batch_begin_once(v); + ret = vhost_vdpa_dma_unmap(v, iova, int128_get64(llsize)); + if (ret) { +@@ -372,7 +401,7 @@ static int vhost_vdpa_init_svq(struct vhost_dev *hdev, struct vhost_vdpa *v, + + shadow_vqs = g_ptr_array_new_full(hdev->nvqs, vhost_svq_free); + for (unsigned n = 0; n < hdev->nvqs; ++n) { +- g_autoptr(VhostShadowVirtqueue) svq = vhost_svq_new(); ++ g_autoptr(VhostShadowVirtqueue) svq = vhost_svq_new(v->iova_tree); + + if (unlikely(!svq)) { + error_setg(errp, "Cannot create svq %u", n); +@@ -809,33 +838,70 @@ static int vhost_vdpa_svq_set_fds(struct vhost_dev *dev, + /** + * Unmap a SVQ area in the device + */ +-static bool vhost_vdpa_svq_unmap_ring(struct vhost_vdpa *v, hwaddr iova, +- hwaddr size) ++static bool vhost_vdpa_svq_unmap_ring(struct vhost_vdpa *v, ++ const DMAMap *needle) + { ++ const DMAMap *result = vhost_iova_tree_find_iova(v->iova_tree, needle); ++ hwaddr size; + int r; + +- size = ROUND_UP(size, qemu_real_host_page_size); +- r = vhost_vdpa_dma_unmap(v, iova, size); ++ if (unlikely(!result)) { ++ error_report("Unable to find SVQ address to unmap"); ++ return false; ++ } ++ ++ size = ROUND_UP(result->size, qemu_real_host_page_size); ++ r = vhost_vdpa_dma_unmap(v, result->iova, size); + return r == 0; + } + + static bool vhost_vdpa_svq_unmap_rings(struct vhost_dev *dev, + const VhostShadowVirtqueue *svq) + { ++ DMAMap needle = {}; + struct vhost_vdpa *v = dev->opaque; + struct vhost_vring_addr svq_addr; +- size_t device_size = vhost_svq_device_area_size(svq); +- size_t driver_size = vhost_svq_driver_area_size(svq); + bool ok; + + vhost_svq_get_vring_addr(svq, &svq_addr); + +- ok = vhost_vdpa_svq_unmap_ring(v, svq_addr.desc_user_addr, driver_size); ++ needle.translated_addr = svq_addr.desc_user_addr; ++ ok = vhost_vdpa_svq_unmap_ring(v, &needle); + if (unlikely(!ok)) { + return false; + } + +- return vhost_vdpa_svq_unmap_ring(v, svq_addr.used_user_addr, device_size); ++ needle.translated_addr = svq_addr.used_user_addr; ++ return vhost_vdpa_svq_unmap_ring(v, &needle); ++} ++ ++/** ++ * Map the SVQ area in the device ++ * ++ * @v: Vhost-vdpa device ++ * @needle: The area to search iova ++ * @errorp: Error pointer ++ */ ++static bool vhost_vdpa_svq_map_ring(struct vhost_vdpa *v, DMAMap *needle, ++ Error **errp) ++{ ++ int r; ++ ++ r = vhost_iova_tree_map_alloc(v->iova_tree, needle); ++ if (unlikely(r != IOVA_OK)) { ++ error_setg(errp, "Cannot allocate iova (%d)", r); ++ return false; ++ } ++ ++ r = vhost_vdpa_dma_map(v, needle->iova, needle->size + 1, ++ (void *)(uintptr_t)needle->translated_addr, ++ needle->perm == IOMMU_RO); ++ if (unlikely(r != 0)) { ++ error_setg_errno(errp, -r, "Cannot map region to device"); ++ vhost_iova_tree_remove(v->iova_tree, needle); ++ } ++ ++ return r == 0; + } + + /** +@@ -851,28 +917,44 @@ static bool vhost_vdpa_svq_map_rings(struct vhost_dev *dev, + struct vhost_vring_addr *addr, + Error **errp) + { ++ DMAMap device_region, driver_region; ++ struct vhost_vring_addr svq_addr; + struct vhost_vdpa *v = dev->opaque; + size_t device_size = vhost_svq_device_area_size(svq); + size_t driver_size = vhost_svq_driver_area_size(svq); +- int r; ++ size_t avail_offset; ++ bool ok; + + ERRP_GUARD(); +- vhost_svq_get_vring_addr(svq, addr); ++ vhost_svq_get_vring_addr(svq, &svq_addr); + +- r = vhost_vdpa_dma_map(v, addr->desc_user_addr, driver_size, +- (void *)(uintptr_t)addr->desc_user_addr, true); +- if (unlikely(r != 0)) { +- error_setg_errno(errp, -r, "Cannot create vq driver region: "); ++ driver_region = (DMAMap) { ++ .translated_addr = svq_addr.desc_user_addr, ++ .size = driver_size - 1, ++ .perm = IOMMU_RO, ++ }; ++ ok = vhost_vdpa_svq_map_ring(v, &driver_region, errp); ++ if (unlikely(!ok)) { ++ error_prepend(errp, "Cannot create vq driver region: "); + return false; + } ++ addr->desc_user_addr = driver_region.iova; ++ avail_offset = svq_addr.avail_user_addr - svq_addr.desc_user_addr; ++ addr->avail_user_addr = driver_region.iova + avail_offset; + +- r = vhost_vdpa_dma_map(v, addr->used_user_addr, device_size, +- (void *)(intptr_t)addr->used_user_addr, false); +- if (unlikely(r != 0)) { +- error_setg_errno(errp, -r, "Cannot create vq device region: "); ++ device_region = (DMAMap) { ++ .translated_addr = svq_addr.used_user_addr, ++ .size = device_size - 1, ++ .perm = IOMMU_RW, ++ }; ++ ok = vhost_vdpa_svq_map_ring(v, &device_region, errp); ++ if (unlikely(!ok)) { ++ error_prepend(errp, "Cannot create vq device region: "); ++ vhost_vdpa_svq_unmap_ring(v, &driver_region); + } ++ addr->used_user_addr = device_region.iova; + +- return r == 0; ++ return ok; + } + + static bool vhost_vdpa_svq_setup(struct vhost_dev *dev, +diff --git a/include/hw/virtio/vhost-vdpa.h b/include/hw/virtio/vhost-vdpa.h +index 009a9f3b6b..ee8e939ad0 100644 +--- a/include/hw/virtio/vhost-vdpa.h ++++ b/include/hw/virtio/vhost-vdpa.h +@@ -14,6 +14,7 @@ + + #include + ++#include "hw/virtio/vhost-iova-tree.h" + #include "hw/virtio/virtio.h" + #include "standard-headers/linux/vhost_types.h" + +@@ -30,6 +31,8 @@ typedef struct vhost_vdpa { + MemoryListener listener; + struct vhost_vdpa_iova_range iova_range; + bool shadow_vqs_enabled; ++ /* IOVA mapping used by the Shadow Virtqueue */ ++ VhostIOVATree *iova_tree; + GPtrArray *shadow_vqs; + struct vhost_dev *dev; + VhostVDPAHostNotifier notifier[VIRTIO_QUEUE_MAX]; +-- +2.27.0 + diff --git a/vdpa-Add-device-migration-blocker.patch b/vdpa-Add-device-migration-blocker.patch new file mode 100644 index 00000000..85644d9c --- /dev/null +++ b/vdpa-Add-device-migration-blocker.patch @@ -0,0 +1,87 @@ +From 3f0eafe9e86bac9cf99176bf65a22d2dab154617 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= +Date: Wed, 20 Jul 2022 08:59:45 +0200 +Subject: [PATCH] vdpa: Add device migration blocker +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Since the vhost-vdpa device is exposing _F_LOG, adding a migration blocker if +it uses CVQ. + +However, qemu is able to migrate simple devices with no CVQ as long as +they use SVQ. To allow it, add a placeholder error to vhost_vdpa, and +only add to vhost_dev when used. vhost_dev machinery place the migration +blocker if needed. + +Signed-off-by: Eugenio Pérez +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Jason Wang +Signed-off-by: fangyi +--- + hw/virtio/vhost-vdpa.c | 15 +++++++++++++++ + include/hw/virtio/vhost-vdpa.h | 1 + + 2 files changed, 16 insertions(+) + +diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c +index 31b58aec59..5956ff4660 100644 +--- a/hw/virtio/vhost-vdpa.c ++++ b/hw/virtio/vhost-vdpa.c +@@ -20,6 +20,7 @@ + #include "hw/virtio/vhost-shadow-virtqueue.h" + #include "hw/virtio/vhost-vdpa.h" + #include "exec/address-spaces.h" ++#include "migration/blocker.h" + #include "qemu/main-loop.h" + #include "cpu.h" + #include "trace.h" +@@ -1024,6 +1025,13 @@ static bool vhost_vdpa_svqs_start(struct vhost_dev *dev) + return true; + } + ++ if (v->migration_blocker) { ++ int r = migrate_add_blocker(v->migration_blocker, &err); ++ if (unlikely(r < 0)) { ++ return false; ++ } ++ } ++ + for (i = 0; i < v->shadow_vqs->len; ++i) { + VirtQueue *vq = virtio_get_queue(dev->vdev, dev->vq_index + i); + VhostShadowVirtqueue *svq = g_ptr_array_index(v->shadow_vqs, i); +@@ -1066,6 +1074,10 @@ err: + vhost_svq_stop(svq); + } + ++ if (v->migration_blocker) { ++ migrate_del_blocker(v->migration_blocker); ++ } ++ + return false; + } + +@@ -1085,6 +1097,9 @@ static bool vhost_vdpa_svqs_stop(struct vhost_dev *dev) + } + } + ++ if (v->migration_blocker) { ++ migrate_del_blocker(v->migration_blocker); ++ } + return true; + } + +diff --git a/include/hw/virtio/vhost-vdpa.h b/include/hw/virtio/vhost-vdpa.h +index 1111d85643..d10a89303e 100644 +--- a/include/hw/virtio/vhost-vdpa.h ++++ b/include/hw/virtio/vhost-vdpa.h +@@ -35,6 +35,7 @@ typedef struct vhost_vdpa { + bool shadow_vqs_enabled; + /* IOVA mapping used by the Shadow Virtqueue */ + VhostIOVATree *iova_tree; ++ Error *migration_blocker; + GPtrArray *shadow_vqs; + const VhostShadowVirtqueueOps *shadow_vq_ops; + void *shadow_vq_ops_opaque; +-- +2.27.0 + diff --git a/vdpa-Add-missing-tracing-to-batch-mapping-functions.patch b/vdpa-Add-missing-tracing-to-batch-mapping-functions.patch new file mode 100644 index 00000000..b305d760 --- /dev/null +++ b/vdpa-Add-missing-tracing-to-batch-mapping-functions.patch @@ -0,0 +1,58 @@ +From d3aa8e2f948c0b3cd2cd723364fe968fd6befca9 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= +Date: Tue, 5 Apr 2022 08:36:28 +0200 +Subject: [PATCH] vdpa: Add missing tracing to batch mapping functions +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +These functions were not traced properly. + +Signed-off-by: Eugenio Pérez +Reviewed-by: Laurent Vivier +Reviewed-by: Stefano Garzarella +Acked-by: Jason Wang +Message-Id: <20220405063628.853745-1-eperezma@redhat.com> +Signed-off-by: Laurent Vivier +Signed-off-by: fangyi +--- + hw/virtio/trace-events | 2 ++ + hw/virtio/vhost-vdpa.c | 2 ++ + 2 files changed, 4 insertions(+) + +diff --git a/hw/virtio/trace-events b/hw/virtio/trace-events +index 650e521e35..37c1555330 100644 +--- a/hw/virtio/trace-events ++++ b/hw/virtio/trace-events +@@ -25,6 +25,8 @@ vhost_user_postcopy_waker_nomatch(const char *rb, uint64_t rb_offset) "%s + 0x%" + # vhost-vdpa.c + vhost_vdpa_dma_map(void *vdpa, int fd, uint32_t msg_type, uint64_t iova, uint64_t size, uint64_t uaddr, uint8_t perm, uint8_t type) "vdpa:%p fd: %d msg_type: %"PRIu32" iova: 0x%"PRIx64" size: 0x%"PRIx64" uaddr: 0x%"PRIx64" perm: 0x%"PRIx8" type: %"PRIu8 + vhost_vdpa_dma_unmap(void *vdpa, int fd, uint32_t msg_type, uint64_t iova, uint64_t size, uint8_t type) "vdpa:%p fd: %d msg_type: %"PRIu32" iova: 0x%"PRIx64" size: 0x%"PRIx64" type: %"PRIu8 ++vhost_vdpa_listener_begin_batch(void *v, int fd, uint32_t msg_type, uint8_t type) "vdpa:%p fd: %d msg_type: %"PRIu32" type: %"PRIu8 ++vhost_vdpa_listener_commit(void *v, int fd, uint32_t msg_type, uint8_t type) "vdpa:%p fd: %d msg_type: %"PRIu32" type: %"PRIu8 + vhost_vdpa_listener_region_add(void *vdpa, uint64_t iova, uint64_t llend, void *vaddr, bool readonly) "vdpa: %p iova 0x%"PRIx64" llend 0x%"PRIx64" vaddr: %p read-only: %d" + vhost_vdpa_listener_region_del(void *vdpa, uint64_t iova, uint64_t llend) "vdpa: %p iova 0x%"PRIx64" llend 0x%"PRIx64 + vhost_vdpa_add_status(void *dev, uint8_t status) "dev: %p status: 0x%"PRIx8 +diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c +index b66697da6e..022d70aefb 100644 +--- a/hw/virtio/vhost-vdpa.c ++++ b/hw/virtio/vhost-vdpa.c +@@ -131,6 +131,7 @@ static void vhost_vdpa_listener_begin_batch(struct vhost_vdpa *v) + .iotlb.type = VHOST_IOTLB_BATCH_BEGIN, + }; + ++ trace_vhost_vdpa_listener_begin_batch(v, fd, msg.type, msg.iotlb.type); + if (write(fd, &msg, sizeof(msg)) != sizeof(msg)) { + error_report("failed to write, fd=%d, errno=%d (%s)", + fd, errno, strerror(errno)); +@@ -165,6 +166,7 @@ static void vhost_vdpa_listener_commit(MemoryListener *listener) + msg.type = v->msg_type; + msg.iotlb.type = VHOST_IOTLB_BATCH_END; + ++ trace_vhost_vdpa_listener_commit(v, fd, msg.type, msg.iotlb.type); + if (write(fd, &msg, sizeof(msg)) != sizeof(msg)) { + error_report("failed to write, fd=%d, errno=%d (%s)", + fd, errno, strerror(errno)); +-- +2.27.0 + diff --git a/vdpa-Add-vhost_vdpa_net_load_mq.patch b/vdpa-Add-vhost_vdpa_net_load_mq.patch new file mode 100644 index 00000000..2b06bfd4 --- /dev/null +++ b/vdpa-Add-vhost_vdpa_net_load_mq.patch @@ -0,0 +1,65 @@ +From 6dc398327ebe7fcfe78b3df4fe9c1386bafef552 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= +Date: Tue, 6 Sep 2022 17:07:16 +0200 +Subject: [PATCH] vdpa: Add vhost_vdpa_net_load_mq +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Same way as with the MAC, restore the expected number of queues at +device's start. + +Signed-off-by: Eugenio Pérez +Signed-off-by: Jason Wang +Signed-off-by: fangyi +--- + net/vhost-vdpa.c | 26 ++++++++++++++++++++++++++ + 1 file changed, 26 insertions(+) + +diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c +index 15cd38b52e..b32fe5e68a 100644 +--- a/net/vhost-vdpa.c ++++ b/net/vhost-vdpa.c +@@ -408,6 +408,28 @@ static int vhost_vdpa_net_load_mac(VhostVDPAState *s, const VirtIONet *n) + return 0; + } + ++static int vhost_vdpa_net_load_mq(VhostVDPAState *s, ++ const VirtIONet *n) ++{ ++ struct virtio_net_ctrl_mq mq; ++ uint64_t features = n->parent_obj.guest_features; ++ ssize_t dev_written; ++ ++ if (!(features & BIT_ULL(VIRTIO_NET_F_MQ))) { ++ return 0; ++ } ++ ++ mq.virtqueue_pairs = cpu_to_le16(n->curr_queue_pairs); ++ dev_written = vhost_vdpa_net_load_cmd(s, VIRTIO_NET_CTRL_MQ, ++ VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET, &mq, ++ sizeof(mq)); ++ if (unlikely(dev_written < 0)) { ++ return dev_written; ++ } ++ ++ return *s->status != VIRTIO_NET_OK; ++} ++ + static int vhost_vdpa_net_load(NetClientState *nc) + { + VhostVDPAState *s = DO_UPCAST(VhostVDPAState, nc, nc); +@@ -426,6 +448,10 @@ static int vhost_vdpa_net_load(NetClientState *nc) + if (unlikely(r < 0)) { + return r; + } ++ r = vhost_vdpa_net_load_mq(s, n); ++ if (unlikely(r)) { ++ return r; ++ } + + return 0; + } +-- +2.27.0 + diff --git a/vdpa-Add-virtio-net-mac-address-via-CVQ-at-start.patch b/vdpa-Add-virtio-net-mac-address-via-CVQ-at-start.patch new file mode 100644 index 00000000..ad2ab280 --- /dev/null +++ b/vdpa-Add-virtio-net-mac-address-via-CVQ-at-start.patch @@ -0,0 +1,78 @@ +From 8df992cbd90fb742e14ea1a90211cf535f20fbaa Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= +Date: Tue, 23 Aug 2022 20:30:36 +0200 +Subject: [PATCH] vdpa: Add virtio-net mac address via CVQ at start +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This is needed so the destination vdpa device see the same state a the +guest set in the source. + +Signed-off-by: Eugenio Pérez +Acked-by: Jason Wang +Signed-off-by: Jason Wang +Signed-off-by: fangyi +--- + net/vhost-vdpa.c | 40 ++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 40 insertions(+) + +diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c +index b24e0919d0..561e43fa92 100644 +--- a/net/vhost-vdpa.c ++++ b/net/vhost-vdpa.c +@@ -371,11 +371,51 @@ static ssize_t vhost_vdpa_net_cvq_add(VhostVDPAState *s, size_t out_len, + return vhost_svq_poll(svq); + } + ++static int vhost_vdpa_net_load(NetClientState *nc) ++{ ++ VhostVDPAState *s = DO_UPCAST(VhostVDPAState, nc, nc); ++ const struct vhost_vdpa *v = &s->vhost_vdpa; ++ const VirtIONet *n; ++ uint64_t features; ++ ++ assert(nc->info->type == NET_CLIENT_DRIVER_VHOST_VDPA); ++ ++ if (!v->shadow_vqs_enabled) { ++ return 0; ++ } ++ ++ n = VIRTIO_NET(v->dev->vdev); ++ features = n->parent_obj.guest_features; ++ if (features & BIT_ULL(VIRTIO_NET_F_CTRL_MAC_ADDR)) { ++ const struct virtio_net_ctrl_hdr ctrl = { ++ .class = VIRTIO_NET_CTRL_MAC, ++ .cmd = VIRTIO_NET_CTRL_MAC_ADDR_SET, ++ }; ++ char *cursor = s->cvq_cmd_out_buffer; ++ ssize_t dev_written; ++ ++ memcpy(cursor, &ctrl, sizeof(ctrl)); ++ cursor += sizeof(ctrl); ++ memcpy(cursor, n->mac, sizeof(n->mac)); ++ ++ dev_written = vhost_vdpa_net_cvq_add(s, sizeof(ctrl) + sizeof(n->mac), ++ sizeof(virtio_net_ctrl_ack)); ++ if (unlikely(dev_written < 0)) { ++ return dev_written; ++ } ++ ++ return *((virtio_net_ctrl_ack *)s->cvq_cmd_in_buffer) != VIRTIO_NET_OK; ++ } ++ ++ return 0; ++} ++ + static NetClientInfo net_vhost_vdpa_cvq_info = { + .type = NET_CLIENT_DRIVER_VHOST_VDPA, + .size = sizeof(VhostVDPAState), + .receive = vhost_vdpa_receive, + .start = vhost_vdpa_net_cvq_start, ++ .load = vhost_vdpa_net_load, + .stop = vhost_vdpa_net_cvq_stop, + .cleanup = vhost_vdpa_cleanup, + .has_vnet_hdr = vhost_vdpa_has_vnet_hdr, +-- +2.27.0 + diff --git a/vdpa-Add-x-svq-to-NetdevVhostVDPAOptions.patch b/vdpa-Add-x-svq-to-NetdevVhostVDPAOptions.patch new file mode 100644 index 00000000..b97319d6 --- /dev/null +++ b/vdpa-Add-x-svq-to-NetdevVhostVDPAOptions.patch @@ -0,0 +1,208 @@ +From 3f278509424df64a731f69f4599460eda9a8d133 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= +Date: Wed, 20 Jul 2022 08:59:46 +0200 +Subject: [PATCH] vdpa: Add x-svq to NetdevVhostVDPAOptions +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Finally offering the possibility to enable SVQ from the command line. + +Signed-off-by: Eugenio Pérez +Acked-by: Markus Armbruster +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Jason Wang +Signed-off-by: fangyi +--- + net/vhost-vdpa.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++-- + qapi/net.json | 9 +++++- + 2 files changed, 77 insertions(+), 4 deletions(-) + +diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c +index 6a0fcab443..460f9674d7 100644 +--- a/net/vhost-vdpa.c ++++ b/net/vhost-vdpa.c +@@ -74,6 +74,28 @@ const int vdpa_feature_bits[] = { + VHOST_INVALID_FEATURE_BIT + }; + ++/** Supported device specific feature bits with SVQ */ ++static const uint64_t vdpa_svq_device_features = ++ BIT_ULL(VIRTIO_NET_F_CSUM) | ++ BIT_ULL(VIRTIO_NET_F_GUEST_CSUM) | ++ BIT_ULL(VIRTIO_NET_F_MTU) | ++ BIT_ULL(VIRTIO_NET_F_MAC) | ++ BIT_ULL(VIRTIO_NET_F_GUEST_TSO4) | ++ BIT_ULL(VIRTIO_NET_F_GUEST_TSO6) | ++ BIT_ULL(VIRTIO_NET_F_GUEST_ECN) | ++ BIT_ULL(VIRTIO_NET_F_GUEST_UFO) | ++ BIT_ULL(VIRTIO_NET_F_HOST_TSO4) | ++ BIT_ULL(VIRTIO_NET_F_HOST_TSO6) | ++ BIT_ULL(VIRTIO_NET_F_HOST_ECN) | ++ BIT_ULL(VIRTIO_NET_F_HOST_UFO) | ++ BIT_ULL(VIRTIO_NET_F_MRG_RXBUF) | ++ BIT_ULL(VIRTIO_NET_F_STATUS) | ++ BIT_ULL(VIRTIO_NET_F_CTRL_VQ) | ++ BIT_ULL(VIRTIO_F_ANY_LAYOUT) | ++ BIT_ULL(VIRTIO_NET_F_CTRL_MAC_ADDR) | ++ BIT_ULL(VIRTIO_NET_F_RSC_EXT) | ++ BIT_ULL(VIRTIO_NET_F_STANDBY); ++ + VHostNetState *vhost_vdpa_get_vhost_net(NetClientState *nc) + { + VhostVDPAState *s = DO_UPCAST(VhostVDPAState, nc, nc); +@@ -132,6 +154,7 @@ err_init: + static void vhost_vdpa_cleanup(NetClientState *nc) + { + VhostVDPAState *s = DO_UPCAST(VhostVDPAState, nc, nc); ++ struct vhost_dev *dev = &s->vhost_net->dev; + + /* + * If a peer NIC is attached, do not cleanup anything. +@@ -144,6 +167,9 @@ static void vhost_vdpa_cleanup(NetClientState *nc) + + qemu_vfree(s->cvq_cmd_out_buffer); + qemu_vfree(s->cvq_cmd_in_buffer); ++ if (dev->vq_index + dev->nvqs == dev->vq_index_end) { ++ g_clear_pointer(&s->vhost_vdpa.iova_tree, vhost_iova_tree_delete); ++ } + if (s->vhost_net) { + vhost_net_cleanup(s->vhost_net); + g_free(s->vhost_net); +@@ -445,7 +471,9 @@ static NetClientState *net_vhost_vdpa_init(NetClientState *peer, + int vdpa_device_fd, + int queue_pair_index, + int nvqs, +- bool is_datapath) ++ bool is_datapath, ++ bool svq, ++ VhostIOVATree *iova_tree) + { + NetClientState *nc = NULL; + VhostVDPAState *s; +@@ -463,6 +491,8 @@ static NetClientState *net_vhost_vdpa_init(NetClientState *peer, + + s->vhost_vdpa.device_fd = vdpa_device_fd; + s->vhost_vdpa.index = queue_pair_index; ++ s->vhost_vdpa.shadow_vqs_enabled = svq; ++ s->vhost_vdpa.iova_tree = iova_tree; + if (!is_datapath) { + s->cvq_cmd_out_buffer = qemu_memalign(qemu_real_host_page_size, + vhost_vdpa_net_cvq_cmd_page_len()); +@@ -473,6 +503,8 @@ static NetClientState *net_vhost_vdpa_init(NetClientState *peer, + + s->vhost_vdpa.shadow_vq_ops = &vhost_vdpa_net_svq_ops; + s->vhost_vdpa.shadow_vq_ops_opaque = s; ++ error_setg(&s->vhost_vdpa.migration_blocker, ++ "Migration disabled: vhost-vdpa uses CVQ."); + } + ret = vhost_vdpa_add(nc, (void *)&s->vhost_vdpa, queue_pair_index, nvqs); + if (ret) { +@@ -482,6 +514,14 @@ static NetClientState *net_vhost_vdpa_init(NetClientState *peer, + return nc; + } + ++static int vhost_vdpa_get_iova_range(int fd, ++ struct vhost_vdpa_iova_range *iova_range) ++{ ++ int ret = ioctl(fd, VHOST_VDPA_GET_IOVA_RANGE, iova_range); ++ ++ return ret < 0 ? -errno : 0; ++} ++ + static int vhost_vdpa_get_features(int fd, uint64_t *features, Error **errp) + { + int ret = ioctl(fd, VHOST_GET_FEATURES, features); +@@ -532,6 +572,7 @@ int net_init_vhost_vdpa(const Netdev *netdev, const char *name, + uint64_t features; + int vdpa_device_fd; + g_autofree NetClientState **ncs = NULL; ++ g_autoptr(VhostIOVATree) iova_tree = NULL; + NetClientState *nc; + int queue_pairs, r, i, has_cvq = 0; + +@@ -559,22 +600,45 @@ int net_init_vhost_vdpa(const Netdev *netdev, const char *name, + return queue_pairs; + } + ++ if (opts->x_svq) { ++ struct vhost_vdpa_iova_range iova_range; ++ ++ uint64_t invalid_dev_features = ++ features & ~vdpa_svq_device_features & ++ /* Transport are all accepted at this point */ ++ ~MAKE_64BIT_MASK(VIRTIO_TRANSPORT_F_START, ++ VIRTIO_TRANSPORT_F_END - VIRTIO_TRANSPORT_F_START); ++ ++ if (invalid_dev_features) { ++ error_setg(errp, "vdpa svq does not work with features 0x%" PRIx64, ++ invalid_dev_features); ++ goto err_svq; ++ } ++ ++ vhost_vdpa_get_iova_range(vdpa_device_fd, &iova_range); ++ iova_tree = vhost_iova_tree_new(iova_range.first, iova_range.last); ++ } ++ + ncs = g_malloc0(sizeof(*ncs) * queue_pairs); + + for (i = 0; i < queue_pairs; i++) { + ncs[i] = net_vhost_vdpa_init(peer, TYPE_VHOST_VDPA, name, +- vdpa_device_fd, i, 2, true); ++ vdpa_device_fd, i, 2, true, opts->x_svq, ++ iova_tree); + if (!ncs[i]) + goto err; + } + + if (has_cvq) { + nc = net_vhost_vdpa_init(peer, TYPE_VHOST_VDPA, name, +- vdpa_device_fd, i, 1, false); ++ vdpa_device_fd, i, 1, false, ++ opts->x_svq, iova_tree); + if (!nc) + goto err; + } + ++ /* iova_tree ownership belongs to last NetClientState */ ++ g_steal_pointer(&iova_tree); + return 0; + + err: +@@ -583,6 +647,8 @@ err: + qemu_del_net_client(ncs[i]); + } + } ++ ++err_svq: + qemu_close(vdpa_device_fd); + + return -1; +diff --git a/qapi/net.json b/qapi/net.json +index 7fab2e7cd8..6a5460ce56 100644 +--- a/qapi/net.json ++++ b/qapi/net.json +@@ -445,12 +445,19 @@ + # @queues: number of queues to be created for multiqueue vhost-vdpa + # (default: 1) + # ++# @x-svq: Start device with (experimental) shadow virtqueue. (Since 7.1) ++# (default: false) ++# ++# Features: ++# @unstable: Member @x-svq is experimental. ++# + # Since: 5.1 + ## + { 'struct': 'NetdevVhostVDPAOptions', + 'data': { + '*vhostdev': 'str', +- '*queues': 'int' } } ++ '*queues': 'int', ++ '*x-svq': {'type': 'bool', 'features' : [ 'unstable'] } } } + + ## + # @NetClientDriver: +-- +2.27.0 + diff --git a/vdpa-Allow-MQ-feature-in-SVQ.patch b/vdpa-Allow-MQ-feature-in-SVQ.patch new file mode 100644 index 00000000..7ebfa15a --- /dev/null +++ b/vdpa-Allow-MQ-feature-in-SVQ.patch @@ -0,0 +1,32 @@ +From 275135fcfb7e7c22ec84a79297ffc9c96fb82639 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= +Date: Tue, 6 Sep 2022 17:07:19 +0200 +Subject: [PATCH] vdpa: Allow MQ feature in SVQ +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Finally enable SVQ with MQ feature. + +Signed-off-by: Eugenio Pérez +Signed-off-by: Jason Wang +Signed-off-by: fangyi +--- + net/vhost-vdpa.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c +index 831709a270..479abf97a7 100644 +--- a/net/vhost-vdpa.c ++++ b/net/vhost-vdpa.c +@@ -93,6 +93,7 @@ static const uint64_t vdpa_svq_device_features = + BIT_ULL(VIRTIO_NET_F_MRG_RXBUF) | + BIT_ULL(VIRTIO_NET_F_STATUS) | + BIT_ULL(VIRTIO_NET_F_CTRL_VQ) | ++ BIT_ULL(VIRTIO_NET_F_MQ) | + BIT_ULL(VIRTIO_F_ANY_LAYOUT) | + BIT_ULL(VIRTIO_NET_F_CTRL_MAC_ADDR) | + BIT_ULL(VIRTIO_NET_F_RSC_EXT) | +-- +2.27.0 + diff --git a/vdpa-Avoid-compiler-to-squash-reads-to-used-idx.patch b/vdpa-Avoid-compiler-to-squash-reads-to-used-idx.patch new file mode 100644 index 00000000..64e5871e --- /dev/null +++ b/vdpa-Avoid-compiler-to-squash-reads-to-used-idx.patch @@ -0,0 +1,46 @@ +From 853f14a29c9a31ca132647770f7d6886103b2b77 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= +Date: Wed, 20 Jul 2022 08:59:29 +0200 +Subject: [PATCH] vdpa: Avoid compiler to squash reads to used idx +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +In the next patch we will allow busypolling of this value. The compiler +have a running path where shadow_used_idx, last_used_idx, and vring used +idx are not modified within the same thread busypolling. + +This was not an issue before since we always cleared device event +notifier before checking it, and that could act as memory barrier. +However, the busypoll needs something similar to kernel READ_ONCE. + +Let's add it here, sepparated from the polling. + +Signed-off-by: Eugenio Pérez +Signed-off-by: Jason Wang +Signed-off-by: fangyi +--- + hw/virtio/vhost-shadow-virtqueue.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/hw/virtio/vhost-shadow-virtqueue.c b/hw/virtio/vhost-shadow-virtqueue.c +index da1e1ce3c7..acf50a9a0b 100644 +--- a/hw/virtio/vhost-shadow-virtqueue.c ++++ b/hw/virtio/vhost-shadow-virtqueue.c +@@ -326,11 +326,12 @@ static void vhost_handle_guest_kick_notifier(EventNotifier *n) + + static bool vhost_svq_more_used(VhostShadowVirtqueue *svq) + { ++ uint16_t *used_idx = &svq->vring.used->idx; + if (svq->last_used_idx != svq->shadow_used_idx) { + return true; + } + +- svq->shadow_used_idx = cpu_to_le16(svq->vring.used->idx); ++ svq->shadow_used_idx = cpu_to_le16(*(volatile uint16_t *)used_idx); + + return svq->last_used_idx != svq->shadow_used_idx; + } +-- +2.27.0 + diff --git a/vdpa-Buffer-CVQ-support-on-shadow-virtqueue.patch b/vdpa-Buffer-CVQ-support-on-shadow-virtqueue.patch new file mode 100644 index 00000000..fdbcc5d8 --- /dev/null +++ b/vdpa-Buffer-CVQ-support-on-shadow-virtqueue.patch @@ -0,0 +1,305 @@ +From 31bf37b3097c1ece48b915137167bbd4bd7340aa Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= +Date: Wed, 20 Jul 2022 08:59:43 +0200 +Subject: [PATCH] vdpa: Buffer CVQ support on shadow virtqueue +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Introduce the control virtqueue support for vDPA shadow virtqueue. This +is needed for advanced networking features like rx filtering. + +Virtio-net control VQ copies the descriptors to qemu's VA, so we avoid +TOCTOU with the guest's or device's memory every time there is a device +model change. Otherwise, the guest could change the memory content in +the time between qemu and the device read it. + +To demonstrate command handling, VIRTIO_NET_F_CTRL_MACADDR is +implemented. If the virtio-net driver changes MAC the virtio-net device +model will be updated with the new one, and a rx filtering change event +will be raised. + +More cvq commands could be added here straightforwardly but they have +not been tested. + +Signed-off-by: Eugenio Pérez +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Jason Wang +Signed-off-by: fangyi +--- + net/vhost-vdpa.c | 214 +++++++++++++++++++++++++++++++++++++++++++++-- + 1 file changed, 206 insertions(+), 8 deletions(-) + +diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c +index 53a14bc756..2d928feefb 100644 +--- a/net/vhost-vdpa.c ++++ b/net/vhost-vdpa.c +@@ -32,6 +32,9 @@ typedef struct VhostVDPAState { + NetClientState nc; + struct vhost_vdpa vhost_vdpa; + VHostNetState *vhost_net; ++ ++ /* Control commands shadow buffers */ ++ void *cvq_cmd_out_buffer, *cvq_cmd_in_buffer; + bool started; + } VhostVDPAState; + +@@ -138,6 +141,9 @@ static void vhost_vdpa_cleanup(NetClientState *nc) + if (nc->peer && nc->peer->info->type == NET_CLIENT_DRIVER_NIC) { + return; + } ++ ++ qemu_vfree(s->cvq_cmd_out_buffer); ++ qemu_vfree(s->cvq_cmd_in_buffer); + if (s->vhost_net) { + vhost_net_cleanup(s->vhost_net); + g_free(s->vhost_net); +@@ -197,24 +203,191 @@ static NetClientInfo net_vhost_vdpa_info = { + .check_peer_type = vhost_vdpa_check_peer_type, + }; + ++static void vhost_vdpa_cvq_unmap_buf(struct vhost_vdpa *v, void *addr) ++{ ++ VhostIOVATree *tree = v->iova_tree; ++ DMAMap needle = { ++ /* ++ * No need to specify size or to look for more translations since ++ * this contiguous chunk was allocated by us. ++ */ ++ .translated_addr = (hwaddr)(uintptr_t)addr, ++ }; ++ const DMAMap *map = vhost_iova_tree_find_iova(tree, &needle); ++ int r; ++ ++ if (unlikely(!map)) { ++ error_report("Cannot locate expected map"); ++ return; ++ } ++ ++ r = vhost_vdpa_dma_unmap(v, map->iova, map->size + 1); ++ if (unlikely(r != 0)) { ++ error_report("Device cannot unmap: %s(%d)", g_strerror(r), r); ++ } ++ ++ vhost_iova_tree_remove(tree, map); ++} ++ ++static size_t vhost_vdpa_net_cvq_cmd_len(void) ++{ ++ /* ++ * MAC_TABLE_SET is the ctrl command that produces the longer out buffer. ++ * In buffer is always 1 byte, so it should fit here ++ */ ++ return sizeof(struct virtio_net_ctrl_hdr) + ++ 2 * sizeof(struct virtio_net_ctrl_mac) + ++ MAC_TABLE_ENTRIES * ETH_ALEN; ++} ++ ++static size_t vhost_vdpa_net_cvq_cmd_page_len(void) ++{ ++ return ROUND_UP(vhost_vdpa_net_cvq_cmd_len(), qemu_real_host_page_size); ++} ++ ++/** Copy and map a guest buffer. */ ++static bool vhost_vdpa_cvq_map_buf(struct vhost_vdpa *v, ++ const struct iovec *out_data, ++ size_t out_num, size_t data_len, void *buf, ++ size_t *written, bool write) ++{ ++ DMAMap map = {}; ++ int r; ++ ++ if (unlikely(!data_len)) { ++ qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid legnth of %s buffer\n", ++ __func__, write ? "in" : "out"); ++ return false; ++ } ++ ++ *written = iov_to_buf(out_data, out_num, 0, buf, data_len); ++ map.translated_addr = (hwaddr)(uintptr_t)buf; ++ map.size = vhost_vdpa_net_cvq_cmd_page_len() - 1; ++ map.perm = write ? IOMMU_RW : IOMMU_RO, ++ r = vhost_iova_tree_map_alloc(v->iova_tree, &map); ++ if (unlikely(r != IOVA_OK)) { ++ error_report("Cannot map injected element"); ++ return false; ++ } ++ ++ r = vhost_vdpa_dma_map(v, map.iova, vhost_vdpa_net_cvq_cmd_page_len(), buf, ++ !write); ++ if (unlikely(r < 0)) { ++ goto dma_map_err; ++ } ++ ++ return true; ++ ++dma_map_err: ++ vhost_iova_tree_remove(v->iova_tree, &map); ++ return false; ++} ++ + /** +- * Forward buffer for the moment. ++ * Copy the guest element into a dedicated buffer suitable to be sent to NIC ++ * ++ * @iov: [0] is the out buffer, [1] is the in one ++ */ ++static bool vhost_vdpa_net_cvq_map_elem(VhostVDPAState *s, ++ VirtQueueElement *elem, ++ struct iovec *iov) ++{ ++ size_t in_copied; ++ bool ok; ++ ++ iov[0].iov_base = s->cvq_cmd_out_buffer; ++ ok = vhost_vdpa_cvq_map_buf(&s->vhost_vdpa, elem->out_sg, elem->out_num, ++ vhost_vdpa_net_cvq_cmd_len(), iov[0].iov_base, ++ &iov[0].iov_len, false); ++ if (unlikely(!ok)) { ++ return false; ++ } ++ ++ iov[1].iov_base = s->cvq_cmd_in_buffer; ++ ok = vhost_vdpa_cvq_map_buf(&s->vhost_vdpa, NULL, 0, ++ sizeof(virtio_net_ctrl_ack), iov[1].iov_base, ++ &in_copied, true); ++ if (unlikely(!ok)) { ++ vhost_vdpa_cvq_unmap_buf(&s->vhost_vdpa, s->cvq_cmd_out_buffer); ++ return false; ++ } ++ ++ iov[1].iov_len = sizeof(virtio_net_ctrl_ack); ++ return true; ++} ++ ++/** ++ * Do not forward commands not supported by SVQ. Otherwise, the device could ++ * accept it and qemu would not know how to update the device model. ++ */ ++static bool vhost_vdpa_net_cvq_validate_cmd(const struct iovec *out, ++ size_t out_num) ++{ ++ struct virtio_net_ctrl_hdr ctrl; ++ size_t n; ++ ++ n = iov_to_buf(out, out_num, 0, &ctrl, sizeof(ctrl)); ++ if (unlikely(n < sizeof(ctrl))) { ++ qemu_log_mask(LOG_GUEST_ERROR, ++ "%s: invalid legnth of out buffer %zu\n", __func__, n); ++ return false; ++ } ++ ++ switch (ctrl.class) { ++ case VIRTIO_NET_CTRL_MAC: ++ switch (ctrl.cmd) { ++ case VIRTIO_NET_CTRL_MAC_ADDR_SET: ++ return true; ++ default: ++ qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid mac cmd %u\n", ++ __func__, ctrl.cmd); ++ }; ++ break; ++ default: ++ qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid control class %u\n", ++ __func__, ctrl.class); ++ }; ++ ++ return false; ++} ++ ++/** ++ * Validate and copy control virtqueue commands. ++ * ++ * Following QEMU guidelines, we offer a copy of the buffers to the device to ++ * prevent TOCTOU bugs. + */ + static int vhost_vdpa_net_handle_ctrl_avail(VhostShadowVirtqueue *svq, + VirtQueueElement *elem, + void *opaque) + { +- unsigned int n = elem->out_num + elem->in_num; +- g_autofree struct iovec *dev_buffers = g_new(struct iovec, n); ++ VhostVDPAState *s = opaque; + size_t in_len, dev_written; + virtio_net_ctrl_ack status = VIRTIO_NET_ERR; +- int r; ++ /* out and in buffers sent to the device */ ++ struct iovec dev_buffers[2] = { ++ { .iov_base = s->cvq_cmd_out_buffer }, ++ { .iov_base = s->cvq_cmd_in_buffer }, ++ }; ++ /* in buffer used for device model */ ++ const struct iovec in = { ++ .iov_base = &status, ++ .iov_len = sizeof(status), ++ }; ++ int r = -EINVAL; ++ bool ok; ++ ++ ok = vhost_vdpa_net_cvq_map_elem(s, elem, dev_buffers); ++ if (unlikely(!ok)) { ++ goto out; ++ } + +- memcpy(dev_buffers, elem->out_sg, elem->out_num); +- memcpy(dev_buffers + elem->out_num, elem->in_sg, elem->in_num); ++ ok = vhost_vdpa_net_cvq_validate_cmd(&dev_buffers[0], 1); ++ if (unlikely(!ok)) { ++ goto out; ++ } + +- r = vhost_svq_add(svq, &dev_buffers[0], elem->out_num, &dev_buffers[1], +- elem->in_num, elem); ++ r = vhost_svq_add(svq, &dev_buffers[0], 1, &dev_buffers[1], 1, elem); + if (unlikely(r != 0)) { + if (unlikely(r == -ENOSPC)) { + qemu_log_mask(LOG_GUEST_ERROR, "%s: No space on device queue\n", +@@ -231,6 +404,18 @@ static int vhost_vdpa_net_handle_ctrl_avail(VhostShadowVirtqueue *svq, + dev_written = vhost_svq_poll(svq); + if (unlikely(dev_written < sizeof(status))) { + error_report("Insufficient written data (%zu)", dev_written); ++ goto out; ++ } ++ ++ memcpy(&status, dev_buffers[1].iov_base, sizeof(status)); ++ if (status != VIRTIO_NET_OK) { ++ goto out; ++ } ++ ++ status = VIRTIO_NET_ERR; ++ virtio_net_handle_ctrl_iov(svq->vdev, &in, 1, dev_buffers, 1); ++ if (status != VIRTIO_NET_OK) { ++ error_report("Bad CVQ processing in model"); + } + + out: +@@ -241,6 +426,12 @@ out: + } + vhost_svq_push_elem(svq, elem, MIN(in_len, sizeof(status))); + g_free(elem); ++ if (dev_buffers[0].iov_base) { ++ vhost_vdpa_cvq_unmap_buf(&s->vhost_vdpa, dev_buffers[0].iov_base); ++ } ++ if (dev_buffers[1].iov_base) { ++ vhost_vdpa_cvq_unmap_buf(&s->vhost_vdpa, dev_buffers[1].iov_base); ++ } + return r; + } + +@@ -273,6 +464,13 @@ static NetClientState *net_vhost_vdpa_init(NetClientState *peer, + s->vhost_vdpa.device_fd = vdpa_device_fd; + s->vhost_vdpa.index = queue_pair_index; + if (!is_datapath) { ++ s->cvq_cmd_out_buffer = qemu_memalign(qemu_real_host_page_size, ++ vhost_vdpa_net_cvq_cmd_page_len()); ++ memset(s->cvq_cmd_out_buffer, 0, vhost_vdpa_net_cvq_cmd_page_len()); ++ s->cvq_cmd_in_buffer = qemu_memalign(qemu_real_host_page_size, ++ vhost_vdpa_net_cvq_cmd_page_len()); ++ memset(s->cvq_cmd_in_buffer, 0, vhost_vdpa_net_cvq_cmd_page_len()); ++ + s->vhost_vdpa.shadow_vq_ops = &vhost_vdpa_net_svq_ops; + s->vhost_vdpa.shadow_vq_ops_opaque = s; + } +-- +2.27.0 + diff --git a/vdpa-Delete-CVQ-migration-blocker.patch b/vdpa-Delete-CVQ-migration-blocker.patch new file mode 100644 index 00000000..568fb20d --- /dev/null +++ b/vdpa-Delete-CVQ-migration-blocker.patch @@ -0,0 +1,89 @@ +From cdc1b97f133a2b79318cc10aa6d1a9b69abac78f Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= +Date: Tue, 23 Aug 2022 20:30:37 +0200 +Subject: [PATCH] vdpa: Delete CVQ migration blocker +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +We can restore the device state in the destination via CVQ now. Remove +the migration blocker. + +Signed-off-by: Eugenio Pérez +Acked-by: Jason Wang +Signed-off-by: Jason Wang +Signed-off-by: fangyi +--- + hw/virtio/vhost-vdpa.c | 15 --------------- + include/hw/virtio/vhost-vdpa.h | 1 - + net/vhost-vdpa.c | 2 -- + 3 files changed, 18 deletions(-) + +diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c +index d7bdc0f37c..0f07c85b91 100644 +--- a/hw/virtio/vhost-vdpa.c ++++ b/hw/virtio/vhost-vdpa.c +@@ -1035,13 +1035,6 @@ static bool vhost_vdpa_svqs_start(struct vhost_dev *dev) + return true; + } + +- if (v->migration_blocker) { +- int r = migrate_add_blocker(v->migration_blocker, &err); +- if (unlikely(r < 0)) { +- return false; +- } +- } +- + for (i = 0; i < v->shadow_vqs->len; ++i) { + VirtQueue *vq = virtio_get_queue(dev->vdev, dev->vq_index + i); + VhostShadowVirtqueue *svq = g_ptr_array_index(v->shadow_vqs, i); +@@ -1084,10 +1077,6 @@ err: + vhost_svq_stop(svq); + } + +- if (v->migration_blocker) { +- migrate_del_blocker(v->migration_blocker); +- } +- + return false; + } + +@@ -1103,10 +1092,6 @@ static void vhost_vdpa_svqs_stop(struct vhost_dev *dev) + VhostShadowVirtqueue *svq = g_ptr_array_index(v->shadow_vqs, i); + vhost_vdpa_svq_unmap_rings(dev, svq); + } +- +- if (v->migration_blocker) { +- migrate_del_blocker(v->migration_blocker); +- } + } + + static int vhost_vdpa_dev_start(struct vhost_dev *dev, bool started) +diff --git a/include/hw/virtio/vhost-vdpa.h b/include/hw/virtio/vhost-vdpa.h +index d10a89303e..1111d85643 100644 +--- a/include/hw/virtio/vhost-vdpa.h ++++ b/include/hw/virtio/vhost-vdpa.h +@@ -35,7 +35,6 @@ typedef struct vhost_vdpa { + bool shadow_vqs_enabled; + /* IOVA mapping used by the Shadow Virtqueue */ + VhostIOVATree *iova_tree; +- Error *migration_blocker; + GPtrArray *shadow_vqs; + const VhostShadowVirtqueueOps *shadow_vq_ops; + void *shadow_vq_ops_opaque; +diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c +index 561e43fa92..b10a18aeb4 100644 +--- a/net/vhost-vdpa.c ++++ b/net/vhost-vdpa.c +@@ -563,8 +563,6 @@ static NetClientState *net_vhost_vdpa_init(NetClientState *peer, + + s->vhost_vdpa.shadow_vq_ops = &vhost_vdpa_net_svq_ops; + s->vhost_vdpa.shadow_vq_ops_opaque = s; +- error_setg(&s->vhost_vdpa.migration_blocker, +- "Migration disabled: vhost-vdpa uses CVQ."); + } + ret = vhost_vdpa_add(nc, (void *)&s->vhost_vdpa, queue_pair_index, nvqs); + if (ret) { +-- +2.27.0 + diff --git a/vdpa-Delete-duplicated-vdpa_feature_bits-entry.patch b/vdpa-Delete-duplicated-vdpa_feature_bits-entry.patch new file mode 100644 index 00000000..8a0b3658 --- /dev/null +++ b/vdpa-Delete-duplicated-vdpa_feature_bits-entry.patch @@ -0,0 +1,34 @@ +From e316083c41f99c424879622c6e79452a6878b32f Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= +Date: Thu, 20 Oct 2022 10:00:58 +0200 +Subject: [PATCH] vdpa: Delete duplicated vdpa_feature_bits entry +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This entry was duplicated on referenced commit. Removing it. + +Fixes: 402378407dbd ("vhost-vdpa: multiqueue support") +Signed-off-by: Eugenio Pérez +Acked-by: Jason Wang +Signed-off-by: Jason Wang +Signed-off-by: fangyi +--- + net/vhost-vdpa.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c +index 479abf97a7..f4f6b8587f 100644 +--- a/net/vhost-vdpa.c ++++ b/net/vhost-vdpa.c +@@ -62,7 +62,6 @@ const int vdpa_feature_bits[] = { + VIRTIO_NET_F_CTRL_RX, + VIRTIO_NET_F_CTRL_RX_EXTRA, + VIRTIO_NET_F_CTRL_VLAN, +- VIRTIO_NET_F_GUEST_ANNOUNCE, + VIRTIO_NET_F_CTRL_MAC_ADDR, + VIRTIO_NET_F_RSS, + VIRTIO_NET_F_MQ, +-- +2.27.0 + diff --git a/vdpa-Export-vhost_vdpa_dma_map-and-unmap-calls.patch b/vdpa-Export-vhost_vdpa_dma_map-and-unmap-calls.patch new file mode 100644 index 00000000..6fade985 --- /dev/null +++ b/vdpa-Export-vhost_vdpa_dma_map-and-unmap-calls.patch @@ -0,0 +1,65 @@ +From 4054b1e42fde8f22703d5fc9bc84a9179ee8f9f7 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= +Date: Wed, 20 Jul 2022 08:59:40 +0200 +Subject: [PATCH] vdpa: Export vhost_vdpa_dma_map and unmap calls +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Shadow CVQ will copy buffers on qemu VA, so we avoid TOCTOU attacks from +the guest that could set a different state in qemu device model and vdpa +device. + +To do so, it needs to be able to map these new buffers to the device. + +Signed-off-by: Eugenio Pérez +Acked-by: Jason Wang +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Jason Wang +Signed-off-by: fangyi +--- + hw/virtio/vhost-vdpa.c | 7 +++---- + include/hw/virtio/vhost-vdpa.h | 4 ++++ + 2 files changed, 7 insertions(+), 4 deletions(-) + +diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c +index a8d42655f0..8e962f511d 100644 +--- a/hw/virtio/vhost-vdpa.c ++++ b/hw/virtio/vhost-vdpa.c +@@ -73,8 +73,8 @@ static bool vhost_vdpa_listener_skipped_section(MemoryRegionSection *section, + return false; + } + +-static int vhost_vdpa_dma_map(struct vhost_vdpa *v, hwaddr iova, hwaddr size, +- void *vaddr, bool readonly) ++int vhost_vdpa_dma_map(struct vhost_vdpa *v, hwaddr iova, hwaddr size, ++ void *vaddr, bool readonly) + { + struct vhost_msg_v2 msg = {}; + int fd = v->device_fd; +@@ -99,8 +99,7 @@ static int vhost_vdpa_dma_map(struct vhost_vdpa *v, hwaddr iova, hwaddr size, + return ret; + } + +-static int vhost_vdpa_dma_unmap(struct vhost_vdpa *v, hwaddr iova, +- hwaddr size) ++int vhost_vdpa_dma_unmap(struct vhost_vdpa *v, hwaddr iova, hwaddr size) + { + struct vhost_msg_v2 msg = {}; + int fd = v->device_fd; +diff --git a/include/hw/virtio/vhost-vdpa.h b/include/hw/virtio/vhost-vdpa.h +index a29dbb3f53..7214eb47dc 100644 +--- a/include/hw/virtio/vhost-vdpa.h ++++ b/include/hw/virtio/vhost-vdpa.h +@@ -39,4 +39,8 @@ typedef struct vhost_vdpa { + VhostVDPAHostNotifier notifier[VIRTIO_QUEUE_MAX]; + } VhostVDPA; + ++int vhost_vdpa_dma_map(struct vhost_vdpa *v, hwaddr iova, hwaddr size, ++ void *vaddr, bool readonly); ++int vhost_vdpa_dma_unmap(struct vhost_vdpa *v, hwaddr iova, hwaddr size); ++ + #endif +-- +2.27.0 + diff --git a/vdpa-Expose-VHOST_F_LOG_ALL-on-SVQ.patch b/vdpa-Expose-VHOST_F_LOG_ALL-on-SVQ.patch new file mode 100644 index 00000000..610d4186 --- /dev/null +++ b/vdpa-Expose-VHOST_F_LOG_ALL-on-SVQ.patch @@ -0,0 +1,120 @@ +From a531a56bddf997f559f67fe9d3dc6d4258c82eb1 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= +Date: Mon, 14 Mar 2022 18:34:54 +0100 +Subject: [PATCH] vdpa: Expose VHOST_F_LOG_ALL on SVQ +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +SVQ is able to log the dirty bits by itself, so let's use it to not +block migration. + +Also, ignore set and clear of VHOST_F_LOG_ALL on set_features if SVQ is +enabled. Even if the device supports it, the reports would be nonsense +because SVQ memory is in the qemu region. + +The log region is still allocated. Future changes might skip that, but +this series is already long enough. + +Signed-off-by: Eugenio Pérez +Acked-by: Michael S. Tsirkin +Signed-off-by: Jason Wang +Signed-off-by: fangyi +--- + hw/virtio/vhost-vdpa.c | 39 ++++++++++++++++++++++++++++++---- + include/hw/virtio/vhost-vdpa.h | 1 + + 2 files changed, 36 insertions(+), 4 deletions(-) + +diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c +index 840141321a..3b5456cc0e 100644 +--- a/hw/virtio/vhost-vdpa.c ++++ b/hw/virtio/vhost-vdpa.c +@@ -375,6 +375,16 @@ static bool vhost_vdpa_one_time_request(struct vhost_dev *dev) + return v->index != 0; + } + ++static int vhost_vdpa_get_dev_features(struct vhost_dev *dev, ++ uint64_t *features) ++{ ++ int ret; ++ ++ ret = vhost_vdpa_call(dev, VHOST_GET_FEATURES, features); ++ trace_vhost_vdpa_get_features(dev, *features); ++ return ret; ++} ++ + static int vhost_vdpa_init_svq(struct vhost_dev *hdev, struct vhost_vdpa *v, + Error **errp) + { +@@ -387,7 +397,7 @@ static int vhost_vdpa_init_svq(struct vhost_dev *hdev, struct vhost_vdpa *v, + return 0; + } + +- r = hdev->vhost_ops->vhost_get_features(hdev, &dev_features); ++ r = vhost_vdpa_get_dev_features(hdev, &dev_features); + if (r != 0) { + error_setg_errno(errp, -r, "Can't get vdpa device features"); + return r; +@@ -612,12 +622,29 @@ static int vhost_vdpa_set_mem_table(struct vhost_dev *dev, + static int vhost_vdpa_set_features(struct vhost_dev *dev, + uint64_t features) + { ++ struct vhost_vdpa *v = dev->opaque; + int ret; + + if (vhost_vdpa_one_time_request(dev)) { + return 0; + } + ++ if (v->shadow_vqs_enabled) { ++ if ((v->acked_features ^ features) == BIT_ULL(VHOST_F_LOG_ALL)) { ++ /* ++ * QEMU is just trying to enable or disable logging. SVQ handles ++ * this sepparately, so no need to forward this. ++ */ ++ v->acked_features = features; ++ return 0; ++ } ++ ++ v->acked_features = features; ++ ++ /* We must not ack _F_LOG if SVQ is enabled */ ++ features &= ~BIT_ULL(VHOST_F_LOG_ALL); ++ } ++ + trace_vhost_vdpa_set_features(dev, features); + ret = vhost_vdpa_call(dev, VHOST_SET_FEATURES, &features); + if (ret) { +@@ -1202,10 +1229,14 @@ static int vhost_vdpa_set_vring_call(struct vhost_dev *dev, + static int vhost_vdpa_get_features(struct vhost_dev *dev, + uint64_t *features) + { +- int ret; ++ struct vhost_vdpa *v = dev->opaque; ++ int ret = vhost_vdpa_get_dev_features(dev, features); ++ ++ if (ret == 0 && v->shadow_vqs_enabled) { ++ /* Add SVQ logging capabilities */ ++ *features |= BIT_ULL(VHOST_F_LOG_ALL); ++ } + +- ret = vhost_vdpa_call(dev, VHOST_GET_FEATURES, features); +- trace_vhost_vdpa_get_features(dev, *features); + return ret; + } + +diff --git a/include/hw/virtio/vhost-vdpa.h b/include/hw/virtio/vhost-vdpa.h +index ee8e939ad0..a29dbb3f53 100644 +--- a/include/hw/virtio/vhost-vdpa.h ++++ b/include/hw/virtio/vhost-vdpa.h +@@ -30,6 +30,7 @@ typedef struct vhost_vdpa { + bool iotlb_batch_begin_sent; + MemoryListener listener; + struct vhost_vdpa_iova_range iova_range; ++ uint64_t acked_features; + bool shadow_vqs_enabled; + /* IOVA mapping used by the Shadow Virtqueue */ + VhostIOVATree *iova_tree; +-- +2.27.0 + diff --git a/vdpa-Extract-get-features-part-from-vhost_vdpa_get_m.patch b/vdpa-Extract-get-features-part-from-vhost_vdpa_get_m.patch new file mode 100644 index 00000000..9a2f3377 --- /dev/null +++ b/vdpa-Extract-get-features-part-from-vhost_vdpa_get_m.patch @@ -0,0 +1,89 @@ +From 29048bdf8848d527b39a383c7f0c4f8c60870f71 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= +Date: Wed, 20 Jul 2022 08:59:44 +0200 +Subject: [PATCH] vdpa: Extract get features part from + vhost_vdpa_get_max_queue_pairs +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +To know the device features is needed for CVQ SVQ, so SVQ knows if it +can handle all commands or not. Extract from +vhost_vdpa_get_max_queue_pairs so we can reuse it. + +Signed-off-by: Eugenio Pérez +Acked-by: Jason Wang +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Jason Wang +Signed-off-by: fangyi +--- + net/vhost-vdpa.c | 30 ++++++++++++++++++++---------- + 1 file changed, 20 insertions(+), 10 deletions(-) + +diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c +index 2d928feefb..6a0fcab443 100644 +--- a/net/vhost-vdpa.c ++++ b/net/vhost-vdpa.c +@@ -482,20 +482,24 @@ static NetClientState *net_vhost_vdpa_init(NetClientState *peer, + return nc; + } + +-static int vhost_vdpa_get_max_queue_pairs(int fd, int *has_cvq, Error **errp) ++static int vhost_vdpa_get_features(int fd, uint64_t *features, Error **errp) ++{ ++ int ret = ioctl(fd, VHOST_GET_FEATURES, features); ++ if (unlikely(ret < 0)) { ++ error_setg_errno(errp, errno, ++ "Fail to query features from vhost-vDPA device"); ++ } ++ return ret; ++} ++ ++static int vhost_vdpa_get_max_queue_pairs(int fd, uint64_t features, ++ int *has_cvq, Error **errp) + { + unsigned long config_size = offsetof(struct vhost_vdpa_config, buf); + g_autofree struct vhost_vdpa_config *config = NULL; + __virtio16 *max_queue_pairs; +- uint64_t features; + int ret; + +- ret = ioctl(fd, VHOST_GET_FEATURES, &features); +- if (ret) { +- error_setg(errp, "Fail to query features from vhost-vDPA device"); +- return ret; +- } +- + if (features & (1 << VIRTIO_NET_F_CTRL_VQ)) { + *has_cvq = 1; + } else { +@@ -525,10 +529,11 @@ int net_init_vhost_vdpa(const Netdev *netdev, const char *name, + NetClientState *peer, Error **errp) + { + const NetdevVhostVDPAOptions *opts; ++ uint64_t features; + int vdpa_device_fd; + g_autofree NetClientState **ncs = NULL; + NetClientState *nc; +- int queue_pairs, i, has_cvq = 0; ++ int queue_pairs, r, i, has_cvq = 0; + + assert(netdev->type == NET_CLIENT_DRIVER_VHOST_VDPA); + opts = &netdev->u.vhost_vdpa; +@@ -542,7 +547,12 @@ int net_init_vhost_vdpa(const Netdev *netdev, const char *name, + return -errno; + } + +- queue_pairs = vhost_vdpa_get_max_queue_pairs(vdpa_device_fd, ++ r = vhost_vdpa_get_features(vdpa_device_fd, &features, errp); ++ if (unlikely(r < 0)) { ++ return r; ++ } ++ ++ queue_pairs = vhost_vdpa_get_max_queue_pairs(vdpa_device_fd, features, + &has_cvq, errp); + if (queue_pairs < 0) { + qemu_close(vdpa_device_fd); +-- +2.27.0 + diff --git a/vdpa-Fix-bad-index-calculus-at-vhost_vdpa_get_vring_.patch b/vdpa-Fix-bad-index-calculus-at-vhost_vdpa_get_vring_.patch new file mode 100644 index 00000000..a156e6c8 --- /dev/null +++ b/vdpa-Fix-bad-index-calculus-at-vhost_vdpa_get_vring_.patch @@ -0,0 +1,41 @@ +From b37494d53478957b9e126e97f03d9501888a4d83 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= +Date: Thu, 12 May 2022 19:57:44 +0200 +Subject: [PATCH] vdpa: Fix bad index calculus at vhost_vdpa_get_vring_base +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Fixes: 6d0b222666 ("vdpa: Adapt vhost_vdpa_get_vring_base to SVQ") + +Acked-by: Jason Wang +Signed-off-by: Eugenio Pérez +Message-Id: <20220512175747.142058-4-eperezma@redhat.com> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Signed-off-by: fangyi +--- + hw/virtio/vhost-vdpa.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c +index 022d70aefb..3b67c9fd12 100644 +--- a/hw/virtio/vhost-vdpa.c ++++ b/hw/virtio/vhost-vdpa.c +@@ -1174,11 +1174,11 @@ static int vhost_vdpa_get_vring_base(struct vhost_dev *dev, + struct vhost_vring_state *ring) + { + struct vhost_vdpa *v = dev->opaque; ++ int vdpa_idx = ring->index - dev->vq_index; + int ret; + + if (v->shadow_vqs_enabled) { +- VhostShadowVirtqueue *svq = g_ptr_array_index(v->shadow_vqs, +- ring->index); ++ VhostShadowVirtqueue *svq = g_ptr_array_index(v->shadow_vqs, vdpa_idx); + + /* + * Setting base as last used idx, so destination will see as available +-- +2.27.0 + diff --git a/vdpa-Fix-file-descriptor-leak-on-get-features-error.patch b/vdpa-Fix-file-descriptor-leak-on-get-features-error.patch new file mode 100644 index 00000000..6436bab1 --- /dev/null +++ b/vdpa-Fix-file-descriptor-leak-on-get-features-error.patch @@ -0,0 +1,50 @@ +From 4077ce7f2d21dc67d18dc444165859b8496a185e Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= +Date: Tue, 2 Aug 2022 13:24:46 +0200 +Subject: [PATCH] vdpa: Fix file descriptor leak on get features error +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +File descriptor vdpa_device_fd is not free in the case of returning +error from vhost_vdpa_get_features. Fixing it by making all errors go to +the same error path. + +Resolves: Coverity CID 1490785 +Fixes: 8170ab3f43 ("vdpa: Extract get features part from vhost_vdpa_get_max_queue_pairs") + +Signed-off-by: Eugenio Pérez +Reviewed-by: Laurent Vivier +Reviewed-by: Michael S. Tsirkin +Message-Id: <20220802112447.249436-2-eperezma@redhat.com> +Signed-off-by: Laurent Vivier +Signed-off-by: fangyi +--- + net/vhost-vdpa.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c +index 460f9674d7..0f75aa6080 100644 +--- a/net/vhost-vdpa.c ++++ b/net/vhost-vdpa.c +@@ -574,7 +574,7 @@ int net_init_vhost_vdpa(const Netdev *netdev, const char *name, + g_autofree NetClientState **ncs = NULL; + g_autoptr(VhostIOVATree) iova_tree = NULL; + NetClientState *nc; +- int queue_pairs, r, i, has_cvq = 0; ++ int queue_pairs, r, i = 0, has_cvq = 0; + + assert(netdev->type == NET_CLIENT_DRIVER_VHOST_VDPA); + opts = &netdev->u.vhost_vdpa; +@@ -590,7 +590,7 @@ int net_init_vhost_vdpa(const Netdev *netdev, const char *name, + + r = vhost_vdpa_get_features(vdpa_device_fd, &features, errp); + if (unlikely(r < 0)) { +- return r; ++ goto err; + } + + queue_pairs = vhost_vdpa_get_max_queue_pairs(vdpa_device_fd, features, +-- +2.27.0 + diff --git a/vdpa-Fix-index-calculus-at-vhost_vdpa_svqs_start.patch b/vdpa-Fix-index-calculus-at-vhost_vdpa_svqs_start.patch new file mode 100644 index 00000000..69f14963 --- /dev/null +++ b/vdpa-Fix-index-calculus-at-vhost_vdpa_svqs_start.patch @@ -0,0 +1,37 @@ +From 2f19a3fd1fbaca215906199ab7da7cd961b68d65 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= +Date: Thu, 12 May 2022 19:57:45 +0200 +Subject: [PATCH] vdpa: Fix index calculus at vhost_vdpa_svqs_start +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +With the introduction of MQ the index of the vq needs to be calculated +with the device model vq_index. + +Signed-off-by: Eugenio Pérez +Acked-by: Jason Wang +Message-Id: <20220512175747.142058-5-eperezma@redhat.com> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Signed-off-by: fangyi +--- + hw/virtio/vhost-vdpa.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c +index 3b67c9fd12..1360f2eaf7 100644 +--- a/hw/virtio/vhost-vdpa.c ++++ b/hw/virtio/vhost-vdpa.c +@@ -1020,7 +1020,7 @@ static bool vhost_vdpa_svqs_start(struct vhost_dev *dev) + VirtQueue *vq = virtio_get_queue(dev->vdev, dev->vq_index + i); + VhostShadowVirtqueue *svq = g_ptr_array_index(v->shadow_vqs, i); + struct vhost_vring_addr addr = { +- .index = i, ++ .index = dev->vq_index + i, + }; + int r; + bool ok = vhost_vdpa_svq_setup(dev, svq, i, &err); +-- +2.27.0 + diff --git a/vdpa-Fix-memory-listener-deletions-of-iova-tree.patch b/vdpa-Fix-memory-listener-deletions-of-iova-tree.patch new file mode 100644 index 00000000..bba1ee0f --- /dev/null +++ b/vdpa-Fix-memory-listener-deletions-of-iova-tree.patch @@ -0,0 +1,53 @@ +From de9a72905ad70e256a73608c92f50c3862b8eb8e Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= +Date: Fri, 22 Jul 2022 10:26:30 +0200 +Subject: [PATCH] vdpa: Fix memory listener deletions of iova tree +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +vhost_vdpa_listener_region_del is always deleting the first iova entry +of the tree, since it's using the needle iova instead of the result's +one. + +This was detected using a vga virtual device in the VM using vdpa SVQ. +It makes some extra memory adding and deleting, so the wrong one was +mapped / unmapped. This was undetected before since all the memory was +mappend and unmapped totally without that device, but other conditions +could trigger it too: + +* mem_region was with .iova = 0, .translated_addr = (correct GPA). +* iova_tree_find_iova returned right result, but does not update + mem_region. +* iova_tree_remove always removed region with .iova = 0. Right iova were + sent to the device. +* Next map will fill the first region with .iova = 0, causing a mapping + with the same iova and device complains, if the next action is a map. +* Next unmap will cause to try to unmap again iova = 0, causing the + device to complain that no region was mapped at iova = 0. + +Fixes: 34e3c94edaef ("vdpa: Add custom IOTLB translations to SVQ") +Reported-by: Lei Yang +Signed-off-by: Eugenio Pérez +Signed-off-by: Jason Wang +Signed-off-by: fangyi +--- + hw/virtio/vhost-vdpa.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c +index 6304f174c2..d0cf7a0745 100644 +--- a/hw/virtio/vhost-vdpa.c ++++ b/hw/virtio/vhost-vdpa.c +@@ -292,7 +292,7 @@ static void vhost_vdpa_listener_region_del(MemoryListener *listener, + + result = vhost_iova_tree_find_iova(v->iova_tree, &mem_region); + iova = result->iova; +- vhost_iova_tree_remove(v->iova_tree, &mem_region); ++ vhost_iova_tree_remove(v->iova_tree, result); + } + vhost_vdpa_iotlb_batch_begin_once(v); + ret = vhost_vdpa_dma_unmap(v, iova, int128_get64(llsize)); +-- +2.27.0 + diff --git a/vdpa-Fix-possible-use-after-free-for-VirtQueueElemen.patch b/vdpa-Fix-possible-use-after-free-for-VirtQueueElemen.patch new file mode 100644 index 00000000..925cb9ef --- /dev/null +++ b/vdpa-Fix-possible-use-after-free-for-VirtQueueElemen.patch @@ -0,0 +1,63 @@ +From c8d132a62f026e51c2fb1f87dbf40aad8080fa9a Mon Sep 17 00:00:00 2001 +From: Hawkins Jiawei +Date: Sat, 8 Jul 2023 00:44:42 +0800 +Subject: [PATCH] vdpa: Fix possible use-after-free for VirtQueueElement +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +QEMU uses vhost_handle_guest_kick() to forward guest's available +buffers to the vdpa device in SVQ avail ring. + +In vhost_handle_guest_kick(), a `g_autofree` `elem` is used to +iterate through the available VirtQueueElements. This `elem` is +then passed to `svq->ops->avail_handler`, specifically to the +vhost_vdpa_net_handle_ctrl_avail(). If this handler fails to +process the CVQ command, vhost_handle_guest_kick() regains +ownership of the `elem`, and either frees it or requeues it. + +Yet the problem is that, vhost_vdpa_net_handle_ctrl_avail() +mistakenly frees the `elem`, even if it fails to forward the +CVQ command to vdpa device. This can result in a use-after-free +for the `elem` in vhost_handle_guest_kick(). + +This patch solves this problem by refactoring +vhost_vdpa_net_handle_ctrl_avail() to only freeing the `elem` if +it owns it. + +Fixes: bd907ae4b0 ("vdpa: manual forward CVQ buffers") +Signed-off-by: Hawkins Jiawei +Message-Id: +Reviewed-by: Eugenio Pérez +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Signed-off-by: fangyi +--- + net/vhost-vdpa.c | 11 ++++++++++- + 1 file changed, 10 insertions(+), 1 deletion(-) + +diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c +index fd5dc8c6aa..94f74b54ae 100644 +--- a/net/vhost-vdpa.c ++++ b/net/vhost-vdpa.c +@@ -658,7 +658,16 @@ out: + error_report("Bad device CVQ written length"); + } + vhost_svq_push_elem(svq, elem, MIN(in_len, sizeof(status))); +- g_free(elem); ++ /* ++ * `elem` belongs to vhost_vdpa_net_handle_ctrl_avail() only when ++ * the function successfully forwards the CVQ command, indicated ++ * by a non-negative value of `dev_written`. Otherwise, it still ++ * belongs to SVQ. ++ * This function should only free the `elem` when it owns. ++ */ ++ if (dev_written >= 0) { ++ g_free(elem); ++ } + return dev_written < 0 ? dev_written : 0; + } + +-- +2.27.0 + diff --git a/vdpa-Make-SVQ-vring-unmapping-return-void.patch b/vdpa-Make-SVQ-vring-unmapping-return-void.patch new file mode 100644 index 00000000..589898bd --- /dev/null +++ b/vdpa-Make-SVQ-vring-unmapping-return-void.patch @@ -0,0 +1,124 @@ +From 39de24fc2b1cd16e8810b9e26cd23bb3896982a4 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= +Date: Tue, 23 Aug 2022 20:20:06 +0200 +Subject: [PATCH] vdpa: Make SVQ vring unmapping return void +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Nothing actually reads the return value, but an error in cleaning some +entries could cause device stop to abort, making a restart impossible. +Better ignore explicitely the return value. + +Reported-by: Lei Yang +Fixes: 34e3c94eda ("vdpa: Add custom IOTLB translations to SVQ") +Signed-off-by: Eugenio Pérez +Acked-by: Jason Wang +Signed-off-by: Jason Wang +Signed-off-by: fangyi +--- + hw/virtio/vhost-vdpa.c | 32 ++++++++++---------------------- + 1 file changed, 10 insertions(+), 22 deletions(-) + +diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c +index 3be6988e9c..31c1b71498 100644 +--- a/hw/virtio/vhost-vdpa.c ++++ b/hw/virtio/vhost-vdpa.c +@@ -886,7 +886,7 @@ static int vhost_vdpa_svq_set_fds(struct vhost_dev *dev, + /** + * Unmap a SVQ area in the device + */ +-static bool vhost_vdpa_svq_unmap_ring(struct vhost_vdpa *v, ++static void vhost_vdpa_svq_unmap_ring(struct vhost_vdpa *v, + const DMAMap *needle) + { + const DMAMap *result = vhost_iova_tree_find_iova(v->iova_tree, needle); +@@ -895,38 +895,33 @@ static bool vhost_vdpa_svq_unmap_ring(struct vhost_vdpa *v, + + if (unlikely(!result)) { + error_report("Unable to find SVQ address to unmap"); +- return false; ++ return; + } + + size = ROUND_UP(result->size, qemu_real_host_page_size); + r = vhost_vdpa_dma_unmap(v, result->iova, size); + if (unlikely(r < 0)) { + error_report("Unable to unmap SVQ vring: %s (%d)", g_strerror(-r), -r); +- return false; ++ return; + } + + vhost_iova_tree_remove(v->iova_tree, *result); +- return r == 0; + } + +-static bool vhost_vdpa_svq_unmap_rings(struct vhost_dev *dev, ++static void vhost_vdpa_svq_unmap_rings(struct vhost_dev *dev, + const VhostShadowVirtqueue *svq) + { + DMAMap needle = {}; + struct vhost_vdpa *v = dev->opaque; + struct vhost_vring_addr svq_addr; +- bool ok; + + vhost_svq_get_vring_addr(svq, &svq_addr); + + needle.translated_addr = svq_addr.desc_user_addr; +- ok = vhost_vdpa_svq_unmap_ring(v, &needle); +- if (unlikely(!ok)) { +- return false; +- } ++ vhost_vdpa_svq_unmap_ring(v, &needle); + + needle.translated_addr = svq_addr.used_user_addr; +- return vhost_vdpa_svq_unmap_ring(v, &needle); ++ vhost_vdpa_svq_unmap_ring(v, &needle); + } + + /** +@@ -1097,26 +1092,22 @@ err: + return false; + } + +-static bool vhost_vdpa_svqs_stop(struct vhost_dev *dev) ++static void vhost_vdpa_svqs_stop(struct vhost_dev *dev) + { + struct vhost_vdpa *v = dev->opaque; + + if (!v->shadow_vqs) { +- return true; ++ return; + } + + for (unsigned i = 0; i < v->shadow_vqs->len; ++i) { + VhostShadowVirtqueue *svq = g_ptr_array_index(v->shadow_vqs, i); +- bool ok = vhost_vdpa_svq_unmap_rings(dev, svq); +- if (unlikely(!ok)) { +- return false; +- } ++ vhost_vdpa_svq_unmap_rings(dev, svq); + } + + if (v->migration_blocker) { + migrate_del_blocker(v->migration_blocker); + } +- return true; + } + + static int vhost_vdpa_dev_start(struct vhost_dev *dev, bool started) +@@ -1133,10 +1124,7 @@ static int vhost_vdpa_dev_start(struct vhost_dev *dev, bool started) + } + vhost_vdpa_set_vring_ready(dev); + } else { +- ok = vhost_vdpa_svqs_stop(dev); +- if (unlikely(!ok)) { +- return -1; +- } ++ vhost_vdpa_svqs_stop(dev); + vhost_vdpa_host_notifiers_uninit(dev, dev->nvqs); + } + +-- +2.27.0 + diff --git a/vdpa-Make-VhostVDPAState-cvq_cmd_in_buffer-control-a.patch b/vdpa-Make-VhostVDPAState-cvq_cmd_in_buffer-control-a.patch new file mode 100644 index 00000000..d9efa497 --- /dev/null +++ b/vdpa-Make-VhostVDPAState-cvq_cmd_in_buffer-control-a.patch @@ -0,0 +1,103 @@ +From fdb55acf1833e6a35171b4e7e1c357f4b133e26f Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= +Date: Tue, 6 Sep 2022 17:07:14 +0200 +Subject: [PATCH] vdpa: Make VhostVDPAState cvq_cmd_in_buffer control ack type +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This allows to simplify the code. Rename to status while we're at it. + +Signed-off-by: Eugenio Pérez +Signed-off-by: Jason Wang +Signed-off-by: fangyi +--- + net/vhost-vdpa.c | 23 ++++++++++++----------- + 1 file changed, 12 insertions(+), 11 deletions(-) + +diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c +index b10a18aeb4..2700ef656f 100644 +--- a/net/vhost-vdpa.c ++++ b/net/vhost-vdpa.c +@@ -34,7 +34,9 @@ typedef struct VhostVDPAState { + VHostNetState *vhost_net; + + /* Control commands shadow buffers */ +- void *cvq_cmd_out_buffer, *cvq_cmd_in_buffer; ++ void *cvq_cmd_out_buffer; ++ virtio_net_ctrl_ack *status; ++ + bool started; + } VhostVDPAState; + +@@ -166,7 +168,7 @@ static void vhost_vdpa_cleanup(NetClientState *nc) + } + + qemu_vfree(s->cvq_cmd_out_buffer); +- qemu_vfree(s->cvq_cmd_in_buffer); ++ qemu_vfree(s->status); + if (dev->vq_index + dev->nvqs == dev->vq_index_end) { + g_clear_pointer(&s->vhost_vdpa.iova_tree, vhost_iova_tree_delete); + } +@@ -318,7 +320,7 @@ static int vhost_vdpa_net_cvq_start(NetClientState *nc) + return r; + } + +- r = vhost_vdpa_cvq_map_buf(&s->vhost_vdpa, s->cvq_cmd_in_buffer, ++ r = vhost_vdpa_cvq_map_buf(&s->vhost_vdpa, s->status, + vhost_vdpa_net_cvq_cmd_page_len(), true); + if (unlikely(r < 0)) { + vhost_vdpa_cvq_unmap_buf(&s->vhost_vdpa, s->cvq_cmd_out_buffer); +@@ -335,7 +337,7 @@ static void vhost_vdpa_net_cvq_stop(NetClientState *nc) + + if (s->vhost_vdpa.shadow_vqs_enabled) { + vhost_vdpa_cvq_unmap_buf(&s->vhost_vdpa, s->cvq_cmd_out_buffer); +- vhost_vdpa_cvq_unmap_buf(&s->vhost_vdpa, s->cvq_cmd_in_buffer); ++ vhost_vdpa_cvq_unmap_buf(&s->vhost_vdpa, s->status); + } + } + +@@ -348,7 +350,7 @@ static ssize_t vhost_vdpa_net_cvq_add(VhostVDPAState *s, size_t out_len, + .iov_len = out_len, + }; + const struct iovec in = { +- .iov_base = s->cvq_cmd_in_buffer, ++ .iov_base = s->status, + .iov_len = sizeof(virtio_net_ctrl_ack), + }; + VhostShadowVirtqueue *svq = g_ptr_array_index(s->vhost_vdpa.shadow_vqs, 0); +@@ -404,7 +406,7 @@ static int vhost_vdpa_net_load(NetClientState *nc) + return dev_written; + } + +- return *((virtio_net_ctrl_ack *)s->cvq_cmd_in_buffer) != VIRTIO_NET_OK; ++ return *s->status != VIRTIO_NET_OK; + } + + return 0; +@@ -499,8 +501,7 @@ static int vhost_vdpa_net_handle_ctrl_avail(VhostShadowVirtqueue *svq, + goto out; + } + +- memcpy(&status, s->cvq_cmd_in_buffer, sizeof(status)); +- if (status != VIRTIO_NET_OK) { ++ if (*s->status != VIRTIO_NET_OK) { + return VIRTIO_NET_ERR; + } + +@@ -557,9 +558,9 @@ static NetClientState *net_vhost_vdpa_init(NetClientState *peer, + s->cvq_cmd_out_buffer = qemu_memalign(qemu_real_host_page_size, + vhost_vdpa_net_cvq_cmd_page_len()); + memset(s->cvq_cmd_out_buffer, 0, vhost_vdpa_net_cvq_cmd_page_len()); +- s->cvq_cmd_in_buffer = qemu_memalign(qemu_real_host_page_size, +- vhost_vdpa_net_cvq_cmd_page_len()); +- memset(s->cvq_cmd_in_buffer, 0, vhost_vdpa_net_cvq_cmd_page_len()); ++ s->status = qemu_memalign(qemu_real_host_page_size, ++ vhost_vdpa_net_cvq_cmd_page_len()); ++ memset(s->status, 0, vhost_vdpa_net_cvq_cmd_page_len()); + + s->vhost_vdpa.shadow_vq_ops = &vhost_vdpa_net_svq_ops; + s->vhost_vdpa.shadow_vq_ops_opaque = s; +-- +2.27.0 + diff --git a/vdpa-Make-ncs-autofree.patch b/vdpa-Make-ncs-autofree.patch new file mode 100644 index 00000000..e2b8775f --- /dev/null +++ b/vdpa-Make-ncs-autofree.patch @@ -0,0 +1,54 @@ +From 1f1c2f74668cd1250cbd00b397dd59be92121314 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= +Date: Mon, 14 Feb 2022 20:34:15 +0100 +Subject: [PATCH] vdpa: Make ncs autofree +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Simplifying memory management. + +Signed-off-by: Eugenio Pérez +Acked-by: Jason Wang +Reviewed-by: Stefano Garzarella +Reviewed-by: Philippe Mathieu-Daudé +Message-Id: <20220214193415.1606752-2-eperezma@redhat.com> +Signed-off-by: Laurent Vivier +Signed-off-by: fangyi +--- + net/vhost-vdpa.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c +index 60b715aef1..9ba0f7bfca 100644 +--- a/net/vhost-vdpa.c ++++ b/net/vhost-vdpa.c +@@ -271,7 +271,8 @@ int net_init_vhost_vdpa(const Netdev *netdev, const char *name, + { + const NetdevVhostVDPAOptions *opts; + int vdpa_device_fd; +- NetClientState **ncs, *nc; ++ g_autofree NetClientState **ncs = NULL; ++ NetClientState *nc; + int queue_pairs, i, has_cvq = 0; + + assert(netdev->type == NET_CLIENT_DRIVER_VHOST_VDPA); +@@ -309,7 +310,6 @@ int net_init_vhost_vdpa(const Netdev *netdev, const char *name, + goto err; + } + +- g_free(ncs); + return 0; + + err: +@@ -317,7 +317,6 @@ err: + qemu_del_net_client(ncs[0]); + } + qemu_close(vdpa_device_fd); +- g_free(ncs); + + return -1; + } +-- +2.27.0 + diff --git a/vdpa-Move-command-buffers-map-to-start-of-net-device.patch b/vdpa-Move-command-buffers-map-to-start-of-net-device.patch new file mode 100644 index 00000000..5b943d29 --- /dev/null +++ b/vdpa-Move-command-buffers-map-to-start-of-net-device.patch @@ -0,0 +1,242 @@ +From 811a2e0b40724cc505141d4caf322030b83f86a3 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= +Date: Tue, 23 Aug 2022 20:30:33 +0200 +Subject: [PATCH] vdpa: Move command buffers map to start of net device +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +As this series will reuse them to restore the device state at the end of +a migration (or a device start), let's allocate only once at the device +start so we don't duplicate their map and unmap. + +Signed-off-by: Eugenio Pérez +Acked-by: Jason Wang +Signed-off-by: Jason Wang +Signed-off-by: fangyi +--- + net/vhost-vdpa.c | 123 ++++++++++++++++++++++------------------------- + 1 file changed, 58 insertions(+), 65 deletions(-) + +diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c +index 04cb08d418..882f5ee89c 100644 +--- a/net/vhost-vdpa.c ++++ b/net/vhost-vdpa.c +@@ -271,29 +271,20 @@ static size_t vhost_vdpa_net_cvq_cmd_page_len(void) + return ROUND_UP(vhost_vdpa_net_cvq_cmd_len(), qemu_real_host_page_size); + } + +-/** Copy and map a guest buffer. */ +-static bool vhost_vdpa_cvq_map_buf(struct vhost_vdpa *v, +- const struct iovec *out_data, +- size_t out_num, size_t data_len, void *buf, +- size_t *written, bool write) ++/** Map CVQ buffer. */ ++static int vhost_vdpa_cvq_map_buf(struct vhost_vdpa *v, void *buf, size_t size, ++ bool write) + { + DMAMap map = {}; + int r; + +- if (unlikely(!data_len)) { +- qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid legnth of %s buffer\n", +- __func__, write ? "in" : "out"); +- return false; +- } +- +- *written = iov_to_buf(out_data, out_num, 0, buf, data_len); + map.translated_addr = (hwaddr)(uintptr_t)buf; +- map.size = vhost_vdpa_net_cvq_cmd_page_len() - 1; ++ map.size = size - 1; + map.perm = write ? IOMMU_RW : IOMMU_RO, + r = vhost_iova_tree_map_alloc(v->iova_tree, &map); + if (unlikely(r != IOVA_OK)) { + error_report("Cannot map injected element"); +- return false; ++ return r; + } + + r = vhost_vdpa_dma_map(v, map.iova, vhost_vdpa_net_cvq_cmd_page_len(), buf, +@@ -302,50 +293,58 @@ static bool vhost_vdpa_cvq_map_buf(struct vhost_vdpa *v, + goto dma_map_err; + } + +- return true; ++ return 0; + + dma_map_err: + vhost_iova_tree_remove(v->iova_tree, map); +- return false; ++ return r; + } + +-/** +- * Copy the guest element into a dedicated buffer suitable to be sent to NIC +- * +- * @iov: [0] is the out buffer, [1] is the in one +- */ +-static bool vhost_vdpa_net_cvq_map_elem(VhostVDPAState *s, +- VirtQueueElement *elem, +- struct iovec *iov) ++static int vhost_vdpa_net_cvq_start(NetClientState *nc) + { +- size_t in_copied; +- bool ok; ++ VhostVDPAState *s; ++ int r; + +- iov[0].iov_base = s->cvq_cmd_out_buffer; +- ok = vhost_vdpa_cvq_map_buf(&s->vhost_vdpa, elem->out_sg, elem->out_num, +- vhost_vdpa_net_cvq_cmd_len(), iov[0].iov_base, +- &iov[0].iov_len, false); +- if (unlikely(!ok)) { +- return false; ++ assert(nc->info->type == NET_CLIENT_DRIVER_VHOST_VDPA); ++ ++ s = DO_UPCAST(VhostVDPAState, nc, nc); ++ if (!s->vhost_vdpa.shadow_vqs_enabled) { ++ return 0; + } + +- iov[1].iov_base = s->cvq_cmd_in_buffer; +- ok = vhost_vdpa_cvq_map_buf(&s->vhost_vdpa, NULL, 0, +- sizeof(virtio_net_ctrl_ack), iov[1].iov_base, +- &in_copied, true); +- if (unlikely(!ok)) { ++ r = vhost_vdpa_cvq_map_buf(&s->vhost_vdpa, s->cvq_cmd_out_buffer, ++ vhost_vdpa_net_cvq_cmd_page_len(), false); ++ if (unlikely(r < 0)) { ++ return r; ++ } ++ ++ r = vhost_vdpa_cvq_map_buf(&s->vhost_vdpa, s->cvq_cmd_in_buffer, ++ vhost_vdpa_net_cvq_cmd_page_len(), true); ++ if (unlikely(r < 0)) { + vhost_vdpa_cvq_unmap_buf(&s->vhost_vdpa, s->cvq_cmd_out_buffer); +- return false; + } + +- iov[1].iov_len = sizeof(virtio_net_ctrl_ack); +- return true; ++ return r; ++} ++ ++static void vhost_vdpa_net_cvq_stop(NetClientState *nc) ++{ ++ VhostVDPAState *s = DO_UPCAST(VhostVDPAState, nc, nc); ++ ++ assert(nc->info->type == NET_CLIENT_DRIVER_VHOST_VDPA); ++ ++ if (s->vhost_vdpa.shadow_vqs_enabled) { ++ vhost_vdpa_cvq_unmap_buf(&s->vhost_vdpa, s->cvq_cmd_out_buffer); ++ vhost_vdpa_cvq_unmap_buf(&s->vhost_vdpa, s->cvq_cmd_in_buffer); ++ } + } + + static NetClientInfo net_vhost_vdpa_cvq_info = { + .type = NET_CLIENT_DRIVER_VHOST_VDPA, + .size = sizeof(VhostVDPAState), + .receive = vhost_vdpa_receive, ++ .start = vhost_vdpa_net_cvq_start, ++ .stop = vhost_vdpa_net_cvq_stop, + .cleanup = vhost_vdpa_cleanup, + .has_vnet_hdr = vhost_vdpa_has_vnet_hdr, + .has_ufo = vhost_vdpa_has_ufo, +@@ -356,19 +355,17 @@ static NetClientInfo net_vhost_vdpa_cvq_info = { + * Do not forward commands not supported by SVQ. Otherwise, the device could + * accept it and qemu would not know how to update the device model. + */ +-static bool vhost_vdpa_net_cvq_validate_cmd(const struct iovec *out, +- size_t out_num) ++static bool vhost_vdpa_net_cvq_validate_cmd(const void *out_buf, size_t len) + { + struct virtio_net_ctrl_hdr ctrl; +- size_t n; + +- n = iov_to_buf(out, out_num, 0, &ctrl, sizeof(ctrl)); +- if (unlikely(n < sizeof(ctrl))) { ++ if (unlikely(len < sizeof(ctrl))) { + qemu_log_mask(LOG_GUEST_ERROR, +- "%s: invalid legnth of out buffer %zu\n", __func__, n); ++ "%s: invalid legnth of out buffer %zu\n", __func__, len); + return false; + } + ++ memcpy(&ctrl, out_buf, sizeof(ctrl)); + switch (ctrl.class) { + case VIRTIO_NET_CTRL_MAC: + switch (ctrl.cmd) { +@@ -400,10 +397,14 @@ static int vhost_vdpa_net_handle_ctrl_avail(VhostShadowVirtqueue *svq, + VhostVDPAState *s = opaque; + size_t in_len, dev_written; + virtio_net_ctrl_ack status = VIRTIO_NET_ERR; +- /* out and in buffers sent to the device */ +- struct iovec dev_buffers[2] = { +- { .iov_base = s->cvq_cmd_out_buffer }, +- { .iov_base = s->cvq_cmd_in_buffer }, ++ /* Out buffer sent to both the vdpa device and the device model */ ++ struct iovec out = { ++ .iov_base = s->cvq_cmd_out_buffer, ++ }; ++ /* In buffer sent to the device */ ++ const struct iovec dev_in = { ++ .iov_base = s->cvq_cmd_in_buffer, ++ .iov_len = sizeof(virtio_net_ctrl_ack), + }; + /* in buffer used for device model */ + const struct iovec in = { +@@ -413,17 +414,15 @@ static int vhost_vdpa_net_handle_ctrl_avail(VhostShadowVirtqueue *svq, + int r = -EINVAL; + bool ok; + +- ok = vhost_vdpa_net_cvq_map_elem(s, elem, dev_buffers); +- if (unlikely(!ok)) { +- goto out; +- } +- +- ok = vhost_vdpa_net_cvq_validate_cmd(&dev_buffers[0], 1); ++ out.iov_len = iov_to_buf(elem->out_sg, elem->out_num, 0, ++ s->cvq_cmd_out_buffer, ++ vhost_vdpa_net_cvq_cmd_len()); ++ ok = vhost_vdpa_net_cvq_validate_cmd(s->cvq_cmd_out_buffer, out.iov_len); + if (unlikely(!ok)) { + goto out; + } + +- r = vhost_svq_add(svq, &dev_buffers[0], 1, &dev_buffers[1], 1, elem); ++ r = vhost_svq_add(svq, &out, 1, &dev_in, 1, elem); + if (unlikely(r != 0)) { + if (unlikely(r == -ENOSPC)) { + qemu_log_mask(LOG_GUEST_ERROR, "%s: No space on device queue\n", +@@ -443,13 +442,13 @@ static int vhost_vdpa_net_handle_ctrl_avail(VhostShadowVirtqueue *svq, + goto out; + } + +- memcpy(&status, dev_buffers[1].iov_base, sizeof(status)); ++ memcpy(&status, s->cvq_cmd_in_buffer, sizeof(status)); + if (status != VIRTIO_NET_OK) { + goto out; + } + + status = VIRTIO_NET_ERR; +- virtio_net_handle_ctrl_iov(svq->vdev, &in, 1, dev_buffers, 1); ++ virtio_net_handle_ctrl_iov(svq->vdev, &in, 1, &out, 1); + if (status != VIRTIO_NET_OK) { + error_report("Bad CVQ processing in model"); + } +@@ -462,12 +461,6 @@ out: + } + vhost_svq_push_elem(svq, elem, MIN(in_len, sizeof(status))); + g_free(elem); +- if (dev_buffers[0].iov_base) { +- vhost_vdpa_cvq_unmap_buf(&s->vhost_vdpa, dev_buffers[0].iov_base); +- } +- if (dev_buffers[1].iov_base) { +- vhost_vdpa_cvq_unmap_buf(&s->vhost_vdpa, dev_buffers[1].iov_base); +- } + return r; + } + +-- +2.27.0 + diff --git a/vdpa-Never-set-log_base-addr-if-SVQ-is-enabled.patch b/vdpa-Never-set-log_base-addr-if-SVQ-is-enabled.patch new file mode 100644 index 00000000..6778cded --- /dev/null +++ b/vdpa-Never-set-log_base-addr-if-SVQ-is-enabled.patch @@ -0,0 +1,36 @@ +From b34bcf052293861e8b88a41dad194d0889c6692f Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= +Date: Mon, 14 Mar 2022 18:34:53 +0100 +Subject: [PATCH] vdpa: Never set log_base addr if SVQ is enabled +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Setting the log address would make the device start reporting invalid +dirty memory because the SVQ vrings are located in qemu's memory. + +Signed-off-by: Eugenio Pérez +Acked-by: Michael S. Tsirkin +Signed-off-by: Jason Wang +Signed-off-by: fangyi +--- + hw/virtio/vhost-vdpa.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c +index 428137f654..840141321a 100644 +--- a/hw/virtio/vhost-vdpa.c ++++ b/hw/virtio/vhost-vdpa.c +@@ -1092,7 +1092,8 @@ static int vhost_vdpa_dev_start(struct vhost_dev *dev, bool started) + static int vhost_vdpa_set_log_base(struct vhost_dev *dev, uint64_t base, + struct vhost_log *log) + { +- if (vhost_vdpa_one_time_request(dev)) { ++ struct vhost_vdpa *v = dev->opaque; ++ if (v->shadow_vqs_enabled || vhost_vdpa_one_time_request(dev)) { + return 0; + } + +-- +2.27.0 + diff --git a/vdpa-Remove-SVQ-vring-from-iova_tree-at-shutdown.patch b/vdpa-Remove-SVQ-vring-from-iova_tree-at-shutdown.patch new file mode 100644 index 00000000..be0cb96a --- /dev/null +++ b/vdpa-Remove-SVQ-vring-from-iova_tree-at-shutdown.patch @@ -0,0 +1,40 @@ +From f52985fb819fbf8efb162a25096abb4c174b9f40 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= +Date: Tue, 23 Aug 2022 20:20:05 +0200 +Subject: [PATCH] vdpa: Remove SVQ vring from iova_tree at shutdown +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Although the device will be reset before usage, the right thing to do is +to clean it. + +Reported-by: Lei Yang +Fixes: 34e3c94eda ("vdpa: Add custom IOTLB translations to SVQ") +Signed-off-by: Eugenio Pérez +Signed-off-by: Jason Wang +Signed-off-by: fangyi +--- + hw/virtio/vhost-vdpa.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c +index 0f640f670b..3be6988e9c 100644 +--- a/hw/virtio/vhost-vdpa.c ++++ b/hw/virtio/vhost-vdpa.c +@@ -900,6 +900,12 @@ static bool vhost_vdpa_svq_unmap_ring(struct vhost_vdpa *v, + + size = ROUND_UP(result->size, qemu_real_host_page_size); + r = vhost_vdpa_dma_unmap(v, result->iova, size); ++ if (unlikely(r < 0)) { ++ error_report("Unable to unmap SVQ vring: %s (%d)", g_strerror(-r), -r); ++ return false; ++ } ++ ++ vhost_iova_tree_remove(v->iova_tree, *result); + return r == 0; + } + +-- +2.27.0 + diff --git a/vdpa-Remove-shadow-CVQ-command-check.patch b/vdpa-Remove-shadow-CVQ-command-check.patch new file mode 100644 index 00000000..90ef701b --- /dev/null +++ b/vdpa-Remove-shadow-CVQ-command-check.patch @@ -0,0 +1,94 @@ +From 6cb9e17dcc07d6fc1467a585fb015991191a92da Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= +Date: Thu, 20 Oct 2022 10:02:30 +0200 +Subject: [PATCH] vdpa: Remove shadow CVQ command check +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The guest will see undefined behavior if it issue not negotiate +commands, bit it is expected somehow. + +Simplify code deleting this check. + +Signed-off-by: Eugenio Pérez +Acked-by: Jason Wang +Signed-off-by: Jason Wang +Signed-off-by: fangyi +--- + net/vhost-vdpa.c | 48 ------------------------------------------------ + 1 file changed, 48 deletions(-) + +diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c +index f4f6b8587f..c8c433002d 100644 +--- a/net/vhost-vdpa.c ++++ b/net/vhost-vdpa.c +@@ -469,48 +469,6 @@ static NetClientInfo net_vhost_vdpa_cvq_info = { + .check_peer_type = vhost_vdpa_check_peer_type, + }; + +-/** +- * Do not forward commands not supported by SVQ. Otherwise, the device could +- * accept it and qemu would not know how to update the device model. +- */ +-static bool vhost_vdpa_net_cvq_validate_cmd(const void *out_buf, size_t len) +-{ +- struct virtio_net_ctrl_hdr ctrl; +- +- if (unlikely(len < sizeof(ctrl))) { +- qemu_log_mask(LOG_GUEST_ERROR, +- "%s: invalid legnth of out buffer %zu\n", __func__, len); +- return false; +- } +- +- memcpy(&ctrl, out_buf, sizeof(ctrl)); +- switch (ctrl.class) { +- case VIRTIO_NET_CTRL_MAC: +- switch (ctrl.cmd) { +- case VIRTIO_NET_CTRL_MAC_ADDR_SET: +- return true; +- default: +- qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid mac cmd %u\n", +- __func__, ctrl.cmd); +- }; +- break; +- case VIRTIO_NET_CTRL_MQ: +- switch (ctrl.cmd) { +- case VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET: +- return true; +- default: +- qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid mq cmd %u\n", +- __func__, ctrl.cmd); +- }; +- break; +- default: +- qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid control class %u\n", +- __func__, ctrl.class); +- }; +- +- return false; +-} +- + /** + * Validate and copy control virtqueue commands. + * +@@ -534,16 +492,10 @@ static int vhost_vdpa_net_handle_ctrl_avail(VhostShadowVirtqueue *svq, + .iov_len = sizeof(status), + }; + ssize_t dev_written = -EINVAL; +- bool ok; + + out.iov_len = iov_to_buf(elem->out_sg, elem->out_num, 0, + s->cvq_cmd_out_buffer, + vhost_vdpa_net_cvq_cmd_len()); +- ok = vhost_vdpa_net_cvq_validate_cmd(s->cvq_cmd_out_buffer, out.iov_len); +- if (unlikely(!ok)) { +- goto out; +- } +- + dev_written = vhost_vdpa_net_cvq_add(s, out.iov_len, sizeof(status)); + if (unlikely(dev_written < 0)) { + goto out; +-- +2.27.0 + diff --git a/vdpa-Return-EIO-if-device-ack-is-VIRTIO_NET_ERR-in-_-new.patch b/vdpa-Return-EIO-if-device-ack-is-VIRTIO_NET_ERR-in-_-new.patch new file mode 100644 index 00000000..6471c52f --- /dev/null +++ b/vdpa-Return-EIO-if-device-ack-is-VIRTIO_NET_ERR-in-_-new.patch @@ -0,0 +1,63 @@ +From 8f2a04c1b5790f6e00160920c3bc88801b5afc16 Mon Sep 17 00:00:00 2001 +From: Hawkins Jiawei +Date: Tue, 4 Jul 2023 11:34:34 +0800 +Subject: [PATCH] vdpa: Return -EIO if device ack is VIRTIO_NET_ERR in + _load_mq() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +According to VirtIO standard, "The class, command and +command-specific-data are set by the driver, +and the device sets the ack byte. +There is little it can do except issue a diagnostic +if ack is not VIRTIO_NET_OK." + +Therefore, QEMU should stop sending the queued SVQ commands and +cancel the device startup if the device's ack is not VIRTIO_NET_OK. + +Yet the problem is that, vhost_vdpa_net_load_mq() returns 1 based on +`*s->status != VIRTIO_NET_OK` when the device's ack is VIRTIO_NET_ERR. +As a result, net->nc->info->load() also returns 1, this makes +vhost_net_start_one() incorrectly assume the device state is +successfully loaded by vhost_vdpa_net_load() and return 0, instead of +goto `fail` label to cancel the device startup, as vhost_net_start_one() +only cancels the device startup when net->nc->info->load() returns a +negative value. + +This patch fixes this problem by returning -EIO when the device's +ack is not VIRTIO_NET_OK. + +Fixes: f64c7cda69 ("vdpa: Add vhost_vdpa_net_load_mq") +Signed-off-by: Hawkins Jiawei +Acked-by: Jason Wang +Acked-by: Eugenio Pérez +Message-Id: +Tested-by: Lei Yang +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Signed-off-by: fangyi +--- + net/vhost-vdpa.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c +index 9af9f6554e..8192045735 100644 +--- a/net/vhost-vdpa.c ++++ b/net/vhost-vdpa.c +@@ -553,8 +553,11 @@ static int vhost_vdpa_net_load_mq(VhostVDPAState *s, + if (unlikely(dev_written < 0)) { + return dev_written; + } ++ if (*s->status != VIRTIO_NET_OK) { ++ return -EIO; ++ } + +- return *s->status != VIRTIO_NET_OK; ++ return 0; + } + + static int vhost_vdpa_net_load(NetClientState *nc) +-- +2.27.0 + diff --git a/vdpa-Return-EIO-if-device-ack-is-VIRTIO_NET_ERR-in-_.patch b/vdpa-Return-EIO-if-device-ack-is-VIRTIO_NET_ERR-in-_.patch new file mode 100644 index 00000000..f457ca3a --- /dev/null +++ b/vdpa-Return-EIO-if-device-ack-is-VIRTIO_NET_ERR-in-_.patch @@ -0,0 +1,62 @@ +From 1c9d6dde6fabf6c1f6a4aeb388921a83279d3071 Mon Sep 17 00:00:00 2001 +From: Hawkins Jiawei +Date: Tue, 4 Jul 2023 11:34:33 +0800 +Subject: [PATCH] vdpa: Return -EIO if device ack is VIRTIO_NET_ERR in + _load_mac() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +According to VirtIO standard, "The class, command and +command-specific-data are set by the driver, +and the device sets the ack byte. +There is little it can do except issue a diagnostic +if ack is not VIRTIO_NET_OK." + +Therefore, QEMU should stop sending the queued SVQ commands and +cancel the device startup if the device's ack is not VIRTIO_NET_OK. + +Yet the problem is that, vhost_vdpa_net_load_mac() returns 1 based on +`*s->status != VIRTIO_NET_OK` when the device's ack is VIRTIO_NET_ERR. +As a result, net->nc->info->load() also returns 1, this makes +vhost_net_start_one() incorrectly assume the device state is +successfully loaded by vhost_vdpa_net_load() and return 0, instead of +goto `fail` label to cancel the device startup, as vhost_net_start_one() +only cancels the device startup when net->nc->info->load() returns a +negative value. + +This patch fixes this problem by returning -EIO when the device's +ack is not VIRTIO_NET_OK. + +Fixes: f73c0c43ac ("vdpa: extract vhost_vdpa_net_load_mac from vhost_vdpa_net_load") +Signed-off-by: Hawkins Jiawei +Acked-by: Jason Wang +Acked-by: Eugenio Pérez +Message-Id: +Tested-by: Lei Yang +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Signed-off-by: fangyi +--- + net/vhost-vdpa.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c +index afca8740bc..9af9f6554e 100644 +--- a/net/vhost-vdpa.c ++++ b/net/vhost-vdpa.c +@@ -527,8 +527,9 @@ static int vhost_vdpa_net_load_mac(VhostVDPAState *s, const VirtIONet *n) + if (unlikely(dev_written < 0)) { + return dev_written; + } +- +- return *s->status != VIRTIO_NET_OK; ++ if (*s->status != VIRTIO_NET_OK) { ++ return -EIO; ++ } + } + + return 0; +-- +2.27.0 + diff --git a/vdpa-Skip-the-maps-not-in-the-iova-tree.patch b/vdpa-Skip-the-maps-not-in-the-iova-tree.patch new file mode 100644 index 00000000..17e13206 --- /dev/null +++ b/vdpa-Skip-the-maps-not-in-the-iova-tree.patch @@ -0,0 +1,39 @@ +From a498bc3ae687778dad2f8161ff17532432df0c1c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= +Date: Tue, 23 Aug 2022 20:20:02 +0200 +Subject: [PATCH] vdpa: Skip the maps not in the iova tree +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Next patch will skip the registering of dma maps that the vdpa device +rejects in the iova tree. We need to consider that here or we cause a +SIGSEGV accessing result. + +Reported-by: Lei Yang +Signed-off-by: Eugenio Pérez +Acked-by: Jason Wang +Signed-off-by: Jason Wang +Signed-off-by: fangyi +--- + hw/virtio/vhost-vdpa.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c +index d0cf7a0745..c551665f5d 100644 +--- a/hw/virtio/vhost-vdpa.c ++++ b/hw/virtio/vhost-vdpa.c +@@ -291,6 +291,10 @@ static void vhost_vdpa_listener_region_del(MemoryListener *listener, + }; + + result = vhost_iova_tree_find_iova(v->iova_tree, &mem_region); ++ if (!result) { ++ /* The memory listener map wasn't mapped */ ++ return; ++ } + iova = result->iova; + vhost_iova_tree_remove(v->iova_tree, result); + } +-- +2.27.0 + diff --git a/vdpa-Use-ring-hwaddr-at-vhost_vdpa_svq_unmap_ring.patch b/vdpa-Use-ring-hwaddr-at-vhost_vdpa_svq_unmap_ring.patch new file mode 100644 index 00000000..606084cd --- /dev/null +++ b/vdpa-Use-ring-hwaddr-at-vhost_vdpa_svq_unmap_ring.patch @@ -0,0 +1,70 @@ +From 1c3e4f7326031d0b689821f655a4352bb746a405 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= +Date: Tue, 23 Aug 2022 20:20:08 +0200 +Subject: [PATCH] vdpa: Use ring hwaddr at vhost_vdpa_svq_unmap_ring +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Reduce code duplication. + +Signed-off-by: Eugenio Pérez +Acked-by: Jason Wang +Signed-off-by: Jason Wang +Signed-off-by: fangyi +--- + hw/virtio/vhost-vdpa.c | 17 ++++++++--------- + 1 file changed, 8 insertions(+), 9 deletions(-) + +diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c +index 31c1b71498..d7bdc0f37c 100644 +--- a/hw/virtio/vhost-vdpa.c ++++ b/hw/virtio/vhost-vdpa.c +@@ -886,10 +886,12 @@ static int vhost_vdpa_svq_set_fds(struct vhost_dev *dev, + /** + * Unmap a SVQ area in the device + */ +-static void vhost_vdpa_svq_unmap_ring(struct vhost_vdpa *v, +- const DMAMap *needle) ++static void vhost_vdpa_svq_unmap_ring(struct vhost_vdpa *v, hwaddr addr) + { +- const DMAMap *result = vhost_iova_tree_find_iova(v->iova_tree, needle); ++ const DMAMap needle = { ++ .translated_addr = addr, ++ }; ++ const DMAMap *result = vhost_iova_tree_find_iova(v->iova_tree, &needle); + hwaddr size; + int r; + +@@ -911,17 +913,14 @@ static void vhost_vdpa_svq_unmap_ring(struct vhost_vdpa *v, + static void vhost_vdpa_svq_unmap_rings(struct vhost_dev *dev, + const VhostShadowVirtqueue *svq) + { +- DMAMap needle = {}; + struct vhost_vdpa *v = dev->opaque; + struct vhost_vring_addr svq_addr; + + vhost_svq_get_vring_addr(svq, &svq_addr); + +- needle.translated_addr = svq_addr.desc_user_addr; +- vhost_vdpa_svq_unmap_ring(v, &needle); ++ vhost_vdpa_svq_unmap_ring(v, svq_addr.desc_user_addr); + +- needle.translated_addr = svq_addr.used_user_addr; +- vhost_vdpa_svq_unmap_ring(v, &needle); ++ vhost_vdpa_svq_unmap_ring(v, svq_addr.used_user_addr); + } + + /** +@@ -999,7 +998,7 @@ static bool vhost_vdpa_svq_map_rings(struct vhost_dev *dev, + ok = vhost_vdpa_svq_map_ring(v, &device_region, errp); + if (unlikely(!ok)) { + error_prepend(errp, "Cannot create vq device region: "); +- vhost_vdpa_svq_unmap_ring(v, &driver_region); ++ vhost_vdpa_svq_unmap_ring(v, driver_region.translated_addr); + } + addr->used_user_addr = device_region.iova; + +-- +2.27.0 + diff --git a/vdpa-adapt-vhost_ops-callbacks-to-svq.patch b/vdpa-adapt-vhost_ops-callbacks-to-svq.patch new file mode 100644 index 00000000..914e13a7 --- /dev/null +++ b/vdpa-adapt-vhost_ops-callbacks-to-svq.patch @@ -0,0 +1,104 @@ +From 1ae2ad1afcb032dc933104da5ad922173961caf8 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= +Date: Mon, 14 Mar 2022 18:34:46 +0100 +Subject: [PATCH] vdpa: adapt vhost_ops callbacks to svq +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +First half of the buffers forwarding part, preparing vhost-vdpa +callbacks to SVQ to offer it. QEMU cannot enable it at this moment, so +this is effectively dead code at the moment, but it helps to reduce +patch size. + +Signed-off-by: Eugenio Pérez +Acked-by: Michael S. Tsirkin +Signed-off-by: Jason Wang +Signed-off-by: fangyi +--- + hw/virtio/vhost-vdpa.c | 48 ++++++++++++++++++++++++++++++++++++------ + 1 file changed, 41 insertions(+), 7 deletions(-) + +diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c +index 8ee63933a8..2f0e6a9bef 100644 +--- a/hw/virtio/vhost-vdpa.c ++++ b/hw/virtio/vhost-vdpa.c +@@ -735,6 +735,13 @@ static int vhost_vdpa_get_config(struct vhost_dev *dev, uint8_t *config, + return ret; + } + ++static int vhost_vdpa_set_dev_vring_base(struct vhost_dev *dev, ++ struct vhost_vring_state *ring) ++{ ++ trace_vhost_vdpa_set_vring_base(dev, ring->index, ring->num); ++ return vhost_vdpa_call(dev, VHOST_SET_VRING_BASE, ring); ++} ++ + static int vhost_vdpa_set_vring_dev_kick(struct vhost_dev *dev, + struct vhost_vring_file *file) + { +@@ -749,6 +756,18 @@ static int vhost_vdpa_set_vring_dev_call(struct vhost_dev *dev, + return vhost_vdpa_call(dev, VHOST_SET_VRING_CALL, file); + } + ++static int vhost_vdpa_set_vring_dev_addr(struct vhost_dev *dev, ++ struct vhost_vring_addr *addr) ++{ ++ trace_vhost_vdpa_set_vring_addr(dev, addr->index, addr->flags, ++ addr->desc_user_addr, addr->used_user_addr, ++ addr->avail_user_addr, ++ addr->log_guest_addr); ++ ++ return vhost_vdpa_call(dev, VHOST_SET_VRING_ADDR, addr); ++ ++} ++ + /** + * Set the shadow virtqueue descriptors to the device + * +@@ -858,11 +877,17 @@ static int vhost_vdpa_set_log_base(struct vhost_dev *dev, uint64_t base, + static int vhost_vdpa_set_vring_addr(struct vhost_dev *dev, + struct vhost_vring_addr *addr) + { +- trace_vhost_vdpa_set_vring_addr(dev, addr->index, addr->flags, +- addr->desc_user_addr, addr->used_user_addr, +- addr->avail_user_addr, +- addr->log_guest_addr); +- return vhost_vdpa_call(dev, VHOST_SET_VRING_ADDR, addr); ++ struct vhost_vdpa *v = dev->opaque; ++ ++ if (v->shadow_vqs_enabled) { ++ /* ++ * Device vring addr was set at device start. SVQ base is handled by ++ * VirtQueue code. ++ */ ++ return 0; ++ } ++ ++ return vhost_vdpa_set_vring_dev_addr(dev, addr); + } + + static int vhost_vdpa_set_vring_num(struct vhost_dev *dev, +@@ -875,8 +900,17 @@ static int vhost_vdpa_set_vring_num(struct vhost_dev *dev, + static int vhost_vdpa_set_vring_base(struct vhost_dev *dev, + struct vhost_vring_state *ring) + { +- trace_vhost_vdpa_set_vring_base(dev, ring->index, ring->num); +- return vhost_vdpa_call(dev, VHOST_SET_VRING_BASE, ring); ++ struct vhost_vdpa *v = dev->opaque; ++ ++ if (v->shadow_vqs_enabled) { ++ /* ++ * Device vring base was set at device start. SVQ base is handled by ++ * VirtQueue code. ++ */ ++ return 0; ++ } ++ ++ return vhost_vdpa_set_dev_vring_base(dev, ring); + } + + static int vhost_vdpa_get_vring_base(struct vhost_dev *dev, +-- +2.27.0 + diff --git a/vdpa-add-asid-parameter-to-vhost_vdpa_dma_map-unmap.patch b/vdpa-add-asid-parameter-to-vhost_vdpa_dma_map-unmap.patch new file mode 100644 index 00000000..0e6774f3 --- /dev/null +++ b/vdpa-add-asid-parameter-to-vhost_vdpa_dma_map-unmap.patch @@ -0,0 +1,227 @@ +From 657f5e7b200bec7b124ca5e2cf4d8e1b721cbfde Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= +Date: Thu, 15 Dec 2022 12:31:41 +0100 +Subject: [PATCH] vdpa: add asid parameter to vhost_vdpa_dma_map/unmap +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +So the caller can choose which ASID is destined. + +No need to update the batch functions as they will always be called from +memory listener updates at the moment. Memory listener updates will +always update ASID 0, as it's the passthrough ASID. + +All vhost devices's ASID are 0 at this moment. + +Signed-off-by: Eugenio Pérez +Acked-by: Jason Wang +Message-Id: <20221215113144.322011-10-eperezma@redhat.com> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Signed-off-by: fangyi +--- + hw/virtio/trace-events | 4 +-- + hw/virtio/vhost-vdpa.c | 36 ++++++++++++++------ + include/hw/virtio/vhost-vdpa.h | 14 ++++++-- + include/standard-headers/linux/vhost_types.h | 2 +- + net/vhost-vdpa.c | 6 ++-- + 5 files changed, 42 insertions(+), 20 deletions(-) + +diff --git a/hw/virtio/trace-events b/hw/virtio/trace-events +index 35d4c00e59..edbbbeb621 100644 +--- a/hw/virtio/trace-events ++++ b/hw/virtio/trace-events +@@ -29,8 +29,8 @@ vhost_user_read(uint32_t req, uint32_t flags) "req:%d flags:0x%"PRIx32"" + vhost_user_write(uint32_t req, uint32_t flags) "req:%d flags:0x%"PRIx32"" + + # vhost-vdpa.c +-vhost_vdpa_dma_map(void *vdpa, int fd, uint32_t msg_type, uint64_t iova, uint64_t size, uint64_t uaddr, uint8_t perm, uint8_t type) "vdpa:%p fd: %d msg_type: %"PRIu32" iova: 0x%"PRIx64" size: 0x%"PRIx64" uaddr: 0x%"PRIx64" perm: 0x%"PRIx8" type: %"PRIu8 +-vhost_vdpa_dma_unmap(void *vdpa, int fd, uint32_t msg_type, uint64_t iova, uint64_t size, uint8_t type) "vdpa:%p fd: %d msg_type: %"PRIu32" iova: 0x%"PRIx64" size: 0x%"PRIx64" type: %"PRIu8 ++vhost_vdpa_dma_map(void *vdpa, int fd, uint32_t msg_type, uint32_t asid, uint64_t iova, uint64_t size, uint64_t uaddr, uint8_t perm, uint8_t type) "vdpa:%p fd: %d msg_type: %"PRIu32" asid: %"PRIu32" iova: 0x%"PRIx64" size: 0x%"PRIx64" uaddr: 0x%"PRIx64" perm: 0x%"PRIx8" type: %"PRIu8 ++vhost_vdpa_dma_unmap(void *vdpa, int fd, uint32_t msg_type, uint32_t asid, uint64_t iova, uint64_t size, uint8_t type) "vdpa:%p fd: %d msg_type: %"PRIu32" asid: %"PRIu32" iova: 0x%"PRIx64" size: 0x%"PRIx64" type: %"PRIu8 + vhost_vdpa_listener_begin_batch(void *v, int fd, uint32_t msg_type, uint8_t type) "vdpa:%p fd: %d msg_type: %"PRIu32" type: %"PRIu8 + vhost_vdpa_listener_commit(void *v, int fd, uint32_t msg_type, uint8_t type) "vdpa:%p fd: %d msg_type: %"PRIu32" type: %"PRIu8 + vhost_vdpa_listener_region_add(void *vdpa, uint64_t iova, uint64_t llend, void *vaddr, bool readonly) "vdpa: %p iova 0x%"PRIx64" llend 0x%"PRIx64" vaddr: %p read-only: %d" +diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c +index 450b5effd2..f4a0878e34 100644 +--- a/hw/virtio/vhost-vdpa.c ++++ b/hw/virtio/vhost-vdpa.c +@@ -74,22 +74,28 @@ static bool vhost_vdpa_listener_skipped_section(MemoryRegionSection *section, + return false; + } + +-int vhost_vdpa_dma_map(struct vhost_vdpa *v, hwaddr iova, hwaddr size, +- void *vaddr, bool readonly) ++/* ++ * The caller must set asid = 0 if the device does not support asid. ++ * This is not an ABI break since it is set to 0 by the initializer anyway. ++ */ ++int vhost_vdpa_dma_map(struct vhost_vdpa *v, uint32_t asid, hwaddr iova, ++ hwaddr size, void *vaddr, bool readonly) + { + struct vhost_msg_v2 msg = {}; + int fd = v->device_fd; + int ret = 0; + + msg.type = v->msg_type; ++ msg.asid = asid; + msg.iotlb.iova = iova; + msg.iotlb.size = size; + msg.iotlb.uaddr = (uint64_t)(uintptr_t)vaddr; + msg.iotlb.perm = readonly ? VHOST_ACCESS_RO : VHOST_ACCESS_RW; + msg.iotlb.type = VHOST_IOTLB_UPDATE; + +- trace_vhost_vdpa_dma_map(v, fd, msg.type, msg.iotlb.iova, msg.iotlb.size, +- msg.iotlb.uaddr, msg.iotlb.perm, msg.iotlb.type); ++ trace_vhost_vdpa_dma_map(v, fd, msg.type, msg.asid, msg.iotlb.iova, ++ msg.iotlb.size, msg.iotlb.uaddr, msg.iotlb.perm, ++ msg.iotlb.type); + + if (write(fd, &msg, sizeof(msg)) != sizeof(msg)) { + error_report("failed to write, fd=%d, errno=%d (%s)", +@@ -100,18 +106,24 @@ int vhost_vdpa_dma_map(struct vhost_vdpa *v, hwaddr iova, hwaddr size, + return ret; + } + +-int vhost_vdpa_dma_unmap(struct vhost_vdpa *v, hwaddr iova, hwaddr size) ++/* ++ * The caller must set asid = 0 if the device does not support asid. ++ * This is not an ABI break since it is set to 0 by the initializer anyway. ++ */ ++int vhost_vdpa_dma_unmap(struct vhost_vdpa *v, uint32_t asid, hwaddr iova, ++ hwaddr size) + { + struct vhost_msg_v2 msg = {}; + int fd = v->device_fd; + int ret = 0; + + msg.type = v->msg_type; ++ msg.asid = asid; + msg.iotlb.iova = iova; + msg.iotlb.size = size; + msg.iotlb.type = VHOST_IOTLB_INVALIDATE; + +- trace_vhost_vdpa_dma_unmap(v, fd, msg.type, msg.iotlb.iova, ++ trace_vhost_vdpa_dma_unmap(v, fd, msg.type, msg.asid, msg.iotlb.iova, + msg.iotlb.size, msg.iotlb.type); + + if (write(fd, &msg, sizeof(msg)) != sizeof(msg)) { +@@ -231,8 +243,8 @@ static void vhost_vdpa_listener_region_add(MemoryListener *listener, + } + + vhost_vdpa_iotlb_batch_begin_once(v); +- ret = vhost_vdpa_dma_map(v, iova, int128_get64(llsize), +- vaddr, section->readonly); ++ ret = vhost_vdpa_dma_map(v, VHOST_VDPA_GUEST_PA_ASID, iova, ++ int128_get64(llsize), vaddr, section->readonly); + if (ret) { + error_report("vhost vdpa map fail!"); + goto fail_map; +@@ -305,7 +317,8 @@ static void vhost_vdpa_listener_region_del(MemoryListener *listener, + vhost_iova_tree_remove(v->iova_tree, *result); + } + vhost_vdpa_iotlb_batch_begin_once(v); +- ret = vhost_vdpa_dma_unmap(v, iova, int128_get64(llsize)); ++ ret = vhost_vdpa_dma_unmap(v, VHOST_VDPA_GUEST_PA_ASID, iova, ++ int128_get64(llsize)); + if (ret) { + error_report("vhost_vdpa dma unmap error!"); + } +@@ -872,7 +885,7 @@ static void vhost_vdpa_svq_unmap_ring(struct vhost_vdpa *v, hwaddr addr) + } + + size = ROUND_UP(result->size, qemu_real_host_page_size); +- r = vhost_vdpa_dma_unmap(v, result->iova, size); ++ r = vhost_vdpa_dma_unmap(v, v->address_space_id, result->iova, size); + if (unlikely(r < 0)) { + error_report("Unable to unmap SVQ vring: %s (%d)", g_strerror(-r), -r); + return; +@@ -912,7 +925,8 @@ static bool vhost_vdpa_svq_map_ring(struct vhost_vdpa *v, DMAMap *needle, + return false; + } + +- r = vhost_vdpa_dma_map(v, needle->iova, needle->size + 1, ++ r = vhost_vdpa_dma_map(v, v->address_space_id, needle->iova, ++ needle->size + 1, + (void *)(uintptr_t)needle->translated_addr, + needle->perm == IOMMU_RO); + if (unlikely(r != 0)) { +diff --git a/include/hw/virtio/vhost-vdpa.h b/include/hw/virtio/vhost-vdpa.h +index 1111d85643..e57dfa1fd1 100644 +--- a/include/hw/virtio/vhost-vdpa.h ++++ b/include/hw/virtio/vhost-vdpa.h +@@ -19,6 +19,12 @@ + #include "hw/virtio/virtio.h" + #include "standard-headers/linux/vhost_types.h" + ++/* ++ * ASID dedicated to map guest's addresses. If SVQ is disabled it maps GPA to ++ * qemu's IOVA. If SVQ is enabled it maps also the SVQ vring here ++ */ ++#define VHOST_VDPA_GUEST_PA_ASID 0 ++ + typedef struct VhostVDPAHostNotifier { + MemoryRegion mr; + void *addr; +@@ -29,6 +35,7 @@ typedef struct vhost_vdpa { + int index; + uint32_t msg_type; + bool iotlb_batch_begin_sent; ++ uint32_t address_space_id; + MemoryListener listener; + struct vhost_vdpa_iova_range iova_range; + uint64_t acked_features; +@@ -42,8 +49,9 @@ typedef struct vhost_vdpa { + VhostVDPAHostNotifier notifier[VIRTIO_QUEUE_MAX]; + } VhostVDPA; + +-int vhost_vdpa_dma_map(struct vhost_vdpa *v, hwaddr iova, hwaddr size, +- void *vaddr, bool readonly); +-int vhost_vdpa_dma_unmap(struct vhost_vdpa *v, hwaddr iova, hwaddr size); ++int vhost_vdpa_dma_map(struct vhost_vdpa *v, uint32_t asid, hwaddr iova, ++ hwaddr size, void *vaddr, bool readonly); ++int vhost_vdpa_dma_unmap(struct vhost_vdpa *v, uint32_t asid, hwaddr iova, ++ hwaddr size); + + #endif +diff --git a/include/standard-headers/linux/vhost_types.h b/include/standard-headers/linux/vhost_types.h +index 0bd2684a2a..fa267e39d4 100644 +--- a/include/standard-headers/linux/vhost_types.h ++++ b/include/standard-headers/linux/vhost_types.h +@@ -87,7 +87,7 @@ struct vhost_msg { + + struct vhost_msg_v2 { + uint32_t type; +- uint32_t reserved; ++ uint32_t asid; + union { + struct vhost_iotlb_msg iotlb; + uint8_t padding[64]; +diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c +index e250d34462..cb1cc2523d 100644 +--- a/net/vhost-vdpa.c ++++ b/net/vhost-vdpa.c +@@ -266,7 +266,7 @@ static void vhost_vdpa_cvq_unmap_buf(struct vhost_vdpa *v, void *addr) + return; + } + +- r = vhost_vdpa_dma_unmap(v, map->iova, map->size + 1); ++ r = vhost_vdpa_dma_unmap(v, v->address_space_id, map->iova, map->size + 1); + if (unlikely(r != 0)) { + error_report("Device cannot unmap: %s(%d)", g_strerror(r), r); + } +@@ -306,8 +306,8 @@ static int vhost_vdpa_cvq_map_buf(struct vhost_vdpa *v, void *buf, size_t size, + return r; + } + +- r = vhost_vdpa_dma_map(v, map.iova, vhost_vdpa_net_cvq_cmd_page_len(), buf, +- !write); ++ r = vhost_vdpa_dma_map(v, v->address_space_id, map.iova, ++ vhost_vdpa_net_cvq_cmd_page_len(), buf, !write); + if (unlikely(r < 0)) { + goto dma_map_err; + } +-- +2.27.0 + diff --git a/vdpa-add-net_vhost_vdpa_cvq_info-NetClientInfo.patch b/vdpa-add-net_vhost_vdpa_cvq_info-NetClientInfo.patch new file mode 100644 index 00000000..f06ea91d --- /dev/null +++ b/vdpa-add-net_vhost_vdpa_cvq_info-NetClientInfo.patch @@ -0,0 +1,53 @@ +From a5717856457e72575a32dfc8e28ec6ba6dcf6d59 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= +Date: Tue, 23 Aug 2022 20:30:32 +0200 +Subject: [PATCH] vdpa: add net_vhost_vdpa_cvq_info NetClientInfo +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Next patches will add a new info callback to restore NIC status through +CVQ. Since only the CVQ vhost device is needed, create it with a new +NetClientInfo. + +Signed-off-by: Eugenio Pérez +Acked-by: Jason Wang +Signed-off-by: Jason Wang +Signed-off-by: fangyi +--- + net/vhost-vdpa.c | 12 +++++++++++- + 1 file changed, 11 insertions(+), 1 deletion(-) + +diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c +index 8cfd086639..04cb08d418 100644 +--- a/net/vhost-vdpa.c ++++ b/net/vhost-vdpa.c +@@ -342,6 +342,16 @@ static bool vhost_vdpa_net_cvq_map_elem(VhostVDPAState *s, + return true; + } + ++static NetClientInfo net_vhost_vdpa_cvq_info = { ++ .type = NET_CLIENT_DRIVER_VHOST_VDPA, ++ .size = sizeof(VhostVDPAState), ++ .receive = vhost_vdpa_receive, ++ .cleanup = vhost_vdpa_cleanup, ++ .has_vnet_hdr = vhost_vdpa_has_vnet_hdr, ++ .has_ufo = vhost_vdpa_has_ufo, ++ .check_peer_type = vhost_vdpa_check_peer_type, ++}; ++ + /** + * Do not forward commands not supported by SVQ. Otherwise, the device could + * accept it and qemu would not know how to update the device model. +@@ -483,7 +493,7 @@ static NetClientState *net_vhost_vdpa_init(NetClientState *peer, + nc = qemu_new_net_client(&net_vhost_vdpa_info, peer, device, + name); + } else { +- nc = qemu_new_net_control_client(&net_vhost_vdpa_info, peer, ++ nc = qemu_new_net_control_client(&net_vhost_vdpa_cvq_info, peer, + device, name); + } + snprintf(nc->info_str, sizeof(nc->info_str), TYPE_VHOST_VDPA); +-- +2.27.0 + diff --git a/vdpa-add-shadow_data-to-vhost_vdpa.patch b/vdpa-add-shadow_data-to-vhost_vdpa.patch new file mode 100644 index 00000000..6c457064 --- /dev/null +++ b/vdpa-add-shadow_data-to-vhost_vdpa.patch @@ -0,0 +1,86 @@ +From e64b1a8253b9161e16b0a7f6c3beb77fb854660d Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= +Date: Thu, 15 Dec 2022 12:31:43 +0100 +Subject: [PATCH] vdpa: add shadow_data to vhost_vdpa +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The memory listener that thells the device how to convert GPA to qemu's +va is registered against CVQ vhost_vdpa. memory listener translations +are always ASID 0, CVQ ones are ASID 1 if supported. + +Let's tell the listener if it needs to register them on iova tree or +not. + +Signed-off-by: Eugenio Pérez +Acked-by: Jason Wang +Message-Id: <20221215113144.322011-12-eperezma@redhat.com> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Signed-off-by: fangyi +--- + hw/virtio/vhost-vdpa.c | 6 +++--- + include/hw/virtio/vhost-vdpa.h | 2 ++ + net/vhost-vdpa.c | 1 + + 3 files changed, 6 insertions(+), 3 deletions(-) + +diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c +index f4a0878e34..6d0d85b733 100644 +--- a/hw/virtio/vhost-vdpa.c ++++ b/hw/virtio/vhost-vdpa.c +@@ -226,7 +226,7 @@ static void vhost_vdpa_listener_region_add(MemoryListener *listener, + vaddr, section->readonly); + + llsize = int128_sub(llend, int128_make64(iova)); +- if (v->shadow_vqs_enabled) { ++ if (v->shadow_data) { + int r; + + mem_region.translated_addr = (hwaddr)(uintptr_t)vaddr, +@@ -253,7 +253,7 @@ static void vhost_vdpa_listener_region_add(MemoryListener *listener, + return; + + fail_map: +- if (v->shadow_vqs_enabled) { ++ if (v->shadow_data) { + vhost_iova_tree_remove(v->iova_tree, mem_region); + } + +@@ -298,7 +298,7 @@ static void vhost_vdpa_listener_region_del(MemoryListener *listener, + + llsize = int128_sub(llend, int128_make64(iova)); + +- if (v->shadow_vqs_enabled) { ++ if (v->shadow_data) { + const DMAMap *result; + const void *vaddr = memory_region_get_ram_ptr(section->mr) + + section->offset_within_region + +diff --git a/include/hw/virtio/vhost-vdpa.h b/include/hw/virtio/vhost-vdpa.h +index e57dfa1fd1..45b969a311 100644 +--- a/include/hw/virtio/vhost-vdpa.h ++++ b/include/hw/virtio/vhost-vdpa.h +@@ -40,6 +40,8 @@ typedef struct vhost_vdpa { + struct vhost_vdpa_iova_range iova_range; + uint64_t acked_features; + bool shadow_vqs_enabled; ++ /* Vdpa must send shadow addresses as IOTLB key for data queues, not GPA */ ++ bool shadow_data; + /* IOVA mapping used by the Shadow Virtqueue */ + VhostIOVATree *iova_tree; + GPtrArray *shadow_vqs; +diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c +index 7adba2c2b6..21fb89bb6b 100644 +--- a/net/vhost-vdpa.c ++++ b/net/vhost-vdpa.c +@@ -580,6 +580,7 @@ static NetClientState *net_vhost_vdpa_init(NetClientState *peer, + s->always_svq = svq; + s->vhost_vdpa.shadow_vqs_enabled = svq; + s->vhost_vdpa.iova_range = iova_range; ++ s->vhost_vdpa.shadow_data = svq; + s->vhost_vdpa.iova_tree = iova_tree; + if (!is_datapath) { + s->cvq_cmd_out_buffer = qemu_memalign(qemu_real_host_page_size, +-- +2.27.0 + diff --git a/vdpa-add-vhost_vdpa_net_valid_svq_features.patch b/vdpa-add-vhost_vdpa_net_valid_svq_features.patch new file mode 100644 index 00000000..622c8901 --- /dev/null +++ b/vdpa-add-vhost_vdpa_net_valid_svq_features.patch @@ -0,0 +1,68 @@ +From 9cd4a76f615cea230ffc33d5b3666f84216f694b Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= +Date: Thu, 15 Dec 2022 12:31:37 +0100 +Subject: [PATCH] vdpa: add vhost_vdpa_net_valid_svq_features +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +It will be reused at vdpa device start so let's extract in its own +function. + +Signed-off-by: Eugenio Pérez +Acked-by: Jason Wang +Message-Id: <20221215113144.322011-6-eperezma@redhat.com> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Signed-off-by: fangyi +--- + net/vhost-vdpa.c | 26 +++++++++++++++++--------- + 1 file changed, 17 insertions(+), 9 deletions(-) + +diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c +index eae2ed364f..217d2545c1 100644 +--- a/net/vhost-vdpa.c ++++ b/net/vhost-vdpa.c +@@ -105,6 +105,22 @@ VHostNetState *vhost_vdpa_get_vhost_net(NetClientState *nc) + return s->vhost_net; + } + ++static bool vhost_vdpa_net_valid_svq_features(uint64_t features, Error **errp) ++{ ++ uint64_t invalid_dev_features = ++ features & ~vdpa_svq_device_features & ++ /* Transport are all accepted at this point */ ++ ~MAKE_64BIT_MASK(VIRTIO_TRANSPORT_F_START, ++ VIRTIO_TRANSPORT_F_END - VIRTIO_TRANSPORT_F_START); ++ ++ if (invalid_dev_features) { ++ error_setg(errp, "vdpa svq does not work with features 0x%" PRIx64, ++ invalid_dev_features); ++ } ++ ++ return !invalid_dev_features; ++} ++ + static int vhost_vdpa_net_check_device_id(struct vhost_net *net) + { + uint32_t device_id; +@@ -683,15 +699,7 @@ int net_init_vhost_vdpa(const Netdev *netdev, const char *name, + if (opts->x_svq) { + struct vhost_vdpa_iova_range iova_range; + +- uint64_t invalid_dev_features = +- features & ~vdpa_svq_device_features & +- /* Transport are all accepted at this point */ +- ~MAKE_64BIT_MASK(VIRTIO_TRANSPORT_F_START, +- VIRTIO_TRANSPORT_F_END - VIRTIO_TRANSPORT_F_START); +- +- if (invalid_dev_features) { +- error_setg(errp, "vdpa svq does not work with features 0x%" PRIx64, +- invalid_dev_features); ++ if (!vhost_vdpa_net_valid_svq_features(features, errp)) { + goto err_svq; + } + +-- +2.27.0 + diff --git a/vdpa-allocate-SVQ-array-unconditionally.patch b/vdpa-allocate-SVQ-array-unconditionally.patch new file mode 100644 index 00000000..9e8cc601 --- /dev/null +++ b/vdpa-allocate-SVQ-array-unconditionally.patch @@ -0,0 +1,42 @@ +From fea179d880cd502f291cc6079b565bc059612d48 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= +Date: Thu, 15 Dec 2022 12:31:40 +0100 +Subject: [PATCH] vdpa: allocate SVQ array unconditionally +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +SVQ may run or not in a device depending on runtime conditions (for +example, if the device can move CVQ to its own group or not). + +Allocate the SVQ array unconditionally at startup, since its hard to +move this allocation elsewhere. + +Signed-off-by: Eugenio Pérez +Acked-by: Jason Wang +Message-Id: <20221215113144.322011-9-eperezma@redhat.com> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Signed-off-by: fangyi +--- + hw/virtio/vhost-vdpa.c | 4 ---- + 1 file changed, 4 deletions(-) + +diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c +index 59bfdbfc24..450b5effd2 100644 +--- a/hw/virtio/vhost-vdpa.c ++++ b/hw/virtio/vhost-vdpa.c +@@ -535,10 +535,6 @@ static void vhost_vdpa_svq_cleanup(struct vhost_dev *dev) + struct vhost_vdpa *v = dev->opaque; + size_t idx; + +- if (!v->shadow_vqs) { +- return; +- } +- + for (idx = 0; idx < v->shadow_vqs->len; ++idx) { + vhost_svq_stop(g_ptr_array_index(v->shadow_vqs, idx)); + } +-- +2.27.0 + diff --git a/vdpa-always-start-CVQ-in-SVQ-mode-if-possible.patch b/vdpa-always-start-CVQ-in-SVQ-mode-if-possible.patch new file mode 100644 index 00000000..32a59b81 --- /dev/null +++ b/vdpa-always-start-CVQ-in-SVQ-mode-if-possible.patch @@ -0,0 +1,224 @@ +From e2e9aeaacdb28b6c2a1bfcfef09113dc9b26a420 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= +Date: Thu, 15 Dec 2022 12:31:44 +0100 +Subject: [PATCH] vdpa: always start CVQ in SVQ mode if possible +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Isolate control virtqueue in its own group, allowing to intercept control +commands but letting dataplane run totally passthrough to the guest. + +Signed-off-by: Eugenio Pérez +Message-Id: <20221215113144.322011-13-eperezma@redhat.com> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Acked-by: Jason Wang +Signed-off-by: fangyi +--- + hw/virtio/vhost-vdpa.c | 3 +- + include/standard-headers/linux/vhost_types.h | 5 + + linux-headers/linux/vhost.h | 14 +++ + net/vhost-vdpa.c | 110 ++++++++++++++++++- + 4 files changed, 130 insertions(+), 2 deletions(-) + +diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c +index 6d0d85b733..8b44f5a7b8 100644 +--- a/hw/virtio/vhost-vdpa.c ++++ b/hw/virtio/vhost-vdpa.c +@@ -641,7 +641,8 @@ static int vhost_vdpa_set_backend_cap(struct vhost_dev *dev) + { + uint64_t features; + uint64_t f = 0x1ULL << VHOST_BACKEND_F_IOTLB_MSG_V2 | +- 0x1ULL << VHOST_BACKEND_F_IOTLB_BATCH; ++ 0x1ULL << VHOST_BACKEND_F_IOTLB_BATCH | ++ 0x1ULL << VHOST_BACKEND_F_IOTLB_ASID; + int r; + + if (vhost_vdpa_call(dev, VHOST_GET_BACKEND_FEATURES, &features)) { +diff --git a/include/standard-headers/linux/vhost_types.h b/include/standard-headers/linux/vhost_types.h +index fa267e39d4..17833e320e 100644 +--- a/include/standard-headers/linux/vhost_types.h ++++ b/include/standard-headers/linux/vhost_types.h +@@ -153,4 +153,9 @@ struct vhost_vdpa_iova_range { + /* vhost-net should add virtio_net_hdr for RX, and strip for TX packets. */ + #define VHOST_NET_F_VIRTIO_NET_HDR 27 + ++/* IOTLB can accept address space identifier through V2 type of IOTLB ++ * message ++ */ ++#define VHOST_BACKEND_F_IOTLB_ASID 0x3 ++ + #endif +diff --git a/linux-headers/linux/vhost.h b/linux-headers/linux/vhost.h +index 5d99e7c242..b6ded7f831 100644 +--- a/linux-headers/linux/vhost.h ++++ b/linux-headers/linux/vhost.h +@@ -157,4 +157,18 @@ + /* Get the count of all virtqueues */ + #define VHOST_VDPA_GET_VQS_COUNT _IOR(VHOST_VIRTIO, 0x80, __u32) + ++/* Get the group for a virtqueue: read index, write group in num, ++ * The virtqueue index is stored in the index field of ++ * vhost_vring_state. The group for this specific virtqueue is ++ * returned via num field of vhost_vring_state. ++ */ ++#define VHOST_VDPA_GET_VRING_GROUP _IOWR(VHOST_VIRTIO, 0x7B, \ ++ struct vhost_vring_state) ++/* Set the ASID for a virtqueue group. The group index is stored in ++ * the index field of vhost_vring_state, the ASID associated with this ++ * group is stored at num field of vhost_vring_state. ++ */ ++#define VHOST_VDPA_SET_GROUP_ASID _IOW(VHOST_VIRTIO, 0x7C, \ ++ struct vhost_vring_state) ++ + #endif +diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c +index 21fb89bb6b..24c4c2ef51 100644 +--- a/net/vhost-vdpa.c ++++ b/net/vhost-vdpa.c +@@ -100,6 +100,8 @@ static const uint64_t vdpa_svq_device_features = + BIT_ULL(VIRTIO_NET_F_RSC_EXT) | + BIT_ULL(VIRTIO_NET_F_STANDBY); + ++#define VHOST_VDPA_NET_CVQ_ASID 1 ++ + VHostNetState *vhost_vdpa_get_vhost_net(NetClientState *nc) + { + VhostVDPAState *s = DO_UPCAST(VhostVDPAState, nc, nc); +@@ -250,6 +252,40 @@ static NetClientInfo net_vhost_vdpa_info = { + .check_peer_type = vhost_vdpa_check_peer_type, + }; + ++static int64_t vhost_vdpa_get_vring_group(int device_fd, unsigned vq_index) ++{ ++ struct vhost_vring_state state = { ++ .index = vq_index, ++ }; ++ int r = ioctl(device_fd, VHOST_VDPA_GET_VRING_GROUP, &state); ++ ++ if (unlikely(r < 0)) { ++ error_report("Cannot get VQ %u group: %s", vq_index, ++ g_strerror(errno)); ++ return r; ++ } ++ ++ return state.num; ++} ++ ++static int vhost_vdpa_set_address_space_id(struct vhost_vdpa *v, ++ unsigned vq_group, ++ unsigned asid_num) ++{ ++ struct vhost_vring_state asid = { ++ .index = vq_group, ++ .num = asid_num, ++ }; ++ int r; ++ ++ r = ioctl(v->device_fd, VHOST_VDPA_SET_GROUP_ASID, &asid); ++ if (unlikely(r < 0)) { ++ error_report("Can't set vq group %u asid %u, errno=%d (%s)", ++ asid.index, asid.num, errno, g_strerror(errno)); ++ } ++ return r; ++} ++ + static void vhost_vdpa_cvq_unmap_buf(struct vhost_vdpa *v, void *addr) + { + VhostIOVATree *tree = v->iova_tree; +@@ -324,11 +360,75 @@ dma_map_err: + static int vhost_vdpa_net_cvq_start(NetClientState *nc) + { + VhostVDPAState *s; +- int r; ++ struct vhost_vdpa *v; ++ uint64_t backend_features; ++ int64_t cvq_group; ++ int cvq_index, r; + + assert(nc->info->type == NET_CLIENT_DRIVER_VHOST_VDPA); + + s = DO_UPCAST(VhostVDPAState, nc, nc); ++ v = &s->vhost_vdpa; ++ ++ v->shadow_data = s->always_svq; ++ v->shadow_vqs_enabled = s->always_svq; ++ s->vhost_vdpa.address_space_id = VHOST_VDPA_GUEST_PA_ASID; ++ ++ if (s->always_svq) { ++ /* SVQ is already configured for all virtqueues */ ++ goto out; ++ } ++ ++ /* ++ * If we early return in these cases SVQ will not be enabled. The migration ++ * will be blocked as long as vhost-vdpa backends will not offer _F_LOG. ++ * ++ * Calling VHOST_GET_BACKEND_FEATURES as they are not available in v->dev ++ * yet. ++ */ ++ r = ioctl(v->device_fd, VHOST_GET_BACKEND_FEATURES, &backend_features); ++ if (unlikely(r < 0)) { ++ error_report("Cannot get vdpa backend_features: %s(%d)", ++ g_strerror(errno), errno); ++ return -1; ++ } ++ if (!(backend_features & VHOST_BACKEND_F_IOTLB_ASID) || ++ !vhost_vdpa_net_valid_svq_features(v->dev->features, NULL)) { ++ return 0; ++ } ++ ++ /* ++ * Check if all the virtqueues of the virtio device are in a different vq ++ * than the last vq. VQ group of last group passed in cvq_group. ++ */ ++ cvq_index = v->dev->vq_index_end - 1; ++ cvq_group = vhost_vdpa_get_vring_group(v->device_fd, cvq_index); ++ if (unlikely(cvq_group < 0)) { ++ return cvq_group; ++ } ++ for (int i = 0; i < cvq_index; ++i) { ++ int64_t group = vhost_vdpa_get_vring_group(v->device_fd, i); ++ ++ if (unlikely(group < 0)) { ++ return group; ++ } ++ ++ if (group == cvq_group) { ++ return 0; ++ } ++ } ++ ++ r = vhost_vdpa_set_address_space_id(v, cvq_group, VHOST_VDPA_NET_CVQ_ASID); ++ if (unlikely(r < 0)) { ++ return r; ++ } ++ ++ v->iova_tree = vhost_iova_tree_new(v->iova_range.first, ++ v->iova_range.last); ++ v->shadow_vqs_enabled = true; ++ s->vhost_vdpa.address_space_id = VHOST_VDPA_NET_CVQ_ASID; ++ ++out: + if (!s->vhost_vdpa.shadow_vqs_enabled) { + return 0; + } +@@ -357,6 +457,14 @@ static void vhost_vdpa_net_cvq_stop(NetClientState *nc) + if (s->vhost_vdpa.shadow_vqs_enabled) { + vhost_vdpa_cvq_unmap_buf(&s->vhost_vdpa, s->cvq_cmd_out_buffer); + vhost_vdpa_cvq_unmap_buf(&s->vhost_vdpa, s->status); ++ if (!s->always_svq) { ++ /* ++ * If only the CVQ is shadowed we can delete this safely. ++ * If all the VQs are shadows this will be needed by the time the ++ * device is started again to register SVQ vrings and similar. ++ */ ++ g_clear_pointer(&s->vhost_vdpa.iova_tree, vhost_iova_tree_delete); ++ } + } + } + +-- +2.27.0 + diff --git a/vdpa-commit-all-host-notifier-MRs-in-a-single-MR-tra.patch b/vdpa-commit-all-host-notifier-MRs-in-a-single-MR-tra.patch new file mode 100644 index 00000000..6c805b2d --- /dev/null +++ b/vdpa-commit-all-host-notifier-MRs-in-a-single-MR-tra.patch @@ -0,0 +1,79 @@ +From aa9c65215f37fc54a280ce89a2cbfd6235e8ec9f Mon Sep 17 00:00:00 2001 +From: Longpeng +Date: Tue, 27 Dec 2022 15:20:15 +0800 +Subject: [PATCH] vdpa: commit all host notifier MRs in a single MR transaction +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This allows the vhost-vdpa device to batch the setup of all its MRs of +host notifiers. + +This significantly reduces the device starting time, e.g. the time spend +on setup the host notifier MRs reduce from 423ms to 32ms for a VM with +64 vCPUs and 3 vhost-vDPA generic devices (vdpa_sim_blk, 64vq per device). + +Signed-off-by: Longpeng +Message-Id: <20221227072015.3134-4-longpeng2@huawei.com> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Reviewed-by: Philippe Mathieu-Daudé +Signed-off-by: fangyi +--- + hw/virtio/vhost-vdpa.c | 25 +++++++++++++++++++------ + 1 file changed, 19 insertions(+), 6 deletions(-) + +diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c +index f93fac538c..2fd7af1c6b 100644 +--- a/hw/virtio/vhost-vdpa.c ++++ b/hw/virtio/vhost-vdpa.c +@@ -522,9 +522,18 @@ static void vhost_vdpa_host_notifiers_uninit(struct vhost_dev *dev, int n) + { + int i; + ++ /* ++ * Pack all the changes to the memory regions in a single ++ * transaction to avoid a few updating of the address space ++ * topology. ++ */ ++ memory_region_transaction_begin(); ++ + for (i = dev->vq_index; i < dev->vq_index + n; i++) { + vhost_vdpa_host_notifier_uninit(dev, i); + } ++ ++ memory_region_transaction_commit(); + } + + static void vhost_vdpa_host_notifiers_init(struct vhost_dev *dev) +@@ -537,17 +546,21 @@ static void vhost_vdpa_host_notifiers_init(struct vhost_dev *dev) + return; + } + ++ /* ++ * Pack all the changes to the memory regions in a single ++ * transaction to avoid a few updating of the address space ++ * topology. ++ */ ++ memory_region_transaction_begin(); ++ + for (i = dev->vq_index; i < dev->vq_index + dev->nvqs; i++) { + if (vhost_vdpa_host_notifier_init(dev, i)) { +- goto err; ++ vhost_vdpa_host_notifiers_uninit(dev, i - dev->vq_index); ++ break; + } + } + +- return; +- +-err: +- vhost_vdpa_host_notifiers_uninit(dev, i - dev->vq_index); +- return; ++ memory_region_transaction_commit(); + } + + static void vhost_vdpa_svq_cleanup(struct vhost_dev *dev) +-- +2.27.0 + diff --git a/vdpa-dev-get-iova-range-explicitly.patch b/vdpa-dev-get-iova-range-explicitly.patch new file mode 100644 index 00000000..f9f8e1a8 --- /dev/null +++ b/vdpa-dev-get-iova-range-explicitly.patch @@ -0,0 +1,104 @@ +From f5d338d28758db5066f199c35d56e0953edcc5d9 Mon Sep 17 00:00:00 2001 +From: Longpeng +Date: Sat, 24 Dec 2022 19:48:47 +0800 +Subject: [PATCH] vdpa-dev: get iova range explicitly + +In commit a585fad26b ("vdpa: request iova_range only once") we remove +GET_IOVA_RANGE form vhost_vdpa_init, the generic vdpa device will start +without iova_range populated, so the device won't work. Let's call +GET_IOVA_RANGE ioctl explicitly. + +Fixes: a585fad26b2e6ccc ("vdpa: request iova_range only once") +Signed-off-by: Longpeng +Message-Id: <20221224114848.3062-2-longpeng2@huawei.com> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Acked-by: Jason Wang +Signed-off-by: fangyi +--- + hw/virtio/vdpa-dev.c | 9 +++++++++ + hw/virtio/vhost-vdpa.c | 7 +++++++ + include/hw/virtio/vhost-vdpa.h | 2 ++ + net/vhost-vdpa.c | 8 -------- + 4 files changed, 18 insertions(+), 8 deletions(-) + +diff --git a/hw/virtio/vdpa-dev.c b/hw/virtio/vdpa-dev.c +index 465b08c0e3..254a213117 100644 +--- a/hw/virtio/vdpa-dev.c ++++ b/hw/virtio/vdpa-dev.c +@@ -53,6 +53,7 @@ static void vhost_vdpa_device_realize(DeviceState *dev, Error **errp) + { + VirtIODevice *vdev = VIRTIO_DEVICE(dev); + VhostVdpaDevice *v = VHOST_VDPA_DEVICE(vdev); ++ struct vhost_vdpa_iova_range iova_range; + uint16_t max_queue_size; + struct vhost_virtqueue *vqs; + int i, ret; +@@ -108,6 +109,14 @@ static void vhost_vdpa_device_realize(DeviceState *dev, Error **errp) + v->dev.backend_features = 0; + v->started = false; + ++ ret = vhost_vdpa_get_iova_range(v->vhostfd, &iova_range); ++ if (ret < 0) { ++ error_setg(errp, "vhost-vdpa-device: get iova range failed: %s", ++ strerror(-ret)); ++ goto free_vqs; ++ } ++ v->vdpa.iova_range = iova_range; ++ + ret = vhost_dev_init(&v->dev, &v->vdpa, VHOST_BACKEND_TYPE_VDPA, 0, NULL); + if (ret < 0) { + error_setg(errp, "vhost-vdpa-device: vhost initialization failed: %s", +diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c +index c9289e2c01..f93fac538c 100644 +--- a/hw/virtio/vhost-vdpa.c ++++ b/hw/virtio/vhost-vdpa.c +@@ -380,6 +380,13 @@ static int vhost_vdpa_add_status(struct vhost_dev *dev, uint8_t status) + return 0; + } + ++int vhost_vdpa_get_iova_range(int fd, struct vhost_vdpa_iova_range *iova_range) ++{ ++ int ret = ioctl(fd, VHOST_VDPA_GET_IOVA_RANGE, iova_range); ++ ++ return ret < 0 ? -errno : 0; ++} ++ + /* + * The use of this function is for requests that only need to be + * applied once. Typically such request occurs at the beginning +diff --git a/include/hw/virtio/vhost-vdpa.h b/include/hw/virtio/vhost-vdpa.h +index 45b969a311..7997f09a8d 100644 +--- a/include/hw/virtio/vhost-vdpa.h ++++ b/include/hw/virtio/vhost-vdpa.h +@@ -51,6 +51,8 @@ typedef struct vhost_vdpa { + VhostVDPAHostNotifier notifier[VIRTIO_QUEUE_MAX]; + } VhostVDPA; + ++int vhost_vdpa_get_iova_range(int fd, struct vhost_vdpa_iova_range *iova_range); ++ + int vhost_vdpa_dma_map(struct vhost_vdpa *v, uint32_t asid, hwaddr iova, + hwaddr size, void *vaddr, bool readonly); + int vhost_vdpa_dma_unmap(struct vhost_vdpa *v, uint32_t asid, hwaddr iova, +diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c +index 3dcf341722..3c370f2dc5 100644 +--- a/net/vhost-vdpa.c ++++ b/net/vhost-vdpa.c +@@ -717,14 +717,6 @@ static NetClientState *net_vhost_vdpa_init(NetClientState *peer, + return nc; + } + +-static int vhost_vdpa_get_iova_range(int fd, +- struct vhost_vdpa_iova_range *iova_range) +-{ +- int ret = ioctl(fd, VHOST_VDPA_GET_IOVA_RANGE, iova_range); +- +- return ret < 0 ? -errno : 0; +-} +- + static int vhost_vdpa_get_features(int fd, uint64_t *features, Error **errp) + { + int ret = ioctl(fd, VHOST_GET_FEATURES, features); +-- +2.27.0 + diff --git a/vdpa-do-not-block-migration-if-device-has-cvq-and-x-.patch b/vdpa-do-not-block-migration-if-device-has-cvq-and-x-.patch new file mode 100644 index 00000000..4956a0fd --- /dev/null +++ b/vdpa-do-not-block-migration-if-device-has-cvq-and-x-.patch @@ -0,0 +1,52 @@ +From 5bd89df7b5c1448f22f37a918569d0367458591b Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= +Date: Fri, 2 Jun 2023 16:38:52 +0200 +Subject: [PATCH] vdpa: do not block migration if device has cvq and x-svq=on +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +It was a mistake to forbid in all cases, as SVQ is already able to send +all the CVQ messages before start forwarding data vqs. It actually +caused a regression, making impossible to migrate device previously +migratable. + +Fixes: 36e4647247f2 ("vdpa: add vhost_vdpa_net_valid_svq_features") +Signed-off-by: Eugenio Pérez +Message-Id: <20230602143854.1879091-2-eperezma@redhat.com> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Tested-by: Lei Yang +Signed-off-by: fangyi +--- + net/vhost-vdpa.c | 11 +++++++---- + 1 file changed, 7 insertions(+), 4 deletions(-) + +diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c +index dc1b4c4be2..cdc54a7b54 100644 +--- a/net/vhost-vdpa.c ++++ b/net/vhost-vdpa.c +@@ -723,13 +723,16 @@ static NetClientState *net_vhost_vdpa_init(NetClientState *peer, + s->vhost_vdpa.shadow_vq_ops_opaque = s; + + /* +- * TODO: We cannot migrate devices with CVQ as there is no way to set +- * the device state (MAC, MQ, etc) before starting the datapath. ++ * TODO: We cannot migrate devices with CVQ and no x-svq enabled as ++ * there is no way to set the device state (MAC, MQ, etc) before ++ * starting the datapath. + * + * Migration blocker ownership now belongs to s->vhost_vdpa. + */ +- error_setg(&s->vhost_vdpa.migration_blocker, +- "net vdpa cannot migrate with CVQ feature"); ++ if (!svq) { ++ error_setg(&s->vhost_vdpa.migration_blocker, ++ "net vdpa cannot migrate with CVQ feature"); ++ } + } + ret = vhost_vdpa_add(nc, (void *)&s->vhost_vdpa, queue_pair_index, nvqs); + if (ret) { +-- +2.27.0 + diff --git a/vdpa-do-not-handle-VIRTIO_NET_F_GUEST_ANNOUNCE-in-vh.patch b/vdpa-do-not-handle-VIRTIO_NET_F_GUEST_ANNOUNCE-in-vh.patch new file mode 100644 index 00000000..1fcc0580 --- /dev/null +++ b/vdpa-do-not-handle-VIRTIO_NET_F_GUEST_ANNOUNCE-in-vh.patch @@ -0,0 +1,35 @@ +From 17cd7f504c47c532eae6b8ecfc21b0e5796e08da Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= +Date: Wed, 21 Dec 2022 12:50:15 +0100 +Subject: [PATCH] vdpa: do not handle VIRTIO_NET_F_GUEST_ANNOUNCE in vhost-vdpa +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +So qemu emulates it even in case the device does not support it. + +Signed-off-by: Eugenio Pérez +Acked-by: Jason Wang +Message-Id: <20221221115015.1400889-5-eperezma@redhat.com> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Signed-off-by: fangyi +--- + net/vhost-vdpa.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c +index 48dd9d15f6..3dcf341722 100644 +--- a/net/vhost-vdpa.c ++++ b/net/vhost-vdpa.c +@@ -72,7 +72,6 @@ const int vdpa_feature_bits[] = { + VIRTIO_F_RING_PACKED, + VIRTIO_NET_F_RSS, + VIRTIO_NET_F_HASH_REPORT, +- VIRTIO_NET_F_GUEST_ANNOUNCE, + VIRTIO_NET_F_STATUS, + VHOST_INVALID_FEATURE_BIT + }; +-- +2.27.0 + diff --git a/vdpa-do-not-save-failed-dma-maps-in-SVQ-iova-tree.patch b/vdpa-do-not-save-failed-dma-maps-in-SVQ-iova-tree.patch new file mode 100644 index 00000000..e1b02447 --- /dev/null +++ b/vdpa-do-not-save-failed-dma-maps-in-SVQ-iova-tree.patch @@ -0,0 +1,74 @@ +From 556aa09e618b0fb40f038b11eafc69750c71f26e Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= +Date: Tue, 23 Aug 2022 20:20:03 +0200 +Subject: [PATCH] vdpa: do not save failed dma maps in SVQ iova tree +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +If a map fails for whatever reason, it must not be saved in the tree. +Otherwise, qemu will try to unmap it in cleanup, leaving to more errors. + +Fixes: 34e3c94eda ("vdpa: Add custom IOTLB translations to SVQ") +Reported-by: Lei Yang +Signed-off-by: Eugenio Pérez +Acked-by: Jason Wang +Signed-off-by: Jason Wang +Signed-off-by: fangyi +--- + hw/virtio/vhost-vdpa.c | 20 +++++++++++++------- + 1 file changed, 13 insertions(+), 7 deletions(-) + +diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c +index c551665f5d..02dab41c42 100644 +--- a/hw/virtio/vhost-vdpa.c ++++ b/hw/virtio/vhost-vdpa.c +@@ -178,6 +178,7 @@ static void vhost_vdpa_listener_commit(MemoryListener *listener) + static void vhost_vdpa_listener_region_add(MemoryListener *listener, + MemoryRegionSection *section) + { ++ DMAMap mem_region = {}; + struct vhost_vdpa *v = container_of(listener, struct vhost_vdpa, listener); + hwaddr iova; + Int128 llend, llsize; +@@ -214,13 +215,13 @@ static void vhost_vdpa_listener_region_add(MemoryListener *listener, + + llsize = int128_sub(llend, int128_make64(iova)); + if (v->shadow_vqs_enabled) { +- DMAMap mem_region = { +- .translated_addr = (hwaddr)(uintptr_t)vaddr, +- .size = int128_get64(llsize) - 1, +- .perm = IOMMU_ACCESS_FLAG(true, section->readonly), +- }; ++ int r; + +- int r = vhost_iova_tree_map_alloc(v->iova_tree, &mem_region); ++ mem_region.translated_addr = (hwaddr)(uintptr_t)vaddr, ++ mem_region.size = int128_get64(llsize) - 1, ++ mem_region.perm = IOMMU_ACCESS_FLAG(true, section->readonly), ++ ++ r = vhost_iova_tree_map_alloc(v->iova_tree, &mem_region); + if (unlikely(r != IOVA_OK)) { + error_report("Can't allocate a mapping (%d)", r); + goto fail; +@@ -234,11 +235,16 @@ static void vhost_vdpa_listener_region_add(MemoryListener *listener, + vaddr, section->readonly); + if (ret) { + error_report("vhost vdpa map fail!"); +- goto fail; ++ goto fail_map; + } + + return; + ++fail_map: ++ if (v->shadow_vqs_enabled) { ++ vhost_iova_tree_remove(v->iova_tree, &mem_region); ++ } ++ + fail: + /* + * On the initfn path, store the first error in the container so we +-- +2.27.0 + diff --git a/vdpa-extract-vhost_vdpa_net_cvq_add-from-vhost_vdpa_.patch b/vdpa-extract-vhost_vdpa_net_cvq_add-from-vhost_vdpa_.patch new file mode 100644 index 00000000..5b2d4b50 --- /dev/null +++ b/vdpa-extract-vhost_vdpa_net_cvq_add-from-vhost_vdpa_.patch @@ -0,0 +1,144 @@ +From af761da9860bd79bd9d214c15d2d30010e73aafa Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= +Date: Tue, 23 Aug 2022 20:30:34 +0200 +Subject: [PATCH] vdpa: extract vhost_vdpa_net_cvq_add from + vhost_vdpa_net_handle_ctrl_avail +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +So we can reuse it to inject state messages. + +Signed-off-by: Eugenio Pérez +Acked-by: Jason Wang +-- +v7: +* Remove double free error + +v6: +* Do not assume in buffer sent to the device is sizeof(virtio_net_ctrl_ack) + +v5: +* Do not use an artificial !NULL VirtQueueElement +* Use only out size instead of iovec dev_buffers for these functions. + +Signed-off-by: Jason Wang +Signed-off-by: fangyi +--- + net/vhost-vdpa.c | 59 +++++++++++++++++++++++++++++++----------------- + 1 file changed, 38 insertions(+), 21 deletions(-) + +diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c +index 882f5ee89c..b24e0919d0 100644 +--- a/net/vhost-vdpa.c ++++ b/net/vhost-vdpa.c +@@ -339,6 +339,38 @@ static void vhost_vdpa_net_cvq_stop(NetClientState *nc) + } + } + ++static ssize_t vhost_vdpa_net_cvq_add(VhostVDPAState *s, size_t out_len, ++ size_t in_len) ++{ ++ /* Buffers for the device */ ++ const struct iovec out = { ++ .iov_base = s->cvq_cmd_out_buffer, ++ .iov_len = out_len, ++ }; ++ const struct iovec in = { ++ .iov_base = s->cvq_cmd_in_buffer, ++ .iov_len = sizeof(virtio_net_ctrl_ack), ++ }; ++ VhostShadowVirtqueue *svq = g_ptr_array_index(s->vhost_vdpa.shadow_vqs, 0); ++ int r; ++ ++ r = vhost_svq_add(svq, &out, 1, &in, 1, NULL); ++ if (unlikely(r != 0)) { ++ if (unlikely(r == -ENOSPC)) { ++ qemu_log_mask(LOG_GUEST_ERROR, "%s: No space on device queue\n", ++ __func__); ++ } ++ return r; ++ } ++ ++ /* ++ * We can poll here since we've had BQL from the time we sent the ++ * descriptor. Also, we need to take the answer before SVQ pulls by itself, ++ * when BQL is released ++ */ ++ return vhost_svq_poll(svq); ++} ++ + static NetClientInfo net_vhost_vdpa_cvq_info = { + .type = NET_CLIENT_DRIVER_VHOST_VDPA, + .size = sizeof(VhostVDPAState), +@@ -395,23 +427,18 @@ static int vhost_vdpa_net_handle_ctrl_avail(VhostShadowVirtqueue *svq, + void *opaque) + { + VhostVDPAState *s = opaque; +- size_t in_len, dev_written; ++ size_t in_len; + virtio_net_ctrl_ack status = VIRTIO_NET_ERR; + /* Out buffer sent to both the vdpa device and the device model */ + struct iovec out = { + .iov_base = s->cvq_cmd_out_buffer, + }; +- /* In buffer sent to the device */ +- const struct iovec dev_in = { +- .iov_base = s->cvq_cmd_in_buffer, +- .iov_len = sizeof(virtio_net_ctrl_ack), +- }; + /* in buffer used for device model */ + const struct iovec in = { + .iov_base = &status, + .iov_len = sizeof(status), + }; +- int r = -EINVAL; ++ ssize_t dev_written = -EINVAL; + bool ok; + + out.iov_len = iov_to_buf(elem->out_sg, elem->out_num, 0, +@@ -422,21 +449,11 @@ static int vhost_vdpa_net_handle_ctrl_avail(VhostShadowVirtqueue *svq, + goto out; + } + +- r = vhost_svq_add(svq, &out, 1, &dev_in, 1, elem); +- if (unlikely(r != 0)) { +- if (unlikely(r == -ENOSPC)) { +- qemu_log_mask(LOG_GUEST_ERROR, "%s: No space on device queue\n", +- __func__); +- } ++ dev_written = vhost_vdpa_net_cvq_add(s, out.iov_len, sizeof(status)); ++ if (unlikely(dev_written < 0)) { + goto out; + } + +- /* +- * We can poll here since we've had BQL from the time we sent the +- * descriptor. Also, we need to take the answer before SVQ pulls by itself, +- * when BQL is released +- */ +- dev_written = vhost_svq_poll(svq); + if (unlikely(dev_written < sizeof(status))) { + error_report("Insufficient written data (%zu)", dev_written); + goto out; +@@ -444,7 +461,7 @@ static int vhost_vdpa_net_handle_ctrl_avail(VhostShadowVirtqueue *svq, + + memcpy(&status, s->cvq_cmd_in_buffer, sizeof(status)); + if (status != VIRTIO_NET_OK) { +- goto out; ++ return VIRTIO_NET_ERR; + } + + status = VIRTIO_NET_ERR; +@@ -461,7 +478,7 @@ out: + } + vhost_svq_push_elem(svq, elem, MIN(in_len, sizeof(status))); + g_free(elem); +- return r; ++ return dev_written < 0 ? dev_written : 0; + } + + static const VhostShadowVirtqueueOps vhost_vdpa_net_svq_ops = { +-- +2.27.0 + diff --git a/vdpa-extract-vhost_vdpa_net_load_mac-from-vhost_vdpa.patch b/vdpa-extract-vhost_vdpa_net_load_mac-from-vhost_vdpa.patch new file mode 100644 index 00000000..8695f98b --- /dev/null +++ b/vdpa-extract-vhost_vdpa_net_load_mac-from-vhost_vdpa.patch @@ -0,0 +1,106 @@ +From 2038b0811acd3255d315354c8468bc565a51a4af Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= +Date: Tue, 6 Sep 2022 17:07:15 +0200 +Subject: [PATCH] vdpa: extract vhost_vdpa_net_load_mac from + vhost_vdpa_net_load +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Since there may be many commands we need to issue to load the NIC +state, let's split them in individual functions + +Signed-off-by: Eugenio Pérez +Signed-off-by: Jason Wang +Signed-off-by: fangyi +--- + net/vhost-vdpa.c | 62 +++++++++++++++++++++++++++++++----------------- + 1 file changed, 40 insertions(+), 22 deletions(-) + +diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c +index 2700ef656f..15cd38b52e 100644 +--- a/net/vhost-vdpa.c ++++ b/net/vhost-vdpa.c +@@ -373,12 +373,47 @@ static ssize_t vhost_vdpa_net_cvq_add(VhostVDPAState *s, size_t out_len, + return vhost_svq_poll(svq); + } + ++static ssize_t vhost_vdpa_net_load_cmd(VhostVDPAState *s, uint8_t class, ++ uint8_t cmd, const void *data, ++ size_t data_size) ++{ ++ const struct virtio_net_ctrl_hdr ctrl = { ++ .class = class, ++ .cmd = cmd, ++ }; ++ ++ assert(data_size < vhost_vdpa_net_cvq_cmd_page_len() - sizeof(ctrl)); ++ ++ memcpy(s->cvq_cmd_out_buffer, &ctrl, sizeof(ctrl)); ++ memcpy(s->cvq_cmd_out_buffer + sizeof(ctrl), data, data_size); ++ ++ return vhost_vdpa_net_cvq_add(s, sizeof(ctrl) + data_size, ++ sizeof(virtio_net_ctrl_ack)); ++} ++ ++static int vhost_vdpa_net_load_mac(VhostVDPAState *s, const VirtIONet *n) ++{ ++ uint64_t features = n->parent_obj.guest_features; ++ if (features & BIT_ULL(VIRTIO_NET_F_CTRL_MAC_ADDR)) { ++ ssize_t dev_written = vhost_vdpa_net_load_cmd(s, VIRTIO_NET_CTRL_MAC, ++ VIRTIO_NET_CTRL_MAC_ADDR_SET, ++ n->mac, sizeof(n->mac)); ++ if (unlikely(dev_written < 0)) { ++ return dev_written; ++ } ++ ++ return *s->status != VIRTIO_NET_OK; ++ } ++ ++ return 0; ++} ++ + static int vhost_vdpa_net_load(NetClientState *nc) + { + VhostVDPAState *s = DO_UPCAST(VhostVDPAState, nc, nc); +- const struct vhost_vdpa *v = &s->vhost_vdpa; ++ struct vhost_vdpa *v = &s->vhost_vdpa; + const VirtIONet *n; +- uint64_t features; ++ int r; + + assert(nc->info->type == NET_CLIENT_DRIVER_VHOST_VDPA); + +@@ -387,26 +422,9 @@ static int vhost_vdpa_net_load(NetClientState *nc) + } + + n = VIRTIO_NET(v->dev->vdev); +- features = n->parent_obj.guest_features; +- if (features & BIT_ULL(VIRTIO_NET_F_CTRL_MAC_ADDR)) { +- const struct virtio_net_ctrl_hdr ctrl = { +- .class = VIRTIO_NET_CTRL_MAC, +- .cmd = VIRTIO_NET_CTRL_MAC_ADDR_SET, +- }; +- char *cursor = s->cvq_cmd_out_buffer; +- ssize_t dev_written; +- +- memcpy(cursor, &ctrl, sizeof(ctrl)); +- cursor += sizeof(ctrl); +- memcpy(cursor, n->mac, sizeof(n->mac)); +- +- dev_written = vhost_vdpa_net_cvq_add(s, sizeof(ctrl) + sizeof(n->mac), +- sizeof(virtio_net_ctrl_ack)); +- if (unlikely(dev_written < 0)) { +- return dev_written; +- } +- +- return *s->status != VIRTIO_NET_OK; ++ r = vhost_vdpa_net_load_mac(s, n); ++ if (unlikely(r < 0)) { ++ return r; + } + + return 0; +-- +2.27.0 + diff --git a/vdpa-fix-VHOST_BACKEND_F_IOTLB_ASID-flag-check.patch b/vdpa-fix-VHOST_BACKEND_F_IOTLB_ASID-flag-check.patch new file mode 100644 index 00000000..c2f2a879 --- /dev/null +++ b/vdpa-fix-VHOST_BACKEND_F_IOTLB_ASID-flag-check.patch @@ -0,0 +1,38 @@ +From 404c9b2cb537a42be18a1b1aaf32df662ed951e0 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= +Date: Tue, 17 Jan 2023 11:53:08 +0100 +Subject: [PATCH] vdpa: fix VHOST_BACKEND_F_IOTLB_ASID flag check +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +VHOST_BACKEND_F_IOTLB_ASID is the feature bit, not the bitmask. Since +the device under test also provided VHOST_BACKEND_F_IOTLB_MSG_V2 and +VHOST_BACKEND_F_IOTLB_BATCH, this went unnoticed. + +Fixes: c1a1008685 ("vdpa: always start CVQ in SVQ mode if possible") +Signed-off-by: Eugenio Pérez +Reviewed-by: Michael S. Tsirkin +Acked-by: Jason Wang +Signed-off-by: Jason Wang +Signed-off-by: fangyi +--- + net/vhost-vdpa.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c +index cdc54a7b54..a1b931ae2c 100644 +--- a/net/vhost-vdpa.c ++++ b/net/vhost-vdpa.c +@@ -391,7 +391,7 @@ static int vhost_vdpa_net_cvq_start(NetClientState *nc) + g_strerror(errno), errno); + return -1; + } +- if (!(backend_features & VHOST_BACKEND_F_IOTLB_ASID) || ++ if (!(backend_features & BIT_ULL(VHOST_BACKEND_F_IOTLB_ASID)) || + !vhost_vdpa_net_valid_svq_features(v->dev->features, NULL)) { + return 0; + } +-- +2.27.0 + diff --git a/vdpa-fix-not-using-CVQ-buffer-in-case-of-error.patch b/vdpa-fix-not-using-CVQ-buffer-in-case-of-error.patch new file mode 100644 index 00000000..4603f6ed --- /dev/null +++ b/vdpa-fix-not-using-CVQ-buffer-in-case-of-error.patch @@ -0,0 +1,39 @@ +From 5da8eddfa24d42a3ef60e111becafa29549e7100 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= +Date: Fri, 2 Jun 2023 19:34:51 +0200 +Subject: [PATCH] vdpa: fix not using CVQ buffer in case of error +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Bug introducing when refactoring. Otherway, the guest never received +the used buffer. + +Fixes: be4278b65fc1 ("vdpa: extract vhost_vdpa_net_cvq_add from vhost_vdpa_net_handle_ctrl_avail") +Signed-off-by: Eugenio Pérez +Message-Id: <20230602173451.1917999-1-eperezma@redhat.com> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Acked-by: Jason Wang +Tested-by: Lei Yang +Signed-off-by: fangyi +--- + net/vhost-vdpa.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c +index 94f74b54ae..afca8740bc 100644 +--- a/net/vhost-vdpa.c ++++ b/net/vhost-vdpa.c +@@ -642,7 +642,7 @@ static int vhost_vdpa_net_handle_ctrl_avail(VhostShadowVirtqueue *svq, + } + + if (*s->status != VIRTIO_NET_OK) { +- return VIRTIO_NET_ERR; ++ goto out; + } + + status = VIRTIO_NET_ERR; +-- +2.27.0 + diff --git a/vdpa-handle-VIRTIO_NET_CTRL_ANNOUNCE-in-vhost_vdpa_n.patch b/vdpa-handle-VIRTIO_NET_CTRL_ANNOUNCE-in-vhost_vdpa_n.patch new file mode 100644 index 00000000..7501a15d --- /dev/null +++ b/vdpa-handle-VIRTIO_NET_CTRL_ANNOUNCE-in-vhost_vdpa_n.patch @@ -0,0 +1,51 @@ +From f6fa1b81efa3ac728a2c528b3c694d8cb5f932f1 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= +Date: Wed, 21 Dec 2022 12:50:14 +0100 +Subject: [PATCH] vdpa: handle VIRTIO_NET_CTRL_ANNOUNCE in + vhost_vdpa_net_handle_ctrl_avail +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Since this capability is emulated by qemu shadowed CVQ cannot forward it +to the device. Process all that command within qemu. + +Signed-off-by: Eugenio Pérez +Message-Id: <20221221115015.1400889-4-eperezma@redhat.com> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Acked-by: Jason Wang +Signed-off-by: fangyi +--- + net/vhost-vdpa.c | 15 ++++++++++++--- + 1 file changed, 12 insertions(+), 3 deletions(-) + +diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c +index 24c4c2ef51..48dd9d15f6 100644 +--- a/net/vhost-vdpa.c ++++ b/net/vhost-vdpa.c +@@ -623,9 +623,18 @@ static int vhost_vdpa_net_handle_ctrl_avail(VhostShadowVirtqueue *svq, + out.iov_len = iov_to_buf(elem->out_sg, elem->out_num, 0, + s->cvq_cmd_out_buffer, + vhost_vdpa_net_cvq_cmd_len()); +- dev_written = vhost_vdpa_net_cvq_add(s, out.iov_len, sizeof(status)); +- if (unlikely(dev_written < 0)) { +- goto out; ++ if (*(uint8_t *)s->cvq_cmd_out_buffer == VIRTIO_NET_CTRL_ANNOUNCE) { ++ /* ++ * Guest announce capability is emulated by qemu, so don't forward to ++ * the device. ++ */ ++ dev_written = sizeof(status); ++ *s->status = VIRTIO_NET_OK; ++ } else { ++ dev_written = vhost_vdpa_net_cvq_add(s, out.iov_len, sizeof(status)); ++ if (unlikely(dev_written < 0)) { ++ goto out; ++ } + } + + if (unlikely(dev_written < sizeof(status))) { +-- +2.27.0 + diff --git a/vdpa-harden-the-error-path-if-get_iova_range-failed.patch b/vdpa-harden-the-error-path-if-get_iova_range-failed.patch new file mode 100644 index 00000000..af79c277 --- /dev/null +++ b/vdpa-harden-the-error-path-if-get_iova_range-failed.patch @@ -0,0 +1,39 @@ +From fe4dd977b4dec6a089992566bda4b29136ed62c9 Mon Sep 17 00:00:00 2001 +From: Longpeng +Date: Sat, 24 Dec 2022 19:48:48 +0800 +Subject: [PATCH] vdpa: harden the error path if get_iova_range failed + +We should stop if the GET_IOVA_RANGE ioctl failed. + +Signed-off-by: Longpeng +Message-Id: <20221224114848.3062-3-longpeng2@huawei.com> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Acked-by: Jason Wang +Signed-off-by: fangyi +--- + net/vhost-vdpa.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c +index 3c370f2dc5..fd5dc8c6aa 100644 +--- a/net/vhost-vdpa.c ++++ b/net/vhost-vdpa.c +@@ -812,7 +812,13 @@ int net_init_vhost_vdpa(const Netdev *netdev, const char *name, + return queue_pairs; + } + +- vhost_vdpa_get_iova_range(vdpa_device_fd, &iova_range); ++ r = vhost_vdpa_get_iova_range(vdpa_device_fd, &iova_range); ++ if (unlikely(r < 0)) { ++ error_setg(errp, "vhost-vdpa: get iova range failed: %s", ++ strerror(-r)); ++ goto err; ++ } ++ + if (opts->x_svq) { + if (!vhost_vdpa_net_valid_svq_features(features, errp)) { + goto err_svq; +-- +2.27.0 + diff --git a/vdpa-manual-forward-CVQ-buffers.patch b/vdpa-manual-forward-CVQ-buffers.patch new file mode 100644 index 00000000..79e47ce9 --- /dev/null +++ b/vdpa-manual-forward-CVQ-buffers.patch @@ -0,0 +1,146 @@ +From 1fd9319e66153dc18bc4a6adfd81f1a0bc6d3a2f Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= +Date: Wed, 20 Jul 2022 08:59:42 +0200 +Subject: [PATCH] vdpa: manual forward CVQ buffers +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Do a simple forwarding of CVQ buffers, the same work SVQ could do but +through callbacks. No functional change intended. + +Signed-off-by: Eugenio Pérez +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Jason Wang +Signed-off-by: fangyi +--- + hw/virtio/vhost-vdpa.c | 3 +- + include/hw/virtio/vhost-vdpa.h | 3 ++ + net/vhost-vdpa.c | 57 ++++++++++++++++++++++++++++++++++ + 3 files changed, 62 insertions(+), 1 deletion(-) + +diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c +index 8e962f511d..31b58aec59 100644 +--- a/hw/virtio/vhost-vdpa.c ++++ b/hw/virtio/vhost-vdpa.c +@@ -421,7 +421,8 @@ static int vhost_vdpa_init_svq(struct vhost_dev *hdev, struct vhost_vdpa *v, + for (unsigned n = 0; n < hdev->nvqs; ++n) { + g_autoptr(VhostShadowVirtqueue) svq; + +- svq = vhost_svq_new(v->iova_tree, NULL, NULL); ++ svq = vhost_svq_new(v->iova_tree, v->shadow_vq_ops, ++ v->shadow_vq_ops_opaque); + if (unlikely(!svq)) { + error_setg(errp, "Cannot create svq %u", n); + return -1; +diff --git a/include/hw/virtio/vhost-vdpa.h b/include/hw/virtio/vhost-vdpa.h +index 7214eb47dc..1111d85643 100644 +--- a/include/hw/virtio/vhost-vdpa.h ++++ b/include/hw/virtio/vhost-vdpa.h +@@ -15,6 +15,7 @@ + #include + + #include "hw/virtio/vhost-iova-tree.h" ++#include "hw/virtio/vhost-shadow-virtqueue.h" + #include "hw/virtio/virtio.h" + #include "standard-headers/linux/vhost_types.h" + +@@ -35,6 +36,8 @@ typedef struct vhost_vdpa { + /* IOVA mapping used by the Shadow Virtqueue */ + VhostIOVATree *iova_tree; + GPtrArray *shadow_vqs; ++ const VhostShadowVirtqueueOps *shadow_vq_ops; ++ void *shadow_vq_ops_opaque; + struct vhost_dev *dev; + VhostVDPAHostNotifier notifier[VIRTIO_QUEUE_MAX]; + } VhostVDPA; +diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c +index 7201c79116..53a14bc756 100644 +--- a/net/vhost-vdpa.c ++++ b/net/vhost-vdpa.c +@@ -11,11 +11,13 @@ + + #include "qemu/osdep.h" + #include "clients.h" ++#include "hw/virtio/virtio-net.h" + #include "net/vhost_net.h" + #include "net/vhost-vdpa.h" + #include "hw/virtio/vhost-vdpa.h" + #include "qemu/config-file.h" + #include "qemu/error-report.h" ++#include "qemu/log.h" + #include "qemu/option.h" + #include "qapi/error.h" + #include +@@ -195,6 +197,57 @@ static NetClientInfo net_vhost_vdpa_info = { + .check_peer_type = vhost_vdpa_check_peer_type, + }; + ++/** ++ * Forward buffer for the moment. ++ */ ++static int vhost_vdpa_net_handle_ctrl_avail(VhostShadowVirtqueue *svq, ++ VirtQueueElement *elem, ++ void *opaque) ++{ ++ unsigned int n = elem->out_num + elem->in_num; ++ g_autofree struct iovec *dev_buffers = g_new(struct iovec, n); ++ size_t in_len, dev_written; ++ virtio_net_ctrl_ack status = VIRTIO_NET_ERR; ++ int r; ++ ++ memcpy(dev_buffers, elem->out_sg, elem->out_num); ++ memcpy(dev_buffers + elem->out_num, elem->in_sg, elem->in_num); ++ ++ r = vhost_svq_add(svq, &dev_buffers[0], elem->out_num, &dev_buffers[1], ++ elem->in_num, elem); ++ if (unlikely(r != 0)) { ++ if (unlikely(r == -ENOSPC)) { ++ qemu_log_mask(LOG_GUEST_ERROR, "%s: No space on device queue\n", ++ __func__); ++ } ++ goto out; ++ } ++ ++ /* ++ * We can poll here since we've had BQL from the time we sent the ++ * descriptor. Also, we need to take the answer before SVQ pulls by itself, ++ * when BQL is released ++ */ ++ dev_written = vhost_svq_poll(svq); ++ if (unlikely(dev_written < sizeof(status))) { ++ error_report("Insufficient written data (%zu)", dev_written); ++ } ++ ++out: ++ in_len = iov_from_buf(elem->in_sg, elem->in_num, 0, &status, ++ sizeof(status)); ++ if (unlikely(in_len < sizeof(status))) { ++ error_report("Bad device CVQ written length"); ++ } ++ vhost_svq_push_elem(svq, elem, MIN(in_len, sizeof(status))); ++ g_free(elem); ++ return r; ++} ++ ++static const VhostShadowVirtqueueOps vhost_vdpa_net_svq_ops = { ++ .avail_handler = vhost_vdpa_net_handle_ctrl_avail, ++}; ++ + static NetClientState *net_vhost_vdpa_init(NetClientState *peer, + const char *device, + const char *name, +@@ -219,6 +272,10 @@ static NetClientState *net_vhost_vdpa_init(NetClientState *peer, + + s->vhost_vdpa.device_fd = vdpa_device_fd; + s->vhost_vdpa.index = queue_pair_index; ++ if (!is_datapath) { ++ s->vhost_vdpa.shadow_vq_ops = &vhost_vdpa_net_svq_ops; ++ s->vhost_vdpa.shadow_vq_ops_opaque = s; ++ } + ret = vhost_vdpa_add(nc, (void *)&s->vhost_vdpa, queue_pair_index, nvqs); + if (ret) { + qemu_del_net_client(nc); +-- +2.27.0 + diff --git a/vdpa-move-SVQ-vring-features-check-to-net.patch b/vdpa-move-SVQ-vring-features-check-to-net.patch new file mode 100644 index 00000000..f5eca1af --- /dev/null +++ b/vdpa-move-SVQ-vring-features-check-to-net.patch @@ -0,0 +1,110 @@ +From 1d56b9b5446b79613ed1668a1afea19a9a7df875 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= +Date: Thu, 15 Dec 2022 12:31:39 +0100 +Subject: [PATCH] vdpa: move SVQ vring features check to net/ +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The next patches will start control SVQ if possible. However, we don't +know if that will be possible at qemu boot anymore. + +Since the moved checks will be already evaluated at net/ to know if it +is ok to shadow CVQ, move them. + +Signed-off-by: Eugenio Pérez +Acked-by: Jason Wang +Message-Id: <20221215113144.322011-8-eperezma@redhat.com> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Signed-off-by: fangyi +--- + hw/virtio/vhost-vdpa.c | 32 ++------------------------------ + net/vhost-vdpa.c | 3 ++- + 2 files changed, 4 insertions(+), 31 deletions(-) + +diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c +index c0e645ec13..59bfdbfc24 100644 +--- a/hw/virtio/vhost-vdpa.c ++++ b/hw/virtio/vhost-vdpa.c +@@ -391,29 +391,9 @@ static int vhost_vdpa_get_dev_features(struct vhost_dev *dev, + return ret; + } + +-static int vhost_vdpa_init_svq(struct vhost_dev *hdev, struct vhost_vdpa *v, +- Error **errp) ++static void vhost_vdpa_init_svq(struct vhost_dev *hdev, struct vhost_vdpa *v) + { + g_autoptr(GPtrArray) shadow_vqs = NULL; +- uint64_t dev_features, svq_features; +- int r; +- bool ok; +- +- if (!v->shadow_vqs_enabled) { +- return 0; +- } +- +- r = vhost_vdpa_get_dev_features(hdev, &dev_features); +- if (r != 0) { +- error_setg_errno(errp, -r, "Can't get vdpa device features"); +- return r; +- } +- +- svq_features = dev_features; +- ok = vhost_svq_valid_features(svq_features, errp); +- if (unlikely(!ok)) { +- return -1; +- } + + shadow_vqs = g_ptr_array_new_full(hdev->nvqs, vhost_svq_free); + for (unsigned n = 0; n < hdev->nvqs; ++n) { +@@ -425,7 +405,6 @@ static int vhost_vdpa_init_svq(struct vhost_dev *hdev, struct vhost_vdpa *v, + } + + v->shadow_vqs = g_steal_pointer(&shadow_vqs); +- return 0; + } + + static int vhost_vdpa_init(struct vhost_dev *dev, void *opaque, Error **errp) +@@ -450,10 +429,7 @@ static int vhost_vdpa_init(struct vhost_dev *dev, void *opaque, Error **errp) + dev->opaque = opaque ; + v->listener = vhost_vdpa_memory_listener; + v->msg_type = VHOST_IOTLB_MSG_V2; +- ret = vhost_vdpa_init_svq(dev, v, errp); +- if (ret) { +- goto err; +- } ++ vhost_vdpa_init_svq(dev, v); + + if (!vhost_vdpa_first_dev(dev)) { + return 0; +@@ -463,10 +439,6 @@ static int vhost_vdpa_init(struct vhost_dev *dev, void *opaque, Error **errp) + VIRTIO_CONFIG_S_DRIVER); + + return 0; +- +-err: +- ram_block_discard_disable(false); +- return ret; + } + + static void vhost_vdpa_host_notifier_uninit(struct vhost_dev *dev, +diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c +index be056a2553..e250d34462 100644 +--- a/net/vhost-vdpa.c ++++ b/net/vhost-vdpa.c +@@ -116,9 +116,10 @@ static bool vhost_vdpa_net_valid_svq_features(uint64_t features, Error **errp) + if (invalid_dev_features) { + error_setg(errp, "vdpa svq does not work with features 0x%" PRIx64, + invalid_dev_features); ++ return false; + } + +- return !invalid_dev_features; ++ return vhost_svq_valid_features(features, errp); + } + + static int vhost_vdpa_net_check_device_id(struct vhost_net *net) +-- +2.27.0 + diff --git a/vdpa-net-block-migration-if-the-device-has-CVQ.patch b/vdpa-net-block-migration-if-the-device-has-CVQ.patch new file mode 100644 index 00000000..a700f8d4 --- /dev/null +++ b/vdpa-net-block-migration-if-the-device-has-CVQ.patch @@ -0,0 +1,70 @@ +From d97454d68f90b441d3fa19c496a7fe6916f50e31 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= +Date: Fri, 3 Mar 2023 18:24:41 +0100 +Subject: [PATCH] vdpa net: block migration if the device has CVQ +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Devices with CVQ need to migrate state beyond vq state. Leaving this to +future series. + +Signed-off-by: Eugenio Pérez +Message-Id: <20230303172445.1089785-11-eperezma@redhat.com> +Tested-by: Lei Yang +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Signed-off-by: fangyi +--- + hw/virtio/vhost-vdpa.c | 1 + + include/hw/virtio/vhost-vdpa.h | 1 + + net/vhost-vdpa.c | 9 +++++++++ + 3 files changed, 11 insertions(+) + +diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c +index f5d816f5ec..dd1ba8878c 100644 +--- a/hw/virtio/vhost-vdpa.c ++++ b/hw/virtio/vhost-vdpa.c +@@ -450,6 +450,7 @@ static int vhost_vdpa_init(struct vhost_dev *dev, void *opaque, Error **errp) + v->msg_type = VHOST_IOTLB_MSG_V2; + vhost_vdpa_init_svq(dev, v); + ++ error_propagate(&dev->migration_blocker, v->migration_blocker); + if (!vhost_vdpa_first_dev(dev)) { + return 0; + } +diff --git a/include/hw/virtio/vhost-vdpa.h b/include/hw/virtio/vhost-vdpa.h +index 7997f09a8d..620a0f70ab 100644 +--- a/include/hw/virtio/vhost-vdpa.h ++++ b/include/hw/virtio/vhost-vdpa.h +@@ -48,6 +48,7 @@ typedef struct vhost_vdpa { + const VhostShadowVirtqueueOps *shadow_vq_ops; + void *shadow_vq_ops_opaque; + struct vhost_dev *dev; ++ Error *migration_blocker; + VhostVDPAHostNotifier notifier[VIRTIO_QUEUE_MAX]; + } VhostVDPA; + +diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c +index 8192045735..dc1b4c4be2 100644 +--- a/net/vhost-vdpa.c ++++ b/net/vhost-vdpa.c +@@ -721,6 +721,15 @@ static NetClientState *net_vhost_vdpa_init(NetClientState *peer, + + s->vhost_vdpa.shadow_vq_ops = &vhost_vdpa_net_svq_ops; + s->vhost_vdpa.shadow_vq_ops_opaque = s; ++ ++ /* ++ * TODO: We cannot migrate devices with CVQ as there is no way to set ++ * the device state (MAC, MQ, etc) before starting the datapath. ++ * ++ * Migration blocker ownership now belongs to s->vhost_vdpa. ++ */ ++ error_setg(&s->vhost_vdpa.migration_blocker, ++ "net vdpa cannot migrate with CVQ feature"); + } + ret = vhost_vdpa_add(nc, (void *)&s->vhost_vdpa, queue_pair_index, nvqs); + if (ret) { +-- +2.27.0 + diff --git a/vdpa-request-iova_range-only-once.patch b/vdpa-request-iova_range-only-once.patch new file mode 100644 index 00000000..c9ce07a7 --- /dev/null +++ b/vdpa-request-iova_range-only-once.patch @@ -0,0 +1,137 @@ +From 5ff455d55b2d58a726d2557076e0f5401496de02 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= +Date: Thu, 15 Dec 2022 12:31:38 +0100 +Subject: [PATCH] vdpa: request iova_range only once +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Currently iova range is requested once per queue pair in the case of +net. Reduce the number of ioctls asking it once at initialization and +reusing that value for each vhost_vdpa. + +Signed-off-by: Eugenio Pérez +Message-Id: <20221215113144.322011-7-eperezma@redhat.com> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Acked-by: Jason Wang +Signed-off-by: fangyi +--- + hw/virtio/vhost-vdpa.c | 15 --------------- + net/vhost-vdpa.c | 27 ++++++++++++++------------- + 2 files changed, 14 insertions(+), 28 deletions(-) + +diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c +index 23e715b05c..c0e645ec13 100644 +--- a/hw/virtio/vhost-vdpa.c ++++ b/hw/virtio/vhost-vdpa.c +@@ -367,19 +367,6 @@ static int vhost_vdpa_add_status(struct vhost_dev *dev, uint8_t status) + return 0; + } + +-static void vhost_vdpa_get_iova_range(struct vhost_vdpa *v) +-{ +- int ret = vhost_vdpa_call(v->dev, VHOST_VDPA_GET_IOVA_RANGE, +- &v->iova_range); +- if (ret != 0) { +- v->iova_range.first = 0; +- v->iova_range.last = UINT64_MAX; +- } +- +- trace_vhost_vdpa_get_iova_range(v->dev, v->iova_range.first, +- v->iova_range.last); +-} +- + /* + * The use of this function is for requests that only need to be + * applied once. Typically such request occurs at the beginning +@@ -468,8 +455,6 @@ static int vhost_vdpa_init(struct vhost_dev *dev, void *opaque, Error **errp) + goto err; + } + +- vhost_vdpa_get_iova_range(v); +- + if (!vhost_vdpa_first_dev(dev)) { + return 0; + } +diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c +index 217d2545c1..be056a2553 100644 +--- a/net/vhost-vdpa.c ++++ b/net/vhost-vdpa.c +@@ -548,14 +548,15 @@ static const VhostShadowVirtqueueOps vhost_vdpa_net_svq_ops = { + }; + + static NetClientState *net_vhost_vdpa_init(NetClientState *peer, +- const char *device, +- const char *name, +- int vdpa_device_fd, +- int queue_pair_index, +- int nvqs, +- bool is_datapath, +- bool svq, +- VhostIOVATree *iova_tree) ++ const char *device, ++ const char *name, ++ int vdpa_device_fd, ++ int queue_pair_index, ++ int nvqs, ++ bool is_datapath, ++ bool svq, ++ struct vhost_vdpa_iova_range iova_range, ++ VhostIOVATree *iova_tree) + { + NetClientState *nc = NULL; + VhostVDPAState *s; +@@ -574,6 +575,7 @@ static NetClientState *net_vhost_vdpa_init(NetClientState *peer, + s->vhost_vdpa.device_fd = vdpa_device_fd; + s->vhost_vdpa.index = queue_pair_index; + s->vhost_vdpa.shadow_vqs_enabled = svq; ++ s->vhost_vdpa.iova_range = iova_range; + s->vhost_vdpa.iova_tree = iova_tree; + if (!is_datapath) { + s->cvq_cmd_out_buffer = qemu_memalign(qemu_real_host_page_size, +@@ -653,6 +655,7 @@ int net_init_vhost_vdpa(const Netdev *netdev, const char *name, + int vdpa_device_fd; + g_autofree NetClientState **ncs = NULL; + g_autoptr(VhostIOVATree) iova_tree = NULL; ++ struct vhost_vdpa_iova_range iova_range; + NetClientState *nc; + int queue_pairs, r, i = 0, has_cvq = 0; + +@@ -696,14 +699,12 @@ int net_init_vhost_vdpa(const Netdev *netdev, const char *name, + return queue_pairs; + } + ++ vhost_vdpa_get_iova_range(vdpa_device_fd, &iova_range); + if (opts->x_svq) { +- struct vhost_vdpa_iova_range iova_range; +- + if (!vhost_vdpa_net_valid_svq_features(features, errp)) { + goto err_svq; + } + +- vhost_vdpa_get_iova_range(vdpa_device_fd, &iova_range); + iova_tree = vhost_iova_tree_new(iova_range.first, iova_range.last); + } + +@@ -712,7 +713,7 @@ int net_init_vhost_vdpa(const Netdev *netdev, const char *name, + for (i = 0; i < queue_pairs; i++) { + ncs[i] = net_vhost_vdpa_init(peer, TYPE_VHOST_VDPA, name, + vdpa_device_fd, i, 2, true, opts->x_svq, +- iova_tree); ++ iova_range, iova_tree); + if (!ncs[i]) + goto err; + } +@@ -720,7 +721,7 @@ int net_init_vhost_vdpa(const Netdev *netdev, const char *name, + if (has_cvq) { + nc = net_vhost_vdpa_init(peer, TYPE_VHOST_VDPA, name, + vdpa_device_fd, i, 1, false, +- opts->x_svq, iova_tree); ++ opts->x_svq, iova_range, iova_tree); + if (!nc) + goto err; + } +-- +2.27.0 + diff --git a/vdpa-stop-all-svq-on-device-deletion.patch b/vdpa-stop-all-svq-on-device-deletion.patch new file mode 100644 index 00000000..a6cb17e1 --- /dev/null +++ b/vdpa-stop-all-svq-on-device-deletion.patch @@ -0,0 +1,73 @@ +From 6b9c4a2607b88faf611da724ead81dc89a7b185b Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= +Date: Thu, 9 Feb 2023 18:00:04 +0100 +Subject: [PATCH] vdpa: stop all svq on device deletion +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Not stopping them leave the device in a bad state when virtio-net +fronted device is unplugged with device_del monitor command. + +This is not triggable in regular poweroff or qemu forces shutdown +because cleanup is called right after vhost_vdpa_dev_start(false). But +devices hot unplug does not call vdpa device cleanups. This lead to all +the vhost_vdpa devices without stop the SVQ but the last. + +Fix it and clean the code, making it symmetric with +vhost_vdpa_svqs_start. + +Fixes: dff4426fa656 ("vhost: Add Shadow VirtQueue kick forwarding capabilities") +Reported-by: Lei Yang +Signed-off-by: Eugenio Pérez +Message-Id: <20230209170004.899472-1-eperezma@redhat.com> +Tested-by: Laurent Vivier +Acked-by: Jason Wang +Signed-off-by: fangyi +--- + hw/virtio/vhost-vdpa.c | 17 ++--------------- + 1 file changed, 2 insertions(+), 15 deletions(-) + +diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c +index dd1ba8878c..986fc795bf 100644 +--- a/hw/virtio/vhost-vdpa.c ++++ b/hw/virtio/vhost-vdpa.c +@@ -692,26 +692,11 @@ static int vhost_vdpa_get_device_id(struct vhost_dev *dev, + return ret; + } + +-static void vhost_vdpa_reset_svq(struct vhost_vdpa *v) +-{ +- if (!v->shadow_vqs_enabled) { +- return; +- } +- +- for (unsigned i = 0; i < v->shadow_vqs->len; ++i) { +- VhostShadowVirtqueue *svq = g_ptr_array_index(v->shadow_vqs, i); +- vhost_svq_stop(svq); +- } +-} +- + static int vhost_vdpa_reset_device(struct vhost_dev *dev) + { +- struct vhost_vdpa *v = dev->opaque; + int ret; + uint8_t status = 0; + +- vhost_vdpa_reset_svq(v); +- + ret = vhost_vdpa_call(dev, VHOST_VDPA_SET_STATUS, &status); + trace_vhost_vdpa_reset_device(dev, status); + return ret; +@@ -1103,6 +1088,8 @@ static void vhost_vdpa_svqs_stop(struct vhost_dev *dev) + + for (unsigned i = 0; i < v->shadow_vqs->len; ++i) { + VhostShadowVirtqueue *svq = g_ptr_array_index(v->shadow_vqs, i); ++ ++ vhost_svq_stop(svq); + vhost_vdpa_svq_unmap_rings(dev, svq); + + event_notifier_cleanup(&svq->hdev_kick); +-- +2.27.0 + diff --git a/vdpa-store-x-svq-parameter-in-VhostVDPAState.patch b/vdpa-store-x-svq-parameter-in-VhostVDPAState.patch new file mode 100644 index 00000000..96f5eae2 --- /dev/null +++ b/vdpa-store-x-svq-parameter-in-VhostVDPAState.patch @@ -0,0 +1,54 @@ +From 7a2278d9cdd9ac2a74bb9745fdf555395ff8dcd7 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= +Date: Thu, 15 Dec 2022 12:31:42 +0100 +Subject: [PATCH] vdpa: store x-svq parameter in VhostVDPAState +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +CVQ can be shadowed two ways: +- Device has x-svq=on parameter (current way) +- The device can isolate CVQ in its own vq group + +QEMU needs to check for the second condition dynamically, because CVQ +index is not known before the driver ack the features. Since this is +dynamic, the CVQ isolation could vary with different conditions, making +it possible to go from "not isolated group" to "isolated". + +Saving the cmdline parameter in an extra field so we never disable CVQ +SVQ in case the device was started with x-svq cmdline. + +Signed-off-by: Eugenio Pérez +Acked-by: Jason Wang +Message-Id: <20221215113144.322011-11-eperezma@redhat.com> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Signed-off-by: fangyi +--- + net/vhost-vdpa.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c +index cb1cc2523d..7adba2c2b6 100644 +--- a/net/vhost-vdpa.c ++++ b/net/vhost-vdpa.c +@@ -37,6 +37,8 @@ typedef struct VhostVDPAState { + void *cvq_cmd_out_buffer; + virtio_net_ctrl_ack *status; + ++ /* The device always have SVQ enabled */ ++ bool always_svq; + bool started; + } VhostVDPAState; + +@@ -575,6 +577,7 @@ static NetClientState *net_vhost_vdpa_init(NetClientState *peer, + + s->vhost_vdpa.device_fd = vdpa_device_fd; + s->vhost_vdpa.index = queue_pair_index; ++ s->always_svq = svq; + s->vhost_vdpa.shadow_vqs_enabled = svq; + s->vhost_vdpa.iova_range = iova_range; + s->vhost_vdpa.iova_tree = iova_tree; +-- +2.27.0 + diff --git a/vdpa-use-v-shadow_vqs_enabled-in-vhost_vdpa_svqs_sta.patch b/vdpa-use-v-shadow_vqs_enabled-in-vhost_vdpa_svqs_sta.patch new file mode 100644 index 00000000..2b22c8e5 --- /dev/null +++ b/vdpa-use-v-shadow_vqs_enabled-in-vhost_vdpa_svqs_sta.patch @@ -0,0 +1,50 @@ +From f2a41f2f0f16402772009efc8eac5e9a08fea0b3 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= +Date: Thu, 15 Dec 2022 12:31:33 +0100 +Subject: [PATCH] vdpa: use v->shadow_vqs_enabled in vhost_vdpa_svqs_start & + stop +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This function used to trust in v->shadow_vqs != NULL to know if it must +start svq or not. + +This is not going to be valid anymore, as qemu is going to allocate svq +array unconditionally (but it will only start them conditionally). + +Signed-off-by: Eugenio Pérez +Acked-by: Jason Wang +Message-Id: <20221215113144.322011-2-eperezma@redhat.com> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Signed-off-by: fangyi +--- + hw/virtio/vhost-vdpa.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c +index 0f07c85b91..08f92bf781 100644 +--- a/hw/virtio/vhost-vdpa.c ++++ b/hw/virtio/vhost-vdpa.c +@@ -1031,7 +1031,7 @@ static bool vhost_vdpa_svqs_start(struct vhost_dev *dev) + Error *err = NULL; + unsigned i; + +- if (!v->shadow_vqs) { ++ if (!v->shadow_vqs_enabled) { + return true; + } + +@@ -1084,7 +1084,7 @@ static void vhost_vdpa_svqs_stop(struct vhost_dev *dev) + { + struct vhost_vdpa *v = dev->opaque; + +- if (!v->shadow_vqs) { ++ if (!v->shadow_vqs_enabled) { + return; + } + +-- +2.27.0 + diff --git a/vdpa-validate-MQ-CVQ-commands.patch b/vdpa-validate-MQ-CVQ-commands.patch new file mode 100644 index 00000000..42627c17 --- /dev/null +++ b/vdpa-validate-MQ-CVQ-commands.patch @@ -0,0 +1,41 @@ +From c9aa596ad26ee9fa1d4f7433485a668e3485d4ca Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= +Date: Tue, 6 Sep 2022 17:07:17 +0200 +Subject: [PATCH] vdpa: validate MQ CVQ commands +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +So we are sure we can update the device model properly before sending to +the device. + +Signed-off-by: Eugenio Pérez +Signed-off-by: Jason Wang +Signed-off-by: fangyi +--- + net/vhost-vdpa.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c +index b32fe5e68a..831709a270 100644 +--- a/net/vhost-vdpa.c ++++ b/net/vhost-vdpa.c +@@ -494,6 +494,15 @@ static bool vhost_vdpa_net_cvq_validate_cmd(const void *out_buf, size_t len) + __func__, ctrl.cmd); + }; + break; ++ case VIRTIO_NET_CTRL_MQ: ++ switch (ctrl.cmd) { ++ case VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET: ++ return true; ++ default: ++ qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid mq cmd %u\n", ++ __func__, ctrl.cmd); ++ }; ++ break; + default: + qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid control class %u\n", + __func__, ctrl.class); +-- +2.27.0 + diff --git a/vga-avoid-crash-if-no-default-vga-card.patch b/vga-avoid-crash-if-no-default-vga-card.patch new file mode 100644 index 00000000..829bcae4 --- /dev/null +++ b/vga-avoid-crash-if-no-default-vga-card.patch @@ -0,0 +1,41 @@ +From 70b0d16c684364594443520fba504e665f167cc4 Mon Sep 17 00:00:00 2001 +From: tangbinzy +Date: Fri, 17 Nov 2023 09:38:56 +0000 +Subject: [PATCH] vga: avoid crash if no default vga card mainline inclusion + commit 6985d8ede92494f3b791de01e8ee9306eb6d5e4a category: bugfix + +--------------------------------------------------------------- + +QEMU in some arch will crash when executing -vga help command, because +there is no default vga model. Add check to this case and avoid crash. + +Resolves: https://gitlab.com/qemu-project/qemu/-/issues/978 + +Signed-off-by: Guo Zhi +Reviewed-by: Thomas Huth +Tested-by: Thomas Huth +Message-Id: <20220503091724.970009-1-qtxuning1999@sjtu.edu.cn> +Signed-off-by: Laurent Vivier + +Signed-off-by: tangbinzy +--- + softmmu/vl.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/softmmu/vl.c b/softmmu/vl.c +index d8996f3d6e..e34c8a0646 100644 +--- a/softmmu/vl.c ++++ b/softmmu/vl.c +@@ -974,7 +974,8 @@ static void select_vgahw(const MachineClass *machine_class, const char *p) + + if (vga_interface_available(t) && ti->opt_name) { + printf("%-20s %s%s\n", ti->opt_name, ti->name ?: "", +- g_str_equal(ti->opt_name, def) ? " (default)" : ""); ++ (def && g_str_equal(ti->opt_name, def)) ? ++ " (default)" : ""); + } + } + exit(0); +-- +2.27.0 + diff --git a/vhost-Add-SVQDescState.patch b/vhost-Add-SVQDescState.patch new file mode 100644 index 00000000..748d3266 --- /dev/null +++ b/vhost-Add-SVQDescState.patch @@ -0,0 +1,116 @@ +From f8caeca478eb902982879ecd7fad9ffa518ad3bb Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= +Date: Wed, 20 Jul 2022 08:59:34 +0200 +Subject: [PATCH] vhost: Add SVQDescState +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This will allow SVQ to add context to the different queue elements. + +This patch only store the actual element, no functional change intended. + +Signed-off-by: Eugenio Pérez +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Jason Wang +Signed-off-by: fangyi +--- + hw/virtio/vhost-shadow-virtqueue.c | 16 ++++++++-------- + hw/virtio/vhost-shadow-virtqueue.h | 8 ++++++-- + 2 files changed, 14 insertions(+), 10 deletions(-) + +diff --git a/hw/virtio/vhost-shadow-virtqueue.c b/hw/virtio/vhost-shadow-virtqueue.c +index 00f5ccddfb..5ddc04e9d6 100644 +--- a/hw/virtio/vhost-shadow-virtqueue.c ++++ b/hw/virtio/vhost-shadow-virtqueue.c +@@ -255,7 +255,7 @@ static int vhost_svq_add(VhostShadowVirtqueue *svq, const struct iovec *out_sg, + return -EINVAL; + } + +- svq->ring_id_maps[qemu_head] = elem; ++ svq->desc_state[qemu_head].elem = elem; + vhost_svq_kick(svq); + return 0; + } +@@ -410,21 +410,21 @@ static VirtQueueElement *vhost_svq_get_buf(VhostShadowVirtqueue *svq, + return NULL; + } + +- if (unlikely(!svq->ring_id_maps[used_elem.id])) { ++ if (unlikely(!svq->desc_state[used_elem.id].elem)) { + qemu_log_mask(LOG_GUEST_ERROR, + "Device %s says index %u is used, but it was not available", + svq->vdev->name, used_elem.id); + return NULL; + } + +- num = svq->ring_id_maps[used_elem.id]->in_num + +- svq->ring_id_maps[used_elem.id]->out_num; ++ num = svq->desc_state[used_elem.id].elem->in_num + ++ svq->desc_state[used_elem.id].elem->out_num; + last_used_chain = vhost_svq_last_desc_of_chain(svq, num, used_elem.id); + svq->desc_next[last_used_chain] = svq->free_head; + svq->free_head = used_elem.id; + + *len = used_elem.len; +- return g_steal_pointer(&svq->ring_id_maps[used_elem.id]); ++ return g_steal_pointer(&svq->desc_state[used_elem.id].elem); + } + + static void vhost_svq_flush(VhostShadowVirtqueue *svq, +@@ -594,7 +594,7 @@ void vhost_svq_start(VhostShadowVirtqueue *svq, VirtIODevice *vdev, + memset(svq->vring.desc, 0, driver_size); + svq->vring.used = qemu_memalign(qemu_real_host_page_size, device_size); + memset(svq->vring.used, 0, device_size); +- svq->ring_id_maps = g_new0(VirtQueueElement *, svq->vring.num); ++ svq->desc_state = g_new0(SVQDescState, svq->vring.num); + svq->desc_next = g_new0(uint16_t, svq->vring.num); + for (unsigned i = 0; i < svq->vring.num - 1; i++) { + svq->desc_next[i] = cpu_to_le16(i + 1); +@@ -619,7 +619,7 @@ void vhost_svq_stop(VhostShadowVirtqueue *svq) + + for (unsigned i = 0; i < svq->vring.num; ++i) { + g_autofree VirtQueueElement *elem = NULL; +- elem = g_steal_pointer(&svq->ring_id_maps[i]); ++ elem = g_steal_pointer(&svq->desc_state[i].elem); + if (elem) { + virtqueue_detach_element(svq->vq, elem, 0); + } +@@ -631,7 +631,7 @@ void vhost_svq_stop(VhostShadowVirtqueue *svq) + } + svq->vq = NULL; + g_free(svq->desc_next); +- g_free(svq->ring_id_maps); ++ g_free(svq->desc_state); + qemu_vfree(svq->vring.desc); + qemu_vfree(svq->vring.used); + } +diff --git a/hw/virtio/vhost-shadow-virtqueue.h b/hw/virtio/vhost-shadow-virtqueue.h +index c132c994e9..d646c35054 100644 +--- a/hw/virtio/vhost-shadow-virtqueue.h ++++ b/hw/virtio/vhost-shadow-virtqueue.h +@@ -15,6 +15,10 @@ + #include "standard-headers/linux/vhost_types.h" + #include "hw/virtio/vhost-iova-tree.h" + ++typedef struct SVQDescState { ++ VirtQueueElement *elem; ++} SVQDescState; ++ + /* Shadow virtqueue to relay notifications */ + typedef struct VhostShadowVirtqueue { + /* Shadow vring */ +@@ -47,8 +51,8 @@ typedef struct VhostShadowVirtqueue { + /* IOVA mapping */ + VhostIOVATree *iova_tree; + +- /* Map for use the guest's descriptors */ +- VirtQueueElement **ring_id_maps; ++ /* SVQ vring descriptors state */ ++ SVQDescState *desc_state; + + /* Next VirtQueue element that guest made available */ + VirtQueueElement *next_guest_avail_elem; +-- +2.27.0 + diff --git a/vhost-Add-Shadow-VirtQueue-call-forwarding-capabilit.patch b/vhost-Add-Shadow-VirtQueue-call-forwarding-capabilit.patch new file mode 100644 index 00000000..41fe5cf4 --- /dev/null +++ b/vhost-Add-Shadow-VirtQueue-call-forwarding-capabilit.patch @@ -0,0 +1,168 @@ +From 6ff532ef853499a16307e09d8bab18c57c03ecae Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= +Date: Mon, 14 Mar 2022 18:34:43 +0100 +Subject: [PATCH] vhost: Add Shadow VirtQueue call forwarding capabilities +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This will make qemu aware of the device used buffers, allowing it to +write the guest memory with its contents if needed. + +Signed-off-by: Eugenio Pérez +Acked-by: Michael S. Tsirkin +Signed-off-by: Jason Wang +Signed-off-by: fangyi +--- + hw/virtio/vhost-shadow-virtqueue.c | 38 ++++++++++++++++++++++++++++++ + hw/virtio/vhost-shadow-virtqueue.h | 4 ++++ + hw/virtio/vhost-vdpa.c | 31 ++++++++++++++++++++++-- + 3 files changed, 71 insertions(+), 2 deletions(-) + +diff --git a/hw/virtio/vhost-shadow-virtqueue.c b/hw/virtio/vhost-shadow-virtqueue.c +index e5da907b8e..55cb5414ef 100644 +--- a/hw/virtio/vhost-shadow-virtqueue.c ++++ b/hw/virtio/vhost-shadow-virtqueue.c +@@ -26,6 +26,42 @@ static void vhost_handle_guest_kick(EventNotifier *n) + event_notifier_set(&svq->hdev_kick); + } + ++/** ++ * Forward vhost notifications ++ * ++ * @n: hdev call event notifier, the one that device set to notify svq. ++ */ ++static void vhost_svq_handle_call(EventNotifier *n) ++{ ++ VhostShadowVirtqueue *svq = container_of(n, VhostShadowVirtqueue, ++ hdev_call); ++ event_notifier_test_and_clear(n); ++ event_notifier_set(&svq->svq_call); ++} ++ ++/** ++ * Set the call notifier for the SVQ to call the guest ++ * ++ * @svq: Shadow virtqueue ++ * @call_fd: call notifier ++ * ++ * Called on BQL context. ++ */ ++void vhost_svq_set_svq_call_fd(VhostShadowVirtqueue *svq, int call_fd) ++{ ++ if (call_fd == VHOST_FILE_UNBIND) { ++ /* ++ * Fail event_notifier_set if called handling device call. ++ * ++ * SVQ still needs device notifications, since it needs to keep ++ * forwarding used buffers even with the unbind. ++ */ ++ memset(&svq->svq_call, 0, sizeof(svq->svq_call)); ++ } else { ++ event_notifier_init_fd(&svq->svq_call, call_fd); ++ } ++} ++ + /** + * Set a new file descriptor for the guest to kick the SVQ and notify for avail + * +@@ -93,6 +129,7 @@ VhostShadowVirtqueue *vhost_svq_new(void) + } + + event_notifier_init_fd(&svq->svq_kick, VHOST_FILE_UNBIND); ++ event_notifier_set_handler(&svq->hdev_call, vhost_svq_handle_call); + return g_steal_pointer(&svq); + + err_init_hdev_call: +@@ -112,6 +149,7 @@ void vhost_svq_free(gpointer pvq) + VhostShadowVirtqueue *vq = pvq; + vhost_svq_stop(vq); + event_notifier_cleanup(&vq->hdev_kick); ++ event_notifier_set_handler(&vq->hdev_call, NULL); + event_notifier_cleanup(&vq->hdev_call); + g_free(vq); + } +diff --git a/hw/virtio/vhost-shadow-virtqueue.h b/hw/virtio/vhost-shadow-virtqueue.h +index 1cbc87d5d8..cbc5213579 100644 +--- a/hw/virtio/vhost-shadow-virtqueue.h ++++ b/hw/virtio/vhost-shadow-virtqueue.h +@@ -28,9 +28,13 @@ typedef struct VhostShadowVirtqueue { + * So shadow virtqueue must not clean it, or we would lose VirtQueue one. + */ + EventNotifier svq_kick; ++ ++ /* Guest's call notifier, where the SVQ calls guest. */ ++ EventNotifier svq_call; + } VhostShadowVirtqueue; + + void vhost_svq_set_svq_kick_fd(VhostShadowVirtqueue *svq, int svq_kick_fd); ++void vhost_svq_set_svq_call_fd(VhostShadowVirtqueue *svq, int call_fd); + + void vhost_svq_stop(VhostShadowVirtqueue *svq); + +diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c +index 7331c8ee04..29c720308f 100644 +--- a/hw/virtio/vhost-vdpa.c ++++ b/hw/virtio/vhost-vdpa.c +@@ -727,6 +727,13 @@ static int vhost_vdpa_set_vring_dev_kick(struct vhost_dev *dev, + return vhost_vdpa_call(dev, VHOST_SET_VRING_KICK, file); + } + ++static int vhost_vdpa_set_vring_dev_call(struct vhost_dev *dev, ++ struct vhost_vring_file *file) ++{ ++ trace_vhost_vdpa_set_vring_call(dev, file->index, file->fd); ++ return vhost_vdpa_call(dev, VHOST_SET_VRING_CALL, file); ++} ++ + /** + * Set the shadow virtqueue descriptors to the device + * +@@ -734,6 +741,9 @@ static int vhost_vdpa_set_vring_dev_kick(struct vhost_dev *dev, + * @svq: The shadow virtqueue + * @idx: The index of the virtqueue in the vhost device + * @errp: Error ++ * ++ * Note that this function does not rewind kick file descriptor if cannot set ++ * call one. + */ + static bool vhost_vdpa_svq_setup(struct vhost_dev *dev, + VhostShadowVirtqueue *svq, unsigned idx, +@@ -749,6 +759,14 @@ static bool vhost_vdpa_svq_setup(struct vhost_dev *dev, + r = vhost_vdpa_set_vring_dev_kick(dev, &file); + if (unlikely(r != 0)) { + error_setg_errno(errp, -r, "Can't set device kick fd"); ++ return false; ++ } ++ ++ event_notifier = &svq->hdev_call; ++ file.fd = event_notifier_get_fd(event_notifier); ++ r = vhost_vdpa_set_vring_dev_call(dev, &file); ++ if (unlikely(r != 0)) { ++ error_setg_errno(errp, -r, "Can't set device call fd"); + } + + return r == 0; +@@ -874,8 +892,17 @@ static int vhost_vdpa_set_vring_kick(struct vhost_dev *dev, + static int vhost_vdpa_set_vring_call(struct vhost_dev *dev, + struct vhost_vring_file *file) + { +- trace_vhost_vdpa_set_vring_call(dev, file->index, file->fd); +- return vhost_vdpa_call(dev, VHOST_SET_VRING_CALL, file); ++ struct vhost_vdpa *v = dev->opaque; ++ ++ if (v->shadow_vqs_enabled) { ++ int vdpa_idx = file->index - dev->vq_index; ++ VhostShadowVirtqueue *svq = g_ptr_array_index(v->shadow_vqs, vdpa_idx); ++ ++ vhost_svq_set_svq_call_fd(svq, file->fd); ++ return 0; ++ } else { ++ return vhost_vdpa_set_vring_dev_call(dev, file); ++ } + } + + static int vhost_vdpa_get_features(struct vhost_dev *dev, +-- +2.27.0 + diff --git a/vhost-Add-Shadow-VirtQueue-kick-forwarding-capabilit.patch b/vhost-Add-Shadow-VirtQueue-kick-forwarding-capabilit.patch new file mode 100644 index 00000000..fc8469e3 --- /dev/null +++ b/vhost-Add-Shadow-VirtQueue-kick-forwarding-capabilit.patch @@ -0,0 +1,395 @@ +From 41585669f68a3896d6d8a5bea868f192b30fad76 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= +Date: Mon, 14 Mar 2022 18:34:42 +0100 +Subject: [PATCH] vhost: Add Shadow VirtQueue kick forwarding capabilities +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +At this mode no buffer forwarding will be performed in SVQ mode: Qemu +will just forward the guest's kicks to the device. + +Host memory notifiers regions are left out for simplicity, and they will +not be addressed in this series. + +Signed-off-by: Eugenio Pérez +Acked-by: Michael S. Tsirkin +Signed-off-by: Jason Wang +Signed-off-by: fangyi +--- + hw/virtio/vhost-shadow-virtqueue.c | 55 +++++++++++ + hw/virtio/vhost-shadow-virtqueue.h | 14 +++ + hw/virtio/vhost-vdpa.c | 144 ++++++++++++++++++++++++++++- + include/hw/virtio/vhost-vdpa.h | 4 + + 4 files changed, 215 insertions(+), 2 deletions(-) + +diff --git a/hw/virtio/vhost-shadow-virtqueue.c b/hw/virtio/vhost-shadow-virtqueue.c +index c1db02c53e..e5da907b8e 100644 +--- a/hw/virtio/vhost-shadow-virtqueue.c ++++ b/hw/virtio/vhost-shadow-virtqueue.c +@@ -11,6 +11,59 @@ + #include "hw/virtio/vhost-shadow-virtqueue.h" + + #include "qemu/error-report.h" ++#include "qemu/main-loop.h" ++#include "linux-headers/linux/vhost.h" ++ ++/** ++ * Forward guest notifications. ++ * ++ * @n: guest kick event notifier, the one that guest set to notify svq. ++ */ ++static void vhost_handle_guest_kick(EventNotifier *n) ++{ ++ VhostShadowVirtqueue *svq = container_of(n, VhostShadowVirtqueue, svq_kick); ++ event_notifier_test_and_clear(n); ++ event_notifier_set(&svq->hdev_kick); ++} ++ ++/** ++ * Set a new file descriptor for the guest to kick the SVQ and notify for avail ++ * ++ * @svq: The svq ++ * @svq_kick_fd: The svq kick fd ++ * ++ * Note that the SVQ will never close the old file descriptor. ++ */ ++void vhost_svq_set_svq_kick_fd(VhostShadowVirtqueue *svq, int svq_kick_fd) ++{ ++ EventNotifier *svq_kick = &svq->svq_kick; ++ bool poll_stop = VHOST_FILE_UNBIND != event_notifier_get_fd(svq_kick); ++ bool poll_start = svq_kick_fd != VHOST_FILE_UNBIND; ++ ++ if (poll_stop) { ++ event_notifier_set_handler(svq_kick, NULL); ++ } ++ ++ /* ++ * event_notifier_set_handler already checks for guest's notifications if ++ * they arrive at the new file descriptor in the switch, so there is no ++ * need to explicitly check for them. ++ */ ++ if (poll_start) { ++ event_notifier_init_fd(svq_kick, svq_kick_fd); ++ event_notifier_set(svq_kick); ++ event_notifier_set_handler(svq_kick, vhost_handle_guest_kick); ++ } ++} ++ ++/** ++ * Stop the shadow virtqueue operation. ++ * @svq: Shadow Virtqueue ++ */ ++void vhost_svq_stop(VhostShadowVirtqueue *svq) ++{ ++ event_notifier_set_handler(&svq->svq_kick, NULL); ++} + + /** + * Creates vhost shadow virtqueue, and instructs the vhost device to use the +@@ -39,6 +92,7 @@ VhostShadowVirtqueue *vhost_svq_new(void) + goto err_init_hdev_call; + } + ++ event_notifier_init_fd(&svq->svq_kick, VHOST_FILE_UNBIND); + return g_steal_pointer(&svq); + + err_init_hdev_call: +@@ -56,6 +110,7 @@ err_init_hdev_kick: + void vhost_svq_free(gpointer pvq) + { + VhostShadowVirtqueue *vq = pvq; ++ vhost_svq_stop(vq); + event_notifier_cleanup(&vq->hdev_kick); + event_notifier_cleanup(&vq->hdev_call); + g_free(vq); +diff --git a/hw/virtio/vhost-shadow-virtqueue.h b/hw/virtio/vhost-shadow-virtqueue.h +index f1519e3c7b..1cbc87d5d8 100644 +--- a/hw/virtio/vhost-shadow-virtqueue.h ++++ b/hw/virtio/vhost-shadow-virtqueue.h +@@ -18,8 +18,22 @@ typedef struct VhostShadowVirtqueue { + EventNotifier hdev_kick; + /* Shadow call notifier, sent to vhost */ + EventNotifier hdev_call; ++ ++ /* ++ * Borrowed virtqueue's guest to host notifier. To borrow it in this event ++ * notifier allows to recover the VhostShadowVirtqueue from the event loop ++ * easily. If we use the VirtQueue's one, we don't have an easy way to ++ * retrieve VhostShadowVirtqueue. ++ * ++ * So shadow virtqueue must not clean it, or we would lose VirtQueue one. ++ */ ++ EventNotifier svq_kick; + } VhostShadowVirtqueue; + ++void vhost_svq_set_svq_kick_fd(VhostShadowVirtqueue *svq, int svq_kick_fd); ++ ++void vhost_svq_stop(VhostShadowVirtqueue *svq); ++ + VhostShadowVirtqueue *vhost_svq_new(void); + + void vhost_svq_free(gpointer vq); +diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c +index 25a2f570a2..7331c8ee04 100644 +--- a/hw/virtio/vhost-vdpa.c ++++ b/hw/virtio/vhost-vdpa.c +@@ -17,12 +17,14 @@ + #include "hw/virtio/vhost.h" + #include "hw/virtio/vhost-backend.h" + #include "hw/virtio/virtio-net.h" ++#include "hw/virtio/vhost-shadow-virtqueue.h" + #include "hw/virtio/vhost-vdpa.h" + #include "exec/address-spaces.h" + #include "qemu/main-loop.h" + #include "cpu.h" + #include "trace.h" + #include "qemu-common.h" ++#include "qapi/error.h" + + static unsigned int vhost_vdpa_used_memslots; + +@@ -344,6 +346,30 @@ static bool vhost_vdpa_one_time_request(struct vhost_dev *dev) + return v->index != 0; + } + ++static int vhost_vdpa_init_svq(struct vhost_dev *hdev, struct vhost_vdpa *v, ++ Error **errp) ++{ ++ g_autoptr(GPtrArray) shadow_vqs = NULL; ++ ++ if (!v->shadow_vqs_enabled) { ++ return 0; ++ } ++ ++ shadow_vqs = g_ptr_array_new_full(hdev->nvqs, vhost_svq_free); ++ for (unsigned n = 0; n < hdev->nvqs; ++n) { ++ g_autoptr(VhostShadowVirtqueue) svq = vhost_svq_new(); ++ ++ if (unlikely(!svq)) { ++ error_setg(errp, "Cannot create svq %u", n); ++ return -1; ++ } ++ g_ptr_array_add(shadow_vqs, g_steal_pointer(&svq)); ++ } ++ ++ v->shadow_vqs = g_steal_pointer(&shadow_vqs); ++ return 0; ++} ++ + static int vhost_vdpa_init(struct vhost_dev *dev, void *opaque, Error **errp) + { + struct vhost_vdpa *v; +@@ -366,6 +392,10 @@ static int vhost_vdpa_init(struct vhost_dev *dev, void *opaque, Error **errp) + dev->opaque = opaque ; + v->listener = vhost_vdpa_memory_listener; + v->msg_type = VHOST_IOTLB_MSG_V2; ++ ret = vhost_vdpa_init_svq(dev, v, errp); ++ if (ret) { ++ goto err; ++ } + + vhost_vdpa_get_iova_range(v); + +@@ -377,6 +407,10 @@ static int vhost_vdpa_init(struct vhost_dev *dev, void *opaque, Error **errp) + VIRTIO_CONFIG_S_DRIVER); + + return 0; ++ ++err: ++ ram_block_discard_disable(false); ++ return ret; + } + + static void vhost_vdpa_host_notifier_uninit(struct vhost_dev *dev, +@@ -447,8 +481,14 @@ static void vhost_vdpa_host_notifiers_uninit(struct vhost_dev *dev, int n) + + static void vhost_vdpa_host_notifiers_init(struct vhost_dev *dev) + { ++ struct vhost_vdpa *v = dev->opaque; + int i; + ++ if (v->shadow_vqs_enabled) { ++ /* FIXME SVQ is not compatible with host notifiers mr */ ++ return; ++ } ++ + for (i = dev->vq_index; i < dev->vq_index + dev->nvqs; i++) { + if (vhost_vdpa_host_notifier_init(dev, i)) { + goto err; +@@ -462,6 +502,21 @@ err: + return; + } + ++static void vhost_vdpa_svq_cleanup(struct vhost_dev *dev) ++{ ++ struct vhost_vdpa *v = dev->opaque; ++ size_t idx; ++ ++ if (!v->shadow_vqs) { ++ return; ++ } ++ ++ for (idx = 0; idx < v->shadow_vqs->len; ++idx) { ++ vhost_svq_stop(g_ptr_array_index(v->shadow_vqs, idx)); ++ } ++ g_ptr_array_free(v->shadow_vqs, true); ++} ++ + static int vhost_vdpa_cleanup(struct vhost_dev *dev) + { + struct vhost_vdpa *v; +@@ -470,6 +525,7 @@ static int vhost_vdpa_cleanup(struct vhost_dev *dev) + trace_vhost_vdpa_cleanup(dev, v); + vhost_vdpa_host_notifiers_uninit(dev, dev->nvqs); + memory_listener_unregister(&v->listener); ++ vhost_vdpa_svq_cleanup(dev); + + dev->opaque = NULL; + ram_block_discard_disable(false); +@@ -561,11 +617,26 @@ static int vhost_vdpa_get_device_id(struct vhost_dev *dev, + return ret; + } + ++static void vhost_vdpa_reset_svq(struct vhost_vdpa *v) ++{ ++ if (!v->shadow_vqs_enabled) { ++ return; ++ } ++ ++ for (unsigned i = 0; i < v->shadow_vqs->len; ++i) { ++ VhostShadowVirtqueue *svq = g_ptr_array_index(v->shadow_vqs, i); ++ vhost_svq_stop(svq); ++ } ++} ++ + static int vhost_vdpa_reset_device(struct vhost_dev *dev) + { ++ struct vhost_vdpa *v = dev->opaque; + int ret; + uint8_t status = 0; + ++ vhost_vdpa_reset_svq(v); ++ + ret = vhost_vdpa_call(dev, VHOST_VDPA_SET_STATUS, &status); + trace_vhost_vdpa_reset_device(dev, status); + return ret; +@@ -649,13 +720,74 @@ static int vhost_vdpa_get_config(struct vhost_dev *dev, uint8_t *config, + return ret; + } + ++static int vhost_vdpa_set_vring_dev_kick(struct vhost_dev *dev, ++ struct vhost_vring_file *file) ++{ ++ trace_vhost_vdpa_set_vring_kick(dev, file->index, file->fd); ++ return vhost_vdpa_call(dev, VHOST_SET_VRING_KICK, file); ++} ++ ++/** ++ * Set the shadow virtqueue descriptors to the device ++ * ++ * @dev: The vhost device model ++ * @svq: The shadow virtqueue ++ * @idx: The index of the virtqueue in the vhost device ++ * @errp: Error ++ */ ++static bool vhost_vdpa_svq_setup(struct vhost_dev *dev, ++ VhostShadowVirtqueue *svq, unsigned idx, ++ Error **errp) ++{ ++ struct vhost_vring_file file = { ++ .index = dev->vq_index + idx, ++ }; ++ const EventNotifier *event_notifier = &svq->hdev_kick; ++ int r; ++ ++ file.fd = event_notifier_get_fd(event_notifier); ++ r = vhost_vdpa_set_vring_dev_kick(dev, &file); ++ if (unlikely(r != 0)) { ++ error_setg_errno(errp, -r, "Can't set device kick fd"); ++ } ++ ++ return r == 0; ++} ++ ++static bool vhost_vdpa_svqs_start(struct vhost_dev *dev) ++{ ++ struct vhost_vdpa *v = dev->opaque; ++ Error *err = NULL; ++ unsigned i; ++ ++ if (!v->shadow_vqs) { ++ return true; ++ } ++ ++ for (i = 0; i < v->shadow_vqs->len; ++i) { ++ VhostShadowVirtqueue *svq = g_ptr_array_index(v->shadow_vqs, i); ++ bool ok = vhost_vdpa_svq_setup(dev, svq, i, &err); ++ if (unlikely(!ok)) { ++ error_reportf_err(err, "Cannot setup SVQ %u: ", i); ++ return false; ++ } ++ } ++ ++ return true; ++} ++ + static int vhost_vdpa_dev_start(struct vhost_dev *dev, bool started) + { + struct vhost_vdpa *v = dev->opaque; ++ bool ok; + trace_vhost_vdpa_dev_start(dev, started); + + if (started) { + vhost_vdpa_host_notifiers_init(dev); ++ ok = vhost_vdpa_svqs_start(dev); ++ if (unlikely(!ok)) { ++ return -1; ++ } + vhost_vdpa_set_vring_ready(dev); + } else { + vhost_vdpa_host_notifiers_uninit(dev, dev->nvqs); +@@ -727,8 +859,16 @@ static int vhost_vdpa_get_vring_base(struct vhost_dev *dev, + static int vhost_vdpa_set_vring_kick(struct vhost_dev *dev, + struct vhost_vring_file *file) + { +- trace_vhost_vdpa_set_vring_kick(dev, file->index, file->fd); +- return vhost_vdpa_call(dev, VHOST_SET_VRING_KICK, file); ++ struct vhost_vdpa *v = dev->opaque; ++ int vdpa_idx = file->index - dev->vq_index; ++ ++ if (v->shadow_vqs_enabled) { ++ VhostShadowVirtqueue *svq = g_ptr_array_index(v->shadow_vqs, vdpa_idx); ++ vhost_svq_set_svq_kick_fd(svq, file->fd); ++ return 0; ++ } else { ++ return vhost_vdpa_set_vring_dev_kick(dev, file); ++ } + } + + static int vhost_vdpa_set_vring_call(struct vhost_dev *dev, +diff --git a/include/hw/virtio/vhost-vdpa.h b/include/hw/virtio/vhost-vdpa.h +index 3ce79a646d..009a9f3b6b 100644 +--- a/include/hw/virtio/vhost-vdpa.h ++++ b/include/hw/virtio/vhost-vdpa.h +@@ -12,6 +12,8 @@ + #ifndef HW_VIRTIO_VHOST_VDPA_H + #define HW_VIRTIO_VHOST_VDPA_H + ++#include ++ + #include "hw/virtio/virtio.h" + #include "standard-headers/linux/vhost_types.h" + +@@ -27,6 +29,8 @@ typedef struct vhost_vdpa { + bool iotlb_batch_begin_sent; + MemoryListener listener; + struct vhost_vdpa_iova_range iova_range; ++ bool shadow_vqs_enabled; ++ GPtrArray *shadow_vqs; + struct vhost_dev *dev; + VhostVDPAHostNotifier notifier[VIRTIO_QUEUE_MAX]; + } VhostVDPA; +-- +2.27.0 + diff --git a/vhost-Add-VhostIOVATree.patch b/vhost-Add-VhostIOVATree.patch new file mode 100644 index 00000000..8f78f901 --- /dev/null +++ b/vhost-Add-VhostIOVATree.patch @@ -0,0 +1,200 @@ +From c938dd769a872c569c3985f06c8b5854231ed74c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= +Date: Mon, 14 Mar 2022 18:34:50 +0100 +Subject: [PATCH] vhost: Add VhostIOVATree +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This tree is able to look for a translated address from an IOVA address. + +At first glance it is similar to util/iova-tree. However, SVQ working on +devices with limited IOVA space need more capabilities, like allocating +IOVA chunks or performing reverse translations (qemu addresses to iova). + +The allocation capability, as "assign a free IOVA address to this chunk +of memory in qemu's address space" allows shadow virtqueue to create a +new address space that is not restricted by guest's addressable one, so +we can allocate shadow vqs vrings outside of it. + +It duplicates the tree so it can search efficiently in both directions, +and it will signal overlap if iova or the translated address is present +in any tree. + +Signed-off-by: Eugenio Pérez +Acked-by: Michael S. Tsirkin +Signed-off-by: Jason Wang +Signed-off-by: fangyi +--- + hw/virtio/meson.build | 2 +- + hw/virtio/vhost-iova-tree.c | 110 ++++++++++++++++++++++++++++++++++++ + hw/virtio/vhost-iova-tree.h | 27 +++++++++ + 3 files changed, 138 insertions(+), 1 deletion(-) + create mode 100644 hw/virtio/vhost-iova-tree.c + create mode 100644 hw/virtio/vhost-iova-tree.h + +diff --git a/hw/virtio/meson.build b/hw/virtio/meson.build +index eb46c05a25..c2e193f56d 100644 +--- a/hw/virtio/meson.build ++++ b/hw/virtio/meson.build +@@ -11,7 +11,7 @@ softmmu_ss.add(when: 'CONFIG_ALL', if_true: files('vhost-stub.c')) + + virtio_ss = ss.source_set() + virtio_ss.add(files('virtio.c')) +-virtio_ss.add(when: 'CONFIG_VHOST', if_true: files('vhost.c', 'vhost-backend.c', 'vhost-shadow-virtqueue.c')) ++virtio_ss.add(when: 'CONFIG_VHOST', if_true: files('vhost.c', 'vhost-backend.c', 'vhost-shadow-virtqueue.c', 'vhost-iova-tree.c')) + virtio_ss.add(when: 'CONFIG_VHOST_USER', if_true: files('vhost-user.c')) + virtio_ss.add(when: 'CONFIG_VHOST_VDPA', if_true: files('vhost-vdpa.c')) + virtio_ss.add(when: 'CONFIG_VIRTIO_BALLOON', if_true: files('virtio-balloon.c')) +diff --git a/hw/virtio/vhost-iova-tree.c b/hw/virtio/vhost-iova-tree.c +new file mode 100644 +index 0000000000..55fed1fefb +--- /dev/null ++++ b/hw/virtio/vhost-iova-tree.c +@@ -0,0 +1,110 @@ ++/* ++ * vhost software live migration iova tree ++ * ++ * SPDX-FileCopyrightText: Red Hat, Inc. 2021 ++ * SPDX-FileContributor: Author: Eugenio Pérez ++ * ++ * SPDX-License-Identifier: GPL-2.0-or-later ++ */ ++ ++#include "qemu/osdep.h" ++#include "qemu/iova-tree.h" ++#include "vhost-iova-tree.h" ++ ++#define iova_min_addr qemu_real_host_page_size ++ ++/** ++ * VhostIOVATree, able to: ++ * - Translate iova address ++ * - Reverse translate iova address (from translated to iova) ++ * - Allocate IOVA regions for translated range (linear operation) ++ */ ++struct VhostIOVATree { ++ /* First addressable iova address in the device */ ++ uint64_t iova_first; ++ ++ /* Last addressable iova address in the device */ ++ uint64_t iova_last; ++ ++ /* IOVA address to qemu memory maps. */ ++ IOVATree *iova_taddr_map; ++}; ++ ++/** ++ * Create a new IOVA tree ++ * ++ * Returns the new IOVA tree ++ */ ++VhostIOVATree *vhost_iova_tree_new(hwaddr iova_first, hwaddr iova_last) ++{ ++ VhostIOVATree *tree = g_new(VhostIOVATree, 1); ++ ++ /* Some devices do not like 0 addresses */ ++ tree->iova_first = MAX(iova_first, iova_min_addr); ++ tree->iova_last = iova_last; ++ ++ tree->iova_taddr_map = iova_tree_new(); ++ return tree; ++} ++ ++/** ++ * Delete an iova tree ++ */ ++void vhost_iova_tree_delete(VhostIOVATree *iova_tree) ++{ ++ iova_tree_destroy(iova_tree->iova_taddr_map); ++ g_free(iova_tree); ++} ++ ++/** ++ * Find the IOVA address stored from a memory address ++ * ++ * @tree: The iova tree ++ * @map: The map with the memory address ++ * ++ * Return the stored mapping, or NULL if not found. ++ */ ++const DMAMap *vhost_iova_tree_find_iova(const VhostIOVATree *tree, ++ const DMAMap *map) ++{ ++ return iova_tree_find_iova(tree->iova_taddr_map, map); ++} ++ ++/** ++ * Allocate a new mapping ++ * ++ * @tree: The iova tree ++ * @map: The iova map ++ * ++ * Returns: ++ * - IOVA_OK if the map fits in the container ++ * - IOVA_ERR_INVALID if the map does not make sense (like size overflow) ++ * - IOVA_ERR_NOMEM if tree cannot allocate more space. ++ * ++ * It returns assignated iova in map->iova if return value is VHOST_DMA_MAP_OK. ++ */ ++int vhost_iova_tree_map_alloc(VhostIOVATree *tree, DMAMap *map) ++{ ++ /* Some vhost devices do not like addr 0. Skip first page */ ++ hwaddr iova_first = tree->iova_first ?: qemu_real_host_page_size; ++ ++ if (map->translated_addr + map->size < map->translated_addr || ++ map->perm == IOMMU_NONE) { ++ return IOVA_ERR_INVALID; ++ } ++ ++ /* Allocate a node in IOVA address */ ++ return iova_tree_alloc_map(tree->iova_taddr_map, map, iova_first, ++ tree->iova_last); ++} ++ ++/** ++ * Remove existing mappings from iova tree ++ * ++ * @iova_tree: The vhost iova tree ++ * @map: The map to remove ++ */ ++void vhost_iova_tree_remove(VhostIOVATree *iova_tree, const DMAMap *map) ++{ ++ iova_tree_remove(iova_tree->iova_taddr_map, map); ++} +diff --git a/hw/virtio/vhost-iova-tree.h b/hw/virtio/vhost-iova-tree.h +new file mode 100644 +index 0000000000..6a4f24e0f9 +--- /dev/null ++++ b/hw/virtio/vhost-iova-tree.h +@@ -0,0 +1,27 @@ ++/* ++ * vhost software live migration iova tree ++ * ++ * SPDX-FileCopyrightText: Red Hat, Inc. 2021 ++ * SPDX-FileContributor: Author: Eugenio Pérez ++ * ++ * SPDX-License-Identifier: GPL-2.0-or-later ++ */ ++ ++#ifndef HW_VIRTIO_VHOST_IOVA_TREE_H ++#define HW_VIRTIO_VHOST_IOVA_TREE_H ++ ++#include "qemu/iova-tree.h" ++#include "exec/memory.h" ++ ++typedef struct VhostIOVATree VhostIOVATree; ++ ++VhostIOVATree *vhost_iova_tree_new(uint64_t iova_first, uint64_t iova_last); ++void vhost_iova_tree_delete(VhostIOVATree *iova_tree); ++G_DEFINE_AUTOPTR_CLEANUP_FUNC(VhostIOVATree, vhost_iova_tree_delete); ++ ++const DMAMap *vhost_iova_tree_find_iova(const VhostIOVATree *iova_tree, ++ const DMAMap *map); ++int vhost_iova_tree_map_alloc(VhostIOVATree *iova_tree, DMAMap *map); ++void vhost_iova_tree_remove(VhostIOVATree *iova_tree, const DMAMap *map); ++ ++#endif +-- +2.27.0 + diff --git a/vhost-Add-VhostShadowVirtqueue.patch b/vhost-Add-VhostShadowVirtqueue.patch new file mode 100644 index 00000000..b4c668b4 --- /dev/null +++ b/vhost-Add-VhostShadowVirtqueue.patch @@ -0,0 +1,147 @@ +From 6f38bfce3fc45c1c68329412d146913a155962c7 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= +Date: Mon, 14 Mar 2022 18:34:41 +0100 +Subject: [PATCH] vhost: Add VhostShadowVirtqueue +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Vhost shadow virtqueue (SVQ) is an intermediate jump for virtqueue +notifications and buffers, allowing qemu to track them. While qemu is +forwarding the buffers and virtqueue changes, it is able to commit the +memory it's being dirtied, the same way regular qemu's VirtIO devices +do. + +This commit only exposes basic SVQ allocation and free. Next patches of +the series add functionality like notifications and buffers forwarding. + +Signed-off-by: Eugenio Pérez +Acked-by: Michael S. Tsirkin +Signed-off-by: Jason Wang +Signed-off-by: fangyi +--- + hw/virtio/meson.build | 2 +- + hw/virtio/vhost-shadow-virtqueue.c | 62 ++++++++++++++++++++++++++++++ + hw/virtio/vhost-shadow-virtqueue.h | 28 ++++++++++++++ + 3 files changed, 91 insertions(+), 1 deletion(-) + create mode 100644 hw/virtio/vhost-shadow-virtqueue.c + create mode 100644 hw/virtio/vhost-shadow-virtqueue.h + +diff --git a/hw/virtio/meson.build b/hw/virtio/meson.build +index 8e8943e20b..eb46c05a25 100644 +--- a/hw/virtio/meson.build ++++ b/hw/virtio/meson.build +@@ -11,7 +11,7 @@ softmmu_ss.add(when: 'CONFIG_ALL', if_true: files('vhost-stub.c')) + + virtio_ss = ss.source_set() + virtio_ss.add(files('virtio.c')) +-virtio_ss.add(when: 'CONFIG_VHOST', if_true: files('vhost.c', 'vhost-backend.c')) ++virtio_ss.add(when: 'CONFIG_VHOST', if_true: files('vhost.c', 'vhost-backend.c', 'vhost-shadow-virtqueue.c')) + virtio_ss.add(when: 'CONFIG_VHOST_USER', if_true: files('vhost-user.c')) + virtio_ss.add(when: 'CONFIG_VHOST_VDPA', if_true: files('vhost-vdpa.c')) + virtio_ss.add(when: 'CONFIG_VIRTIO_BALLOON', if_true: files('virtio-balloon.c')) +diff --git a/hw/virtio/vhost-shadow-virtqueue.c b/hw/virtio/vhost-shadow-virtqueue.c +new file mode 100644 +index 0000000000..c1db02c53e +--- /dev/null ++++ b/hw/virtio/vhost-shadow-virtqueue.c +@@ -0,0 +1,62 @@ ++/* ++ * vhost shadow virtqueue ++ * ++ * SPDX-FileCopyrightText: Red Hat, Inc. 2021 ++ * SPDX-FileContributor: Author: Eugenio Pérez ++ * ++ * SPDX-License-Identifier: GPL-2.0-or-later ++ */ ++ ++#include "qemu/osdep.h" ++#include "hw/virtio/vhost-shadow-virtqueue.h" ++ ++#include "qemu/error-report.h" ++ ++/** ++ * Creates vhost shadow virtqueue, and instructs the vhost device to use the ++ * shadow methods and file descriptors. ++ * ++ * Returns the new virtqueue or NULL. ++ * ++ * In case of error, reason is reported through error_report. ++ */ ++VhostShadowVirtqueue *vhost_svq_new(void) ++{ ++ g_autofree VhostShadowVirtqueue *svq = g_new0(VhostShadowVirtqueue, 1); ++ int r; ++ ++ r = event_notifier_init(&svq->hdev_kick, 0); ++ if (r != 0) { ++ error_report("Couldn't create kick event notifier: %s (%d)", ++ g_strerror(errno), errno); ++ goto err_init_hdev_kick; ++ } ++ ++ r = event_notifier_init(&svq->hdev_call, 0); ++ if (r != 0) { ++ error_report("Couldn't create call event notifier: %s (%d)", ++ g_strerror(errno), errno); ++ goto err_init_hdev_call; ++ } ++ ++ return g_steal_pointer(&svq); ++ ++err_init_hdev_call: ++ event_notifier_cleanup(&svq->hdev_kick); ++ ++err_init_hdev_kick: ++ return NULL; ++} ++ ++/** ++ * Free the resources of the shadow virtqueue. ++ * ++ * @pvq: gpointer to SVQ so it can be used by autofree functions. ++ */ ++void vhost_svq_free(gpointer pvq) ++{ ++ VhostShadowVirtqueue *vq = pvq; ++ event_notifier_cleanup(&vq->hdev_kick); ++ event_notifier_cleanup(&vq->hdev_call); ++ g_free(vq); ++} +diff --git a/hw/virtio/vhost-shadow-virtqueue.h b/hw/virtio/vhost-shadow-virtqueue.h +new file mode 100644 +index 0000000000..f1519e3c7b +--- /dev/null ++++ b/hw/virtio/vhost-shadow-virtqueue.h +@@ -0,0 +1,28 @@ ++/* ++ * vhost shadow virtqueue ++ * ++ * SPDX-FileCopyrightText: Red Hat, Inc. 2021 ++ * SPDX-FileContributor: Author: Eugenio Pérez ++ * ++ * SPDX-License-Identifier: GPL-2.0-or-later ++ */ ++ ++#ifndef VHOST_SHADOW_VIRTQUEUE_H ++#define VHOST_SHADOW_VIRTQUEUE_H ++ ++#include "qemu/event_notifier.h" ++ ++/* Shadow virtqueue to relay notifications */ ++typedef struct VhostShadowVirtqueue { ++ /* Shadow kick notifier, sent to vhost */ ++ EventNotifier hdev_kick; ++ /* Shadow call notifier, sent to vhost */ ++ EventNotifier hdev_call; ++} VhostShadowVirtqueue; ++ ++VhostShadowVirtqueue *vhost_svq_new(void); ++ ++void vhost_svq_free(gpointer vq); ++G_DEFINE_AUTOPTR_CLEANUP_FUNC(VhostShadowVirtqueue, vhost_svq_free); ++ ++#endif +-- +2.27.0 + diff --git a/vhost-Add-svq-avail_handler-callback.patch b/vhost-Add-svq-avail_handler-callback.patch new file mode 100644 index 00000000..b288a39d --- /dev/null +++ b/vhost-Add-svq-avail_handler-callback.patch @@ -0,0 +1,145 @@ +From 14cc79b8bda66ace21616adccf6c2ccd65b7256a Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= +Date: Wed, 20 Jul 2022 08:59:39 +0200 +Subject: [PATCH] vhost: Add svq avail_handler callback +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This allows external handlers to be aware of new buffers that the guest +places in the virtqueue. + +When this callback is defined the ownership of the guest's virtqueue +element is transferred to the callback. This means that if the user +wants to forward the descriptor it needs to manually inject it. The +callback is also free to process the command by itself and use the +element with svq_push. + +Signed-off-by: Eugenio Pérez +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Jason Wang +Signed-off-by: fangyi +--- + hw/virtio/vhost-shadow-virtqueue.c | 14 ++++++++++++-- + hw/virtio/vhost-shadow-virtqueue.h | 31 +++++++++++++++++++++++++++++- + hw/virtio/vhost-vdpa.c | 3 ++- + 3 files changed, 44 insertions(+), 4 deletions(-) + +diff --git a/hw/virtio/vhost-shadow-virtqueue.c b/hw/virtio/vhost-shadow-virtqueue.c +index d2676b94e0..ae443f54fe 100644 +--- a/hw/virtio/vhost-shadow-virtqueue.c ++++ b/hw/virtio/vhost-shadow-virtqueue.c +@@ -305,7 +305,11 @@ static void vhost_handle_guest_kick(VhostShadowVirtqueue *svq) + break; + } + +- r = vhost_svq_add_element(svq, elem); ++ if (svq->ops) { ++ r = svq->ops->avail_handler(svq, elem, svq->ops_opaque); ++ } else { ++ r = vhost_svq_add_element(svq, elem); ++ } + if (unlikely(r != 0)) { + if (r == -ENOSPC) { + /* +@@ -684,12 +688,16 @@ void vhost_svq_stop(VhostShadowVirtqueue *svq) + * shadow methods and file descriptors. + * + * @iova_tree: Tree to perform descriptors translations ++ * @ops: SVQ owner callbacks ++ * @ops_opaque: ops opaque pointer + * + * Returns the new virtqueue or NULL. + * + * In case of error, reason is reported through error_report. + */ +-VhostShadowVirtqueue *vhost_svq_new(VhostIOVATree *iova_tree) ++VhostShadowVirtqueue *vhost_svq_new(VhostIOVATree *iova_tree, ++ const VhostShadowVirtqueueOps *ops, ++ void *ops_opaque) + { + g_autofree VhostShadowVirtqueue *svq = g_new0(VhostShadowVirtqueue, 1); + int r; +@@ -711,6 +719,8 @@ VhostShadowVirtqueue *vhost_svq_new(VhostIOVATree *iova_tree) + event_notifier_init_fd(&svq->svq_kick, VHOST_FILE_UNBIND); + event_notifier_set_handler(&svq->hdev_call, vhost_svq_handle_call); + svq->iova_tree = iova_tree; ++ svq->ops = ops; ++ svq->ops_opaque = ops_opaque; + return g_steal_pointer(&svq); + + err_init_hdev_call: +diff --git a/hw/virtio/vhost-shadow-virtqueue.h b/hw/virtio/vhost-shadow-virtqueue.h +index cf442f7dea..d04c34a589 100644 +--- a/hw/virtio/vhost-shadow-virtqueue.h ++++ b/hw/virtio/vhost-shadow-virtqueue.h +@@ -25,6 +25,27 @@ typedef struct SVQDescState { + unsigned int ndescs; + } SVQDescState; + ++typedef struct VhostShadowVirtqueue VhostShadowVirtqueue; ++ ++/** ++ * Callback to handle an avail buffer. ++ * ++ * @svq: Shadow virtqueue ++ * @elem: Element placed in the queue by the guest ++ * @vq_callback_opaque: Opaque ++ * ++ * Returns 0 if the vq is running as expected. ++ * ++ * Note that ownership of elem is transferred to the callback. ++ */ ++typedef int (*VirtQueueAvailCallback)(VhostShadowVirtqueue *svq, ++ VirtQueueElement *elem, ++ void *vq_callback_opaque); ++ ++typedef struct VhostShadowVirtqueueOps { ++ VirtQueueAvailCallback avail_handler; ++} VhostShadowVirtqueueOps; ++ + /* Shadow virtqueue to relay notifications */ + typedef struct VhostShadowVirtqueue { + /* Shadow vring */ +@@ -69,6 +90,12 @@ typedef struct VhostShadowVirtqueue { + */ + uint16_t *desc_next; + ++ /* Caller callbacks */ ++ const VhostShadowVirtqueueOps *ops; ++ ++ /* Caller callbacks opaque */ ++ void *ops_opaque; ++ + /* Next head to expose to the device */ + uint16_t shadow_avail_idx; + +@@ -102,7 +129,9 @@ void vhost_svq_start(VhostShadowVirtqueue *svq, VirtIODevice *vdev, + VirtQueue *vq); + void vhost_svq_stop(VhostShadowVirtqueue *svq); + +-VhostShadowVirtqueue *vhost_svq_new(VhostIOVATree *iova_tree); ++VhostShadowVirtqueue *vhost_svq_new(VhostIOVATree *iova_tree, ++ const VhostShadowVirtqueueOps *ops, ++ void *ops_opaque); + + void vhost_svq_free(gpointer vq); + G_DEFINE_AUTOPTR_CLEANUP_FUNC(VhostShadowVirtqueue, vhost_svq_free); +diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c +index 73ff599f2b..a8d42655f0 100644 +--- a/hw/virtio/vhost-vdpa.c ++++ b/hw/virtio/vhost-vdpa.c +@@ -420,8 +420,9 @@ static int vhost_vdpa_init_svq(struct vhost_dev *hdev, struct vhost_vdpa *v, + + shadow_vqs = g_ptr_array_new_full(hdev->nvqs, vhost_svq_free); + for (unsigned n = 0; n < hdev->nvqs; ++n) { +- g_autoptr(VhostShadowVirtqueue) svq = vhost_svq_new(v->iova_tree); ++ g_autoptr(VhostShadowVirtqueue) svq; + ++ svq = vhost_svq_new(v->iova_tree, NULL, NULL); + if (unlikely(!svq)) { + error_setg(errp, "Cannot create svq %u", n); + return -1; +-- +2.27.0 + diff --git a/vhost-Add-vhost_svq_valid_features-to-shadow-vq.patch b/vhost-Add-vhost_svq_valid_features-to-shadow-vq.patch new file mode 100644 index 00000000..53bb3be9 --- /dev/null +++ b/vhost-Add-vhost_svq_valid_features-to-shadow-vq.patch @@ -0,0 +1,133 @@ +From 2f41ff8e23ed358890fb66b6f524627a9747cc14 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= +Date: Mon, 14 Mar 2022 18:34:44 +0100 +Subject: [PATCH] vhost: Add vhost_svq_valid_features to shadow vq +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This allows SVQ to negotiate features with the guest and the device. For +the device, SVQ is a driver. While this function bypasses all +non-transport features, it needs to disable the features that SVQ does +not support when forwarding buffers. This includes packed vq layout, +indirect descriptors or event idx. + +Future changes can add support to offer more features to the guest, +since the use of VirtQueue gives this for free. This is left out at the +moment for simplicity. + +Signed-off-by: Eugenio Pérez +Acked-by: Michael S. Tsirkin +Signed-off-by: Jason Wang +Signed-off-by: fangyi +--- + hw/virtio/vhost-shadow-virtqueue.c | 44 ++++++++++++++++++++++++++++++ + hw/virtio/vhost-shadow-virtqueue.h | 2 ++ + hw/virtio/vhost-vdpa.c | 15 ++++++++++ + 3 files changed, 61 insertions(+) + +diff --git a/hw/virtio/vhost-shadow-virtqueue.c b/hw/virtio/vhost-shadow-virtqueue.c +index 55cb5414ef..519328445c 100644 +--- a/hw/virtio/vhost-shadow-virtqueue.c ++++ b/hw/virtio/vhost-shadow-virtqueue.c +@@ -11,9 +11,53 @@ + #include "hw/virtio/vhost-shadow-virtqueue.h" + + #include "qemu/error-report.h" ++#include "qapi/error.h" + #include "qemu/main-loop.h" + #include "linux-headers/linux/vhost.h" + ++/** ++ * Validate the transport device features that both guests can use with the SVQ ++ * and SVQs can use with the device. ++ * ++ * @dev_features: The features ++ * @errp: Error pointer ++ */ ++bool vhost_svq_valid_features(uint64_t features, Error **errp) ++{ ++ bool ok = true; ++ uint64_t svq_features = features; ++ ++ for (uint64_t b = VIRTIO_TRANSPORT_F_START; b <= VIRTIO_TRANSPORT_F_END; ++ ++b) { ++ switch (b) { ++ case VIRTIO_F_ANY_LAYOUT: ++ continue; ++ ++ case VIRTIO_F_ACCESS_PLATFORM: ++ /* SVQ trust in the host's IOMMU to translate addresses */ ++ case VIRTIO_F_VERSION_1: ++ /* SVQ trust that the guest vring is little endian */ ++ if (!(svq_features & BIT_ULL(b))) { ++ svq_features |= BIT_ULL(b); ++ ok = false; ++ } ++ continue; ++ ++ default: ++ if (svq_features & BIT_ULL(b)) { ++ svq_features &= ~BIT_ULL(b); ++ ok = false; ++ } ++ } ++ } ++ ++ if (!ok) { ++ error_setg(errp, "SVQ Invalid device feature flags, offer: 0x%"PRIx64 ++ ", ok: 0x%"PRIx64, features, svq_features); ++ } ++ return ok; ++} ++ + /** + * Forward guest notifications. + * +diff --git a/hw/virtio/vhost-shadow-virtqueue.h b/hw/virtio/vhost-shadow-virtqueue.h +index cbc5213579..9e12f77201 100644 +--- a/hw/virtio/vhost-shadow-virtqueue.h ++++ b/hw/virtio/vhost-shadow-virtqueue.h +@@ -33,6 +33,8 @@ typedef struct VhostShadowVirtqueue { + EventNotifier svq_call; + } VhostShadowVirtqueue; + ++bool vhost_svq_valid_features(uint64_t features, Error **errp); ++ + void vhost_svq_set_svq_kick_fd(VhostShadowVirtqueue *svq, int svq_kick_fd); + void vhost_svq_set_svq_call_fd(VhostShadowVirtqueue *svq, int call_fd); + +diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c +index 29c720308f..8ee63933a8 100644 +--- a/hw/virtio/vhost-vdpa.c ++++ b/hw/virtio/vhost-vdpa.c +@@ -350,11 +350,26 @@ static int vhost_vdpa_init_svq(struct vhost_dev *hdev, struct vhost_vdpa *v, + Error **errp) + { + g_autoptr(GPtrArray) shadow_vqs = NULL; ++ uint64_t dev_features, svq_features; ++ int r; ++ bool ok; + + if (!v->shadow_vqs_enabled) { + return 0; + } + ++ r = hdev->vhost_ops->vhost_get_features(hdev, &dev_features); ++ if (r != 0) { ++ error_setg_errno(errp, -r, "Can't get vdpa device features"); ++ return r; ++ } ++ ++ svq_features = dev_features; ++ ok = vhost_svq_valid_features(svq_features, errp); ++ if (unlikely(!ok)) { ++ return -1; ++ } ++ + shadow_vqs = g_ptr_array_new_full(hdev->nvqs, vhost_svq_free); + for (unsigned n = 0; n < hdev->nvqs; ++n) { + g_autoptr(VhostShadowVirtqueue) svq = vhost_svq_new(); +-- +2.27.0 + diff --git a/vhost-Always-store-new-kick-fd-on-vhost_svq_set_svq_.patch b/vhost-Always-store-new-kick-fd-on-vhost_svq_set_svq_.patch new file mode 100644 index 00000000..e013942d --- /dev/null +++ b/vhost-Always-store-new-kick-fd-on-vhost_svq_set_svq_.patch @@ -0,0 +1,57 @@ +From 42cdf9d4b5c4ec0a6fbbebd79c21e5c39d831a48 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= +Date: Tue, 23 Aug 2022 20:20:07 +0200 +Subject: [PATCH] vhost: Always store new kick fd on vhost_svq_set_svq_kick_fd +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +We can unbind twice a file descriptor if we call twice +vhost_svq_set_svq_kick_fd because of this. Since it comes from vhost and +not from SVQ, that file descriptor could be a different thing that +guest's vhost notifier. + +Likewise, it can happens the same if a guest start and stop the device +multiple times. + +Reported-by: Lei Yang +Fixes: dff4426fa6 ("vhost: Add Shadow VirtQueue kick forwarding capabilities") +Signed-off-by: Eugenio Pérez +Acked-by: Jason Wang +Signed-off-by: Jason Wang +Signed-off-by: fangyi +--- + hw/virtio/vhost-shadow-virtqueue.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/hw/virtio/vhost-shadow-virtqueue.c b/hw/virtio/vhost-shadow-virtqueue.c +index 47e831667c..1ea7b5cf59 100644 +--- a/hw/virtio/vhost-shadow-virtqueue.c ++++ b/hw/virtio/vhost-shadow-virtqueue.c +@@ -601,13 +601,13 @@ void vhost_svq_set_svq_kick_fd(VhostShadowVirtqueue *svq, int svq_kick_fd) + event_notifier_set_handler(svq_kick, NULL); + } + ++ event_notifier_init_fd(svq_kick, svq_kick_fd); + /* + * event_notifier_set_handler already checks for guest's notifications if + * they arrive at the new file descriptor in the switch, so there is no + * need to explicitly check for them. + */ + if (poll_start) { +- event_notifier_init_fd(svq_kick, svq_kick_fd); + event_notifier_set(svq_kick); + event_notifier_set_handler(svq_kick, vhost_handle_guest_kick_notifier); + } +@@ -655,7 +655,7 @@ void vhost_svq_start(VhostShadowVirtqueue *svq, VirtIODevice *vdev, + */ + void vhost_svq_stop(VhostShadowVirtqueue *svq) + { +- event_notifier_set_handler(&svq->svq_kick, NULL); ++ vhost_svq_set_svq_kick_fd(svq, VHOST_FILE_UNBIND); + g_autofree VirtQueueElement *next_avail_elem = NULL; + + if (!svq->vq) { +-- +2.27.0 + diff --git a/vhost-Check-for-queue-full-at-vhost_svq_add.patch b/vhost-Check-for-queue-full-at-vhost_svq_add.patch new file mode 100644 index 00000000..98f4f8e1 --- /dev/null +++ b/vhost-Check-for-queue-full-at-vhost_svq_add.patch @@ -0,0 +1,115 @@ +From 53e6a3ff0ad77689e8cfb79b2e97ca30058949a9 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= +Date: Wed, 20 Jul 2022 08:59:32 +0200 +Subject: [PATCH] vhost: Check for queue full at vhost_svq_add +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The series need to expose vhost_svq_add with full functionality, +including checking for full queue. + +Signed-off-by: Eugenio Pérez +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Jason Wang +Signed-off-by: fangyi +--- + hw/virtio/vhost-shadow-virtqueue.c | 59 +++++++++++++++++------------- + 1 file changed, 33 insertions(+), 26 deletions(-) + +diff --git a/hw/virtio/vhost-shadow-virtqueue.c b/hw/virtio/vhost-shadow-virtqueue.c +index b99630acee..7104004a81 100644 +--- a/hw/virtio/vhost-shadow-virtqueue.c ++++ b/hw/virtio/vhost-shadow-virtqueue.c +@@ -232,21 +232,29 @@ static void vhost_svq_kick(VhostShadowVirtqueue *svq) + * Add an element to a SVQ. + * + * The caller must check that there is enough slots for the new element. It +- * takes ownership of the element: In case of failure, it is free and the SVQ +- * is considered broken. ++ * takes ownership of the element: In case of failure not ENOSPC, it is free. ++ * ++ * Return -EINVAL if element is invalid, -ENOSPC if dev queue is full + */ +-static bool vhost_svq_add(VhostShadowVirtqueue *svq, VirtQueueElement *elem) ++static int vhost_svq_add(VhostShadowVirtqueue *svq, VirtQueueElement *elem) + { + unsigned qemu_head; +- bool ok = vhost_svq_add_split(svq, elem, &qemu_head); ++ unsigned ndescs = elem->in_num + elem->out_num; ++ bool ok; ++ ++ if (unlikely(ndescs > vhost_svq_available_slots(svq))) { ++ return -ENOSPC; ++ } ++ ++ ok = vhost_svq_add_split(svq, elem, &qemu_head); + if (unlikely(!ok)) { + g_free(elem); +- return false; ++ return -EINVAL; + } + + svq->ring_id_maps[qemu_head] = elem; + vhost_svq_kick(svq); +- return true; ++ return 0; + } + + /** +@@ -273,7 +281,7 @@ static void vhost_handle_guest_kick(VhostShadowVirtqueue *svq) + + while (true) { + VirtQueueElement *elem; +- bool ok; ++ int r; + + if (svq->next_guest_avail_elem) { + elem = g_steal_pointer(&svq->next_guest_avail_elem); +@@ -285,25 +293,24 @@ static void vhost_handle_guest_kick(VhostShadowVirtqueue *svq) + break; + } + +- if (elem->out_num + elem->in_num > vhost_svq_available_slots(svq)) { +- /* +- * This condition is possible since a contiguous buffer in GPA +- * does not imply a contiguous buffer in qemu's VA +- * scatter-gather segments. If that happens, the buffer exposed +- * to the device needs to be a chain of descriptors at this +- * moment. +- * +- * SVQ cannot hold more available buffers if we are here: +- * queue the current guest descriptor and ignore further kicks +- * until some elements are used. +- */ +- svq->next_guest_avail_elem = elem; +- return; +- } +- +- ok = vhost_svq_add(svq, elem); +- if (unlikely(!ok)) { +- /* VQ is broken, just return and ignore any other kicks */ ++ r = vhost_svq_add(svq, elem); ++ if (unlikely(r != 0)) { ++ if (r == -ENOSPC) { ++ /* ++ * This condition is possible since a contiguous buffer in ++ * GPA does not imply a contiguous buffer in qemu's VA ++ * scatter-gather segments. If that happens, the buffer ++ * exposed to the device needs to be a chain of descriptors ++ * at this moment. ++ * ++ * SVQ cannot hold more available buffers if we are here: ++ * queue the current guest descriptor and ignore kicks ++ * until some elements are used. ++ */ ++ svq->next_guest_avail_elem = elem; ++ } ++ ++ /* VQ is full or broken, just return and ignore kicks */ + return; + } + } +-- +2.27.0 + diff --git a/vhost-Decouple-vhost_svq_add-from-VirtQueueElement.patch b/vhost-Decouple-vhost_svq_add-from-VirtQueueElement.patch new file mode 100644 index 00000000..298fe6ac --- /dev/null +++ b/vhost-Decouple-vhost_svq_add-from-VirtQueueElement.patch @@ -0,0 +1,119 @@ +From 1f484df7fb48cdf24e619118ddf67b8cd4e02231 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= +Date: Wed, 20 Jul 2022 08:59:33 +0200 +Subject: [PATCH] vhost: Decouple vhost_svq_add from VirtQueueElement +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +VirtQueueElement comes from the guest, but we're heading SVQ to be able +to modify the element presented to the device without the guest's +knowledge. + +To do so, make SVQ accept sg buffers directly, instead of using +VirtQueueElement. + +Add vhost_svq_add_element to maintain element convenience. + +Signed-off-by: Eugenio Pérez +Acked-by: Jason Wang +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Jason Wang +Signed-off-by: fangyi +--- + hw/virtio/vhost-shadow-virtqueue.c | 33 ++++++++++++++++++++---------- + 1 file changed, 22 insertions(+), 11 deletions(-) + +diff --git a/hw/virtio/vhost-shadow-virtqueue.c b/hw/virtio/vhost-shadow-virtqueue.c +index 7104004a81..00f5ccddfb 100644 +--- a/hw/virtio/vhost-shadow-virtqueue.c ++++ b/hw/virtio/vhost-shadow-virtqueue.c +@@ -171,30 +171,31 @@ static bool vhost_svq_vring_write_descs(VhostShadowVirtqueue *svq, hwaddr *sg, + } + + static bool vhost_svq_add_split(VhostShadowVirtqueue *svq, +- VirtQueueElement *elem, unsigned *head) ++ const struct iovec *out_sg, size_t out_num, ++ const struct iovec *in_sg, size_t in_num, ++ unsigned *head) + { + unsigned avail_idx; + vring_avail_t *avail = svq->vring.avail; + bool ok; +- g_autofree hwaddr *sgs = g_new(hwaddr, MAX(elem->out_num, elem->in_num)); ++ g_autofree hwaddr *sgs = g_new(hwaddr, MAX(out_num, in_num)); + + *head = svq->free_head; + + /* We need some descriptors here */ +- if (unlikely(!elem->out_num && !elem->in_num)) { ++ if (unlikely(!out_num && !in_num)) { + qemu_log_mask(LOG_GUEST_ERROR, + "Guest provided element with no descriptors"); + return false; + } + +- ok = vhost_svq_vring_write_descs(svq, sgs, elem->out_sg, elem->out_num, +- elem->in_num > 0, false); ++ ok = vhost_svq_vring_write_descs(svq, sgs, out_sg, out_num, in_num > 0, ++ false); + if (unlikely(!ok)) { + return false; + } + +- ok = vhost_svq_vring_write_descs(svq, sgs, elem->in_sg, elem->in_num, false, +- true); ++ ok = vhost_svq_vring_write_descs(svq, sgs, in_sg, in_num, false, true); + if (unlikely(!ok)) { + return false; + } +@@ -236,17 +237,19 @@ static void vhost_svq_kick(VhostShadowVirtqueue *svq) + * + * Return -EINVAL if element is invalid, -ENOSPC if dev queue is full + */ +-static int vhost_svq_add(VhostShadowVirtqueue *svq, VirtQueueElement *elem) ++static int vhost_svq_add(VhostShadowVirtqueue *svq, const struct iovec *out_sg, ++ size_t out_num, const struct iovec *in_sg, ++ size_t in_num, VirtQueueElement *elem) + { + unsigned qemu_head; +- unsigned ndescs = elem->in_num + elem->out_num; ++ unsigned ndescs = in_num + out_num; + bool ok; + + if (unlikely(ndescs > vhost_svq_available_slots(svq))) { + return -ENOSPC; + } + +- ok = vhost_svq_add_split(svq, elem, &qemu_head); ++ ok = vhost_svq_add_split(svq, out_sg, out_num, in_sg, in_num, &qemu_head); + if (unlikely(!ok)) { + g_free(elem); + return -EINVAL; +@@ -257,6 +260,14 @@ static int vhost_svq_add(VhostShadowVirtqueue *svq, VirtQueueElement *elem) + return 0; + } + ++/* Convenience wrapper to add a guest's element to SVQ */ ++static int vhost_svq_add_element(VhostShadowVirtqueue *svq, ++ VirtQueueElement *elem) ++{ ++ return vhost_svq_add(svq, elem->out_sg, elem->out_num, elem->in_sg, ++ elem->in_num, elem); ++} ++ + /** + * Forward available buffers. + * +@@ -293,7 +304,7 @@ static void vhost_handle_guest_kick(VhostShadowVirtqueue *svq) + break; + } + +- r = vhost_svq_add(svq, elem); ++ r = vhost_svq_add_element(svq, elem); + if (unlikely(r != 0)) { + if (r == -ENOSPC) { + /* +-- +2.27.0 + diff --git a/vhost-Expose-vhost_svq_add.patch b/vhost-Expose-vhost_svq_add.patch new file mode 100644 index 00000000..d514ec4e --- /dev/null +++ b/vhost-Expose-vhost_svq_add.patch @@ -0,0 +1,54 @@ +From 9e4727140479522c62070069d552b378c73864f3 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= +Date: Wed, 20 Jul 2022 08:59:37 +0200 +Subject: [PATCH] vhost: Expose vhost_svq_add +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This allows external parts of SVQ to forward custom buffers to the +device. + +Signed-off-by: Eugenio Pérez +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Jason Wang +Signed-off-by: fangyi +--- + hw/virtio/vhost-shadow-virtqueue.c | 6 +++--- + hw/virtio/vhost-shadow-virtqueue.h | 3 +++ + 2 files changed, 6 insertions(+), 3 deletions(-) + +diff --git a/hw/virtio/vhost-shadow-virtqueue.c b/hw/virtio/vhost-shadow-virtqueue.c +index 3b5d3bd3f3..5a85365478 100644 +--- a/hw/virtio/vhost-shadow-virtqueue.c ++++ b/hw/virtio/vhost-shadow-virtqueue.c +@@ -237,9 +237,9 @@ static void vhost_svq_kick(VhostShadowVirtqueue *svq) + * + * Return -EINVAL if element is invalid, -ENOSPC if dev queue is full + */ +-static int vhost_svq_add(VhostShadowVirtqueue *svq, const struct iovec *out_sg, +- size_t out_num, const struct iovec *in_sg, +- size_t in_num, VirtQueueElement *elem) ++int vhost_svq_add(VhostShadowVirtqueue *svq, const struct iovec *out_sg, ++ size_t out_num, const struct iovec *in_sg, size_t in_num, ++ VirtQueueElement *elem) + { + unsigned qemu_head; + unsigned ndescs = in_num + out_num; +diff --git a/hw/virtio/vhost-shadow-virtqueue.h b/hw/virtio/vhost-shadow-virtqueue.h +index d9fc1f1799..dd78f4bec2 100644 +--- a/hw/virtio/vhost-shadow-virtqueue.h ++++ b/hw/virtio/vhost-shadow-virtqueue.h +@@ -86,6 +86,9 @@ bool vhost_svq_valid_features(uint64_t features, Error **errp); + + void vhost_svq_push_elem(VhostShadowVirtqueue *svq, + const VirtQueueElement *elem, uint32_t len); ++int vhost_svq_add(VhostShadowVirtqueue *svq, const struct iovec *out_sg, ++ size_t out_num, const struct iovec *in_sg, size_t in_num, ++ VirtQueueElement *elem); + + void vhost_svq_set_svq_kick_fd(VhostShadowVirtqueue *svq, int svq_kick_fd); + void vhost_svq_set_svq_call_fd(VhostShadowVirtqueue *svq, int call_fd); +-- +2.27.0 + diff --git a/vhost-Fix-device-s-used-descriptor-dequeue.patch b/vhost-Fix-device-s-used-descriptor-dequeue.patch new file mode 100644 index 00000000..f1f751e6 --- /dev/null +++ b/vhost-Fix-device-s-used-descriptor-dequeue.patch @@ -0,0 +1,64 @@ +From a704fb13777c6820cb8a451dbe0b082f6840f9ef Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= +Date: Thu, 12 May 2022 19:57:43 +0200 +Subject: [PATCH] vhost: Fix device's used descriptor dequeue +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Only the first one of them were properly enqueued back. + +Fixes: 100890f7ca ("vhost: Shadow virtqueue buffers forwarding") + +Signed-off-by: Eugenio Pérez +Message-Id: <20220512175747.142058-3-eperezma@redhat.com> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Signed-off-by: fangyi +--- + hw/virtio/vhost-shadow-virtqueue.c | 17 +++++++++++++++-- + 1 file changed, 15 insertions(+), 2 deletions(-) + +diff --git a/hw/virtio/vhost-shadow-virtqueue.c b/hw/virtio/vhost-shadow-virtqueue.c +index 6057a437df..0b394694de 100644 +--- a/hw/virtio/vhost-shadow-virtqueue.c ++++ b/hw/virtio/vhost-shadow-virtqueue.c +@@ -333,12 +333,22 @@ static void vhost_svq_disable_notification(VhostShadowVirtqueue *svq) + svq->vring.avail->flags |= cpu_to_le16(VRING_AVAIL_F_NO_INTERRUPT); + } + ++static uint16_t vhost_svq_last_desc_of_chain(const VhostShadowVirtqueue *svq, ++ uint16_t num, uint16_t i) ++{ ++ for (uint16_t j = 0; j < (num - 1); ++j) { ++ i = le16_to_cpu(svq->desc_next[i]); ++ } ++ ++ return i; ++} ++ + static VirtQueueElement *vhost_svq_get_buf(VhostShadowVirtqueue *svq, + uint32_t *len) + { + const vring_used_t *used = svq->vring.used; + vring_used_elem_t used_elem; +- uint16_t last_used; ++ uint16_t last_used, last_used_chain, num; + + if (!vhost_svq_more_used(svq)) { + return NULL; +@@ -364,7 +374,10 @@ static VirtQueueElement *vhost_svq_get_buf(VhostShadowVirtqueue *svq, + return NULL; + } + +- svq->desc_next[used_elem.id] = svq->free_head; ++ num = svq->ring_id_maps[used_elem.id]->in_num + ++ svq->ring_id_maps[used_elem.id]->out_num; ++ last_used_chain = vhost_svq_last_desc_of_chain(svq, num, used_elem.id); ++ svq->desc_next[last_used_chain] = svq->free_head; + svq->free_head = used_elem.id; + + *len = used_elem.len; +-- +2.27.0 + diff --git a/vhost-Fix-element-in-vhost_svq_add-failure.patch b/vhost-Fix-element-in-vhost_svq_add-failure.patch new file mode 100644 index 00000000..bad4669e --- /dev/null +++ b/vhost-Fix-element-in-vhost_svq_add-failure.patch @@ -0,0 +1,49 @@ +From 3f2c58f4a5abda763c2d4627c7da252ecf604bbb Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= +Date: Thu, 12 May 2022 19:57:47 +0200 +Subject: [PATCH] vhost: Fix element in vhost_svq_add failure +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Coverity rightly reports that is not free in that case. + +Fixes: Coverity CID 1487559 +Fixes: 100890f7ca ("vhost: Shadow virtqueue buffers forwarding") + +Signed-off-by: Eugenio Pérez +Message-Id: <20220512175747.142058-7-eperezma@redhat.com> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Signed-off-by: fangyi +--- + hw/virtio/vhost-shadow-virtqueue.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/hw/virtio/vhost-shadow-virtqueue.c b/hw/virtio/vhost-shadow-virtqueue.c +index 0b394694de..cea2c3f8dd 100644 +--- a/hw/virtio/vhost-shadow-virtqueue.c ++++ b/hw/virtio/vhost-shadow-virtqueue.c +@@ -198,11 +198,19 @@ static bool vhost_svq_add_split(VhostShadowVirtqueue *svq, + return true; + } + ++/** ++ * Add an element to a SVQ. ++ * ++ * The caller must check that there is enough slots for the new element. It ++ * takes ownership of the element: In case of failure, it is free and the SVQ ++ * is considered broken. ++ */ + static bool vhost_svq_add(VhostShadowVirtqueue *svq, VirtQueueElement *elem) + { + unsigned qemu_head; + bool ok = vhost_svq_add_split(svq, elem, &qemu_head); + if (unlikely(!ok)) { ++ g_free(elem); + return false; + } + +-- +2.27.0 + diff --git a/vhost-Fix-false-positive-out-of-bounds.patch b/vhost-Fix-false-positive-out-of-bounds.patch new file mode 100644 index 00000000..1a6687eb --- /dev/null +++ b/vhost-Fix-false-positive-out-of-bounds.patch @@ -0,0 +1,49 @@ +From 9c38d583be2704d7cb5a40e25c9ba0227cbe70cd Mon Sep 17 00:00:00 2001 +From: Hawkins Jiawei +Date: Fri, 7 Jul 2023 23:27:31 +0800 +Subject: [PATCH] vhost: Fix false positive out-of-bounds + +QEMU uses vhost_svq_translate_addr() to translate addresses +between the QEMU's virtual address and the SVQ IOVA. In order +to validate this translation, QEMU checks whether the translated +range falls within the mapped range. + +Yet the problem is that, the value of `needle_last`, which is calculated +by `needle.translated_addr + iovec[i].iov_len`, should represent the +exclusive boundary of the translated range, rather than the last +inclusive addresses of the range. Consequently, QEMU fails the check +when the translated range matches the size of the mapped range. + +This patch solves this problem by fixing the `needle_last` value to +the last inclusive address of the translated range. + +Note that this bug cannot be triggered at the moment, because QEMU +is unable to translate such a big range due to the truncation of +the CVQ command in vhost_vdpa_net_handle_ctrl_avail(). + +Fixes: 34e3c94eda ("vdpa: Add custom IOTLB translations to SVQ") +Signed-off-by: Hawkins Jiawei +Message-Id: +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Signed-off-by: fangyi +--- + hw/virtio/vhost-shadow-virtqueue.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/hw/virtio/vhost-shadow-virtqueue.c b/hw/virtio/vhost-shadow-virtqueue.c +index 8d99edb196..8b5902a8a5 100644 +--- a/hw/virtio/vhost-shadow-virtqueue.c ++++ b/hw/virtio/vhost-shadow-virtqueue.c +@@ -109,7 +109,7 @@ static bool vhost_svq_translate_addr(const VhostShadowVirtqueue *svq, + addrs[i] = map->iova + off; + + needle_last = int128_add(int128_make64(needle.translated_addr), +- int128_make64(iovec[i].iov_len)); ++ int128_makes64(iovec[i].iov_len - 1)); + map_last = int128_make64(map->translated_addr + map->size); + if (unlikely(int128_gt(needle_last, map_last))) { + qemu_log_mask(LOG_GUEST_ERROR, +-- +2.27.0 + diff --git a/vhost-Get-vring-base-from-vq-not-svq.patch b/vhost-Get-vring-base-from-vq-not-svq.patch new file mode 100644 index 00000000..d388ff19 --- /dev/null +++ b/vhost-Get-vring-base-from-vq-not-svq.patch @@ -0,0 +1,78 @@ +From a11196160aaf5ba1102ba324c5a7926e83548f6b Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= +Date: Mon, 18 Jul 2022 14:05:45 +0200 +Subject: [PATCH] vhost: Get vring base from vq, not svq +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The SVQ vring used idx usually match with the guest visible one, as long +as all the guest buffers (GPA) maps to exactly one buffer within qemu's +VA. However, as we can see in virtqueue_map_desc, a single guest buffer +could map to many buffers in SVQ vring. + +Also, its also a mistake to rewind them at the source of migration. +Since VirtQueue is able to migrate the inflight descriptors, its +responsability of the destination to perform the rewind just in case it +cannot report the inflight descriptors to the device. + +This makes easier to migrate between backends or to recover them in +vhost devices that support set in flight descriptors. + +Fixes: 6d0b22266633 ("vdpa: Adapt vhost_vdpa_get_vring_base to SVQ") +Signed-off-by: Eugenio Pérez +Signed-off-by: Jason Wang +Signed-off-by: fangyi +--- + hw/virtio/vhost-vdpa.c | 24 ++++++++++++------------ + 1 file changed, 12 insertions(+), 12 deletions(-) + +diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c +index 5956ff4660..6304f174c2 100644 +--- a/hw/virtio/vhost-vdpa.c ++++ b/hw/virtio/vhost-vdpa.c +@@ -1181,7 +1181,18 @@ static int vhost_vdpa_set_vring_base(struct vhost_dev *dev, + struct vhost_vring_state *ring) + { + struct vhost_vdpa *v = dev->opaque; ++ VirtQueue *vq = virtio_get_queue(dev->vdev, ring->index); + ++ /* ++ * vhost-vdpa devices does not support in-flight requests. Set all of them ++ * as available. ++ * ++ * TODO: This is ok for networking, but other kinds of devices might ++ * have problems with these retransmissions. ++ */ ++ while (virtqueue_rewind(vq, 1)) { ++ continue; ++ } + if (v->shadow_vqs_enabled) { + /* + * Device vring base was set at device start. SVQ base is handled by +@@ -1197,21 +1208,10 @@ static int vhost_vdpa_get_vring_base(struct vhost_dev *dev, + struct vhost_vring_state *ring) + { + struct vhost_vdpa *v = dev->opaque; +- int vdpa_idx = ring->index - dev->vq_index; + int ret; + + if (v->shadow_vqs_enabled) { +- VhostShadowVirtqueue *svq = g_ptr_array_index(v->shadow_vqs, vdpa_idx); +- +- /* +- * Setting base as last used idx, so destination will see as available +- * all the entries that the device did not use, including the in-flight +- * processing ones. +- * +- * TODO: This is ok for networking, but other kinds of devices might +- * have problems with these retransmissions. +- */ +- ring->num = svq->last_used_idx; ++ ring->num = virtio_queue_get_last_avail_idx(dev->vdev, ring->index); + return 0; + } + +-- +2.27.0 + diff --git a/vhost-Move-vhost_svq_kick-call-to-vhost_svq_add.patch b/vhost-Move-vhost_svq_kick-call-to-vhost_svq_add.patch new file mode 100644 index 00000000..5636e942 --- /dev/null +++ b/vhost-Move-vhost_svq_kick-call-to-vhost_svq_add.patch @@ -0,0 +1,42 @@ +From ebce19945a9bbe3144affa6f5f4129b914e749a0 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= +Date: Wed, 20 Jul 2022 08:59:31 +0200 +Subject: [PATCH] vhost: Move vhost_svq_kick call to vhost_svq_add +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The series needs to expose vhost_svq_add with full functionality, +including kick + +Signed-off-by: Eugenio Pérez +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Jason Wang +Signed-off-by: fangyi +--- + hw/virtio/vhost-shadow-virtqueue.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/hw/virtio/vhost-shadow-virtqueue.c b/hw/virtio/vhost-shadow-virtqueue.c +index 1ba863b802..b99630acee 100644 +--- a/hw/virtio/vhost-shadow-virtqueue.c ++++ b/hw/virtio/vhost-shadow-virtqueue.c +@@ -245,6 +245,7 @@ static bool vhost_svq_add(VhostShadowVirtqueue *svq, VirtQueueElement *elem) + } + + svq->ring_id_maps[qemu_head] = elem; ++ vhost_svq_kick(svq); + return true; + } + +@@ -305,7 +306,6 @@ static void vhost_handle_guest_kick(VhostShadowVirtqueue *svq) + /* VQ is broken, just return and ignore any other kicks */ + return; + } +- vhost_svq_kick(svq); + } + + virtio_queue_set_notification(svq->vq, true); +-- +2.27.0 + diff --git a/vhost-Reorder-vhost_svq_kick.patch b/vhost-Reorder-vhost_svq_kick.patch new file mode 100644 index 00000000..459e3547 --- /dev/null +++ b/vhost-Reorder-vhost_svq_kick.patch @@ -0,0 +1,69 @@ +From 5bf30b401a5fa16189589381d42bfc5f6cf8cf9c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= +Date: Wed, 20 Jul 2022 08:59:30 +0200 +Subject: [PATCH] vhost: Reorder vhost_svq_kick +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Future code needs to call it from vhost_svq_add. + +No functional change intended. + +Signed-off-by: Eugenio Pérez +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Jason Wang +Signed-off-by: fangyi +--- + hw/virtio/vhost-shadow-virtqueue.c | 28 ++++++++++++++-------------- + 1 file changed, 14 insertions(+), 14 deletions(-) + +diff --git a/hw/virtio/vhost-shadow-virtqueue.c b/hw/virtio/vhost-shadow-virtqueue.c +index acf50a9a0b..1ba863b802 100644 +--- a/hw/virtio/vhost-shadow-virtqueue.c ++++ b/hw/virtio/vhost-shadow-virtqueue.c +@@ -214,6 +214,20 @@ static bool vhost_svq_add_split(VhostShadowVirtqueue *svq, + return true; + } + ++static void vhost_svq_kick(VhostShadowVirtqueue *svq) ++{ ++ /* ++ * We need to expose the available array entries before checking the used ++ * flags ++ */ ++ smp_mb(); ++ if (svq->vring.used->flags & VRING_USED_F_NO_NOTIFY) { ++ return; ++ } ++ ++ event_notifier_set(&svq->hdev_kick); ++} ++ + /** + * Add an element to a SVQ. + * +@@ -234,20 +248,6 @@ static bool vhost_svq_add(VhostShadowVirtqueue *svq, VirtQueueElement *elem) + return true; + } + +-static void vhost_svq_kick(VhostShadowVirtqueue *svq) +-{ +- /* +- * We need to expose the available array entries before checking the used +- * flags +- */ +- smp_mb(); +- if (svq->vring.used->flags & VRING_USED_F_NO_NOTIFY) { +- return; +- } +- +- event_notifier_set(&svq->hdev_kick); +-} +- + /** + * Forward available buffers. + * +-- +2.27.0 + diff --git a/vhost-Shadow-virtqueue-buffers-forwarding.patch b/vhost-Shadow-virtqueue-buffers-forwarding.patch new file mode 100644 index 00000000..5d38f7a8 --- /dev/null +++ b/vhost-Shadow-virtqueue-buffers-forwarding.patch @@ -0,0 +1,684 @@ +From bb7c23fd4979edaeeedf05e05cfed0d086430500 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= +Date: Mon, 14 Mar 2022 18:34:47 +0100 +Subject: [PATCH] vhost: Shadow virtqueue buffers forwarding +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Initial version of shadow virtqueue that actually forward buffers. There +is no iommu support at the moment, and that will be addressed in future +patches of this series. Since all vhost-vdpa devices use forced IOMMU, +this means that SVQ is not usable at this point of the series on any +device. + +For simplicity it only supports modern devices, that expects vring +in little endian, with split ring and no event idx or indirect +descriptors. Support for them will not be added in this series. + +It reuses the VirtQueue code for the device part. The driver part is +based on Linux's virtio_ring driver, but with stripped functionality +and optimizations so it's easier to review. + +However, forwarding buffers have some particular pieces: One of the most +unexpected ones is that a guest's buffer can expand through more than +one descriptor in SVQ. While this is handled gracefully by qemu's +emulated virtio devices, it may cause unexpected SVQ queue full. This +patch also solves it by checking for this condition at both guest's +kicks and device's calls. The code may be more elegant in the future if +SVQ code runs in its own iocontext. + +Signed-off-by: Eugenio Pérez +Acked-by: Michael S. Tsirkin +Signed-off-by: Jason Wang +Signed-off-by: fangyi +--- + hw/virtio/vhost-shadow-virtqueue.c | 351 ++++++++++++++++++++++++++++- + hw/virtio/vhost-shadow-virtqueue.h | 26 +++ + hw/virtio/vhost-vdpa.c | 155 ++++++++++++- + 3 files changed, 521 insertions(+), 11 deletions(-) + +diff --git a/hw/virtio/vhost-shadow-virtqueue.c b/hw/virtio/vhost-shadow-virtqueue.c +index 573ac0d9cf..46e94f0861 100644 +--- a/hw/virtio/vhost-shadow-virtqueue.c ++++ b/hw/virtio/vhost-shadow-virtqueue.c +@@ -13,6 +13,7 @@ + #include "qemu/error-report.h" + #include "qapi/error.h" + #include "qemu/main-loop.h" ++#include "qemu/log.h" + #include "linux-headers/linux/vhost.h" + + /** +@@ -59,28 +60,307 @@ bool vhost_svq_valid_features(uint64_t features, Error **errp) + } + + /** +- * Forward guest notifications. ++ * Number of descriptors that the SVQ can make available from the guest. ++ * ++ * @svq: The svq ++ */ ++static uint16_t vhost_svq_available_slots(const VhostShadowVirtqueue *svq) ++{ ++ return svq->vring.num - (svq->shadow_avail_idx - svq->shadow_used_idx); ++} ++ ++static void vhost_vring_write_descs(VhostShadowVirtqueue *svq, ++ const struct iovec *iovec, size_t num, ++ bool more_descs, bool write) ++{ ++ uint16_t i = svq->free_head, last = svq->free_head; ++ unsigned n; ++ uint16_t flags = write ? cpu_to_le16(VRING_DESC_F_WRITE) : 0; ++ vring_desc_t *descs = svq->vring.desc; ++ ++ if (num == 0) { ++ return; ++ } ++ ++ for (n = 0; n < num; n++) { ++ if (more_descs || (n + 1 < num)) { ++ descs[i].flags = flags | cpu_to_le16(VRING_DESC_F_NEXT); ++ } else { ++ descs[i].flags = flags; ++ } ++ descs[i].addr = cpu_to_le64((hwaddr)(intptr_t)iovec[n].iov_base); ++ descs[i].len = cpu_to_le32(iovec[n].iov_len); ++ ++ last = i; ++ i = cpu_to_le16(descs[i].next); ++ } ++ ++ svq->free_head = le16_to_cpu(descs[last].next); ++} ++ ++static bool vhost_svq_add_split(VhostShadowVirtqueue *svq, ++ VirtQueueElement *elem, unsigned *head) ++{ ++ unsigned avail_idx; ++ vring_avail_t *avail = svq->vring.avail; ++ ++ *head = svq->free_head; ++ ++ /* We need some descriptors here */ ++ if (unlikely(!elem->out_num && !elem->in_num)) { ++ qemu_log_mask(LOG_GUEST_ERROR, ++ "Guest provided element with no descriptors"); ++ return false; ++ } ++ ++ vhost_vring_write_descs(svq, elem->out_sg, elem->out_num, elem->in_num > 0, ++ false); ++ vhost_vring_write_descs(svq, elem->in_sg, elem->in_num, false, true); ++ ++ /* ++ * Put the entry in the available array (but don't update avail->idx until ++ * they do sync). ++ */ ++ avail_idx = svq->shadow_avail_idx & (svq->vring.num - 1); ++ avail->ring[avail_idx] = cpu_to_le16(*head); ++ svq->shadow_avail_idx++; ++ ++ /* Update the avail index after write the descriptor */ ++ smp_wmb(); ++ avail->idx = cpu_to_le16(svq->shadow_avail_idx); ++ ++ return true; ++} ++ ++static bool vhost_svq_add(VhostShadowVirtqueue *svq, VirtQueueElement *elem) ++{ ++ unsigned qemu_head; ++ bool ok = vhost_svq_add_split(svq, elem, &qemu_head); ++ if (unlikely(!ok)) { ++ return false; ++ } ++ ++ svq->ring_id_maps[qemu_head] = elem; ++ return true; ++} ++ ++static void vhost_svq_kick(VhostShadowVirtqueue *svq) ++{ ++ /* ++ * We need to expose the available array entries before checking the used ++ * flags ++ */ ++ smp_mb(); ++ if (svq->vring.used->flags & VRING_USED_F_NO_NOTIFY) { ++ return; ++ } ++ ++ event_notifier_set(&svq->hdev_kick); ++} ++ ++/** ++ * Forward available buffers. ++ * ++ * @svq: Shadow VirtQueue ++ * ++ * Note that this function does not guarantee that all guest's available ++ * buffers are available to the device in SVQ avail ring. The guest may have ++ * exposed a GPA / GIOVA contiguous buffer, but it may not be contiguous in ++ * qemu vaddr. ++ * ++ * If that happens, guest's kick notifications will be disabled until the ++ * device uses some buffers. ++ */ ++static void vhost_handle_guest_kick(VhostShadowVirtqueue *svq) ++{ ++ /* Clear event notifier */ ++ event_notifier_test_and_clear(&svq->svq_kick); ++ ++ /* Forward to the device as many available buffers as possible */ ++ do { ++ virtio_queue_set_notification(svq->vq, false); ++ ++ while (true) { ++ VirtQueueElement *elem; ++ bool ok; ++ ++ if (svq->next_guest_avail_elem) { ++ elem = g_steal_pointer(&svq->next_guest_avail_elem); ++ } else { ++ elem = virtqueue_pop(svq->vq, sizeof(*elem)); ++ } ++ ++ if (!elem) { ++ break; ++ } ++ ++ if (elem->out_num + elem->in_num > vhost_svq_available_slots(svq)) { ++ /* ++ * This condition is possible since a contiguous buffer in GPA ++ * does not imply a contiguous buffer in qemu's VA ++ * scatter-gather segments. If that happens, the buffer exposed ++ * to the device needs to be a chain of descriptors at this ++ * moment. ++ * ++ * SVQ cannot hold more available buffers if we are here: ++ * queue the current guest descriptor and ignore further kicks ++ * until some elements are used. ++ */ ++ svq->next_guest_avail_elem = elem; ++ return; ++ } ++ ++ ok = vhost_svq_add(svq, elem); ++ if (unlikely(!ok)) { ++ /* VQ is broken, just return and ignore any other kicks */ ++ return; ++ } ++ vhost_svq_kick(svq); ++ } ++ ++ virtio_queue_set_notification(svq->vq, true); ++ } while (!virtio_queue_empty(svq->vq)); ++} ++ ++/** ++ * Handle guest's kick. + * + * @n: guest kick event notifier, the one that guest set to notify svq. + */ +-static void vhost_handle_guest_kick(EventNotifier *n) ++static void vhost_handle_guest_kick_notifier(EventNotifier *n) + { + VhostShadowVirtqueue *svq = container_of(n, VhostShadowVirtqueue, svq_kick); + event_notifier_test_and_clear(n); +- event_notifier_set(&svq->hdev_kick); ++ vhost_handle_guest_kick(svq); ++} ++ ++static bool vhost_svq_more_used(VhostShadowVirtqueue *svq) ++{ ++ if (svq->last_used_idx != svq->shadow_used_idx) { ++ return true; ++ } ++ ++ svq->shadow_used_idx = cpu_to_le16(svq->vring.used->idx); ++ ++ return svq->last_used_idx != svq->shadow_used_idx; + } + + /** +- * Forward vhost notifications ++ * Enable vhost device calls after disable them. ++ * ++ * @svq: The svq ++ * ++ * It returns false if there are pending used buffers from the vhost device, ++ * avoiding the possible races between SVQ checking for more work and enabling ++ * callbacks. True if SVQ used vring has no more pending buffers. ++ */ ++static bool vhost_svq_enable_notification(VhostShadowVirtqueue *svq) ++{ ++ svq->vring.avail->flags &= ~cpu_to_le16(VRING_AVAIL_F_NO_INTERRUPT); ++ /* Make sure the flag is written before the read of used_idx */ ++ smp_mb(); ++ return !vhost_svq_more_used(svq); ++} ++ ++static void vhost_svq_disable_notification(VhostShadowVirtqueue *svq) ++{ ++ svq->vring.avail->flags |= cpu_to_le16(VRING_AVAIL_F_NO_INTERRUPT); ++} ++ ++static VirtQueueElement *vhost_svq_get_buf(VhostShadowVirtqueue *svq, ++ uint32_t *len) ++{ ++ vring_desc_t *descs = svq->vring.desc; ++ const vring_used_t *used = svq->vring.used; ++ vring_used_elem_t used_elem; ++ uint16_t last_used; ++ ++ if (!vhost_svq_more_used(svq)) { ++ return NULL; ++ } ++ ++ /* Only get used array entries after they have been exposed by dev */ ++ smp_rmb(); ++ last_used = svq->last_used_idx & (svq->vring.num - 1); ++ used_elem.id = le32_to_cpu(used->ring[last_used].id); ++ used_elem.len = le32_to_cpu(used->ring[last_used].len); ++ ++ svq->last_used_idx++; ++ if (unlikely(used_elem.id >= svq->vring.num)) { ++ qemu_log_mask(LOG_GUEST_ERROR, "Device %s says index %u is used", ++ svq->vdev->name, used_elem.id); ++ return NULL; ++ } ++ ++ if (unlikely(!svq->ring_id_maps[used_elem.id])) { ++ qemu_log_mask(LOG_GUEST_ERROR, ++ "Device %s says index %u is used, but it was not available", ++ svq->vdev->name, used_elem.id); ++ return NULL; ++ } ++ ++ descs[used_elem.id].next = svq->free_head; ++ svq->free_head = used_elem.id; ++ ++ *len = used_elem.len; ++ return g_steal_pointer(&svq->ring_id_maps[used_elem.id]); ++} ++ ++static void vhost_svq_flush(VhostShadowVirtqueue *svq, ++ bool check_for_avail_queue) ++{ ++ VirtQueue *vq = svq->vq; ++ ++ /* Forward as many used buffers as possible. */ ++ do { ++ unsigned i = 0; ++ ++ vhost_svq_disable_notification(svq); ++ while (true) { ++ uint32_t len; ++ g_autofree VirtQueueElement *elem = vhost_svq_get_buf(svq, &len); ++ if (!elem) { ++ break; ++ } ++ ++ if (unlikely(i >= svq->vring.num)) { ++ qemu_log_mask(LOG_GUEST_ERROR, ++ "More than %u used buffers obtained in a %u size SVQ", ++ i, svq->vring.num); ++ virtqueue_fill(vq, elem, len, i); ++ virtqueue_flush(vq, i); ++ return; ++ } ++ virtqueue_fill(vq, elem, len, i++); ++ } ++ ++ virtqueue_flush(vq, i); ++ event_notifier_set(&svq->svq_call); ++ ++ if (check_for_avail_queue && svq->next_guest_avail_elem) { ++ /* ++ * Avail ring was full when vhost_svq_flush was called, so it's a ++ * good moment to make more descriptors available if possible. ++ */ ++ vhost_handle_guest_kick(svq); ++ } ++ } while (!vhost_svq_enable_notification(svq)); ++} ++ ++/** ++ * Forward used buffers. + * + * @n: hdev call event notifier, the one that device set to notify svq. ++ * ++ * Note that we are not making any buffers available in the loop, there is no ++ * way that it runs more than virtqueue size times. + */ + static void vhost_svq_handle_call(EventNotifier *n) + { + VhostShadowVirtqueue *svq = container_of(n, VhostShadowVirtqueue, + hdev_call); + event_notifier_test_and_clear(n); +- event_notifier_set(&svq->svq_call); ++ vhost_svq_flush(svq, true); + } + + /** +@@ -161,7 +441,41 @@ void vhost_svq_set_svq_kick_fd(VhostShadowVirtqueue *svq, int svq_kick_fd) + if (poll_start) { + event_notifier_init_fd(svq_kick, svq_kick_fd); + event_notifier_set(svq_kick); +- event_notifier_set_handler(svq_kick, vhost_handle_guest_kick); ++ event_notifier_set_handler(svq_kick, vhost_handle_guest_kick_notifier); ++ } ++} ++ ++/** ++ * Start the shadow virtqueue operation. ++ * ++ * @svq: Shadow Virtqueue ++ * @vdev: VirtIO device ++ * @vq: Virtqueue to shadow ++ */ ++void vhost_svq_start(VhostShadowVirtqueue *svq, VirtIODevice *vdev, ++ VirtQueue *vq) ++{ ++ size_t desc_size, driver_size, device_size; ++ ++ svq->next_guest_avail_elem = NULL; ++ svq->shadow_avail_idx = 0; ++ svq->shadow_used_idx = 0; ++ svq->last_used_idx = 0; ++ svq->vdev = vdev; ++ svq->vq = vq; ++ ++ svq->vring.num = virtio_queue_get_num(vdev, virtio_get_queue_index(vq)); ++ driver_size = vhost_svq_driver_area_size(svq); ++ device_size = vhost_svq_device_area_size(svq); ++ svq->vring.desc = qemu_memalign(qemu_real_host_page_size, driver_size); ++ desc_size = sizeof(vring_desc_t) * svq->vring.num; ++ svq->vring.avail = (void *)((char *)svq->vring.desc + desc_size); ++ memset(svq->vring.desc, 0, driver_size); ++ svq->vring.used = qemu_memalign(qemu_real_host_page_size, device_size); ++ memset(svq->vring.used, 0, device_size); ++ svq->ring_id_maps = g_new0(VirtQueueElement *, svq->vring.num); ++ for (unsigned i = 0; i < svq->vring.num - 1; i++) { ++ svq->vring.desc[i].next = cpu_to_le16(i + 1); + } + } + +@@ -172,6 +486,31 @@ void vhost_svq_set_svq_kick_fd(VhostShadowVirtqueue *svq, int svq_kick_fd) + void vhost_svq_stop(VhostShadowVirtqueue *svq) + { + event_notifier_set_handler(&svq->svq_kick, NULL); ++ g_autofree VirtQueueElement *next_avail_elem = NULL; ++ ++ if (!svq->vq) { ++ return; ++ } ++ ++ /* Send all pending used descriptors to guest */ ++ vhost_svq_flush(svq, false); ++ ++ for (unsigned i = 0; i < svq->vring.num; ++i) { ++ g_autofree VirtQueueElement *elem = NULL; ++ elem = g_steal_pointer(&svq->ring_id_maps[i]); ++ if (elem) { ++ virtqueue_detach_element(svq->vq, elem, 0); ++ } ++ } ++ ++ next_avail_elem = g_steal_pointer(&svq->next_guest_avail_elem); ++ if (next_avail_elem) { ++ virtqueue_detach_element(svq->vq, next_avail_elem, 0); ++ } ++ svq->vq = NULL; ++ g_free(svq->ring_id_maps); ++ qemu_vfree(svq->vring.desc); ++ qemu_vfree(svq->vring.used); + } + + /** +diff --git a/hw/virtio/vhost-shadow-virtqueue.h b/hw/virtio/vhost-shadow-virtqueue.h +index 82cea1c3fa..38b3b91ca7 100644 +--- a/hw/virtio/vhost-shadow-virtqueue.h ++++ b/hw/virtio/vhost-shadow-virtqueue.h +@@ -36,6 +36,30 @@ typedef struct VhostShadowVirtqueue { + + /* Guest's call notifier, where the SVQ calls guest. */ + EventNotifier svq_call; ++ ++ /* Virtio queue shadowing */ ++ VirtQueue *vq; ++ ++ /* Virtio device */ ++ VirtIODevice *vdev; ++ ++ /* Map for use the guest's descriptors */ ++ VirtQueueElement **ring_id_maps; ++ ++ /* Next VirtQueue element that guest made available */ ++ VirtQueueElement *next_guest_avail_elem; ++ ++ /* Next head to expose to the device */ ++ uint16_t shadow_avail_idx; ++ ++ /* Next free descriptor */ ++ uint16_t free_head; ++ ++ /* Last seen used idx */ ++ uint16_t shadow_used_idx; ++ ++ /* Next head to consume from the device */ ++ uint16_t last_used_idx; + } VhostShadowVirtqueue; + + bool vhost_svq_valid_features(uint64_t features, Error **errp); +@@ -47,6 +71,8 @@ void vhost_svq_get_vring_addr(const VhostShadowVirtqueue *svq, + size_t vhost_svq_driver_area_size(const VhostShadowVirtqueue *svq); + size_t vhost_svq_device_area_size(const VhostShadowVirtqueue *svq); + ++void vhost_svq_start(VhostShadowVirtqueue *svq, VirtIODevice *vdev, ++ VirtQueue *vq); + void vhost_svq_stop(VhostShadowVirtqueue *svq); + + VhostShadowVirtqueue *vhost_svq_new(void); +diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c +index 2f0e6a9bef..db34f26246 100644 +--- a/hw/virtio/vhost-vdpa.c ++++ b/hw/virtio/vhost-vdpa.c +@@ -779,9 +779,9 @@ static int vhost_vdpa_set_vring_dev_addr(struct vhost_dev *dev, + * Note that this function does not rewind kick file descriptor if cannot set + * call one. + */ +-static bool vhost_vdpa_svq_setup(struct vhost_dev *dev, +- VhostShadowVirtqueue *svq, unsigned idx, +- Error **errp) ++static int vhost_vdpa_svq_set_fds(struct vhost_dev *dev, ++ VhostShadowVirtqueue *svq, unsigned idx, ++ Error **errp) + { + struct vhost_vring_file file = { + .index = dev->vq_index + idx, +@@ -793,7 +793,7 @@ static bool vhost_vdpa_svq_setup(struct vhost_dev *dev, + r = vhost_vdpa_set_vring_dev_kick(dev, &file); + if (unlikely(r != 0)) { + error_setg_errno(errp, -r, "Can't set device kick fd"); +- return false; ++ return r; + } + + event_notifier = &svq->hdev_call; +@@ -803,6 +803,95 @@ static bool vhost_vdpa_svq_setup(struct vhost_dev *dev, + error_setg_errno(errp, -r, "Can't set device call fd"); + } + ++ return r; ++} ++ ++/** ++ * Unmap a SVQ area in the device ++ */ ++static bool vhost_vdpa_svq_unmap_ring(struct vhost_vdpa *v, hwaddr iova, ++ hwaddr size) ++{ ++ int r; ++ ++ size = ROUND_UP(size, qemu_real_host_page_size); ++ r = vhost_vdpa_dma_unmap(v, iova, size); ++ return r == 0; ++} ++ ++static bool vhost_vdpa_svq_unmap_rings(struct vhost_dev *dev, ++ const VhostShadowVirtqueue *svq) ++{ ++ struct vhost_vdpa *v = dev->opaque; ++ struct vhost_vring_addr svq_addr; ++ size_t device_size = vhost_svq_device_area_size(svq); ++ size_t driver_size = vhost_svq_driver_area_size(svq); ++ bool ok; ++ ++ vhost_svq_get_vring_addr(svq, &svq_addr); ++ ++ ok = vhost_vdpa_svq_unmap_ring(v, svq_addr.desc_user_addr, driver_size); ++ if (unlikely(!ok)) { ++ return false; ++ } ++ ++ return vhost_vdpa_svq_unmap_ring(v, svq_addr.used_user_addr, device_size); ++} ++ ++/** ++ * Map the shadow virtqueue rings in the device ++ * ++ * @dev: The vhost device ++ * @svq: The shadow virtqueue ++ * @addr: Assigned IOVA addresses ++ * @errp: Error pointer ++ */ ++static bool vhost_vdpa_svq_map_rings(struct vhost_dev *dev, ++ const VhostShadowVirtqueue *svq, ++ struct vhost_vring_addr *addr, ++ Error **errp) ++{ ++ struct vhost_vdpa *v = dev->opaque; ++ size_t device_size = vhost_svq_device_area_size(svq); ++ size_t driver_size = vhost_svq_driver_area_size(svq); ++ int r; ++ ++ ERRP_GUARD(); ++ vhost_svq_get_vring_addr(svq, addr); ++ ++ r = vhost_vdpa_dma_map(v, addr->desc_user_addr, driver_size, ++ (void *)(uintptr_t)addr->desc_user_addr, true); ++ if (unlikely(r != 0)) { ++ error_setg_errno(errp, -r, "Cannot create vq driver region: "); ++ return false; ++ } ++ ++ r = vhost_vdpa_dma_map(v, addr->used_user_addr, device_size, ++ (void *)(intptr_t)addr->used_user_addr, false); ++ if (unlikely(r != 0)) { ++ error_setg_errno(errp, -r, "Cannot create vq device region: "); ++ } ++ ++ return r == 0; ++} ++ ++static bool vhost_vdpa_svq_setup(struct vhost_dev *dev, ++ VhostShadowVirtqueue *svq, unsigned idx, ++ Error **errp) ++{ ++ uint16_t vq_index = dev->vq_index + idx; ++ struct vhost_vring_state s = { ++ .index = vq_index, ++ }; ++ int r; ++ ++ r = vhost_vdpa_set_dev_vring_base(dev, &s); ++ if (unlikely(r)) { ++ error_setg_errno(errp, -r, "Cannot set vring base"); ++ return false; ++ } ++ ++ r = vhost_vdpa_svq_set_fds(dev, svq, idx, errp); + return r == 0; + } + +@@ -817,10 +906,62 @@ static bool vhost_vdpa_svqs_start(struct vhost_dev *dev) + } + + for (i = 0; i < v->shadow_vqs->len; ++i) { ++ VirtQueue *vq = virtio_get_queue(dev->vdev, dev->vq_index + i); + VhostShadowVirtqueue *svq = g_ptr_array_index(v->shadow_vqs, i); ++ struct vhost_vring_addr addr = { ++ .index = i, ++ }; ++ int r; + bool ok = vhost_vdpa_svq_setup(dev, svq, i, &err); + if (unlikely(!ok)) { +- error_reportf_err(err, "Cannot setup SVQ %u: ", i); ++ goto err; ++ } ++ ++ vhost_svq_start(svq, dev->vdev, vq); ++ ok = vhost_vdpa_svq_map_rings(dev, svq, &addr, &err); ++ if (unlikely(!ok)) { ++ goto err_map; ++ } ++ ++ /* Override vring GPA set by vhost subsystem */ ++ r = vhost_vdpa_set_vring_dev_addr(dev, &addr); ++ if (unlikely(r != 0)) { ++ error_setg_errno(&err, -r, "Cannot set device address"); ++ goto err_set_addr; ++ } ++ } ++ ++ return true; ++ ++err_set_addr: ++ vhost_vdpa_svq_unmap_rings(dev, g_ptr_array_index(v->shadow_vqs, i)); ++ ++err_map: ++ vhost_svq_stop(g_ptr_array_index(v->shadow_vqs, i)); ++ ++err: ++ error_reportf_err(err, "Cannot setup SVQ %u: ", i); ++ for (unsigned j = 0; j < i; ++j) { ++ VhostShadowVirtqueue *svq = g_ptr_array_index(v->shadow_vqs, j); ++ vhost_vdpa_svq_unmap_rings(dev, svq); ++ vhost_svq_stop(svq); ++ } ++ ++ return false; ++} ++ ++static bool vhost_vdpa_svqs_stop(struct vhost_dev *dev) ++{ ++ struct vhost_vdpa *v = dev->opaque; ++ ++ if (!v->shadow_vqs) { ++ return true; ++ } ++ ++ for (unsigned i = 0; i < v->shadow_vqs->len; ++i) { ++ VhostShadowVirtqueue *svq = g_ptr_array_index(v->shadow_vqs, i); ++ bool ok = vhost_vdpa_svq_unmap_rings(dev, svq); ++ if (unlikely(!ok)) { + return false; + } + } +@@ -842,6 +983,10 @@ static int vhost_vdpa_dev_start(struct vhost_dev *dev, bool started) + } + vhost_vdpa_set_vring_ready(dev); + } else { ++ ok = vhost_vdpa_svqs_stop(dev); ++ if (unlikely(!ok)) { ++ return -1; ++ } + vhost_vdpa_host_notifiers_uninit(dev, dev->nvqs); + } + +-- +2.27.0 + diff --git a/vhost-Track-descriptor-chain-in-private-at-SVQ.patch b/vhost-Track-descriptor-chain-in-private-at-SVQ.patch new file mode 100644 index 00000000..dbcdb743 --- /dev/null +++ b/vhost-Track-descriptor-chain-in-private-at-SVQ.patch @@ -0,0 +1,104 @@ +From de3c31598e00c4bcee42f3921f714b0928716535 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= +Date: Thu, 12 May 2022 19:57:42 +0200 +Subject: [PATCH] vhost: Track descriptor chain in private at SVQ +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The device could have access to modify them, and it definitely have +access when we implement packed vq. Harden SVQ maintaining a private +copy of the descriptor chain. Other fields like buffer addresses are +already maintained sepparatedly. + +Signed-off-by: Eugenio Pérez +Message-Id: <20220512175747.142058-2-eperezma@redhat.com> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Signed-off-by: fangyi +--- + hw/virtio/vhost-shadow-virtqueue.c | 12 +++++++----- + hw/virtio/vhost-shadow-virtqueue.h | 6 ++++++ + 2 files changed, 13 insertions(+), 5 deletions(-) + +diff --git a/hw/virtio/vhost-shadow-virtqueue.c b/hw/virtio/vhost-shadow-virtqueue.c +index c38b6b6ab5..6057a437df 100644 +--- a/hw/virtio/vhost-shadow-virtqueue.c ++++ b/hw/virtio/vhost-shadow-virtqueue.c +@@ -137,6 +137,7 @@ static void vhost_vring_write_descs(VhostShadowVirtqueue *svq, hwaddr *sg, + for (n = 0; n < num; n++) { + if (more_descs || (n + 1 < num)) { + descs[i].flags = flags | cpu_to_le16(VRING_DESC_F_NEXT); ++ descs[i].next = cpu_to_le16(svq->desc_next[i]); + } else { + descs[i].flags = flags; + } +@@ -144,10 +145,10 @@ static void vhost_vring_write_descs(VhostShadowVirtqueue *svq, hwaddr *sg, + descs[i].len = cpu_to_le32(iovec[n].iov_len); + + last = i; +- i = cpu_to_le16(descs[i].next); ++ i = cpu_to_le16(svq->desc_next[i]); + } + +- svq->free_head = le16_to_cpu(descs[last].next); ++ svq->free_head = le16_to_cpu(svq->desc_next[last]); + } + + static bool vhost_svq_add_split(VhostShadowVirtqueue *svq, +@@ -335,7 +336,6 @@ static void vhost_svq_disable_notification(VhostShadowVirtqueue *svq) + static VirtQueueElement *vhost_svq_get_buf(VhostShadowVirtqueue *svq, + uint32_t *len) + { +- vring_desc_t *descs = svq->vring.desc; + const vring_used_t *used = svq->vring.used; + vring_used_elem_t used_elem; + uint16_t last_used; +@@ -364,7 +364,7 @@ static VirtQueueElement *vhost_svq_get_buf(VhostShadowVirtqueue *svq, + return NULL; + } + +- descs[used_elem.id].next = svq->free_head; ++ svq->desc_next[used_elem.id] = svq->free_head; + svq->free_head = used_elem.id; + + *len = used_elem.len; +@@ -539,8 +539,9 @@ void vhost_svq_start(VhostShadowVirtqueue *svq, VirtIODevice *vdev, + svq->vring.used = qemu_memalign(qemu_real_host_page_size, device_size); + memset(svq->vring.used, 0, device_size); + svq->ring_id_maps = g_new0(VirtQueueElement *, svq->vring.num); ++ svq->desc_next = g_new0(uint16_t, svq->vring.num); + for (unsigned i = 0; i < svq->vring.num - 1; i++) { +- svq->vring.desc[i].next = cpu_to_le16(i + 1); ++ svq->desc_next[i] = cpu_to_le16(i + 1); + } + } + +@@ -573,6 +574,7 @@ void vhost_svq_stop(VhostShadowVirtqueue *svq) + virtqueue_detach_element(svq->vq, next_avail_elem, 0); + } + svq->vq = NULL; ++ g_free(svq->desc_next); + g_free(svq->ring_id_maps); + qemu_vfree(svq->vring.desc); + qemu_vfree(svq->vring.used); +diff --git a/hw/virtio/vhost-shadow-virtqueue.h b/hw/virtio/vhost-shadow-virtqueue.h +index e5e24c536d..c132c994e9 100644 +--- a/hw/virtio/vhost-shadow-virtqueue.h ++++ b/hw/virtio/vhost-shadow-virtqueue.h +@@ -53,6 +53,12 @@ typedef struct VhostShadowVirtqueue { + /* Next VirtQueue element that guest made available */ + VirtQueueElement *next_guest_avail_elem; + ++ /* ++ * Backup next field for each descriptor so we can recover securely, not ++ * needing to trust the device access. ++ */ ++ uint16_t *desc_next; ++ + /* Next head to expose to the device */ + uint16_t shadow_avail_idx; + +-- +2.27.0 + diff --git a/vhost-Track-number-of-descs-in-SVQDescState.patch b/vhost-Track-number-of-descs-in-SVQDescState.patch new file mode 100644 index 00000000..1c247898 --- /dev/null +++ b/vhost-Track-number-of-descs-in-SVQDescState.patch @@ -0,0 +1,62 @@ +From d76e2c5a5213d51dd8c48315e26c277423ade99f Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= +Date: Wed, 20 Jul 2022 08:59:35 +0200 +Subject: [PATCH] vhost: Track number of descs in SVQDescState +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +A guest's buffer continuos on GPA may need multiple descriptors on +qemu's VA, so SVQ should track its length sepparatedly. + +Signed-off-by: Eugenio Pérez +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Jason Wang +Signed-off-by: fangyi +--- + hw/virtio/vhost-shadow-virtqueue.c | 4 ++-- + hw/virtio/vhost-shadow-virtqueue.h | 6 ++++++ + 2 files changed, 8 insertions(+), 2 deletions(-) + +diff --git a/hw/virtio/vhost-shadow-virtqueue.c b/hw/virtio/vhost-shadow-virtqueue.c +index 5ddc04e9d6..c10c74b91f 100644 +--- a/hw/virtio/vhost-shadow-virtqueue.c ++++ b/hw/virtio/vhost-shadow-virtqueue.c +@@ -256,6 +256,7 @@ static int vhost_svq_add(VhostShadowVirtqueue *svq, const struct iovec *out_sg, + } + + svq->desc_state[qemu_head].elem = elem; ++ svq->desc_state[qemu_head].ndescs = ndescs; + vhost_svq_kick(svq); + return 0; + } +@@ -417,8 +418,7 @@ static VirtQueueElement *vhost_svq_get_buf(VhostShadowVirtqueue *svq, + return NULL; + } + +- num = svq->desc_state[used_elem.id].elem->in_num + +- svq->desc_state[used_elem.id].elem->out_num; ++ num = svq->desc_state[used_elem.id].ndescs; + last_used_chain = vhost_svq_last_desc_of_chain(svq, num, used_elem.id); + svq->desc_next[last_used_chain] = svq->free_head; + svq->free_head = used_elem.id; +diff --git a/hw/virtio/vhost-shadow-virtqueue.h b/hw/virtio/vhost-shadow-virtqueue.h +index d646c35054..5c7e7cbab6 100644 +--- a/hw/virtio/vhost-shadow-virtqueue.h ++++ b/hw/virtio/vhost-shadow-virtqueue.h +@@ -17,6 +17,12 @@ + + typedef struct SVQDescState { + VirtQueueElement *elem; ++ ++ /* ++ * Number of descriptors exposed to the device. May or may not match ++ * guest's ++ */ ++ unsigned int ndescs; + } SVQDescState; + + /* Shadow virtqueue to relay notifications */ +-- +2.27.0 + diff --git a/vhost-add-support-for-configure-interrupt-new.patch b/vhost-add-support-for-configure-interrupt-new.patch new file mode 100644 index 00000000..0be96f27 --- /dev/null +++ b/vhost-add-support-for-configure-interrupt-new.patch @@ -0,0 +1,172 @@ +From 59957a4caee59e0c82b8d02ed1c1820db523ae64 Mon Sep 17 00:00:00 2001 +From: Cindy Lu +Date: Thu, 22 Dec 2022 15:04:48 +0800 +Subject: [PATCH] vhost: add support for configure interrupt + +Add functions to support configure interrupt. +The configure interrupt process will start in vhost_dev_start +and stop in vhost_dev_stop. + +Also add the functions to support vhost_config_pending and +vhost_config_mask. + +Signed-off-by: Cindy Lu +Message-Id: <20221222070451.936503-8-lulu@redhat.com> +Acked-by: Jason Wang +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Signed-off-by: fangyi +--- + hw/virtio/vhost.c | 78 ++++++++++++++++++++++++++++++++++++++- + include/hw/virtio/vhost.h | 4 ++ + 2 files changed, 81 insertions(+), 1 deletion(-) + +diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c +index 19ea9aef69..490c97424b 100644 +--- a/hw/virtio/vhost.c ++++ b/hw/virtio/vhost.c +@@ -1627,7 +1627,68 @@ void vhost_virtqueue_mask(struct vhost_dev *hdev, VirtIODevice *vdev, int n, + file.index = hdev->vhost_ops->vhost_get_vq_index(hdev, n); + r = hdev->vhost_ops->vhost_set_vring_call(hdev, &file); + if (r < 0) { +- VHOST_OPS_DEBUG(r, "vhost_set_vring_call failed"); ++ error_report("vhost_set_vring_call failed %d", -r); ++ } ++} ++ ++bool vhost_config_pending(struct vhost_dev *hdev) ++{ ++ assert(hdev->vhost_ops); ++ if ((hdev->started == false) || ++ (hdev->vhost_ops->vhost_set_config_call == NULL)) { ++ return false; ++ } ++ ++ EventNotifier *notifier = ++ &hdev->vqs[VHOST_QUEUE_NUM_CONFIG_INR].masked_config_notifier; ++ return event_notifier_test_and_clear(notifier); ++} ++ ++void vhost_config_mask(struct vhost_dev *hdev, VirtIODevice *vdev, bool mask) ++{ ++ int fd; ++ int r; ++ EventNotifier *notifier = ++ &hdev->vqs[VHOST_QUEUE_NUM_CONFIG_INR].masked_config_notifier; ++ EventNotifier *config_notifier = &vdev->config_notifier; ++ assert(hdev->vhost_ops); ++ ++ if ((hdev->started == false) || ++ (hdev->vhost_ops->vhost_set_config_call == NULL)) { ++ return; ++ } ++ if (mask) { ++ assert(vdev->use_guest_notifier_mask); ++ fd = event_notifier_get_fd(notifier); ++ } else { ++ fd = event_notifier_get_fd(config_notifier); ++ } ++ r = hdev->vhost_ops->vhost_set_config_call(hdev, fd); ++ if (r < 0) { ++ error_report("vhost_set_config_call failed %d", -r); ++ } ++} ++ ++static void vhost_stop_config_intr(struct vhost_dev *dev) ++{ ++ int fd = -1; ++ assert(dev->vhost_ops); ++ if (dev->vhost_ops->vhost_set_config_call) { ++ dev->vhost_ops->vhost_set_config_call(dev, fd); ++ } ++} ++ ++static void vhost_start_config_intr(struct vhost_dev *dev) ++{ ++ int r; ++ ++ assert(dev->vhost_ops); ++ int fd = event_notifier_get_fd(&dev->vdev->config_notifier); ++ if (dev->vhost_ops->vhost_set_config_call) { ++ r = dev->vhost_ops->vhost_set_config_call(dev, fd); ++ if (!r) { ++ event_notifier_set(&dev->vdev->config_notifier); ++ } + } + } + +@@ -1867,6 +1928,16 @@ int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev, bool vrings) + } + } + ++ r = event_notifier_init( ++ &hdev->vqs[VHOST_QUEUE_NUM_CONFIG_INR].masked_config_notifier, 0); ++ if (r < 0) { ++ return r; ++ } ++ event_notifier_test_and_clear( ++ &hdev->vqs[VHOST_QUEUE_NUM_CONFIG_INR].masked_config_notifier); ++ if (!vdev->use_guest_notifier_mask) { ++ vhost_config_mask(hdev, vdev, true); ++ } + if (hdev->log_enabled) { + uint64_t log_base; + +@@ -1905,6 +1976,7 @@ int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev, bool vrings) + vhost_device_iotlb_miss(hdev, vq->used_phys, true); + } + } ++ vhost_start_config_intr(hdev); + return 0; + fail_start: + if (vrings) { +@@ -1934,6 +2006,9 @@ void vhost_dev_stop(struct vhost_dev *hdev, VirtIODevice *vdev, bool vrings) + + /* should only be called after backend is connected */ + assert(hdev->vhost_ops); ++ event_notifier_test_and_clear( ++ &hdev->vqs[VHOST_QUEUE_NUM_CONFIG_INR].masked_config_notifier); ++ event_notifier_test_and_clear(&vdev->config_notifier); + + trace_vhost_dev_stop(hdev, vdev->name, vrings); + +@@ -1956,6 +2031,7 @@ void vhost_dev_stop(struct vhost_dev *hdev, VirtIODevice *vdev, bool vrings) + } + memory_listener_unregister(&hdev->iommu_listener); + } ++ vhost_stop_config_intr(hdev); + vhost_log_put(hdev, true); + hdev->started = false; + vdev->vhost_started = false; +diff --git a/include/hw/virtio/vhost.h b/include/hw/virtio/vhost.h +index 662e0f4370..420f93e5cd 100644 +--- a/include/hw/virtio/vhost.h ++++ b/include/hw/virtio/vhost.h +@@ -32,6 +32,7 @@ struct vhost_virtqueue { + unsigned long long used_phys; + unsigned used_size; + EventNotifier masked_notifier; ++ EventNotifier masked_config_notifier; + struct vhost_dev *dev; + }; + +@@ -40,6 +41,7 @@ typedef unsigned long vhost_log_chunk_t; + #define VHOST_LOG_BITS (8 * sizeof(vhost_log_chunk_t)) + #define VHOST_LOG_CHUNK (VHOST_LOG_PAGE * VHOST_LOG_BITS) + #define VHOST_INVALID_FEATURE_BIT (0xff) ++#define VHOST_QUEUE_NUM_CONFIG_INR 0 + + struct vhost_log { + unsigned long long size; +@@ -163,6 +165,8 @@ int vhost_dev_enable_notifiers(struct vhost_dev *hdev, VirtIODevice *vdev); + * Disable direct notifications to vhost device. + */ + void vhost_dev_disable_notifiers(struct vhost_dev *hdev, VirtIODevice *vdev); ++bool vhost_config_pending(struct vhost_dev *hdev); ++void vhost_config_mask(struct vhost_dev *hdev, VirtIODevice *vdev, bool mask); + + /** + * vhost_dev_start() - start the vhost device +-- +2.27.0 + diff --git a/vhost-add-support-for-configure-interrupt.patch b/vhost-add-support-for-configure-interrupt.patch new file mode 100644 index 00000000..d8916c37 --- /dev/null +++ b/vhost-add-support-for-configure-interrupt.patch @@ -0,0 +1,170 @@ +From 9823b7bb536cea50c9750320436511fd60b797cd Mon Sep 17 00:00:00 2001 +From: fangyi +Date: Thu, 16 Nov 2023 09:54:52 +0800 +Subject: [PATCH] vhost: add support for configure interrupt + +Add functions to support configure interrupt. +The configure interrupt process will start in vhost_dev_start +and stop in vhost_dev_stop. + +Also add the functions to support vhost_config_pending and +vhost_config_mask, for masked_config_notifier, we only +use the notifier saved in vq 0. + +Signed-off-by: Cindy Lu +Message-Id: <20211104164827.21911-8-lulu@redhat.com> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Signed-off-by: fangyi +--- + hw/virtio/vhost.c | 76 +++++++++++++++++++++++++++++++++++++++ + include/hw/virtio/vhost.h | 4 +++ + 2 files changed, 80 insertions(+) + +diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c +index 2d11e3c2f8..c3f375f276 100644 +--- a/hw/virtio/vhost.c ++++ b/hw/virtio/vhost.c +@@ -1588,6 +1588,67 @@ void vhost_virtqueue_mask(struct vhost_dev *hdev, VirtIODevice *vdev, int n, + } + } + ++bool vhost_config_pending(struct vhost_dev *hdev) ++{ ++ assert(hdev->vhost_ops); ++ if ((hdev->started == false) || ++ (hdev->vhost_ops->vhost_set_config_call == NULL)) { ++ return false; ++ } ++ ++ EventNotifier *notifier = ++ &hdev->vqs[VHOST_QUEUE_NUM_CONFIG_INR].masked_config_notifier; ++ return event_notifier_test_and_clear(notifier); ++} ++ ++void vhost_config_mask(struct vhost_dev *hdev, VirtIODevice *vdev, bool mask) ++{ ++ int fd; ++ int r; ++ EventNotifier *notifier = ++ &hdev->vqs[VHOST_QUEUE_NUM_CONFIG_INR].masked_config_notifier; ++ EventNotifier *config_notifier = &vdev->config_notifier; ++ assert(hdev->vhost_ops); ++ ++ if ((hdev->started == false) || ++ (hdev->vhost_ops->vhost_set_config_call == NULL)) { ++ return; ++ } ++ if (mask) { ++ assert(vdev->use_guest_notifier_mask); ++ fd = event_notifier_get_fd(notifier); ++ } else { ++ fd = event_notifier_get_fd(config_notifier); ++ } ++ r = hdev->vhost_ops->vhost_set_config_call(hdev, fd); ++ if (r < 0) { ++ VHOST_OPS_DEBUG("vhost_set_config_call failed"); ++ } ++} ++ ++static void vhost_stop_config_intr(struct vhost_dev *dev) ++{ ++ int fd = -1; ++ assert(dev->vhost_ops); ++ if (dev->vhost_ops->vhost_set_config_call) { ++ dev->vhost_ops->vhost_set_config_call(dev, fd); ++ } ++} ++ ++static void vhost_start_config_intr(struct vhost_dev *dev) ++{ ++ int r; ++ ++ assert(dev->vhost_ops); ++ int fd = event_notifier_get_fd(&dev->vdev->config_notifier); ++ if (dev->vhost_ops->vhost_set_config_call) { ++ r = dev->vhost_ops->vhost_set_config_call(dev, fd); ++ if (!r) { ++ event_notifier_set(&dev->vdev->config_notifier); ++ } ++ } ++} ++ + uint64_t vhost_get_features(struct vhost_dev *hdev, const int *feature_bits, + uint64_t features) + { +@@ -1800,6 +1861,16 @@ int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev) + } + } + ++ r = event_notifier_init( ++ &hdev->vqs[VHOST_QUEUE_NUM_CONFIG_INR].masked_config_notifier, 0); ++ if (r < 0) { ++ return r; ++ } ++ event_notifier_test_and_clear( ++ &hdev->vqs[VHOST_QUEUE_NUM_CONFIG_INR].masked_config_notifier); ++ if (!vdev->use_guest_notifier_mask) { ++ vhost_config_mask(hdev, vdev, true); ++ } + if (hdev->log_enabled) { + uint64_t log_base; + +@@ -1833,6 +1904,7 @@ int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev) + vhost_device_iotlb_miss(hdev, vq->used_phys, true); + } + } ++ vhost_start_config_intr(hdev); + return 0; + fail_log: + vhost_log_put(hdev, false); +@@ -1858,6 +1930,9 @@ void vhost_dev_stop(struct vhost_dev *hdev, VirtIODevice *vdev) + + /* should only be called after backend is connected */ + assert(hdev->vhost_ops); ++ event_notifier_test_and_clear( ++ &hdev->vqs[VHOST_QUEUE_NUM_CONFIG_INR].masked_config_notifier); ++ event_notifier_test_and_clear(&vdev->config_notifier); + + if (hdev->vhost_ops->vhost_dev_start) { + hdev->vhost_ops->vhost_dev_start(hdev, false); +@@ -1875,6 +1950,7 @@ void vhost_dev_stop(struct vhost_dev *hdev, VirtIODevice *vdev) + } + memory_listener_unregister(&hdev->iommu_listener); + } ++ vhost_stop_config_intr(hdev); + vhost_log_put(hdev, true); + hdev->started = false; + hdev->vdev = NULL; +diff --git a/include/hw/virtio/vhost.h b/include/hw/virtio/vhost.h +index 86f36f0106..2ae5c3bfd8 100644 +--- a/include/hw/virtio/vhost.h ++++ b/include/hw/virtio/vhost.h +@@ -29,6 +29,7 @@ struct vhost_virtqueue { + unsigned long long used_phys; + unsigned used_size; + EventNotifier masked_notifier; ++ EventNotifier masked_config_notifier; + struct vhost_dev *dev; + }; + +@@ -37,6 +38,7 @@ typedef unsigned long vhost_log_chunk_t; + #define VHOST_LOG_BITS (8 * sizeof(vhost_log_chunk_t)) + #define VHOST_LOG_CHUNK (VHOST_LOG_PAGE * VHOST_LOG_BITS) + #define VHOST_INVALID_FEATURE_BIT (0xff) ++#define VHOST_QUEUE_NUM_CONFIG_INR 0 + + struct vhost_log { + unsigned long long size; +@@ -116,6 +118,8 @@ int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev); + void vhost_dev_stop(struct vhost_dev *hdev, VirtIODevice *vdev); + int vhost_dev_enable_notifiers(struct vhost_dev *hdev, VirtIODevice *vdev); + void vhost_dev_disable_notifiers(struct vhost_dev *hdev, VirtIODevice *vdev); ++bool vhost_config_pending(struct vhost_dev *hdev); ++void vhost_config_mask(struct vhost_dev *hdev, VirtIODevice *vdev, bool mask); + + /* Test and clear masked event pending status. + * Should be called after unmask to avoid losing events. +-- +2.27.0 + diff --git a/vhost-add-vhost_svq_poll.patch b/vhost-add-vhost_svq_poll.patch new file mode 100644 index 00000000..90b430ab --- /dev/null +++ b/vhost-add-vhost_svq_poll.patch @@ -0,0 +1,73 @@ +From 65869116f29f0c92a394af2308c154c855938923 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= +Date: Wed, 20 Jul 2022 08:59:38 +0200 +Subject: [PATCH] vhost: add vhost_svq_poll +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +It allows the Shadow Control VirtQueue to wait for the device to use the +available buffers. + +Signed-off-by: Eugenio Pérez +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Jason Wang +Signed-off-by: fangyi +--- + hw/virtio/vhost-shadow-virtqueue.c | 27 +++++++++++++++++++++++++++ + hw/virtio/vhost-shadow-virtqueue.h | 1 + + 2 files changed, 28 insertions(+) + +diff --git a/hw/virtio/vhost-shadow-virtqueue.c b/hw/virtio/vhost-shadow-virtqueue.c +index 5a85365478..d2676b94e0 100644 +--- a/hw/virtio/vhost-shadow-virtqueue.c ++++ b/hw/virtio/vhost-shadow-virtqueue.c +@@ -484,6 +484,33 @@ static void vhost_svq_flush(VhostShadowVirtqueue *svq, + } while (!vhost_svq_enable_notification(svq)); + } + ++/** ++ * Poll the SVQ for one device used buffer. ++ * ++ * This function race with main event loop SVQ polling, so extra ++ * synchronization is needed. ++ * ++ * Return the length written by the device. ++ */ ++size_t vhost_svq_poll(VhostShadowVirtqueue *svq) ++{ ++ int64_t start_us = g_get_monotonic_time(); ++ do { ++ uint32_t len; ++ VirtQueueElement *elem = vhost_svq_get_buf(svq, &len); ++ if (elem) { ++ return len; ++ } ++ ++ if (unlikely(g_get_monotonic_time() - start_us > 10e6)) { ++ return 0; ++ } ++ ++ /* Make sure we read new used_idx */ ++ smp_rmb(); ++ } while (true); ++} ++ + /** + * Forward used buffers. + * +diff --git a/hw/virtio/vhost-shadow-virtqueue.h b/hw/virtio/vhost-shadow-virtqueue.h +index dd78f4bec2..cf442f7dea 100644 +--- a/hw/virtio/vhost-shadow-virtqueue.h ++++ b/hw/virtio/vhost-shadow-virtqueue.h +@@ -89,6 +89,7 @@ void vhost_svq_push_elem(VhostShadowVirtqueue *svq, + int vhost_svq_add(VhostShadowVirtqueue *svq, const struct iovec *out_sg, + size_t out_num, const struct iovec *in_sg, size_t in_num, + VirtQueueElement *elem); ++size_t vhost_svq_poll(VhostShadowVirtqueue *svq); + + void vhost_svq_set_svq_kick_fd(VhostShadowVirtqueue *svq, int svq_kick_fd); + void vhost_svq_set_svq_call_fd(VhostShadowVirtqueue *svq, int call_fd); +-- +2.27.0 + diff --git a/vhost-add-vhost_svq_push_elem.patch b/vhost-add-vhost_svq_push_elem.patch new file mode 100644 index 00000000..395d975a --- /dev/null +++ b/vhost-add-vhost_svq_push_elem.patch @@ -0,0 +1,64 @@ +From ac243c5186493f41c9ff0d60558dabb651c56983 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= +Date: Wed, 20 Jul 2022 08:59:36 +0200 +Subject: [PATCH] vhost: add vhost_svq_push_elem +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This function allows external SVQ users to return guest's available +buffers. + +Signed-off-by: Eugenio Pérez +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Jason Wang +Signed-off-by: fangyi +--- + hw/virtio/vhost-shadow-virtqueue.c | 16 ++++++++++++++++ + hw/virtio/vhost-shadow-virtqueue.h | 3 +++ + 2 files changed, 19 insertions(+) + +diff --git a/hw/virtio/vhost-shadow-virtqueue.c b/hw/virtio/vhost-shadow-virtqueue.c +index c10c74b91f..3b5d3bd3f3 100644 +--- a/hw/virtio/vhost-shadow-virtqueue.c ++++ b/hw/virtio/vhost-shadow-virtqueue.c +@@ -427,6 +427,22 @@ static VirtQueueElement *vhost_svq_get_buf(VhostShadowVirtqueue *svq, + return g_steal_pointer(&svq->desc_state[used_elem.id].elem); + } + ++/** ++ * Push an element to SVQ, returning it to the guest. ++ */ ++void vhost_svq_push_elem(VhostShadowVirtqueue *svq, ++ const VirtQueueElement *elem, uint32_t len) ++{ ++ virtqueue_push(svq->vq, elem, len); ++ if (svq->next_guest_avail_elem) { ++ /* ++ * Avail ring was full when vhost_svq_flush was called, so it's a ++ * good moment to make more descriptors available if possible. ++ */ ++ vhost_handle_guest_kick(svq); ++ } ++} ++ + static void vhost_svq_flush(VhostShadowVirtqueue *svq, + bool check_for_avail_queue) + { +diff --git a/hw/virtio/vhost-shadow-virtqueue.h b/hw/virtio/vhost-shadow-virtqueue.h +index 5c7e7cbab6..d9fc1f1799 100644 +--- a/hw/virtio/vhost-shadow-virtqueue.h ++++ b/hw/virtio/vhost-shadow-virtqueue.h +@@ -84,6 +84,9 @@ typedef struct VhostShadowVirtqueue { + + bool vhost_svq_valid_features(uint64_t features, Error **errp); + ++void vhost_svq_push_elem(VhostShadowVirtqueue *svq, ++ const VirtQueueElement *elem, uint32_t len); ++ + void vhost_svq_set_svq_kick_fd(VhostShadowVirtqueue *svq, int svq_kick_fd); + void vhost_svq_set_svq_call_fd(VhostShadowVirtqueue *svq, int call_fd); + void vhost_svq_get_vring_addr(const VhostShadowVirtqueue *svq, +-- +2.27.0 + diff --git a/vhost-allocate-SVQ-device-file-descriptors-at-device.patch b/vhost-allocate-SVQ-device-file-descriptors-at-device.patch new file mode 100644 index 00000000..5b85e729 --- /dev/null +++ b/vhost-allocate-SVQ-device-file-descriptors-at-device.patch @@ -0,0 +1,162 @@ +From 539c46ecb41417007840c750d364b5332cbdc5b5 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= +Date: Thu, 15 Dec 2022 12:31:35 +0100 +Subject: [PATCH] vhost: allocate SVQ device file descriptors at device start +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The next patches will start control SVQ if possible. However, we don't +know if that will be possible at qemu boot anymore. + +Delay device file descriptors until we know it at device start. This +will avoid to create them if the device does not support SVQ. + +Signed-off-by: Eugenio Pérez +Acked-by: Jason Wang +Message-Id: <20221215113144.322011-4-eperezma@redhat.com> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Signed-off-by: fangyi +--- + hw/virtio/vhost-shadow-virtqueue.c | 31 ++------------------------ + hw/virtio/vhost-vdpa.c | 35 ++++++++++++++++++++++++------ + 2 files changed, 30 insertions(+), 36 deletions(-) + +diff --git a/hw/virtio/vhost-shadow-virtqueue.c b/hw/virtio/vhost-shadow-virtqueue.c +index bc12bb42f3..47e831667c 100644 +--- a/hw/virtio/vhost-shadow-virtqueue.c ++++ b/hw/virtio/vhost-shadow-virtqueue.c +@@ -692,43 +692,18 @@ void vhost_svq_stop(VhostShadowVirtqueue *svq) + * @iova_tree: Tree to perform descriptors translations + * @ops: SVQ owner callbacks + * @ops_opaque: ops opaque pointer +- * +- * Returns the new virtqueue or NULL. +- * +- * In case of error, reason is reported through error_report. + */ + VhostShadowVirtqueue *vhost_svq_new(VhostIOVATree *iova_tree, + const VhostShadowVirtqueueOps *ops, + void *ops_opaque) + { +- g_autofree VhostShadowVirtqueue *svq = g_new0(VhostShadowVirtqueue, 1); +- int r; +- +- r = event_notifier_init(&svq->hdev_kick, 0); +- if (r != 0) { +- error_report("Couldn't create kick event notifier: %s (%d)", +- g_strerror(errno), errno); +- goto err_init_hdev_kick; +- } +- +- r = event_notifier_init(&svq->hdev_call, 0); +- if (r != 0) { +- error_report("Couldn't create call event notifier: %s (%d)", +- g_strerror(errno), errno); +- goto err_init_hdev_call; +- } ++ VhostShadowVirtqueue *svq = g_new0(VhostShadowVirtqueue, 1); + + event_notifier_init_fd(&svq->svq_kick, VHOST_FILE_UNBIND); + svq->iova_tree = iova_tree; + svq->ops = ops; + svq->ops_opaque = ops_opaque; +- return g_steal_pointer(&svq); +- +-err_init_hdev_call: +- event_notifier_cleanup(&svq->hdev_kick); +- +-err_init_hdev_kick: +- return NULL; ++ return svq; + } + + /** +@@ -740,7 +715,5 @@ void vhost_svq_free(gpointer pvq) + { + VhostShadowVirtqueue *vq = pvq; + vhost_svq_stop(vq); +- event_notifier_cleanup(&vq->hdev_kick); +- event_notifier_cleanup(&vq->hdev_call); + g_free(vq); + } +diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c +index 08f92bf781..23e715b05c 100644 +--- a/hw/virtio/vhost-vdpa.c ++++ b/hw/virtio/vhost-vdpa.c +@@ -430,15 +430,11 @@ static int vhost_vdpa_init_svq(struct vhost_dev *hdev, struct vhost_vdpa *v, + + shadow_vqs = g_ptr_array_new_full(hdev->nvqs, vhost_svq_free); + for (unsigned n = 0; n < hdev->nvqs; ++n) { +- g_autoptr(VhostShadowVirtqueue) svq; ++ VhostShadowVirtqueue *svq; + + svq = vhost_svq_new(v->iova_tree, v->shadow_vq_ops, + v->shadow_vq_ops_opaque); +- if (unlikely(!svq)) { +- error_setg(errp, "Cannot create svq %u", n); +- return -1; +- } +- g_ptr_array_add(shadow_vqs, g_steal_pointer(&svq)); ++ g_ptr_array_add(shadow_vqs, svq); + } + + v->shadow_vqs = g_steal_pointer(&shadow_vqs); +@@ -866,11 +862,23 @@ static int vhost_vdpa_svq_set_fds(struct vhost_dev *dev, + const EventNotifier *event_notifier = &svq->hdev_kick; + int r; + ++ r = event_notifier_init(&svq->hdev_kick, 0); ++ if (r != 0) { ++ error_setg_errno(errp, -r, "Couldn't create kick event notifier"); ++ goto err_init_hdev_kick; ++ } ++ ++ r = event_notifier_init(&svq->hdev_call, 0); ++ if (r != 0) { ++ error_setg_errno(errp, -r, "Couldn't create call event notifier"); ++ goto err_init_hdev_call; ++ } ++ + file.fd = event_notifier_get_fd(event_notifier); + r = vhost_vdpa_set_vring_dev_kick(dev, &file); + if (unlikely(r != 0)) { + error_setg_errno(errp, -r, "Can't set device kick fd"); +- return r; ++ goto err_init_set_dev_fd; + } + + event_notifier = &svq->hdev_call; +@@ -878,8 +886,18 @@ static int vhost_vdpa_svq_set_fds(struct vhost_dev *dev, + r = vhost_vdpa_set_vring_dev_call(dev, &file); + if (unlikely(r != 0)) { + error_setg_errno(errp, -r, "Can't set device call fd"); ++ goto err_init_set_dev_fd; + } + ++ return 0; ++ ++err_init_set_dev_fd: ++ event_notifier_set_handler(&svq->hdev_call, NULL); ++ ++err_init_hdev_call: ++ event_notifier_cleanup(&svq->hdev_kick); ++ ++err_init_hdev_kick: + return r; + } + +@@ -1091,6 +1109,9 @@ static void vhost_vdpa_svqs_stop(struct vhost_dev *dev) + for (unsigned i = 0; i < v->shadow_vqs->len; ++i) { + VhostShadowVirtqueue *svq = g_ptr_array_index(v->shadow_vqs, i); + vhost_vdpa_svq_unmap_rings(dev, svq); ++ ++ event_notifier_cleanup(&svq->hdev_kick); ++ event_notifier_cleanup(&svq->hdev_call); + } + } + +-- +2.27.0 + diff --git a/vhost-enable-vrings-in-vhost_dev_start-for-vhost-use.patch b/vhost-enable-vrings-in-vhost_dev_start-for-vhost-use.patch new file mode 100644 index 00000000..51fdba43 --- /dev/null +++ b/vhost-enable-vrings-in-vhost_dev_start-for-vhost-use.patch @@ -0,0 +1,453 @@ +From f0586baaa57c4042135b6d8f4d940da8a99e3737 Mon Sep 17 00:00:00 2001 +From: Stefano Garzarella +Date: Wed, 30 Nov 2022 11:24:36 +0000 +Subject: [PATCH] vhost: enable vrings in vhost_dev_start() for vhost-user + devices +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Commit 02b61f38d3 ("hw/virtio: incorporate backend features in features") +properly negotiates VHOST_USER_F_PROTOCOL_FEATURES with the vhost-user +backend, but we forgot to enable vrings as specified in +docs/interop/vhost-user.rst: + + If ``VHOST_USER_F_PROTOCOL_FEATURES`` has not been negotiated, the + ring starts directly in the enabled state. + + If ``VHOST_USER_F_PROTOCOL_FEATURES`` has been negotiated, the ring is + initialized in a disabled state and is enabled by + ``VHOST_USER_SET_VRING_ENABLE`` with parameter 1. + +Some vhost-user front-ends already did this by calling +vhost_ops.vhost_set_vring_enable() directly: +- backends/cryptodev-vhost.c +- hw/net/virtio-net.c +- hw/virtio/vhost-user-gpio.c + +But most didn't do that, so we would leave the vrings disabled and some +backends would not work. We observed this issue with the rust version of +virtiofsd [1], which uses the event loop [2] provided by the +vhost-user-backend crate where requests are not processed if vring is +not enabled. + +Let's fix this issue by enabling the vrings in vhost_dev_start() for +vhost-user front-ends that don't already do this directly. Same thing +also in vhost_dev_stop() where we disable vrings. + +[1] https://gitlab.com/virtio-fs/virtiofsd +[2] https://github.com/rust-vmm/vhost/blob/240fc2966/crates/vhost-user-backend/src/event_loop.rs#L217 + +Fixes: 02b61f38d3 ("hw/virtio: incorporate backend features in features") +Reported-by: German Maglione +Tested-by: German Maglione +Signed-off-by: Stefano Garzarella +Acked-by: Raphael Norwitz +Message-Id: <20221123131630.52020-1-sgarzare@redhat.com> +Signed-off-by: Alex Bennée +Reviewed-by: Michael S. Tsirkin +Message-Id: <20221130112439.2527228-3-alex.bennee@linaro.org> +Signed-off-by: Michael S. Tsirkin +Signed-off-by: fangyi +--- + backends/cryptodev-vhost.c | 4 ++-- + backends/vhost-user.c | 4 ++-- + hw/block/vhost-user-blk.c | 4 ++-- + hw/net/vhost_net.c | 6 ++--- + hw/scsi/vhost-scsi-common.c | 4 ++-- + hw/virtio/trace-events | 4 ++-- + hw/virtio/vdpa-dev.c | 4 ++-- + hw/virtio/vhost-user-fs.c | 4 ++-- + hw/virtio/vhost-user-i2c.c | 4 ++-- + hw/virtio/vhost-user-rng.c | 4 ++-- + hw/virtio/vhost-vsock-common.c | 4 ++-- + hw/virtio/vhost.c | 44 ++++++++++++++++++++++++++++++---- + include/hw/virtio/vhost.h | 9 +++++-- + 13 files changed, 69 insertions(+), 30 deletions(-) + +diff --git a/backends/cryptodev-vhost.c b/backends/cryptodev-vhost.c +index bc13e466b4..572f87b3be 100644 +--- a/backends/cryptodev-vhost.c ++++ b/backends/cryptodev-vhost.c +@@ -94,7 +94,7 @@ cryptodev_vhost_start_one(CryptoDevBackendVhost *crypto, + goto fail_notifiers; + } + +- r = vhost_dev_start(&crypto->dev, dev); ++ r = vhost_dev_start(&crypto->dev, dev, false); + if (r < 0) { + goto fail_start; + } +@@ -111,7 +111,7 @@ static void + cryptodev_vhost_stop_one(CryptoDevBackendVhost *crypto, + VirtIODevice *dev) + { +- vhost_dev_stop(&crypto->dev, dev); ++ vhost_dev_stop(&crypto->dev, dev, false); + vhost_dev_disable_notifiers(&crypto->dev, dev); + } + +diff --git a/backends/vhost-user.c b/backends/vhost-user.c +index 10b39992d2..6632e2fe6f 100644 +--- a/backends/vhost-user.c ++++ b/backends/vhost-user.c +@@ -85,7 +85,7 @@ vhost_user_backend_start(VhostUserBackend *b) + } + + b->dev.acked_features = b->vdev->guest_features; +- ret = vhost_dev_start(&b->dev, b->vdev); ++ ret = vhost_dev_start(&b->dev, b->vdev, true); + if (ret < 0) { + error_report("Error start vhost dev"); + goto err_guest_notifiers; +@@ -120,7 +120,7 @@ vhost_user_backend_stop(VhostUserBackend *b) + return; + } + +- vhost_dev_stop(&b->dev, b->vdev); ++ vhost_dev_stop(&b->dev, b->vdev, true); + + if (k->set_guest_notifiers) { + ret = k->set_guest_notifiers(qbus->parent, +diff --git a/hw/block/vhost-user-blk.c b/hw/block/vhost-user-blk.c +index 9bf18434c2..eddc5588fa 100644 +--- a/hw/block/vhost-user-blk.c ++++ b/hw/block/vhost-user-blk.c +@@ -167,7 +167,7 @@ static int vhost_user_blk_start(VirtIODevice *vdev, Error **errp) + goto err_guest_notifiers; + } + +- ret = vhost_dev_start(&s->dev, vdev); ++ ret = vhost_dev_start(&s->dev, vdev, true); + if (ret < 0) { + error_setg_errno(errp, -ret, "Error starting vhost"); + goto err_guest_notifiers; +@@ -207,7 +207,7 @@ static void vhost_user_blk_stop(VirtIODevice *vdev) + return; + } + +- vhost_dev_stop(&s->dev, vdev); ++ vhost_dev_stop(&s->dev, vdev, true); + + ret = k->set_guest_notifiers(qbus->parent, s->dev.nvqs, false); + if (ret < 0) { +diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c +index f709c060b6..c950d7e2e8 100644 +--- a/hw/net/vhost_net.c ++++ b/hw/net/vhost_net.c +@@ -319,7 +319,7 @@ static int vhost_net_start_one(struct vhost_net *net, + goto fail_notifiers; + } + +- r = vhost_dev_start(&net->dev, dev); ++ r = vhost_dev_start(&net->dev, dev, false); + if (r < 0) { + goto fail_start; + } +@@ -368,7 +368,7 @@ fail: + if (net->nc->info->poll) { + net->nc->info->poll(net->nc, true); + } +- vhost_dev_stop(&net->dev, dev); ++ vhost_dev_stop(&net->dev, dev, false); + fail_start: + vhost_dev_disable_notifiers(&net->dev, dev); + fail_notifiers: +@@ -389,7 +389,7 @@ static void vhost_net_stop_one(struct vhost_net *net, + if (net->nc->info->poll) { + net->nc->info->poll(net->nc, true); + } +- vhost_dev_stop(&net->dev, dev); ++ vhost_dev_stop(&net->dev, dev, false); + if (net->nc->info->stop) { + net->nc->info->stop(net->nc); + } +diff --git a/hw/scsi/vhost-scsi-common.c b/hw/scsi/vhost-scsi-common.c +index 767f827e55..18ea5dcfa1 100644 +--- a/hw/scsi/vhost-scsi-common.c ++++ b/hw/scsi/vhost-scsi-common.c +@@ -68,7 +68,7 @@ int vhost_scsi_common_start(VHostSCSICommon *vsc) + goto err_guest_notifiers; + } + +- ret = vhost_dev_start(&vsc->dev, vdev); ++ ret = vhost_dev_start(&vsc->dev, vdev, true); + if (ret < 0) { + error_report("Error start vhost dev"); + goto err_guest_notifiers; +@@ -101,7 +101,7 @@ void vhost_scsi_common_stop(VHostSCSICommon *vsc) + VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus); + int ret = 0; + +- vhost_dev_stop(&vsc->dev, vdev); ++ vhost_dev_stop(&vsc->dev, vdev, true); + + if (k->set_guest_notifiers) { + ret = k->set_guest_notifiers(qbus->parent, vsc->dev.nvqs, false); +diff --git a/hw/virtio/trace-events b/hw/virtio/trace-events +index b8a33b2a83..35d4c00e59 100644 +--- a/hw/virtio/trace-events ++++ b/hw/virtio/trace-events +@@ -9,8 +9,8 @@ vhost_section(const char *name) "%s" + vhost_reject_section(const char *name, int d) "%s:%d" + vhost_iotlb_miss(void *dev, int step) "%p step %d" + vhost_dev_cleanup(void *dev) "%p" +-vhost_dev_start(void *dev, const char *name) "%p:%s" +-vhost_dev_stop(void *dev, const char *name) "%p:%s" ++vhost_dev_start(void *dev, const char *name, bool vrings) "%p:%s vrings:%d" ++vhost_dev_stop(void *dev, const char *name, bool vrings) "%p:%s vrings:%d" + + + # vhost-user.c +diff --git a/hw/virtio/vdpa-dev.c b/hw/virtio/vdpa-dev.c +index 1840f0e450..465b08c0e3 100644 +--- a/hw/virtio/vdpa-dev.c ++++ b/hw/virtio/vdpa-dev.c +@@ -242,7 +242,7 @@ static int vhost_vdpa_device_start(VirtIODevice *vdev, Error **errp) + + s->dev.acked_features = vdev->guest_features; + +- ret = vhost_dev_start(&s->dev, vdev); ++ ret = vhost_dev_start(&s->dev, vdev, false); + if (ret < 0) { + error_setg_errno(errp, -ret, "Error starting vhost"); + goto err_guest_notifiers; +@@ -283,7 +283,7 @@ static void vhost_vdpa_device_stop(VirtIODevice *vdev) + return; + } + +- vhost_dev_stop(&s->dev, vdev); ++ vhost_dev_stop(&s->dev, vdev, false); + + ret = k->set_guest_notifiers(qbus->parent, s->dev.nvqs, false); + if (ret < 0) { +diff --git a/hw/virtio/vhost-user-fs.c b/hw/virtio/vhost-user-fs.c +index 392b7d3aa1..c2739557f2 100644 +--- a/hw/virtio/vhost-user-fs.c ++++ b/hw/virtio/vhost-user-fs.c +@@ -74,7 +74,7 @@ static void vuf_start(VirtIODevice *vdev) + } + + fs->vhost_dev.acked_features = vdev->guest_features; +- ret = vhost_dev_start(&fs->vhost_dev, vdev); ++ ret = vhost_dev_start(&fs->vhost_dev, vdev, true); + if (ret < 0) { + error_report("Error starting vhost: %d", -ret); + goto err_guest_notifiers; +@@ -108,7 +108,7 @@ static void vuf_stop(VirtIODevice *vdev) + return; + } + +- vhost_dev_stop(&fs->vhost_dev, vdev); ++ vhost_dev_stop(&fs->vhost_dev, vdev, true); + + ret = k->set_guest_notifiers(qbus->parent, fs->vhost_dev.nvqs, false); + if (ret < 0) { +diff --git a/hw/virtio/vhost-user-i2c.c b/hw/virtio/vhost-user-i2c.c +index d172632bb0..dcaf471115 100644 +--- a/hw/virtio/vhost-user-i2c.c ++++ b/hw/virtio/vhost-user-i2c.c +@@ -45,7 +45,7 @@ static void vu_i2c_start(VirtIODevice *vdev) + + i2c->vhost_dev.acked_features = vdev->guest_features; + +- ret = vhost_dev_start(&i2c->vhost_dev, vdev); ++ ret = vhost_dev_start(&i2c->vhost_dev, vdev, true); + if (ret < 0) { + error_report("Error starting vhost-user-i2c: %d", -ret); + goto err_guest_notifiers; +@@ -79,7 +79,7 @@ static void vu_i2c_stop(VirtIODevice *vdev) + return; + } + +- vhost_dev_stop(&i2c->vhost_dev, vdev); ++ vhost_dev_stop(&i2c->vhost_dev, vdev, true); + + ret = k->set_guest_notifiers(qbus->parent, i2c->vhost_dev.nvqs, false); + if (ret < 0) { +diff --git a/hw/virtio/vhost-user-rng.c b/hw/virtio/vhost-user-rng.c +index 543f3e3cef..f25b7cf624 100644 +--- a/hw/virtio/vhost-user-rng.c ++++ b/hw/virtio/vhost-user-rng.c +@@ -42,7 +42,7 @@ static void vu_rng_start(VirtIODevice *vdev) + } + + rng->vhost_dev.acked_features = vdev->guest_features; +- ret = vhost_dev_start(&rng->vhost_dev, vdev); ++ ret = vhost_dev_start(&rng->vhost_dev, vdev, true); + if (ret < 0) { + error_report("Error starting vhost-user-rng: %d", -ret); + goto err_guest_notifiers; +@@ -76,7 +76,7 @@ static void vu_rng_stop(VirtIODevice *vdev) + return; + } + +- vhost_dev_stop(&rng->vhost_dev, vdev); ++ vhost_dev_stop(&rng->vhost_dev, vdev, true); + + ret = k->set_guest_notifiers(qbus->parent, rng->vhost_dev.nvqs, false); + if (ret < 0) { +diff --git a/hw/virtio/vhost-vsock-common.c b/hw/virtio/vhost-vsock-common.c +index cd45aaf28e..42e4db4712 100644 +--- a/hw/virtio/vhost-vsock-common.c ++++ b/hw/virtio/vhost-vsock-common.c +@@ -68,7 +68,7 @@ int vhost_vsock_common_start(VirtIODevice *vdev) + } + + vvc->vhost_dev.acked_features = vdev->guest_features; +- ret = vhost_dev_start(&vvc->vhost_dev, vdev); ++ ret = vhost_dev_start(&vvc->vhost_dev, vdev, true); + if (ret < 0) { + error_report("Error starting vhost: %d", -ret); + goto err_guest_notifiers; +@@ -103,7 +103,7 @@ void vhost_vsock_common_stop(VirtIODevice *vdev) + return; + } + +- vhost_dev_stop(&vvc->vhost_dev, vdev); ++ vhost_dev_stop(&vvc->vhost_dev, vdev, true); + + ret = k->set_guest_notifiers(qbus->parent, vvc->vhost_dev.nvqs, false); + if (ret < 0) { +diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c +index 86c727d2ab..22ec9e1ef7 100644 +--- a/hw/virtio/vhost.c ++++ b/hw/virtio/vhost.c +@@ -1760,15 +1760,36 @@ int vhost_dev_get_inflight(struct vhost_dev *dev, uint16_t queue_size, + return 0; + } + ++static int vhost_dev_set_vring_enable(struct vhost_dev *hdev, int enable) ++{ ++ if (!hdev->vhost_ops->vhost_set_vring_enable) { ++ return 0; ++ } ++ ++ /* ++ * For vhost-user devices, if VHOST_USER_F_PROTOCOL_FEATURES has not ++ * been negotiated, the rings start directly in the enabled state, and ++ * .vhost_set_vring_enable callback will fail since ++ * VHOST_USER_SET_VRING_ENABLE is not supported. ++ */ ++ if (hdev->vhost_ops->backend_type == VHOST_BACKEND_TYPE_USER && ++ !virtio_has_feature(hdev->backend_features, ++ VHOST_USER_F_PROTOCOL_FEATURES)) { ++ return 0; ++ } ++ ++ return hdev->vhost_ops->vhost_set_vring_enable(hdev, enable); ++} ++ + /* Host notifiers must be enabled at this point. */ +-int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev) ++int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev, bool vrings) + { + int i, r; + + /* should only be called after backend is connected */ + assert(hdev->vhost_ops); + +- trace_vhost_dev_start(hdev, vdev->name); ++ trace_vhost_dev_start(hdev, vdev->name, vrings); + + vdev->vhost_started = true; + hdev->started = true; +@@ -1813,10 +1834,16 @@ int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev) + goto fail_log; + } + } ++ if (vrings) { ++ r = vhost_dev_set_vring_enable(hdev, true); ++ if (r) { ++ goto fail_log; ++ } ++ } + if (hdev->vhost_ops->vhost_dev_start) { + r = hdev->vhost_ops->vhost_dev_start(hdev, true); + if (r) { +- goto fail_log; ++ goto fail_start; + } + } + if (vhost_dev_has_iommu(hdev) && +@@ -1831,6 +1858,10 @@ int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev) + } + } + return 0; ++fail_start: ++ if (vrings) { ++ vhost_dev_set_vring_enable(hdev, false); ++ } + fail_log: + vhost_log_put(hdev, false); + fail_vq: +@@ -1849,18 +1880,21 @@ fail_features: + } + + /* Host notifiers must be enabled at this point. */ +-void vhost_dev_stop(struct vhost_dev *hdev, VirtIODevice *vdev) ++void vhost_dev_stop(struct vhost_dev *hdev, VirtIODevice *vdev, bool vrings) + { + int i; + + /* should only be called after backend is connected */ + assert(hdev->vhost_ops); + +- trace_vhost_dev_stop(hdev, vdev->name); ++ trace_vhost_dev_stop(hdev, vdev->name, vrings); + + if (hdev->vhost_ops->vhost_dev_start) { + hdev->vhost_ops->vhost_dev_start(hdev, false); + } ++ if (vrings) { ++ vhost_dev_set_vring_enable(hdev, false); ++ } + for (i = 0; i < hdev->nvqs; ++i) { + vhost_virtqueue_stop(hdev, + vdev, +diff --git a/include/hw/virtio/vhost.h b/include/hw/virtio/vhost.h +index d7ab2579ff..662e0f4370 100644 +--- a/include/hw/virtio/vhost.h ++++ b/include/hw/virtio/vhost.h +@@ -5,6 +5,9 @@ + #include "hw/virtio/virtio.h" + #include "exec/memory.h" + ++#define VHOST_F_DEVICE_IOTLB 63 ++#define VHOST_USER_F_PROTOCOL_FEATURES 30 ++ + /* Generic structures common for any vhost based device. */ + + struct vhost_inflight { +@@ -165,24 +168,26 @@ void vhost_dev_disable_notifiers(struct vhost_dev *hdev, VirtIODevice *vdev); + * vhost_dev_start() - start the vhost device + * @hdev: common vhost_dev structure + * @vdev: the VirtIODevice structure ++ * @vrings: true to have vrings enabled in this call + * + * Starts the vhost device. From this point VirtIO feature negotiation + * can start and the device can start processing VirtIO transactions. + * + * Return: 0 on success, < 0 on error. + */ +-int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev); ++int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev, bool vrings); + + /** + * vhost_dev_stop() - stop the vhost device + * @hdev: common vhost_dev structure + * @vdev: the VirtIODevice structure ++ * @vrings: true to have vrings disabled in this call + * + * Stop the vhost device. After the device is stopped the notifiers + * can be disabled (@vhost_dev_disable_notifiers) and the device can + * be torn down (@vhost_dev_cleanup). + */ +-void vhost_dev_stop(struct vhost_dev *hdev, VirtIODevice *vdev); ++void vhost_dev_stop(struct vhost_dev *hdev, VirtIODevice *vdev, bool vrings); + + /** + * DOC: vhost device configuration handling +-- +2.27.0 + diff --git a/vhost-fix-possible-wrap-in-SVQ-descriptor-ring.patch b/vhost-fix-possible-wrap-in-SVQ-descriptor-ring.patch new file mode 100644 index 00000000..a21d4be0 --- /dev/null +++ b/vhost-fix-possible-wrap-in-SVQ-descriptor-ring.patch @@ -0,0 +1,108 @@ +From fdc4e7386f7fa5f0d47d6d7b582a01854073206e Mon Sep 17 00:00:00 2001 +From: Hawkins Jiawei +Date: Tue, 9 May 2023 16:48:17 +0800 +Subject: [PATCH] vhost: fix possible wrap in SVQ descriptor ring +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +QEMU invokes vhost_svq_add() when adding a guest's element +into SVQ. In vhost_svq_add(), it uses vhost_svq_available_slots() +to check whether QEMU can add the element into SVQ. If there is +enough space, then QEMU combines some out descriptors and some +in descriptors into one descriptor chain, and adds it into +`svq->vring.desc` by vhost_svq_vring_write_descs(). + +Yet the problem is that, `svq->shadow_avail_idx - svq->shadow_used_idx` +in vhost_svq_available_slots() returns the number of occupied elements, +or the number of descriptor chains, instead of the number of occupied +descriptors, which may cause wrapping in SVQ descriptor ring. + +Here is an example. In vhost_handle_guest_kick(), QEMU forwards +as many available buffers to device by virtqueue_pop() and +vhost_svq_add_element(). virtqueue_pop() returns a guest's element, +and then this element is added into SVQ by vhost_svq_add_element(), +a wrapper to vhost_svq_add(). If QEMU invokes virtqueue_pop() and +vhost_svq_add_element() `svq->vring.num` times, +vhost_svq_available_slots() thinks QEMU just ran out of slots and +everything should work fine. But in fact, virtqueue_pop() returns +`svq->vring.num` elements or descriptor chains, more than +`svq->vring.num` descriptors due to guest memory fragmentation, +and this causes wrapping in SVQ descriptor ring. + +This bug is valid even before marking the descriptors used. +If the guest memory is fragmented, SVQ must add chains +so it can try to add more descriptors than possible. + +This patch solves it by adding `num_free` field in +VhostShadowVirtqueue structure and updating this field +in vhost_svq_add() and vhost_svq_get_buf(), to record +the number of free descriptors. + +Fixes: 100890f7ca ("vhost: Shadow virtqueue buffers forwarding") +Signed-off-by: Hawkins Jiawei +Acked-by: Eugenio Pérez +Message-Id: <20230509084817.3973-1-yin31149@gmail.com> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Tested-by: Lei Yang +Signed-off-by: fangyi +--- + hw/virtio/vhost-shadow-virtqueue.c | 5 ++++- + hw/virtio/vhost-shadow-virtqueue.h | 3 +++ + 2 files changed, 7 insertions(+), 1 deletion(-) + +diff --git a/hw/virtio/vhost-shadow-virtqueue.c b/hw/virtio/vhost-shadow-virtqueue.c +index 7d6afcb528..8d99edb196 100644 +--- a/hw/virtio/vhost-shadow-virtqueue.c ++++ b/hw/virtio/vhost-shadow-virtqueue.c +@@ -66,7 +66,7 @@ bool vhost_svq_valid_features(uint64_t features, Error **errp) + */ + static uint16_t vhost_svq_available_slots(const VhostShadowVirtqueue *svq) + { +- return svq->vring.num - (svq->shadow_avail_idx - svq->shadow_used_idx); ++ return svq->num_free; + } + + /** +@@ -255,6 +255,7 @@ int vhost_svq_add(VhostShadowVirtqueue *svq, const struct iovec *out_sg, + return -EINVAL; + } + ++ svq->num_free -= ndescs; + svq->desc_state[qemu_head].elem = elem; + svq->desc_state[qemu_head].ndescs = ndescs; + vhost_svq_kick(svq); +@@ -426,6 +427,7 @@ static VirtQueueElement *vhost_svq_get_buf(VhostShadowVirtqueue *svq, + last_used_chain = vhost_svq_last_desc_of_chain(svq, num, used_elem.id); + svq->desc_next[last_used_chain] = svq->free_head; + svq->free_head = used_elem.id; ++ svq->num_free += num; + + *len = used_elem.len; + return g_steal_pointer(&svq->desc_state[used_elem.id].elem); +@@ -636,6 +638,7 @@ void vhost_svq_start(VhostShadowVirtqueue *svq, VirtIODevice *vdev, + svq->iova_tree = iova_tree; + + svq->vring.num = virtio_queue_get_num(vdev, virtio_get_queue_index(vq)); ++ svq->num_free = svq->vring.num; + driver_size = vhost_svq_driver_area_size(svq); + device_size = vhost_svq_device_area_size(svq); + svq->vring.desc = qemu_memalign(qemu_real_host_page_size, driver_size); +diff --git a/hw/virtio/vhost-shadow-virtqueue.h b/hw/virtio/vhost-shadow-virtqueue.h +index 926a4897b1..6efe051a70 100644 +--- a/hw/virtio/vhost-shadow-virtqueue.h ++++ b/hw/virtio/vhost-shadow-virtqueue.h +@@ -107,6 +107,9 @@ typedef struct VhostShadowVirtqueue { + + /* Next head to consume from the device */ + uint16_t last_used_idx; ++ ++ /* Size of SVQ vring free descriptors */ ++ uint16_t num_free; + } VhostShadowVirtqueue; + + bool vhost_svq_valid_features(uint64_t features, Error **errp); +-- +2.27.0 + diff --git a/vhost-fix-the-fd-leak.patch b/vhost-fix-the-fd-leak.patch new file mode 100644 index 00000000..2ccc1833 --- /dev/null +++ b/vhost-fix-the-fd-leak.patch @@ -0,0 +1,37 @@ +From 2fb147eb0189ee24a74ebf784b9a682667288d3d Mon Sep 17 00:00:00 2001 +From: Li Feng +Date: Mon, 31 Jul 2023 20:10:06 +0800 +Subject: [PATCH] vhost: fix the fd leak + +When the vhost-user reconnect to the backend, the notifer should be +cleanup. Otherwise, the fd resource will be exhausted. + +Fixes: f9a09ca3ea ("vhost: add support for configure interrupt") + +Signed-off-by: Li Feng +Reviewed-by: Raphael Norwitz +Message-Id: <20230731121018.2856310-2-fengli@smartx.com> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Tested-by: Fiona Ebner +Signed-off-by: fangyi +--- + hw/virtio/vhost.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c +index 490c97424b..63ddcb3e6d 100644 +--- a/hw/virtio/vhost.c ++++ b/hw/virtio/vhost.c +@@ -2009,6 +2009,8 @@ void vhost_dev_stop(struct vhost_dev *hdev, VirtIODevice *vdev, bool vrings) + event_notifier_test_and_clear( + &hdev->vqs[VHOST_QUEUE_NUM_CONFIG_INR].masked_config_notifier); + event_notifier_test_and_clear(&vdev->config_notifier); ++ event_notifier_cleanup( ++ &hdev->vqs[VHOST_QUEUE_NUM_CONFIG_INR].masked_config_notifier); + + trace_vhost_dev_stop(hdev, vdev->name, vrings); + +-- +2.27.0 + diff --git a/vhost-fix-vq-dirty-bitmap-syncing-when-vIOMMU-is-ena.patch b/vhost-fix-vq-dirty-bitmap-syncing-when-vIOMMU-is-ena.patch new file mode 100644 index 00000000..9854a13c --- /dev/null +++ b/vhost-fix-vq-dirty-bitmap-syncing-when-vIOMMU-is-ena.patch @@ -0,0 +1,143 @@ +From 1f8330f9b4cba6ce8d88d227aeae4849c0062cf0 Mon Sep 17 00:00:00 2001 +From: Jason Wang +Date: Fri, 16 Dec 2022 11:35:52 +0800 +Subject: [PATCH] vhost: fix vq dirty bitmap syncing when vIOMMU is enabled + +When vIOMMU is enabled, the vq->used_phys is actually the IOVA not +GPA. So we need to translate it to GPA before the syncing otherwise we +may hit the following crash since IOVA could be out of the scope of +the GPA log size. This could be noted when using virtio-IOMMU with +vhost using 1G memory. + +Fixes: c471ad0e9bd46 ("vhost_net: device IOTLB support") +Cc: qemu-stable@nongnu.org +Tested-by: Lei Yang +Reported-by: Yalan Zhang +Signed-off-by: Jason Wang +Message-Id: <20221216033552.77087-1-jasowang@redhat.com> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Signed-off-by: fangyi +--- + hw/virtio/vhost.c | 84 ++++++++++++++++++++++++++++++++++++----------- + 1 file changed, 64 insertions(+), 20 deletions(-) + +diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c +index 8e8657fb0d..19ea9aef69 100644 +--- a/hw/virtio/vhost.c ++++ b/hw/virtio/vhost.c +@@ -20,6 +20,7 @@ + #include "qemu/range.h" + #include "qemu/error-report.h" + #include "qemu/memfd.h" ++#include "qemu/log.h" + #include "standard-headers/linux/vhost_types.h" + #include "hw/virtio/virtio-bus.h" + #include "hw/virtio/virtio-access.h" +@@ -110,6 +111,24 @@ static void vhost_dev_sync_region(struct vhost_dev *dev, + } + } + ++static bool vhost_dev_has_iommu(struct vhost_dev *dev) ++{ ++ VirtIODevice *vdev = dev->vdev; ++ ++ /* ++ * For vhost, VIRTIO_F_IOMMU_PLATFORM means the backend support ++ * incremental memory mapping API via IOTLB API. For platform that ++ * does not have IOMMU, there's no need to enable this feature ++ * which may cause unnecessary IOTLB miss/update transactions. ++ */ ++ if (vdev) { ++ return virtio_bus_device_iommu_enabled(vdev) && ++ virtio_host_has_feature(vdev, VIRTIO_F_IOMMU_PLATFORM); ++ } else { ++ return false; ++ } ++} ++ + static int vhost_sync_dirty_bitmap(struct vhost_dev *dev, + MemoryRegionSection *section, + hwaddr first, +@@ -141,8 +160,51 @@ static int vhost_sync_dirty_bitmap(struct vhost_dev *dev, + continue; + } + +- vhost_dev_sync_region(dev, section, start_addr, end_addr, vq->used_phys, +- range_get_last(vq->used_phys, vq->used_size)); ++ if (vhost_dev_has_iommu(dev)) { ++ IOMMUTLBEntry iotlb; ++ hwaddr used_phys = vq->used_phys, used_size = vq->used_size; ++ hwaddr phys, s, offset; ++ ++ while (used_size) { ++ rcu_read_lock(); ++ iotlb = address_space_get_iotlb_entry(dev->vdev->dma_as, ++ used_phys, ++ true, ++ MEMTXATTRS_UNSPECIFIED); ++ rcu_read_unlock(); ++ ++ if (!iotlb.target_as) { ++ qemu_log_mask(LOG_GUEST_ERROR, "translation " ++ "failure for used_iova %"PRIx64"\n", ++ used_phys); ++ return -EINVAL; ++ } ++ ++ offset = used_phys & iotlb.addr_mask; ++ phys = iotlb.translated_addr + offset; ++ ++ /* ++ * Distance from start of used ring until last byte of ++ * IOMMU page. ++ */ ++ s = iotlb.addr_mask - offset; ++ /* ++ * Size of used ring, or of the part of it until end ++ * of IOMMU page. To avoid zero result, do the adding ++ * outside of MIN(). ++ */ ++ s = MIN(s, used_size - 1) + 1; ++ ++ vhost_dev_sync_region(dev, section, start_addr, end_addr, phys, ++ range_get_last(phys, s)); ++ used_size -= s; ++ used_phys += s; ++ } ++ } else { ++ vhost_dev_sync_region(dev, section, start_addr, ++ end_addr, vq->used_phys, ++ range_get_last(vq->used_phys, vq->used_size)); ++ } + } + return 0; + } +@@ -310,24 +372,6 @@ static inline void vhost_dev_log_resize(struct vhost_dev *dev, uint64_t size) + dev->log_size = size; + } + +-static bool vhost_dev_has_iommu(struct vhost_dev *dev) +-{ +- VirtIODevice *vdev = dev->vdev; +- +- /* +- * For vhost, VIRTIO_F_IOMMU_PLATFORM means the backend support +- * incremental memory mapping API via IOTLB API. For platform that +- * does not have IOMMU, there's no need to enable this feature +- * which may cause unnecessary IOTLB miss/update transactions. +- */ +- if (vdev) { +- return virtio_bus_device_iommu_enabled(vdev) && +- virtio_host_has_feature(vdev, VIRTIO_F_IOMMU_PLATFORM); +- } else { +- return false; +- } +-} +- + static void *vhost_memory_map(struct vhost_dev *dev, hwaddr addr, + hwaddr *plen, bool is_write) + { +-- +2.27.0 + diff --git a/vhost-introduce-new-VhostOps-vhost_set_config_call-new.patch b/vhost-introduce-new-VhostOps-vhost_set_config_call-new.patch new file mode 100644 index 00000000..b1e7a940 --- /dev/null +++ b/vhost-introduce-new-VhostOps-vhost_set_config_call-new.patch @@ -0,0 +1,42 @@ +From 0e8cd86ad1cc2c67fb3bd31493b534d740c9ac28 Mon Sep 17 00:00:00 2001 +From: Cindy Lu +Date: Thu, 22 Dec 2022 15:04:45 +0800 +Subject: [PATCH] vhost: introduce new VhostOps vhost_set_config_call + +This patch introduces new VhostOps vhost_set_config_call. +This function allows the qemu to set the config +event fd to kernel driver. + +Signed-off-by: Cindy Lu +Message-Id: <20221222070451.936503-5-lulu@redhat.com> +Acked-by: Jason Wang +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +--- + include/hw/virtio/vhost-backend.h | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/include/hw/virtio/vhost-backend.h b/include/hw/virtio/vhost-backend.h +index a64708f456..bd1c7dfe4f 100644 +--- a/include/hw/virtio/vhost-backend.h ++++ b/include/hw/virtio/vhost-backend.h +@@ -125,6 +125,8 @@ typedef int (*vhost_vq_get_addr_op)(struct vhost_dev *dev, + typedef int (*vhost_get_device_id_op)(struct vhost_dev *dev, uint32_t *dev_id); + + typedef bool (*vhost_force_iommu_op)(struct vhost_dev *dev); ++typedef int (*vhost_set_config_call_op)(struct vhost_dev *dev, ++ int fd); + typedef void (*vhost_set_used_memslots_op)(struct vhost_dev *dev); + typedef unsigned int (*vhost_get_used_memslots_op)(void); + +@@ -173,6 +175,7 @@ typedef struct VhostOps { + vhost_vq_get_addr_op vhost_vq_get_addr; + vhost_get_device_id_op vhost_get_device_id; + vhost_force_iommu_op vhost_force_iommu; ++ vhost_set_config_call_op vhost_set_config_call; + vhost_set_used_memslots_op vhost_set_used_memslots; + vhost_get_used_memslots_op vhost_get_used_memslots; + } VhostOps; +-- +2.27.0 + diff --git a/vhost-introduce-new-VhostOps-vhost_set_config_call.patch b/vhost-introduce-new-VhostOps-vhost_set_config_call.patch new file mode 100644 index 00000000..92b4c263 --- /dev/null +++ b/vhost-introduce-new-VhostOps-vhost_set_config_call.patch @@ -0,0 +1,41 @@ +From af8377d0e9437401ad30d80a27ab1fcf8252fad1 Mon Sep 17 00:00:00 2001 +From: fangyi +Date: Thu, 16 Nov 2023 09:54:57 +0800 +Subject: [PATCH] vhost: introduce new VhostOps vhost_set_config_call + +This patch introduces new VhostOps vhost_set_config_call. This function allows the +vhost to set the event fd to kernel + +Signed-off-by: Cindy Lu +Message-Id: <20211104164827.21911-5-lulu@redhat.com> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Signed-off-by: fangyi +--- + include/hw/virtio/vhost-backend.h | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/include/hw/virtio/vhost-backend.h b/include/hw/virtio/vhost-backend.h +index a64708f456..bd1c7dfe4f 100644 +--- a/include/hw/virtio/vhost-backend.h ++++ b/include/hw/virtio/vhost-backend.h +@@ -125,6 +125,8 @@ typedef int (*vhost_vq_get_addr_op)(struct vhost_dev *dev, + typedef int (*vhost_get_device_id_op)(struct vhost_dev *dev, uint32_t *dev_id); + + typedef bool (*vhost_force_iommu_op)(struct vhost_dev *dev); ++typedef int (*vhost_set_config_call_op)(struct vhost_dev *dev, ++ int fd); + typedef void (*vhost_set_used_memslots_op)(struct vhost_dev *dev); + typedef unsigned int (*vhost_get_used_memslots_op)(void); + +@@ -173,6 +175,7 @@ typedef struct VhostOps { + vhost_vq_get_addr_op vhost_vq_get_addr; + vhost_get_device_id_op vhost_get_device_id; + vhost_force_iommu_op vhost_force_iommu; ++ vhost_set_config_call_op vhost_set_config_call; + vhost_set_used_memslots_op vhost_set_used_memslots; + vhost_get_used_memslots_op vhost_get_used_memslots; + } VhostOps; +-- +2.27.0 + diff --git a/vhost-move-descriptor-translation-to-vhost_svq_vring.patch b/vhost-move-descriptor-translation-to-vhost_svq_vring.patch new file mode 100644 index 00000000..a45e88f8 --- /dev/null +++ b/vhost-move-descriptor-translation-to-vhost_svq_vring.patch @@ -0,0 +1,101 @@ +From 16fdc235caece008e3802934250f434e9ca03dd3 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= +Date: Wed, 20 Jul 2022 08:59:26 +0200 +Subject: [PATCH] vhost: move descriptor translation to + vhost_svq_vring_write_descs +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +It's done for both in and out descriptors so it's better placed here. + +Acked-by: Jason Wang +Signed-off-by: Eugenio Pérez +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Jason Wang +Signed-off-by: fangyi +--- + hw/virtio/vhost-shadow-virtqueue.c | 38 +++++++++++++++++++++--------- + 1 file changed, 27 insertions(+), 11 deletions(-) + +diff --git a/hw/virtio/vhost-shadow-virtqueue.c b/hw/virtio/vhost-shadow-virtqueue.c +index cea2c3f8dd..da1e1ce3c7 100644 +--- a/hw/virtio/vhost-shadow-virtqueue.c ++++ b/hw/virtio/vhost-shadow-virtqueue.c +@@ -121,17 +121,35 @@ static bool vhost_svq_translate_addr(const VhostShadowVirtqueue *svq, + return true; + } + +-static void vhost_vring_write_descs(VhostShadowVirtqueue *svq, hwaddr *sg, +- const struct iovec *iovec, size_t num, +- bool more_descs, bool write) ++/** ++ * Write descriptors to SVQ vring ++ * ++ * @svq: The shadow virtqueue ++ * @sg: Cache for hwaddr ++ * @iovec: The iovec from the guest ++ * @num: iovec length ++ * @more_descs: True if more descriptors come in the chain ++ * @write: True if they are writeable descriptors ++ * ++ * Return true if success, false otherwise and print error. ++ */ ++static bool vhost_svq_vring_write_descs(VhostShadowVirtqueue *svq, hwaddr *sg, ++ const struct iovec *iovec, size_t num, ++ bool more_descs, bool write) + { + uint16_t i = svq->free_head, last = svq->free_head; + unsigned n; + uint16_t flags = write ? cpu_to_le16(VRING_DESC_F_WRITE) : 0; + vring_desc_t *descs = svq->vring.desc; ++ bool ok; + + if (num == 0) { +- return; ++ return true; ++ } ++ ++ ok = vhost_svq_translate_addr(svq, sg, iovec, num); ++ if (unlikely(!ok)) { ++ return false; + } + + for (n = 0; n < num; n++) { +@@ -149,6 +167,7 @@ static void vhost_vring_write_descs(VhostShadowVirtqueue *svq, hwaddr *sg, + } + + svq->free_head = le16_to_cpu(svq->desc_next[last]); ++ return true; + } + + static bool vhost_svq_add_split(VhostShadowVirtqueue *svq, +@@ -168,21 +187,18 @@ static bool vhost_svq_add_split(VhostShadowVirtqueue *svq, + return false; + } + +- ok = vhost_svq_translate_addr(svq, sgs, elem->out_sg, elem->out_num); ++ ok = vhost_svq_vring_write_descs(svq, sgs, elem->out_sg, elem->out_num, ++ elem->in_num > 0, false); + if (unlikely(!ok)) { + return false; + } +- vhost_vring_write_descs(svq, sgs, elem->out_sg, elem->out_num, +- elem->in_num > 0, false); +- + +- ok = vhost_svq_translate_addr(svq, sgs, elem->in_sg, elem->in_num); ++ ok = vhost_svq_vring_write_descs(svq, sgs, elem->in_sg, elem->in_num, false, ++ true); + if (unlikely(!ok)) { + return false; + } + +- vhost_vring_write_descs(svq, sgs, elem->in_sg, elem->in_num, false, true); +- + /* + * Put the entry in the available array (but don't update avail->idx until + * they do sync). +-- +2.27.0 + diff --git a/vhost-move-iova_tree-set-to-vhost_svq_start.patch b/vhost-move-iova_tree-set-to-vhost_svq_start.patch new file mode 100644 index 00000000..93cccc1a --- /dev/null +++ b/vhost-move-iova_tree-set-to-vhost_svq_start.patch @@ -0,0 +1,114 @@ +From 7c93447234412390e6cd3bae1d5001426287a362 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= +Date: Thu, 15 Dec 2022 12:31:36 +0100 +Subject: [PATCH] vhost: move iova_tree set to vhost_svq_start +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Since we don't know if we will use SVQ at qemu initialization, let's +allocate iova_tree only if needed. To do so, accept it at SVQ start, not +at initialization. + +This will avoid to create it if the device does not support SVQ. + +Signed-off-by: Eugenio Pérez +Acked-by: Jason Wang +Message-Id: <20221215113144.322011-5-eperezma@redhat.com> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Signed-off-by: fangyi +--- + hw/virtio/vhost-shadow-virtqueue.c | 9 ++++----- + hw/virtio/vhost-shadow-virtqueue.h | 5 ++--- + hw/virtio/vhost-vdpa.c | 5 ++--- + 3 files changed, 8 insertions(+), 11 deletions(-) + +diff --git a/hw/virtio/vhost-shadow-virtqueue.c b/hw/virtio/vhost-shadow-virtqueue.c +index 1ea7b5cf59..7d6afcb528 100644 +--- a/hw/virtio/vhost-shadow-virtqueue.c ++++ b/hw/virtio/vhost-shadow-virtqueue.c +@@ -619,9 +619,10 @@ void vhost_svq_set_svq_kick_fd(VhostShadowVirtqueue *svq, int svq_kick_fd) + * @svq: Shadow Virtqueue + * @vdev: VirtIO device + * @vq: Virtqueue to shadow ++ * @iova_tree: Tree to perform descriptors translations + */ + void vhost_svq_start(VhostShadowVirtqueue *svq, VirtIODevice *vdev, +- VirtQueue *vq) ++ VirtQueue *vq, VhostIOVATree *iova_tree) + { + size_t desc_size, driver_size, device_size; + +@@ -632,6 +633,7 @@ void vhost_svq_start(VhostShadowVirtqueue *svq, VirtIODevice *vdev, + svq->last_used_idx = 0; + svq->vdev = vdev; + svq->vq = vq; ++ svq->iova_tree = iova_tree; + + svq->vring.num = virtio_queue_get_num(vdev, virtio_get_queue_index(vq)); + driver_size = vhost_svq_driver_area_size(svq); +@@ -689,18 +691,15 @@ void vhost_svq_stop(VhostShadowVirtqueue *svq) + * Creates vhost shadow virtqueue, and instructs the vhost device to use the + * shadow methods and file descriptors. + * +- * @iova_tree: Tree to perform descriptors translations + * @ops: SVQ owner callbacks + * @ops_opaque: ops opaque pointer + */ +-VhostShadowVirtqueue *vhost_svq_new(VhostIOVATree *iova_tree, +- const VhostShadowVirtqueueOps *ops, ++VhostShadowVirtqueue *vhost_svq_new(const VhostShadowVirtqueueOps *ops, + void *ops_opaque) + { + VhostShadowVirtqueue *svq = g_new0(VhostShadowVirtqueue, 1); + + event_notifier_init_fd(&svq->svq_kick, VHOST_FILE_UNBIND); +- svq->iova_tree = iova_tree; + svq->ops = ops; + svq->ops_opaque = ops_opaque; + return svq; +diff --git a/hw/virtio/vhost-shadow-virtqueue.h b/hw/virtio/vhost-shadow-virtqueue.h +index d04c34a589..926a4897b1 100644 +--- a/hw/virtio/vhost-shadow-virtqueue.h ++++ b/hw/virtio/vhost-shadow-virtqueue.h +@@ -126,11 +126,10 @@ size_t vhost_svq_driver_area_size(const VhostShadowVirtqueue *svq); + size_t vhost_svq_device_area_size(const VhostShadowVirtqueue *svq); + + void vhost_svq_start(VhostShadowVirtqueue *svq, VirtIODevice *vdev, +- VirtQueue *vq); ++ VirtQueue *vq, VhostIOVATree *iova_tree); + void vhost_svq_stop(VhostShadowVirtqueue *svq); + +-VhostShadowVirtqueue *vhost_svq_new(VhostIOVATree *iova_tree, +- const VhostShadowVirtqueueOps *ops, ++VhostShadowVirtqueue *vhost_svq_new(const VhostShadowVirtqueueOps *ops, + void *ops_opaque); + + void vhost_svq_free(gpointer vq); +diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c +index 2fd7af1c6b..f5d816f5ec 100644 +--- a/hw/virtio/vhost-vdpa.c ++++ b/hw/virtio/vhost-vdpa.c +@@ -419,8 +419,7 @@ static void vhost_vdpa_init_svq(struct vhost_dev *hdev, struct vhost_vdpa *v) + for (unsigned n = 0; n < hdev->nvqs; ++n) { + VhostShadowVirtqueue *svq; + +- svq = vhost_svq_new(v->iova_tree, v->shadow_vq_ops, +- v->shadow_vq_ops_opaque); ++ svq = vhost_svq_new(v->shadow_vq_ops, v->shadow_vq_ops_opaque); + g_ptr_array_add(shadow_vqs, svq); + } + +@@ -1060,7 +1059,7 @@ static bool vhost_vdpa_svqs_start(struct vhost_dev *dev) + goto err; + } + +- vhost_svq_start(svq, dev->vdev, vq); ++ vhost_svq_start(svq, dev->vdev, vq, v->iova_tree); + ok = vhost_vdpa_svq_map_rings(dev, svq, &addr, &err); + if (unlikely(!ok)) { + goto err_map; +-- +2.27.0 + diff --git a/vhost-release-virtqueue-objects-in-error-path.patch b/vhost-release-virtqueue-objects-in-error-path.patch new file mode 100644 index 00000000..895d2b2b --- /dev/null +++ b/vhost-release-virtqueue-objects-in-error-path.patch @@ -0,0 +1,39 @@ +From ec9c8583bee8ba140274abd3f5e8366442ceaa8e Mon Sep 17 00:00:00 2001 +From: Prasad Pandit +Date: Mon, 29 May 2023 17:13:33 +0530 +Subject: [PATCH] vhost: release virtqueue objects in error path + +vhost_dev_start function does not release virtqueue objects when +event_notifier_init() function fails. Release virtqueue objects +and log a message about function failure. + +Signed-off-by: Prasad Pandit +Message-Id: <20230529114333.31686-3-ppandit@redhat.com> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Fixes: f9a09ca3ea ("vhost: add support for configure interrupt") +Reviewed-by: Peter Xu +Cc: qemu-stable@nongnu.org +Acked-by: Jason Wang +Signed-off-by: fangyi +--- + hw/virtio/vhost.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c +index 63ddcb3e6d..59a12735f9 100644 +--- a/hw/virtio/vhost.c ++++ b/hw/virtio/vhost.c +@@ -1931,7 +1931,8 @@ int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev, bool vrings) + r = event_notifier_init( + &hdev->vqs[VHOST_QUEUE_NUM_CONFIG_INR].masked_config_notifier, 0); + if (r < 0) { +- return r; ++ VHOST_OPS_DEBUG(r, "event_notifier_init failed"); ++ goto fail_vq; + } + event_notifier_test_and_clear( + &hdev->vqs[VHOST_QUEUE_NUM_CONFIG_INR].masked_config_notifier); +-- +2.27.0 + diff --git a/vhost-set-SVQ-device-call-handler-at-SVQ-start.patch b/vhost-set-SVQ-device-call-handler-at-SVQ-start.patch new file mode 100644 index 00000000..1d95b5ce --- /dev/null +++ b/vhost-set-SVQ-device-call-handler-at-SVQ-start.patch @@ -0,0 +1,65 @@ +From 462ece480c425ef9de419f5454ec2b7293c35e16 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= +Date: Thu, 15 Dec 2022 12:31:34 +0100 +Subject: [PATCH] vhost: set SVQ device call handler at SVQ start +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +By the end of this series CVQ is shadowed as long as the features +support it. + +Since we don't know at the beginning of qemu running if this is +supported, move the event notifier handler setting to the start of the +SVQ, instead of the start of qemu run. This will avoid to create them if +the device does not support SVQ. + +Signed-off-by: Eugenio Pérez +Acked-by: Jason Wang +Message-Id: <20221215113144.322011-3-eperezma@redhat.com> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Signed-off-by: fangyi +--- + hw/virtio/vhost-shadow-virtqueue.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/hw/virtio/vhost-shadow-virtqueue.c b/hw/virtio/vhost-shadow-virtqueue.c +index ae443f54fe..bc12bb42f3 100644 +--- a/hw/virtio/vhost-shadow-virtqueue.c ++++ b/hw/virtio/vhost-shadow-virtqueue.c +@@ -625,6 +625,7 @@ void vhost_svq_start(VhostShadowVirtqueue *svq, VirtIODevice *vdev, + { + size_t desc_size, driver_size, device_size; + ++ event_notifier_set_handler(&svq->hdev_call, vhost_svq_handle_call); + svq->next_guest_avail_elem = NULL; + svq->shadow_avail_idx = 0; + svq->shadow_used_idx = 0; +@@ -681,6 +682,7 @@ void vhost_svq_stop(VhostShadowVirtqueue *svq) + g_free(svq->desc_state); + qemu_vfree(svq->vring.desc); + qemu_vfree(svq->vring.used); ++ event_notifier_set_handler(&svq->hdev_call, NULL); + } + + /** +@@ -717,7 +719,6 @@ VhostShadowVirtqueue *vhost_svq_new(VhostIOVATree *iova_tree, + } + + event_notifier_init_fd(&svq->svq_kick, VHOST_FILE_UNBIND); +- event_notifier_set_handler(&svq->hdev_call, vhost_svq_handle_call); + svq->iova_tree = iova_tree; + svq->ops = ops; + svq->ops_opaque = ops_opaque; +@@ -740,7 +741,6 @@ void vhost_svq_free(gpointer pvq) + VhostShadowVirtqueue *vq = pvq; + vhost_svq_stop(vq); + event_notifier_cleanup(&vq->hdev_kick); +- event_notifier_set_handler(&vq->hdev_call, NULL); + event_notifier_cleanup(&vq->hdev_call); + g_free(vq); + } +-- +2.27.0 + diff --git a/vhost-stick-to-errno-error-return-convention.patch b/vhost-stick-to-errno-error-return-convention.patch new file mode 100644 index 00000000..2607c446 --- /dev/null +++ b/vhost-stick-to-errno-error-return-convention.patch @@ -0,0 +1,349 @@ +From a5d0727f516b27e39b1f223e8dcf57b4c1bf95ea Mon Sep 17 00:00:00 2001 +From: fangyi +Date: Thu, 16 Nov 2023 09:54:56 +0800 +Subject: [PATCH] vhost: stick to -errno error return convention + +The generic vhost code expects that many of the VhostOps methods in the +respective backends set errno on errors. However, none of the existing +backends actually bothers to do so. In a number of those methods errno +from the failed call is clobbered by successful later calls to some +library functions; on a few code paths the generic vhost code then +negates and returns that errno, thus making failures look as successes +to the caller. + +As a result, in certain scenarios (e.g. live migration) the device +doesn't notice the first failure and goes on through its state +transitions as if everything is ok, instead of taking recovery actions +(break and reestablish the vhost-user connection, cancel migration, etc) +before it's too late. + +To fix this, consolidate on the convention to return negated errno on +failures throughout generic vhost, and use it for error propagation. + +Signed-off-by: Roman Kagan +Message-Id: <20211111153354.18807-10-rvkagan@yandex-team.ru> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Signed-off-by: fangyi +--- + hw/virtio/vhost.c | 100 +++++++++++++++++++++------------------------- + 1 file changed, 46 insertions(+), 54 deletions(-) + +diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c +index c3f375f276..caa53443ab 100644 +--- a/hw/virtio/vhost.c ++++ b/hw/virtio/vhost.c +@@ -34,11 +34,13 @@ + #define _VHOST_DEBUG 1 + + #ifdef _VHOST_DEBUG +-#define VHOST_OPS_DEBUG(fmt, ...) \ +- do { error_report(fmt ": %s (%d)", ## __VA_ARGS__, \ +- strerror(errno), errno); } while (0) ++#define VHOST_OPS_DEBUG(retval, fmt, ...) \ ++ do { \ ++ error_report(fmt ": %s (%d)", ## __VA_ARGS__, \ ++ strerror(-retval), -retval); \ ++ } while (0) + #else +-#define VHOST_OPS_DEBUG(fmt, ...) \ ++#define VHOST_OPS_DEBUG(retval, fmt, ...) \ + do { } while (0) + #endif + +@@ -300,7 +302,7 @@ static inline void vhost_dev_log_resize(struct vhost_dev *dev, uint64_t size) + releasing the current log, to ensure no logging is lost */ + r = dev->vhost_ops->vhost_set_log_base(dev, log_base, log); + if (r < 0) { +- VHOST_OPS_DEBUG("vhost_set_log_base failed"); ++ VHOST_OPS_DEBUG(r, "vhost_set_log_base failed"); + } + + vhost_log_put(dev, true); +@@ -552,7 +554,7 @@ static void vhost_commit(MemoryListener *listener) + if (!dev->log_enabled) { + r = dev->vhost_ops->vhost_set_mem_table(dev, dev->mem); + if (r < 0) { +- VHOST_OPS_DEBUG("vhost_set_mem_table failed"); ++ VHOST_OPS_DEBUG(r, "vhost_set_mem_table failed"); + } + goto out; + } +@@ -566,7 +568,7 @@ static void vhost_commit(MemoryListener *listener) + } + r = dev->vhost_ops->vhost_set_mem_table(dev, dev->mem); + if (r < 0) { +- VHOST_OPS_DEBUG("vhost_set_mem_table failed"); ++ VHOST_OPS_DEBUG(r, "vhost_set_mem_table failed"); + } + /* To log less, can only decrease log size after table update. */ + if (dev->log_size > log_size + VHOST_LOG_BUFFER) { +@@ -817,8 +819,8 @@ static int vhost_virtqueue_set_addr(struct vhost_dev *dev, + if (dev->vhost_ops->vhost_vq_get_addr) { + r = dev->vhost_ops->vhost_vq_get_addr(dev, &addr, vq); + if (r < 0) { +- VHOST_OPS_DEBUG("vhost_vq_get_addr failed"); +- return -errno; ++ VHOST_OPS_DEBUG(r, "vhost_vq_get_addr failed"); ++ return r; + } + } else { + addr.desc_user_addr = (uint64_t)(unsigned long)vq->desc; +@@ -830,10 +832,9 @@ static int vhost_virtqueue_set_addr(struct vhost_dev *dev, + addr.flags = enable_log ? (1 << VHOST_VRING_F_LOG) : 0; + r = dev->vhost_ops->vhost_set_vring_addr(dev, &addr); + if (r < 0) { +- VHOST_OPS_DEBUG("vhost_set_vring_addr failed"); +- return -errno; ++ VHOST_OPS_DEBUG(r, "vhost_set_vring_addr failed"); + } +- return 0; ++ return r; + } + + static int vhost_dev_set_features(struct vhost_dev *dev, +@@ -854,19 +855,19 @@ static int vhost_dev_set_features(struct vhost_dev *dev, + } + r = dev->vhost_ops->vhost_set_features(dev, features); + if (r < 0) { +- VHOST_OPS_DEBUG("vhost_set_features failed"); ++ VHOST_OPS_DEBUG(r, "vhost_set_features failed"); + goto out; + } + if (dev->vhost_ops->vhost_set_backend_cap) { + r = dev->vhost_ops->vhost_set_backend_cap(dev); + if (r < 0) { +- VHOST_OPS_DEBUG("vhost_set_backend_cap failed"); ++ VHOST_OPS_DEBUG(r, "vhost_set_backend_cap failed"); + goto out; + } + } + + out: +- return r < 0 ? -errno : 0; ++ return r; + } + + static int vhost_dev_set_log(struct vhost_dev *dev, bool enable_log) +@@ -1021,22 +1022,17 @@ static int vhost_virtqueue_set_vring_endian_legacy(struct vhost_dev *dev, + bool is_big_endian, + int vhost_vq_index) + { ++ int r; + struct vhost_vring_state s = { + .index = vhost_vq_index, + .num = is_big_endian + }; + +- if (!dev->vhost_ops->vhost_set_vring_endian(dev, &s)) { +- return 0; +- } +- +- VHOST_OPS_DEBUG("vhost_set_vring_endian failed"); +- if (errno == ENOTTY) { +- error_report("vhost does not support cross-endian"); +- return -ENOSYS; ++ r = dev->vhost_ops->vhost_set_vring_endian(dev, &s); ++ if (r < 0) { ++ VHOST_OPS_DEBUG(r, "vhost_set_vring_endian failed"); + } +- +- return -errno; ++ return r; + } + + static int vhost_memory_region_lookup(struct vhost_dev *hdev, +@@ -1128,15 +1124,15 @@ static int vhost_virtqueue_start(struct vhost_dev *dev, + vq->num = state.num = virtio_queue_get_num(vdev, idx); + r = dev->vhost_ops->vhost_set_vring_num(dev, &state); + if (r) { +- VHOST_OPS_DEBUG("vhost_set_vring_num failed"); +- return -errno; ++ VHOST_OPS_DEBUG(r, "vhost_set_vring_num failed"); ++ return r; + } + + state.num = virtio_queue_get_last_avail_idx(vdev, idx); + r = dev->vhost_ops->vhost_set_vring_base(dev, &state); + if (r) { +- VHOST_OPS_DEBUG("vhost_set_vring_base failed"); +- return -errno; ++ VHOST_OPS_DEBUG(r, "vhost_set_vring_base failed"); ++ return r; + } + + if (vhost_needs_vring_endian(vdev)) { +@@ -1144,7 +1140,7 @@ static int vhost_virtqueue_start(struct vhost_dev *dev, + virtio_is_big_endian(vdev), + vhost_vq_index); + if (r) { +- return -errno; ++ return r; + } + } + +@@ -1172,15 +1168,13 @@ static int vhost_virtqueue_start(struct vhost_dev *dev, + + r = vhost_virtqueue_set_addr(dev, vq, vhost_vq_index, dev->log_enabled); + if (r < 0) { +- r = -errno; + goto fail_alloc; + } + + file.fd = event_notifier_get_fd(virtio_queue_get_host_notifier(vvq)); + r = dev->vhost_ops->vhost_set_vring_kick(dev, &file); + if (r) { +- VHOST_OPS_DEBUG("vhost_set_vring_kick failed"); +- r = -errno; ++ VHOST_OPS_DEBUG(r, "vhost_set_vring_kick failed"); + goto fail_kick; + } + +@@ -1240,7 +1234,7 @@ static void vhost_virtqueue_stop(struct vhost_dev *dev, + + r = dev->vhost_ops->vhost_get_vring_base(dev, &state); + if (r < 0) { +- VHOST_OPS_DEBUG("vhost VQ %u ring restore failed: %d", idx, r); ++ VHOST_OPS_DEBUG(r, "vhost VQ %u ring restore failed: %d", idx, r); + /* Connection to the backend is broken, so let's sync internal + * last avail idx to the device used idx. + */ +@@ -1284,7 +1278,7 @@ static int vhost_virtqueue_set_busyloop_timeout(struct vhost_dev *dev, + + r = dev->vhost_ops->vhost_set_vring_busyloop_timeout(dev, &state); + if (r) { +- VHOST_OPS_DEBUG("vhost_set_vring_busyloop_timeout failed"); ++ VHOST_OPS_DEBUG(r, "vhost_set_vring_busyloop_timeout failed"); + return r; + } + +@@ -1306,8 +1300,7 @@ static int vhost_virtqueue_init(struct vhost_dev *dev, + file.fd = event_notifier_get_fd(&vq->masked_notifier); + r = dev->vhost_ops->vhost_set_vring_call(dev, &file); + if (r) { +- VHOST_OPS_DEBUG("vhost_set_vring_call failed"); +- r = -errno; ++ VHOST_OPS_DEBUG(r, "vhost_set_vring_call failed"); + goto fail_call; + } + +@@ -1584,7 +1577,7 @@ void vhost_virtqueue_mask(struct vhost_dev *hdev, VirtIODevice *vdev, int n, + file.index = hdev->vhost_ops->vhost_get_vq_index(hdev, n); + r = hdev->vhost_ops->vhost_set_vring_call(hdev, &file); + if (r < 0) { +- VHOST_OPS_DEBUG("vhost_set_vring_call failed"); ++ VHOST_OPS_DEBUG(r, "vhost_set_vring_call failed"); + } + } + +@@ -1622,7 +1615,7 @@ void vhost_config_mask(struct vhost_dev *hdev, VirtIODevice *vdev, bool mask) + } + r = hdev->vhost_ops->vhost_set_config_call(hdev, fd); + if (r < 0) { +- VHOST_OPS_DEBUG("vhost_set_config_call failed"); ++ VHOST_OPS_DEBUG(r, "vhost_set_config_call failed"); + } + } + +@@ -1687,7 +1680,7 @@ int vhost_dev_get_config(struct vhost_dev *hdev, uint8_t *config, + } + + error_setg(errp, "vhost_get_config not implemented"); +- return -ENOTSUP; ++ return -ENOSYS; + } + + int vhost_dev_set_config(struct vhost_dev *hdev, const uint8_t *data, +@@ -1700,7 +1693,7 @@ int vhost_dev_set_config(struct vhost_dev *hdev, const uint8_t *data, + size, flags); + } + +- return -1; ++ return -ENOSYS; + } + + void vhost_dev_set_config_notifier(struct vhost_dev *hdev, +@@ -1729,7 +1722,7 @@ static int vhost_dev_resize_inflight(struct vhost_inflight *inflight, + + if (err) { + error_report_err(err); +- return -1; ++ return -ENOMEM; + } + + vhost_dev_free_inflight(inflight); +@@ -1762,8 +1755,9 @@ int vhost_dev_load_inflight(struct vhost_inflight *inflight, QEMUFile *f) + } + + if (inflight->size != size) { +- if (vhost_dev_resize_inflight(inflight, size)) { +- return -1; ++ int ret = vhost_dev_resize_inflight(inflight, size); ++ if (ret < 0) { ++ return ret; + } + } + inflight->queue_size = qemu_get_be16(f); +@@ -1786,7 +1780,7 @@ int vhost_dev_prepare_inflight(struct vhost_dev *hdev, VirtIODevice *vdev) + + r = vhost_dev_set_features(hdev, hdev->log_enabled); + if (r < 0) { +- VHOST_OPS_DEBUG("vhost_dev_prepare_inflight failed"); ++ VHOST_OPS_DEBUG(r, "vhost_dev_prepare_inflight failed"); + return r; + } + +@@ -1801,8 +1795,8 @@ int vhost_dev_set_inflight(struct vhost_dev *dev, + if (dev->vhost_ops->vhost_set_inflight_fd && inflight->addr) { + r = dev->vhost_ops->vhost_set_inflight_fd(dev, inflight); + if (r) { +- VHOST_OPS_DEBUG("vhost_set_inflight_fd failed"); +- return -errno; ++ VHOST_OPS_DEBUG(r, "vhost_set_inflight_fd failed"); ++ return r; + } + } + +@@ -1817,8 +1811,8 @@ int vhost_dev_get_inflight(struct vhost_dev *dev, uint16_t queue_size, + if (dev->vhost_ops->vhost_get_inflight_fd) { + r = dev->vhost_ops->vhost_get_inflight_fd(dev, queue_size, inflight); + if (r) { +- VHOST_OPS_DEBUG("vhost_get_inflight_fd failed"); +- return -errno; ++ VHOST_OPS_DEBUG(r, "vhost_get_inflight_fd failed"); ++ return r; + } + } + +@@ -1847,8 +1841,7 @@ int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev) + + r = hdev->vhost_ops->vhost_set_mem_table(hdev, hdev->mem); + if (r < 0) { +- VHOST_OPS_DEBUG("vhost_set_mem_table failed"); +- r = -errno; ++ VHOST_OPS_DEBUG(r, "vhost_set_mem_table failed"); + goto fail_mem; + } + for (i = 0; i < hdev->nvqs; ++i) { +@@ -1882,8 +1875,7 @@ int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev) + hdev->log_size ? log_base : 0, + hdev->log); + if (r < 0) { +- VHOST_OPS_DEBUG("vhost_set_log_base failed"); +- r = -errno; ++ VHOST_OPS_DEBUG(r, "vhost_set_log_base failed"); + goto fail_log; + } + } +@@ -1963,7 +1955,7 @@ int vhost_net_set_backend(struct vhost_dev *hdev, + return hdev->vhost_ops->vhost_net_set_backend(hdev, file); + } + +- return -1; ++ return -ENOSYS; + } + + bool used_memslots_is_exceeded(void) +-- +2.27.0 + diff --git a/vhost-user-stick-to-errno-error-return-convention.patch b/vhost-user-stick-to-errno-error-return-convention.patch new file mode 100644 index 00000000..037c3a28 --- /dev/null +++ b/vhost-user-stick-to-errno-error-return-convention.patch @@ -0,0 +1,1100 @@ +From f6c384a73aaaa7dfc52ed3ceb8ec135f33551629 Mon Sep 17 00:00:00 2001 +From: fangyi +Date: Thu, 16 Nov 2023 09:54:55 +0800 +Subject: [PATCH] vhost-user: stick to -errno error return convention + +VhostOps methods in user_ops are not very consistent in their error +returns: some return negated errno while others just -1. + +Make sure all of them consistently return negated errno. This also +helps error propagation from the functions being called inside. +Besides, this synchronizes the error return convention with the other +two vhost backends, kernel and vdpa, and will therefore allow for +consistent error propagation in the generic vhost code (in a followup +patch). + +Signed-off-by: Roman Kagan +Message-Id: <20211111153354.18807-9-rvkagan@yandex-team.ru> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Signed-off-by: fangyi +--- + hw/virtio/vhost-user.c | 401 +++++++++++++++++++++++------------------ + 1 file changed, 223 insertions(+), 178 deletions(-) + +diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c +index 24f80d5d18..358dc82010 100644 +--- a/hw/virtio/vhost-user.c ++++ b/hw/virtio/vhost-user.c +@@ -283,9 +283,10 @@ static int vhost_user_read_header(struct vhost_dev *dev, VhostUserMsg *msg) + + r = qemu_chr_fe_read_all(chr, p, size); + if (r != size) { ++ int saved_errno = errno; + error_report("Failed to read msg header. Read %d instead of %d." + " Original request %d.", r, size, msg->hdr.request); +- return -1; ++ return r < 0 ? -saved_errno : -EIO; + } + + /* validate received flags */ +@@ -293,7 +294,7 @@ static int vhost_user_read_header(struct vhost_dev *dev, VhostUserMsg *msg) + error_report("Failed to read msg header." + " Flags 0x%x instead of 0x%x.", msg->hdr.flags, + VHOST_USER_REPLY_MASK | VHOST_USER_VERSION); +- return -1; ++ return -EPROTO; + } + + return 0; +@@ -317,8 +318,9 @@ static gboolean vhost_user_read_cb(void *do_not_use, GIOCondition condition, + uint8_t *p = (uint8_t *) msg; + int r, size; + +- if (vhost_user_read_header(dev, msg) < 0) { +- data->ret = -1; ++ r = vhost_user_read_header(dev, msg); ++ if (r < 0) { ++ data->ret = r; + goto end; + } + +@@ -327,7 +329,7 @@ static gboolean vhost_user_read_cb(void *do_not_use, GIOCondition condition, + error_report("Failed to read msg header." + " Size %d exceeds the maximum %zu.", msg->hdr.size, + VHOST_USER_PAYLOAD_SIZE); +- data->ret = -1; ++ data->ret = -EPROTO; + goto end; + } + +@@ -336,9 +338,10 @@ static gboolean vhost_user_read_cb(void *do_not_use, GIOCondition condition, + size = msg->hdr.size; + r = qemu_chr_fe_read_all(chr, p, size); + if (r != size) { ++ int saved_errno = errno; + error_report("Failed to read msg payload." + " Read %d instead of %d.", r, msg->hdr.size); +- data->ret = -1; ++ data->ret = r < 0 ? -saved_errno : -EIO; + goto end; + } + } +@@ -421,24 +424,26 @@ static int vhost_user_read(struct vhost_dev *dev, VhostUserMsg *msg) + static int process_message_reply(struct vhost_dev *dev, + const VhostUserMsg *msg) + { ++ int ret; + VhostUserMsg msg_reply; + + if ((msg->hdr.flags & VHOST_USER_NEED_REPLY_MASK) == 0) { + return 0; + } + +- if (vhost_user_read(dev, &msg_reply) < 0) { +- return -1; ++ ret = vhost_user_read(dev, &msg_reply); ++ if (ret < 0) { ++ return ret; + } + + if (msg_reply.hdr.request != msg->hdr.request) { + error_report("Received unexpected msg type. " + "Expected %d received %d", + msg->hdr.request, msg_reply.hdr.request); +- return -1; ++ return -EPROTO; + } + +- return msg_reply.payload.u64 ? -1 : 0; ++ return msg_reply.payload.u64 ? -EIO : 0; + } + + static bool vhost_user_one_time_request(VhostUserRequest request) +@@ -475,14 +480,15 @@ static int vhost_user_write(struct vhost_dev *dev, VhostUserMsg *msg, + + if (qemu_chr_fe_set_msgfds(chr, fds, fd_num) < 0) { + error_report("Failed to set msg fds."); +- return -1; ++ return -EINVAL; + } + + ret = qemu_chr_fe_write_all(chr, (const uint8_t *) msg, size); + if (ret != size) { ++ int saved_errno = errno; + error_report("Failed to write msg." + " Wrote %d instead of %d.", ret, size); +- return -1; ++ return ret < 0 ? -saved_errno : -EIO; + } + + return 0; +@@ -505,6 +511,7 @@ static int vhost_user_set_log_base(struct vhost_dev *dev, uint64_t base, + size_t fd_num = 0; + bool shmfd = virtio_has_feature(dev->protocol_features, + VHOST_USER_PROTOCOL_F_LOG_SHMFD); ++ int ret; + VhostUserMsg msg = { + .hdr.request = VHOST_USER_SET_LOG_BASE, + .hdr.flags = VHOST_USER_VERSION, +@@ -517,21 +524,23 @@ static int vhost_user_set_log_base(struct vhost_dev *dev, uint64_t base, + fds[fd_num++] = log->fd; + } + +- if (vhost_user_write(dev, &msg, fds, fd_num) < 0) { +- return -1; ++ ret = vhost_user_write(dev, &msg, fds, fd_num); ++ if (ret < 0) { ++ return ret; + } + + if (shmfd) { + msg.hdr.size = 0; +- if (vhost_user_read(dev, &msg) < 0) { +- return -1; ++ ret = vhost_user_read(dev, &msg); ++ if (ret < 0) { ++ return ret; + } + + if (msg.hdr.request != VHOST_USER_SET_LOG_BASE) { + error_report("Received unexpected msg type. " + "Expected %d received %d", + VHOST_USER_SET_LOG_BASE, msg.hdr.request); +- return -1; ++ return -EPROTO; + } + } + +@@ -591,7 +600,7 @@ static int vhost_user_fill_set_mem_table_msg(struct vhost_user *u, + u->region_rb[i] = mr->ram_block; + } else if (*fd_num == VHOST_MEMORY_BASELINE_NREGIONS) { + error_report("Failed preparing vhost-user memory table msg"); +- return -1; ++ return -ENOBUFS; + } + vhost_user_fill_msg_region(®ion_buffer, reg, offset); + msg->payload.memory.regions[*fd_num] = region_buffer; +@@ -607,14 +616,14 @@ static int vhost_user_fill_set_mem_table_msg(struct vhost_user *u, + if (!*fd_num) { + error_report("Failed initializing vhost-user memory map, " + "consider using -object memory-backend-file share=on"); +- return -1; ++ return -EINVAL; + } + + msg->hdr.size = sizeof(msg->payload.memory.nregions); + msg->hdr.size += sizeof(msg->payload.memory.padding); + msg->hdr.size += *fd_num * sizeof(VhostUserMemoryRegion); + +- return 1; ++ return 0; + } + + static inline bool reg_equal(struct vhost_memory_region *shadow_reg, +@@ -744,8 +753,9 @@ static int send_remove_regions(struct vhost_dev *dev, + vhost_user_fill_msg_region(®ion_buffer, shadow_reg, 0); + msg->payload.mem_reg.region = region_buffer; + +- if (vhost_user_write(dev, msg, &fd, 1) < 0) { +- return -1; ++ ret = vhost_user_write(dev, msg, &fd, 1); ++ if (ret < 0) { ++ return ret; + } + + if (reply_supported) { +@@ -804,15 +814,17 @@ static int send_add_regions(struct vhost_dev *dev, + vhost_user_fill_msg_region(®ion_buffer, reg, offset); + msg->payload.mem_reg.region = region_buffer; + +- if (vhost_user_write(dev, msg, &fd, 1) < 0) { +- return -1; ++ ret = vhost_user_write(dev, msg, &fd, 1); ++ if (ret < 0) { ++ return ret; + } + + if (track_ramblocks) { + uint64_t reply_gpa; + +- if (vhost_user_read(dev, &msg_reply) < 0) { +- return -1; ++ ret = vhost_user_read(dev, &msg_reply); ++ if (ret < 0) { ++ return ret; + } + + reply_gpa = msg_reply.payload.mem_reg.region.guest_phys_addr; +@@ -822,7 +834,7 @@ static int send_add_regions(struct vhost_dev *dev, + "Expected %d received %d", __func__, + VHOST_USER_ADD_MEM_REG, + msg_reply.hdr.request); +- return -1; ++ return -EPROTO; + } + + /* +@@ -833,7 +845,7 @@ static int send_add_regions(struct vhost_dev *dev, + error_report("%s: Unexpected size for postcopy reply " + "%d vs %d", __func__, msg_reply.hdr.size, + msg->hdr.size); +- return -1; ++ return -EPROTO; + } + + /* Get the postcopy client base from the backend's reply. */ +@@ -849,7 +861,7 @@ static int send_add_regions(struct vhost_dev *dev, + "Got guest physical address %" PRIX64 ", expected " + "%" PRIX64, __func__, reply_gpa, + dev->mem->regions[reg_idx].guest_phys_addr); +- return -1; ++ return -EPROTO; + } + } else if (reply_supported) { + ret = process_message_reply(dev, msg); +@@ -890,6 +902,7 @@ static int vhost_user_add_remove_regions(struct vhost_dev *dev, + struct scrub_regions rem_reg[VHOST_USER_MAX_RAM_SLOTS]; + uint64_t shadow_pcb[VHOST_USER_MAX_RAM_SLOTS] = {}; + int nr_add_reg, nr_rem_reg; ++ int ret; + + msg->hdr.size = sizeof(msg->payload.mem_reg); + +@@ -897,16 +910,20 @@ static int vhost_user_add_remove_regions(struct vhost_dev *dev, + scrub_shadow_regions(dev, add_reg, &nr_add_reg, rem_reg, &nr_rem_reg, + shadow_pcb, track_ramblocks); + +- if (nr_rem_reg && send_remove_regions(dev, rem_reg, nr_rem_reg, msg, +- reply_supported) < 0) +- { +- goto err; ++ if (nr_rem_reg) { ++ ret = send_remove_regions(dev, rem_reg, nr_rem_reg, msg, ++ reply_supported); ++ if (ret < 0) { ++ goto err; ++ } + } + +- if (nr_add_reg && send_add_regions(dev, add_reg, nr_add_reg, msg, +- shadow_pcb, reply_supported, track_ramblocks) < 0) +- { +- goto err; ++ if (nr_add_reg) { ++ ret = send_add_regions(dev, add_reg, nr_add_reg, msg, shadow_pcb, ++ reply_supported, track_ramblocks); ++ if (ret < 0) { ++ goto err; ++ } + } + + if (track_ramblocks) { +@@ -921,8 +938,9 @@ static int vhost_user_add_remove_regions(struct vhost_dev *dev, + msg->hdr.size = sizeof(msg->payload.u64); + msg->payload.u64 = 0; /* OK */ + +- if (vhost_user_write(dev, msg, NULL, 0) < 0) { +- return -1; ++ ret = vhost_user_write(dev, msg, NULL, 0); ++ if (ret < 0) { ++ return ret; + } + } + +@@ -934,7 +952,7 @@ err: + sizeof(uint64_t) * VHOST_USER_MAX_RAM_SLOTS); + } + +- return -1; ++ return ret; + } + + static int vhost_user_set_mem_table_postcopy(struct vhost_dev *dev, +@@ -947,6 +965,7 @@ static int vhost_user_set_mem_table_postcopy(struct vhost_dev *dev, + size_t fd_num = 0; + VhostUserMsg msg_reply; + int region_i, msg_i; ++ int ret; + + VhostUserMsg msg = { + .hdr.flags = VHOST_USER_VERSION, +@@ -964,29 +983,32 @@ static int vhost_user_set_mem_table_postcopy(struct vhost_dev *dev, + } + + if (config_mem_slots) { +- if (vhost_user_add_remove_regions(dev, &msg, reply_supported, +- true) < 0) { +- return -1; ++ ret = vhost_user_add_remove_regions(dev, &msg, reply_supported, true); ++ if (ret < 0) { ++ return ret; + } + } else { +- if (vhost_user_fill_set_mem_table_msg(u, dev, &msg, fds, &fd_num, +- true) < 0) { +- return -1; ++ ret = vhost_user_fill_set_mem_table_msg(u, dev, &msg, fds, &fd_num, ++ true); ++ if (ret < 0) { ++ return ret; + } + +- if (vhost_user_write(dev, &msg, fds, fd_num) < 0) { +- return -1; ++ ret = vhost_user_write(dev, &msg, fds, fd_num); ++ if (ret < 0) { ++ return ret; + } + +- if (vhost_user_read(dev, &msg_reply) < 0) { +- return -1; ++ ret = vhost_user_read(dev, &msg_reply); ++ if (ret < 0) { ++ return ret; + } + + if (msg_reply.hdr.request != VHOST_USER_SET_MEM_TABLE) { + error_report("%s: Received unexpected msg type." + "Expected %d received %d", __func__, + VHOST_USER_SET_MEM_TABLE, msg_reply.hdr.request); +- return -1; ++ return -EPROTO; + } + + /* +@@ -997,7 +1019,7 @@ static int vhost_user_set_mem_table_postcopy(struct vhost_dev *dev, + error_report("%s: Unexpected size for postcopy reply " + "%d vs %d", __func__, msg_reply.hdr.size, + msg.hdr.size); +- return -1; ++ return -EPROTO; + } + + memset(u->postcopy_client_bases, 0, +@@ -1027,7 +1049,7 @@ static int vhost_user_set_mem_table_postcopy(struct vhost_dev *dev, + error_report("%s: postcopy reply not fully consumed " + "%d vs %zd", + __func__, msg_i, fd_num); +- return -1; ++ return -EIO; + } + + /* +@@ -1038,8 +1060,9 @@ static int vhost_user_set_mem_table_postcopy(struct vhost_dev *dev, + /* TODO: Use this for failure cases as well with a bad value. */ + msg.hdr.size = sizeof(msg.payload.u64); + msg.payload.u64 = 0; /* OK */ +- if (vhost_user_write(dev, &msg, NULL, 0) < 0) { +- return -1; ++ ret = vhost_user_write(dev, &msg, NULL, 0); ++ if (ret < 0) { ++ return ret; + } + } + +@@ -1058,6 +1081,7 @@ static int vhost_user_set_mem_table(struct vhost_dev *dev, + bool config_mem_slots = + virtio_has_feature(dev->protocol_features, + VHOST_USER_PROTOCOL_F_CONFIGURE_MEM_SLOTS); ++ int ret; + + if (do_postcopy) { + /* +@@ -1077,17 +1101,20 @@ static int vhost_user_set_mem_table(struct vhost_dev *dev, + } + + if (config_mem_slots) { +- if (vhost_user_add_remove_regions(dev, &msg, reply_supported, +- false) < 0) { +- return -1; ++ ret = vhost_user_add_remove_regions(dev, &msg, reply_supported, false); ++ if (ret < 0) { ++ return ret; + } + } else { +- if (vhost_user_fill_set_mem_table_msg(u, dev, &msg, fds, &fd_num, +- false) < 0) { +- return -1; ++ ret = vhost_user_fill_set_mem_table_msg(u, dev, &msg, fds, &fd_num, ++ false); ++ if (ret < 0) { ++ return ret; + } +- if (vhost_user_write(dev, &msg, fds, fd_num) < 0) { +- return -1; ++ ++ ret = vhost_user_write(dev, &msg, fds, fd_num); ++ if (ret < 0) { ++ return ret; + } + + if (reply_supported) { +@@ -1112,14 +1139,10 @@ static int vhost_user_set_vring_endian(struct vhost_dev *dev, + + if (!cross_endian) { + error_report("vhost-user trying to send unhandled ioctl"); +- return -1; ++ return -ENOTSUP; + } + +- if (vhost_user_write(dev, &msg, NULL, 0) < 0) { +- return -1; +- } +- +- return 0; ++ return vhost_user_write(dev, &msg, NULL, 0); + } + + static int vhost_set_vring(struct vhost_dev *dev, +@@ -1133,11 +1156,7 @@ static int vhost_set_vring(struct vhost_dev *dev, + .hdr.size = sizeof(msg.payload.state), + }; + +- if (vhost_user_write(dev, &msg, NULL, 0) < 0) { +- return -1; +- } +- +- return 0; ++ return vhost_user_write(dev, &msg, NULL, 0); + } + + static int vhost_user_set_vring_num(struct vhost_dev *dev, +@@ -1180,16 +1199,25 @@ static int vhost_user_set_vring_enable(struct vhost_dev *dev, int enable) + int i; + + if (!virtio_has_feature(dev->features, VHOST_USER_F_PROTOCOL_FEATURES)) { +- return -1; ++ return -EINVAL; + } + + for (i = 0; i < dev->nvqs; ++i) { ++ int ret; + struct vhost_vring_state state = { + .index = dev->vq_index + i, + .num = enable, + }; + +- vhost_set_vring(dev, VHOST_USER_SET_VRING_ENABLE, &state); ++ ret = vhost_set_vring(dev, VHOST_USER_SET_VRING_ENABLE, &state); ++ if (ret < 0) { ++ /* ++ * Restoring the previous state is likely infeasible, as well as ++ * proceeding regardless the error, so just bail out and hope for ++ * the device-level recovery. ++ */ ++ return ret; ++ } + } + + return 0; +@@ -1198,6 +1226,7 @@ static int vhost_user_set_vring_enable(struct vhost_dev *dev, int enable) + static int vhost_user_get_vring_base(struct vhost_dev *dev, + struct vhost_vring_state *ring) + { ++ int ret; + VhostUserMsg msg = { + .hdr.request = VHOST_USER_GET_VRING_BASE, + .hdr.flags = VHOST_USER_VERSION, +@@ -1208,23 +1237,25 @@ static int vhost_user_get_vring_base(struct vhost_dev *dev, + + vhost_user_host_notifier_remove(u->user, dev->vdev, ring->index); + +- if (vhost_user_write(dev, &msg, NULL, 0) < 0) { +- return -1; ++ ret = vhost_user_write(dev, &msg, NULL, 0); ++ if (ret < 0) { ++ return ret; + } + +- if (vhost_user_read(dev, &msg) < 0) { +- return -1; ++ ret = vhost_user_read(dev, &msg); ++ if (ret < 0) { ++ return ret; + } + + if (msg.hdr.request != VHOST_USER_GET_VRING_BASE) { + error_report("Received unexpected msg type. Expected %d received %d", + VHOST_USER_GET_VRING_BASE, msg.hdr.request); +- return -1; ++ return -EPROTO; + } + + if (msg.hdr.size != sizeof(msg.payload.state)) { + error_report("Received bad msg size."); +- return -1; ++ return -EPROTO; + } + + *ring = msg.payload.state; +@@ -1251,11 +1282,7 @@ static int vhost_set_vring_file(struct vhost_dev *dev, + msg.payload.u64 |= VHOST_USER_VRING_NOFD_MASK; + } + +- if (vhost_user_write(dev, &msg, fds, fd_num) < 0) { +- return -1; +- } +- +- return 0; ++ return vhost_user_write(dev, &msg, fds, fd_num); + } + + static int vhost_user_set_vring_kick(struct vhost_dev *dev, +@@ -1273,6 +1300,7 @@ static int vhost_user_set_vring_call(struct vhost_dev *dev, + + static int vhost_user_get_u64(struct vhost_dev *dev, int request, uint64_t *u64) + { ++ int ret; + VhostUserMsg msg = { + .hdr.request = request, + .hdr.flags = VHOST_USER_VERSION, +@@ -1282,23 +1310,25 @@ static int vhost_user_get_u64(struct vhost_dev *dev, int request, uint64_t *u64) + return 0; + } + +- if (vhost_user_write(dev, &msg, NULL, 0) < 0) { +- return -1; ++ ret = vhost_user_write(dev, &msg, NULL, 0); ++ if (ret < 0) { ++ return ret; + } + +- if (vhost_user_read(dev, &msg) < 0) { +- return -1; ++ ret = vhost_user_read(dev, &msg); ++ if (ret < 0) { ++ return ret; + } + + if (msg.hdr.request != request) { + error_report("Received unexpected msg type. Expected %d received %d", + request, msg.hdr.request); +- return -1; ++ return -EPROTO; + } + + if (msg.hdr.size != sizeof(msg.payload.u64)) { + error_report("Received bad msg size."); +- return -1; ++ return -EPROTO; + } + + *u64 = msg.payload.u64; +@@ -1336,6 +1366,7 @@ static int enforce_reply(struct vhost_dev *dev, + static int vhost_user_set_vring_addr(struct vhost_dev *dev, + struct vhost_vring_addr *addr) + { ++ int ret; + VhostUserMsg msg = { + .hdr.request = VHOST_USER_SET_VRING_ADDR, + .hdr.flags = VHOST_USER_VERSION, +@@ -1356,8 +1387,9 @@ static int vhost_user_set_vring_addr(struct vhost_dev *dev, + msg.hdr.flags |= VHOST_USER_NEED_REPLY_MASK; + } + +- if (vhost_user_write(dev, &msg, NULL, 0) < 0) { +- return -1; ++ ret = vhost_user_write(dev, &msg, NULL, 0); ++ if (ret < 0) { ++ return ret; + } + + if (wait_for_reply) { +@@ -1376,6 +1408,7 @@ static int vhost_user_set_u64(struct vhost_dev *dev, int request, uint64_t u64, + .payload.u64 = u64, + .hdr.size = sizeof(msg.payload.u64), + }; ++ int ret; + + if (wait_for_reply) { + bool reply_supported = virtio_has_feature(dev->protocol_features, +@@ -1385,8 +1418,9 @@ static int vhost_user_set_u64(struct vhost_dev *dev, int request, uint64_t u64, + } + } + +- if (vhost_user_write(dev, &msg, NULL, 0) < 0) { +- return -1; ++ ret = vhost_user_write(dev, &msg, NULL, 0); ++ if (ret < 0) { ++ return ret; + } + + if (wait_for_reply) { +@@ -1423,11 +1457,7 @@ static int vhost_user_set_owner(struct vhost_dev *dev) + .hdr.flags = VHOST_USER_VERSION, + }; + +- if (vhost_user_write(dev, &msg, NULL, 0) < 0) { +- return -EPROTO; +- } +- +- return 0; ++ return vhost_user_write(dev, &msg, NULL, 0); + } + + static int vhost_user_get_max_memslots(struct vhost_dev *dev, +@@ -1458,26 +1488,16 @@ static int vhost_user_reset_device(struct vhost_dev *dev) + ? VHOST_USER_RESET_DEVICE + : VHOST_USER_RESET_OWNER; + +- if (vhost_user_write(dev, &msg, NULL, 0) < 0) { +- return -1; +- } +- +- return 0; ++ return vhost_user_write(dev, &msg, NULL, 0); + } + + static int vhost_user_slave_handle_config_change(struct vhost_dev *dev) + { +- int ret = -1; +- +- if (!dev->config_ops) { +- return -1; ++ if (!dev->config_ops || !dev->config_ops->vhost_dev_config_notifier) { ++ return -ENOSYS; + } + +- if (dev->config_ops->vhost_dev_config_notifier) { +- ret = dev->config_ops->vhost_dev_config_notifier(dev); +- } +- +- return ret; ++ return dev->config_ops->vhost_dev_config_notifier(dev); + } + + static int vhost_user_slave_handle_vring_host_notifier(struct vhost_dev *dev, +@@ -1496,7 +1516,7 @@ static int vhost_user_slave_handle_vring_host_notifier(struct vhost_dev *dev, + if (!virtio_has_feature(dev->protocol_features, + VHOST_USER_PROTOCOL_F_HOST_NOTIFIER) || + vdev == NULL || queue_idx >= virtio_get_num_queues(vdev)) { +- return -1; ++ return -EINVAL; + } + + n = &user->notifier[queue_idx]; +@@ -1509,13 +1529,13 @@ static int vhost_user_slave_handle_vring_host_notifier(struct vhost_dev *dev, + + /* Sanity check. */ + if (area->size != page_size) { +- return -1; ++ return -EINVAL; + } + + addr = mmap(NULL, page_size, PROT_READ | PROT_WRITE, MAP_SHARED, + fd, area->offset); + if (addr == MAP_FAILED) { +- return -1; ++ return -EFAULT; + } + + name = g_strdup_printf("vhost-user/host-notifier@%p mmaps[%d]", +@@ -1531,7 +1551,7 @@ static int vhost_user_slave_handle_vring_host_notifier(struct vhost_dev *dev, + if (virtio_queue_set_host_notifier_mr(vdev, queue_idx, &n->mr, true)) { + object_unparent(OBJECT(&n->mr)); + munmap(addr, page_size); +- return -1; ++ return -ENXIO; + } + + n->addr = addr; +@@ -1660,14 +1680,15 @@ static int vhost_setup_slave_channel(struct vhost_dev *dev) + } + + if (socketpair(PF_UNIX, SOCK_STREAM, 0, sv) == -1) { ++ int saved_errno = errno; + error_report("socketpair() failed"); +- return -1; ++ return -saved_errno; + } + + ioc = QIO_CHANNEL(qio_channel_socket_new_fd(sv[0], &local_err)); + if (!ioc) { + error_report_err(local_err); +- return -1; ++ return -ECONNREFUSED; + } + u->slave_ioc = ioc; + slave_update_read_handler(dev, NULL); +@@ -1774,35 +1795,38 @@ static int vhost_user_postcopy_advise(struct vhost_dev *dev, Error **errp) + struct vhost_user *u = dev->opaque; + CharBackend *chr = u->user->chr; + int ufd; ++ int ret; + VhostUserMsg msg = { + .hdr.request = VHOST_USER_POSTCOPY_ADVISE, + .hdr.flags = VHOST_USER_VERSION, + }; + +- if (vhost_user_write(dev, &msg, NULL, 0) < 0) { ++ ret = vhost_user_write(dev, &msg, NULL, 0); ++ if (ret < 0) { + error_setg(errp, "Failed to send postcopy_advise to vhost"); +- return -1; ++ return ret; + } + +- if (vhost_user_read(dev, &msg) < 0) { ++ ret = vhost_user_read(dev, &msg); ++ if (ret < 0) { + error_setg(errp, "Failed to get postcopy_advise reply from vhost"); +- return -1; ++ return ret; + } + + if (msg.hdr.request != VHOST_USER_POSTCOPY_ADVISE) { + error_setg(errp, "Unexpected msg type. Expected %d received %d", + VHOST_USER_POSTCOPY_ADVISE, msg.hdr.request); +- return -1; ++ return -EPROTO; + } + + if (msg.hdr.size) { + error_setg(errp, "Received bad msg size."); +- return -1; ++ return -EPROTO; + } + ufd = qemu_chr_fe_get_msgfd(chr); + if (ufd < 0) { + error_setg(errp, "%s: Failed to get ufd", __func__); +- return -1; ++ return -EIO; + } + qemu_set_nonblock(ufd); + +@@ -1816,7 +1840,7 @@ static int vhost_user_postcopy_advise(struct vhost_dev *dev, Error **errp) + return 0; + #else + error_setg(errp, "Postcopy not supported on non-Linux systems"); +- return -1; ++ return -ENOSYS; + #endif + } + +@@ -1832,10 +1856,13 @@ static int vhost_user_postcopy_listen(struct vhost_dev *dev, Error **errp) + .hdr.flags = VHOST_USER_VERSION | VHOST_USER_NEED_REPLY_MASK, + }; + u->postcopy_listen = true; ++ + trace_vhost_user_postcopy_listen(); +- if (vhost_user_write(dev, &msg, NULL, 0) < 0) { ++ ++ ret = vhost_user_write(dev, &msg, NULL, 0); ++ if (ret < 0) { + error_setg(errp, "Failed to send postcopy_listen to vhost"); +- return -1; ++ return ret; + } + + ret = process_message_reply(dev, &msg); +@@ -1860,9 +1887,11 @@ static int vhost_user_postcopy_end(struct vhost_dev *dev, Error **errp) + struct vhost_user *u = dev->opaque; + + trace_vhost_user_postcopy_end_entry(); +- if (vhost_user_write(dev, &msg, NULL, 0) < 0) { ++ ++ ret = vhost_user_write(dev, &msg, NULL, 0); ++ if (ret < 0) { + error_setg(errp, "Failed to send postcopy_end to vhost"); +- return -1; ++ return ret; + } + + ret = process_message_reply(dev, &msg); +@@ -2141,7 +2170,7 @@ static int vhost_user_migration_done(struct vhost_dev *dev, char* mac_addr) + + return vhost_user_write(dev, &msg, NULL, 0); + } +- return -1; ++ return -ENOTSUP; + } + + static bool vhost_user_can_merge(struct vhost_dev *dev, +@@ -2162,6 +2191,7 @@ static int vhost_user_net_set_mtu(struct vhost_dev *dev, uint16_t mtu) + VhostUserMsg msg; + bool reply_supported = virtio_has_feature(dev->protocol_features, + VHOST_USER_PROTOCOL_F_REPLY_ACK); ++ int ret; + + if (!(dev->protocol_features & (1ULL << VHOST_USER_PROTOCOL_F_NET_MTU))) { + return 0; +@@ -2175,8 +2205,9 @@ static int vhost_user_net_set_mtu(struct vhost_dev *dev, uint16_t mtu) + msg.hdr.flags |= VHOST_USER_NEED_REPLY_MASK; + } + +- if (vhost_user_write(dev, &msg, NULL, 0) < 0) { +- return -1; ++ ret = vhost_user_write(dev, &msg, NULL, 0); ++ if (ret < 0) { ++ return ret; + } + + /* If reply_ack supported, slave has to ack specified MTU is valid */ +@@ -2190,6 +2221,7 @@ static int vhost_user_net_set_mtu(struct vhost_dev *dev, uint16_t mtu) + static int vhost_user_send_device_iotlb_msg(struct vhost_dev *dev, + struct vhost_iotlb_msg *imsg) + { ++ int ret; + VhostUserMsg msg = { + .hdr.request = VHOST_USER_IOTLB_MSG, + .hdr.size = sizeof(msg.payload.iotlb), +@@ -2197,8 +2229,9 @@ static int vhost_user_send_device_iotlb_msg(struct vhost_dev *dev, + .payload.iotlb = *imsg, + }; + +- if (vhost_user_write(dev, &msg, NULL, 0) < 0) { +- return -EFAULT; ++ ret = vhost_user_write(dev, &msg, NULL, 0); ++ if (ret < 0) { ++ return ret; + } + + return process_message_reply(dev, &msg); +@@ -2213,6 +2246,7 @@ static void vhost_user_set_iotlb_callback(struct vhost_dev *dev, int enabled) + static int vhost_user_get_config(struct vhost_dev *dev, uint8_t *config, + uint32_t config_len, Error **errp) + { ++ int ret; + VhostUserMsg msg = { + .hdr.request = VHOST_USER_GET_CONFIG, + .hdr.flags = VHOST_USER_VERSION, +@@ -2229,26 +2263,28 @@ static int vhost_user_get_config(struct vhost_dev *dev, uint8_t *config, + + msg.payload.config.offset = 0; + msg.payload.config.size = config_len; +- if (vhost_user_write(dev, &msg, NULL, 0) < 0) { +- error_setg_errno(errp, EPROTO, "vhost_get_config failed"); +- return -EPROTO; ++ ret = vhost_user_write(dev, &msg, NULL, 0); ++ if (ret < 0) { ++ error_setg_errno(errp, -ret, "vhost_get_config failed"); ++ return ret; + } + +- if (vhost_user_read(dev, &msg) < 0) { +- error_setg_errno(errp, EPROTO, "vhost_get_config failed"); +- return -EPROTO; ++ ret = vhost_user_read(dev, &msg); ++ if (ret < 0) { ++ error_setg_errno(errp, -ret, "vhost_get_config failed"); ++ return ret; + } + + if (msg.hdr.request != VHOST_USER_GET_CONFIG) { + error_setg(errp, + "Received unexpected msg type. Expected %d received %d", + VHOST_USER_GET_CONFIG, msg.hdr.request); +- return -EINVAL; ++ return -EPROTO; + } + + if (msg.hdr.size != VHOST_USER_CONFIG_HDR_SIZE + config_len) { + error_setg(errp, "Received bad msg size."); +- return -EINVAL; ++ return -EPROTO; + } + + memcpy(config, msg.payload.config.region, config_len); +@@ -2259,6 +2295,7 @@ static int vhost_user_get_config(struct vhost_dev *dev, uint8_t *config, + static int vhost_user_set_config(struct vhost_dev *dev, const uint8_t *data, + uint32_t offset, uint32_t size, uint32_t flags) + { ++ int ret; + uint8_t *p; + bool reply_supported = virtio_has_feature(dev->protocol_features, + VHOST_USER_PROTOCOL_F_REPLY_ACK); +@@ -2271,7 +2308,7 @@ static int vhost_user_set_config(struct vhost_dev *dev, const uint8_t *data, + + if (!virtio_has_feature(dev->protocol_features, + VHOST_USER_PROTOCOL_F_CONFIG)) { +- return -1; ++ return -ENOTSUP; + } + + if (reply_supported) { +@@ -2279,7 +2316,7 @@ static int vhost_user_set_config(struct vhost_dev *dev, const uint8_t *data, + } + + if (size > VHOST_USER_MAX_CONFIG_SIZE) { +- return -1; ++ return -EINVAL; + } + + msg.payload.config.offset = offset, +@@ -2288,8 +2325,9 @@ static int vhost_user_set_config(struct vhost_dev *dev, const uint8_t *data, + p = msg.payload.config.region; + memcpy(p, data, size); + +- if (vhost_user_write(dev, &msg, NULL, 0) < 0) { +- return -1; ++ ret = vhost_user_write(dev, &msg, NULL, 0); ++ if (ret < 0) { ++ return ret; + } + + if (reply_supported) { +@@ -2303,6 +2341,7 @@ static int vhost_user_crypto_create_session(struct vhost_dev *dev, + void *session_info, + uint64_t *session_id) + { ++ int ret; + bool crypto_session = virtio_has_feature(dev->protocol_features, + VHOST_USER_PROTOCOL_F_CRYPTO_SESSION); + CryptoDevBackendSymSessionInfo *sess_info = session_info; +@@ -2316,7 +2355,7 @@ static int vhost_user_crypto_create_session(struct vhost_dev *dev, + + if (!crypto_session) { + error_report("vhost-user trying to send unhandled ioctl"); +- return -1; ++ return -ENOTSUP; + } + + memcpy(&msg.payload.session.session_setup_data, sess_info, +@@ -2329,31 +2368,35 @@ static int vhost_user_crypto_create_session(struct vhost_dev *dev, + memcpy(&msg.payload.session.auth_key, sess_info->auth_key, + sess_info->auth_key_len); + } +- if (vhost_user_write(dev, &msg, NULL, 0) < 0) { +- error_report("vhost_user_write() return -1, create session failed"); +- return -1; ++ ret = vhost_user_write(dev, &msg, NULL, 0); ++ if (ret < 0) { ++ error_report("vhost_user_write() return %d, create session failed", ++ ret); ++ return ret; + } + +- if (vhost_user_read(dev, &msg) < 0) { +- error_report("vhost_user_read() return -1, create session failed"); +- return -1; ++ ret = vhost_user_read(dev, &msg); ++ if (ret < 0) { ++ error_report("vhost_user_read() return %d, create session failed", ++ ret); ++ return ret; + } + + if (msg.hdr.request != VHOST_USER_CREATE_CRYPTO_SESSION) { + error_report("Received unexpected msg type. Expected %d received %d", + VHOST_USER_CREATE_CRYPTO_SESSION, msg.hdr.request); +- return -1; ++ return -EPROTO; + } + + if (msg.hdr.size != sizeof(msg.payload.session)) { + error_report("Received bad msg size."); +- return -1; ++ return -EPROTO; + } + + if (msg.payload.session.session_id < 0) { + error_report("Bad session id: %" PRId64 "", + msg.payload.session.session_id); +- return -1; ++ return -EINVAL; + } + *session_id = msg.payload.session.session_id; + +@@ -2363,6 +2406,7 @@ static int vhost_user_crypto_create_session(struct vhost_dev *dev, + static int + vhost_user_crypto_close_session(struct vhost_dev *dev, uint64_t session_id) + { ++ int ret; + bool crypto_session = virtio_has_feature(dev->protocol_features, + VHOST_USER_PROTOCOL_F_CRYPTO_SESSION); + VhostUserMsg msg = { +@@ -2374,12 +2418,14 @@ vhost_user_crypto_close_session(struct vhost_dev *dev, uint64_t session_id) + + if (!crypto_session) { + error_report("vhost-user trying to send unhandled ioctl"); +- return -1; ++ return -ENOTSUP; + } + +- if (vhost_user_write(dev, &msg, NULL, 0) < 0) { +- error_report("vhost_user_write() return -1, close session failed"); +- return -1; ++ ret = vhost_user_write(dev, &msg, NULL, 0); ++ if (ret < 0) { ++ error_report("vhost_user_write() return %d, close session failed", ++ ret); ++ return ret; + } + + return 0; +@@ -2401,6 +2447,7 @@ static int vhost_user_get_inflight_fd(struct vhost_dev *dev, + { + void *addr; + int fd; ++ int ret; + struct vhost_user *u = dev->opaque; + CharBackend *chr = u->user->chr; + VhostUserMsg msg = { +@@ -2416,24 +2463,26 @@ static int vhost_user_get_inflight_fd(struct vhost_dev *dev, + return 0; + } + +- if (vhost_user_write(dev, &msg, NULL, 0) < 0) { +- return -1; ++ ret = vhost_user_write(dev, &msg, NULL, 0); ++ if (ret < 0) { ++ return ret; + } + +- if (vhost_user_read(dev, &msg) < 0) { +- return -1; ++ ret = vhost_user_read(dev, &msg); ++ if (ret < 0) { ++ return ret; + } + + if (msg.hdr.request != VHOST_USER_GET_INFLIGHT_FD) { + error_report("Received unexpected msg type. " + "Expected %d received %d", + VHOST_USER_GET_INFLIGHT_FD, msg.hdr.request); +- return -1; ++ return -EPROTO; + } + + if (msg.hdr.size != sizeof(msg.payload.inflight)) { + error_report("Received bad msg size."); +- return -1; ++ return -EPROTO; + } + + if (!msg.payload.inflight.mmap_size) { +@@ -2443,7 +2492,7 @@ static int vhost_user_get_inflight_fd(struct vhost_dev *dev, + fd = qemu_chr_fe_get_msgfd(chr); + if (fd < 0) { + error_report("Failed to get mem fd"); +- return -1; ++ return -EIO; + } + + addr = mmap(0, msg.payload.inflight.mmap_size, PROT_READ | PROT_WRITE, +@@ -2452,7 +2501,7 @@ static int vhost_user_get_inflight_fd(struct vhost_dev *dev, + if (addr == MAP_FAILED) { + error_report("Failed to mmap mem fd"); + close(fd); +- return -1; ++ return -EFAULT; + } + + inflight->addr = addr; +@@ -2482,11 +2531,7 @@ static int vhost_user_set_inflight_fd(struct vhost_dev *dev, + return 0; + } + +- if (vhost_user_write(dev, &msg, &inflight->fd, 1) < 0) { +- return -1; +- } +- +- return 0; ++ return vhost_user_write(dev, &msg, &inflight->fd, 1); + } + + bool vhost_user_init(VhostUserState *user, CharBackend *chr, Error **errp) +-- +2.27.0 + diff --git a/vhost-vdpa-add-support-for-config-interrupt-new.patch b/vhost-vdpa-add-support-for-config-interrupt-new.patch new file mode 100644 index 00000000..9d673955 --- /dev/null +++ b/vhost-vdpa-add-support-for-config-interrupt-new.patch @@ -0,0 +1,62 @@ +From 1a5b6648f563f7991fba0c4cb07a3a4d05834c83 Mon Sep 17 00:00:00 2001 +From: Cindy Lu +Date: Thu, 22 Dec 2022 15:04:46 +0800 +Subject: [PATCH] vhost-vdpa: add support for config interrupt + +Add new call back function in vhost-vdpa, The function +vhost_set_config_call can set the event fd to kernel. +This function will be called in the vhost_dev_start +and vhost_dev_stop + +Signed-off-by: Cindy Lu +Message-Id: <20221222070451.936503-6-lulu@redhat.com> +Acked-by: Jason Wang +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Signed-off-by: fangyi +--- + hw/virtio/trace-events | 1 + + hw/virtio/vhost-vdpa.c | 8 ++++++++ + 2 files changed, 9 insertions(+) + +diff --git a/hw/virtio/trace-events b/hw/virtio/trace-events +index edbbbeb621..0396518241 100644 +--- a/hw/virtio/trace-events ++++ b/hw/virtio/trace-events +@@ -61,6 +61,7 @@ vhost_vdpa_get_features(void *dev, uint64_t features) "dev: %p features: 0x%"PRI + vhost_vdpa_set_owner(void *dev) "dev: %p" + vhost_vdpa_vq_get_addr(void *dev, void *vq, uint64_t desc_user_addr, uint64_t avail_user_addr, uint64_t used_user_addr) "dev: %p vq: %p desc_user_addr: 0x%"PRIx64" avail_user_addr: 0x%"PRIx64" used_user_addr: 0x%"PRIx64 + vhost_vdpa_get_iova_range(void *dev, uint64_t first, uint64_t last) "dev: %p first: 0x%"PRIx64" last: 0x%"PRIx64 ++vhost_vdpa_set_config_call(void *dev, int fd)"dev: %p fd: %d" + + # virtio.c + virtqueue_alloc_element(void *elem, size_t sz, unsigned in_num, unsigned out_num) "elem %p size %zd in_num %u out_num %u" +diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c +index 8b44f5a7b8..c9289e2c01 100644 +--- a/hw/virtio/vhost-vdpa.c ++++ b/hw/virtio/vhost-vdpa.c +@@ -719,6 +719,13 @@ static int vhost_vdpa_set_vring_ready(struct vhost_dev *dev) + return 0; + } + ++static int vhost_vdpa_set_config_call(struct vhost_dev *dev, ++ int fd) ++{ ++ trace_vhost_vdpa_set_config_call(dev, fd); ++ return vhost_vdpa_call(dev, VHOST_VDPA_SET_CONFIG_CALL, &fd); ++} ++ + static void vhost_vdpa_dump_config(struct vhost_dev *dev, const uint8_t *config, + uint32_t config_len) + { +@@ -1311,6 +1318,7 @@ const VhostOps vdpa_ops = { + .vhost_get_device_id = vhost_vdpa_get_device_id, + .vhost_vq_get_addr = vhost_vdpa_vq_get_addr, + .vhost_force_iommu = vhost_vdpa_force_iommu, ++ .vhost_set_config_call = vhost_vdpa_set_config_call, + .vhost_set_used_memslots = vhost_vdpa_set_used_memslots, + .vhost_get_used_memslots = vhost_vdpa_get_used_memslots, + }; +-- +2.27.0 + diff --git a/vhost-vdpa-add-support-for-config-interrupt.patch b/vhost-vdpa-add-support-for-config-interrupt.patch new file mode 100644 index 00000000..f154b19a --- /dev/null +++ b/vhost-vdpa-add-support-for-config-interrupt.patch @@ -0,0 +1,59 @@ +From cc9df379f703274eb600dd6af7dbacae4d457d5f Mon Sep 17 00:00:00 2001 +From: fangyi +Date: Thu, 16 Nov 2023 09:54:51 +0800 +Subject: [PATCH] vhost-vdpa: add support for config interrupt + +Add new call back function in vhost-vdpa, this function will +set the event fd to kernel. This function will be called +in the vhost_dev_start and vhost_dev_stop + +Signed-off-by: Cindy Lu +Message-Id: <20211104164827.21911-6-lulu@redhat.com> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Signed-off-by: fangyi +--- + hw/virtio/trace-events | 1 + + hw/virtio/vhost-vdpa.c | 7 +++++++ + 2 files changed, 8 insertions(+) + +diff --git a/hw/virtio/trace-events b/hw/virtio/trace-events +index 650e521e35..39c36ff7a6 100644 +--- a/hw/virtio/trace-events ++++ b/hw/virtio/trace-events +@@ -53,6 +53,7 @@ vhost_vdpa_get_features(void *dev, uint64_t features) "dev: %p features: 0x%"PRI + vhost_vdpa_set_owner(void *dev) "dev: %p" + vhost_vdpa_vq_get_addr(void *dev, void *vq, uint64_t desc_user_addr, uint64_t avail_user_addr, uint64_t used_user_addr) "dev: %p vq: %p desc_user_addr: 0x%"PRIx64" avail_user_addr: 0x%"PRIx64" used_user_addr: 0x%"PRIx64 + vhost_vdpa_get_iova_range(void *dev, uint64_t first, uint64_t last) "dev: %p first: 0x%"PRIx64" last: 0x%"PRIx64 ++vhost_vdpa_set_config_call(void *dev, int fd)"dev: %p fd: %d" + + # virtio.c + virtqueue_alloc_element(void *elem, size_t sz, unsigned in_num, unsigned out_num) "elem %p size %zd in_num %u out_num %u" +diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c +index 287025ef93..b7bbd65cdd 100644 +--- a/hw/virtio/vhost-vdpa.c ++++ b/hw/virtio/vhost-vdpa.c +@@ -728,6 +728,12 @@ static int vhost_vdpa_set_vring_call(struct vhost_dev *dev, + trace_vhost_vdpa_set_vring_call(dev, file->index, file->fd); + return vhost_vdpa_call(dev, VHOST_SET_VRING_CALL, file); + } ++static int vhost_vdpa_set_config_call(struct vhost_dev *dev, ++ int fd) ++{ ++ trace_vhost_vdpa_set_config_call(dev, fd); ++ return vhost_vdpa_call(dev, VHOST_VDPA_SET_CONFIG_CALL, &fd); ++} + + static int vhost_vdpa_get_features(struct vhost_dev *dev, + uint64_t *features) +@@ -808,6 +814,7 @@ const VhostOps vdpa_ops = { + .vhost_get_device_id = vhost_vdpa_get_device_id, + .vhost_vq_get_addr = vhost_vdpa_vq_get_addr, + .vhost_force_iommu = vhost_vdpa_force_iommu, ++ .vhost_set_config_call = vhost_vdpa_set_config_call, + .vhost_set_used_memslots = vhost_vdpa_set_used_memslots, + .vhost_get_used_memslots = vhost_vdpa_get_used_memslots, + }; +-- +2.27.0 + diff --git a/vhost-vdpa-allow-passing-opened-vhostfd-to-vhost-vdp.patch b/vhost-vdpa-allow-passing-opened-vhostfd-to-vhost-vdp.patch new file mode 100644 index 00000000..c17fb9d8 --- /dev/null +++ b/vhost-vdpa-allow-passing-opened-vhostfd-to-vhost-vdp.patch @@ -0,0 +1,114 @@ +From 2feaf4260eae797c518c86d181f24eca5948b8b0 Mon Sep 17 00:00:00 2001 +From: Si-Wei Liu +Date: Sat, 8 Oct 2022 00:58:58 -0700 +Subject: [PATCH] vhost-vdpa: allow passing opened vhostfd to vhost-vdpa +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Similar to other vhost backends, vhostfd can be passed to vhost-vdpa +backend as another parameter to instantiate vhost-vdpa net client. +This would benefit the use case where only open file descriptors, as +opposed to raw vhost-vdpa device paths, are accessible from the QEMU +process. + +(qemu) netdev_add type=vhost-vdpa,vhostfd=61,id=vhost-vdpa1 + +Signed-off-by: Si-Wei Liu +Acked-by: Eugenio Pérez +Signed-off-by: Jason Wang +Signed-off-by: fangyi +--- + net/vhost-vdpa.c | 25 ++++++++++++++++++++----- + qapi/net.json | 3 +++ + qemu-options.hx | 6 ++++-- + 3 files changed, 27 insertions(+), 7 deletions(-) + +diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c +index c8c433002d..58225649f9 100644 +--- a/net/vhost-vdpa.c ++++ b/net/vhost-vdpa.c +@@ -642,14 +642,29 @@ int net_init_vhost_vdpa(const Netdev *netdev, const char *name, + + assert(netdev->type == NET_CLIENT_DRIVER_VHOST_VDPA); + opts = &netdev->u.vhost_vdpa; +- if (!opts->vhostdev) { +- error_setg(errp, "vdpa character device not specified with vhostdev"); ++ if (!opts->has_vhostdev && !opts->has_vhostfd) { ++ error_setg(errp, ++ "vhost-vdpa: neither vhostdev= nor vhostfd= was specified"); + return -1; + } + +- vdpa_device_fd = qemu_open(opts->vhostdev, O_RDWR, errp); +- if (vdpa_device_fd == -1) { +- return -errno; ++ if (opts->has_vhostdev && opts->has_vhostfd) { ++ error_setg(errp, ++ "vhost-vdpa: vhostdev= and vhostfd= are mutually exclusive"); ++ return -1; ++ } ++ ++ if (opts->has_vhostdev) { ++ vdpa_device_fd = qemu_open(opts->vhostdev, O_RDWR, errp); ++ if (vdpa_device_fd == -1) { ++ return -errno; ++ } ++ } else if (opts->has_vhostfd) { ++ vdpa_device_fd = monitor_fd_param(monitor_cur(), opts->vhostfd, errp); ++ if (vdpa_device_fd == -1) { ++ error_prepend(errp, "vhost-vdpa: unable to parse vhostfd: "); ++ return -1; ++ } + } + + r = vhost_vdpa_get_features(vdpa_device_fd, &features, errp); +diff --git a/qapi/net.json b/qapi/net.json +index 6a5460ce56..a38a7b611b 100644 +--- a/qapi/net.json ++++ b/qapi/net.json +@@ -442,6 +442,8 @@ + # @vhostdev: path of vhost-vdpa device + # (default:'/dev/vhost-vdpa-0') + # ++# @vhostfd: file descriptor of an already opened vhost vdpa device ++# + # @queues: number of queues to be created for multiqueue vhost-vdpa + # (default: 1) + # +@@ -456,6 +458,7 @@ + { 'struct': 'NetdevVhostVDPAOptions', + 'data': { + '*vhostdev': 'str', ++ '*vhostfd': 'str', + '*queues': 'int', + '*x-svq': {'type': 'bool', 'features' : [ 'unstable'] } } } + +diff --git a/qemu-options.hx b/qemu-options.hx +index e329ec58ca..e25b76771d 100644 +--- a/qemu-options.hx ++++ b/qemu-options.hx +@@ -2739,8 +2739,10 @@ DEF("netdev", HAS_ARG, QEMU_OPTION_netdev, + " configure a vhost-user network, backed by a chardev 'dev'\n" + #endif + #ifdef __linux__ +- "-netdev vhost-vdpa,id=str,vhostdev=/path/to/dev\n" ++ "-netdev vhost-vdpa,id=str[,vhostdev=/path/to/dev][,vhostfd=h]\n" + " configure a vhost-vdpa network,Establish a vhost-vdpa netdev\n" ++ " use 'vhostdev=/path/to/dev' to open a vhost vdpa device\n" ++ " use 'vhostfd=h' to connect to an already opened vhost vdpa device\n" + #endif + "-netdev hubport,id=str,hubid=n[,netdev=nd]\n" + " configure a hub port on the hub with ID 'n'\n", QEMU_ARCH_ALL) +@@ -3220,7 +3222,7 @@ SRST + -netdev type=vhost-user,id=net0,chardev=chr0 \ + -device virtio-net-pci,netdev=net0 + +-``-netdev vhost-vdpa,vhostdev=/path/to/dev`` ++``-netdev vhost-vdpa[,vhostdev=/path/to/dev][,vhostfd=h]`` + Establish a vhost-vdpa netdev. + + vDPA device is a device that uses a datapath which complies with +-- +2.27.0 + diff --git a/vhost-vdpa-backend-feature-should-set-only-once.patch b/vhost-vdpa-backend-feature-should-set-only-once.patch new file mode 100644 index 00000000..b14e65f8 --- /dev/null +++ b/vhost-vdpa-backend-feature-should-set-only-once.patch @@ -0,0 +1,49 @@ +From a089328f183371ec7f7cd641f46beeeea2c9decc Mon Sep 17 00:00:00 2001 +From: Si-Wei Liu +Date: Fri, 6 May 2022 19:28:16 -0700 +Subject: [PATCH] vhost-vdpa: backend feature should set only once +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The vhost_vdpa_one_time_request() branch in +vhost_vdpa_set_backend_cap() incorrectly sends down +ioctls on vhost_dev with non-zero index. This may +end up with multiple VHOST_SET_BACKEND_FEATURES +ioctl calls sent down on the vhost-vdpa fd that is +shared between all these vhost_dev's. + +To fix it, send down ioctl only once via the first +vhost_dev with index 0. Toggle the polarity of the +vhost_vdpa_one_time_request() test should do the +trick. + +Fixes: 4d191cfdc7de ("vhost-vdpa: classify one time request") +Signed-off-by: Si-Wei Liu +Reviewed-by: Stefano Garzarella +Acked-by: Jason Wang +Acked-by: Eugenio Pérez +Message-Id: <1651890498-24478-6-git-send-email-si-wei.liu@oracle.com> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Signed-off-by: fangyi +--- + hw/virtio/vhost-vdpa.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c +index 1360f2eaf7..cb74d71b80 100644 +--- a/hw/virtio/vhost-vdpa.c ++++ b/hw/virtio/vhost-vdpa.c +@@ -669,7 +669,7 @@ static int vhost_vdpa_set_backend_cap(struct vhost_dev *dev) + + features &= f; + +- if (vhost_vdpa_one_time_request(dev)) { ++ if (!vhost_vdpa_one_time_request(dev)) { + r = vhost_vdpa_call(dev, VHOST_SET_BACKEND_FEATURES, &features); + if (r) { + return -EFAULT; +-- +2.27.0 + diff --git a/vhost-vdpa-change-name-and-polarity-for-vhost_vdpa_o.patch b/vhost-vdpa-change-name-and-polarity-for-vhost_vdpa_o.patch new file mode 100644 index 00000000..3c67ccd0 --- /dev/null +++ b/vhost-vdpa-change-name-and-polarity-for-vhost_vdpa_o.patch @@ -0,0 +1,111 @@ +From fdf8d168adeac8e91bb61d4940756af0df3b8d2c Mon Sep 17 00:00:00 2001 +From: Si-Wei Liu +Date: Fri, 6 May 2022 19:28:17 -0700 +Subject: [PATCH] vhost-vdpa: change name and polarity for + vhost_vdpa_one_time_request() + +The name vhost_vdpa_one_time_request() was confusing. No +matter whatever it returns, its typical occurrence had +always been at requests that only need to be applied once. +And the name didn't suggest what it actually checks for. +Change it to vhost_vdpa_first_dev() with polarity flipped +for better readibility of code. That way it is able to +reflect what the check is really about. + +This call is applicable to request which performs operation +only once, before queues are set up, and usually at the beginning +of the caller function. Document the requirement for it in place. + +Signed-off-by: Si-Wei Liu +Message-Id: <1651890498-24478-7-git-send-email-si-wei.liu@oracle.com> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Reviewed-by: Stefano Garzarella +Acked-by: Jason Wang +Signed-off-by: fangyi +--- + hw/virtio/vhost-vdpa.c | 23 +++++++++++++++-------- + 1 file changed, 15 insertions(+), 8 deletions(-) + +diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c +index cb74d71b80..73ff599f2b 100644 +--- a/hw/virtio/vhost-vdpa.c ++++ b/hw/virtio/vhost-vdpa.c +@@ -370,11 +370,18 @@ static void vhost_vdpa_get_iova_range(struct vhost_vdpa *v) + v->iova_range.last); + } + +-static bool vhost_vdpa_one_time_request(struct vhost_dev *dev) ++/* ++ * The use of this function is for requests that only need to be ++ * applied once. Typically such request occurs at the beginning ++ * of operation, and before setting up queues. It should not be ++ * used for request that performs operation until all queues are ++ * set, which would need to check dev->vq_index_end instead. ++ */ ++static bool vhost_vdpa_first_dev(struct vhost_dev *dev) + { + struct vhost_vdpa *v = dev->opaque; + +- return v->index != 0; ++ return v->index == 0; + } + + static int vhost_vdpa_get_dev_features(struct vhost_dev *dev, +@@ -455,7 +462,7 @@ static int vhost_vdpa_init(struct vhost_dev *dev, void *opaque, Error **errp) + + vhost_vdpa_get_iova_range(v); + +- if (vhost_vdpa_one_time_request(dev)) { ++ if (!vhost_vdpa_first_dev(dev)) { + return 0; + } + +@@ -598,7 +605,7 @@ static int vhost_vdpa_memslots_limit(struct vhost_dev *dev) + static int vhost_vdpa_set_mem_table(struct vhost_dev *dev, + struct vhost_memory *mem) + { +- if (vhost_vdpa_one_time_request(dev)) { ++ if (!vhost_vdpa_first_dev(dev)) { + return 0; + } + +@@ -627,7 +634,7 @@ static int vhost_vdpa_set_features(struct vhost_dev *dev, + struct vhost_vdpa *v = dev->opaque; + int ret; + +- if (vhost_vdpa_one_time_request(dev)) { ++ if (!vhost_vdpa_first_dev(dev)) { + return 0; + } + +@@ -669,7 +676,7 @@ static int vhost_vdpa_set_backend_cap(struct vhost_dev *dev) + + features &= f; + +- if (!vhost_vdpa_one_time_request(dev)) { ++ if (vhost_vdpa_first_dev(dev)) { + r = vhost_vdpa_call(dev, VHOST_SET_BACKEND_FEATURES, &features); + if (r) { + return -EFAULT; +@@ -1122,7 +1129,7 @@ static int vhost_vdpa_set_log_base(struct vhost_dev *dev, uint64_t base, + struct vhost_log *log) + { + struct vhost_vdpa *v = dev->opaque; +- if (v->shadow_vqs_enabled || vhost_vdpa_one_time_request(dev)) { ++ if (v->shadow_vqs_enabled || !vhost_vdpa_first_dev(dev)) { + return 0; + } + +@@ -1244,7 +1251,7 @@ static int vhost_vdpa_get_features(struct vhost_dev *dev, + + static int vhost_vdpa_set_owner(struct vhost_dev *dev) + { +- if (vhost_vdpa_one_time_request(dev)) { ++ if (!vhost_vdpa_first_dev(dev)) { + return 0; + } + +-- +2.27.0 + diff --git a/vhost-vdpa-fix-assert-virtio_net_get_subqueue-nc-asy.patch b/vhost-vdpa-fix-assert-virtio_net_get_subqueue-nc-asy.patch new file mode 100644 index 00000000..b49311e9 --- /dev/null +++ b/vhost-vdpa-fix-assert-virtio_net_get_subqueue-nc-asy.patch @@ -0,0 +1,75 @@ +From 0462d79e6b607799538ac96b9486b60ee6819e9f Mon Sep 17 00:00:00 2001 +From: Si-Wei Liu +Date: Tue, 8 Nov 2022 12:19:28 +0800 +Subject: [PATCH] vhost-vdpa: fix assert + !virtio_net_get_subqueue(nc)->async_tx.elem in virtio_net_reset + +The citing commit has incorrect code in vhost_vdpa_receive() that returns +zero instead of full packet size to the caller. This renders pending packets +unable to be freed so then get clogged in the tx queue forever. When device +is being reset later on, below assertion failure ensues: + +0 0x00007f86d53bb387 in raise () from /lib64/libc.so.6 +1 0x00007f86d53bca78 in abort () from /lib64/libc.so.6 +2 0x00007f86d53b41a6 in __assert_fail_base () from /lib64/libc.so.6 +3 0x00007f86d53b4252 in __assert_fail () from /lib64/libc.so.6 +4 0x000055b8f6ff6fcc in virtio_net_reset (vdev=) at /usr/src/debug/qemu/hw/net/virtio-net.c:563 +5 0x000055b8f7012fcf in virtio_reset (opaque=0x55b8faf881f0) at /usr/src/debug/qemu/hw/virtio/virtio.c:1993 +6 0x000055b8f71f0086 in virtio_bus_reset (bus=bus@entry=0x55b8faf88178) at /usr/src/debug/qemu/hw/virtio/virtio-bus.c:102 +7 0x000055b8f71f1620 in virtio_pci_reset (qdev=) at /usr/src/debug/qemu/hw/virtio/virtio-pci.c:1845 +8 0x000055b8f6fafc6c in memory_region_write_accessor (mr=, addr=, value=, + size=, shift=, mask=, attrs=...) at /usr/src/debug/qemu/memory.c:483 +9 0x000055b8f6fadce9 in access_with_adjusted_size (addr=addr@entry=20, value=value@entry=0x7f867e7fb7e8, size=size@entry=1, + access_size_min=, access_size_max=, access_fn=0x55b8f6fafc20 , + mr=0x55b8faf80a50, attrs=...) at /usr/src/debug/qemu/memory.c:544 +10 0x000055b8f6fb1d0b in memory_region_dispatch_write (mr=mr@entry=0x55b8faf80a50, addr=addr@entry=20, data=0, op=, + attrs=attrs@entry=...) at /usr/src/debug/qemu/memory.c:1470 +11 0x000055b8f6f62ada in flatview_write_continue (fv=fv@entry=0x7f86ac04cd20, addr=addr@entry=549755813908, attrs=..., + attrs@entry=..., buf=buf@entry=0x7f86d0223028
, len=len@entry=1, addr1=20, l=1, + mr=0x55b8faf80a50) at /usr/src/debug/qemu/exec.c:3266 +12 0x000055b8f6f62c8f in flatview_write (fv=0x7f86ac04cd20, addr=549755813908, attrs=..., + buf=0x7f86d0223028
, len=1) at /usr/src/debug/qemu/exec.c:3306 +13 0x000055b8f6f674cb in address_space_write (as=, addr=, attrs=..., buf=, + len=) at /usr/src/debug/qemu/exec.c:3396 +14 0x000055b8f6f67575 in address_space_rw (as=, addr=, attrs=..., attrs@entry=..., + buf=buf@entry=0x7f86d0223028
, len=, is_write=) + at /usr/src/debug/qemu/exec.c:3406 +15 0x000055b8f6fc1cc8 in kvm_cpu_exec (cpu=cpu@entry=0x55b8f9aa0e10) at /usr/src/debug/qemu/accel/kvm/kvm-all.c:2410 +16 0x000055b8f6fa5f5e in qemu_kvm_cpu_thread_fn (arg=0x55b8f9aa0e10) at /usr/src/debug/qemu/cpus.c:1318 +17 0x000055b8f7336e16 in qemu_thread_start (args=0x55b8f9ac8480) at /usr/src/debug/qemu/util/qemu-thread-posix.c:519 +18 0x00007f86d575aea5 in start_thread () from /lib64/libpthread.so.0 +19 0x00007f86d5483b2d in clone () from /lib64/libc.so.6 + +Make vhost_vdpa_receive() return the size passed in as is, so that the +caller qemu_deliver_packet_iov() would eventually propagate it back to +virtio_net_flush_tx() to release pending packets from the async_tx queue. +Which corresponds to the drop path where qemu_sendv_packet_async() returns +non-zero in virtio_net_flush_tx(). + +Fixes: 846a1e85da64 ("vdpa: Add dummy receive callback") +Cc: Eugenio Perez Martin +Signed-off-by: Si-Wei Liu +Signed-off-by: Jason Wang +Signed-off-by: Stefan Hajnoczi +Message-Id: <20221108041929.18417-2-jasowang@redhat.com> +Signed-off-by: fangyi +--- + net/vhost-vdpa.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c +index c89f9d1243..eae2ed364f 100644 +--- a/net/vhost-vdpa.c ++++ b/net/vhost-vdpa.c +@@ -218,7 +218,7 @@ static bool vhost_vdpa_check_peer_type(NetClientState *nc, ObjectClass *oc, + static ssize_t vhost_vdpa_receive(NetClientState *nc, const uint8_t *buf, + size_t size) + { +- return 0; ++ return size; + } + + static NetClientInfo net_vhost_vdpa_info = { +-- +2.27.0 + diff --git a/vhost-vdpa-fix-improper-cleanup-in-net_init_vhost_vd.patch b/vhost-vdpa-fix-improper-cleanup-in-net_init_vhost_vd.patch new file mode 100644 index 00000000..ecb45191 --- /dev/null +++ b/vhost-vdpa-fix-improper-cleanup-in-net_init_vhost_vd.patch @@ -0,0 +1,36 @@ +From ddd117ccb7dfc57dcd45d52d35cd71f746d81c3a Mon Sep 17 00:00:00 2001 +From: Si-Wei Liu +Date: Fri, 6 May 2022 19:28:14 -0700 +Subject: [PATCH] vhost-vdpa: fix improper cleanup in net_init_vhost_vdpa + +... such that no memory leaks on dangling net clients in case of +error. + +Signed-off-by: Si-Wei Liu +Acked-by: Jason Wang +Message-Id: <1651890498-24478-4-git-send-email-si-wei.liu@oracle.com> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Signed-off-by: fangyi +--- + net/vhost-vdpa.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c +index 9ba0f7bfca..7201c79116 100644 +--- a/net/vhost-vdpa.c ++++ b/net/vhost-vdpa.c +@@ -314,7 +314,9 @@ int net_init_vhost_vdpa(const Netdev *netdev, const char *name, + + err: + if (i) { +- qemu_del_net_client(ncs[0]); ++ for (i--; i >= 0; i--) { ++ qemu_del_net_client(ncs[i]); ++ } + } + qemu_close(vdpa_device_fd); + +-- +2.27.0 + diff --git a/vhost-vdpa-fix-typo-in-a-comment.patch b/vhost-vdpa-fix-typo-in-a-comment.patch new file mode 100644 index 00000000..b55cff07 --- /dev/null +++ b/vhost-vdpa-fix-typo-in-a-comment.patch @@ -0,0 +1,35 @@ +From 208e92b8d029d8483f994858304d49af5b6d875a Mon Sep 17 00:00:00 2001 +From: Stefano Garzarella +Date: Mon, 28 Mar 2022 17:20:22 +0200 +Subject: [PATCH] vhost-vdpa: fix typo in a comment +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Replace vpda with vdpa. + +Signed-off-by: Stefano Garzarella +Reviewed-by: Philippe Mathieu-Daudé +Message-Id: <20220328152022.73245-1-sgarzare@redhat.com> +Signed-off-by: Laurent Vivier +Signed-off-by: fangyi +--- + hw/virtio/vhost-vdpa.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c +index 3b5456cc0e..b66697da6e 100644 +--- a/hw/virtio/vhost-vdpa.c ++++ b/hw/virtio/vhost-vdpa.c +@@ -301,7 +301,7 @@ static void vhost_vdpa_listener_region_del(MemoryListener *listener, + memory_region_unref(section->mr); + } + /* +- * IOTLB API is used by vhost-vpda which requires incremental updating ++ * IOTLB API is used by vhost-vdpa which requires incremental updating + * of the mapping. So we can not use generic vhost memory listener which + * depends on the addnop(). + */ +-- +2.27.0 + diff --git a/vhost-vdpa-stick-to-errno-error-return-convention.patch b/vhost-vdpa-stick-to-errno-error-return-convention.patch new file mode 100644 index 00000000..1ef8091e --- /dev/null +++ b/vhost-vdpa-stick-to-errno-error-return-convention.patch @@ -0,0 +1,107 @@ +From 69fdbac8d37a02cfc91e6c849a768e58e57dd15f Mon Sep 17 00:00:00 2001 +From: fangyi +Date: Thu, 16 Nov 2023 09:54:55 +0800 +Subject: [PATCH] vhost-vdpa: stick to -errno error return convention + +Almost all VhostOps methods in vdpa_ops follow the convention of +returning negated errno on error. + +Adjust the few that don't. To that end, rework vhost_vdpa_add_status to +check if setting of the requested status bits has succeeded and return +the respective error code it hasn't, and propagate the error codes +wherever it's appropriate. + +Signed-off-by: Roman Kagan +Message-Id: <20211111153354.18807-8-rvkagan@yandex-team.ru> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Signed-off-by: fangyi +--- + hw/virtio/vhost-vdpa.c | 37 +++++++++++++++++++++++-------------- + 1 file changed, 23 insertions(+), 14 deletions(-) + +diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c +index b7bbd65cdd..d8fba0b714 100644 +--- a/hw/virtio/vhost-vdpa.c ++++ b/hw/virtio/vhost-vdpa.c +@@ -294,18 +294,34 @@ static int vhost_vdpa_call(struct vhost_dev *dev, unsigned long int request, + return ret < 0 ? -errno : ret; + } + +-static void vhost_vdpa_add_status(struct vhost_dev *dev, uint8_t status) ++static int vhost_vdpa_add_status(struct vhost_dev *dev, uint8_t status) + { + uint8_t s; ++ int ret; + + trace_vhost_vdpa_add_status(dev, status); +- if (vhost_vdpa_call(dev, VHOST_VDPA_GET_STATUS, &s)) { +- return; ++ ret = vhost_vdpa_call(dev, VHOST_VDPA_GET_STATUS, &s); ++ if (ret < 0) { ++ return ret; + } + + s |= status; + +- vhost_vdpa_call(dev, VHOST_VDPA_SET_STATUS, &s); ++ ret = vhost_vdpa_call(dev, VHOST_VDPA_SET_STATUS, &s); ++ if (ret < 0) { ++ return ret; ++ } ++ ++ ret = vhost_vdpa_call(dev, VHOST_VDPA_GET_STATUS, &s); ++ if (ret < 0) { ++ return ret; ++ } ++ ++ if (!(s & status)) { ++ return -EIO; ++ } ++ ++ return 0; + } + + static void vhost_vdpa_get_iova_range(struct vhost_vdpa *v) +@@ -487,7 +503,7 @@ static int vhost_vdpa_set_mem_table(struct vhost_dev *dev, + } + } + if (mem->padding) { +- return -1; ++ return -EINVAL; + } + + return 0; +@@ -504,14 +520,11 @@ static int vhost_vdpa_set_features(struct vhost_dev *dev, + + trace_vhost_vdpa_set_features(dev, features); + ret = vhost_vdpa_call(dev, VHOST_SET_FEATURES, &features); +- uint8_t status = 0; + if (ret) { + return ret; + } +- vhost_vdpa_add_status(dev, VIRTIO_CONFIG_S_FEATURES_OK); +- vhost_vdpa_call(dev, VHOST_VDPA_GET_STATUS, &status); + +- return !(status & VIRTIO_CONFIG_S_FEATURES_OK); ++ return vhost_vdpa_add_status(dev, VIRTIO_CONFIG_S_FEATURES_OK); + } + + static int vhost_vdpa_set_backend_cap(struct vhost_dev *dev) +@@ -653,12 +666,8 @@ static int vhost_vdpa_dev_start(struct vhost_dev *dev, bool started) + } + + if (started) { +- uint8_t status = 0; + memory_listener_register(&v->listener, &address_space_memory); +- vhost_vdpa_add_status(dev, VIRTIO_CONFIG_S_DRIVER_OK); +- vhost_vdpa_call(dev, VHOST_VDPA_GET_STATUS, &status); +- +- return !(status & VIRTIO_CONFIG_S_DRIVER_OK); ++ return vhost_vdpa_add_status(dev, VIRTIO_CONFIG_S_DRIVER_OK); + } else { + vhost_vdpa_reset_device(dev); + vhost_vdpa_add_status(dev, VIRTIO_CONFIG_S_ACKNOWLEDGE | +-- +2.27.0 + diff --git a/vhost_net-Add-NetClientInfo-start-callback.patch b/vhost_net-Add-NetClientInfo-start-callback.patch new file mode 100644 index 00000000..546c4ef9 --- /dev/null +++ b/vhost_net-Add-NetClientInfo-start-callback.patch @@ -0,0 +1,64 @@ +From 533bcae898152213703a1f15b3d4a938292fd23f Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= +Date: Tue, 23 Aug 2022 20:30:30 +0200 +Subject: [PATCH] vhost_net: Add NetClientInfo start callback +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This is used by the backend to perform actions before the device is +started. + +In particular, vdpa net use it to map CVQ buffers to the device, so it +can send control commands using them. + +Signed-off-by: Eugenio Pérez +Acked-by: Jason Wang +Signed-off-by: Jason Wang +Signed-off-by: fangyi +--- + hw/net/vhost_net.c | 7 +++++++ + include/net/net.h | 2 ++ + 2 files changed, 9 insertions(+) + +diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c +index bea053a742..92df7558bf 100644 +--- a/hw/net/vhost_net.c ++++ b/hw/net/vhost_net.c +@@ -307,6 +307,13 @@ static int vhost_net_start_one(struct vhost_net *net, + struct vhost_vring_file file = { }; + int r; + ++ if (net->nc->info->start) { ++ r = net->nc->info->start(net->nc); ++ if (r < 0) { ++ return r; ++ } ++ } ++ + r = vhost_dev_enable_notifiers(&net->dev, dev); + if (r < 0) { + goto fail_notifiers; +diff --git a/include/net/net.h b/include/net/net.h +index 523136c7ac..ad9e80083a 100644 +--- a/include/net/net.h ++++ b/include/net/net.h +@@ -44,6 +44,7 @@ typedef struct NICConf { + + typedef void (NetPoll)(NetClientState *, bool enable); + typedef bool (NetCanReceive)(NetClientState *); ++typedef int (NetStart)(NetClientState *); + typedef ssize_t (NetReceive)(NetClientState *, const uint8_t *, size_t); + typedef ssize_t (NetReceiveIOV)(NetClientState *, const struct iovec *, int); + typedef void (NetCleanup) (NetClientState *); +@@ -71,6 +72,7 @@ typedef struct NetClientInfo { + NetReceive *receive_raw; + NetReceiveIOV *receive_iov; + NetCanReceive *can_receive; ++ NetStart *start; + NetCleanup *cleanup; + LinkStatusChanged *link_status_changed; + QueryRxFilter *query_rx_filter; +-- +2.27.0 + diff --git a/vhost_net-Add-NetClientInfo-stop-callback.patch b/vhost_net-Add-NetClientInfo-stop-callback.patch new file mode 100644 index 00000000..80cbd526 --- /dev/null +++ b/vhost_net-Add-NetClientInfo-stop-callback.patch @@ -0,0 +1,59 @@ +From d25c4237821c994e36b7a23e0a0c609993707d47 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= +Date: Tue, 23 Aug 2022 20:30:31 +0200 +Subject: [PATCH] vhost_net: Add NetClientInfo stop callback +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Used by the backend to perform actions after the device is stopped. + +In particular, vdpa net use it to unmap CVQ buffers to the device, +cleaning the actions performed in prepare(). + +Signed-off-by: Eugenio Pérez +Acked-by: Jason Wang +Signed-off-by: Jason Wang +Signed-off-by: fangyi +--- + hw/net/vhost_net.c | 3 +++ + include/net/net.h | 2 ++ + 2 files changed, 5 insertions(+) + +diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c +index 92df7558bf..fe6932171b 100644 +--- a/hw/net/vhost_net.c ++++ b/hw/net/vhost_net.c +@@ -383,6 +383,9 @@ static void vhost_net_stop_one(struct vhost_net *net, + net->nc->info->poll(net->nc, true); + } + vhost_dev_stop(&net->dev, dev); ++ if (net->nc->info->stop) { ++ net->nc->info->stop(net->nc); ++ } + vhost_dev_disable_notifiers(&net->dev, dev); + } + +diff --git a/include/net/net.h b/include/net/net.h +index ad9e80083a..476ad45b9a 100644 +--- a/include/net/net.h ++++ b/include/net/net.h +@@ -45,6 +45,7 @@ typedef struct NICConf { + typedef void (NetPoll)(NetClientState *, bool enable); + typedef bool (NetCanReceive)(NetClientState *); + typedef int (NetStart)(NetClientState *); ++typedef void (NetStop)(NetClientState *); + typedef ssize_t (NetReceive)(NetClientState *, const uint8_t *, size_t); + typedef ssize_t (NetReceiveIOV)(NetClientState *, const struct iovec *, int); + typedef void (NetCleanup) (NetClientState *); +@@ -73,6 +74,7 @@ typedef struct NetClientInfo { + NetReceiveIOV *receive_iov; + NetCanReceive *can_receive; + NetStart *start; ++ NetStop *stop; + NetCleanup *cleanup; + LinkStatusChanged *link_status_changed; + QueryRxFilter *query_rx_filter; +-- +2.27.0 + diff --git a/vhost_net-add-NetClientState-load-callback.patch b/vhost_net-add-NetClientState-load-callback.patch new file mode 100644 index 00000000..39d93523 --- /dev/null +++ b/vhost_net-add-NetClientState-load-callback.patch @@ -0,0 +1,64 @@ +From 4b0c6e40f26af49416d00b186840344b424b48ac Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= +Date: Tue, 23 Aug 2022 20:30:35 +0200 +Subject: [PATCH] vhost_net: add NetClientState->load() callback +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +It allows per-net client operations right after device's successful +start. In particular, to load the device status. + +Vhost-vdpa net will use it to add the CVQ buffers to restore the device +status. + +Signed-off-by: Eugenio Pérez +Acked-by: Jason Wang +Signed-off-by: Jason Wang +Signed-off-by: fangyi +--- + hw/net/vhost_net.c | 7 +++++++ + include/net/net.h | 2 ++ + 2 files changed, 9 insertions(+) + +diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c +index fe6932171b..f709c060b6 100644 +--- a/hw/net/vhost_net.c ++++ b/hw/net/vhost_net.c +@@ -344,6 +344,13 @@ static int vhost_net_start_one(struct vhost_net *net, + } + } + } ++ ++ if (net->nc->info->load) { ++ r = net->nc->info->load(net->nc); ++ if (r < 0) { ++ goto fail; ++ } ++ } + return 0; + fail: + file.fd = -1; +diff --git a/include/net/net.h b/include/net/net.h +index 476ad45b9a..81d0b21def 100644 +--- a/include/net/net.h ++++ b/include/net/net.h +@@ -45,6 +45,7 @@ typedef struct NICConf { + typedef void (NetPoll)(NetClientState *, bool enable); + typedef bool (NetCanReceive)(NetClientState *); + typedef int (NetStart)(NetClientState *); ++typedef int (NetLoad)(NetClientState *); + typedef void (NetStop)(NetClientState *); + typedef ssize_t (NetReceive)(NetClientState *, const uint8_t *, size_t); + typedef ssize_t (NetReceiveIOV)(NetClientState *, const struct iovec *, int); +@@ -74,6 +75,7 @@ typedef struct NetClientInfo { + NetReceiveIOV *receive_iov; + NetCanReceive *can_receive; + NetStart *start; ++ NetLoad *load; + NetStop *stop; + NetCleanup *cleanup; + LinkStatusChanged *link_status_changed; +-- +2.27.0 + diff --git a/virtio-Add-vhost_svq_get_vring_addr.patch b/virtio-Add-vhost_svq_get_vring_addr.patch new file mode 100644 index 00000000..67f864e8 --- /dev/null +++ b/virtio-Add-vhost_svq_get_vring_addr.patch @@ -0,0 +1,96 @@ +From c9b863e96be5277e775cb424cf8ea34f8f921776 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= +Date: Mon, 14 Mar 2022 18:34:45 +0100 +Subject: [PATCH] virtio: Add vhost_svq_get_vring_addr +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +It reports the shadow virtqueue address from qemu virtual address space. + +Since this will be different from the guest's vaddr, but the device can +access it, SVQ takes special care about its alignment & lack of garbage +data. It assumes that IOMMU will work in host_page_size ranges for that. + +Signed-off-by: Eugenio Pérez +Acked-by: Michael S. Tsirkin +Signed-off-by: Jason Wang +Signed-off-by: fangyi +--- + hw/virtio/vhost-shadow-virtqueue.c | 29 +++++++++++++++++++++++++++++ + hw/virtio/vhost-shadow-virtqueue.h | 9 +++++++++ + 2 files changed, 38 insertions(+) + +diff --git a/hw/virtio/vhost-shadow-virtqueue.c b/hw/virtio/vhost-shadow-virtqueue.c +index 519328445c..573ac0d9cf 100644 +--- a/hw/virtio/vhost-shadow-virtqueue.c ++++ b/hw/virtio/vhost-shadow-virtqueue.c +@@ -106,6 +106,35 @@ void vhost_svq_set_svq_call_fd(VhostShadowVirtqueue *svq, int call_fd) + } + } + ++/** ++ * Get the shadow vq vring address. ++ * @svq: Shadow virtqueue ++ * @addr: Destination to store address ++ */ ++void vhost_svq_get_vring_addr(const VhostShadowVirtqueue *svq, ++ struct vhost_vring_addr *addr) ++{ ++ addr->desc_user_addr = (uint64_t)(intptr_t)svq->vring.desc; ++ addr->avail_user_addr = (uint64_t)(intptr_t)svq->vring.avail; ++ addr->used_user_addr = (uint64_t)(intptr_t)svq->vring.used; ++} ++ ++size_t vhost_svq_driver_area_size(const VhostShadowVirtqueue *svq) ++{ ++ size_t desc_size = sizeof(vring_desc_t) * svq->vring.num; ++ size_t avail_size = offsetof(vring_avail_t, ring) + ++ sizeof(uint16_t) * svq->vring.num; ++ ++ return ROUND_UP(desc_size + avail_size, qemu_real_host_page_size); ++} ++ ++size_t vhost_svq_device_area_size(const VhostShadowVirtqueue *svq) ++{ ++ size_t used_size = offsetof(vring_used_t, ring) + ++ sizeof(vring_used_elem_t) * svq->vring.num; ++ return ROUND_UP(used_size, qemu_real_host_page_size); ++} ++ + /** + * Set a new file descriptor for the guest to kick the SVQ and notify for avail + * +diff --git a/hw/virtio/vhost-shadow-virtqueue.h b/hw/virtio/vhost-shadow-virtqueue.h +index 9e12f77201..82cea1c3fa 100644 +--- a/hw/virtio/vhost-shadow-virtqueue.h ++++ b/hw/virtio/vhost-shadow-virtqueue.h +@@ -11,9 +11,14 @@ + #define VHOST_SHADOW_VIRTQUEUE_H + + #include "qemu/event_notifier.h" ++#include "hw/virtio/virtio.h" ++#include "standard-headers/linux/vhost_types.h" + + /* Shadow virtqueue to relay notifications */ + typedef struct VhostShadowVirtqueue { ++ /* Shadow vring */ ++ struct vring vring; ++ + /* Shadow kick notifier, sent to vhost */ + EventNotifier hdev_kick; + /* Shadow call notifier, sent to vhost */ +@@ -37,6 +42,10 @@ bool vhost_svq_valid_features(uint64_t features, Error **errp); + + void vhost_svq_set_svq_kick_fd(VhostShadowVirtqueue *svq, int svq_kick_fd); + void vhost_svq_set_svq_call_fd(VhostShadowVirtqueue *svq, int call_fd); ++void vhost_svq_get_vring_addr(const VhostShadowVirtqueue *svq, ++ struct vhost_vring_addr *addr); ++size_t vhost_svq_driver_area_size(const VhostShadowVirtqueue *svq); ++size_t vhost_svq_device_area_size(const VhostShadowVirtqueue *svq); + + void vhost_svq_stop(VhostShadowVirtqueue *svq); + +-- +2.27.0 + diff --git a/virtio-add-support-for-configure-interrupt-new.patch b/virtio-add-support-for-configure-interrupt-new.patch new file mode 100644 index 00000000..72a13479 --- /dev/null +++ b/virtio-add-support-for-configure-interrupt-new.patch @@ -0,0 +1,102 @@ +From 90152f58401b828febbb060cff86330827e6befe Mon Sep 17 00:00:00 2001 +From: Cindy Lu +Date: Thu, 22 Dec 2022 15:04:47 +0800 +Subject: [PATCH] virtio: add support for configure interrupt + +Add the functions to support the configure interrupt in virtio +The function virtio_config_guest_notifier_read will notify the +guest if there is an configure interrupt. +The function virtio_config_set_guest_notifier_fd_handler is +to set the fd hander for the notifier + +Signed-off-by: Cindy Lu +Message-Id: <20221222070451.936503-7-lulu@redhat.com> +Acked-by: Jason Wang +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Signed-off-by: fangyi +--- + hw/virtio/virtio.c | 29 +++++++++++++++++++++++++++++ + include/hw/virtio/virtio.h | 4 ++++ + 2 files changed, 33 insertions(+) + +diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c +index 12f4a8ab3d..e3f392fc59 100644 +--- a/hw/virtio/virtio.c ++++ b/hw/virtio/virtio.c +@@ -3548,7 +3548,14 @@ static void virtio_queue_guest_notifier_read(EventNotifier *n) + virtio_irq(vq); + } + } ++static void virtio_config_guest_notifier_read(EventNotifier *n) ++{ ++ VirtIODevice *vdev = container_of(n, VirtIODevice, config_notifier); + ++ if (event_notifier_test_and_clear(n)) { ++ virtio_notify_config(vdev); ++ } ++} + void virtio_queue_set_guest_notifier_fd_handler(VirtQueue *vq, bool assign, + bool with_irqfd) + { +@@ -3565,6 +3572,23 @@ void virtio_queue_set_guest_notifier_fd_handler(VirtQueue *vq, bool assign, + } + } + ++void virtio_config_set_guest_notifier_fd_handler(VirtIODevice *vdev, ++ bool assign, bool with_irqfd) ++{ ++ EventNotifier *n; ++ n = &vdev->config_notifier; ++ if (assign && !with_irqfd) { ++ event_notifier_set_handler(n, virtio_config_guest_notifier_read); ++ } else { ++ event_notifier_set_handler(n, NULL); ++ } ++ if (!assign) { ++ /* Test and clear notifier before closing it,*/ ++ /* in case poll callback didn't have time to run. */ ++ virtio_config_guest_notifier_read(n); ++ } ++} ++ + EventNotifier *virtio_queue_get_guest_notifier(VirtQueue *vq) + { + return &vq->guest_notifier; +@@ -3638,6 +3662,11 @@ EventNotifier *virtio_queue_get_host_notifier(VirtQueue *vq) + return &vq->host_notifier; + } + ++EventNotifier *virtio_config_get_guest_notifier(VirtIODevice *vdev) ++{ ++ return &vdev->config_notifier; ++} ++ + void virtio_queue_set_host_notifier_enabled(VirtQueue *vq, bool enabled) + { + vq->host_notifier_enabled = enabled; +diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h +index 91d1c3433a..43509b33ff 100644 +--- a/include/hw/virtio/virtio.h ++++ b/include/hw/virtio/virtio.h +@@ -114,6 +114,7 @@ struct VirtIODevice + bool use_guest_notifier_mask; + AddressSpace *dma_as; + QLIST_HEAD(, VirtQueue) *vector_queues; ++ EventNotifier config_notifier; + }; + + struct VirtioDeviceClass { +@@ -329,6 +330,9 @@ void virtio_queue_aio_set_host_notifier_handler(VirtQueue *vq, AioContext *ctx, + VirtIOHandleAIOOutput handle_output); + VirtQueue *virtio_vector_first_queue(VirtIODevice *vdev, uint16_t vector); + VirtQueue *virtio_vector_next_queue(VirtQueue *vq); ++EventNotifier *virtio_config_get_guest_notifier(VirtIODevice *vdev); ++void virtio_config_set_guest_notifier_fd_handler(VirtIODevice *vdev, ++ bool assign, bool with_irqfd); + + static inline void virtio_add_feature(uint64_t *features, unsigned int fbit) + { +-- +2.27.0 + diff --git a/virtio-add-support-for-configure-interrupt.patch b/virtio-add-support-for-configure-interrupt.patch new file mode 100644 index 00000000..b5bc73ab --- /dev/null +++ b/virtio-add-support-for-configure-interrupt.patch @@ -0,0 +1,106 @@ +From 3ada114454dba1f4b8c6c30e64dfeedd41a6efc8 Mon Sep 17 00:00:00 2001 +From: fangyi +Date: Thu, 16 Nov 2023 09:54:52 +0800 +Subject: [PATCH] virtio: add support for configure interrupt + +Add the functions to support the configure interrupt in virtio +The function virtio_config_guest_notifier_read will notify the +guest if there is an configure interrupt. +The function virtio_config_set_guest_notifier_fd_handler is +to set the fd hander for the notifier + +Signed-off-by: Cindy Lu +Message-Id: <20211104164827.21911-7-lulu@redhat.com> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Signed-off-by: fangyi +--- + hw/virtio/virtio.c | 29 +++++++++++++++++++++++++++++ + include/hw/virtio/virtio.h | 4 ++++ + 2 files changed, 33 insertions(+) + +diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c +index 071668e3e0..d90cabe868 100644 +--- a/hw/virtio/virtio.c ++++ b/hw/virtio/virtio.c +@@ -3546,7 +3546,14 @@ static void virtio_queue_guest_notifier_read(EventNotifier *n) + virtio_irq(vq); + } + } ++static void virtio_config_guest_notifier_read(EventNotifier *n) ++{ ++ VirtIODevice *vdev = container_of(n, VirtIODevice, config_notifier); + ++ if (event_notifier_test_and_clear(n)) { ++ virtio_notify_config(vdev); ++ } ++} + void virtio_queue_set_guest_notifier_fd_handler(VirtQueue *vq, bool assign, + bool with_irqfd) + { +@@ -3563,6 +3570,23 @@ void virtio_queue_set_guest_notifier_fd_handler(VirtQueue *vq, bool assign, + } + } + ++void virtio_config_set_guest_notifier_fd_handler(VirtIODevice *vdev, ++ bool assign, bool with_irqfd) ++{ ++ EventNotifier *n; ++ n = &vdev->config_notifier; ++ if (assign && !with_irqfd) { ++ event_notifier_set_handler(n, virtio_config_guest_notifier_read); ++ } else { ++ event_notifier_set_handler(n, NULL); ++ } ++ if (!assign) { ++ /* Test and clear notifier before closing it,*/ ++ /* in case poll callback didn't have time to run. */ ++ virtio_config_guest_notifier_read(n); ++ } ++} ++ + EventNotifier *virtio_queue_get_guest_notifier(VirtQueue *vq) + { + return &vq->guest_notifier; +@@ -3636,6 +3660,11 @@ EventNotifier *virtio_queue_get_host_notifier(VirtQueue *vq) + return &vq->host_notifier; + } + ++EventNotifier *virtio_config_get_guest_notifier(VirtIODevice *vdev) ++{ ++ return &vdev->config_notifier; ++} ++ + void virtio_queue_set_host_notifier_enabled(VirtQueue *vq, bool enabled) + { + vq->host_notifier_enabled = enabled; +diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h +index c113a5b864..8788ccd1f3 100644 +--- a/include/hw/virtio/virtio.h ++++ b/include/hw/virtio/virtio.h +@@ -112,6 +112,7 @@ struct VirtIODevice + bool use_guest_notifier_mask; + AddressSpace *dma_as; + QLIST_HEAD(, VirtQueue) *vector_queues; ++ EventNotifier config_notifier; + }; + + struct VirtioDeviceClass { +@@ -315,11 +316,14 @@ uint16_t virtio_get_queue_index(VirtQueue *vq); + EventNotifier *virtio_queue_get_guest_notifier(VirtQueue *vq); + void virtio_queue_set_guest_notifier_fd_handler(VirtQueue *vq, bool assign, + bool with_irqfd); ++void virtio_config_set_guest_notifier_fd_handler(VirtIODevice *vdev, ++ bool assign, bool with_irqfd); + int virtio_device_start_ioeventfd(VirtIODevice *vdev); + int virtio_device_grab_ioeventfd(VirtIODevice *vdev); + void virtio_device_release_ioeventfd(VirtIODevice *vdev); + bool virtio_device_ioeventfd_enabled(VirtIODevice *vdev); + EventNotifier *virtio_queue_get_host_notifier(VirtQueue *vq); ++EventNotifier *virtio_config_get_guest_notifier(VirtIODevice *vdev); + void virtio_queue_set_host_notifier_enabled(VirtQueue *vq, bool enabled); + void virtio_queue_host_notifier_read(EventNotifier *n); + void virtio_queue_aio_set_host_notifier_handler(VirtQueue *vq, AioContext *ctx, +-- +2.27.0 + diff --git a/virtio-add-vhost-support-for-virtio-devices.patch b/virtio-add-vhost-support-for-virtio-devices.patch new file mode 100644 index 00000000..5d944801 --- /dev/null +++ b/virtio-add-vhost-support-for-virtio-devices.patch @@ -0,0 +1,336 @@ +From b51d5c0def1e902a716bd3896d2f1868c635c554 Mon Sep 17 00:00:00 2001 +From: Jonah Palmer +Date: Fri, 1 Apr 2022 09:23:19 -0400 +Subject: [PATCH] virtio: add vhost support for virtio devices + +This patch adds a get_vhost() callback function for VirtIODevices that +returns the device's corresponding vhost_dev structure, if the vhost +device is running. This patch also adds a vhost_started flag for +VirtIODevices. + +Previously, a VirtIODevice wouldn't be able to tell if its corresponding +vhost device was active or not. + +Signed-off-by: Jonah Palmer +Message-Id: <1648819405-25696-3-git-send-email-jonah.palmer@oracle.com> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Signed-off-by: fangyi +--- + hw/block/vhost-user-blk.c | 7 +++++++ + hw/display/vhost-user-gpu.c | 7 +++++++ + hw/input/vhost-user-input.c | 7 +++++++ + hw/net/virtio-net.c | 9 +++++++++ + hw/scsi/vhost-scsi.c | 8 ++++++++ + hw/virtio/vhost-user-fs.c | 7 +++++++ + hw/virtio/vhost-user-rng.c | 7 +++++++ + hw/virtio/vhost-vsock-common.c | 7 +++++++ + hw/virtio/vhost.c | 4 +++- + hw/virtio/virtio-crypto.c | 10 ++++++++++ + hw/virtio/virtio.c | 1 + + include/hw/virtio/virtio.h | 3 +++ + 12 files changed, 76 insertions(+), 1 deletion(-) + +diff --git a/hw/block/vhost-user-blk.c b/hw/block/vhost-user-blk.c +index bcc3f83c4b..9bf18434c2 100644 +--- a/hw/block/vhost-user-blk.c ++++ b/hw/block/vhost-user-blk.c +@@ -573,6 +573,12 @@ static void vhost_user_blk_instance_init(Object *obj) + "/disk@0,0", DEVICE(obj)); + } + ++static struct vhost_dev *vhost_user_blk_get_vhost(VirtIODevice *vdev) ++{ ++ VHostUserBlk *s = VHOST_USER_BLK(vdev); ++ return &s->dev; ++} ++ + static const VMStateDescription vmstate_vhost_user_blk = { + .name = "vhost-user-blk", + .minimum_version_id = 1, +@@ -607,6 +613,7 @@ static void vhost_user_blk_class_init(ObjectClass *klass, void *data) + vdc->get_features = vhost_user_blk_get_features; + vdc->set_status = vhost_user_blk_set_status; + vdc->reset = vhost_user_blk_reset; ++ vdc->get_vhost = vhost_user_blk_get_vhost; + } + + static const TypeInfo vhost_user_blk_info = { +diff --git a/hw/display/vhost-user-gpu.c b/hw/display/vhost-user-gpu.c +index 49df56cd14..6e93b463d6 100644 +--- a/hw/display/vhost-user-gpu.c ++++ b/hw/display/vhost-user-gpu.c +@@ -565,6 +565,12 @@ vhost_user_gpu_device_realize(DeviceState *qdev, Error **errp) + g->vhost_gpu_fd = -1; + } + ++static struct vhost_dev *vhost_user_gpu_get_vhost(VirtIODevice *vdev) ++{ ++ VhostUserGPU *g = VHOST_USER_GPU(vdev); ++ return &g->vhost->dev; ++} ++ + static Property vhost_user_gpu_properties[] = { + VIRTIO_GPU_BASE_PROPERTIES(VhostUserGPU, parent_obj.conf), + DEFINE_PROP_END_OF_LIST(), +@@ -586,6 +592,7 @@ vhost_user_gpu_class_init(ObjectClass *klass, void *data) + vdc->guest_notifier_pending = vhost_user_gpu_guest_notifier_pending; + vdc->get_config = vhost_user_gpu_get_config; + vdc->set_config = vhost_user_gpu_set_config; ++ vdc->get_vhost = vhost_user_gpu_get_vhost; + + device_class_set_props(dc, vhost_user_gpu_properties); + } +diff --git a/hw/input/vhost-user-input.c b/hw/input/vhost-user-input.c +index 273e96a7b1..43d2ff3816 100644 +--- a/hw/input/vhost-user-input.c ++++ b/hw/input/vhost-user-input.c +@@ -79,6 +79,12 @@ static void vhost_input_set_config(VirtIODevice *vdev, + virtio_notify_config(vdev); + } + ++static struct vhost_dev *vhost_input_get_vhost(VirtIODevice *vdev) ++{ ++ VHostUserInput *vhi = VHOST_USER_INPUT(vdev); ++ return &vhi->vhost->dev; ++} ++ + static const VMStateDescription vmstate_vhost_input = { + .name = "vhost-user-input", + .unmigratable = 1, +@@ -93,6 +99,7 @@ static void vhost_input_class_init(ObjectClass *klass, void *data) + dc->vmsd = &vmstate_vhost_input; + vdc->get_config = vhost_input_get_config; + vdc->set_config = vhost_input_set_config; ++ vdc->get_vhost = vhost_input_get_vhost; + vic->realize = vhost_input_realize; + vic->change_active = vhost_input_change_active; + } +diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c +index 3bd786cc22..41bb4010b0 100644 +--- a/hw/net/virtio-net.c ++++ b/hw/net/virtio-net.c +@@ -3644,6 +3644,14 @@ static bool dev_unplug_pending(void *opaque) + return vdc->primary_unplug_pending(dev); + } + ++static struct vhost_dev *virtio_net_get_vhost(VirtIODevice *vdev) ++{ ++ VirtIONet *n = VIRTIO_NET(vdev); ++ NetClientState *nc = qemu_get_queue(n->nic); ++ struct vhost_net *net = get_vhost_net(nc->peer); ++ return &net->dev; ++} ++ + static const VMStateDescription vmstate_virtio_net = { + .name = "virtio-net", + .minimum_version_id = VIRTIO_NET_VM_VERSION, +@@ -3785,6 +3793,7 @@ static void virtio_net_class_init(ObjectClass *klass, void *data) + vdc->post_load = virtio_net_post_load_virtio; + vdc->vmsd = &vmstate_virtio_net_device; + vdc->primary_unplug_pending = primary_unplug_pending; ++ vdc->get_vhost = virtio_net_get_vhost; + } + + static const TypeInfo virtio_net_info = { +diff --git a/hw/scsi/vhost-scsi.c b/hw/scsi/vhost-scsi.c +index 039caf2614..b0a9c45e43 100644 +--- a/hw/scsi/vhost-scsi.c ++++ b/hw/scsi/vhost-scsi.c +@@ -264,6 +264,13 @@ static void vhost_scsi_unrealize(DeviceState *dev) + virtio_scsi_common_unrealize(dev); + } + ++static struct vhost_dev *vhost_scsi_get_vhost(VirtIODevice *vdev) ++{ ++ VHostSCSI *s = VHOST_SCSI(vdev); ++ VHostSCSICommon *vsc = VHOST_SCSI_COMMON(s); ++ return &vsc->dev; ++} ++ + static Property vhost_scsi_properties[] = { + DEFINE_PROP_STRING("vhostfd", VirtIOSCSICommon, conf.vhostfd), + DEFINE_PROP_STRING("wwpn", VirtIOSCSICommon, conf.wwpn), +@@ -298,6 +305,7 @@ static void vhost_scsi_class_init(ObjectClass *klass, void *data) + vdc->get_features = vhost_scsi_common_get_features; + vdc->set_config = vhost_scsi_common_set_config; + vdc->set_status = vhost_scsi_set_status; ++ vdc->get_vhost = vhost_scsi_get_vhost; + fwc->get_dev_path = vhost_scsi_common_get_fw_dev_path; + } + +diff --git a/hw/virtio/vhost-user-fs.c b/hw/virtio/vhost-user-fs.c +index fc7dcc96ef..392b7d3aa1 100644 +--- a/hw/virtio/vhost-user-fs.c ++++ b/hw/virtio/vhost-user-fs.c +@@ -277,6 +277,12 @@ static void vuf_device_unrealize(DeviceState *dev) + g_free(vhost_vqs); + } + ++static struct vhost_dev *vuf_get_vhost(VirtIODevice *vdev) ++{ ++ VHostUserFS *fs = VHOST_USER_FS(vdev); ++ return &fs->vhost_dev; ++} ++ + static const VMStateDescription vuf_vmstate = { + .name = "vhost-user-fs", + .unmigratable = 1, +@@ -314,6 +320,7 @@ static void vuf_class_init(ObjectClass *klass, void *data) + vdc->set_status = vuf_set_status; + vdc->guest_notifier_mask = vuf_guest_notifier_mask; + vdc->guest_notifier_pending = vuf_guest_notifier_pending; ++ vdc->get_vhost = vuf_get_vhost; + } + + static const TypeInfo vuf_info = { +diff --git a/hw/virtio/vhost-user-rng.c b/hw/virtio/vhost-user-rng.c +index 209ee5bf9a..543f3e3cef 100644 +--- a/hw/virtio/vhost-user-rng.c ++++ b/hw/virtio/vhost-user-rng.c +@@ -247,6 +247,12 @@ static void vu_rng_device_unrealize(DeviceState *dev) + vhost_user_cleanup(&rng->vhost_user); + } + ++static struct vhost_dev *vu_rng_get_vhost(VirtIODevice *vdev) ++{ ++ VHostUserRNG *rng = VHOST_USER_RNG(vdev); ++ return &rng->vhost_dev; ++} ++ + static const VMStateDescription vu_rng_vmstate = { + .name = "vhost-user-rng", + .unmigratable = 1, +@@ -272,6 +278,7 @@ static void vu_rng_class_init(ObjectClass *klass, void *data) + vdc->set_status = vu_rng_set_status; + vdc->guest_notifier_mask = vu_rng_guest_notifier_mask; + vdc->guest_notifier_pending = vu_rng_guest_notifier_pending; ++ vdc->get_vhost = vu_rng_get_vhost; + } + + static const TypeInfo vu_rng_info = { +diff --git a/hw/virtio/vhost-vsock-common.c b/hw/virtio/vhost-vsock-common.c +index ed706681ac..cd45aaf28e 100644 +--- a/hw/virtio/vhost-vsock-common.c ++++ b/hw/virtio/vhost-vsock-common.c +@@ -259,6 +259,12 @@ void vhost_vsock_common_unrealize(VirtIODevice *vdev) + virtio_cleanup(vdev); + } + ++static struct vhost_dev *vhost_vsock_common_get_vhost(VirtIODevice *vdev) ++{ ++ VHostVSockCommon *vvc = VHOST_VSOCK_COMMON(vdev); ++ return &vvc->vhost_dev; ++} ++ + static Property vhost_vsock_common_properties[] = { + DEFINE_PROP_ON_OFF_AUTO("seqpacket", VHostVSockCommon, seqpacket, + ON_OFF_AUTO_AUTO), +@@ -274,6 +280,7 @@ static void vhost_vsock_common_class_init(ObjectClass *klass, void *data) + set_bit(DEVICE_CATEGORY_MISC, dc->categories); + vdc->guest_notifier_mask = vhost_vsock_common_guest_notifier_mask; + vdc->guest_notifier_pending = vhost_vsock_common_guest_notifier_pending; ++ vdc->get_vhost = vhost_vsock_common_get_vhost; + } + + static const TypeInfo vhost_vsock_common_info = { +diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c +index 2f9bb96d63..c1f5cb5b91 100644 +--- a/hw/virtio/vhost.c ++++ b/hw/virtio/vhost.c +@@ -1766,6 +1766,7 @@ int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev) + /* should only be called after backend is connected */ + assert(hdev->vhost_ops); + ++ vdev->vhost_started = true; + hdev->started = true; + hdev->vdev = vdev; + +@@ -1838,7 +1839,7 @@ fail_vq: + + fail_mem: + fail_features: +- ++ vdev->vhost_started = false; + hdev->started = false; + return r; + } +@@ -1869,6 +1870,7 @@ void vhost_dev_stop(struct vhost_dev *hdev, VirtIODevice *vdev) + } + vhost_log_put(hdev, true); + hdev->started = false; ++ vdev->vhost_started = false; + hdev->vdev = NULL; + } + +diff --git a/hw/virtio/virtio-crypto.c b/hw/virtio/virtio-crypto.c +index 274c7b4dea..f9d849fa43 100644 +--- a/hw/virtio/virtio-crypto.c ++++ b/hw/virtio/virtio-crypto.c +@@ -966,6 +966,15 @@ static bool virtio_crypto_guest_notifier_pending(VirtIODevice *vdev, int idx) + return cryptodev_vhost_virtqueue_pending(vdev, queue, idx); + } + ++static struct vhost_dev *virtio_crypto_get_vhost(VirtIODevice *vdev) ++{ ++ VirtIOCrypto *vcrypto = VIRTIO_CRYPTO(vdev); ++ CryptoDevBackend *b = vcrypto->cryptodev; ++ CryptoDevBackendClient *cc = b->conf.peers.ccs[0]; ++ CryptoDevBackendVhost *vhost_crypto = cryptodev_get_vhost(cc, b, 0); ++ return &vhost_crypto->dev; ++} ++ + static void virtio_crypto_class_init(ObjectClass *klass, void *data) + { + DeviceClass *dc = DEVICE_CLASS(klass); +@@ -982,6 +991,7 @@ static void virtio_crypto_class_init(ObjectClass *klass, void *data) + vdc->set_status = virtio_crypto_set_status; + vdc->guest_notifier_mask = virtio_crypto_guest_notifier_mask; + vdc->guest_notifier_pending = virtio_crypto_guest_notifier_pending; ++ vdc->get_vhost = virtio_crypto_get_vhost; + } + + static void virtio_crypto_instance_init(Object *obj) +diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c +index c1497f59aa..12f4a8ab3d 100644 +--- a/hw/virtio/virtio.c ++++ b/hw/virtio/virtio.c +@@ -3298,6 +3298,7 @@ void virtio_init(VirtIODevice *vdev, const char *name, + + vdev->start_on_kick = false; + vdev->started = false; ++ vdev->vhost_started = false; + vdev->device_id = device_id; + vdev->status = 0; + qatomic_set(&vdev->isr, 0); +diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h +index 7472145821..223e82436f 100644 +--- a/include/hw/virtio/virtio.h ++++ b/include/hw/virtio/virtio.h +@@ -22,6 +22,7 @@ + #include "standard-headers/linux/virtio_config.h" + #include "standard-headers/linux/virtio_ring.h" + #include "qom/object.h" ++#include "hw/virtio/vhost.h" + + /* A guest should never accept this. It implies negotiation is broken. */ + #define VIRTIO_F_BAD_FEATURE 30 +@@ -103,6 +104,7 @@ struct VirtIODevice + bool started; + bool start_on_kick; /* when virtio 1.0 feature has not been negotiated */ + bool disable_legacy_check; ++ bool vhost_started; + VMChangeStateEntry *vmstate; + char *bus_name; + uint8_t device_endian; +@@ -162,6 +164,7 @@ struct VirtioDeviceClass { + int (*post_load)(VirtIODevice *vdev); + const VMStateDescription *vmsd; + bool (*primary_unplug_pending)(void *opaque); ++ struct vhost_dev *(*get_vhost)(VirtIODevice *vdev); + }; + + void virtio_instance_init_common(Object *proxy_obj, void *data, +-- +2.27.0 + diff --git a/virtio-crypto-verify-src-dst-buffer-length-for-sym-request.patch b/virtio-crypto-verify-src-dst-buffer-length-for-sym-request.patch new file mode 100644 index 00000000..76ce5d75 --- /dev/null +++ b/virtio-crypto-verify-src-dst-buffer-length-for-sym-request.patch @@ -0,0 +1,46 @@ +From 9110c9bf711a39b3c9a1bdbe2fc84f38930d3094 Mon Sep 17 00:00:00 2001 +From: zhenwei pi +Date: Thu, 3 Aug 2023 10:43:13 +0800 +Subject: [PATCH] virtio-crypto: verify src&dst buffer length for sym request + +For symmetric algorithms, the length of ciphertext must be as same +as the plaintext. +The missing verification of the src_len and the dst_len in +virtio_crypto_sym_op_helper() may lead buffer overflow/divulged. + +This patch is originally written by Yiming Tao for QEMU-SECURITY, +resend it(a few changes of error message) in qemu-devel. + +Fixes: CVE-2023-3180 +Fixes: 04b9b37edda("virtio-crypto: add data queue processing handler") +Cc: Gonglei +Cc: Mauro Matteo Cascella +Cc: Yiming Tao +Signed-off-by: zhenwei pi +Message-Id: <20230803024314.29962-2-pizhenwei@bytedance.com> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Signed-off-by: fangyi +--- + hw/virtio/virtio-crypto.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/hw/virtio/virtio-crypto.c b/hw/virtio/virtio-crypto.c +index 98304184cd..9f7dcc88ba 100644 +--- a/hw/virtio/virtio-crypto.c ++++ b/hw/virtio/virtio-crypto.c +@@ -466,6 +466,11 @@ virtio_crypto_sym_op_helper(VirtIODevice *vdev, + return NULL; + } + ++ if (unlikely(src_len != dst_len)) { ++ virtio_error(vdev, "sym request src len is different from dst len"); ++ return NULL; ++ } ++ + max_len = (uint64_t)iv_len + aad_len + src_len + dst_len + hash_result_len; + if (unlikely(max_len > vcrypto->conf.max_size)) { + virtio_error(vdev, "virtio-crypto too big length"); +-- +2.27.0 + diff --git a/virtio-fix-enable-vhost-user-build-on-non-Linux.patch b/virtio-fix-enable-vhost-user-build-on-non-Linux.patch new file mode 100644 index 00000000..c124baf6 --- /dev/null +++ b/virtio-fix-enable-vhost-user-build-on-non-Linux.patch @@ -0,0 +1,39 @@ +From 558472cd6040b5515baaf860b5bba0c1c511d18b Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Mon, 28 Mar 2022 17:58:27 +0200 +Subject: [PATCH] virtio: fix --enable-vhost-user build on non-Linux +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The vhost-shadow-virtqueue.c build requires include files from +linux-headers/, so it cannot be built on non-Linux systems. +Fortunately it is only needed by vhost-vdpa, so move it there. + +Acked-by: Eugenio Pérez +Acked-by: Jason Wang +Signed-off-by: Paolo Bonzini +Signed-off-by: fangyi +--- + hw/virtio/meson.build | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/hw/virtio/meson.build b/hw/virtio/meson.build +index c2e193f56d..c2da69616f 100644 +--- a/hw/virtio/meson.build ++++ b/hw/virtio/meson.build +@@ -11,9 +11,9 @@ softmmu_ss.add(when: 'CONFIG_ALL', if_true: files('vhost-stub.c')) + + virtio_ss = ss.source_set() + virtio_ss.add(files('virtio.c')) +-virtio_ss.add(when: 'CONFIG_VHOST', if_true: files('vhost.c', 'vhost-backend.c', 'vhost-shadow-virtqueue.c', 'vhost-iova-tree.c')) ++virtio_ss.add(when: 'CONFIG_VHOST', if_true: files('vhost.c', 'vhost-backend.c', 'vhost-iova-tree.c')) + virtio_ss.add(when: 'CONFIG_VHOST_USER', if_true: files('vhost-user.c')) +-virtio_ss.add(when: 'CONFIG_VHOST_VDPA', if_true: files('vhost-vdpa.c')) ++virtio_ss.add(when: 'CONFIG_VHOST_VDPA', if_true: files('vhost-shadow-virtqueue.c', 'vhost-vdpa.c')) + virtio_ss.add(when: 'CONFIG_VIRTIO_BALLOON', if_true: files('virtio-balloon.c')) + virtio_ss.add(when: 'CONFIG_VIRTIO_CRYPTO', if_true: files('virtio-crypto.c')) + virtio_ss.add(when: ['CONFIG_VIRTIO_CRYPTO', 'CONFIG_VIRTIO_PCI'], if_true: files('virtio-crypto-pci.c')) +-- +2.27.0 + diff --git a/virtio-i2c-Check-notifier-helpers-for-VIRTIO_CONFIG_.patch b/virtio-i2c-Check-notifier-helpers-for-VIRTIO_CONFIG_.patch new file mode 100644 index 00000000..79c916cd --- /dev/null +++ b/virtio-i2c-Check-notifier-helpers-for-VIRTIO_CONFIG_.patch @@ -0,0 +1,55 @@ +From 7f25adf1fd99b5b8f9455537d0c6108837ee25de Mon Sep 17 00:00:00 2001 +From: Viresh Kumar +Date: Tue, 18 Apr 2023 09:24:54 +0530 +Subject: [PATCH] virtio: i2c: Check notifier helpers for VIRTIO_CONFIG_IRQ_IDX + +Since the driver doesn't support interrupts, we must return early when +index is set to VIRTIO_CONFIG_IRQ_IDX. + +Fixes: 544f0278afca ("virtio: introduce macro VIRTIO_CONFIG_IRQ_IDX") +Signed-off-by: Viresh Kumar +Message-Id: +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Signed-off-by: fangyi +--- + hw/virtio/vhost-user-i2c.c | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +diff --git a/hw/virtio/vhost-user-i2c.c b/hw/virtio/vhost-user-i2c.c +index dcaf471115..19add4a707 100644 +--- a/hw/virtio/vhost-user-i2c.c ++++ b/hw/virtio/vhost-user-i2c.c +@@ -129,6 +129,14 @@ static void vu_i2c_guest_notifier_mask(VirtIODevice *vdev, int idx, bool mask) + { + VHostUserI2C *i2c = VHOST_USER_I2C(vdev); + ++ /* ++ * We don't support interrupts, return early if index is set to ++ * VIRTIO_CONFIG_IRQ_IDX. ++ */ ++ if (idx == VIRTIO_CONFIG_IRQ_IDX) { ++ return; ++ } ++ + vhost_virtqueue_mask(&i2c->vhost_dev, vdev, idx, mask); + } + +@@ -136,6 +144,14 @@ static bool vu_i2c_guest_notifier_pending(VirtIODevice *vdev, int idx) + { + VHostUserI2C *i2c = VHOST_USER_I2C(vdev); + ++ /* ++ * We don't support interrupts, return early if index is set to ++ * VIRTIO_CONFIG_IRQ_IDX. ++ */ ++ if (idx == VIRTIO_CONFIG_IRQ_IDX) { ++ return false; ++ } ++ + return vhost_virtqueue_pending(&i2c->vhost_dev, idx); + } + +-- +2.27.0 + diff --git a/virtio-introduce-macro-IRTIO_CONFIG_IRQ_IDX.patch b/virtio-introduce-macro-IRTIO_CONFIG_IRQ_IDX.patch new file mode 100644 index 00000000..c46da01c --- /dev/null +++ b/virtio-introduce-macro-IRTIO_CONFIG_IRQ_IDX.patch @@ -0,0 +1,166 @@ +From 438e224baf7c2debab5ac109739316d9db562e2c Mon Sep 17 00:00:00 2001 +From: fangyi +Date: Thu, 16 Nov 2023 09:54:50 +0800 +Subject: [PATCH] virtio: introduce macro IRTIO_CONFIG_IRQ_IDX + +To support configure interrupt for vhost-vdpa +Introduce VIRTIO_CONFIG_IRQ_IDX -1 as configure interrupt's queue index, +Then we can reuse the functions guest_notifier_mask and guest_notifier_pending. +Add the check of queue index in these drivers, if the driver does not support +configure interrupt, the function will just return + +Signed-off-by: Cindy Lu +Message-Id: <20211104164827.21911-2-lulu@redhat.com> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Signed-off-by: fangyi +--- + hw/display/vhost-user-gpu.c | 6 ++++++ + hw/net/virtio-net.c | 10 ++++++++-- + hw/virtio/vhost-user-fs.c | 6 ++++++ + hw/virtio/vhost-vsock-common.c | 6 ++++++ + hw/virtio/virtio-crypto.c | 6 ++++++ + include/hw/virtio/virtio.h | 3 +++ + 6 files changed, 35 insertions(+), 2 deletions(-) + +diff --git a/hw/display/vhost-user-gpu.c b/hw/display/vhost-user-gpu.c +index 49df56cd14..73ad3d84c9 100644 +--- a/hw/display/vhost-user-gpu.c ++++ b/hw/display/vhost-user-gpu.c +@@ -485,6 +485,9 @@ vhost_user_gpu_guest_notifier_pending(VirtIODevice *vdev, int idx) + { + VhostUserGPU *g = VHOST_USER_GPU(vdev); + ++ if (idx == VIRTIO_CONFIG_IRQ_IDX) { ++ return false; ++ } + return vhost_virtqueue_pending(&g->vhost->dev, idx); + } + +@@ -493,6 +496,9 @@ vhost_user_gpu_guest_notifier_mask(VirtIODevice *vdev, int idx, bool mask) + { + VhostUserGPU *g = VHOST_USER_GPU(vdev); + ++ if (idx == VIRTIO_CONFIG_IRQ_IDX) { ++ return; ++ } + vhost_virtqueue_mask(&g->vhost->dev, vdev, idx, mask); + } + +diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c +index 3bd786cc22..7537f44d10 100644 +--- a/hw/net/virtio-net.c ++++ b/hw/net/virtio-net.c +@@ -3195,6 +3195,9 @@ static bool virtio_net_guest_notifier_pending(VirtIODevice *vdev, int idx) + VirtIONet *n = VIRTIO_NET(vdev); + NetClientState *nc = qemu_get_subqueue(n->nic, vq2q(idx)); + assert(n->vhost_started); ++ if (idx == VIRTIO_CONFIG_IRQ_IDX) { ++ return false; ++ } + return vhost_net_virtqueue_pending(get_vhost_net(nc->peer), idx); + } + +@@ -3204,8 +3207,11 @@ static void virtio_net_guest_notifier_mask(VirtIODevice *vdev, int idx, + VirtIONet *n = VIRTIO_NET(vdev); + NetClientState *nc = qemu_get_subqueue(n->nic, vq2q(idx)); + assert(n->vhost_started); +- vhost_net_virtqueue_mask(get_vhost_net(nc->peer), +- vdev, idx, mask); ++ if (idx == VIRTIO_CONFIG_IRQ_IDX) { ++ return; ++ } ++ ++ vhost_net_virtqueue_mask(get_vhost_net(nc->peer), vdev, idx, mask); + } + + static void virtio_net_set_config_size(VirtIONet *n, uint64_t host_features) +diff --git a/hw/virtio/vhost-user-fs.c b/hw/virtio/vhost-user-fs.c +index fc7dcc96ef..90c2bc9c5d 100644 +--- a/hw/virtio/vhost-user-fs.c ++++ b/hw/virtio/vhost-user-fs.c +@@ -161,6 +161,9 @@ static void vuf_guest_notifier_mask(VirtIODevice *vdev, int idx, + { + VHostUserFS *fs = VHOST_USER_FS(vdev); + ++ if (idx == VIRTIO_CONFIG_IRQ_IDX) { ++ return; ++ } + vhost_virtqueue_mask(&fs->vhost_dev, vdev, idx, mask); + } + +@@ -168,6 +171,9 @@ static bool vuf_guest_notifier_pending(VirtIODevice *vdev, int idx) + { + VHostUserFS *fs = VHOST_USER_FS(vdev); + ++ if (idx == VIRTIO_CONFIG_IRQ_IDX) { ++ return false; ++ } + return vhost_virtqueue_pending(&fs->vhost_dev, idx); + } + +diff --git a/hw/virtio/vhost-vsock-common.c b/hw/virtio/vhost-vsock-common.c +index ed706681ac..b1f0d46209 100644 +--- a/hw/virtio/vhost-vsock-common.c ++++ b/hw/virtio/vhost-vsock-common.c +@@ -125,6 +125,9 @@ static void vhost_vsock_common_guest_notifier_mask(VirtIODevice *vdev, int idx, + { + VHostVSockCommon *vvc = VHOST_VSOCK_COMMON(vdev); + ++ if (idx == VIRTIO_CONFIG_IRQ_IDX) { ++ return; ++ } + vhost_virtqueue_mask(&vvc->vhost_dev, vdev, idx, mask); + } + +@@ -133,6 +136,9 @@ static bool vhost_vsock_common_guest_notifier_pending(VirtIODevice *vdev, + { + VHostVSockCommon *vvc = VHOST_VSOCK_COMMON(vdev); + ++ if (idx == VIRTIO_CONFIG_IRQ_IDX) { ++ return false; ++ } + return vhost_virtqueue_pending(&vvc->vhost_dev, idx); + } + +diff --git a/hw/virtio/virtio-crypto.c b/hw/virtio/virtio-crypto.c +index 274c7b4dea..52ba34ef1e 100644 +--- a/hw/virtio/virtio-crypto.c ++++ b/hw/virtio/virtio-crypto.c +@@ -953,6 +953,9 @@ static void virtio_crypto_guest_notifier_mask(VirtIODevice *vdev, int idx, + + assert(vcrypto->vhost_started); + ++ if (idx == VIRTIO_CONFIG_IRQ_IDX) { ++ return; ++ } + cryptodev_vhost_virtqueue_mask(vdev, queue, idx, mask); + } + +@@ -963,6 +966,9 @@ static bool virtio_crypto_guest_notifier_pending(VirtIODevice *vdev, int idx) + + assert(vcrypto->vhost_started); + ++ if (idx == VIRTIO_CONFIG_IRQ_IDX) { ++ return false; ++ } + return cryptodev_vhost_virtqueue_pending(vdev, queue, idx); + } + +diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h +index 7472145821..c113a5b864 100644 +--- a/include/hw/virtio/virtio.h ++++ b/include/hw/virtio/virtio.h +@@ -68,6 +68,9 @@ typedef struct VirtQueueElement + + #define VIRTIO_NO_VECTOR 0xffff + ++/* special index value used internally for config irqs */ ++#define VIRTIO_CONFIG_IRQ_IDX -1 ++ + #define TYPE_VIRTIO_DEVICE "virtio-device" + OBJECT_DECLARE_TYPE(VirtIODevice, VirtioDeviceClass, VIRTIO_DEVICE) + +-- +2.27.0 + diff --git a/virtio-introduce-macro-VIRTIO_CONFIG_IRQ_IDX.patch b/virtio-introduce-macro-VIRTIO_CONFIG_IRQ_IDX.patch new file mode 100644 index 00000000..67c848be --- /dev/null +++ b/virtio-introduce-macro-VIRTIO_CONFIG_IRQ_IDX.patch @@ -0,0 +1,227 @@ +From 61630772adbe254719e312fb7704a8edd00cc72b Mon Sep 17 00:00:00 2001 +From: Cindy Lu +Date: Thu, 22 Dec 2022 15:04:42 +0800 +Subject: [PATCH] virtio: introduce macro VIRTIO_CONFIG_IRQ_IDX + +To support configure interrupt for vhost-vdpa +Introduce VIRTIO_CONFIG_IRQ_IDX -1 as configure interrupt's queue index, +Then we can reuse the functions guest_notifier_mask and guest_notifier_pending. +Add the check of queue index in these drivers, if the driver does not support +configure interrupt, the function will just return + +Signed-off-by: Cindy Lu +Message-Id: <20221222070451.936503-2-lulu@redhat.com> +Acked-by: Jason Wang +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Signed-off-by: fangyi +--- + hw/display/vhost-user-gpu.c | 18 ++++++++++++++++++ + hw/net/virtio-net.c | 22 ++++++++++++++++++++-- + hw/virtio/vhost-user-fs.c | 18 ++++++++++++++++++ + hw/virtio/vhost-vsock-common.c | 18 ++++++++++++++++++ + hw/virtio/virtio-crypto.c | 18 ++++++++++++++++++ + include/hw/virtio/virtio.h | 3 +++ + 6 files changed, 95 insertions(+), 2 deletions(-) + +diff --git a/hw/display/vhost-user-gpu.c b/hw/display/vhost-user-gpu.c +index 6e93b463d6..1c78272a83 100644 +--- a/hw/display/vhost-user-gpu.c ++++ b/hw/display/vhost-user-gpu.c +@@ -485,6 +485,15 @@ vhost_user_gpu_guest_notifier_pending(VirtIODevice *vdev, int idx) + { + VhostUserGPU *g = VHOST_USER_GPU(vdev); + ++ /* ++ * Add the check for configure interrupt, Use VIRTIO_CONFIG_IRQ_IDX -1 ++ * as the Marco of configure interrupt's IDX, If this driver does not ++ * support, the function will return ++ */ ++ ++ if (idx == VIRTIO_CONFIG_IRQ_IDX) { ++ return false; ++ } + return vhost_virtqueue_pending(&g->vhost->dev, idx); + } + +@@ -493,6 +502,15 @@ vhost_user_gpu_guest_notifier_mask(VirtIODevice *vdev, int idx, bool mask) + { + VhostUserGPU *g = VHOST_USER_GPU(vdev); + ++ /* ++ * Add the check for configure interrupt, Use VIRTIO_CONFIG_IRQ_IDX -1 ++ * as the Marco of configure interrupt's IDX, If this driver does not ++ * support, the function will return ++ */ ++ ++ if (idx == VIRTIO_CONFIG_IRQ_IDX) { ++ return; ++ } + vhost_virtqueue_mask(&g->vhost->dev, vdev, idx, mask); + } + +diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c +index 867a1e77dc..304f501da5 100644 +--- a/hw/net/virtio-net.c ++++ b/hw/net/virtio-net.c +@@ -3232,6 +3232,15 @@ static bool virtio_net_guest_notifier_pending(VirtIODevice *vdev, int idx) + } else { + nc = qemu_get_subqueue(n->nic, vq2q(idx)); + } ++ /* ++ * Add the check for configure interrupt, Use VIRTIO_CONFIG_IRQ_IDX -1 ++ * as the Marco of configure interrupt's IDX, If this driver does not ++ * support, the function will return false ++ */ ++ ++ if (idx == VIRTIO_CONFIG_IRQ_IDX) { ++ return false; ++ } + return vhost_net_virtqueue_pending(get_vhost_net(nc->peer), idx); + } + +@@ -3255,8 +3264,17 @@ static void virtio_net_guest_notifier_mask(VirtIODevice *vdev, int idx, + } else { + nc = qemu_get_subqueue(n->nic, vq2q(idx)); + } +- vhost_net_virtqueue_mask(get_vhost_net(nc->peer), +- vdev, idx, mask); ++ /* ++ *Add the check for configure interrupt, Use VIRTIO_CONFIG_IRQ_IDX -1 ++ * as the Marco of configure interrupt's IDX, If this driver does not ++ * support, the function will return ++ */ ++ ++ if (idx == VIRTIO_CONFIG_IRQ_IDX) { ++ return; ++ } ++ ++ vhost_net_virtqueue_mask(get_vhost_net(nc->peer), vdev, idx, mask); + } + + static void virtio_net_set_config_size(VirtIONet *n, uint64_t host_features) +diff --git a/hw/virtio/vhost-user-fs.c b/hw/virtio/vhost-user-fs.c +index c2739557f2..0c6ecd3b4f 100644 +--- a/hw/virtio/vhost-user-fs.c ++++ b/hw/virtio/vhost-user-fs.c +@@ -161,6 +161,15 @@ static void vuf_guest_notifier_mask(VirtIODevice *vdev, int idx, + { + VHostUserFS *fs = VHOST_USER_FS(vdev); + ++ /* ++ * Add the check for configure interrupt, Use VIRTIO_CONFIG_IRQ_IDX -1 ++ * as the Marco of configure interrupt's IDX, If this driver does not ++ * support, the function will return ++ */ ++ ++ if (idx == VIRTIO_CONFIG_IRQ_IDX) { ++ return; ++ } + vhost_virtqueue_mask(&fs->vhost_dev, vdev, idx, mask); + } + +@@ -168,6 +177,15 @@ static bool vuf_guest_notifier_pending(VirtIODevice *vdev, int idx) + { + VHostUserFS *fs = VHOST_USER_FS(vdev); + ++ /* ++ * Add the check for configure interrupt, Use VIRTIO_CONFIG_IRQ_IDX -1 ++ * as the Marco of configure interrupt's IDX, If this driver does not ++ * support, the function will return ++ */ ++ ++ if (idx == VIRTIO_CONFIG_IRQ_IDX) { ++ return false; ++ } + return vhost_virtqueue_pending(&fs->vhost_dev, idx); + } + +diff --git a/hw/virtio/vhost-vsock-common.c b/hw/virtio/vhost-vsock-common.c +index 42e4db4712..e4a8d90f4c 100644 +--- a/hw/virtio/vhost-vsock-common.c ++++ b/hw/virtio/vhost-vsock-common.c +@@ -125,6 +125,15 @@ static void vhost_vsock_common_guest_notifier_mask(VirtIODevice *vdev, int idx, + { + VHostVSockCommon *vvc = VHOST_VSOCK_COMMON(vdev); + ++ /* ++ * Add the check for configure interrupt, Use VIRTIO_CONFIG_IRQ_IDX -1 ++ * as the Marco of configure interrupt's IDX, If this driver does not ++ * support, the function will return ++ */ ++ ++ if (idx == VIRTIO_CONFIG_IRQ_IDX) { ++ return; ++ } + vhost_virtqueue_mask(&vvc->vhost_dev, vdev, idx, mask); + } + +@@ -133,6 +142,15 @@ static bool vhost_vsock_common_guest_notifier_pending(VirtIODevice *vdev, + { + VHostVSockCommon *vvc = VHOST_VSOCK_COMMON(vdev); + ++ /* ++ * Add the check for configure interrupt, Use VIRTIO_CONFIG_IRQ_IDX -1 ++ * as the Marco of configure interrupt's IDX, If this driver does not ++ * support, the function will return ++ */ ++ ++ if (idx == VIRTIO_CONFIG_IRQ_IDX) { ++ return false; ++ } + return vhost_virtqueue_pending(&vvc->vhost_dev, idx); + } + +diff --git a/hw/virtio/virtio-crypto.c b/hw/virtio/virtio-crypto.c +index f9d849fa43..98304184cd 100644 +--- a/hw/virtio/virtio-crypto.c ++++ b/hw/virtio/virtio-crypto.c +@@ -953,6 +953,15 @@ static void virtio_crypto_guest_notifier_mask(VirtIODevice *vdev, int idx, + + assert(vcrypto->vhost_started); + ++ /* ++ * Add the check for configure interrupt, Use VIRTIO_CONFIG_IRQ_IDX -1 ++ * as the Marco of configure interrupt's IDX, If this driver does not ++ * support, the function will return ++ */ ++ ++ if (idx == VIRTIO_CONFIG_IRQ_IDX) { ++ return; ++ } + cryptodev_vhost_virtqueue_mask(vdev, queue, idx, mask); + } + +@@ -963,6 +972,15 @@ static bool virtio_crypto_guest_notifier_pending(VirtIODevice *vdev, int idx) + + assert(vcrypto->vhost_started); + ++ /* ++ * Add the check for configure interrupt, Use VIRTIO_CONFIG_IRQ_IDX -1 ++ * as the Marco of configure interrupt's IDX, If this driver does not ++ * support, the function will return ++ */ ++ ++ if (idx == VIRTIO_CONFIG_IRQ_IDX) { ++ return false; ++ } + return cryptodev_vhost_virtqueue_pending(vdev, queue, idx); + } + +diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h +index 223e82436f..91d1c3433a 100644 +--- a/include/hw/virtio/virtio.h ++++ b/include/hw/virtio/virtio.h +@@ -69,6 +69,9 @@ typedef struct VirtQueueElement + + #define VIRTIO_NO_VECTOR 0xffff + ++/* special index value used internally for config irqs */ ++#define VIRTIO_CONFIG_IRQ_IDX -1 ++ + #define TYPE_VIRTIO_DEVICE "virtio-device" + OBJECT_DECLARE_TYPE(VirtIODevice, VirtioDeviceClass, VIRTIO_DEVICE) + +-- +2.27.0 + diff --git a/virtio-iommu-Fix-the-partial-copy-of-probe-request.patch b/virtio-iommu-Fix-the-partial-copy-of-probe-request.patch new file mode 100644 index 00000000..4ae4766b --- /dev/null +++ b/virtio-iommu-Fix-the-partial-copy-of-probe-request.patch @@ -0,0 +1,60 @@ +From 1e73eaa18c753157046d22e43333fd9bc711eaa9 Mon Sep 17 00:00:00 2001 +From: tangbinzy +Date: Fri, 17 Nov 2023 09:55:19 +0000 +Subject: [PATCH] virtio-iommu: Fix the partial copy of probe request mainline + inclusion commit 45461aace83d961e933b27519b81d17b4c690514 category: bugfix + +--------------------------------------------------------------- + +The structure of probe request doesn't include the tail, this leads +to a few field missed to be copied. Currently this isn't an issue as +those missed field belong to reserved field, just in case reserved +field will be used in the future. + +Changed 4th parameter of virtio_iommu_iov_to_req() to receive size +of device-readable part. + +Fixes: 1733eebb9e75b ("virtio-iommu: Implement RESV_MEM probe request") +Signed-off-by: Zhenzhong Duan +Message-Id: <20220623023152.3473231-1-zhenzhong.duan@intel.com> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Reviewed-by: Jean-Philippe Brucker +Reviewed-by: Eric Auger + +Signed-off-by: tangbinzy +--- + hw/virtio/virtio-iommu.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/hw/virtio/virtio-iommu.c b/hw/virtio/virtio-iommu.c +index ed47d4cb64..ae33d93b11 100644 +--- a/hw/virtio/virtio-iommu.c ++++ b/hw/virtio/virtio-iommu.c +@@ -547,11 +547,10 @@ static int virtio_iommu_probe(VirtIOIOMMU *s, + + static int virtio_iommu_iov_to_req(struct iovec *iov, + unsigned int iov_cnt, +- void *req, size_t req_sz) ++ void *req, size_t payload_sz) + { +- size_t sz, payload_sz = req_sz - sizeof(struct virtio_iommu_req_tail); ++ size_t sz = iov_to_buf(iov, iov_cnt, 0, req, payload_sz); + +- sz = iov_to_buf(iov, iov_cnt, 0, req, payload_sz); + if (unlikely(sz != payload_sz)) { + return VIRTIO_IOMMU_S_INVAL; + } +@@ -564,7 +563,8 @@ static int virtio_iommu_handle_ ## __req(VirtIOIOMMU *s, \ + unsigned int iov_cnt) \ + { \ + struct virtio_iommu_req_ ## __req req; \ +- int ret = virtio_iommu_iov_to_req(iov, iov_cnt, &req, sizeof(req)); \ ++ int ret = virtio_iommu_iov_to_req(iov, iov_cnt, &req, \ ++ sizeof(req) - sizeof(struct virtio_iommu_req_tail));\ + \ + return ret ? ret : virtio_iommu_ ## __req(s, &req); \ + } +-- +2.27.0 + diff --git a/virtio-mmio-add-support-for-configure-interrupt-new.patch b/virtio-mmio-add-support-for-configure-interrupt-new.patch new file mode 100644 index 00000000..c0900ca3 --- /dev/null +++ b/virtio-mmio-add-support-for-configure-interrupt-new.patch @@ -0,0 +1,67 @@ +From 3f5311e1a80539a9cc21905fd3134709417e3747 Mon Sep 17 00:00:00 2001 +From: Cindy Lu +Date: Thu, 22 Dec 2022 15:04:50 +0800 +Subject: [PATCH] virtio-mmio: add support for configure interrupt + +Add configure interrupt support in virtio-mmio bus. +add function to set configure guest notifier. + +Signed-off-by: Cindy Lu +Message-Id: <20221222070451.936503-10-lulu@redhat.com> +Acked-by: Jason Wang +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Signed-off-by: fangyi +--- + hw/virtio/virtio-mmio.c | 27 +++++++++++++++++++++++++++ + 1 file changed, 27 insertions(+) + +diff --git a/hw/virtio/virtio-mmio.c b/hw/virtio/virtio-mmio.c +index 72da12fea5..508dd4cdb7 100644 +--- a/hw/virtio/virtio-mmio.c ++++ b/hw/virtio/virtio-mmio.c +@@ -673,7 +673,30 @@ static int virtio_mmio_set_guest_notifier(DeviceState *d, int n, bool assign, + + return 0; + } ++static int virtio_mmio_set_config_guest_notifier(DeviceState *d, bool assign, ++ bool with_irqfd) ++{ ++ VirtIOMMIOProxy *proxy = VIRTIO_MMIO(d); ++ VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); ++ VirtioDeviceClass *vdc = VIRTIO_DEVICE_GET_CLASS(vdev); ++ EventNotifier *notifier = virtio_config_get_guest_notifier(vdev); ++ int r = 0; + ++ if (assign) { ++ r = event_notifier_init(notifier, 0); ++ if (r < 0) { ++ return r; ++ } ++ virtio_config_set_guest_notifier_fd_handler(vdev, assign, with_irqfd); ++ } else { ++ virtio_config_set_guest_notifier_fd_handler(vdev, assign, with_irqfd); ++ event_notifier_cleanup(notifier); ++ } ++ if (vdc->guest_notifier_mask && vdev->use_guest_notifier_mask) { ++ vdc->guest_notifier_mask(vdev, VIRTIO_CONFIG_IRQ_IDX, !assign); ++ } ++ return r; ++} + static int virtio_mmio_set_guest_notifiers(DeviceState *d, int nvqs, + bool assign) + { +@@ -695,6 +718,10 @@ static int virtio_mmio_set_guest_notifiers(DeviceState *d, int nvqs, + goto assign_error; + } + } ++ r = virtio_mmio_set_config_guest_notifier(d, assign, with_irqfd); ++ if (r < 0) { ++ goto assign_error; ++ } + + return 0; + +-- +2.27.0 + diff --git a/virtio-mmio-add-support-for-configure-interrupt.patch b/virtio-mmio-add-support-for-configure-interrupt.patch new file mode 100644 index 00000000..0b4d4259 --- /dev/null +++ b/virtio-mmio-add-support-for-configure-interrupt.patch @@ -0,0 +1,66 @@ +From 89b329c73a84ca3f1376f8d8533154306bc50187 Mon Sep 17 00:00:00 2001 +From: fangyi +Date: Thu, 16 Nov 2023 09:54:54 +0800 +Subject: [PATCH] virtio-mmio: add support for configure interrupt + +Add configure interrupt support for virtio-mmio bus. This +interrupt will be working while the backend is vhost-vdpa + +Signed-off-by: Cindy Lu +Message-Id: <20211104164827.21911-10-lulu@redhat.com> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Signed-off-by: fangyi +--- + hw/virtio/virtio-mmio.c | 27 +++++++++++++++++++++++++++ + 1 file changed, 27 insertions(+) + +diff --git a/hw/virtio/virtio-mmio.c b/hw/virtio/virtio-mmio.c +index 72da12fea5..809132018b 100644 +--- a/hw/virtio/virtio-mmio.c ++++ b/hw/virtio/virtio-mmio.c +@@ -673,7 +673,30 @@ static int virtio_mmio_set_guest_notifier(DeviceState *d, int n, bool assign, + + return 0; + } ++static int virtio_mmio_set_config_guest_notifier(DeviceState *d, bool assign) ++{ ++ VirtIOMMIOProxy *proxy = VIRTIO_MMIO(d); ++ VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); ++ VirtioDeviceClass *vdc = VIRTIO_DEVICE_GET_CLASS(vdev); ++ bool with_irqfd = false; ++ EventNotifier *notifier = virtio_config_get_guest_notifier(vdev); ++ int r = 0; + ++ if (assign) { ++ r = event_notifier_init(notifier, 0); ++ if (r < 0) { ++ return r; ++ } ++ virtio_config_set_guest_notifier_fd_handler(vdev, assign, with_irqfd); ++ } else { ++ virtio_config_set_guest_notifier_fd_handler(vdev, assign, with_irqfd); ++ event_notifier_cleanup(notifier); ++ } ++ if (vdc->guest_notifier_mask && vdev->use_guest_notifier_mask) { ++ vdc->guest_notifier_mask(vdev, VIRTIO_CONFIG_IRQ_IDX, !assign); ++ } ++ return r; ++} + static int virtio_mmio_set_guest_notifiers(DeviceState *d, int nvqs, + bool assign) + { +@@ -695,6 +718,10 @@ static int virtio_mmio_set_guest_notifiers(DeviceState *d, int nvqs, + goto assign_error; + } + } ++ r = virtio_mmio_set_config_guest_notifier(d, assign); ++ if (r < 0) { ++ goto assign_error; ++ } + + return 0; + +-- +2.27.0 + diff --git a/virtio-net-Expose-MAC_TABLE_ENTRIES.patch b/virtio-net-Expose-MAC_TABLE_ENTRIES.patch new file mode 100644 index 00000000..15e74057 --- /dev/null +++ b/virtio-net-Expose-MAC_TABLE_ENTRIES.patch @@ -0,0 +1,50 @@ +From c8ee92256e06a7fec7cfff3bf18e21ec03016613 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= +Date: Wed, 20 Jul 2022 08:59:27 +0200 +Subject: [PATCH] virtio-net: Expose MAC_TABLE_ENTRIES +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +vhost-vdpa control virtqueue needs to know the maximum entries supported +by the virtio-net device, so we know if it is possible to apply the +filter. + +Signed-off-by: Eugenio Pérez +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Jason Wang +Signed-off-by: fangyi +--- + hw/net/virtio-net.c | 1 - + include/hw/virtio/virtio-net.h | 3 +++ + 2 files changed, 3 insertions(+), 1 deletion(-) + +diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c +index 512b37eb76..36d24b47bb 100644 +--- a/hw/net/virtio-net.c ++++ b/hw/net/virtio-net.c +@@ -48,7 +48,6 @@ + + #define VIRTIO_NET_VM_VERSION 11 + +-#define MAC_TABLE_ENTRIES 64 + #define MAX_VLAN (1 << 12) /* Per 802.1Q definition */ + + /* previously fixed value */ +diff --git a/include/hw/virtio/virtio-net.h b/include/hw/virtio/virtio-net.h +index eb87032627..cce1c554f7 100644 +--- a/include/hw/virtio/virtio-net.h ++++ b/include/hw/virtio/virtio-net.h +@@ -35,6 +35,9 @@ OBJECT_DECLARE_SIMPLE_TYPE(VirtIONet, VIRTIO_NET) + * and latency. */ + #define TX_BURST 256 + ++/* Maximum VIRTIO_NET_CTRL_MAC_TABLE_SET unicast + multicast entries. */ ++#define MAC_TABLE_ENTRIES 64 ++ + typedef struct virtio_net_conf + { + uint32_t txtimer; +-- +2.27.0 + diff --git a/virtio-net-Expose-ctrl-virtqueue-logic.patch b/virtio-net-Expose-ctrl-virtqueue-logic.patch new file mode 100644 index 00000000..fc50d200 --- /dev/null +++ b/virtio-net-Expose-ctrl-virtqueue-logic.patch @@ -0,0 +1,149 @@ +From 4987c967fb3b9b403bde7a1103f5ea1bf20445c7 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= +Date: Wed, 20 Jul 2022 08:59:28 +0200 +Subject: [PATCH] virtio-net: Expose ctrl virtqueue logic +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This allows external vhost-net devices to modify the state of the +VirtIO device model once the vhost-vdpa device has acknowledged the +control commands. + +Signed-off-by: Eugenio Pérez +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Jason Wang +Signed-off-by: fangyi +--- + hw/net/virtio-net.c | 83 ++++++++++++++++++++-------------- + include/hw/virtio/virtio-net.h | 4 ++ + 2 files changed, 53 insertions(+), 34 deletions(-) + +diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c +index 36d24b47bb..999072921d 100644 +--- a/hw/net/virtio-net.c ++++ b/hw/net/virtio-net.c +@@ -1452,56 +1452,71 @@ static int virtio_net_handle_mq(VirtIONet *n, uint8_t cmd, + return VIRTIO_NET_OK; + } + +-static void virtio_net_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq) ++size_t virtio_net_handle_ctrl_iov(VirtIODevice *vdev, ++ const struct iovec *in_sg, unsigned in_num, ++ const struct iovec *out_sg, ++ unsigned out_num) + { + VirtIONet *n = VIRTIO_NET(vdev); + struct virtio_net_ctrl_hdr ctrl; + virtio_net_ctrl_ack status = VIRTIO_NET_ERR; +- VirtQueueElement *elem; + size_t s; + struct iovec *iov, *iov2; +- unsigned int iov_cnt; ++ ++ if (iov_size(in_sg, in_num) < sizeof(status) || ++ iov_size(out_sg, out_num) < sizeof(ctrl)) { ++ virtio_error(vdev, "virtio-net ctrl missing headers"); ++ return 0; ++ } ++ ++ iov2 = iov = g_memdup(out_sg, sizeof(struct iovec) * out_num); ++ s = iov_to_buf(iov, out_num, 0, &ctrl, sizeof(ctrl)); ++ iov_discard_front(&iov, &out_num, sizeof(ctrl)); ++ if (s != sizeof(ctrl)) { ++ status = VIRTIO_NET_ERR; ++ } else if (ctrl.class == VIRTIO_NET_CTRL_RX) { ++ status = virtio_net_handle_rx_mode(n, ctrl.cmd, iov, out_num); ++ } else if (ctrl.class == VIRTIO_NET_CTRL_MAC) { ++ status = virtio_net_handle_mac(n, ctrl.cmd, iov, out_num); ++ } else if (ctrl.class == VIRTIO_NET_CTRL_VLAN) { ++ status = virtio_net_handle_vlan_table(n, ctrl.cmd, iov, out_num); ++ } else if (ctrl.class == VIRTIO_NET_CTRL_ANNOUNCE) { ++ status = virtio_net_handle_announce(n, ctrl.cmd, iov, out_num); ++ } else if (ctrl.class == VIRTIO_NET_CTRL_MQ) { ++ status = virtio_net_handle_mq(n, ctrl.cmd, iov, out_num); ++ } else if (ctrl.class == VIRTIO_NET_CTRL_GUEST_OFFLOADS) { ++ status = virtio_net_handle_offloads(n, ctrl.cmd, iov, out_num); ++ } ++ ++ s = iov_from_buf(in_sg, in_num, 0, &status, sizeof(status)); ++ assert(s == sizeof(status)); ++ ++ g_free(iov2); ++ return sizeof(status); ++} ++ ++static void virtio_net_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq) ++{ ++ VirtQueueElement *elem; + + for (;;) { ++ size_t written; + elem = virtqueue_pop(vq, sizeof(VirtQueueElement)); + if (!elem) { + break; + } +- if (iov_size(elem->in_sg, elem->in_num) < sizeof(status) || +- iov_size(elem->out_sg, elem->out_num) < sizeof(ctrl)) { +- virtio_error(vdev, "virtio-net ctrl missing headers"); ++ ++ written = virtio_net_handle_ctrl_iov(vdev, elem->in_sg, elem->in_num, ++ elem->out_sg, elem->out_num); ++ if (written > 0) { ++ virtqueue_push(vq, elem, written); ++ virtio_notify(vdev, vq); ++ g_free(elem); ++ } else { + virtqueue_detach_element(vq, elem, 0); + g_free(elem); + break; + } +- +- iov_cnt = elem->out_num; +- iov2 = iov = g_memdup(elem->out_sg, sizeof(struct iovec) * elem->out_num); +- s = iov_to_buf(iov, iov_cnt, 0, &ctrl, sizeof(ctrl)); +- iov_discard_front(&iov, &iov_cnt, sizeof(ctrl)); +- if (s != sizeof(ctrl)) { +- status = VIRTIO_NET_ERR; +- } else if (ctrl.class == VIRTIO_NET_CTRL_RX) { +- status = virtio_net_handle_rx_mode(n, ctrl.cmd, iov, iov_cnt); +- } else if (ctrl.class == VIRTIO_NET_CTRL_MAC) { +- status = virtio_net_handle_mac(n, ctrl.cmd, iov, iov_cnt); +- } else if (ctrl.class == VIRTIO_NET_CTRL_VLAN) { +- status = virtio_net_handle_vlan_table(n, ctrl.cmd, iov, iov_cnt); +- } else if (ctrl.class == VIRTIO_NET_CTRL_ANNOUNCE) { +- status = virtio_net_handle_announce(n, ctrl.cmd, iov, iov_cnt); +- } else if (ctrl.class == VIRTIO_NET_CTRL_MQ) { +- status = virtio_net_handle_mq(n, ctrl.cmd, iov, iov_cnt); +- } else if (ctrl.class == VIRTIO_NET_CTRL_GUEST_OFFLOADS) { +- status = virtio_net_handle_offloads(n, ctrl.cmd, iov, iov_cnt); +- } +- +- s = iov_from_buf(elem->in_sg, elem->in_num, 0, &status, sizeof(status)); +- assert(s == sizeof(status)); +- +- virtqueue_push(vq, elem, sizeof(status)); +- virtio_notify(vdev, vq); +- g_free(iov2); +- g_free(elem); + } + } + +diff --git a/include/hw/virtio/virtio-net.h b/include/hw/virtio/virtio-net.h +index cce1c554f7..ef234ffe7e 100644 +--- a/include/hw/virtio/virtio-net.h ++++ b/include/hw/virtio/virtio-net.h +@@ -221,6 +221,10 @@ struct VirtIONet { + struct EBPFRSSContext ebpf_rss; + }; + ++size_t virtio_net_handle_ctrl_iov(VirtIODevice *vdev, ++ const struct iovec *in_sg, unsigned in_num, ++ const struct iovec *out_sg, ++ unsigned out_num); + void virtio_net_set_netclient_name(VirtIONet *n, const char *name, + const char *type); + +-- +2.27.0 + diff --git a/virtio-net-Update-virtio-net-curr_queue_pairs-in-vdp.patch b/virtio-net-Update-virtio-net-curr_queue_pairs-in-vdp.patch new file mode 100644 index 00000000..fb9f7adb --- /dev/null +++ b/virtio-net-Update-virtio-net-curr_queue_pairs-in-vdp.patch @@ -0,0 +1,53 @@ +From 49c90114e00fb1cbbe25eeaee825981210c24f41 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= +Date: Tue, 6 Sep 2022 17:07:18 +0200 +Subject: [PATCH] virtio-net: Update virtio-net curr_queue_pairs in vdpa + backends +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +It was returned as error before. Instead of it, simply update the +corresponding field so qemu can send it in the migration data. + +Signed-off-by: Eugenio Pérez +Acked-by: Si-Wei Liu +Signed-off-by: Jason Wang +Signed-off-by: fangyi +--- + hw/net/virtio-net.c | 17 ++++++----------- + 1 file changed, 6 insertions(+), 11 deletions(-) + +diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c +index 999072921d..867a1e77dc 100644 +--- a/hw/net/virtio-net.c ++++ b/hw/net/virtio-net.c +@@ -1431,19 +1431,14 @@ static int virtio_net_handle_mq(VirtIONet *n, uint8_t cmd, + return VIRTIO_NET_ERR; + } + +- /* Avoid changing the number of queue_pairs for vdpa device in +- * userspace handler. A future fix is needed to handle the mq +- * change in userspace handler with vhost-vdpa. Let's disable +- * the mq handling from userspace for now and only allow get +- * done through the kernel. Ripples may be seen when falling +- * back to userspace, but without doing it qemu process would +- * crash on a recursive entry to virtio_net_set_status(). +- */ ++ n->curr_queue_pairs = queue_pairs; + if (nc->peer && nc->peer->info->type == NET_CLIENT_DRIVER_VHOST_VDPA) { +- return VIRTIO_NET_ERR; ++ /* ++ * Avoid updating the backend for a vdpa device: We're only interested ++ * in updating the device model queues. ++ */ ++ return VIRTIO_NET_OK; + } +- +- n->curr_queue_pairs = queue_pairs; + /* stop the backend before changing the number of queue_pairs to avoid handling a + * disabled queue */ + virtio_net_set_status(vdev, vdev->status); +-- +2.27.0 + diff --git a/virtio-net-add-support-for-configure-interrupt-new.patch b/virtio-net-add-support-for-configure-interrupt-new.patch new file mode 100644 index 00000000..006222de --- /dev/null +++ b/virtio-net-add-support-for-configure-interrupt-new.patch @@ -0,0 +1,102 @@ +From e55e9f52865565415000834b4cacb741b0abb2d8 Mon Sep 17 00:00:00 2001 +From: Cindy Lu +Date: Thu, 22 Dec 2022 15:04:49 +0800 +Subject: [PATCH] virtio-net: add support for configure interrupt + +Add functions to support configure interrupt in virtio_net +Add the functions to support vhost_net_config_pending +and vhost_net_config_mask. + +Signed-off-by: Cindy Lu +Message-Id: <20221222070451.936503-9-lulu@redhat.com> +Acked-by: Jason Wang +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Signed-off-by: fangyi +--- + hw/net/vhost_net-stub.c | 9 +++++++++ + hw/net/vhost_net.c | 9 +++++++++ + hw/net/virtio-net.c | 4 ++-- + include/net/vhost_net.h | 2 ++ + 4 files changed, 22 insertions(+), 2 deletions(-) + +diff --git a/hw/net/vhost_net-stub.c b/hw/net/vhost_net-stub.c +index 199b09952a..db171829b4 100644 +--- a/hw/net/vhost_net-stub.c ++++ b/hw/net/vhost_net-stub.c +@@ -82,6 +82,15 @@ void vhost_net_virtqueue_mask(VHostNetState *net, VirtIODevice *dev, + { + } + ++bool vhost_net_config_pending(VHostNetState *net) ++{ ++ return false; ++} ++ ++void vhost_net_config_mask(VHostNetState *net, VirtIODevice *dev, bool mask) ++{ ++} ++ + int vhost_net_notify_migration_done(struct vhost_net *net, char* mac_addr) + { + return -1; +diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c +index c950d7e2e8..d226dba83c 100644 +--- a/hw/net/vhost_net.c ++++ b/hw/net/vhost_net.c +@@ -541,6 +541,15 @@ void vhost_net_virtqueue_mask(VHostNetState *net, VirtIODevice *dev, + vhost_virtqueue_mask(&net->dev, dev, idx, mask); + } + ++bool vhost_net_config_pending(VHostNetState *net) ++{ ++ return vhost_config_pending(&net->dev); ++} ++ ++void vhost_net_config_mask(VHostNetState *net, VirtIODevice *dev, bool mask) ++{ ++ vhost_config_mask(&net->dev, dev, mask); ++} + VHostNetState *get_vhost_net(NetClientState *nc) + { + VHostNetState *vhost_net = 0; +diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c +index 304f501da5..bc26f5347a 100644 +--- a/hw/net/virtio-net.c ++++ b/hw/net/virtio-net.c +@@ -3239,7 +3239,7 @@ static bool virtio_net_guest_notifier_pending(VirtIODevice *vdev, int idx) + */ + + if (idx == VIRTIO_CONFIG_IRQ_IDX) { +- return false; ++ return vhost_net_config_pending(get_vhost_net(nc->peer)); + } + return vhost_net_virtqueue_pending(get_vhost_net(nc->peer), idx); + } +@@ -3271,9 +3271,9 @@ static void virtio_net_guest_notifier_mask(VirtIODevice *vdev, int idx, + */ + + if (idx == VIRTIO_CONFIG_IRQ_IDX) { ++ vhost_net_config_mask(get_vhost_net(nc->peer), vdev, mask); + return; + } +- + vhost_net_virtqueue_mask(get_vhost_net(nc->peer), vdev, idx, mask); + } + +diff --git a/include/net/vhost_net.h b/include/net/vhost_net.h +index 7bdbf484e4..1844f0ed46 100644 +--- a/include/net/vhost_net.h ++++ b/include/net/vhost_net.h +@@ -39,6 +39,8 @@ int vhost_net_set_config(struct vhost_net *net, const uint8_t *data, + bool vhost_net_virtqueue_pending(VHostNetState *net, int n); + void vhost_net_virtqueue_mask(VHostNetState *net, VirtIODevice *dev, + int idx, bool mask); ++bool vhost_net_config_pending(VHostNetState *net); ++void vhost_net_config_mask(VHostNetState *net, VirtIODevice *dev, bool mask); + int vhost_net_notify_migration_done(VHostNetState *net, char* mac_addr); + VHostNetState *get_vhost_net(NetClientState *nc); + +-- +2.27.0 + diff --git a/virtio-net-add-support-for-configure-interrupt.patch b/virtio-net-add-support-for-configure-interrupt.patch new file mode 100644 index 00000000..98ac5d22 --- /dev/null +++ b/virtio-net-add-support-for-configure-interrupt.patch @@ -0,0 +1,56 @@ +From 0ae5aeef8aa5bf2d32fdf393cf66c36172c3e974 Mon Sep 17 00:00:00 2001 +From: fangyi +Date: Thu, 16 Nov 2023 09:54:53 +0800 +Subject: [PATCH] virtio-net: add support for configure interrupt + +Add functions to support configure interrupt in virtio_net +The functions are config_pending and config_mask, while +this input idx is VIRTIO_CONFIG_IRQ_IDX will check the +function of configure interrupt. + +Signed-off-by: Cindy Lu +Message-Id: <20211104164827.21911-9-lulu@redhat.com> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Signed-off-by: fangyi +--- + hw/net/vhost_net.c | 9 +++++++++ + include/net/vhost_net.h | 2 ++ + 2 files changed, 11 insertions(+) + +diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c +index bea053a742..d5a92144bb 100644 +--- a/hw/net/vhost_net.c ++++ b/hw/net/vhost_net.c +@@ -524,6 +524,15 @@ void vhost_net_virtqueue_mask(VHostNetState *net, VirtIODevice *dev, + vhost_virtqueue_mask(&net->dev, dev, idx, mask); + } + ++bool vhost_net_config_pending(VHostNetState *net) ++{ ++ return vhost_config_pending(&net->dev); ++} ++ ++void vhost_net_config_mask(VHostNetState *net, VirtIODevice *dev, bool mask) ++{ ++ vhost_config_mask(&net->dev, dev, mask); ++} + VHostNetState *get_vhost_net(NetClientState *nc) + { + VHostNetState *vhost_net = 0; +diff --git a/include/net/vhost_net.h b/include/net/vhost_net.h +index 7bdbf484e4..1844f0ed46 100644 +--- a/include/net/vhost_net.h ++++ b/include/net/vhost_net.h +@@ -39,6 +39,8 @@ int vhost_net_set_config(struct vhost_net *net, const uint8_t *data, + bool vhost_net_virtqueue_pending(VHostNetState *net, int n); + void vhost_net_virtqueue_mask(VHostNetState *net, VirtIODevice *dev, + int idx, bool mask); ++bool vhost_net_config_pending(VHostNetState *net); ++void vhost_net_config_mask(VHostNetState *net, VirtIODevice *dev, bool mask); + int vhost_net_notify_migration_done(VHostNetState *net, char* mac_addr); + VHostNetState *get_vhost_net(NetClientState *nc); + +-- +2.27.0 + diff --git a/virtio-net-align-ctrl_vq-index-for-non-mq-guest-for-.patch b/virtio-net-align-ctrl_vq-index-for-non-mq-guest-for-.patch new file mode 100644 index 00000000..2c86d647 --- /dev/null +++ b/virtio-net-align-ctrl_vq-index-for-non-mq-guest-for-.patch @@ -0,0 +1,131 @@ +From 9bfeaccd2adb6bc4d4e7efacc508324112e5651f Mon Sep 17 00:00:00 2001 +From: Si-Wei Liu +Date: Fri, 6 May 2022 19:28:13 -0700 +Subject: [PATCH] virtio-net: align ctrl_vq index for non-mq guest for + vhost_vdpa + +With MQ enabled vdpa device and non-MQ supporting guest e.g. +booting vdpa with mq=on over OVMF of single vqp, below assert +failure is seen: + +../hw/virtio/vhost-vdpa.c:560: vhost_vdpa_get_vq_index: Assertion `idx >= dev->vq_index && idx < dev->vq_index + dev->nvqs' failed. + +0 0x00007f8ce3ff3387 in raise () at /lib64/libc.so.6 +1 0x00007f8ce3ff4a78 in abort () at /lib64/libc.so.6 +2 0x00007f8ce3fec1a6 in __assert_fail_base () at /lib64/libc.so.6 +3 0x00007f8ce3fec252 in () at /lib64/libc.so.6 +4 0x0000558f52d79421 in vhost_vdpa_get_vq_index (dev=, idx=) at ../hw/virtio/vhost-vdpa.c:563 +5 0x0000558f52d79421 in vhost_vdpa_get_vq_index (dev=, idx=) at ../hw/virtio/vhost-vdpa.c:558 +6 0x0000558f52d7329a in vhost_virtqueue_mask (hdev=0x558f55c01800, vdev=0x558f568f91f0, n=2, mask=) at ../hw/virtio/vhost.c:1557 +7 0x0000558f52c6b89a in virtio_pci_set_guest_notifier (d=d@entry=0x558f568f0f60, n=n@entry=2, assign=assign@entry=true, with_irqfd=with_irqfd@entry=false) + at ../hw/virtio/virtio-pci.c:974 +8 0x0000558f52c6c0d8 in virtio_pci_set_guest_notifiers (d=0x558f568f0f60, nvqs=3, assign=true) at ../hw/virtio/virtio-pci.c:1019 +9 0x0000558f52bf091d in vhost_net_start (dev=dev@entry=0x558f568f91f0, ncs=0x558f56937cd0, data_queue_pairs=data_queue_pairs@entry=1, cvq=cvq@entry=1) + at ../hw/net/vhost_net.c:361 +10 0x0000558f52d4e5e7 in virtio_net_set_status (status=, n=0x558f568f91f0) at ../hw/net/virtio-net.c:289 +11 0x0000558f52d4e5e7 in virtio_net_set_status (vdev=0x558f568f91f0, status=15 '\017') at ../hw/net/virtio-net.c:370 +12 0x0000558f52d6c4b2 in virtio_set_status (vdev=vdev@entry=0x558f568f91f0, val=val@entry=15 '\017') at ../hw/virtio/virtio.c:1945 +13 0x0000558f52c69eff in virtio_pci_common_write (opaque=0x558f568f0f60, addr=, val=, size=) at ../hw/virtio/virtio-pci.c:1292 +14 0x0000558f52d15d6e in memory_region_write_accessor (mr=0x558f568f19d0, addr=20, value=, size=1, shift=, mask=, attrs=...) + at ../softmmu/memory.c:492 +15 0x0000558f52d127de in access_with_adjusted_size (addr=addr@entry=20, value=value@entry=0x7f8cdbffe748, size=size@entry=1, access_size_min=, access_size_max=, access_fn=0x558f52d15cf0 , mr=0x558f568f19d0, attrs=...) at ../softmmu/memory.c:554 +16 0x0000558f52d157ef in memory_region_dispatch_write (mr=mr@entry=0x558f568f19d0, addr=20, data=, op=, attrs=attrs@entry=...) + at ../softmmu/memory.c:1504 +17 0x0000558f52d078e7 in flatview_write_continue (fv=fv@entry=0x7f8accbc3b90, addr=addr@entry=103079215124, attrs=..., ptr=ptr@entry=0x7f8ce6300028, len=len@entry=1, addr1=, l=, mr=0x558f568f19d0) at /home/opc/qemu-upstream/include/qemu/host-utils.h:165 +18 0x0000558f52d07b06 in flatview_write (fv=0x7f8accbc3b90, addr=103079215124, attrs=..., buf=0x7f8ce6300028, len=1) at ../softmmu/physmem.c:2822 +19 0x0000558f52d0b36b in address_space_write (as=, addr=, attrs=..., buf=buf@entry=0x7f8ce6300028, len=) + at ../softmmu/physmem.c:2914 +20 0x0000558f52d0b3da in address_space_rw (as=, addr=, attrs=..., + attrs@entry=..., buf=buf@entry=0x7f8ce6300028, len=, is_write=) at ../softmmu/physmem.c:2924 +21 0x0000558f52dced09 in kvm_cpu_exec (cpu=cpu@entry=0x558f55c2da60) at ../accel/kvm/kvm-all.c:2903 +22 0x0000558f52dcfabd in kvm_vcpu_thread_fn (arg=arg@entry=0x558f55c2da60) at ../accel/kvm/kvm-accel-ops.c:49 +23 0x0000558f52f9f04a in qemu_thread_start (args=) at ../util/qemu-thread-posix.c:556 +24 0x00007f8ce4392ea5 in start_thread () at /lib64/libpthread.so.0 +25 0x00007f8ce40bb9fd in clone () at /lib64/libc.so.6 + +The cause for the assert failure is due to that the vhost_dev index +for the ctrl vq was not aligned with actual one in use by the guest. +Upon multiqueue feature negotiation in virtio_net_set_multiqueue(), +if guest doesn't support multiqueue, the guest vq layout would shrink +to a single queue pair, consisting of 3 vqs in total (rx, tx and ctrl). +This results in ctrl_vq taking a different vhost_dev group index than +the default. We can map vq to the correct vhost_dev group by checking +if MQ is supported by guest and successfully negotiated. Since the +MQ feature is only present along with CTRL_VQ, we ensure the index +2 is only meant for the control vq while MQ is not supported by guest. + +Fixes: 22288fe ("virtio-net: vhost control virtqueue support") +Suggested-by: Jason Wang +Signed-off-by: Si-Wei Liu +Acked-by: Jason Wang +Message-Id: <1651890498-24478-3-git-send-email-si-wei.liu@oracle.com> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Signed-off-by: fangyi +--- + hw/net/virtio-net.c | 33 +++++++++++++++++++++++++++++++-- + 1 file changed, 31 insertions(+), 2 deletions(-) + +diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c +index 41bb4010b0..eed3fb5cd3 100644 +--- a/hw/net/virtio-net.c ++++ b/hw/net/virtio-net.c +@@ -14,6 +14,7 @@ + #include "qemu/osdep.h" + #include "qemu/atomic.h" + #include "qemu/iov.h" ++#include "qemu/log.h" + #include "qemu/main-loop.h" + #include "qemu/module.h" + #include "hw/virtio/virtio.h" +@@ -3193,8 +3194,22 @@ static NetClientInfo net_virtio_info = { + static bool virtio_net_guest_notifier_pending(VirtIODevice *vdev, int idx) + { + VirtIONet *n = VIRTIO_NET(vdev); +- NetClientState *nc = qemu_get_subqueue(n->nic, vq2q(idx)); ++ NetClientState *nc; + assert(n->vhost_started); ++ if (!virtio_vdev_has_feature(vdev, VIRTIO_NET_F_MQ) && idx == 2) { ++ /* Must guard against invalid features and bogus queue index ++ * from being set by malicious guest, or penetrated through ++ * buggy migration stream. ++ */ ++ if (!virtio_vdev_has_feature(vdev, VIRTIO_NET_F_CTRL_VQ)) { ++ qemu_log_mask(LOG_GUEST_ERROR, ++ "%s: bogus vq index ignored\n", __func__); ++ return false; ++ } ++ nc = qemu_get_subqueue(n->nic, n->max_queue_pairs); ++ } else { ++ nc = qemu_get_subqueue(n->nic, vq2q(idx)); ++ } + return vhost_net_virtqueue_pending(get_vhost_net(nc->peer), idx); + } + +@@ -3202,8 +3217,22 @@ static void virtio_net_guest_notifier_mask(VirtIODevice *vdev, int idx, + bool mask) + { + VirtIONet *n = VIRTIO_NET(vdev); +- NetClientState *nc = qemu_get_subqueue(n->nic, vq2q(idx)); ++ NetClientState *nc; + assert(n->vhost_started); ++ if (!virtio_vdev_has_feature(vdev, VIRTIO_NET_F_MQ) && idx == 2) { ++ /* Must guard against invalid features and bogus queue index ++ * from being set by malicious guest, or penetrated through ++ * buggy migration stream. ++ */ ++ if (!virtio_vdev_has_feature(vdev, VIRTIO_NET_F_CTRL_VQ)) { ++ qemu_log_mask(LOG_GUEST_ERROR, ++ "%s: bogus vq index ignored\n", __func__); ++ return; ++ } ++ nc = qemu_get_subqueue(n->nic, n->max_queue_pairs); ++ } else { ++ nc = qemu_get_subqueue(n->nic, vq2q(idx)); ++ } + vhost_net_virtqueue_mask(get_vhost_net(nc->peer), + vdev, idx, mask); + } +-- +2.27.0 + diff --git a/virtio-net-clear-guest_announce-feature-if-no-cvq-ba.patch b/virtio-net-clear-guest_announce-feature-if-no-cvq-ba.patch new file mode 100644 index 00000000..8ead1210 --- /dev/null +++ b/virtio-net-clear-guest_announce-feature-if-no-cvq-ba.patch @@ -0,0 +1,67 @@ +From 7c85ae20bc8a6bb2e08794d01e6f65af7626a05d Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= +Date: Tue, 24 Jan 2023 17:11:59 +0100 +Subject: [PATCH] virtio-net: clear guest_announce feature if no cvq backend +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Since GUEST_ANNOUNCE is emulated the feature bit could be set without +backend support. This happens in the vDPA case. + +However, backend vDPA parent may not have CVQ support. This causes an +incoherent feature set, and the driver may refuse to start. This +happens in virtio-net Linux driver. + +This may be solved differently in the future. Qemu is able to emulate a +CVQ just for guest_announce purposes, helping guest to notify the new +location with vDPA devices that does not support it. However, this is +left as a TODO as it is way more complex to backport. + +Tested with vdpa_net_sim, toggling manually VIRTIO_NET_F_CTRL_VQ in the +driver and migrating it with x-svq=on. + +Fixes: 980003debddd ("vdpa: do not handle VIRTIO_NET_F_GUEST_ANNOUNCE in vhost-vdpa") +Reported-by: Dawar, Gautam +Signed-off-by: Eugenio Pérez +Message-Id: <20230124161159.2182117-1-eperezma@redhat.com> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Reviewed-by: David Edmondson +Reviewed-by: Gautam Dawar +Tested-by: Gautam Dawar +Tested-by: Lei Yang +Signed-off-by: fangyi +--- + hw/net/virtio-net.c | 15 +++++++++++++++ + 1 file changed, 15 insertions(+) + +diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c +index bc26f5347a..ae37b3461b 100644 +--- a/hw/net/virtio-net.c ++++ b/hw/net/virtio-net.c +@@ -771,6 +771,21 @@ static uint64_t virtio_net_get_features(VirtIODevice *vdev, uint64_t features, + features |= (1ULL << VIRTIO_NET_F_MTU); + } + ++ /* ++ * Since GUEST_ANNOUNCE is emulated the feature bit could be set without ++ * enabled. This happens in the vDPA case. ++ * ++ * Make sure the feature set is not incoherent, as the driver could refuse ++ * to start. ++ * ++ * TODO: QEMU is able to emulate a CVQ just for guest_announce purposes, ++ * helping guest to notify the new location with vDPA devices that does not ++ * support it. ++ */ ++ if (!virtio_has_feature(vdev->backend_features, VIRTIO_NET_F_CTRL_VQ)) { ++ virtio_clear_feature(&features, VIRTIO_NET_F_GUEST_ANNOUNCE); ++ } ++ + return features; + } + +-- +2.27.0 + diff --git a/virtio-net-don-t-handle-mq-request-in-userspace-hand.patch b/virtio-net-don-t-handle-mq-request-in-userspace-hand.patch new file mode 100644 index 00000000..27e2366d --- /dev/null +++ b/virtio-net-don-t-handle-mq-request-in-userspace-hand.patch @@ -0,0 +1,97 @@ +From f45beb1e364dc0a6d42425d716f5e31b69d7710d Mon Sep 17 00:00:00 2001 +From: Si-Wei Liu +Date: Fri, 6 May 2022 19:28:18 -0700 +Subject: [PATCH] virtio-net: don't handle mq request in userspace handler for + vhost-vdpa + +virtio_queue_host_notifier_read() tends to read pending event +left behind on ioeventfd in the vhost_net_stop() path, and +attempts to handle outstanding kicks from userspace vq handler. +However, in the ctrl_vq handler, virtio_net_handle_mq() has a +recursive call into virtio_net_set_status(), which may lead to +segmentation fault as shown in below stack trace: + +0 0x000055f800df1780 in qdev_get_parent_bus (dev=0x0) at ../hw/core/qdev.c:376 +1 0x000055f800c68ad8 in virtio_bus_device_iommu_enabled (vdev=vdev@entry=0x0) at ../hw/virtio/virtio-bus.c:331 +2 0x000055f800d70d7f in vhost_memory_unmap (dev=) at ../hw/virtio/vhost.c:318 +3 0x000055f800d70d7f in vhost_memory_unmap (dev=, buffer=0x7fc19bec5240, len=2052, is_write=1, access_len=2052) at ../hw/virtio/vhost.c:336 +4 0x000055f800d71867 in vhost_virtqueue_stop (dev=dev@entry=0x55f8037ccc30, vdev=vdev@entry=0x55f8044ec590, vq=0x55f8037cceb0, idx=0) at ../hw/virtio/vhost.c:1241 +5 0x000055f800d7406c in vhost_dev_stop (hdev=hdev@entry=0x55f8037ccc30, vdev=vdev@entry=0x55f8044ec590) at ../hw/virtio/vhost.c:1839 +6 0x000055f800bf00a7 in vhost_net_stop_one (net=0x55f8037ccc30, dev=0x55f8044ec590) at ../hw/net/vhost_net.c:315 +7 0x000055f800bf0678 in vhost_net_stop (dev=dev@entry=0x55f8044ec590, ncs=0x55f80452bae0, data_queue_pairs=data_queue_pairs@entry=7, cvq=cvq@entry=1) + at ../hw/net/vhost_net.c:423 +8 0x000055f800d4e628 in virtio_net_set_status (status=, n=0x55f8044ec590) at ../hw/net/virtio-net.c:296 +9 0x000055f800d4e628 in virtio_net_set_status (vdev=vdev@entry=0x55f8044ec590, status=15 '\017') at ../hw/net/virtio-net.c:370 +10 0x000055f800d534d8 in virtio_net_handle_ctrl (iov_cnt=, iov=, cmd=0 '\000', n=0x55f8044ec590) at ../hw/net/virtio-net.c:1408 +11 0x000055f800d534d8 in virtio_net_handle_ctrl (vdev=0x55f8044ec590, vq=0x7fc1a7e888d0) at ../hw/net/virtio-net.c:1452 +12 0x000055f800d69f37 in virtio_queue_host_notifier_read (vq=0x7fc1a7e888d0) at ../hw/virtio/virtio.c:2331 +13 0x000055f800d69f37 in virtio_queue_host_notifier_read (n=n@entry=0x7fc1a7e8894c) at ../hw/virtio/virtio.c:3575 +14 0x000055f800c688e6 in virtio_bus_cleanup_host_notifier (bus=, n=n@entry=14) at ../hw/virtio/virtio-bus.c:312 +15 0x000055f800d73106 in vhost_dev_disable_notifiers (hdev=hdev@entry=0x55f8035b51b0, vdev=vdev@entry=0x55f8044ec590) + at ../../../include/hw/virtio/virtio-bus.h:35 +16 0x000055f800bf00b2 in vhost_net_stop_one (net=0x55f8035b51b0, dev=0x55f8044ec590) at ../hw/net/vhost_net.c:316 +17 0x000055f800bf0678 in vhost_net_stop (dev=dev@entry=0x55f8044ec590, ncs=0x55f80452bae0, data_queue_pairs=data_queue_pairs@entry=7, cvq=cvq@entry=1) + at ../hw/net/vhost_net.c:423 +18 0x000055f800d4e628 in virtio_net_set_status (status=, n=0x55f8044ec590) at ../hw/net/virtio-net.c:296 +19 0x000055f800d4e628 in virtio_net_set_status (vdev=0x55f8044ec590, status=15 '\017') at ../hw/net/virtio-net.c:370 +20 0x000055f800d6c4b2 in virtio_set_status (vdev=0x55f8044ec590, val=) at ../hw/virtio/virtio.c:1945 +21 0x000055f800d11d9d in vm_state_notify (running=running@entry=false, state=state@entry=RUN_STATE_SHUTDOWN) at ../softmmu/runstate.c:333 +22 0x000055f800d04e7a in do_vm_stop (state=state@entry=RUN_STATE_SHUTDOWN, send_stop=send_stop@entry=false) at ../softmmu/cpus.c:262 +23 0x000055f800d04e99 in vm_shutdown () at ../softmmu/cpus.c:280 +24 0x000055f800d126af in qemu_cleanup () at ../softmmu/runstate.c:812 +25 0x000055f800ad5b13 in main (argc=, argv=, envp=) at ../softmmu/main.c:51 + +For now, temporarily disable handling MQ request from the ctrl_vq +userspace hanlder to avoid the recursive virtio_net_set_status() +call. Some rework is needed to allow changing the number of +queues without going through a full virtio_net_set_status cycle, +particularly for vhost-vdpa backend. + +This patch will need to be reverted as soon as future patches of +having the change of #queues handled in userspace is merged. + +Fixes: 402378407db ("vhost-vdpa: multiqueue support") +Signed-off-by: Si-Wei Liu +Acked-by: Jason Wang +Message-Id: <1651890498-24478-8-git-send-email-si-wei.liu@oracle.com> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Signed-off-by: fangyi +--- + hw/net/virtio-net.c | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c +index eed3fb5cd3..512b37eb76 100644 +--- a/hw/net/virtio-net.c ++++ b/hw/net/virtio-net.c +@@ -1400,6 +1400,7 @@ static int virtio_net_handle_mq(VirtIONet *n, uint8_t cmd, + { + VirtIODevice *vdev = VIRTIO_DEVICE(n); + uint16_t queue_pairs; ++ NetClientState *nc = qemu_get_queue(n->nic); + + virtio_net_disable_rss(n); + if (cmd == VIRTIO_NET_CTRL_MQ_HASH_CONFIG) { +@@ -1431,6 +1432,18 @@ static int virtio_net_handle_mq(VirtIONet *n, uint8_t cmd, + return VIRTIO_NET_ERR; + } + ++ /* Avoid changing the number of queue_pairs for vdpa device in ++ * userspace handler. A future fix is needed to handle the mq ++ * change in userspace handler with vhost-vdpa. Let's disable ++ * the mq handling from userspace for now and only allow get ++ * done through the kernel. Ripples may be seen when falling ++ * back to userspace, but without doing it qemu process would ++ * crash on a recursive entry to virtio_net_set_status(). ++ */ ++ if (nc->peer && nc->peer->info->type == NET_CLIENT_DRIVER_VHOST_VDPA) { ++ return VIRTIO_NET_ERR; ++ } ++ + n->curr_queue_pairs = queue_pairs; + /* stop the backend before changing the number of queue_pairs to avoid handling a + * disabled queue */ +-- +2.27.0 + diff --git a/virtio-pci-add-support-for-configure-interrupt-new.patch b/virtio-pci-add-support-for-configure-interrupt-new.patch new file mode 100644 index 00000000..91715da5 --- /dev/null +++ b/virtio-pci-add-support-for-configure-interrupt-new.patch @@ -0,0 +1,261 @@ +From 7e8f9690b0558a99001d45751754df7caf2ff32b Mon Sep 17 00:00:00 2001 +From: Cindy Lu +Date: Thu, 22 Dec 2022 15:04:51 +0800 +Subject: [PATCH] virtio-pci: add support for configure interrupt + +Add process to handle the configure interrupt, The function's +logic is the same with vq interrupt.Add extra process to check +the configure interrupt + +Signed-off-by: Cindy Lu +Message-Id: <20221222070451.936503-11-lulu@redhat.com> +Acked-by: Jason Wang +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Signed-off-by: fangyi +--- + hw/virtio/virtio-pci.c | 118 ++++++++++++++++++++++++++++++++++------- + hw/virtio/virtio-pci.h | 4 +- + 2 files changed, 102 insertions(+), 20 deletions(-) + +diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c +index 75be770971..82706b8b32 100644 +--- a/hw/virtio/virtio-pci.c ++++ b/hw/virtio/virtio-pci.c +@@ -812,7 +812,8 @@ static int virtio_pci_get_notifier(VirtIOPCIProxy *proxy, int queue_no, + VirtQueue *vq; + + if (queue_no == VIRTIO_CONFIG_IRQ_IDX) { +- return -1; ++ *n = virtio_config_get_guest_notifier(vdev); ++ *vector = vdev->config_vector; + } else { + if (!virtio_queue_get_num(vdev, queue_no)) { + return -1; +@@ -872,7 +873,7 @@ undo: + } + return ret; + } +-static int kvm_virtio_pci_vector_use(VirtIOPCIProxy *proxy, int nvqs) ++static int kvm_virtio_pci_vector_vq_use(VirtIOPCIProxy *proxy, int nvqs) + { + int queue_no; + int ret = 0; +@@ -887,6 +888,10 @@ static int kvm_virtio_pci_vector_use(VirtIOPCIProxy *proxy, int nvqs) + return ret; + } + ++static int kvm_virtio_pci_vector_config_use(VirtIOPCIProxy *proxy) ++{ ++ return kvm_virtio_pci_vector_use_one(proxy, VIRTIO_CONFIG_IRQ_IDX); ++} + + static void kvm_virtio_pci_vector_release_one(VirtIOPCIProxy *proxy, + int queue_no) +@@ -911,7 +916,7 @@ static void kvm_virtio_pci_vector_release_one(VirtIOPCIProxy *proxy, + kvm_virtio_pci_vq_vector_release(proxy, vector); + } + +-static void kvm_virtio_pci_vector_release(VirtIOPCIProxy *proxy, int nvqs) ++static void kvm_virtio_pci_vector_vq_release(VirtIOPCIProxy *proxy, int nvqs) + { + int queue_no; + VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); +@@ -924,6 +929,11 @@ static void kvm_virtio_pci_vector_release(VirtIOPCIProxy *proxy, int nvqs) + } + } + ++static void kvm_virtio_pci_vector_config_release(VirtIOPCIProxy *proxy) ++{ ++ kvm_virtio_pci_vector_release_one(proxy, VIRTIO_CONFIG_IRQ_IDX); ++} ++ + static int virtio_pci_one_vector_unmask(VirtIOPCIProxy *proxy, + unsigned int queue_no, + unsigned int vector, +@@ -1005,9 +1015,19 @@ static int virtio_pci_vector_unmask(PCIDevice *dev, unsigned vector, + } + vq = virtio_vector_next_queue(vq); + } +- ++ /* unmask config intr */ ++ if (vector == vdev->config_vector) { ++ n = virtio_config_get_guest_notifier(vdev); ++ ret = virtio_pci_one_vector_unmask(proxy, VIRTIO_CONFIG_IRQ_IDX, vector, ++ msg, n); ++ if (ret < 0) { ++ goto undo_config; ++ } ++ } + return 0; +- ++undo_config: ++ n = virtio_config_get_guest_notifier(vdev); ++ virtio_pci_one_vector_mask(proxy, VIRTIO_CONFIG_IRQ_IDX, vector, n); + undo: + vq = virtio_vector_first_queue(vdev, vector); + while (vq && unmasked >= 0) { +@@ -1041,6 +1061,11 @@ static void virtio_pci_vector_mask(PCIDevice *dev, unsigned vector) + } + vq = virtio_vector_next_queue(vq); + } ++ ++ if (vector == vdev->config_vector) { ++ n = virtio_config_get_guest_notifier(vdev); ++ virtio_pci_one_vector_mask(proxy, VIRTIO_CONFIG_IRQ_IDX, vector, n); ++ } + } + + static void virtio_pci_vector_poll(PCIDevice *dev, +@@ -1072,6 +1097,34 @@ static void virtio_pci_vector_poll(PCIDevice *dev, + msix_set_pending(dev, vector); + } + } ++ /* poll the config intr */ ++ ret = virtio_pci_get_notifier(proxy, VIRTIO_CONFIG_IRQ_IDX, ¬ifier, ++ &vector); ++ if (ret < 0) { ++ return; ++ } ++ if (vector < vector_start || vector >= vector_end || ++ !msix_is_masked(dev, vector)) { ++ return; ++ } ++ if (k->guest_notifier_pending) { ++ if (k->guest_notifier_pending(vdev, VIRTIO_CONFIG_IRQ_IDX)) { ++ msix_set_pending(dev, vector); ++ } ++ } else if (event_notifier_test_and_clear(notifier)) { ++ msix_set_pending(dev, vector); ++ } ++} ++ ++void virtio_pci_set_guest_notifier_fd_handler(VirtIODevice *vdev, VirtQueue *vq, ++ int n, bool assign, ++ bool with_irqfd) ++{ ++ if (n == VIRTIO_CONFIG_IRQ_IDX) { ++ virtio_config_set_guest_notifier_fd_handler(vdev, assign, with_irqfd); ++ } else { ++ virtio_queue_set_guest_notifier_fd_handler(vq, assign, with_irqfd); ++ } + } + + static int virtio_pci_set_guest_notifier(DeviceState *d, int n, bool assign, +@@ -1080,17 +1133,25 @@ static int virtio_pci_set_guest_notifier(DeviceState *d, int n, bool assign, + VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d); + VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); + VirtioDeviceClass *vdc = VIRTIO_DEVICE_GET_CLASS(vdev); +- VirtQueue *vq = virtio_get_queue(vdev, n); +- EventNotifier *notifier = virtio_queue_get_guest_notifier(vq); ++ VirtQueue *vq = NULL; ++ EventNotifier *notifier = NULL; ++ ++ if (n == VIRTIO_CONFIG_IRQ_IDX) { ++ notifier = virtio_config_get_guest_notifier(vdev); ++ } else { ++ vq = virtio_get_queue(vdev, n); ++ notifier = virtio_queue_get_guest_notifier(vq); ++ } + + if (assign) { + int r = event_notifier_init(notifier, 0); + if (r < 0) { + return r; + } +- virtio_queue_set_guest_notifier_fd_handler(vq, true, with_irqfd); ++ virtio_pci_set_guest_notifier_fd_handler(vdev, vq, n, true, with_irqfd); + } else { +- virtio_queue_set_guest_notifier_fd_handler(vq, false, with_irqfd); ++ virtio_pci_set_guest_notifier_fd_handler(vdev, vq, n, false, ++ with_irqfd); + event_notifier_cleanup(notifier); + } + +@@ -1128,10 +1189,13 @@ static int virtio_pci_set_guest_notifiers(DeviceState *d, int nvqs, bool assign) + proxy->nvqs_with_notifiers = nvqs; + + /* Must unset vector notifier while guest notifier is still assigned */ +- if ((proxy->vector_irqfd || k->guest_notifier_mask) && !assign) { ++ if ((proxy->vector_irqfd || ++ (vdev->use_guest_notifier_mask && k->guest_notifier_mask)) && ++ !assign) { + msix_unset_vector_notifiers(&proxy->pci_dev); + if (proxy->vector_irqfd) { +- kvm_virtio_pci_vector_release(proxy, nvqs); ++ kvm_virtio_pci_vector_vq_release(proxy, nvqs); ++ kvm_virtio_pci_vector_config_release(proxy); + g_free(proxy->vector_irqfd); + proxy->vector_irqfd = NULL; + } +@@ -1147,20 +1211,30 @@ static int virtio_pci_set_guest_notifiers(DeviceState *d, int nvqs, bool assign) + goto assign_error; + } + } +- ++ r = virtio_pci_set_guest_notifier(d, VIRTIO_CONFIG_IRQ_IDX, assign, ++ with_irqfd); ++ if (r < 0) { ++ goto config_assign_error; ++ } + /* Must set vector notifier after guest notifier has been assigned */ +- if ((with_irqfd || k->guest_notifier_mask) && assign) { ++ if ((with_irqfd || ++ (vdev->use_guest_notifier_mask && k->guest_notifier_mask)) && ++ assign) { + if (with_irqfd) { + proxy->vector_irqfd = + g_malloc0(sizeof(*proxy->vector_irqfd) * + msix_nr_vectors_allocated(&proxy->pci_dev)); +- r = kvm_virtio_pci_vector_use(proxy, nvqs); ++ r = kvm_virtio_pci_vector_vq_use(proxy, nvqs); ++ if (r < 0) { ++ goto config_assign_error; ++ } ++ r = kvm_virtio_pci_vector_config_use(proxy); + if (r < 0) { +- goto assign_error; ++ goto config_error; + } + } +- r = msix_set_vector_notifiers(&proxy->pci_dev, +- virtio_pci_vector_unmask, ++ ++ r = msix_set_vector_notifiers(&proxy->pci_dev, virtio_pci_vector_unmask, + virtio_pci_vector_mask, + virtio_pci_vector_poll); + if (r < 0) { +@@ -1173,9 +1247,15 @@ static int virtio_pci_set_guest_notifiers(DeviceState *d, int nvqs, bool assign) + notifiers_error: + if (with_irqfd) { + assert(assign); +- kvm_virtio_pci_vector_release(proxy, nvqs); ++ kvm_virtio_pci_vector_vq_release(proxy, nvqs); + } +- ++config_error: ++ if (with_irqfd) { ++ kvm_virtio_pci_vector_config_release(proxy); ++ } ++config_assign_error: ++ virtio_pci_set_guest_notifier(d, VIRTIO_CONFIG_IRQ_IDX, !assign, ++ with_irqfd); + assign_error: + /* We get here on assignment failure. Recover by undoing for VQs 0 .. n. */ + assert(assign); +diff --git a/hw/virtio/virtio-pci.h b/hw/virtio/virtio-pci.h +index d95b1a13a5..6d8e071d8d 100644 +--- a/hw/virtio/virtio-pci.h ++++ b/hw/virtio/virtio-pci.h +@@ -256,5 +256,7 @@ void virtio_pci_types_register(const VirtioPCIDeviceTypeInfo *t); + * @fixed_queues. + */ + unsigned virtio_pci_optimal_num_queues(unsigned fixed_queues); +- ++void virtio_pci_set_guest_notifier_fd_handler(VirtIODevice *vdev, VirtQueue *vq, ++ int n, bool assign, ++ bool with_irqfd); + #endif +-- +2.27.0 + diff --git a/virtio-pci-add-support-for-configure-interrupt.patch b/virtio-pci-add-support-for-configure-interrupt.patch new file mode 100644 index 00000000..9aa53c1c --- /dev/null +++ b/virtio-pci-add-support-for-configure-interrupt.patch @@ -0,0 +1,218 @@ +From ce91ab22c29c56e4e18ee2e861b65657f7bb3e90 Mon Sep 17 00:00:00 2001 +From: fangyi +Date: Thu, 16 Nov 2023 09:54:54 +0800 +Subject: [PATCH] virtio-pci: add support for configure interrupt + +Add support for configure interrupt, The process is used kvm_irqfd_assign +to set the gsi to kernel. When the configure notifier was signal by +host, qemu will inject a msix interrupt to guest + +Signed-off-by: Cindy Lu +Message-Id: <20211104164827.21911-11-lulu@redhat.com> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Signed-off-by: fangyi +--- + hw/virtio/virtio-pci.c | 92 ++++++++++++++++++++++++++++++++++++------ + hw/virtio/virtio-pci.h | 4 +- + 2 files changed, 83 insertions(+), 13 deletions(-) + +diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c +index 75be770971..90237f523e 100644 +--- a/hw/virtio/virtio-pci.c ++++ b/hw/virtio/virtio-pci.c +@@ -812,7 +812,8 @@ static int virtio_pci_get_notifier(VirtIOPCIProxy *proxy, int queue_no, + VirtQueue *vq; + + if (queue_no == VIRTIO_CONFIG_IRQ_IDX) { +- return -1; ++ *n = virtio_config_get_guest_notifier(vdev); ++ *vector = vdev->config_vector; + } else { + if (!virtio_queue_get_num(vdev, queue_no)) { + return -1; +@@ -887,6 +888,10 @@ static int kvm_virtio_pci_vector_use(VirtIOPCIProxy *proxy, int nvqs) + return ret; + } + ++static int kvm_virtio_pci_vector_config_use(VirtIOPCIProxy *proxy) ++{ ++ return kvm_virtio_pci_vector_use_one(proxy, VIRTIO_CONFIG_IRQ_IDX); ++} + + static void kvm_virtio_pci_vector_release_one(VirtIOPCIProxy *proxy, + int queue_no) +@@ -924,6 +929,11 @@ static void kvm_virtio_pci_vector_release(VirtIOPCIProxy *proxy, int nvqs) + } + } + ++static void kvm_virtio_pci_vector_config_release(VirtIOPCIProxy *proxy) ++{ ++ kvm_virtio_pci_vector_release_one(proxy, VIRTIO_CONFIG_IRQ_IDX); ++} ++ + static int virtio_pci_one_vector_unmask(VirtIOPCIProxy *proxy, + unsigned int queue_no, + unsigned int vector, +@@ -1005,9 +1015,17 @@ static int virtio_pci_vector_unmask(PCIDevice *dev, unsigned vector, + } + vq = virtio_vector_next_queue(vq); + } +- ++ /* unmask config intr */ ++ n = virtio_config_get_guest_notifier(vdev); ++ ret = virtio_pci_one_vector_unmask(proxy, VIRTIO_CONFIG_IRQ_IDX, vector, ++ msg, n); ++ if (ret < 0) { ++ goto undo_config; ++ } + return 0; +- ++undo_config: ++ n = virtio_config_get_guest_notifier(vdev); ++ virtio_pci_one_vector_mask(proxy, VIRTIO_CONFIG_IRQ_IDX, vector, n); + undo: + vq = virtio_vector_first_queue(vdev, vector); + while (vq && unmasked >= 0) { +@@ -1041,6 +1059,8 @@ static void virtio_pci_vector_mask(PCIDevice *dev, unsigned vector) + } + vq = virtio_vector_next_queue(vq); + } ++ n = virtio_config_get_guest_notifier(vdev); ++ virtio_pci_one_vector_mask(proxy, VIRTIO_CONFIG_IRQ_IDX, vector, n); + } + + static void virtio_pci_vector_poll(PCIDevice *dev, +@@ -1072,6 +1092,34 @@ static void virtio_pci_vector_poll(PCIDevice *dev, + msix_set_pending(dev, vector); + } + } ++ /* poll the config intr */ ++ ret = virtio_pci_get_notifier(proxy, VIRTIO_CONFIG_IRQ_IDX, ¬ifier, ++ &vector); ++ if (ret < 0) { ++ return; ++ } ++ if (vector < vector_start || vector >= vector_end || ++ !msix_is_masked(dev, vector)) { ++ return; ++ } ++ if (k->guest_notifier_pending) { ++ if (k->guest_notifier_pending(vdev, VIRTIO_CONFIG_IRQ_IDX)) { ++ msix_set_pending(dev, vector); ++ } ++ } else if (event_notifier_test_and_clear(notifier)) { ++ msix_set_pending(dev, vector); ++ } ++} ++ ++void virtio_pci_set_guest_notifier_fd_handler(VirtIODevice *vdev, VirtQueue *vq, ++ int n, bool assign, ++ bool with_irqfd) ++{ ++ if (n == VIRTIO_CONFIG_IRQ_IDX) { ++ virtio_config_set_guest_notifier_fd_handler(vdev, assign, with_irqfd); ++ } else { ++ virtio_queue_set_guest_notifier_fd_handler(vq, assign, with_irqfd); ++ } + } + + static int virtio_pci_set_guest_notifier(DeviceState *d, int n, bool assign, +@@ -1080,17 +1128,25 @@ static int virtio_pci_set_guest_notifier(DeviceState *d, int n, bool assign, + VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d); + VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); + VirtioDeviceClass *vdc = VIRTIO_DEVICE_GET_CLASS(vdev); +- VirtQueue *vq = virtio_get_queue(vdev, n); +- EventNotifier *notifier = virtio_queue_get_guest_notifier(vq); ++ VirtQueue *vq = NULL; ++ EventNotifier *notifier = NULL; ++ ++ if (n == VIRTIO_CONFIG_IRQ_IDX) { ++ notifier = virtio_config_get_guest_notifier(vdev); ++ } else { ++ vq = virtio_get_queue(vdev, n); ++ notifier = virtio_queue_get_guest_notifier(vq); ++ } + + if (assign) { + int r = event_notifier_init(notifier, 0); + if (r < 0) { + return r; + } +- virtio_queue_set_guest_notifier_fd_handler(vq, true, with_irqfd); ++ virtio_pci_set_guest_notifier_fd_handler(vdev, vq, n, true, with_irqfd); + } else { +- virtio_queue_set_guest_notifier_fd_handler(vq, false, with_irqfd); ++ virtio_pci_set_guest_notifier_fd_handler(vdev, vq, n, false, ++ with_irqfd); + event_notifier_cleanup(notifier); + } + +@@ -1132,6 +1188,7 @@ static int virtio_pci_set_guest_notifiers(DeviceState *d, int nvqs, bool assign) + msix_unset_vector_notifiers(&proxy->pci_dev); + if (proxy->vector_irqfd) { + kvm_virtio_pci_vector_release(proxy, nvqs); ++ kvm_virtio_pci_vector_config_release(proxy); + g_free(proxy->vector_irqfd); + proxy->vector_irqfd = NULL; + } +@@ -1147,7 +1204,11 @@ static int virtio_pci_set_guest_notifiers(DeviceState *d, int nvqs, bool assign) + goto assign_error; + } + } +- ++ r = virtio_pci_set_guest_notifier(d, VIRTIO_CONFIG_IRQ_IDX, assign, ++ with_irqfd); ++ if (r < 0) { ++ goto config_assign_error; ++ } + /* Must set vector notifier after guest notifier has been assigned */ + if ((with_irqfd || k->guest_notifier_mask) && assign) { + if (with_irqfd) { +@@ -1156,11 +1217,14 @@ static int virtio_pci_set_guest_notifiers(DeviceState *d, int nvqs, bool assign) + msix_nr_vectors_allocated(&proxy->pci_dev)); + r = kvm_virtio_pci_vector_use(proxy, nvqs); + if (r < 0) { +- goto assign_error; ++ goto config_assign_error; + } + } +- r = msix_set_vector_notifiers(&proxy->pci_dev, +- virtio_pci_vector_unmask, ++ r = kvm_virtio_pci_vector_config_use(proxy); ++ if (r < 0) { ++ goto config_error; ++ } ++ r = msix_set_vector_notifiers(&proxy->pci_dev, virtio_pci_vector_unmask, + virtio_pci_vector_mask, + virtio_pci_vector_poll); + if (r < 0) { +@@ -1175,7 +1239,11 @@ notifiers_error: + assert(assign); + kvm_virtio_pci_vector_release(proxy, nvqs); + } +- ++config_error: ++ kvm_virtio_pci_vector_config_release(proxy); ++config_assign_error: ++ virtio_pci_set_guest_notifier(d, VIRTIO_CONFIG_IRQ_IDX, !assign, ++ with_irqfd); + assign_error: + /* We get here on assignment failure. Recover by undoing for VQs 0 .. n. */ + assert(assign); +diff --git a/hw/virtio/virtio-pci.h b/hw/virtio/virtio-pci.h +index d95b1a13a5..6d8e071d8d 100644 +--- a/hw/virtio/virtio-pci.h ++++ b/hw/virtio/virtio-pci.h +@@ -256,5 +256,7 @@ void virtio_pci_types_register(const VirtioPCIDeviceTypeInfo *t); + * @fixed_queues. + */ + unsigned virtio_pci_optimal_num_queues(unsigned fixed_queues); +- ++void virtio_pci_set_guest_notifier_fd_handler(VirtIODevice *vdev, VirtQueue *vq, ++ int n, bool assign, ++ bool with_irqfd); + #endif +-- +2.27.0 + diff --git a/virtio-pci-decouple-notifier-from-interrupt-process-new.patch b/virtio-pci-decouple-notifier-from-interrupt-process-new.patch new file mode 100644 index 00000000..89380b31 --- /dev/null +++ b/virtio-pci-decouple-notifier-from-interrupt-process-new.patch @@ -0,0 +1,259 @@ +From e7e028565dd2620b86e884f953761b96a1ecdfdc Mon Sep 17 00:00:00 2001 +From: Cindy Lu +Date: Thu, 22 Dec 2022 15:04:43 +0800 +Subject: [PATCH] virtio-pci: decouple notifier from interrupt process + +To reuse the notifier process. We add the virtio_pci_get_notifier +to get the notifier and vector. The INPUT for this function is IDX, +The OUTPUT is the notifier and the vector + +Signed-off-by: Cindy Lu +Message-Id: <20221222070451.936503-3-lulu@redhat.com> +Acked-by: Jason Wang +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Signed-off-by: fangyi +--- + hw/virtio/virtio-pci.c | 88 +++++++++++++++++++++++++++--------------- + 1 file changed, 57 insertions(+), 31 deletions(-) + +diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c +index 21c0ec3b1b..85d7357f66 100644 +--- a/hw/virtio/virtio-pci.c ++++ b/hw/virtio/virtio-pci.c +@@ -789,29 +789,41 @@ static void kvm_virtio_pci_vq_vector_release(VirtIOPCIProxy *proxy, + } + + static int kvm_virtio_pci_irqfd_use(VirtIOPCIProxy *proxy, +- unsigned int queue_no, ++ EventNotifier *n, + unsigned int vector) + { + VirtIOIRQFD *irqfd = &proxy->vector_irqfd[vector]; +- VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); +- VirtQueue *vq = virtio_get_queue(vdev, queue_no); +- EventNotifier *n = virtio_queue_get_guest_notifier(vq); + return kvm_irqchip_add_irqfd_notifier_gsi(kvm_state, n, NULL, irqfd->virq); + } + + static void kvm_virtio_pci_irqfd_release(VirtIOPCIProxy *proxy, +- unsigned int queue_no, ++ EventNotifier *n , + unsigned int vector) + { +- VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); +- VirtQueue *vq = virtio_get_queue(vdev, queue_no); +- EventNotifier *n = virtio_queue_get_guest_notifier(vq); + VirtIOIRQFD *irqfd = &proxy->vector_irqfd[vector]; + int ret; + + ret = kvm_irqchip_remove_irqfd_notifier_gsi(kvm_state, n, irqfd->virq); + assert(ret == 0); + } ++static int virtio_pci_get_notifier(VirtIOPCIProxy *proxy, int queue_no, ++ EventNotifier **n, unsigned int *vector) ++{ ++ VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); ++ VirtQueue *vq; ++ ++ if (queue_no == VIRTIO_CONFIG_IRQ_IDX) { ++ return -1; ++ } else { ++ if (!virtio_queue_get_num(vdev, queue_no)) { ++ return -1; ++ } ++ *vector = virtio_queue_vector(vdev, queue_no); ++ vq = virtio_get_queue(vdev, queue_no); ++ *n = virtio_queue_get_guest_notifier(vq); ++ } ++ return 0; ++} + + static int kvm_virtio_pci_vector_use(VirtIOPCIProxy *proxy, int nvqs) + { +@@ -820,12 +832,15 @@ static int kvm_virtio_pci_vector_use(VirtIOPCIProxy *proxy, int nvqs) + VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev); + unsigned int vector; + int ret, queue_no; +- ++ EventNotifier *n; + for (queue_no = 0; queue_no < nvqs; queue_no++) { + if (!virtio_queue_get_num(vdev, queue_no)) { + break; + } +- vector = virtio_queue_vector(vdev, queue_no); ++ ret = virtio_pci_get_notifier(proxy, queue_no, &n, &vector); ++ if (ret < 0) { ++ break; ++ } + if (vector >= msix_nr_vectors_allocated(dev)) { + continue; + } +@@ -837,7 +852,7 @@ static int kvm_virtio_pci_vector_use(VirtIOPCIProxy *proxy, int nvqs) + * Otherwise, delay until unmasked in the frontend. + */ + if (vdev->use_guest_notifier_mask && k->guest_notifier_mask) { +- ret = kvm_virtio_pci_irqfd_use(proxy, queue_no, vector); ++ ret = kvm_virtio_pci_irqfd_use(proxy, n, vector); + if (ret < 0) { + kvm_virtio_pci_vq_vector_release(proxy, vector); + goto undo; +@@ -853,7 +868,11 @@ undo: + continue; + } + if (vdev->use_guest_notifier_mask && k->guest_notifier_mask) { +- kvm_virtio_pci_irqfd_release(proxy, queue_no, vector); ++ ret = virtio_pci_get_notifier(proxy, queue_no, &n, &vector); ++ if (ret < 0) { ++ break; ++ } ++ kvm_virtio_pci_irqfd_release(proxy, n, vector); + } + kvm_virtio_pci_vq_vector_release(proxy, vector); + } +@@ -867,12 +886,16 @@ static void kvm_virtio_pci_vector_release(VirtIOPCIProxy *proxy, int nvqs) + unsigned int vector; + int queue_no; + VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev); +- ++ EventNotifier *n; ++ int ret ; + for (queue_no = 0; queue_no < nvqs; queue_no++) { + if (!virtio_queue_get_num(vdev, queue_no)) { + break; + } +- vector = virtio_queue_vector(vdev, queue_no); ++ ret = virtio_pci_get_notifier(proxy, queue_no, &n, &vector); ++ if (ret < 0) { ++ break; ++ } + if (vector >= msix_nr_vectors_allocated(dev)) { + continue; + } +@@ -880,21 +903,20 @@ static void kvm_virtio_pci_vector_release(VirtIOPCIProxy *proxy, int nvqs) + * Otherwise, it was cleaned when masked in the frontend. + */ + if (vdev->use_guest_notifier_mask && k->guest_notifier_mask) { +- kvm_virtio_pci_irqfd_release(proxy, queue_no, vector); ++ kvm_virtio_pci_irqfd_release(proxy, n, vector); + } + kvm_virtio_pci_vq_vector_release(proxy, vector); + } + } + +-static int virtio_pci_vq_vector_unmask(VirtIOPCIProxy *proxy, ++static int virtio_pci_one_vector_unmask(VirtIOPCIProxy *proxy, + unsigned int queue_no, + unsigned int vector, +- MSIMessage msg) ++ MSIMessage msg, ++ EventNotifier *n) + { + VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); + VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev); +- VirtQueue *vq = virtio_get_queue(vdev, queue_no); +- EventNotifier *n = virtio_queue_get_guest_notifier(vq); + VirtIOIRQFD *irqfd; + int ret = 0; + +@@ -921,14 +943,15 @@ static int virtio_pci_vq_vector_unmask(VirtIOPCIProxy *proxy, + event_notifier_set(n); + } + } else { +- ret = kvm_virtio_pci_irqfd_use(proxy, queue_no, vector); ++ ret = kvm_virtio_pci_irqfd_use(proxy, n, vector); + } + return ret; + } + +-static void virtio_pci_vq_vector_mask(VirtIOPCIProxy *proxy, ++static void virtio_pci_one_vector_mask(VirtIOPCIProxy *proxy, + unsigned int queue_no, +- unsigned int vector) ++ unsigned int vector, ++ EventNotifier *n) + { + VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); + VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev); +@@ -939,7 +962,7 @@ static void virtio_pci_vq_vector_mask(VirtIOPCIProxy *proxy, + if (vdev->use_guest_notifier_mask && k->guest_notifier_mask) { + k->guest_notifier_mask(vdev, queue_no, true); + } else { +- kvm_virtio_pci_irqfd_release(proxy, queue_no, vector); ++ kvm_virtio_pci_irqfd_release(proxy, n, vector); + } + } + +@@ -949,6 +972,7 @@ static int virtio_pci_vector_unmask(PCIDevice *dev, unsigned vector, + VirtIOPCIProxy *proxy = container_of(dev, VirtIOPCIProxy, pci_dev); + VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); + VirtQueue *vq = virtio_vector_first_queue(vdev, vector); ++ EventNotifier *n; + int ret, index, unmasked = 0; + + while (vq) { +@@ -957,7 +981,8 @@ static int virtio_pci_vector_unmask(PCIDevice *dev, unsigned vector, + break; + } + if (index < proxy->nvqs_with_notifiers) { +- ret = virtio_pci_vq_vector_unmask(proxy, index, vector, msg); ++ n = virtio_queue_get_guest_notifier(vq); ++ ret = virtio_pci_one_vector_unmask(proxy, index, vector, msg, n); + if (ret < 0) { + goto undo; + } +@@ -973,7 +998,8 @@ undo: + while (vq && unmasked >= 0) { + index = virtio_get_queue_index(vq); + if (index < proxy->nvqs_with_notifiers) { +- virtio_pci_vq_vector_mask(proxy, index, vector); ++ n = virtio_queue_get_guest_notifier(vq); ++ virtio_pci_one_vector_mask(proxy, index, vector, n); + --unmasked; + } + vq = virtio_vector_next_queue(vq); +@@ -986,15 +1012,17 @@ static void virtio_pci_vector_mask(PCIDevice *dev, unsigned vector) + VirtIOPCIProxy *proxy = container_of(dev, VirtIOPCIProxy, pci_dev); + VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); + VirtQueue *vq = virtio_vector_first_queue(vdev, vector); ++ EventNotifier *n; + int index; + + while (vq) { + index = virtio_get_queue_index(vq); ++ n = virtio_queue_get_guest_notifier(vq); + if (!virtio_queue_get_num(vdev, index)) { + break; + } + if (index < proxy->nvqs_with_notifiers) { +- virtio_pci_vq_vector_mask(proxy, index, vector); ++ virtio_pci_one_vector_mask(proxy, index, vector, n); + } + vq = virtio_vector_next_queue(vq); + } +@@ -1010,19 +1038,17 @@ static void virtio_pci_vector_poll(PCIDevice *dev, + int queue_no; + unsigned int vector; + EventNotifier *notifier; +- VirtQueue *vq; ++ int ret; + + for (queue_no = 0; queue_no < proxy->nvqs_with_notifiers; queue_no++) { +- if (!virtio_queue_get_num(vdev, queue_no)) { ++ ret = virtio_pci_get_notifier(proxy, queue_no, ¬ifier, &vector); ++ if (ret < 0) { + break; + } +- vector = virtio_queue_vector(vdev, queue_no); + if (vector < vector_start || vector >= vector_end || + !msix_is_masked(dev, vector)) { + continue; + } +- vq = virtio_get_queue(vdev, queue_no); +- notifier = virtio_queue_get_guest_notifier(vq); + if (k->guest_notifier_pending) { + if (k->guest_notifier_pending(vdev, queue_no)) { + msix_set_pending(dev, vector); +-- +2.27.0 + diff --git a/virtio-pci-decouple-notifier-from-interrupt-process.patch b/virtio-pci-decouple-notifier-from-interrupt-process.patch new file mode 100644 index 00000000..0c3d6208 --- /dev/null +++ b/virtio-pci-decouple-notifier-from-interrupt-process.patch @@ -0,0 +1,259 @@ +From 22998eab50bc17b9af19e377df04d1583a7ddbda Mon Sep 17 00:00:00 2001 +From: fangyi +Date: Thu, 16 Nov 2023 09:54:50 +0800 +Subject: [PATCH] virtio-pci: decouple notifier from interrupt process + +To reuse the notifier process in configure interrupt. +Use the virtio_pci_get_notifier function to get the notifier. +the INPUT of this function is the IDX, the OUTPUT is notifier and +the vector + +Signed-off-by: Cindy Lu +Message-Id: <20211104164827.21911-3-lulu@redhat.com> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Signed-off-by: fangyi +--- + hw/virtio/virtio-pci.c | 88 +++++++++++++++++++++++++++--------------- + 1 file changed, 57 insertions(+), 31 deletions(-) + +diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c +index 21c0ec3b1b..85d7357f66 100644 +--- a/hw/virtio/virtio-pci.c ++++ b/hw/virtio/virtio-pci.c +@@ -789,29 +789,41 @@ static void kvm_virtio_pci_vq_vector_release(VirtIOPCIProxy *proxy, + } + + static int kvm_virtio_pci_irqfd_use(VirtIOPCIProxy *proxy, +- unsigned int queue_no, ++ EventNotifier *n, + unsigned int vector) + { + VirtIOIRQFD *irqfd = &proxy->vector_irqfd[vector]; +- VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); +- VirtQueue *vq = virtio_get_queue(vdev, queue_no); +- EventNotifier *n = virtio_queue_get_guest_notifier(vq); + return kvm_irqchip_add_irqfd_notifier_gsi(kvm_state, n, NULL, irqfd->virq); + } + + static void kvm_virtio_pci_irqfd_release(VirtIOPCIProxy *proxy, +- unsigned int queue_no, ++ EventNotifier *n , + unsigned int vector) + { +- VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); +- VirtQueue *vq = virtio_get_queue(vdev, queue_no); +- EventNotifier *n = virtio_queue_get_guest_notifier(vq); + VirtIOIRQFD *irqfd = &proxy->vector_irqfd[vector]; + int ret; + + ret = kvm_irqchip_remove_irqfd_notifier_gsi(kvm_state, n, irqfd->virq); + assert(ret == 0); + } ++static int virtio_pci_get_notifier(VirtIOPCIProxy *proxy, int queue_no, ++ EventNotifier **n, unsigned int *vector) ++{ ++ VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); ++ VirtQueue *vq; ++ ++ if (queue_no == VIRTIO_CONFIG_IRQ_IDX) { ++ return -1; ++ } else { ++ if (!virtio_queue_get_num(vdev, queue_no)) { ++ return -1; ++ } ++ *vector = virtio_queue_vector(vdev, queue_no); ++ vq = virtio_get_queue(vdev, queue_no); ++ *n = virtio_queue_get_guest_notifier(vq); ++ } ++ return 0; ++} + + static int kvm_virtio_pci_vector_use(VirtIOPCIProxy *proxy, int nvqs) + { +@@ -820,12 +832,15 @@ static int kvm_virtio_pci_vector_use(VirtIOPCIProxy *proxy, int nvqs) + VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev); + unsigned int vector; + int ret, queue_no; +- ++ EventNotifier *n; + for (queue_no = 0; queue_no < nvqs; queue_no++) { + if (!virtio_queue_get_num(vdev, queue_no)) { + break; + } +- vector = virtio_queue_vector(vdev, queue_no); ++ ret = virtio_pci_get_notifier(proxy, queue_no, &n, &vector); ++ if (ret < 0) { ++ break; ++ } + if (vector >= msix_nr_vectors_allocated(dev)) { + continue; + } +@@ -837,7 +852,7 @@ static int kvm_virtio_pci_vector_use(VirtIOPCIProxy *proxy, int nvqs) + * Otherwise, delay until unmasked in the frontend. + */ + if (vdev->use_guest_notifier_mask && k->guest_notifier_mask) { +- ret = kvm_virtio_pci_irqfd_use(proxy, queue_no, vector); ++ ret = kvm_virtio_pci_irqfd_use(proxy, n, vector); + if (ret < 0) { + kvm_virtio_pci_vq_vector_release(proxy, vector); + goto undo; +@@ -853,7 +868,11 @@ undo: + continue; + } + if (vdev->use_guest_notifier_mask && k->guest_notifier_mask) { +- kvm_virtio_pci_irqfd_release(proxy, queue_no, vector); ++ ret = virtio_pci_get_notifier(proxy, queue_no, &n, &vector); ++ if (ret < 0) { ++ break; ++ } ++ kvm_virtio_pci_irqfd_release(proxy, n, vector); + } + kvm_virtio_pci_vq_vector_release(proxy, vector); + } +@@ -867,12 +886,16 @@ static void kvm_virtio_pci_vector_release(VirtIOPCIProxy *proxy, int nvqs) + unsigned int vector; + int queue_no; + VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev); +- ++ EventNotifier *n; ++ int ret ; + for (queue_no = 0; queue_no < nvqs; queue_no++) { + if (!virtio_queue_get_num(vdev, queue_no)) { + break; + } +- vector = virtio_queue_vector(vdev, queue_no); ++ ret = virtio_pci_get_notifier(proxy, queue_no, &n, &vector); ++ if (ret < 0) { ++ break; ++ } + if (vector >= msix_nr_vectors_allocated(dev)) { + continue; + } +@@ -880,21 +903,20 @@ static void kvm_virtio_pci_vector_release(VirtIOPCIProxy *proxy, int nvqs) + * Otherwise, it was cleaned when masked in the frontend. + */ + if (vdev->use_guest_notifier_mask && k->guest_notifier_mask) { +- kvm_virtio_pci_irqfd_release(proxy, queue_no, vector); ++ kvm_virtio_pci_irqfd_release(proxy, n, vector); + } + kvm_virtio_pci_vq_vector_release(proxy, vector); + } + } + +-static int virtio_pci_vq_vector_unmask(VirtIOPCIProxy *proxy, ++static int virtio_pci_one_vector_unmask(VirtIOPCIProxy *proxy, + unsigned int queue_no, + unsigned int vector, +- MSIMessage msg) ++ MSIMessage msg, ++ EventNotifier *n) + { + VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); + VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev); +- VirtQueue *vq = virtio_get_queue(vdev, queue_no); +- EventNotifier *n = virtio_queue_get_guest_notifier(vq); + VirtIOIRQFD *irqfd; + int ret = 0; + +@@ -921,14 +943,15 @@ static int virtio_pci_vq_vector_unmask(VirtIOPCIProxy *proxy, + event_notifier_set(n); + } + } else { +- ret = kvm_virtio_pci_irqfd_use(proxy, queue_no, vector); ++ ret = kvm_virtio_pci_irqfd_use(proxy, n, vector); + } + return ret; + } + +-static void virtio_pci_vq_vector_mask(VirtIOPCIProxy *proxy, ++static void virtio_pci_one_vector_mask(VirtIOPCIProxy *proxy, + unsigned int queue_no, +- unsigned int vector) ++ unsigned int vector, ++ EventNotifier *n) + { + VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); + VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev); +@@ -939,7 +962,7 @@ static void virtio_pci_vq_vector_mask(VirtIOPCIProxy *proxy, + if (vdev->use_guest_notifier_mask && k->guest_notifier_mask) { + k->guest_notifier_mask(vdev, queue_no, true); + } else { +- kvm_virtio_pci_irqfd_release(proxy, queue_no, vector); ++ kvm_virtio_pci_irqfd_release(proxy, n, vector); + } + } + +@@ -949,6 +972,7 @@ static int virtio_pci_vector_unmask(PCIDevice *dev, unsigned vector, + VirtIOPCIProxy *proxy = container_of(dev, VirtIOPCIProxy, pci_dev); + VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); + VirtQueue *vq = virtio_vector_first_queue(vdev, vector); ++ EventNotifier *n; + int ret, index, unmasked = 0; + + while (vq) { +@@ -957,7 +981,8 @@ static int virtio_pci_vector_unmask(PCIDevice *dev, unsigned vector, + break; + } + if (index < proxy->nvqs_with_notifiers) { +- ret = virtio_pci_vq_vector_unmask(proxy, index, vector, msg); ++ n = virtio_queue_get_guest_notifier(vq); ++ ret = virtio_pci_one_vector_unmask(proxy, index, vector, msg, n); + if (ret < 0) { + goto undo; + } +@@ -973,7 +998,8 @@ undo: + while (vq && unmasked >= 0) { + index = virtio_get_queue_index(vq); + if (index < proxy->nvqs_with_notifiers) { +- virtio_pci_vq_vector_mask(proxy, index, vector); ++ n = virtio_queue_get_guest_notifier(vq); ++ virtio_pci_one_vector_mask(proxy, index, vector, n); + --unmasked; + } + vq = virtio_vector_next_queue(vq); +@@ -986,15 +1012,17 @@ static void virtio_pci_vector_mask(PCIDevice *dev, unsigned vector) + VirtIOPCIProxy *proxy = container_of(dev, VirtIOPCIProxy, pci_dev); + VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); + VirtQueue *vq = virtio_vector_first_queue(vdev, vector); ++ EventNotifier *n; + int index; + + while (vq) { + index = virtio_get_queue_index(vq); ++ n = virtio_queue_get_guest_notifier(vq); + if (!virtio_queue_get_num(vdev, index)) { + break; + } + if (index < proxy->nvqs_with_notifiers) { +- virtio_pci_vq_vector_mask(proxy, index, vector); ++ virtio_pci_one_vector_mask(proxy, index, vector, n); + } + vq = virtio_vector_next_queue(vq); + } +@@ -1010,19 +1038,17 @@ static void virtio_pci_vector_poll(PCIDevice *dev, + int queue_no; + unsigned int vector; + EventNotifier *notifier; +- VirtQueue *vq; ++ int ret; + + for (queue_no = 0; queue_no < proxy->nvqs_with_notifiers; queue_no++) { +- if (!virtio_queue_get_num(vdev, queue_no)) { ++ ret = virtio_pci_get_notifier(proxy, queue_no, ¬ifier, &vector); ++ if (ret < 0) { + break; + } +- vector = virtio_queue_vector(vdev, queue_no); + if (vector < vector_start || vector >= vector_end || + !msix_is_masked(dev, vector)) { + continue; + } +- vq = virtio_get_queue(vdev, queue_no); +- notifier = virtio_queue_get_guest_notifier(vq); + if (k->guest_notifier_pending) { + if (k->guest_notifier_pending(vdev, queue_no)) { + msix_set_pending(dev, vector); +-- +2.27.0 + diff --git a/virtio-pci-decouple-the-single-vector-from-the-inter-new.patch b/virtio-pci-decouple-the-single-vector-from-the-inter-new.patch new file mode 100644 index 00000000..1bff2796 --- /dev/null +++ b/virtio-pci-decouple-the-single-vector-from-the-inter-new.patch @@ -0,0 +1,198 @@ +From 99e35c22ecd4847c652f136334c5949651e8419d Mon Sep 17 00:00:00 2001 +From: Cindy Lu +Date: Thu, 22 Dec 2022 15:04:44 +0800 +Subject: [PATCH] virtio-pci: decouple the single vector from the interrupt + process + +To reuse the interrupt process in configure interrupt +Need to decouple the single vector from the interrupt process. +We add new function kvm_virtio_pci_vector_use_one and _release_one. +These functions are used for the single vector, the whole process will +finish in the loop with vq number. + +Signed-off-by: Cindy Lu +Message-Id: <20221222070451.936503-4-lulu@redhat.com> +Acked-by: Jason Wang +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Signed-off-by: fangyi +--- + hw/virtio/virtio-pci.c | 131 +++++++++++++++++++++++------------------ + 1 file changed, 73 insertions(+), 58 deletions(-) + +diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c +index 85d7357f66..75be770971 100644 +--- a/hw/virtio/virtio-pci.c ++++ b/hw/virtio/virtio-pci.c +@@ -762,7 +762,6 @@ static uint32_t virtio_read_config(PCIDevice *pci_dev, + } + + static int kvm_virtio_pci_vq_vector_use(VirtIOPCIProxy *proxy, +- unsigned int queue_no, + unsigned int vector) + { + VirtIOIRQFD *irqfd = &proxy->vector_irqfd[vector]; +@@ -825,87 +824,103 @@ static int virtio_pci_get_notifier(VirtIOPCIProxy *proxy, int queue_no, + return 0; + } + +-static int kvm_virtio_pci_vector_use(VirtIOPCIProxy *proxy, int nvqs) ++static int kvm_virtio_pci_vector_use_one(VirtIOPCIProxy *proxy, int queue_no) + { ++ unsigned int vector; ++ int ret; ++ EventNotifier *n; + PCIDevice *dev = &proxy->pci_dev; + VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); + VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev); +- unsigned int vector; +- int ret, queue_no; +- EventNotifier *n; +- for (queue_no = 0; queue_no < nvqs; queue_no++) { +- if (!virtio_queue_get_num(vdev, queue_no)) { +- break; +- } +- ret = virtio_pci_get_notifier(proxy, queue_no, &n, &vector); +- if (ret < 0) { +- break; +- } +- if (vector >= msix_nr_vectors_allocated(dev)) { +- continue; +- } +- ret = kvm_virtio_pci_vq_vector_use(proxy, queue_no, vector); ++ ++ ret = virtio_pci_get_notifier(proxy, queue_no, &n, &vector); ++ if (ret < 0) { ++ return ret; ++ } ++ if (vector >= msix_nr_vectors_allocated(dev)) { ++ return 0; ++ } ++ ret = kvm_virtio_pci_vq_vector_use(proxy, vector); ++ if (ret < 0) { ++ goto undo; ++ } ++ /* ++ * If guest supports masking, set up irqfd now. ++ * Otherwise, delay until unmasked in the frontend. ++ */ ++ if (vdev->use_guest_notifier_mask && k->guest_notifier_mask) { ++ ret = kvm_virtio_pci_irqfd_use(proxy, n, vector); + if (ret < 0) { ++ kvm_virtio_pci_vq_vector_release(proxy, vector); + goto undo; + } +- /* If guest supports masking, set up irqfd now. +- * Otherwise, delay until unmasked in the frontend. +- */ +- if (vdev->use_guest_notifier_mask && k->guest_notifier_mask) { +- ret = kvm_virtio_pci_irqfd_use(proxy, n, vector); +- if (ret < 0) { +- kvm_virtio_pci_vq_vector_release(proxy, vector); +- goto undo; +- } +- } + } +- return 0; + ++ return 0; + undo: +- while (--queue_no >= 0) { +- vector = virtio_queue_vector(vdev, queue_no); +- if (vector >= msix_nr_vectors_allocated(dev)) { +- continue; ++ ++ vector = virtio_queue_vector(vdev, queue_no); ++ if (vector >= msix_nr_vectors_allocated(dev)) { ++ return ret; ++ } ++ if (vdev->use_guest_notifier_mask && k->guest_notifier_mask) { ++ ret = virtio_pci_get_notifier(proxy, queue_no, &n, &vector); ++ if (ret < 0) { ++ return ret; + } +- if (vdev->use_guest_notifier_mask && k->guest_notifier_mask) { +- ret = virtio_pci_get_notifier(proxy, queue_no, &n, &vector); +- if (ret < 0) { +- break; +- } +- kvm_virtio_pci_irqfd_release(proxy, n, vector); ++ kvm_virtio_pci_irqfd_release(proxy, n, vector); ++ } ++ return ret; ++} ++static int kvm_virtio_pci_vector_use(VirtIOPCIProxy *proxy, int nvqs) ++{ ++ int queue_no; ++ int ret = 0; ++ VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); ++ ++ for (queue_no = 0; queue_no < nvqs; queue_no++) { ++ if (!virtio_queue_get_num(vdev, queue_no)) { ++ return -1; + } +- kvm_virtio_pci_vq_vector_release(proxy, vector); ++ ret = kvm_virtio_pci_vector_use_one(proxy, queue_no); + } + return ret; + } + +-static void kvm_virtio_pci_vector_release(VirtIOPCIProxy *proxy, int nvqs) ++ ++static void kvm_virtio_pci_vector_release_one(VirtIOPCIProxy *proxy, ++ int queue_no) + { +- PCIDevice *dev = &proxy->pci_dev; + VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); + unsigned int vector; +- int queue_no; +- VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev); + EventNotifier *n; +- int ret ; ++ int ret; ++ VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev); ++ PCIDevice *dev = &proxy->pci_dev; ++ ++ ret = virtio_pci_get_notifier(proxy, queue_no, &n, &vector); ++ if (ret < 0) { ++ return; ++ } ++ if (vector >= msix_nr_vectors_allocated(dev)) { ++ return; ++ } ++ if (vdev->use_guest_notifier_mask && k->guest_notifier_mask) { ++ kvm_virtio_pci_irqfd_release(proxy, n, vector); ++ } ++ kvm_virtio_pci_vq_vector_release(proxy, vector); ++} ++ ++static void kvm_virtio_pci_vector_release(VirtIOPCIProxy *proxy, int nvqs) ++{ ++ int queue_no; ++ VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); ++ + for (queue_no = 0; queue_no < nvqs; queue_no++) { + if (!virtio_queue_get_num(vdev, queue_no)) { + break; + } +- ret = virtio_pci_get_notifier(proxy, queue_no, &n, &vector); +- if (ret < 0) { +- break; +- } +- if (vector >= msix_nr_vectors_allocated(dev)) { +- continue; +- } +- /* If guest supports masking, clean up irqfd now. +- * Otherwise, it was cleaned when masked in the frontend. +- */ +- if (vdev->use_guest_notifier_mask && k->guest_notifier_mask) { +- kvm_virtio_pci_irqfd_release(proxy, n, vector); +- } +- kvm_virtio_pci_vq_vector_release(proxy, vector); ++ kvm_virtio_pci_vector_release_one(proxy, queue_no); + } + } + +-- +2.27.0 + diff --git a/virtio-pci-decouple-the-single-vector-from-the-inter.patch b/virtio-pci-decouple-the-single-vector-from-the-inter.patch new file mode 100644 index 00000000..a6989f9b --- /dev/null +++ b/virtio-pci-decouple-the-single-vector-from-the-inter.patch @@ -0,0 +1,196 @@ +From b3223ddde84840ccc6bb2282dfc146616b85a362 Mon Sep 17 00:00:00 2001 +From: fangyi +Date: Thu, 16 Nov 2023 09:54:51 +0800 +Subject: [PATCH] virtio-pci: decouple the single vector from the interrupt + process + +To reuse the interrupt process in configure interrupt +Need to decouple the single vector from the interrupt process. Add new function +kvm_virtio_pci_vector_use_one and _release_one. These functions are use +for the single vector, the whole process will finish in a loop for the vq number. + +Signed-off-by: Cindy Lu +Message-Id: <20211104164827.21911-4-lulu@redhat.com> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Signed-off-by: fangyi +--- + hw/virtio/virtio-pci.c | 131 +++++++++++++++++++++++------------------ + 1 file changed, 73 insertions(+), 58 deletions(-) + +diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c +index 85d7357f66..75be770971 100644 +--- a/hw/virtio/virtio-pci.c ++++ b/hw/virtio/virtio-pci.c +@@ -762,7 +762,6 @@ static uint32_t virtio_read_config(PCIDevice *pci_dev, + } + + static int kvm_virtio_pci_vq_vector_use(VirtIOPCIProxy *proxy, +- unsigned int queue_no, + unsigned int vector) + { + VirtIOIRQFD *irqfd = &proxy->vector_irqfd[vector]; +@@ -825,87 +824,103 @@ static int virtio_pci_get_notifier(VirtIOPCIProxy *proxy, int queue_no, + return 0; + } + +-static int kvm_virtio_pci_vector_use(VirtIOPCIProxy *proxy, int nvqs) ++static int kvm_virtio_pci_vector_use_one(VirtIOPCIProxy *proxy, int queue_no) + { ++ unsigned int vector; ++ int ret; ++ EventNotifier *n; + PCIDevice *dev = &proxy->pci_dev; + VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); + VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev); +- unsigned int vector; +- int ret, queue_no; +- EventNotifier *n; +- for (queue_no = 0; queue_no < nvqs; queue_no++) { +- if (!virtio_queue_get_num(vdev, queue_no)) { +- break; +- } +- ret = virtio_pci_get_notifier(proxy, queue_no, &n, &vector); +- if (ret < 0) { +- break; +- } +- if (vector >= msix_nr_vectors_allocated(dev)) { +- continue; +- } +- ret = kvm_virtio_pci_vq_vector_use(proxy, queue_no, vector); ++ ++ ret = virtio_pci_get_notifier(proxy, queue_no, &n, &vector); ++ if (ret < 0) { ++ return ret; ++ } ++ if (vector >= msix_nr_vectors_allocated(dev)) { ++ return 0; ++ } ++ ret = kvm_virtio_pci_vq_vector_use(proxy, vector); ++ if (ret < 0) { ++ goto undo; ++ } ++ /* ++ * If guest supports masking, set up irqfd now. ++ * Otherwise, delay until unmasked in the frontend. ++ */ ++ if (vdev->use_guest_notifier_mask && k->guest_notifier_mask) { ++ ret = kvm_virtio_pci_irqfd_use(proxy, n, vector); + if (ret < 0) { ++ kvm_virtio_pci_vq_vector_release(proxy, vector); + goto undo; + } +- /* If guest supports masking, set up irqfd now. +- * Otherwise, delay until unmasked in the frontend. +- */ +- if (vdev->use_guest_notifier_mask && k->guest_notifier_mask) { +- ret = kvm_virtio_pci_irqfd_use(proxy, n, vector); +- if (ret < 0) { +- kvm_virtio_pci_vq_vector_release(proxy, vector); +- goto undo; +- } +- } + } +- return 0; + ++ return 0; + undo: +- while (--queue_no >= 0) { +- vector = virtio_queue_vector(vdev, queue_no); +- if (vector >= msix_nr_vectors_allocated(dev)) { +- continue; ++ ++ vector = virtio_queue_vector(vdev, queue_no); ++ if (vector >= msix_nr_vectors_allocated(dev)) { ++ return ret; ++ } ++ if (vdev->use_guest_notifier_mask && k->guest_notifier_mask) { ++ ret = virtio_pci_get_notifier(proxy, queue_no, &n, &vector); ++ if (ret < 0) { ++ return ret; + } +- if (vdev->use_guest_notifier_mask && k->guest_notifier_mask) { +- ret = virtio_pci_get_notifier(proxy, queue_no, &n, &vector); +- if (ret < 0) { +- break; +- } +- kvm_virtio_pci_irqfd_release(proxy, n, vector); ++ kvm_virtio_pci_irqfd_release(proxy, n, vector); ++ } ++ return ret; ++} ++static int kvm_virtio_pci_vector_use(VirtIOPCIProxy *proxy, int nvqs) ++{ ++ int queue_no; ++ int ret = 0; ++ VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); ++ ++ for (queue_no = 0; queue_no < nvqs; queue_no++) { ++ if (!virtio_queue_get_num(vdev, queue_no)) { ++ return -1; + } +- kvm_virtio_pci_vq_vector_release(proxy, vector); ++ ret = kvm_virtio_pci_vector_use_one(proxy, queue_no); + } + return ret; + } + +-static void kvm_virtio_pci_vector_release(VirtIOPCIProxy *proxy, int nvqs) ++ ++static void kvm_virtio_pci_vector_release_one(VirtIOPCIProxy *proxy, ++ int queue_no) + { +- PCIDevice *dev = &proxy->pci_dev; + VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); + unsigned int vector; +- int queue_no; +- VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev); + EventNotifier *n; +- int ret ; ++ int ret; ++ VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev); ++ PCIDevice *dev = &proxy->pci_dev; ++ ++ ret = virtio_pci_get_notifier(proxy, queue_no, &n, &vector); ++ if (ret < 0) { ++ return; ++ } ++ if (vector >= msix_nr_vectors_allocated(dev)) { ++ return; ++ } ++ if (vdev->use_guest_notifier_mask && k->guest_notifier_mask) { ++ kvm_virtio_pci_irqfd_release(proxy, n, vector); ++ } ++ kvm_virtio_pci_vq_vector_release(proxy, vector); ++} ++ ++static void kvm_virtio_pci_vector_release(VirtIOPCIProxy *proxy, int nvqs) ++{ ++ int queue_no; ++ VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); ++ + for (queue_no = 0; queue_no < nvqs; queue_no++) { + if (!virtio_queue_get_num(vdev, queue_no)) { + break; + } +- ret = virtio_pci_get_notifier(proxy, queue_no, &n, &vector); +- if (ret < 0) { +- break; +- } +- if (vector >= msix_nr_vectors_allocated(dev)) { +- continue; +- } +- /* If guest supports masking, clean up irqfd now. +- * Otherwise, it was cleaned when masked in the frontend. +- */ +- if (vdev->use_guest_notifier_mask && k->guest_notifier_mask) { +- kvm_virtio_pci_irqfd_release(proxy, n, vector); +- } +- kvm_virtio_pci_vq_vector_release(proxy, vector); ++ kvm_virtio_pci_vector_release_one(proxy, queue_no); + } + } + +-- +2.27.0 + diff --git a/virtio-signal-after-wrapping-packed-used_idx.patch b/virtio-signal-after-wrapping-packed-used_idx.patch new file mode 100644 index 00000000..3fa3b633 --- /dev/null +++ b/virtio-signal-after-wrapping-packed-used_idx.patch @@ -0,0 +1,51 @@ +From 671f0830d70c1e35deb63cc66db7ce8b713e8967 Mon Sep 17 00:00:00 2001 +From: Stefan Hajnoczi +Date: Tue, 30 Nov 2021 13:45:10 +0000 +Subject: [PATCH] virtio: signal after wrapping packed used_idx + +Packed Virtqueues wrap used_idx instead of letting it run freely like +Split Virtqueues do. If the used ring wraps more than once there is no +way to compare vq->signalled_used and vq->used_idx in +virtio_packed_should_notify() since they are modulo vq->vring.num. + +This causes the device to stop sending used buffer notifications when +when virtio_packed_should_notify() is called less than once each time +around the used ring. + +It is possible to trigger this with virtio-blk's dataplane +notify_guest_bh() irq coalescing optimization. The call to +virtio_notify_irqfd() (and virtio_packed_should_notify()) is deferred to +a BH. If the guest driver is polling it can complete and submit more +requests before the BH executes, causing the used ring to wrap more than +once. The result is that the virtio-blk device ceases to raise +interrupts and I/O hangs. + +Cc: Tiwei Bie +Cc: Jason Wang +Cc: Michael S. Tsirkin +Signed-off-by: Stefan Hajnoczi +Message-Id: <20211130134510.267382-1-stefanha@redhat.com> +Fixes: 86044b24e865fb9596ed77a4d0f3af8b90a088a1 ("virtio: basic packed virtqueue support") +Acked-by: Jason Wang +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Signed-off-by: fangyi +--- + hw/virtio/virtio.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c +index d90cabe868..05409b84d1 100644 +--- a/hw/virtio/virtio.c ++++ b/hw/virtio/virtio.c +@@ -885,6 +885,7 @@ static void virtqueue_packed_flush(VirtQueue *vq, unsigned int count) + if (vq->used_idx >= vq->vring.num) { + vq->used_idx -= vq->vring.num; + vq->used_wrap_counter ^= 1; ++ vq->signalled_used_valid = false; + } + } + +-- +2.27.0 + -- Gitee From 5cea6d28e9a0bf8cf5a5b98f6b3614cb75597873 Mon Sep 17 00:00:00 2001 From: JianChunfu Date: Tue, 28 Nov 2023 09:54:55 +0800 Subject: [PATCH 02/19] spec: Add support for the ppc64le platform Add support for the powerpc platform of ppc64le. Signed-off-by: JianChunfu (cherry picked from commit 95d9ef98ff9bb6f92511eab25e0bcd62af87af3f) --- qemu.spec | 34 +++++++++++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/qemu.spec b/qemu.spec index be323000..56bec06b 100644 --- a/qemu.spec +++ b/qemu.spec @@ -3,7 +3,7 @@ Name: qemu Version: 6.2.0 -Release: 84 +Release: 85 Epoch: 10 Summary: QEMU is a generic and open source machine emulator and virtualizer License: GPLv2 and BSD and MIT and CC-BY-SA-4.0 @@ -947,6 +947,12 @@ Requires: qemu %description system-x86_64 This package provides the QEMU system emulator for x86_64. +%package system-ppc64 +Summary: Qemu-system-ppc64 +Requires: qemu +%description system-ppc64 +This package provides the QEMU system emulator for ppc64le. + %package system-riscv Summary: Qemu-system-riscv32, Qemu-system-riscv64 Requires: qemu @@ -973,6 +979,11 @@ buildarch="aarch64-softmmu" targetarch="x86_64-softmmu arm-softmmu riscv32-softmmu riscv64-softmmu" %endif +%ifarch ppc64le +buildarch="ppc64-softmmu" +targetarch="x86_64-softmmu aarch64-softmmu arm-softmmu riscv32-softmmu riscv64-softmmu" +%endif + %ifarch loongarch64 buildarch="loongarch64-softmmu" targetarch="x86_64-softmmu aarch64-softmmu arm-softmmu riscv32-softmmu riscv64-softmmu" @@ -1093,18 +1104,20 @@ chmod -x %{buildroot}%{_mandir}/man1/* rm -rf %{buildroot}%{_datadir}/%{name}/vgabios-ati.bin rm -rf %{buildroot}%{_datadir}/%{name}/bios-microvm.bin rm -rf %{buildroot}%{_datadir}/%{name}/openbios-* -rm -rf %{buildroot}%{_datadir}/%{name}/slof.bin rm -rf %{buildroot}%{_datadir}/%{name}/QEMU,*.bin rm -rf %{buildroot}%{_datadir}/%{name}/bamboo.dtb rm -rf %{buildroot}%{_datadir}/%{name}/canyonlands.dtb rm -rf %{buildroot}%{_datadir}/%{name}/hppa-firmware.img rm -rf %{buildroot}%{_datadir}/%{name}/palcode-clipper rm -rf %{buildroot}%{_datadir}/%{name}/petalogix-* -rm -rf %{buildroot}%{_datadir}/%{name}/ppc_* rm -rf %{buildroot}%{_datadir}/%{name}/qemu_vga.ndrv rm -rf %{buildroot}%{_datadir}/%{name}/s390-* +%ifnarch ppc64le +rm -rf %{buildroot}%{_datadir}/%{name}/slof.bin rm -rf %{buildroot}%{_datadir}/%{name}/skiboot.lid rm -rf %{buildroot}%{_datadir}/%{name}/spapr-* +rm -rf %{buildroot}%{_datadir}/%{name}/ppc_* +%endif rm -rf %{buildroot}%{_datadir}/%{name}/u-boot* rm -rf %{buildroot}%{_datadir}/%{name}/core3-hmcode rm -rf %{buildroot}%{_datadir}/%{name}/core3-reset @@ -1134,6 +1147,9 @@ rm -rf %{buildroot}%{_libdir}/%{name}/ui-spice-core.so rm -rf %{buildroot}%{_libexecdir}/vhost-user-gpu rm -rf %{buildroot}%{_datadir}/%{name}/vhost-user/50-qemu-gpu.json rm -rf %{buildroot}%{_datadir}/%{name}/vhost-user/50-qemu-virtiofsd.json +%ifarch ppc64le +rm -rf %{buildroot}%{_datadir}/%{name}/opensbi-riscv*.elf +%endif %if %{with rbd} strip %{buildroot}%{_libdir}/%{name}/block-rbd.so @@ -1268,11 +1284,20 @@ getent passwd qemu >/dev/null || \ %{_datadir}/%{name}/sgabios.bin %endif +%ifarch ppc64le +%files system-ppc64 +%{_bindir}/qemu-system-ppc64 +%{_datadir}/%{name}/slof.bin +%{_datadir}/%{name}/skiboot.lid +%endif + %files system-riscv %{_bindir}/qemu-system-riscv32 %{_bindir}/qemu-system-riscv64 %{_datadir}/%{name}/opensbi-riscv*.bin +%ifnarch ppc64le %{_datadir}/%{name}/opensbi-riscv*.elf +%endif %ifarch loongarch64 %files system-loongarch64 @@ -1358,6 +1383,9 @@ getent passwd qemu >/dev/null || \ %endif %changelog +* Fri Dec 1 2023 - 10:6.2.0-85 +- spec: Add support for the ppc64le platform + * Tue Nov 28 2023 - 10:6.2.0-84 - hw/arm/fsl-imx: Do not ignore Error argument - hw/net/cadence_gem.c: spelling fixes: Octects -- Gitee From fdab267ba9e95ffbf467d254736989b7889ccbce Mon Sep 17 00:00:00 2001 From: Jiabo Feng Date: Tue, 5 Dec 2023 18:00:19 +0800 Subject: [PATCH 03/19] QEMU update to version 6.2.0-86(master) - vdpa: move memory listener to the realize stage - vdpa: implement vdpa device migration - vhost: implement post resume bh - vhost: implement migration state notifier for vdpa device - vhost: implement savevm_hanlder for vdpa device - vhost: implement vhost_vdpa_device_suspend/resume - vhost: implement vhost-vdpa suspend/resume - vhost: add vhost_dev_suspend/resume_op - vhost: introduce bytemap for vhost backend logging - vhost-vdpa: add migration log ops for VhostOps - vhost-vdpa: add VHOST_BACKEND_F_BYTEMAPLOG - vhost: fix null pointer access - ui/gtk: prevent ui lock up when dpy_gl_update called again before current draw event occurs - hw/usb: dev-mtp: Use g_mkdir() - target/ppc/cpu-models: Remove the "default" CPU alias - hw/intc/arm_gicv3: ICC_PMR_EL1 high bits should be RAZ - Fixed a QEMU hang when guest poweroff in COLO mode - migration/colo: More accurate update checkpoint time - scripts/entitlement.sh: Use backward-compatible cp flags - block/nvme: fix infinite loop in nvme_free_req_queue_cb() - hw/net: npcm7xx_emc fix missing queue_flush - Add dummy Aspeed AST2600 Display Port MCU (DPMCU) - hw/arm: ast2600: Fix address mapping of second SPI controller - vhost-user-blk: reconnect on any error during realize - vhost-user-blk: propagate error return from generic vhost - hw/riscv: boot: Reduce FDT address alignment constraints - Revert "hw/virtio/virtio-iommu-pci: Enforce the device is plugged on the root bus" - Fix STM32F2XX USART data register readout - block: use 'unsigned' for in_flight field on driver state - sphinx: change default language to 'en' - tests/qtest: Fix two format strings - trivial typos: namesapce - hw/ide/atapi.c: Correct typos (CD-CDROM -> CD-ROM) - hw/virtio/virtio-iommu-pci: Enforce the device is plugged on the root bus - hw/display/next-fb: Fix comment typo - xen/pass-through: merge emulated bits correctly mainline inclusion commit be9c61da9fc57eb7d293f380d0805ca6f46c2657 category: bugfix - tests/qtest/migration-test.c: spelling fix: bandwith - target/i386/cpu: Improve error message for property "vendor" - balloon: Fix a misleading error message - target/arm: Don't set syndrome ISS for loads and stores with writeback mainline inclusion commit 53ae2fdef1f5661cbaa2ea571c517f98e6041cb8 category: bugfix - disas/hppa: Show hexcode of instruction along with disassembly - tcg/loongarch64: Fix tcg_out_mov() Aborted - ui/qmp-cmds: Improve two error messages - qga: Improve guest-exec-status error message - hmp: Improve sync-profile error message - spapr/pci: Correct "does not support hotplugging error messages - xen/pass-through: don't create needless register group mainline inclusion commit c0e86b7624cb9d6db03e0d48cf82659e5b89a6a6 category: bugfix Signed-off-by: Jiabo Feng (cherry picked from commit 39a0a891d853faf21cb5709a3a05b45031a6a4ee) --- ...speed-AST2600-Display-Port-MCU-DPMCU.patch | 84 ++++ ...TM32F2XX-USART-data-register-readout.patch | 43 ++ ...ang-when-guest-poweroff-in-COLO-mode.patch | 83 ++++ ...-virtio-iommu-pci-Enforce-the-device.patch | 49 ++ balloon-Fix-a-misleading-error-message.patch | 60 +++ ...nfinite-loop-in-nvme_free_req_queue_.patch | 64 +++ ...ed-for-in_flight-field-on-driver-sta.patch | 54 +++ ...hexcode-of-instruction-along-with-di.patch | 48 ++ hmp-Improve-sync-profile-error-message.patch | 52 ++ ...ix-address-mapping-of-second-SPI-con.patch | 40 ++ hw-display-next-fb-Fix-comment-typo.patch | 36 ++ ...tapi.c-Correct-typos-CD-CDROM-CD-ROM.patch | 41 ++ ...3-ICC_PMR_EL1-high-bits-should-be-RA.patch | 54 +++ ...-npcm7xx_emc-fix-missing-queue_flush.patch | 75 +++ ...duce-FDT-address-alignment-constrain.patch | 46 ++ hw-usb-dev-mtp-Use-g_mkdir.patch | 48 ++ ...-iommu-pci-Enforce-the-device-is-plu.patch | 69 +++ ...More-accurate-update-checkpoint-time.patch | 44 ++ qemu.spec | 99 +++- ...rove-guest-exec-status-error-message.patch | 42 ++ ...ent.sh-Use-backward-compatible-cp-fl.patch | 35 ++ ...t-does-not-support-hotplugging-error.patch | 45 ++ sphinx-change-default-language-to-en.patch | 38 ++ ...-set-syndrome-ISS-for-loads-and-stor.patch | 51 ++ ...Improve-error-message-for-property-v.patch | 45 ++ ...-models-Remove-the-default-CPU-alias.patch | 40 ++ tcg-loongarch64-Fix-tcg_out_mov-Aborted.patch | 64 +++ tests-qtest-Fix-two-format-strings.patch | 44 ++ ...gration-test.c-spelling-fix-bandwith.patch | 26 + trivial-typos-namesapce.patch | 89 ++++ ...i-lock-up-when-dpy_gl_update-called-.patch | 71 +++ ui-qmp-cmds-Improve-two-error-messages.patch | 68 +++ vdpa-implement-vdpa-device-migration.patch | 77 +++ ...memory-listener-to-the-realize-stage.patch | 112 +++++ vhost-add-vhost_dev_suspend-resume_op.patch | 64 +++ vhost-fix-null-pointer-access.patch | 74 +++ ...migration-state-notifier-for-vdpa-de.patch | 78 +++ vhost-implement-post-resume-bh.patch | 56 +++ ...ement-savevm_hanlder-for-vdpa-device.patch | 265 ++++++++++ ...-implement-vhost-vdpa-suspend-resume.patch | 85 ++++ ...ent-vhost_vdpa_device_suspend-resume.patch | 453 ++++++++++++++++++ ...ce-bytemap-for-vhost-backend-logging.patch | 271 +++++++++++ ...ropagate-error-return-from-generic-v.patch | 36 ++ ...econnect-on-any-error-during-realize.patch | 51 ++ ...-vdpa-add-VHOST_BACKEND_F_BYTEMAPLOG.patch | 49 ++ ...a-add-migration-log-ops-for-VhostOps.patch | 129 +++++ ...-don-t-create-needless-register-grou.patch | 63 +++ ...hrough-merge-emulated-bits-correctly.patch | 67 +++ 48 files changed, 3676 insertions(+), 1 deletion(-) create mode 100644 Add-dummy-Aspeed-AST2600-Display-Port-MCU-DPMCU.patch create mode 100644 Fix-STM32F2XX-USART-data-register-readout.patch create mode 100644 Fixed-a-QEMU-hang-when-guest-poweroff-in-COLO-mode.patch create mode 100644 Revert-hw-virtio-virtio-iommu-pci-Enforce-the-device.patch create mode 100644 balloon-Fix-a-misleading-error-message.patch create mode 100644 block-nvme-fix-infinite-loop-in-nvme_free_req_queue_.patch create mode 100644 block-use-unsigned-for-in_flight-field-on-driver-sta.patch create mode 100644 disas-hppa-Show-hexcode-of-instruction-along-with-di.patch create mode 100644 hmp-Improve-sync-profile-error-message.patch create mode 100644 hw-arm-ast2600-Fix-address-mapping-of-second-SPI-con.patch create mode 100644 hw-display-next-fb-Fix-comment-typo.patch create mode 100644 hw-ide-atapi.c-Correct-typos-CD-CDROM-CD-ROM.patch create mode 100644 hw-intc-arm_gicv3-ICC_PMR_EL1-high-bits-should-be-RA.patch create mode 100644 hw-net-npcm7xx_emc-fix-missing-queue_flush.patch create mode 100644 hw-riscv-boot-Reduce-FDT-address-alignment-constrain.patch create mode 100644 hw-usb-dev-mtp-Use-g_mkdir.patch create mode 100644 hw-virtio-virtio-iommu-pci-Enforce-the-device-is-plu.patch create mode 100644 migration-colo-More-accurate-update-checkpoint-time.patch create mode 100644 qga-Improve-guest-exec-status-error-message.patch create mode 100644 scripts-entitlement.sh-Use-backward-compatible-cp-fl.patch create mode 100644 spapr-pci-Correct-does-not-support-hotplugging-error.patch create mode 100644 sphinx-change-default-language-to-en.patch create mode 100644 target-arm-Don-t-set-syndrome-ISS-for-loads-and-stor.patch create mode 100644 target-i386-cpu-Improve-error-message-for-property-v.patch create mode 100644 target-ppc-cpu-models-Remove-the-default-CPU-alias.patch create mode 100644 tcg-loongarch64-Fix-tcg_out_mov-Aborted.patch create mode 100644 tests-qtest-Fix-two-format-strings.patch create mode 100644 tests-qtest-migration-test.c-spelling-fix-bandwith.patch create mode 100644 trivial-typos-namesapce.patch create mode 100644 ui-gtk-prevent-ui-lock-up-when-dpy_gl_update-called-.patch create mode 100644 ui-qmp-cmds-Improve-two-error-messages.patch create mode 100644 vdpa-implement-vdpa-device-migration.patch create mode 100644 vdpa-move-memory-listener-to-the-realize-stage.patch create mode 100644 vhost-add-vhost_dev_suspend-resume_op.patch create mode 100644 vhost-fix-null-pointer-access.patch create mode 100644 vhost-implement-migration-state-notifier-for-vdpa-de.patch create mode 100644 vhost-implement-post-resume-bh.patch create mode 100644 vhost-implement-savevm_hanlder-for-vdpa-device.patch create mode 100644 vhost-implement-vhost-vdpa-suspend-resume.patch create mode 100644 vhost-implement-vhost_vdpa_device_suspend-resume.patch create mode 100644 vhost-introduce-bytemap-for-vhost-backend-logging.patch create mode 100644 vhost-user-blk-propagate-error-return-from-generic-v.patch create mode 100644 vhost-user-blk-reconnect-on-any-error-during-realize.patch create mode 100644 vhost-vdpa-add-VHOST_BACKEND_F_BYTEMAPLOG.patch create mode 100644 vhost-vdpa-add-migration-log-ops-for-VhostOps.patch create mode 100644 xen-pass-through-don-t-create-needless-register-grou.patch create mode 100644 xen-pass-through-merge-emulated-bits-correctly.patch diff --git a/Add-dummy-Aspeed-AST2600-Display-Port-MCU-DPMCU.patch b/Add-dummy-Aspeed-AST2600-Display-Port-MCU-DPMCU.patch new file mode 100644 index 00000000..2887ce74 --- /dev/null +++ b/Add-dummy-Aspeed-AST2600-Display-Port-MCU-DPMCU.patch @@ -0,0 +1,84 @@ +From 48f112e0b8e65fccc3bf66510fafb6e9a8d58e90 Mon Sep 17 00:00:00 2001 +From: Luo Yifan +Date: Mon, 4 Dec 2023 10:50:04 +0800 +Subject: [PATCH] Add dummy Aspeed AST2600 Display Port MCU (DPMCU) +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +cherry picked from commit d9e9cd59df4bc92e4cf7ad1bfa6e2a8429ff31b4 + +AST2600 Display Port MCU introduces 0x18000000~0x1803FFFF as it's memory +and io address. If guest machine try to access DPMCU memory, it will +cause a fatal error. + +Signed-off-by: Troy Lee +Reviewed-by: Philippe Mathieu-Daudé +Reviewed-by: Cédric Le Goater +Message-id: 20211210083034.726610-1-troy_lee@aspeedtech.com +Signed-off-by: Peter Maydell +Signed-off-by: Luo Yifan +--- + hw/arm/aspeed_ast2600.c | 8 ++++++++ + include/hw/arm/aspeed_soc.h | 2 ++ + 2 files changed, 10 insertions(+) + +diff --git a/hw/arm/aspeed_ast2600.c b/hw/arm/aspeed_ast2600.c +index 0384357a95..e33483fb5d 100644 +--- a/hw/arm/aspeed_ast2600.c ++++ b/hw/arm/aspeed_ast2600.c +@@ -19,9 +19,11 @@ + #include "sysemu/sysemu.h" + + #define ASPEED_SOC_IOMEM_SIZE 0x00200000 ++#define ASPEED_SOC_DPMCU_SIZE 0x00040000 + + static const hwaddr aspeed_soc_ast2600_memmap[] = { + [ASPEED_DEV_SRAM] = 0x10000000, ++ [ASPEED_DEV_DPMCU] = 0x18000000, + /* 0x16000000 0x17FFFFFF : AHB BUS do LPC Bus bridge */ + [ASPEED_DEV_IOMEM] = 0x1E600000, + [ASPEED_DEV_PWM] = 0x1E610000, +@@ -44,6 +46,7 @@ static const hwaddr aspeed_soc_ast2600_memmap[] = { + [ASPEED_DEV_SCU] = 0x1E6E2000, + [ASPEED_DEV_XDMA] = 0x1E6E7000, + [ASPEED_DEV_ADC] = 0x1E6E9000, ++ [ASPEED_DEV_DP] = 0x1E6EB000, + [ASPEED_DEV_VIDEO] = 0x1E700000, + [ASPEED_DEV_SDHCI] = 0x1E740000, + [ASPEED_DEV_EMMC] = 0x1E750000, +@@ -104,6 +107,7 @@ static const int aspeed_soc_ast2600_irqmap[] = { + [ASPEED_DEV_ETH3] = 32, + [ASPEED_DEV_ETH4] = 33, + [ASPEED_DEV_KCS] = 138, /* 138 -> 142 */ ++ [ASPEED_DEV_DP] = 62, + }; + + static qemu_irq aspeed_soc_get_irq(AspeedSoCState *s, int ctrl) +@@ -298,6 +302,10 @@ static void aspeed_soc_ast2600_realize(DeviceState *dev, Error **errp) + memory_region_add_subregion(get_system_memory(), + sc->memmap[ASPEED_DEV_SRAM], &s->sram); + ++ /* DPMCU */ ++ create_unimplemented_device("aspeed.dpmcu", sc->memmap[ASPEED_DEV_DPMCU], ++ ASPEED_SOC_DPMCU_SIZE); ++ + /* SCU */ + if (!sysbus_realize(SYS_BUS_DEVICE(&s->scu), errp)) { + return; +diff --git a/include/hw/arm/aspeed_soc.h b/include/hw/arm/aspeed_soc.h +index 8139358549..18fb7eed46 100644 +--- a/include/hw/arm/aspeed_soc.h ++++ b/include/hw/arm/aspeed_soc.h +@@ -139,6 +139,8 @@ enum { + ASPEED_DEV_EMMC, + ASPEED_DEV_KCS, + ASPEED_DEV_HACE, ++ ASPEED_DEV_DPMCU, ++ ASPEED_DEV_DP, + }; + + #endif /* ASPEED_SOC_H */ +-- +2.27.0 + diff --git a/Fix-STM32F2XX-USART-data-register-readout.patch b/Fix-STM32F2XX-USART-data-register-readout.patch new file mode 100644 index 00000000..3244c318 --- /dev/null +++ b/Fix-STM32F2XX-USART-data-register-readout.patch @@ -0,0 +1,43 @@ +From 8733b8a26407177b867d3293283c257efeb784a0 Mon Sep 17 00:00:00 2001 +From: Luo Yifan +Date: Fri, 1 Dec 2023 12:51:56 +0800 +Subject: [PATCH] Fix STM32F2XX USART data register readout +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +cherry picked from commit ab08c3467605365b44fab1b66bb6254db86814f6 + +Fix issue where the data register may be overwritten by next character +reception before being read and returned. + +Signed-off-by: Olivier Hériveaux +Reviewed-by: Peter Maydell +Reviewed-by: Alistair Francis +Message-id: 20211128120723.4053-1-olivier.heriveaux@ledger.fr +Signed-off-by: Peter Maydell +Signed-off-by: Luo Yifan +--- + hw/char/stm32f2xx_usart.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/hw/char/stm32f2xx_usart.c b/hw/char/stm32f2xx_usart.c +index 8df0832424..fde67f4f03 100644 +--- a/hw/char/stm32f2xx_usart.c ++++ b/hw/char/stm32f2xx_usart.c +@@ -103,10 +103,11 @@ static uint64_t stm32f2xx_usart_read(void *opaque, hwaddr addr, + return retvalue; + case USART_DR: + DB_PRINT("Value: 0x%" PRIx32 ", %c\n", s->usart_dr, (char) s->usart_dr); ++ retvalue = s->usart_dr & 0x3FF; + s->usart_sr &= ~USART_SR_RXNE; + qemu_chr_fe_accept_input(&s->chr); + qemu_set_irq(s->irq, 0); +- return s->usart_dr & 0x3FF; ++ return retvalue; + case USART_BRR: + return s->usart_brr; + case USART_CR1: +-- +2.27.0 + diff --git a/Fixed-a-QEMU-hang-when-guest-poweroff-in-COLO-mode.patch b/Fixed-a-QEMU-hang-when-guest-poweroff-in-COLO-mode.patch new file mode 100644 index 00000000..10e21c23 --- /dev/null +++ b/Fixed-a-QEMU-hang-when-guest-poweroff-in-COLO-mode.patch @@ -0,0 +1,83 @@ +From 6de250962994520ba8daca709cd4b3b54d5e3afb Mon Sep 17 00:00:00 2001 +From: Luo Yifan +Date: Fri, 1 Dec 2023 10:47:48 +0800 +Subject: [PATCH] Fixed a QEMU hang when guest poweroff in COLO mode + +cherry picked from commit 795969ab1fe6d5a0f524be92e2e1ecd13f1873eb + +When the PVM guest poweroff, the COLO thread may wait a semaphore +in colo_process_checkpoint().So, we should wake up the COLO thread +before migration shutdown. + +Signed-off-by: Lei Rao +Reviewed-by: Zhang Chen +Reviewed-by: Juan Quintela +Signed-off-by: Juan Quintela +Signed-off-by: Luo Yifan +--- + include/migration/colo.h | 1 + + migration/colo.c | 20 ++++++++++++++++++++ + migration/migration.c | 6 ++++++ + 3 files changed, 27 insertions(+) + +diff --git a/include/migration/colo.h b/include/migration/colo.h +index 768e1f04c3..5fbe1a6d5d 100644 +--- a/include/migration/colo.h ++++ b/include/migration/colo.h +@@ -37,4 +37,5 @@ COLOMode get_colo_mode(void); + void colo_do_failover(void); + + void colo_checkpoint_notify(void *opaque); ++void colo_shutdown(void); + #endif +diff --git a/migration/colo.c b/migration/colo.c +index 2415325262..0d3d98f707 100644 +--- a/migration/colo.c ++++ b/migration/colo.c +@@ -820,6 +820,26 @@ static void colo_wait_handle_message(MigrationIncomingState *mis, + } + } + ++void colo_shutdown(void) ++{ ++ MigrationIncomingState *mis = NULL; ++ MigrationState *s = NULL; ++ ++ switch (get_colo_mode()) { ++ case COLO_MODE_PRIMARY: ++ s = migrate_get_current(); ++ qemu_event_set(&s->colo_checkpoint_event); ++ qemu_sem_post(&s->colo_exit_sem); ++ break; ++ case COLO_MODE_SECONDARY: ++ mis = migration_incoming_get_current(); ++ qemu_sem_post(&mis->colo_incoming_sem); ++ break; ++ default: ++ break; ++ } ++} ++ + void *colo_process_incoming_thread(void *opaque) + { + MigrationIncomingState *mis = opaque; +diff --git a/migration/migration.c b/migration/migration.c +index 2ec116f901..cceaacc7f7 100644 +--- a/migration/migration.c ++++ b/migration/migration.c +@@ -226,6 +226,12 @@ void migration_cancel(const Error *error) + + void migration_shutdown(void) + { ++ /* ++ * When the QEMU main thread exit, the COLO thread ++ * may wait a semaphore. So, we should wakeup the ++ * COLO thread before migration shutdown. ++ */ ++ colo_shutdown(); + /* + * Cancel the current migration - that will (eventually) + * stop the migration using this structure +-- +2.27.0 + diff --git a/Revert-hw-virtio-virtio-iommu-pci-Enforce-the-device.patch b/Revert-hw-virtio-virtio-iommu-pci-Enforce-the-device.patch new file mode 100644 index 00000000..b3017089 --- /dev/null +++ b/Revert-hw-virtio-virtio-iommu-pci-Enforce-the-device.patch @@ -0,0 +1,49 @@ +From f66f64cf3ca968db2ca7f45bfd125ec7d85624e5 Mon Sep 17 00:00:00 2001 +From: jiangdongxu +Date: Mon, 4 Dec 2023 17:30:02 +0800 +Subject: [PATCH] Revert "hw/virtio/virtio-iommu-pci: Enforce the device is + plugged on the root bus" + +This reverts commit a2323aa79da71c92e818306f1e18184619309a35. + +Signed-off-by: jiangdongxu +--- + hw/virtio/virtio-iommu-pci.c | 13 +++---------- + 1 file changed, 3 insertions(+), 10 deletions(-) + +diff --git a/hw/virtio/virtio-iommu-pci.c b/hw/virtio/virtio-iommu-pci.c +index 37eb2fb979..a160ae6b41 100644 +--- a/hw/virtio/virtio-iommu-pci.c ++++ b/hw/virtio/virtio-iommu-pci.c +@@ -44,7 +44,6 @@ static Property virtio_iommu_pci_properties[] = { + static void virtio_iommu_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp) + { + VirtIOIOMMUPCI *dev = VIRTIO_IOMMU_PCI(vpci_dev); +- PCIBus *pbus = pci_get_bus(&vpci_dev->pci_dev); + DeviceState *vdev = DEVICE(&dev->vdev); + VirtIOIOMMU *s = VIRTIO_IOMMU(vdev); + +@@ -66,17 +65,11 @@ static void virtio_iommu_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp) + s->reserved_regions[i].type != VIRTIO_IOMMU_RESV_MEM_T_MSI) { + error_setg(errp, "reserved region %d has an invalid type", i); + error_append_hint(errp, "Valid values are 0 and 1\n"); +- return; +- } ++ } + } +- if (!pci_bus_is_root(pbus)) { +- error_setg(errp, "virtio-iommu-pci must be plugged on the root bus"); +- return; +- } +- + object_property_set_link(OBJECT(dev), "primary-bus", +- OBJECT(pbus), &error_abort); +- ++ OBJECT(pci_get_bus(&vpci_dev->pci_dev)), ++ &error_abort); + virtio_pci_force_virtio_1(vpci_dev); + qdev_realize(vdev, BUS(&vpci_dev->bus), errp); + } +-- +2.27.0 + diff --git a/balloon-Fix-a-misleading-error-message.patch b/balloon-Fix-a-misleading-error-message.patch new file mode 100644 index 00000000..e0f7cdc8 --- /dev/null +++ b/balloon-Fix-a-misleading-error-message.patch @@ -0,0 +1,60 @@ +From 0c24a55d582e8219b64f2090cbdd21027d496bb1 Mon Sep 17 00:00:00 2001 +From: boringandboring +Date: Mon, 27 Nov 2023 10:44:31 +0800 +Subject: [PATCH] balloon: Fix a misleading error message + +cherry picked from eeef44b3a583637265f602882a0d058a52e3a33b + +The error message + + {"execute": "balloon", "arguments":{"value": -1}} + {"error": {"class": "GenericError", "desc": "Parameter 'target' expects a size"}} + +points to 'target' instead of 'value'. Fix: + + {"error": {"class": "GenericError", "desc": "Parameter 'value' expects a size"}} + +Root cause: qmp_balloon()'s parameter is named @target. Rename it to +@value to match the QAPI schema. + +Signed-off-by: Markus Armbruster +Message-ID: <20231031111059.3407803-7-armbru@redhat.com> +Reviewed-by: David Hildenbrand +Reviewed-by: Michael S. Tsirkin +Tested-by: Mario Casquero + +Signed-off-by: boringandboring +--- + softmmu/balloon.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/softmmu/balloon.c b/softmmu/balloon.c +index e0e8969a4b..fda7af832e 100644 +--- a/softmmu/balloon.c ++++ b/softmmu/balloon.c +@@ -90,17 +90,17 @@ BalloonInfo *qmp_query_balloon(Error **errp) + return info; + } + +-void qmp_balloon(int64_t target, Error **errp) ++void qmp_balloon(int64_t value, Error **errp) + { + if (!have_balloon(errp)) { + return; + } + +- if (target <= 0) { +- error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "target", "a size"); ++ if (value <= 0) { ++ error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "value", "a size"); + return; + } + +- trace_balloon_event(balloon_opaque, target); +- balloon_event_fn(balloon_opaque, target); ++ trace_balloon_event(balloon_opaque, value); ++ balloon_event_fn(balloon_opaque, value); + } +-- +2.27.0 + diff --git a/block-nvme-fix-infinite-loop-in-nvme_free_req_queue_.patch b/block-nvme-fix-infinite-loop-in-nvme_free_req_queue_.patch new file mode 100644 index 00000000..eb0595fa --- /dev/null +++ b/block-nvme-fix-infinite-loop-in-nvme_free_req_queue_.patch @@ -0,0 +1,64 @@ +From ba31baabf9ad582c8a256a58123c036b6a70ba15 Mon Sep 17 00:00:00 2001 +From: Luo Yifan +Date: Fri, 1 Dec 2023 10:00:41 +0800 +Subject: [PATCH] block/nvme: fix infinite loop in nvme_free_req_queue_cb() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +cherry picked from commit cf4fbc3030c974fff726756a7ceef8386cdf500b + +When the request free list is exhausted the coroutine waits on +q->free_req_queue for the next free request. Whenever a request is +completed a BH is scheduled to invoke nvme_free_req_queue_cb() and wake +up waiting coroutines. + +1. nvme_get_free_req() waits for a free request: + + while (q->free_req_head == -1) { + ... + trace_nvme_free_req_queue_wait(q->s, q->index); + qemu_co_queue_wait(&q->free_req_queue, &q->lock); + ... + } + +2. nvme_free_req_queue_cb() wakes up the coroutine: + + while (qemu_co_enter_next(&q->free_req_queue, &q->lock)) { + ^--- infinite loop when free_req_head == -1 + } + +nvme_free_req_queue_cb() and the coroutine form an infinite loop when +q->free_req_head == -1. Fix this by checking q->free_req_head in +nvme_free_req_queue_cb(). If the free request list is exhausted, don't +wake waiting coroutines. Eventually an in-flight request will complete +and the BH will be scheduled again, guaranteeing forward progress. + +Signed-off-by: Stefan Hajnoczi +Reviewed-by: Philippe Mathieu-Daudé +Message-id: 20211208152246.244585-1-stefanha@redhat.com +Signed-off-by: Stefan Hajnoczi +Signed-off-by: Luo Yifan +--- + block/nvme.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/block/nvme.c b/block/nvme.c +index e4f336d79c..fa360b9b3c 100644 +--- a/block/nvme.c ++++ b/block/nvme.c +@@ -206,8 +206,9 @@ static void nvme_free_req_queue_cb(void *opaque) + NVMeQueuePair *q = opaque; + + qemu_mutex_lock(&q->lock); +- while (qemu_co_enter_next(&q->free_req_queue, &q->lock)) { +- /* Retry all pending requests */ ++ while (q->free_req_head != -1 && ++ qemu_co_enter_next(&q->free_req_queue, &q->lock)) { ++ /* Retry waiting requests */ + } + qemu_mutex_unlock(&q->lock); + } +-- +2.27.0 + diff --git a/block-use-unsigned-for-in_flight-field-on-driver-sta.patch b/block-use-unsigned-for-in_flight-field-on-driver-sta.patch new file mode 100644 index 00000000..5ff052c6 --- /dev/null +++ b/block-use-unsigned-for-in_flight-field-on-driver-sta.patch @@ -0,0 +1,54 @@ +From d82b2052d61cd57fb2ebf53f633cb0ff272d16c3 Mon Sep 17 00:00:00 2001 +From: Wanghe Xiao +Date: Sat, 25 Nov 2023 02:53:08 -0800 +Subject: [PATCH] block: use 'unsigned' for in_flight field on driver state + +cherry picked from commit 1b8f777673985af366de099ad4e41d334b36fb12 + +This patch makes in_flight field 'unsigned' for BDRVNBDState and +MirrorBlockJob. This matches the definition of this field on BDS +and is generically correct - we should never get negative value here. + +Signed-off-by: Denis V. Lunev +CC: John Snow +CC: Vladimir Sementsov-Ogievskiy +CC: Kevin Wolf +CC: Hanna Reitz +CC: Eric Blake +Reviewed-by: Vladimir Sementsov-Ogievskiy +Signed-off-by: Vladimir Sementsov-Ogievskiy +Signed-off-by: Wanghe Xiao +--- + block/mirror.c | 2 +- + block/nbd.c | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/block/mirror.c b/block/mirror.c +index b7f0cba9b9..d1863565c4 100644 +--- a/block/mirror.c ++++ b/block/mirror.c +@@ -72,7 +72,7 @@ typedef struct MirrorBlockJob { + + uint64_t last_pause_ns; + unsigned long *in_flight_bitmap; +- int in_flight; ++ unsigned in_flight; + int64_t bytes_in_flight; + QTAILQ_HEAD(, MirrorOp) ops_in_flight; + int ret; +diff --git a/block/nbd.c b/block/nbd.c +index 33adfddc41..a543e68d2f 100644 +--- a/block/nbd.c ++++ b/block/nbd.c +@@ -76,7 +76,7 @@ typedef struct BDRVNBDState { + CoQueue free_sema; + + CoMutex receive_mutex; +- int in_flight; ++ unsigned in_flight; + NBDClientState state; + + QEMUTimer *reconnect_delay_timer; +-- +2.27.0 + diff --git a/disas-hppa-Show-hexcode-of-instruction-along-with-di.patch b/disas-hppa-Show-hexcode-of-instruction-along-with-di.patch new file mode 100644 index 00000000..16cd69a7 --- /dev/null +++ b/disas-hppa-Show-hexcode-of-instruction-along-with-di.patch @@ -0,0 +1,48 @@ +From 7949977cef7b7b4170dad873f9b5788f0c4e40ee Mon Sep 17 00:00:00 2001 +From: boringandboring +Date: Mon, 27 Nov 2023 10:54:54 +0800 +Subject: [PATCH] disas/hppa: Show hexcode of instruction along with + disassembly + +cherry picked from 2f926bfd5b79e6219ae65a1e530b38f37d62b384 + +On hppa many instructions can be expressed by different bytecodes. +To be able to debug qemu translation bugs it's therefore necessary to see the +currently executed byte codes without the need to lookup the sequence without +the full executable. +With this patch the instruction byte code is shown beside the disassembly. + +Signed-off-by: Helge Deller +Reviewed-by: Richard Henderson + +Signed-off-by: boringandboring +--- + disas/hppa.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/disas/hppa.c b/disas/hppa.c +index dcf9a47f34..cce4f4aa37 100644 +--- a/disas/hppa.c ++++ b/disas/hppa.c +@@ -1968,6 +1968,10 @@ print_insn_hppa (bfd_vma memaddr, disassemble_info *info) + + insn = bfd_getb32 (buffer); + ++ info->fprintf_func(info->stream, " %02x %02x %02x %02x ", ++ (insn >> 24) & 0xff, (insn >> 16) & 0xff, ++ (insn >> 8) & 0xff, insn & 0xff); ++ + for (i = 0; i < NUMOPCODES; ++i) + { + const struct pa_opcode *opcode = &pa_opcodes[i]; +@@ -2826,6 +2830,6 @@ print_insn_hppa (bfd_vma memaddr, disassemble_info *info) + return sizeof (insn); + } + } +- (*info->fprintf_func) (info->stream, "#%8x", insn); ++ info->fprintf_func(info->stream, ""); + return sizeof (insn); + } +-- +2.27.0 + diff --git a/hmp-Improve-sync-profile-error-message.patch b/hmp-Improve-sync-profile-error-message.patch new file mode 100644 index 00000000..703bbe85 --- /dev/null +++ b/hmp-Improve-sync-profile-error-message.patch @@ -0,0 +1,52 @@ +From 3860a3a40673bdbcf8f8fde9017e9e1ecbd82b36 Mon Sep 17 00:00:00 2001 +From: boringandboring +Date: Mon, 27 Nov 2023 16:09:24 +0800 +Subject: [PATCH] hmp: Improve sync-profile error message +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +cherry picked from 7200fb211ef306c36d5e9060263b2a4d2f6d4700 + +Improve + + (qemu) sync-profile of + Error: Invalid parameter 'of' + +to + + Error: invalid parameter 'of', expecting 'on', 'off', or 'reset' + +Signed-off-by: Markus Armbruster +Message-ID: <20231031111059.3407803-3-armbru@redhat.com> +Reviewed-by: Philippe Mathieu-Daudé +Reviewed-by: Dr. David Alan Gilbert +--- + monitor/hmp-cmds.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c +index 9570011232..5246c82e14 100644 +--- a/monitor/hmp-cmds.c ++++ b/monitor/hmp-cmds.c +@@ -46,7 +46,6 @@ + #include "qapi/qapi-visit-migration.h" + #include "qapi/qmp/qdict.h" + #include "qapi/qapi-visit-migration.h" +-#include "qapi/qmp/qerror.h" + #include "qapi/string-input-visitor.h" + #include "qapi/string-output-visitor.h" + #include "qom/object_interfaces.h" +@@ -920,7 +919,8 @@ void hmp_sync_profile(Monitor *mon, const QDict *qdict) + } else { + Error *err = NULL; + +- error_setg(&err, QERR_INVALID_PARAMETER, op); ++ error_setg(&err, "invalid parameter '%s'," ++ " expecting 'on', 'off', or 'reset'", op); + hmp_handle_error(mon, err); + } + } +-- +2.27.0 + diff --git a/hw-arm-ast2600-Fix-address-mapping-of-second-SPI-con.patch b/hw-arm-ast2600-Fix-address-mapping-of-second-SPI-con.patch new file mode 100644 index 00000000..9935b5e9 --- /dev/null +++ b/hw-arm-ast2600-Fix-address-mapping-of-second-SPI-con.patch @@ -0,0 +1,40 @@ +From 13a37e4130fbdfcd9a5027b4339eee592ee76889 Mon Sep 17 00:00:00 2001 +From: Luo Yifan +Date: Mon, 4 Dec 2023 11:01:29 +0800 +Subject: [PATCH] hw/arm: ast2600: Fix address mapping of second SPI controller +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +cherry picked from commit 08048cbd5e7dc0a0359ccb8c7968e4d011174801 + +Address should be 0x1E631000 and not 0x1E641000 as initially introduced. + +Resolves: https://gitlab.com/qemu-project/qemu/-/issues/838 +Fixes: f25c0ae1079d ("aspeed/soc: Add AST2600 support") +Suggested-by: Troy Lee +Signed-off-by: Cédric Le Goater +Reviewed-by: Philippe Mathieu-Daudé +Message-id: 20220126083520.4135713-1-clg@kaod.org +Signed-off-by: Peter Maydell +Signed-off-by: Luo Yifan +--- + hw/arm/aspeed_ast2600.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/hw/arm/aspeed_ast2600.c b/hw/arm/aspeed_ast2600.c +index 0384357a95..d83a70300e 100644 +--- a/hw/arm/aspeed_ast2600.c ++++ b/hw/arm/aspeed_ast2600.c +@@ -27,7 +27,7 @@ static const hwaddr aspeed_soc_ast2600_memmap[] = { + [ASPEED_DEV_PWM] = 0x1E610000, + [ASPEED_DEV_FMC] = 0x1E620000, + [ASPEED_DEV_SPI1] = 0x1E630000, +- [ASPEED_DEV_SPI2] = 0x1E641000, ++ [ASPEED_DEV_SPI2] = 0x1E631000, + [ASPEED_DEV_EHCI1] = 0x1E6A1000, + [ASPEED_DEV_EHCI2] = 0x1E6A3000, + [ASPEED_DEV_MII1] = 0x1E650000, +-- +2.27.0 + diff --git a/hw-display-next-fb-Fix-comment-typo.patch b/hw-display-next-fb-Fix-comment-typo.patch new file mode 100644 index 00000000..f23a0732 --- /dev/null +++ b/hw-display-next-fb-Fix-comment-typo.patch @@ -0,0 +1,36 @@ +From 7252e8e0f5a4c43854efa3e31071a678f4e61d37 Mon Sep 17 00:00:00 2001 +From: Wanghe Xiao +Date: Sat, 25 Nov 2023 01:49:31 -0800 +Subject: [PATCH] hw/display/next-fb: Fix comment typo +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +cherry picked from commit c1966f515d9bb6d8ed7076f4bebdc45407700100 + +Signed-off-by: Evgeny Ermakov +Message-Id: <20221125160849.23711-1-evgeny.v.ermakov@gmail.com> +Reviewed-by: Philippe Mathieu-Daudé +Reviewed-by: Peter Maydell +Signed-off-by: Thomas Huth +Signed-off-by: Wanghe Xiao +--- + hw/display/next-fb.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/hw/display/next-fb.c b/hw/display/next-fb.c +index dd6a1aa8ae..8446ff3c00 100644 +--- a/hw/display/next-fb.c ++++ b/hw/display/next-fb.c +@@ -126,7 +126,7 @@ static void nextfb_class_init(ObjectClass *oc, void *data) + set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories); + dc->realize = nextfb_realize; + +- /* Note: This device does not any state that we have to reset or migrate */ ++ /* Note: This device does not have any state that we have to reset or migrate */ + } + + static const TypeInfo nextfb_info = { +-- +2.27.0 + diff --git a/hw-ide-atapi.c-Correct-typos-CD-CDROM-CD-ROM.patch b/hw-ide-atapi.c-Correct-typos-CD-CDROM-CD-ROM.patch new file mode 100644 index 00000000..672ab709 --- /dev/null +++ b/hw-ide-atapi.c-Correct-typos-CD-CDROM-CD-ROM.patch @@ -0,0 +1,41 @@ +From c8c702a9970572800626be337e3b5c8b44e4bcca Mon Sep 17 00:00:00 2001 +From: Wanghe Xiao +Date: Sat, 25 Nov 2023 02:43:50 -0800 +Subject: [PATCH] hw/ide/atapi.c: Correct typos (CD-CDROM -> CD-ROM) + +cherry picked from commit 99337bd1e3a323d07dc29da99cf3f48d3990ad81 + +Signed-off-by: Lev Kujawski +Reviewed-by: Laurent Vivier +Message-Id: <20220528204702.167912-1-lkujaw@member.fsf.org> +Signed-off-by: Laurent Vivier +Signed-off-by: Wanghe Xiao +--- + hw/ide/atapi.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/hw/ide/atapi.c b/hw/ide/atapi.c +index b626199e3d..88b2890faf 100644 +--- a/hw/ide/atapi.c ++++ b/hw/ide/atapi.c +@@ -318,7 +318,7 @@ static void ide_atapi_cmd_reply(IDEState *s, int size, int max_size) + } + } + +-/* start a CD-CDROM read command */ ++/* start a CD-ROM read command */ + static void ide_atapi_cmd_read_pio(IDEState *s, int lba, int nb_sectors, + int sector_size) + { +@@ -417,7 +417,7 @@ eot: + ide_set_inactive(s, false); + } + +-/* start a CD-CDROM read command with DMA */ ++/* start a CD-ROM read command with DMA */ + /* XXX: test if DMA is available */ + static void ide_atapi_cmd_read_dma(IDEState *s, int lba, int nb_sectors, + int sector_size) +-- +2.27.0 + diff --git a/hw-intc-arm_gicv3-ICC_PMR_EL1-high-bits-should-be-RA.patch b/hw-intc-arm_gicv3-ICC_PMR_EL1-high-bits-should-be-RA.patch new file mode 100644 index 00000000..92d2b86e --- /dev/null +++ b/hw-intc-arm_gicv3-ICC_PMR_EL1-high-bits-should-be-RA.patch @@ -0,0 +1,54 @@ +From bd71d640e5d3731a91ccd6cc4ded251d401b4b2d Mon Sep 17 00:00:00 2001 +From: boringandboring +Date: Tue, 28 Nov 2023 09:38:09 +0800 +Subject: [PATCH] hw/intc/arm_gicv3: ICC_PMR_EL1 high bits should be RAZ + +cherry picked from 70726a15bc7e61d16f3efe5bfd9b061ca077f533 + +The ICC_PMR_ELx and ICV_PMR_ELx bit masks returned from +ic{c,v}_fullprio_mask should technically also remove any +bit above 7 as these are marked reserved (read 0) and should +therefore should not be written as anything other than 0. + +This was noted during a run of a proprietary test system and +discused on the mailing list [1] and initially thought not to +be an issue due to RES0 being technically allowed to be +written to and read back as long as the implementation does +not use the RES0 bits. It is very possible that the values +are used in comparison without masking, as pointed out by +Peter in [2], if (cs->hppi.prio >= cs->icc_pmr_el1) may well +do the wrong thing. + +Masking these values in ic{c,v}_fullprio_mask() should fix +this and prevent any future problems with playing with the +values. + +[1]: https://lists.nongnu.org/archive/html/qemu-arm/2023-11/msg00607.html +[2]: https://lists.nongnu.org/archive/html/qemu-arm/2023-11/msg00737.html + +Signed-off-by: Ben Dooks +Message-id: 20231116172818.792364-1-ben.dooks@codethink.co.uk +Suggested-by: Peter Maydell +Reviewed-by: Peter Maydell +Signed-off-by: Peter Maydell +Signed-off-by: boringandboring +--- + hw/intc/arm_gicv3_cpuif.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/hw/intc/arm_gicv3_cpuif.c b/hw/intc/arm_gicv3_cpuif.c +index 274a40a40c..eaa1381b3d 100644 +--- a/hw/intc/arm_gicv3_cpuif.c ++++ b/hw/intc/arm_gicv3_cpuif.c +@@ -137,7 +137,7 @@ static uint32_t icv_fullprio_mask(GICv3CPUState *cs) + * with the group priority, whose mask depends on the value of VBPR + * for the interrupt group.) + */ +- return ~0U << (8 - cs->vpribits); ++ return (~0U << (8 - cs->vpribits)) & 0xff; + } + + static int ich_highest_active_virt_prio(GICv3CPUState *cs) +-- +2.27.0 + diff --git a/hw-net-npcm7xx_emc-fix-missing-queue_flush.patch b/hw-net-npcm7xx_emc-fix-missing-queue_flush.patch new file mode 100644 index 00000000..bce9a4f9 --- /dev/null +++ b/hw-net-npcm7xx_emc-fix-missing-queue_flush.patch @@ -0,0 +1,75 @@ +From cf11e02156e202db1be5e9c85b67d5dfaa56ce48 Mon Sep 17 00:00:00 2001 +From: Luo Yifan +Date: Mon, 4 Dec 2023 10:28:53 +0800 +Subject: [PATCH] hw/net: npcm7xx_emc fix missing queue_flush +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +cherry picked from commit 530cd6c26df47c4f294c6335c9829e6c968fe7a8 + +The rx_active boolean change to true should always trigger a try_read +call that flushes the queue. + +Signed-off-by: Patrick Venture +Reviewed-by: Philippe Mathieu-Daudé +Message-id: 20211203221002.1719306-1-venture@google.com +Signed-off-by: Peter Maydell +Signed-off-by: Luo Yifan +--- + hw/net/npcm7xx_emc.c | 18 ++++++++---------- + 1 file changed, 8 insertions(+), 10 deletions(-) + +diff --git a/hw/net/npcm7xx_emc.c b/hw/net/npcm7xx_emc.c +index df2efe1bf8..9a2328935c 100644 +--- a/hw/net/npcm7xx_emc.c ++++ b/hw/net/npcm7xx_emc.c +@@ -286,6 +286,12 @@ static void emc_halt_rx(NPCM7xxEMCState *emc, uint32_t mista_flag) + emc_set_mista(emc, mista_flag); + } + ++static void emc_enable_rx_and_flush(NPCM7xxEMCState *emc) ++{ ++ emc->rx_active = true; ++ qemu_flush_queued_packets(qemu_get_queue(emc->nic)); ++} ++ + static void emc_set_next_tx_descriptor(NPCM7xxEMCState *emc, + const NPCM7xxEMCTxDesc *tx_desc, + uint32_t desc_addr) +@@ -585,13 +591,6 @@ static ssize_t emc_receive(NetClientState *nc, const uint8_t *buf, size_t len1) + return len; + } + +-static void emc_try_receive_next_packet(NPCM7xxEMCState *emc) +-{ +- if (emc_can_receive(qemu_get_queue(emc->nic))) { +- qemu_flush_queued_packets(qemu_get_queue(emc->nic)); +- } +-} +- + static uint64_t npcm7xx_emc_read(void *opaque, hwaddr offset, unsigned size) + { + NPCM7xxEMCState *emc = opaque; +@@ -707,7 +706,7 @@ static void npcm7xx_emc_write(void *opaque, hwaddr offset, + emc->regs[REG_MGSTA] |= REG_MGSTA_RXHA; + } + if (value & REG_MCMDR_RXON) { +- emc->rx_active = true; ++ emc_enable_rx_and_flush(emc); + } else { + emc_halt_rx(emc, 0); + } +@@ -743,8 +742,7 @@ static void npcm7xx_emc_write(void *opaque, hwaddr offset, + break; + case REG_RSDR: + if (emc->regs[REG_MCMDR] & REG_MCMDR_RXON) { +- emc->rx_active = true; +- emc_try_receive_next_packet(emc); ++ emc_enable_rx_and_flush(emc); + } + break; + case REG_MIIDA: +-- +2.27.0 + diff --git a/hw-riscv-boot-Reduce-FDT-address-alignment-constrain.patch b/hw-riscv-boot-Reduce-FDT-address-alignment-constrain.patch new file mode 100644 index 00000000..ca3125a4 --- /dev/null +++ b/hw-riscv-boot-Reduce-FDT-address-alignment-constrain.patch @@ -0,0 +1,46 @@ +From 919af9a7472996b17c45fcd508ae29ec58117e8c Mon Sep 17 00:00:00 2001 +From: Wanghe Xiao +Date: Sat, 25 Nov 2023 02:39:26 -0800 +Subject: [PATCH] hw/riscv: boot: Reduce FDT address alignment constraints + +cherry picked from commit ec2c62dacc186893a6ce63089f96b1906dd68804 + +We previously stored the device tree at a 16MB alignment from the end of +memory (or 3GB). This means we need at least 16MB of memory to be able +to do this. We don't actually need the FDT to be 16MB aligned, so let's +drop it down to 2MB so that we can support systems with less memory, +while also allowing FDT size expansion. + +Resolves: https://gitlab.com/qemu-project/qemu/-/issues/992 +Signed-off-by: Alistair Francis +Reviewed-by: Atish Patra +Reviewed-by: Bin Meng +Tested-by: Bin Meng +Message-Id: <20220608062015.317894-1-alistair.francis@opensource.wdc.com> +Signed-off-by: Alistair Francis +Signed-off-by: Wanghe Xiao +--- + hw/riscv/boot.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/hw/riscv/boot.c b/hw/riscv/boot.c +index 519fa455a1..c035aa68f5 100644 +--- a/hw/riscv/boot.c ++++ b/hw/riscv/boot.c +@@ -217,11 +217,11 @@ uint32_t riscv_load_fdt(hwaddr dram_base, uint64_t mem_size, void *fdt) + /* + * We should put fdt as far as possible to avoid kernel/initrd overwriting + * its content. But it should be addressable by 32 bit system as well. +- * Thus, put it at an 16MB aligned address that less than fdt size from the ++ * Thus, put it at an 2MB aligned address that less than fdt size from the + * end of dram or 3GB whichever is lesser. + */ + temp = MIN(dram_end, 3072 * MiB); +- fdt_addr = QEMU_ALIGN_DOWN(temp - fdtsize, 16 * MiB); ++ fdt_addr = QEMU_ALIGN_DOWN(temp - fdtsize, 2 * MiB); + + ret = fdt_pack(fdt); + /* Should only fail if we've built a corrupted tree */ +-- +2.27.0 + diff --git a/hw-usb-dev-mtp-Use-g_mkdir.patch b/hw-usb-dev-mtp-Use-g_mkdir.patch new file mode 100644 index 00000000..4e866717 --- /dev/null +++ b/hw-usb-dev-mtp-Use-g_mkdir.patch @@ -0,0 +1,48 @@ +From af6c51e5ef35cdf966888fb6874944d9615384a8 Mon Sep 17 00:00:00 2001 +From: Wanghe Xiao +Date: Sat, 25 Nov 2023 02:20:54 -0800 +Subject: [PATCH] hw/usb: dev-mtp: Use g_mkdir() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +cherry picked from commit 34b55848a15bca120d9b9381881c40b045409ee9 + +Use g_mkdir() to create a directory on all platforms. + +Signed-off-by: Bin Meng +Acked-by: Gerd Hoffmann +Signed-off-by: Alex Bennée +Reviewed-by: Philippe Mathieu-Daudé +Message-Id: <20221006151927.2079583-8-bmeng.cn@gmail.com> +Message-Id: <20221027183637.2772968-15-alex.bennee@linaro.org> +Signed-off-by: Wanghe Xiao +--- + hw/usb/dev-mtp.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/hw/usb/dev-mtp.c b/hw/usb/dev-mtp.c +index c1d1694fd0..882f6bc72f 100644 +--- a/hw/usb/dev-mtp.c ++++ b/hw/usb/dev-mtp.c +@@ -15,7 +15,7 @@ + #include "qemu/error-report.h" + #include + #include +- ++#include + #include + + +@@ -1623,7 +1623,7 @@ static void usb_mtp_write_data(MTPState *s, uint32_t handle) + if (s->dataset.filename) { + path = g_strdup_printf("%s/%s", parent->path, s->dataset.filename); + if (s->dataset.format == FMT_ASSOCIATION) { +- ret = mkdir(path, mask); ++ ret = g_mkdir(path, mask); + if (!ret) { + usb_mtp_queue_result(s, RES_OK, d->trans, 3, + QEMU_STORAGE_ID, +-- +2.27.0 + diff --git a/hw-virtio-virtio-iommu-pci-Enforce-the-device-is-plu.patch b/hw-virtio-virtio-iommu-pci-Enforce-the-device-is-plu.patch new file mode 100644 index 00000000..f442f06b --- /dev/null +++ b/hw-virtio-virtio-iommu-pci-Enforce-the-device-is-plu.patch @@ -0,0 +1,69 @@ +From a2323aa79da71c92e818306f1e18184619309a35 Mon Sep 17 00:00:00 2001 +From: Wanghe Xiao +Date: Sat, 25 Nov 2023 02:03:07 -0800 +Subject: [PATCH] hw/virtio/virtio-iommu-pci: Enforce the device is plugged on + the root bus + +cherry picked from commit e72cfabf4ef2f0031e5d0b8129fb1533d383654d + +In theory the virtio-iommu-pci could be plugged anywhere in the PCIe +topology and as long as the dt/acpi info are properly built this should +work. However at the moment we fail to do that because the +virtio-iommu-pci BDF is not computed at plug time and in that case +vms->virtio_iommu_bdf gets an incorrect value. + +For instance if the virtio-iommu-pci is plugged onto a pcie root port +and the virtio-iommu protects a virtio-block-pci device the guest does +not boot. + +So let's do not pretend we do support this case and fail the initialize() +if we detect the virtio-iommu-pci is plugged anywhere else than on the +root bus. Anyway this ability is not needed. + +Signed-off-by: Eric Auger +Message-Id: <20221012163448.121368-1-eric.auger@redhat.com> +Reviewed-by: Jean-Philippe Brucker +Tested-by: Jean-Philippe Brucker +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Signed-off-by: Wanghe Xiao +--- + hw/virtio/virtio-iommu-pci.c | 13 ++++++++++--- + 1 file changed, 10 insertions(+), 3 deletions(-) + +diff --git a/hw/virtio/virtio-iommu-pci.c b/hw/virtio/virtio-iommu-pci.c +index a160ae6b41..37eb2fb979 100644 +--- a/hw/virtio/virtio-iommu-pci.c ++++ b/hw/virtio/virtio-iommu-pci.c +@@ -44,6 +44,7 @@ static Property virtio_iommu_pci_properties[] = { + static void virtio_iommu_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp) + { + VirtIOIOMMUPCI *dev = VIRTIO_IOMMU_PCI(vpci_dev); ++ PCIBus *pbus = pci_get_bus(&vpci_dev->pci_dev); + DeviceState *vdev = DEVICE(&dev->vdev); + VirtIOIOMMU *s = VIRTIO_IOMMU(vdev); + +@@ -65,11 +66,17 @@ static void virtio_iommu_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp) + s->reserved_regions[i].type != VIRTIO_IOMMU_RESV_MEM_T_MSI) { + error_setg(errp, "reserved region %d has an invalid type", i); + error_append_hint(errp, "Valid values are 0 and 1\n"); +- } ++ return; ++ } + } ++ if (!pci_bus_is_root(pbus)) { ++ error_setg(errp, "virtio-iommu-pci must be plugged on the root bus"); ++ return; ++ } ++ + object_property_set_link(OBJECT(dev), "primary-bus", +- OBJECT(pci_get_bus(&vpci_dev->pci_dev)), +- &error_abort); ++ OBJECT(pbus), &error_abort); ++ + virtio_pci_force_virtio_1(vpci_dev); + qdev_realize(vdev, BUS(&vpci_dev->bus), errp); + } +-- +2.27.0 + diff --git a/migration-colo-More-accurate-update-checkpoint-time.patch b/migration-colo-More-accurate-update-checkpoint-time.patch new file mode 100644 index 00000000..21a4aad3 --- /dev/null +++ b/migration-colo-More-accurate-update-checkpoint-time.patch @@ -0,0 +1,44 @@ +From 3577b5c059bd3f83d47f72ef400e85160d56bc58 Mon Sep 17 00:00:00 2001 +From: Luo Yifan +Date: Fri, 1 Dec 2023 11:11:43 +0800 +Subject: [PATCH] migration/colo: More accurate update checkpoint time + +cherry picked from commit 0e0f0479e28c6c1a1d024b2e5200cade479d6901 + +Previous operation(like vm_start and replication_start_all) will consume +extra time before update the timer, so reduce time in this patch. + +Signed-off-by: Zhang Chen +Reviewed-by: Juan Quintela +Signed-off-by: Juan Quintela +Signed-off-by: Luo Yifan +--- + migration/colo.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +diff --git a/migration/colo.c b/migration/colo.c +index 2415325262..c8fadae956 100644 +--- a/migration/colo.c ++++ b/migration/colo.c +@@ -530,7 +530,6 @@ static void colo_process_checkpoint(MigrationState *s) + { + QIOChannelBuffer *bioc; + QEMUFile *fb = NULL; +- int64_t current_time = qemu_clock_get_ms(QEMU_CLOCK_HOST); + Error *local_err = NULL; + int ret; + +@@ -578,8 +577,8 @@ static void colo_process_checkpoint(MigrationState *s) + qemu_mutex_unlock_iothread(); + trace_colo_vm_state_change("stop", "run"); + +- timer_mod(s->colo_delay_timer, +- current_time + s->parameters.x_checkpoint_delay); ++ timer_mod(s->colo_delay_timer, qemu_clock_get_ms(QEMU_CLOCK_HOST) + ++ s->parameters.x_checkpoint_delay); + + while (s->state == MIGRATION_STATUS_COLO) { + if (failover_get_state() != FAILOVER_STATUS_NONE) { +-- +2.27.0 + diff --git a/qemu.spec b/qemu.spec index 56bec06b..bc9d629c 100644 --- a/qemu.spec +++ b/qemu.spec @@ -3,7 +3,7 @@ Name: qemu Version: 6.2.0 -Release: 85 +Release: 86 Epoch: 10 Summary: QEMU is a generic and open source machine emulator and virtualizer License: GPLv2 and BSD and MIT and CC-BY-SA-4.0 @@ -785,6 +785,54 @@ Patch0770: libvhost-user-Fix-VHOST_USER_GET_MAX_MEM_SLOTS-reply.patch Patch0771: tests-qtest-check-the-return-value.patch Patch0772: hw-net-cadence_gem.c-spelling-fixes-Octects.patch Patch0773: hw-arm-fsl-imx-Do-not-ignore-Error-argument.patch +Patch0774: xen-pass-through-don-t-create-needless-register-grou.patch +Patch0775: spapr-pci-Correct-does-not-support-hotplugging-error.patch +Patch0776: hmp-Improve-sync-profile-error-message.patch +Patch0777: qga-Improve-guest-exec-status-error-message.patch +Patch0778: ui-qmp-cmds-Improve-two-error-messages.patch +Patch0779: tcg-loongarch64-Fix-tcg_out_mov-Aborted.patch +Patch0780: disas-hppa-Show-hexcode-of-instruction-along-with-di.patch +Patch0781: target-arm-Don-t-set-syndrome-ISS-for-loads-and-stor.patch +Patch0782: balloon-Fix-a-misleading-error-message.patch +Patch0783: target-i386-cpu-Improve-error-message-for-property-v.patch +Patch0784: tests-qtest-migration-test.c-spelling-fix-bandwith.patch +Patch0785: xen-pass-through-merge-emulated-bits-correctly.patch +Patch0786: hw-display-next-fb-Fix-comment-typo.patch +Patch0787: hw-virtio-virtio-iommu-pci-Enforce-the-device-is-plu.patch +Patch0788: hw-ide-atapi.c-Correct-typos-CD-CDROM-CD-ROM.patch +Patch0789: trivial-typos-namesapce.patch +Patch0790: tests-qtest-Fix-two-format-strings.patch +Patch0791: sphinx-change-default-language-to-en.patch +Patch0792: block-use-unsigned-for-in_flight-field-on-driver-sta.patch +Patch0793: Fix-STM32F2XX-USART-data-register-readout.patch +Patch0794: Revert-hw-virtio-virtio-iommu-pci-Enforce-the-device.patch +Patch0795: hw-riscv-boot-Reduce-FDT-address-alignment-constrain.patch +Patch0796: vhost-user-blk-propagate-error-return-from-generic-v.patch +Patch0797: vhost-user-blk-reconnect-on-any-error-during-realize.patch +Patch0798: hw-arm-ast2600-Fix-address-mapping-of-second-SPI-con.patch +Patch0799: Add-dummy-Aspeed-AST2600-Display-Port-MCU-DPMCU.patch +Patch0800: hw-net-npcm7xx_emc-fix-missing-queue_flush.patch +Patch0801: block-nvme-fix-infinite-loop-in-nvme_free_req_queue_.patch +Patch0802: scripts-entitlement.sh-Use-backward-compatible-cp-fl.patch +Patch0803: migration-colo-More-accurate-update-checkpoint-time.patch +Patch0804: Fixed-a-QEMU-hang-when-guest-poweroff-in-COLO-mode.patch +Patch0805: hw-intc-arm_gicv3-ICC_PMR_EL1-high-bits-should-be-RA.patch +Patch0806: target-ppc-cpu-models-Remove-the-default-CPU-alias.patch +Patch0807: hw-usb-dev-mtp-Use-g_mkdir.patch +Patch0808: ui-gtk-prevent-ui-lock-up-when-dpy_gl_update-called-.patch +Patch0809: vhost-fix-null-pointer-access.patch +Patch0810: vhost-vdpa-add-VHOST_BACKEND_F_BYTEMAPLOG.patch +Patch0811: vhost-vdpa-add-migration-log-ops-for-VhostOps.patch +Patch0812: vhost-introduce-bytemap-for-vhost-backend-logging.patch +Patch0813: vhost-add-vhost_dev_suspend-resume_op.patch +Patch0814: vhost-implement-vhost-vdpa-suspend-resume.patch +Patch0815: vhost-implement-vhost_vdpa_device_suspend-resume.patch +Patch0816: vhost-implement-savevm_hanlder-for-vdpa-device.patch +Patch0817: vhost-implement-migration-state-notifier-for-vdpa-de.patch +Patch0818: vhost-implement-post-resume-bh.patch +Patch0819: vdpa-implement-vdpa-device-migration.patch +Patch0820: vdpa-move-memory-listener-to-the-realize-stage.patch + BuildRequires: flex BuildRequires: gcc @@ -1383,6 +1431,55 @@ getent passwd qemu >/dev/null || \ %endif %changelog +* Tue Dec 5 2023 - 10:6.2.0-86 +- vdpa: move memory listener to the realize stage +- vdpa: implement vdpa device migration +- vhost: implement post resume bh +- vhost: implement migration state notifier for vdpa device +- vhost: implement savevm_hanlder for vdpa device +- vhost: implement vhost_vdpa_device_suspend/resume +- vhost: implement vhost-vdpa suspend/resume +- vhost: add vhost_dev_suspend/resume_op +- vhost: introduce bytemap for vhost backend logging +- vhost-vdpa: add migration log ops for VhostOps +- vhost-vdpa: add VHOST_BACKEND_F_BYTEMAPLOG +- vhost: fix null pointer access +- ui/gtk: prevent ui lock up when dpy_gl_update called again before current draw event occurs +- hw/usb: dev-mtp: Use g_mkdir() +- target/ppc/cpu-models: Remove the "default" CPU alias +- hw/intc/arm_gicv3: ICC_PMR_EL1 high bits should be RAZ +- Fixed a QEMU hang when guest poweroff in COLO mode +- migration/colo: More accurate update checkpoint time +- scripts/entitlement.sh: Use backward-compatible cp flags +- block/nvme: fix infinite loop in nvme_free_req_queue_cb() +- hw/net: npcm7xx_emc fix missing queue_flush +- Add dummy Aspeed AST2600 Display Port MCU (DPMCU) +- hw/arm: ast2600: Fix address mapping of second SPI controller +- vhost-user-blk: reconnect on any error during realize +- vhost-user-blk: propagate error return from generic vhost +- hw/riscv: boot: Reduce FDT address alignment constraints +- Revert "hw/virtio/virtio-iommu-pci: Enforce the device is plugged on the root bus" +- Fix STM32F2XX USART data register readout +- block: use 'unsigned' for in_flight field on driver state +- sphinx: change default language to 'en' +- tests/qtest: Fix two format strings +- trivial typos: namesapce +- hw/ide/atapi.c: Correct typos (CD-CDROM -> CD-ROM) +- hw/virtio/virtio-iommu-pci: Enforce the device is plugged on the root bus +- hw/display/next-fb: Fix comment typo +- xen/pass-through: merge emulated bits correctly mainline inclusion commit be9c61da9fc57eb7d293f380d0805ca6f46c2657 category: bugfix +- tests/qtest/migration-test.c: spelling fix: bandwith +- target/i386/cpu: Improve error message for property "vendor" +- balloon: Fix a misleading error message +- target/arm: Don't set syndrome ISS for loads and stores with writeback mainline inclusion commit 53ae2fdef1f5661cbaa2ea571c517f98e6041cb8 category: bugfix +- disas/hppa: Show hexcode of instruction along with disassembly +- tcg/loongarch64: Fix tcg_out_mov() Aborted +- ui/qmp-cmds: Improve two error messages +- qga: Improve guest-exec-status error message +- hmp: Improve sync-profile error message +- spapr/pci: Correct "does not support hotplugging error messages +- xen/pass-through: don't create needless register group mainline inclusion commit c0e86b7624cb9d6db03e0d48cf82659e5b89a6a6 category: bugfix + * Fri Dec 1 2023 - 10:6.2.0-85 - spec: Add support for the ppc64le platform diff --git a/qga-Improve-guest-exec-status-error-message.patch b/qga-Improve-guest-exec-status-error-message.patch new file mode 100644 index 00000000..debbba79 --- /dev/null +++ b/qga-Improve-guest-exec-status-error-message.patch @@ -0,0 +1,42 @@ +From f28bc5e3a6418d8477e84b52e06dcab5db7cbf15 Mon Sep 17 00:00:00 2001 +From: boringandboring +Date: Mon, 27 Nov 2023 15:52:06 +0800 +Subject: [PATCH] qga: Improve guest-exec-status error message +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +cherry picked from b665165938d89c8e1f83f970d3722f507ce87acd + +When the PID passed to guest-exec-status does not exist, we report + + "Invalid parameter 'pid'" + +Improve this to + + "PID 1234 does not exist" + +Signed-off-by: Markus Armbruster +Message-ID: <20231031111059.3407803-4-armbru@redhat.com> +Reviewed-by: Konstantin Kostiuk +Reviewed-by: Philippe Mathieu-Daudé +--- + qga/commands.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/qga/commands.c b/qga/commands.c +index 05f89725be..9fe73786fc 100644 +--- a/qga/commands.c ++++ b/qga/commands.c +@@ -156,7 +156,7 @@ GuestExecStatus *qmp_guest_exec_status(int64_t pid, Error **errp) + + gei = guest_exec_info_find(pid); + if (gei == NULL) { +- error_setg(errp, QERR_INVALID_PARAMETER, "pid"); ++ error_setg(errp, "PID " PRId64 " does not exist"); + return NULL; + } + +-- +2.27.0 + diff --git a/scripts-entitlement.sh-Use-backward-compatible-cp-fl.patch b/scripts-entitlement.sh-Use-backward-compatible-cp-fl.patch new file mode 100644 index 00000000..6139fc97 --- /dev/null +++ b/scripts-entitlement.sh-Use-backward-compatible-cp-fl.patch @@ -0,0 +1,35 @@ +From 66da71e852323bf1eb7b75b93cfb13eb748ad10f Mon Sep 17 00:00:00 2001 +From: Luo Yifan +Date: Mon, 4 Dec 2023 10:09:12 +0800 +Subject: [PATCH] scripts/entitlement.sh: Use backward-compatible cp flags + +cherry picked from commit 4006a27c5e44734350009262efb0e2ec8da5ff09 + +Older versions of Mac OS X do not support cp -a. The cp man page indicates +that -a is equivalent to -pPR. + +Signed-off-by: Evan Miller +Message-Id: <40635C6E-059A-4146-B1E2-F6376700EE85@gmail.com> +[Leave out -R, these are files and not directories. - Paolo] +Signed-off-by: Paolo Bonzini +Signed-off-by: Luo Yifan +--- + scripts/entitlement.sh | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/scripts/entitlement.sh b/scripts/entitlement.sh +index e2c956a3ac..0f412949ec 100755 +--- a/scripts/entitlement.sh ++++ b/scripts/entitlement.sh +@@ -15,7 +15,7 @@ ENTITLEMENT="$4" + + if $in_place; then + trap 'rm "$DST.tmp"' exit +- cp -af "$SRC" "$DST.tmp" ++ cp -pPf "$SRC" "$DST.tmp" + SRC="$DST.tmp" + else + cd "$MESON_INSTALL_DESTDIR_PREFIX" +-- +2.27.0 + diff --git a/spapr-pci-Correct-does-not-support-hotplugging-error.patch b/spapr-pci-Correct-does-not-support-hotplugging-error.patch new file mode 100644 index 00000000..cb82a76b --- /dev/null +++ b/spapr-pci-Correct-does-not-support-hotplugging-error.patch @@ -0,0 +1,45 @@ +From f647bc67bcdbfc2dd1cb1f1ba1abdb2b04c5c10f Mon Sep 17 00:00:00 2001 +From: boringandboring +Date: Mon, 27 Nov 2023 16:19:33 +0800 +Subject: [PATCH] spapr/pci: Correct "does not support hotplugging error + messages + +cherry picked from db8227a68addb9db6392001c7e02d406282ea462 + +When dynamic-reconfiguration is off, hot plug / unplug can fail with +"Bus 'spapr-pci-host-bridge' does not support hotplugging". +spapr-pci-host-bridge is a device, not a bus. Report the name of the +bus it provides instead: 'pci.0'. + +Signed-off-by: Markus Armbruster +Message-ID: <20231031111059.3407803-2-armbru@redhat.com> +Reviewed-by: Daniel Henrique Barboza +--- + hw/ppc/spapr_pci.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c +index d3367e8578..3b518f1be9 100644 +--- a/hw/ppc/spapr_pci.c ++++ b/hw/ppc/spapr_pci.c +@@ -1554,7 +1554,7 @@ static void spapr_pci_pre_plug(HotplugHandler *plug_handler, + */ + if (plugged_dev->hotplugged) { + error_setg(errp, QERR_BUS_NO_HOTPLUG, +- object_get_typename(OBJECT(phb))); ++ phb->parent_obj.bus->qbus.name); + return; + } + } +@@ -1677,7 +1677,7 @@ static void spapr_pci_unplug_request(HotplugHandler *plug_handler, + + if (!phb->dr_enabled) { + error_setg(errp, QERR_BUS_NO_HOTPLUG, +- object_get_typename(OBJECT(phb))); ++ phb->parent_obj.bus->qbus.name); + return; + } + +-- +2.27.0 + diff --git a/sphinx-change-default-language-to-en.patch b/sphinx-change-default-language-to-en.patch new file mode 100644 index 00000000..77f2b2af --- /dev/null +++ b/sphinx-change-default-language-to-en.patch @@ -0,0 +1,38 @@ +From a6861159f23833f878be833e2c0c37060ac14513 Mon Sep 17 00:00:00 2001 +From: Wanghe Xiao +Date: Sat, 25 Nov 2023 02:57:47 -0800 +Subject: [PATCH] sphinx: change default language to 'en' + +cherry picked from commit ba1a6723f58640ba281bc952abc255e97c70bad5 + +Fixes the following Sphinx warning (treated as error) starting +with 5.0 release: + +Warning, treated as error: +Invalid configuration value found: 'language = None'. Update your configuration to a valid langauge code. Falling back to 'en' (English). + +Signed-off-by: Martin Liska +Message-id: e91e51ee-48ac-437e-6467-98b56ee40042@suse.cz +Reviewed-by: Peter Maydell +Signed-off-by: Peter Maydell +Signed-off-by: Wanghe Xiao +--- + docs/conf.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/docs/conf.py b/docs/conf.py +index 763e7d2434..84b593e12a 100644 +--- a/docs/conf.py ++++ b/docs/conf.py +@@ -120,7 +120,7 @@ + # + # This is also used if you do content translation via gettext catalogs. + # Usually you set "language" from the command line for these cases. +-language = None ++language = 'en' + + # List of patterns, relative to source directory, that match files and + # directories to ignore when looking for source files. +-- +2.27.0 + diff --git a/target-arm-Don-t-set-syndrome-ISS-for-loads-and-stor.patch b/target-arm-Don-t-set-syndrome-ISS-for-loads-and-stor.patch new file mode 100644 index 00000000..4fe6a0cd --- /dev/null +++ b/target-arm-Don-t-set-syndrome-ISS-for-loads-and-stor.patch @@ -0,0 +1,51 @@ +From dd5bf5817259ea414f40b25f4aef3864eddb9706 Mon Sep 17 00:00:00 2001 +From: tangbinzy +Date: Mon, 27 Nov 2023 03:24:57 +0000 +Subject: [PATCH] target/arm: Don't set syndrome ISS for loads and stores with + writeback mainline inclusion commit 53ae2fdef1f5661cbaa2ea571c517f98e6041cb8 + category: bugfix + +--------------------------------------------------------------- + +The architecture requires that for faults on loads and stores which +do writeback, the syndrome information does not have the ISS +instruction syndrome information (i.e. ISV is 0). We got this wrong +for the load and store instructions covered by disas_ldst_reg_imm9(). +Calculate iss_valid correctly so that if the insn is a writeback one +it is false. + +Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1057 +Signed-off-by: Peter Maydell +Reviewed-by: Richard Henderson +Message-id: 20220715123323.1550983-1-peter.maydell@linaro.org + +Signed-off-by: tangbinzy +--- + target/arm/translate-a64.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c +index cec672f229..549a671bea 100644 +--- a/target/arm/translate-a64.c ++++ b/target/arm/translate-a64.c +@@ -3039,7 +3039,7 @@ static void disas_ldst_reg_imm9(DisasContext *s, uint32_t insn, + bool is_store = false; + bool is_extended = false; + bool is_unpriv = (idx == 2); +- bool iss_valid = !is_vector; ++ bool iss_valid; + bool post_index; + bool writeback; + int memidx; +@@ -3092,6 +3092,8 @@ static void disas_ldst_reg_imm9(DisasContext *s, uint32_t insn, + g_assert_not_reached(); + } + ++ iss_valid = !is_vector && !writeback; ++ + if (rn == 31) { + gen_check_sp_alignment(s); + } +-- +2.27.0 + diff --git a/target-i386-cpu-Improve-error-message-for-property-v.patch b/target-i386-cpu-Improve-error-message-for-property-v.patch new file mode 100644 index 00000000..462d4877 --- /dev/null +++ b/target-i386-cpu-Improve-error-message-for-property-v.patch @@ -0,0 +1,45 @@ +From dca8f8c8bc4466d2502bcd305fcc8e84adf992da Mon Sep 17 00:00:00 2001 +From: boringandboring +Date: Mon, 27 Nov 2023 10:20:40 +0800 +Subject: [PATCH] target/i386/cpu: Improve error message for property "vendor" +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +cherry picked from 298d8b122056052951bda487392d8aabbfd0f3e5 + +Improve + + $ qemu-system-x86_64 -device max-x86_64-cpu,vendor=me + qemu-system-x86_64: -device max-x86_64-cpu,vendor=me: Property '.vendor' doesn't take value 'me' + +to + + qemu-system-x86_64: -device max-x86_64-cpu,vendor=0123456789abc: value of property 'vendor' must consist of exactly 12 characters + +Signed-off-by: Markus Armbruster +Message-ID: <20231031111059.3407803-8-armbru@redhat.com> +Reviewed-by: Philippe Mathieu-Daudé + +Signed-off-by: boringandboring +--- + target/i386/cpu.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index 6aaa730a0d..53a7484ca8 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -4805,7 +4805,8 @@ static void x86_cpuid_set_vendor(Object *obj, const char *value, + int i; + + if (strlen(value) != CPUID_VENDOR_SZ) { +- error_setg(errp, QERR_PROPERTY_VALUE_BAD, "", "vendor", value); ++ error_setg(errp, "value of property 'vendor' must consist of" ++ " exactly " stringify(CPUID_VENDOR_SZ) " characters"); + return; + } + +-- +2.27.0 + diff --git a/target-ppc-cpu-models-Remove-the-default-CPU-alias.patch b/target-ppc-cpu-models-Remove-the-default-CPU-alias.patch new file mode 100644 index 00000000..048ca97c --- /dev/null +++ b/target-ppc-cpu-models-Remove-the-default-CPU-alias.patch @@ -0,0 +1,40 @@ +From 73ece819848b2ecc110ec676413d5a86ffc0f8fc Mon Sep 17 00:00:00 2001 +From: Wanghe Xiao +Date: Sat, 25 Nov 2023 02:26:10 -0800 +Subject: [PATCH] target/ppc/cpu-models: Remove the "default" CPU alias +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +cherry picked from commit 7886605961d0a9c40ada0c28dee5fa0b42a30836 + +QEMU emulates a *lot* of PowerPC-based machines - having a CPU +that is named "default" and cannot be used with most of those +machines sounds just wrong. Thus let's remove this old and confusing +alias now. + +Signed-off-by: Thomas Huth +Reviewed-by: Greg Kurz +Reviewed-by: Cédric Le Goater +Message-Id: <20220705151030.662140-1-thuth@redhat.com> +Signed-off-by: Daniel Henrique Barboza +Signed-off-by: Wanghe Xiao +--- + target/ppc/cpu-models.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/target/ppc/cpu-models.c b/target/ppc/cpu-models.c +index 4baa111713..02efc95723 100644 +--- a/target/ppc/cpu-models.c ++++ b/target/ppc/cpu-models.c +@@ -963,6 +963,6 @@ PowerPCCPUAlias ppc_cpu_aliases[] = { + #endif + { "ppc32", "604" }, + { "ppc", "604" }, +- { "default", "604" }, ++ + { NULL, NULL } + }; +-- +2.27.0 + diff --git a/tcg-loongarch64-Fix-tcg_out_mov-Aborted.patch b/tcg-loongarch64-Fix-tcg_out_mov-Aborted.patch new file mode 100644 index 00000000..190a5c32 --- /dev/null +++ b/tcg-loongarch64-Fix-tcg_out_mov-Aborted.patch @@ -0,0 +1,64 @@ +From ea14e0f1c97b6af8db9fa7b2d0df14ef03d9acb9 Mon Sep 17 00:00:00 2001 +From: boringandboring +Date: Mon, 27 Nov 2023 14:04:58 +0800 +Subject: [PATCH] tcg/loongarch64: Fix tcg_out_mov() Aborted +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +cherry picked from 85d57a37be1461d599747ab86dc0acc46732dbce + +On LoongArch host, we got an Aborted from tcg_out_mov(). + +qemu-x86_64 configure with '--enable-debug'. + +> (gdb) b /home1/gaosong/code/qemu/tcg/loongarch64/tcg-target.c.inc:312 +> Breakpoint 1 at 0x2576f0: file /home1/gaosong/code/qemu/tcg/loongarch64/tcg-target.c.inc, line 312. +> (gdb) run hello +[...] +> Thread 1 "qemu-x86_64" hit Breakpoint 1, tcg_out_mov (s=0xaaaae91760 , type=TCG_TYPE_V128, ret=TCG_REG_V2, +> arg=TCG_REG_V0) at /home1/gaosong/code/qemu/tcg/loongarch64/tcg-target.c.inc:312 +> 312 g_assert_not_reached(); +> (gdb) bt +> #0 tcg_out_mov (s=0xaaaae91760 , type=TCG_TYPE_V128, ret=TCG_REG_V2, arg=TCG_REG_V0) +> at /home1/gaosong/code/qemu/tcg/loongarch64/tcg-target.c.inc:312 +> #1 0x000000aaaad0fee0 in tcg_reg_alloc_mov (s=0xaaaae91760 , op=0xaaaaf67c20) at ../tcg/tcg.c:4632 +> #2 0x000000aaaad142f4 in tcg_gen_code (s=0xaaaae91760 , tb=0xffe8030340 , +> pc_start=4346094) at ../tcg/tcg.c:6135 +[...] +> (gdb) c +> Continuing. +> ** +> ERROR:/home1/gaosong/code/qemu/tcg/loongarch64/tcg-target.c.inc:312:tcg_out_mov: code should not be reached +> Bail out! ERROR:/home1/gaosong/code/qemu/tcg/loongarch64/tcg-target.c.inc:312:tcg_out_mov: code should not be reached +> +> Thread 1 "qemu-x86_64" received signal SIGABRT, Aborted. +> 0x000000fff7b1c390 in raise () from /lib64/libc.so.6 +> (gdb) q + +Fixes: 16288ded94 ("tcg/loongarch64: Lower basic tcg vec ops to LSX") +Reviewed-by: Philippe Mathieu-Daudé +Reviewed-by: Richard Henderson +Signed-off-by: Song Gao +Message-Id: <20231120065916.374045-1-gaosong@loongson.cn> +--- + tcg/loongarch64/tcg-target.c.inc | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc +index 0b28b30002..ee7d4d728d 100644 +--- a/tcg/loongarch64/tcg-target.c.inc ++++ b/tcg/loongarch64/tcg-target.c.inc +@@ -255,6 +255,9 @@ static bool tcg_out_mov(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg) + */ + tcg_out_opc_or(s, ret, arg, TCG_REG_ZERO); + break; ++ case TCG_TYPE_V128: ++ tcg_out_opc_vori_b(s, ret, arg, 0); ++ break; + default: + g_assert_not_reached(); + } +-- +2.27.0 + diff --git a/tests-qtest-Fix-two-format-strings.patch b/tests-qtest-Fix-two-format-strings.patch new file mode 100644 index 00000000..ed739b90 --- /dev/null +++ b/tests-qtest-Fix-two-format-strings.patch @@ -0,0 +1,44 @@ +From 00b21f96b39b892d9dff0fc7616e88e7238d54cc Mon Sep 17 00:00:00 2001 +From: Wanghe Xiao +Date: Sat, 25 Nov 2023 02:14:16 -0800 +Subject: [PATCH] tests/qtest: Fix two format strings +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +cherry picked from commit d46e6bba55f858b829251e2f4bd7b150cdb5b1d6 + +Signed-off-by: Stefan Weil +Message-Id: <20221105115525.623059-1-sw@weilnetz.de> +Reviewed-by: Philippe Mathieu-Daudé +Signed-off-by: Thomas Huth +Signed-off-by: Wanghe Xiao +--- + tests/qtest/migration-test.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c +index 8fad247f6c..194c7cb661 100644 +--- a/tests/qtest/migration-test.c ++++ b/tests/qtest/migration-test.c +@@ -1406,7 +1406,7 @@ static void calc_dirty_rate(QTestState *who, uint64_t calc_time) + qobject_unref(qmp_command(who, + "{ 'execute': 'calc-dirty-rate'," + "'arguments': { " +- "'calc-time': %ld," ++ "'calc-time': %" PRIu64 "," + "'mode': 'dirty-ring' }}", + calc_time)); + } +@@ -1421,7 +1421,7 @@ static void dirtylimit_set_all(QTestState *who, uint64_t dirtyrate) + qobject_unref(qmp_command(who, + "{ 'execute': 'set-vcpu-dirty-limit'," + "'arguments': { " +- "'dirty-rate': %ld } }", ++ "'dirty-rate': %" PRIu64 " } }", + dirtyrate)); + } + +-- +2.27.0 + diff --git a/tests-qtest-migration-test.c-spelling-fix-bandwith.patch b/tests-qtest-migration-test.c-spelling-fix-bandwith.patch new file mode 100644 index 00000000..93b57eb5 --- /dev/null +++ b/tests-qtest-migration-test.c-spelling-fix-bandwith.patch @@ -0,0 +1,26 @@ +From a13b274df192b01a2b8f3f5ca5497a330705caa3 Mon Sep 17 00:00:00 2001 +From: zhujun2 +Date: Fri, 24 Nov 2023 00:46:51 -0800 +Subject: [PATCH] tests/qtest/migration-test.c: spelling fix: bandwith + +Signed-off-by: zhujun2 +--- + tests/qtest/migration-test.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c +index 8fad247f6c..3813b15ea9 100644 +--- a/tests/qtest/migration-test.c ++++ b/tests/qtest/migration-test.c +@@ -1157,7 +1157,7 @@ static void test_migrate_auto_converge(void) + + /* + * We want the test to be stable and as fast as possible. +- * E.g., with 1Gb/s bandwith migration may pass without throttling, ++ * E.g., with 1Gb/s bandwidth migration may pass without throttling, + * so we need to decrease a bandwidth. + */ + const int64_t init_pct = 5, inc_pct = 50, max_pct = 95; +-- +2.27.0 + diff --git a/trivial-typos-namesapce.patch b/trivial-typos-namesapce.patch new file mode 100644 index 00000000..60564e4e --- /dev/null +++ b/trivial-typos-namesapce.patch @@ -0,0 +1,89 @@ +From ec92a6e31bb5bf118a09bdc085e1e4f476b98f1e Mon Sep 17 00:00:00 2001 +From: Wanghe Xiao +Date: Sat, 25 Nov 2023 02:48:55 -0800 +Subject: [PATCH] trivial typos: namesapce + +cherry picked from commit a0984714fb700683094a754a2320a2e150cf10a7 + +'namespace' is misspelled in a bunch of places. + +Signed-off-by: Dr. David Alan Gilbert +Reviewed-by: Klaus Jensen +Message-Id: <20220614104045.85728-3-dgilbert@redhat.com> +Signed-off-by: Laurent Vivier +Signed-off-by: Wanghe Xiao +--- + hw/9pfs/9p-xattr-user.c | 8 ++++---- + hw/acpi/nvdimm.c | 2 +- + hw/nvme/ctrl.c | 2 +- + 3 files changed, 6 insertions(+), 6 deletions(-) + +diff --git a/hw/9pfs/9p-xattr-user.c b/hw/9pfs/9p-xattr-user.c +index f2ae9582e6..535677ed60 100644 +--- a/hw/9pfs/9p-xattr-user.c ++++ b/hw/9pfs/9p-xattr-user.c +@@ -27,7 +27,7 @@ static ssize_t mp_user_getxattr(FsContext *ctx, const char *path, + { + if (strncmp(name, "user.virtfs.", 12) == 0) { + /* +- * Don't allow fetch of user.virtfs namesapce ++ * Don't allow fetch of user.virtfs namespace + * in case of mapped security + */ + errno = ENOATTR; +@@ -49,7 +49,7 @@ static ssize_t mp_user_listxattr(FsContext *ctx, const char *path, + name_size -= 12; + } else { + /* +- * Don't allow fetch of user.virtfs namesapce ++ * Don't allow fetch of user.virtfs namespace + * in case of mapped security + */ + return 0; +@@ -74,7 +74,7 @@ static int mp_user_setxattr(FsContext *ctx, const char *path, const char *name, + { + if (strncmp(name, "user.virtfs.", 12) == 0) { + /* +- * Don't allow fetch of user.virtfs namesapce ++ * Don't allow fetch of user.virtfs namespace + * in case of mapped security + */ + errno = EACCES; +@@ -88,7 +88,7 @@ static int mp_user_removexattr(FsContext *ctx, + { + if (strncmp(name, "user.virtfs.", 12) == 0) { + /* +- * Don't allow fetch of user.virtfs namesapce ++ * Don't allow fetch of user.virtfs namespace + * in case of mapped security + */ + errno = EACCES; +diff --git a/hw/acpi/nvdimm.c b/hw/acpi/nvdimm.c +index 0d43da19ea..5f85b16327 100644 +--- a/hw/acpi/nvdimm.c ++++ b/hw/acpi/nvdimm.c +@@ -476,7 +476,7 @@ struct NvdimmFuncGetLabelDataOut { + /* the size of buffer filled by QEMU. */ + uint32_t len; + uint32_t func_ret_status; /* return status code. */ +- uint8_t out_buf[]; /* the data got via Get Namesapce Label function. */ ++ uint8_t out_buf[]; /* the data got via Get Namespace Label function. */ + } QEMU_PACKED; + typedef struct NvdimmFuncGetLabelDataOut NvdimmFuncGetLabelDataOut; + QEMU_BUILD_BUG_ON(sizeof(NvdimmFuncGetLabelDataOut) > NVDIMM_DSM_MEMORY_SIZE); +diff --git a/hw/nvme/ctrl.c b/hw/nvme/ctrl.c +index d64dd9c361..7c9f97bdb3 100644 +--- a/hw/nvme/ctrl.c ++++ b/hw/nvme/ctrl.c +@@ -71,7 +71,7 @@ + * the SUBNQN field in the controller will report the NQN of the subsystem + * device. This also enables multi controller capability represented in + * Identify Controller data structure in CMIC (Controller Multi-path I/O and +- * Namesapce Sharing Capabilities). ++ * Namespace Sharing Capabilities). + * + * - `aerl` + * The Asynchronous Event Request Limit (AERL). Indicates the maximum number +-- +2.27.0 + diff --git a/ui-gtk-prevent-ui-lock-up-when-dpy_gl_update-called-.patch b/ui-gtk-prevent-ui-lock-up-when-dpy_gl_update-called-.patch new file mode 100644 index 00000000..1b658ad6 --- /dev/null +++ b/ui-gtk-prevent-ui-lock-up-when-dpy_gl_update-called-.patch @@ -0,0 +1,71 @@ +From 37625d78afdadb5e88aa4616d613f64184db41bf Mon Sep 17 00:00:00 2001 +From: Wanghe Xiao +Date: Sat, 25 Nov 2023 01:42:26 -0800 +Subject: [PATCH] ui/gtk: prevent ui lock up when dpy_gl_update called again + before current draw event occurs +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +cherry picked from commit 64f1359bd08060ffe7a5689fdcbaeec6d8a59980 + +A warning, "qemu: warning: console: no gl-unblock within" followed by +guest scanout lockup can happen if dpy_gl_update is called in a row +and the second call is made before gd_draw_event scheduled by the first +call is taking place. This is because draw call returns without decrementing +gl_block ref count if the dmabuf was already submitted as shown below. + +(gd_gl_area_draw/gd_egl_draw) + + if (dmabuf) { + if (!dmabuf->draw_submitted) { + return; + } else { + dmabuf->draw_submitted = false; + } + } + +So it should not schedule any redundant draw event in case draw_submitted is +already set in gd_egl_fluch/gd_gl_area_scanout_flush. + +Cc: Gerd Hoffmann +Cc: Vivek Kasireddy +Signed-off-by: Dongwon Kim +Reviewed-by: Marc-André Lureau +Message-Id: <20221021192315.9110-1-dongwon.kim@intel.com> +Signed-off-by: Gerd Hoffmann +Signed-off-by: Wanghe Xiao +--- + ui/gtk-egl.c | 2 +- + ui/gtk-gl-area.c | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/ui/gtk-egl.c b/ui/gtk-egl.c +index 45cb67712d..0e1e5bfaaa 100644 +--- a/ui/gtk-egl.c ++++ b/ui/gtk-egl.c +@@ -340,7 +340,7 @@ void gd_egl_flush(DisplayChangeListener *dcl, + VirtualConsole *vc = container_of(dcl, VirtualConsole, gfx.dcl); + GtkWidget *area = vc->gfx.drawing_area; + +- if (vc->gfx.guest_fb.dmabuf) { ++ if (vc->gfx.guest_fb.dmabuf && !vc->gfx.guest_fb.dmabuf->draw_submitted) { + graphic_hw_gl_block(vc->gfx.dcl.con, true); + vc->gfx.guest_fb.dmabuf->draw_submitted = true; + gtk_widget_queue_draw_area(area, x, y, w, h); +diff --git a/ui/gtk-gl-area.c b/ui/gtk-gl-area.c +index 01e4e74ee3..11e0cb4af2 100644 +--- a/ui/gtk-gl-area.c ++++ b/ui/gtk-gl-area.c +@@ -246,7 +246,7 @@ void gd_gl_area_scanout_flush(DisplayChangeListener *dcl, + { + VirtualConsole *vc = container_of(dcl, VirtualConsole, gfx.dcl); + +- if (vc->gfx.guest_fb.dmabuf) { ++ if (vc->gfx.guest_fb.dmabuf && !vc->gfx.guest_fb.dmabuf->draw_submitted) { + graphic_hw_gl_block(vc->gfx.dcl.con, true); + vc->gfx.guest_fb.dmabuf->draw_submitted = true; + } +-- +2.27.0 + diff --git a/ui-qmp-cmds-Improve-two-error-messages.patch b/ui-qmp-cmds-Improve-two-error-messages.patch new file mode 100644 index 00000000..9cab96b9 --- /dev/null +++ b/ui-qmp-cmds-Improve-two-error-messages.patch @@ -0,0 +1,68 @@ +From 0425d773b3fa0da62be489ae6c76d1805f28f388 Mon Sep 17 00:00:00 2001 +From: boringandboring +Date: Mon, 27 Nov 2023 15:47:21 +0800 +Subject: [PATCH] ui/qmp-cmds: Improve two error messages +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +cherry picked from 517b0220efd421acf885eed109571a61e95b192a + +set_password with "protocol": "vnc" supports only "connected": "keep". +Any other value is rejected with + + Invalid parameter 'connected' + +Improve this to + + parameter 'connected' must be 'keep' when 'protocol' is 'vnc' + +client_migrate_info requires "port" or "tls-port". When both are +missing, it fails with + + Parameter 'port/tls-port' is missing + +Improve this to + + parameter 'port' or 'tls-port' is required + +Signed-off-by: Markus Armbruster +Message-ID: <20231031111059.3407803-5-armbru@redhat.com> +Reviewed-by: Philippe Mathieu-Daudé + +Signed-off-by: boringandboring +--- + monitor/misc.c | 2 +- + monitor/qmp-cmds.c | 3 ++- + 2 files changed, 3 insertions(+), 2 deletions(-) + +diff --git a/monitor/misc.c b/monitor/misc.c +index a3a6e47844..25a23e2290 100644 +--- a/monitor/misc.c ++++ b/monitor/misc.c +@@ -397,7 +397,7 @@ void qmp_client_migrate_info(const char *protocol, const char *hostname, + } + + if (!has_port && !has_tls_port) { +- error_setg(errp, QERR_MISSING_PARAMETER, "port/tls-port"); ++ error_setg(errp, "parameter 'port' or 'tls-port' is required"); + return; + } + +diff --git a/monitor/qmp-cmds.c b/monitor/qmp-cmds.c +index d71beace6a..b44cca8234 100644 +--- a/monitor/qmp-cmds.c ++++ b/monitor/qmp-cmds.c +@@ -199,7 +199,8 @@ void qmp_set_password(const char *protocol, const char *password, + } else if (strcmp(protocol, "vnc") == 0) { + if (fail_if_connected || disconnect_if_connected) { + /* vnc supports "connected=keep" only */ +- error_setg(errp, QERR_INVALID_PARAMETER, "connected"); ++ error_setg(errp, "parameter 'connected' must be 'keep'" ++ " when 'protocol' is 'vnc'"); + return; + } + /* Note that setting an empty password will not disable login through +-- +2.27.0 + diff --git a/vdpa-implement-vdpa-device-migration.patch b/vdpa-implement-vdpa-device-migration.patch new file mode 100644 index 00000000..ffc1d795 --- /dev/null +++ b/vdpa-implement-vdpa-device-migration.patch @@ -0,0 +1,77 @@ +From 722147da4fb76c0ee6e75957712073a820ab1d75 Mon Sep 17 00:00:00 2001 +From: fangyi +Date: Mon, 4 Dec 2023 15:59:56 +0800 +Subject: [PATCH] vdpa: implement vdpa device migration + +Integrate the live migration code, call the registered live +migration function, and open the vdpa live migration prototype + +Signed-off-by: libai +Signed-off-by: jiangdongxu +Signed-off-by: fangyi +--- + hw/virtio/vdpa-dev.c | 13 ++++++++++++- + 1 file changed, 12 insertions(+), 1 deletion(-) + +diff --git a/hw/virtio/vdpa-dev.c b/hw/virtio/vdpa-dev.c +index 254a213117..986b5d0a78 100644 +--- a/hw/virtio/vdpa-dev.c ++++ b/hw/virtio/vdpa-dev.c +@@ -29,6 +29,8 @@ + #include "hw/virtio/vdpa-dev.h" + #include "sysemu/sysemu.h" + #include "sysemu/runstate.h" ++#include "hw/virtio/vdpa-dev-mig.h" ++#include "migration/migration.h" + + static void + vhost_vdpa_device_dummy_handle_output(VirtIODevice *vdev, VirtQueue *vq) +@@ -155,6 +157,8 @@ static void vhost_vdpa_device_realize(DeviceState *dev, Error **errp) + vhost_vdpa_device_dummy_handle_output); + } + ++ vdpa_migration_register(v); ++ + return; + + free_config: +@@ -174,6 +178,7 @@ static void vhost_vdpa_device_unrealize(DeviceState *dev) + VhostVdpaDevice *s = VHOST_VDPA_DEVICE(vdev); + int i; + ++ vdpa_migration_unregister(s); + virtio_set_status(vdev, 0); + + for (i = 0; i < s->num_queues; i++) { +@@ -306,6 +311,7 @@ static void vhost_vdpa_device_stop(VirtIODevice *vdev) + static void vhost_vdpa_device_set_status(VirtIODevice *vdev, uint8_t status) + { + VhostVdpaDevice *s = VHOST_VDPA_DEVICE(vdev); ++ MigrationState *ms = migrate_get_current(); + bool should_start = virtio_device_started(vdev, status); + Error *local_err = NULL; + int ret; +@@ -318,6 +324,11 @@ static void vhost_vdpa_device_set_status(VirtIODevice *vdev, uint8_t status) + return; + } + ++ if (ms->state == RUN_STATE_PAUSED || ++ ms->state == RUN_STATE_RESTORE_VM) { ++ return; ++ } ++ + if (should_start) { + ret = vhost_vdpa_device_start(vdev, &local_err); + if (ret < 0) { +@@ -336,7 +347,7 @@ static Property vhost_vdpa_device_properties[] = { + + static const VMStateDescription vmstate_vhost_vdpa_device = { + .name = "vhost-vdpa-device", +- .unmigratable = 1, ++ .unmigratable = 0, + .minimum_version_id = 1, + .version_id = 1, + .fields = (VMStateField[]) { +-- +2.27.0 + diff --git a/vdpa-move-memory-listener-to-the-realize-stage.patch b/vdpa-move-memory-listener-to-the-realize-stage.patch new file mode 100644 index 00000000..b762409f --- /dev/null +++ b/vdpa-move-memory-listener-to-the-realize-stage.patch @@ -0,0 +1,112 @@ +From 232ee383f3a2363bdc8f1bde873740375b5b92bb Mon Sep 17 00:00:00 2001 +From: fangyi +Date: Mon, 4 Dec 2023 16:01:16 +0800 +Subject: [PATCH] vdpa: move memory listener to the realize stage + +Move the memory listener registration of vdpa from the start stage +to the realize stage. Avoid that in the start phase, the memory +listener callback function has not yet been processed. + +Signed-off-by: jiangdongxu +Signed-off-by: fangyi +--- + hw/virtio/vdpa-dev.c | 4 ++++ + hw/virtio/vhost-vdpa.c | 8 -------- + 2 files changed, 4 insertions(+), 8 deletions(-) + +diff --git a/hw/virtio/vdpa-dev.c b/hw/virtio/vdpa-dev.c +index 986b5d0a78..143dadc88d 100644 +--- a/hw/virtio/vdpa-dev.c ++++ b/hw/virtio/vdpa-dev.c +@@ -31,6 +31,7 @@ + #include "sysemu/runstate.h" + #include "hw/virtio/vdpa-dev-mig.h" + #include "migration/migration.h" ++#include "exec/address-spaces.h" + + static void + vhost_vdpa_device_dummy_handle_output(VirtIODevice *vdev, VirtQueue *vq) +@@ -126,6 +127,7 @@ static void vhost_vdpa_device_realize(DeviceState *dev, Error **errp) + goto free_vqs; + } + ++ memory_listener_register(&v->vdpa.listener, &address_space_memory); + v->config_size = vhost_vdpa_device_get_u32(v->vhostfd, + VHOST_VDPA_GET_CONFIG_SIZE, + errp); +@@ -164,6 +166,7 @@ static void vhost_vdpa_device_realize(DeviceState *dev, Error **errp) + free_config: + g_free(v->config); + vhost_cleanup: ++ memory_listener_unregister(&v->vdpa.listener); + vhost_dev_cleanup(&v->dev); + free_vqs: + g_free(vqs); +@@ -189,6 +192,7 @@ static void vhost_vdpa_device_unrealize(DeviceState *dev) + + g_free(s->config); + g_free(s->dev.vqs); ++ memory_listener_unregister(&s->vdpa.listener); + vhost_dev_cleanup(&s->dev); + qemu_close(s->vhostfd); + s->vhostfd = -1; +diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c +index 7688dc0eba..c7aaff7f20 100644 +--- a/hw/virtio/vhost-vdpa.c ++++ b/hw/virtio/vhost-vdpa.c +@@ -1100,7 +1100,6 @@ static void vhost_vdpa_svqs_stop(struct vhost_dev *dev) + + static int vhost_vdpa_dev_start(struct vhost_dev *dev, bool started) + { +- struct vhost_vdpa *v = dev->opaque; + bool ok; + trace_vhost_vdpa_dev_start(dev, started); + +@@ -1121,14 +1120,11 @@ static int vhost_vdpa_dev_start(struct vhost_dev *dev, bool started) + } + + if (started) { +- memory_listener_register(&v->listener, &address_space_memory); + return vhost_vdpa_add_status(dev, VIRTIO_CONFIG_S_DRIVER_OK); + } else { + vhost_vdpa_reset_device(dev); + vhost_vdpa_add_status(dev, VIRTIO_CONFIG_S_ACKNOWLEDGE | + VIRTIO_CONFIG_S_DRIVER); +- memory_listener_unregister(&v->listener); +- + return 0; + } + } +@@ -1320,7 +1316,6 @@ static unsigned int vhost_vdpa_get_used_memslots(void) + + static int vhost_vdpa_suspend_device(struct vhost_dev *dev) + { +- struct vhost_vdpa *v = dev->opaque; + int ret; + + vhost_vdpa_svqs_stop(dev); +@@ -1331,13 +1326,11 @@ static int vhost_vdpa_suspend_device(struct vhost_dev *dev) + } + + ret = vhost_vdpa_call(dev, VHOST_VDPA_SUSPEND, NULL); +- memory_listener_unregister(&v->listener); + return ret; + } + + static int vhost_vdpa_resume_device(struct vhost_dev *dev) + { +- struct vhost_vdpa *v = dev->opaque; + bool ok; + + vhost_vdpa_host_notifiers_init(dev); +@@ -1351,7 +1344,6 @@ static int vhost_vdpa_resume_device(struct vhost_dev *dev) + return 0; + } + +- memory_listener_register(&v->listener, &address_space_memory); + return vhost_vdpa_call(dev, VHOST_VDPA_RESUME, NULL); + } + +-- +2.27.0 + diff --git a/vhost-add-vhost_dev_suspend-resume_op.patch b/vhost-add-vhost_dev_suspend-resume_op.patch new file mode 100644 index 00000000..e0976317 --- /dev/null +++ b/vhost-add-vhost_dev_suspend-resume_op.patch @@ -0,0 +1,64 @@ +From 745bbf64b2a1e74366550bffbb68da1df2a9f378 Mon Sep 17 00:00:00 2001 +From: fangyi +Date: Mon, 4 Dec 2023 15:13:41 +0800 +Subject: [PATCH] vhost: add vhost_dev_suspend/resume_op + +Signed-off-by: jiangdongxu +Signed-off-by: fangyi +--- + include/hw/virtio/vhost-backend.h | 5 +++++ + linux-headers/linux/vhost.h | 17 +++++++++++++++++ + 2 files changed, 22 insertions(+) + +diff --git a/include/hw/virtio/vhost-backend.h b/include/hw/virtio/vhost-backend.h +index 86154dd0b2..2ca6250567 100644 +--- a/include/hw/virtio/vhost-backend.h ++++ b/include/hw/virtio/vhost-backend.h +@@ -135,6 +135,9 @@ typedef int (*vhost_set_config_call_op)(struct vhost_dev *dev, + typedef void (*vhost_set_used_memslots_op)(struct vhost_dev *dev); + typedef unsigned int (*vhost_get_used_memslots_op)(void); + ++typedef int (*vhost_dev_suspend_op)(struct vhost_dev *dev); ++typedef int (*vhost_dev_resume_op)(struct vhost_dev *dev); ++ + typedef struct VhostOps { + VhostBackendType backend_type; + vhost_backend_init vhost_backend_init; +@@ -186,6 +189,8 @@ typedef struct VhostOps { + vhost_set_config_call_op vhost_set_config_call; + vhost_set_used_memslots_op vhost_set_used_memslots; + vhost_get_used_memslots_op vhost_get_used_memslots; ++ vhost_dev_suspend_op vhost_dev_suspend; ++ vhost_dev_resume_op vhost_dev_resume; + } VhostOps; + + int vhost_backend_update_device_iotlb(struct vhost_dev *dev, +diff --git a/linux-headers/linux/vhost.h b/linux-headers/linux/vhost.h +index 65c6b49788..9b3f71b20f 100644 +--- a/linux-headers/linux/vhost.h ++++ b/linux-headers/linux/vhost.h +@@ -175,4 +175,21 @@ + #define VHOST_VDPA_SET_GROUP_ASID _IOW(VHOST_VIRTIO, 0x7C, \ + struct vhost_vring_state) + ++/* Suspend a device so it does not process virtqueue requests anymore ++ * ++ * After the return of ioctl the device must preserve all the necessary state ++ * (the virtqueue vring base plus the possible device specific states) that is ++ * required for restoring in the future. The device must not change its ++ * configuration after that point. ++ */ ++#define VHOST_VDPA_SUSPEND _IO(VHOST_VIRTIO, 0x7D) ++ ++/* Resume a device so it can resume processing virtqueue requests ++ * ++ * After the return of this ioctl the device will have restored all the ++ * necessary states and it is fully operational to continue processing the ++ * virtqueue descriptors. ++ */ ++#define VHOST_VDPA_RESUME _IO(VHOST_VIRTIO, 0x7E) ++ + #endif +-- +2.27.0 + diff --git a/vhost-fix-null-pointer-access.patch b/vhost-fix-null-pointer-access.patch new file mode 100644 index 00000000..432e8a78 --- /dev/null +++ b/vhost-fix-null-pointer-access.patch @@ -0,0 +1,74 @@ +From e2db610c0b0cb9130ba1ce2668a57318a416fdc4 Mon Sep 17 00:00:00 2001 +From: fangyi +Date: Mon, 4 Dec 2023 14:48:18 +0800 +Subject: [PATCH] vhost: fix null pointer access + +Check vhost_get/set_used_memslots function before calling it. + +Signed-off-by: libai +Signed-off-by: jiangdongxu +Signed-off-by: fangyi +--- + hw/virtio/vhost.c | 18 ++++++++++++++++-- + 1 file changed, 16 insertions(+), 2 deletions(-) + +diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c +index 59a12735f9..7930b37499 100644 +--- a/hw/virtio/vhost.c ++++ b/hw/virtio/vhost.c +@@ -58,6 +58,10 @@ bool vhost_has_free_slot(void) + struct vhost_dev *hdev; + + QLIST_FOREACH(hdev, &vhost_devices, entry) { ++ if (!hdev->vhost_ops->vhost_get_used_memslots || ++ !hdev->vhost_ops->vhost_backend_memslots_limit) { ++ continue; ++ } + if (hdev->vhost_ops->vhost_get_used_memslots() >= + hdev->vhost_ops->vhost_backend_memslots_limit(hdev)) { + return false; +@@ -748,7 +752,9 @@ static void vhost_region_add_section(struct vhost_dev *dev, + dev->tmp_sections[dev->n_tmp_sections - 1].fv = NULL; + memory_region_ref(section->mr); + } +- dev->vhost_ops->vhost_set_used_memslots(dev); ++ if (dev->vhost_ops->vhost_set_used_memslots) { ++ dev->vhost_ops->vhost_set_used_memslots(dev); ++ } + } + + /* Used for both add and nop callbacks */ +@@ -772,7 +778,9 @@ static void vhost_region_del(MemoryListener *listener, + if (!vhost_section(dev, section)) { + return; + } +- dev->vhost_ops->vhost_set_used_memslots(dev); ++ if (dev->vhost_ops->vhost_set_used_memslots) { ++ dev->vhost_ops->vhost_set_used_memslots(dev); ++ } + } + + static void vhost_iommu_unmap_notify(IOMMUNotifier *n, IOMMUTLBEntry *iotlb) +@@ -1367,6 +1375,11 @@ static void vhost_virtqueue_cleanup(struct vhost_virtqueue *vq) + + static bool vhost_dev_used_memslots_is_exceeded(struct vhost_dev *hdev) + { ++ if (!hdev->vhost_ops->vhost_get_used_memslots || ++ !hdev->vhost_ops->vhost_backend_memslots_limit) { ++ goto out; ++ } ++ + if (hdev->vhost_ops->vhost_get_used_memslots() > + hdev->vhost_ops->vhost_backend_memslots_limit(hdev)) { + error_report("vhost backend memory slots limit is less" +@@ -1375,6 +1388,7 @@ static bool vhost_dev_used_memslots_is_exceeded(struct vhost_dev *hdev) + return true; + } + ++out: + used_memslots_exceeded = false; + return false; + } +-- +2.27.0 + diff --git a/vhost-implement-migration-state-notifier-for-vdpa-de.patch b/vhost-implement-migration-state-notifier-for-vdpa-de.patch new file mode 100644 index 00000000..24696142 --- /dev/null +++ b/vhost-implement-migration-state-notifier-for-vdpa-de.patch @@ -0,0 +1,78 @@ +From ce5fa02db01263ef5188b3bb3a1367c806ddb7ce Mon Sep 17 00:00:00 2001 +From: fangyi +Date: Mon, 4 Dec 2023 15:55:53 +0800 +Subject: [PATCH] vhost: implement migration state notifier for vdpa device + +Signed-off-by: libai +Signed-off-by: jiangdongxu +Signed-off-by: fangyi +--- + hw/virtio/vdpa-dev-mig.c | 28 ++++++++++++++++++++++++++++ + include/hw/virtio/vdpa-dev.h | 1 + + 2 files changed, 29 insertions(+) + +diff --git a/hw/virtio/vdpa-dev-mig.c b/hw/virtio/vdpa-dev-mig.c +index c0bcbda7d4..a36517b147 100644 +--- a/hw/virtio/vdpa-dev-mig.c ++++ b/hw/virtio/vdpa-dev-mig.c +@@ -344,6 +344,31 @@ static SaveVMHandlers savevm_vdpa_handlers = { + .load_setup = vdpa_load_setup, + }; + ++static void vdpa_migration_state_notifier(Notifier *notifier, void *data) ++{ ++ MigrationState *s = data; ++ VhostVdpaDevice *vdev = container_of(notifier, ++ VhostVdpaDevice, ++ migration_state); ++ struct vhost_dev *hdev = &vdev->dev; ++ int ret; ++ ++ switch (s->state) { ++ case MIGRATION_STATUS_CANCELLING: ++ case MIGRATION_STATUS_CANCELLED: ++ case MIGRATION_STATUS_FAILED: ++ ret = vhost_vdpa_set_mig_state(hdev, VDPA_DEVICE_CANCEL); ++ if (ret) { ++ error_report("Failed to set state CANCEL\n"); ++ } ++ ++ break; ++ case MIGRATION_STATUS_COMPLETED: ++ default: ++ break; ++ } ++} ++ + void vdpa_migration_register(VhostVdpaDevice *vdev) + { + vdev->vmstate = qdev_add_vm_change_state_handler(DEVICE(vdev), +@@ -351,10 +376,13 @@ void vdpa_migration_register(VhostVdpaDevice *vdev) + DEVICE(vdev)); + register_savevm_live("vdpa", -1, 1, + &savevm_vdpa_handlers, DEVICE(vdev)); ++ vdev->migration_state.notify = vdpa_migration_state_notifier; ++ add_migration_state_change_notifier(&vdev->migration_state); + } + + void vdpa_migration_unregister(VhostVdpaDevice *vdev) + { ++ remove_migration_state_change_notifier(&vdev->migration_state); + unregister_savevm(VMSTATE_IF(&vdev->parent_obj.parent_obj), "vdpa", DEVICE(vdev)); + qemu_del_vm_change_state_handler(vdev->vmstate); + } +diff --git a/include/hw/virtio/vdpa-dev.h b/include/hw/virtio/vdpa-dev.h +index 43cbcef81b..20f50c76c6 100644 +--- a/include/hw/virtio/vdpa-dev.h ++++ b/include/hw/virtio/vdpa-dev.h +@@ -39,6 +39,7 @@ struct VhostVdpaDevice { + bool started; + int (*post_init)(VhostVdpaDevice *v, Error **errp); + VMChangeStateEntry *vmstate; ++ Notifier migration_state; + }; + + #endif +-- +2.27.0 + diff --git a/vhost-implement-post-resume-bh.patch b/vhost-implement-post-resume-bh.patch new file mode 100644 index 00000000..b16606d7 --- /dev/null +++ b/vhost-implement-post-resume-bh.patch @@ -0,0 +1,56 @@ +From 07fc3e07d6160508f7e6543e2fc49668607f79ad Mon Sep 17 00:00:00 2001 +From: fangyi +Date: Mon, 4 Dec 2023 15:57:35 +0800 +Subject: [PATCH] vhost: implement post resume bh + +Signed-off-by: jiangdongxu +Signed-off-by: fangyi +--- + hw/virtio/vdpa-dev-mig.c | 17 +++++++++++++++++ + 1 file changed, 17 insertions(+) + +diff --git a/hw/virtio/vdpa-dev-mig.c b/hw/virtio/vdpa-dev-mig.c +index a36517b147..ee3e27f2bb 100644 +--- a/hw/virtio/vdpa-dev-mig.c ++++ b/hw/virtio/vdpa-dev-mig.c +@@ -33,6 +33,7 @@ + #include "qemu/error-report.h" + #include "hw/virtio/vdpa-dev-mig.h" + #include "migration/qemu-file-types.h" ++#include "qemu/main-loop.h" + + /* + * Flags used as delimiter: +@@ -225,6 +226,18 @@ err_host_notifiers: + return ret; + } + ++static void vdpa_dev_migration_handle_incoming_bh(void *opaque) ++{ ++ struct vhost_dev *hdev = opaque; ++ int ret; ++ ++ /* Post start device, unsupport rollback if failed! */ ++ ret = vhost_vdpa_set_mig_state(hdev, VDPA_DEVICE_POST_START); ++ if (ret) { ++ error_report("Failed to set state: POST_START\n"); ++ } ++} ++ + static void vdpa_dev_vmstate_change(void *opaque, bool running, RunState state) + { + VhostVdpaDevice *vdpa = VHOST_VDPA_DEVICE(opaque); +@@ -254,6 +267,10 @@ static void vdpa_dev_vmstate_change(void *opaque, bool running, RunState state) + + if (mis->state == RUN_STATE_RESTORE_VM) { + vhost_vdpa_call(hdev, VHOST_VDPA_RESUME, NULL); ++ /* post resume */ ++ mis->bh = qemu_bh_new(vdpa_dev_migration_handle_incoming_bh, ++ hdev); ++ qemu_bh_schedule(mis->bh); + } + } + } +-- +2.27.0 + diff --git a/vhost-implement-savevm_hanlder-for-vdpa-device.patch b/vhost-implement-savevm_hanlder-for-vdpa-device.patch new file mode 100644 index 00000000..16cacc11 --- /dev/null +++ b/vhost-implement-savevm_hanlder-for-vdpa-device.patch @@ -0,0 +1,265 @@ +From 9cd596fd081bdb88b03b5e969631d8d08797c14d Mon Sep 17 00:00:00 2001 +From: fangyi +Date: Mon, 4 Dec 2023 15:53:28 +0800 +Subject: [PATCH] vhost: implement savevm_hanlder for vdpa device + +Signed-off-by: libai +Signed-off-by: jiangdongxu +Signed-off-by: fangyi +--- + hw/virtio/vdpa-dev-mig.c | 174 +++++++++++++++++++++++++++++++ + include/hw/virtio/vdpa-dev-mig.h | 13 +++ + linux-headers/linux/vhost.h | 8 ++ + 3 files changed, 195 insertions(+) + +diff --git a/hw/virtio/vdpa-dev-mig.c b/hw/virtio/vdpa-dev-mig.c +index 64c9e245d1..c0bcbda7d4 100644 +--- a/hw/virtio/vdpa-dev-mig.c ++++ b/hw/virtio/vdpa-dev-mig.c +@@ -32,6 +32,17 @@ + #include "sysemu/runstate.h" + #include "qemu/error-report.h" + #include "hw/virtio/vdpa-dev-mig.h" ++#include "migration/qemu-file-types.h" ++ ++/* ++ * Flags used as delimiter: ++ * 0xffffffff => MSB 32-bit all 1s ++ * 0xef10 => emulated (virtual) function IO ++ * 0x0000 => 16-bits reserved for flags ++ */ ++#define VDPA_MIG_FLAG_END_OF_STATE (0xffffffffef100001ULL) ++#define VDPA_MIG_FLAG_DEV_CONFIG_STATE (0xffffffffef100002ULL) ++#define VDPA_MIG_FLAG_DEV_SETUP_STATE (0xffffffffef100003ULL) + + static int vhost_vdpa_call(struct vhost_dev *dev, unsigned long int request, + void *arg) +@@ -47,6 +58,80 @@ static int vhost_vdpa_call(struct vhost_dev *dev, unsigned long int request, + return ioctl(fd, request, arg); + } + ++static int vhost_vdpa_set_mig_state(struct vhost_dev *dev, uint8_t state) ++{ ++ return vhost_vdpa_call(dev, VHOST_VDPA_SET_MIG_STATE, &state); ++} ++ ++static int vhost_vdpa_dev_buffer_size(struct vhost_dev *dev, uint32_t *size) ++{ ++ return vhost_vdpa_call(dev, VHOST_GET_DEV_BUFFER_SIZE, size); ++} ++ ++static int vhost_vdpa_dev_buffer_save(struct vhost_dev *dev, QEMUFile *f) ++{ ++ struct vhost_vdpa_config *config; ++ unsigned long config_size = offsetof(struct vhost_vdpa_config, buf); ++ uint32_t buffer_size = 0; ++ int ret; ++ ++ ret = vhost_vdpa_dev_buffer_size(dev, &buffer_size); ++ if (ret) { ++ error_report("get dev buffer size failed: %d\n", ret); ++ return ret; ++ } ++ ++ qemu_put_be32(f, buffer_size); ++ ++ config = g_malloc(buffer_size + config_size); ++ config->off = 0; ++ config->len = buffer_size; ++ ++ ret = vhost_vdpa_call(dev, VHOST_GET_DEV_BUFFER, config); ++ if (ret) { ++ error_report("get dev buffer failed: %d\n", ret); ++ goto free; ++ } ++ ++ qemu_put_buffer(f, config->buf, buffer_size); ++free: ++ g_free(config); ++ ++ return ret; ++} ++ ++static int vhost_vdpa_dev_buffer_load(struct vhost_dev *dev, QEMUFile *f) ++{ ++ struct vhost_vdpa_config *config; ++ unsigned long config_size = offsetof(struct vhost_vdpa_config, buf); ++ uint32_t buffer_size, recv_size; ++ int ret; ++ ++ buffer_size = qemu_get_be32(f); ++ ++ config = g_malloc(buffer_size + config_size); ++ config->off = 0; ++ config->len = buffer_size; ++ ++ recv_size = qemu_get_buffer(f, config->buf, buffer_size); ++ if (recv_size != buffer_size) { ++ error_report("read dev mig buffer failed, buffer_size: %u, " ++ "recv_size: %u\n", buffer_size, recv_size); ++ ret = -EINVAL; ++ goto free; ++ } ++ ++ ret = vhost_vdpa_call(dev, VHOST_SET_DEV_BUFFER, config); ++ if (ret) { ++ error_report("set dev buffer failed: %d\n", ret); ++ } ++ ++free: ++ g_free(config); ++ ++ return ret; ++} ++ + static int vhost_vdpa_device_suspend(VhostVdpaDevice *vdpa) + { + VirtIODevice *vdev = VIRTIO_DEVICE(vdpa); +@@ -173,14 +258,103 @@ static void vdpa_dev_vmstate_change(void *opaque, bool running, RunState state) + } + } + ++static int vdpa_save_setup(QEMUFile *f, void *opaque) ++{ ++ qemu_put_be64(f, VDPA_MIG_FLAG_DEV_SETUP_STATE); ++ qemu_put_be64(f, VDPA_MIG_FLAG_END_OF_STATE); ++ ++ return qemu_file_get_error(f); ++} ++ ++static int vdpa_save_complete_precopy(QEMUFile *f, void *opaque) ++{ ++ VhostVdpaDevice *vdev = VHOST_VDPA_DEVICE(opaque); ++ struct vhost_dev *hdev = &vdev->dev; ++ int ret; ++ ++ qemu_put_be64(f, VDPA_MIG_FLAG_DEV_CONFIG_STATE); ++ ret = vhost_vdpa_dev_buffer_save(hdev, f); ++ if (ret) { ++ error_report("Save vdpa device buffer failed: %d\n", ret); ++ return ret; ++ } ++ qemu_put_be64(f, VDPA_MIG_FLAG_END_OF_STATE); ++ ++ return qemu_file_get_error(f); ++} ++ ++static int vdpa_load_state(QEMUFile *f, void *opaque, int version_id) ++{ ++ VhostVdpaDevice *vdev = VHOST_VDPA_DEVICE(opaque); ++ struct vhost_dev *hdev = &vdev->dev; ++ ++ int ret; ++ uint64_t data; ++ ++ data = qemu_get_be64(f); ++ while (data != VDPA_MIG_FLAG_END_OF_STATE) { ++ if (data == VDPA_MIG_FLAG_DEV_SETUP_STATE) { ++ data = qemu_get_be64(f); ++ if (data == VDPA_MIG_FLAG_END_OF_STATE) { ++ return 0; ++ } else { ++ error_report("SETUP STATE: EOS not found 0x%lx\n", data); ++ return -EINVAL; ++ } ++ } else if (data == VDPA_MIG_FLAG_DEV_CONFIG_STATE) { ++ ret = vhost_vdpa_dev_buffer_load(hdev, f); ++ if (ret) { ++ error_report("fail to restore device buffer.\n"); ++ return ret; ++ } ++ } ++ ++ ret = qemu_file_get_error(f); ++ if (ret) { ++ error_report("qemu file error: %d\n", ret); ++ return ret; ++ } ++ data = qemu_get_be64(f); ++ } ++ ++ return 0; ++} ++ ++static int vdpa_load_setup(QEMUFile *f, void *opaque) ++{ ++ VhostVdpaDevice *v = VHOST_VDPA_DEVICE(opaque); ++ struct vhost_dev *hdev = &v->dev; ++ int ret = 0; ++ ++ ret = vhost_vdpa_set_mig_state(hdev, VDPA_DEVICE_PRE_START); ++ if (ret) { ++ error_report("pre start device failed: %d\n", ret); ++ goto out; ++ } ++ ++ return qemu_file_get_error(f); ++out: ++ return ret; ++} ++ ++static SaveVMHandlers savevm_vdpa_handlers = { ++ .save_setup = vdpa_save_setup, ++ .save_live_complete_precopy = vdpa_save_complete_precopy, ++ .load_state = vdpa_load_state, ++ .load_setup = vdpa_load_setup, ++}; ++ + void vdpa_migration_register(VhostVdpaDevice *vdev) + { + vdev->vmstate = qdev_add_vm_change_state_handler(DEVICE(vdev), + vdpa_dev_vmstate_change, + DEVICE(vdev)); ++ register_savevm_live("vdpa", -1, 1, ++ &savevm_vdpa_handlers, DEVICE(vdev)); + } + + void vdpa_migration_unregister(VhostVdpaDevice *vdev) + { ++ unregister_savevm(VMSTATE_IF(&vdev->parent_obj.parent_obj), "vdpa", DEVICE(vdev)); + qemu_del_vm_change_state_handler(vdev->vmstate); + } +diff --git a/include/hw/virtio/vdpa-dev-mig.h b/include/hw/virtio/vdpa-dev-mig.h +index 89665ca747..adc1d657f7 100644 +--- a/include/hw/virtio/vdpa-dev-mig.h ++++ b/include/hw/virtio/vdpa-dev-mig.h +@@ -9,6 +9,19 @@ + + #include "hw/virtio/vdpa-dev.h" + ++enum { ++ VDPA_DEVICE_START, ++ VDPA_DEVICE_STOP, ++ VDPA_DEVICE_PRE_START, ++ VDPA_DEVICE_PRE_STOP, ++ VDPA_DEVICE_CANCEL, ++ VDPA_DEVICE_POST_START, ++ VDPA_DEVICE_START_ASYNC, ++ VDPA_DEVICE_STOP_ASYNC, ++ VDPA_DEVICE_PRE_START_ASYNC, ++ VDPA_DEVICE_QUERY_OP_STATE, ++}; ++ + void vdpa_migration_register(VhostVdpaDevice *vdev); + + void vdpa_migration_unregister(VhostVdpaDevice *vdev); +diff --git a/linux-headers/linux/vhost.h b/linux-headers/linux/vhost.h +index 9b3f71b20f..457923974c 100644 +--- a/linux-headers/linux/vhost.h ++++ b/linux-headers/linux/vhost.h +@@ -192,4 +192,12 @@ + */ + #define VHOST_VDPA_RESUME _IO(VHOST_VIRTIO, 0x7E) + ++/* set and get device buffer */ ++#define VHOST_GET_DEV_BUFFER _IOR(VHOST_VIRTIO, 0xb0, struct vhost_vdpa_config) ++#define VHOST_SET_DEV_BUFFER _IOW(VHOST_VIRTIO, 0xb1, struct vhost_vdpa_config) ++#define VHOST_GET_DEV_BUFFER_SIZE _IOR(VHOST_VIRTIO, 0xb3, __u32) ++ ++/* set device migtration state */ ++#define VHOST_VDPA_SET_MIG_STATE _IOW(VHOST_VIRTIO, 0xb2, __u8) ++ + #endif +-- +2.27.0 + diff --git a/vhost-implement-vhost-vdpa-suspend-resume.patch b/vhost-implement-vhost-vdpa-suspend-resume.patch new file mode 100644 index 00000000..1a499e6c --- /dev/null +++ b/vhost-implement-vhost-vdpa-suspend-resume.patch @@ -0,0 +1,85 @@ +From 98c74a827b742807f979fc36bca99ba0db38d295 Mon Sep 17 00:00:00 2001 +From: fangyi +Date: Mon, 4 Dec 2023 15:22:20 +0800 +Subject: [PATCH] vhost: implement vhost-vdpa suspend/resume + +vhost-vdpa implements the vhost_dev_suspend interface, +which will be called during the shutdown phase of the +live migration source virtual machine to suspend the +device but not reset the device information. + +vhost-vdpa implements the vhost_dev_resume interface. +If the live migration fails, it will be called during +the startup phase of the source virtual machine. +Enable the device but set the status, etc. + +Signed-off-by: libai +Signed-off-by: jiangdongxu +Signed-off-by: fangyi +--- + hw/virtio/vhost-vdpa.c | 44 ++++++++++++++++++++++++++++++++++++++++-- + 1 file changed, 42 insertions(+), 2 deletions(-) + +diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c +index 7663d78b43..7688dc0eba 100644 +--- a/hw/virtio/vhost-vdpa.c ++++ b/hw/virtio/vhost-vdpa.c +@@ -1318,6 +1318,43 @@ static unsigned int vhost_vdpa_get_used_memslots(void) + return vhost_vdpa_used_memslots; + } + ++static int vhost_vdpa_suspend_device(struct vhost_dev *dev) ++{ ++ struct vhost_vdpa *v = dev->opaque; ++ int ret; ++ ++ vhost_vdpa_svqs_stop(dev); ++ vhost_vdpa_host_notifiers_uninit(dev, dev->nvqs); ++ ++ if (dev->vq_index + dev->nvqs != dev->vq_index_end) { ++ return 0; ++ } ++ ++ ret = vhost_vdpa_call(dev, VHOST_VDPA_SUSPEND, NULL); ++ memory_listener_unregister(&v->listener); ++ return ret; ++} ++ ++static int vhost_vdpa_resume_device(struct vhost_dev *dev) ++{ ++ struct vhost_vdpa *v = dev->opaque; ++ bool ok; ++ ++ vhost_vdpa_host_notifiers_init(dev); ++ ok = vhost_vdpa_svqs_start(dev); ++ if (unlikely(!ok)) { ++ return -1; ++ } ++ vhost_vdpa_set_vring_ready(dev); ++ ++ if (dev->vq_index + dev->nvqs != dev->vq_index_end) { ++ return 0; ++ } ++ ++ memory_listener_register(&v->listener, &address_space_memory); ++ return vhost_vdpa_call(dev, VHOST_VDPA_RESUME, NULL); ++} ++ + static int vhost_vdpa_log_sync(struct vhost_dev *dev) + { + struct vhost_vdpa *v = dev->opaque; +@@ -1364,6 +1401,9 @@ const VhostOps vdpa_ops = { + .vhost_force_iommu = vhost_vdpa_force_iommu, + .vhost_log_sync = vhost_vdpa_log_sync, + .vhost_set_config_call = vhost_vdpa_set_config_call, +- .vhost_set_used_memslots = vhost_vdpa_set_used_memslots, +- .vhost_get_used_memslots = vhost_vdpa_get_used_memslots, ++ .vhost_set_used_memslots = vhost_vdpa_set_used_memslots, ++ .vhost_get_used_memslots = vhost_vdpa_get_used_memslots, ++ .vhost_dev_suspend = vhost_vdpa_suspend_device, ++ .vhost_dev_resume = vhost_vdpa_resume_device, ++ + }; +-- +2.27.0 + diff --git a/vhost-implement-vhost_vdpa_device_suspend-resume.patch b/vhost-implement-vhost_vdpa_device_suspend-resume.patch new file mode 100644 index 00000000..9345bd28 --- /dev/null +++ b/vhost-implement-vhost_vdpa_device_suspend-resume.patch @@ -0,0 +1,453 @@ +From a21603f7ecfaa2fb53b2037f46ee3fb868d8c9cb Mon Sep 17 00:00:00 2001 +From: fangyi +Date: Mon, 4 Dec 2023 15:27:34 +0800 +Subject: [PATCH] vhost: implement vhost_vdpa_device_suspend/resume + +Signed-off-by: jiangdongxu +Signed-off-by: fangyi +--- + hw/virtio/meson.build | 2 +- + hw/virtio/vdpa-dev-mig.c | 186 +++++++++++++++++++++++++++++++ + hw/virtio/vhost.c | 138 +++++++++++++++++++++++ + include/hw/virtio/vdpa-dev-mig.h | 16 +++ + include/hw/virtio/vdpa-dev.h | 1 + + include/hw/virtio/vhost.h | 4 + + migration/migration.c | 3 +- + migration/migration.h | 2 + + 8 files changed, 349 insertions(+), 3 deletions(-) + create mode 100644 hw/virtio/vdpa-dev-mig.c + create mode 100644 include/hw/virtio/vdpa-dev-mig.h + +diff --git a/hw/virtio/meson.build b/hw/virtio/meson.build +index c2da69616f..94a030f329 100644 +--- a/hw/virtio/meson.build ++++ b/hw/virtio/meson.build +@@ -29,7 +29,7 @@ virtio_ss.add(when: 'CONFIG_VHOST_USER_I2C', if_true: files('vhost-user-i2c.c')) + virtio_ss.add(when: ['CONFIG_VIRTIO_PCI', 'CONFIG_VHOST_USER_I2C'], if_true: files('vhost-user-i2c-pci.c')) + virtio_ss.add(when: 'CONFIG_VHOST_USER_RNG', if_true: files('vhost-user-rng.c')) + virtio_ss.add(when: ['CONFIG_VHOST_USER_RNG', 'CONFIG_VIRTIO_PCI'], if_true: files('vhost-user-rng-pci.c')) +-virtio_ss.add(when: 'CONFIG_VHOST_VDPA_DEV', if_true: files('vdpa-dev.c')) ++virtio_ss.add(when: 'CONFIG_VHOST_VDPA_DEV', if_true: files('vdpa-dev.c', 'vdpa-dev-mig.c')) + + virtio_pci_ss = ss.source_set() + virtio_pci_ss.add(when: 'CONFIG_VHOST_VSOCK', if_true: files('vhost-vsock-pci.c')) +diff --git a/hw/virtio/vdpa-dev-mig.c b/hw/virtio/vdpa-dev-mig.c +new file mode 100644 +index 0000000000..64c9e245d1 +--- /dev/null ++++ b/hw/virtio/vdpa-dev-mig.c +@@ -0,0 +1,186 @@ ++/* ++ * Copyright (c) Huawei Technologies Co., Ltd. 2023. All rights reserved. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, see . ++ */ ++ ++#include ++#include ++#include "qemu/osdep.h" ++#include "migration/misc.h" ++#include "hw/qdev-core.h" ++#include "hw/qdev-properties.h" ++#include "hw/virtio/vhost.h" ++#include "hw/virtio/vdpa-dev.h" ++#include "hw/virtio/virtio.h" ++#include "hw/virtio/virtio-bus.h" ++#include "hw/virtio/virtio-access.h" ++#include "migration/register.h" ++#include "migration/migration.h" ++#include "qemu-common.h" ++#include "sysemu/runstate.h" ++#include "qemu/error-report.h" ++#include "hw/virtio/vdpa-dev-mig.h" ++ ++static int vhost_vdpa_call(struct vhost_dev *dev, unsigned long int request, ++ void *arg) ++{ ++ struct vhost_vdpa *v = dev->opaque; ++ int fd = v->device_fd; ++ ++ if (dev->vhost_ops->backend_type != VHOST_BACKEND_TYPE_VDPA) { ++ error_report("backend type isn't VDPA. Operation not permitted!\n"); ++ return -EPERM; ++ } ++ ++ return ioctl(fd, request, arg); ++} ++ ++static int vhost_vdpa_device_suspend(VhostVdpaDevice *vdpa) ++{ ++ VirtIODevice *vdev = VIRTIO_DEVICE(vdpa); ++ BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev))); ++ VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus); ++ int ret; ++ ++ if (!vdpa->started) { ++ return -EFAULT; ++ } ++ ++ if (!k->set_guest_notifiers) { ++ return -EFAULT; ++ } ++ ++ vdpa->started = false; ++ ++ ret = vhost_dev_suspend(&vdpa->dev, vdev, false); ++ if (ret) { ++ goto suspend_fail; ++ } ++ ++ ret = k->set_guest_notifiers(qbus->parent, vdpa->dev.nvqs, false); ++ if (ret < 0) { ++ error_report("vhost guest notifier cleanup failed: %d\n", ret); ++ goto set_guest_notifiers_fail; ++ } ++ ++ vhost_dev_disable_notifiers(&vdpa->dev, vdev); ++ return ret; ++ ++set_guest_notifiers_fail: ++ ret = k->set_guest_notifiers(qbus->parent, vdpa->dev.nvqs, true); ++ if (ret) { ++ error_report("vhost guest notifier restore failed: %d\n", ret); ++ } ++ ++suspend_fail: ++ vdpa->started = true; ++ return ret; ++} ++ ++static int vhost_vdpa_device_resume(VhostVdpaDevice *vdpa) ++{ ++ VirtIODevice *vdev = VIRTIO_DEVICE(vdpa); ++ BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev))); ++ VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus); ++ int i, ret; ++ ++ if (!k->set_guest_notifiers) { ++ error_report("binding does not support guest notifiers\n"); ++ return -ENOSYS; ++ } ++ ++ ret = vhost_dev_enable_notifiers(&vdpa->dev, vdev); ++ if (ret < 0) { ++ error_report("Error enabling host notifiers: %d\n", ret); ++ return ret; ++ } ++ ++ ret = k->set_guest_notifiers(qbus->parent, vdpa->dev.nvqs, true); ++ if (ret < 0) { ++ error_report("Error binding guest notifier: %d\n", ret); ++ goto err_host_notifiers; ++ } ++ ++ vdpa->dev.acked_features = vdev->guest_features; ++ ++ ret = vhost_dev_resume(&vdpa->dev, vdev, false); ++ if (ret < 0) { ++ error_report("Error starting vhost: %d\n", ret); ++ goto err_guest_notifiers; ++ } ++ vdpa->started = true; ++ ++ /* ++ * guest_notifier_mask/pending not used yet, so just unmask ++ * everything here. virtio-pci will do the right thing by ++ * enabling/disabling irqfd. ++ */ ++ for (i = 0; i < vdpa->dev.nvqs; i++) { ++ vhost_virtqueue_mask(&vdpa->dev, vdev, i, false); ++ } ++ ++ return ret; ++ ++err_guest_notifiers: ++ k->set_guest_notifiers(qbus->parent, vdpa->dev.nvqs, false); ++err_host_notifiers: ++ vhost_dev_disable_notifiers(&vdpa->dev, vdev); ++ return ret; ++} ++ ++static void vdpa_dev_vmstate_change(void *opaque, bool running, RunState state) ++{ ++ VhostVdpaDevice *vdpa = VHOST_VDPA_DEVICE(opaque); ++ struct vhost_dev *hdev = &vdpa->dev; ++ int ret; ++ MigrationState *ms = migrate_get_current(); ++ MigrationIncomingState *mis = migration_incoming_get_current(); ++ ++ if (!running) { ++ if (ms->state == RUN_STATE_PAUSED) { ++ ret = vhost_vdpa_device_suspend(vdpa); ++ if (ret) { ++ error_report("suspend vdpa device failed: %d\n", ret); ++ if (ms->migration_thread_running) { ++ migrate_fd_cancel(ms); ++ } ++ } ++ } ++ } else { ++ if (ms->state == RUN_STATE_RESTORE_VM) { ++ ret = vhost_vdpa_device_resume(vdpa); ++ if (ret) { ++ error_report("migration dest resume device failed, abort!\n"); ++ exit(EXIT_FAILURE); ++ } ++ } ++ ++ if (mis->state == RUN_STATE_RESTORE_VM) { ++ vhost_vdpa_call(hdev, VHOST_VDPA_RESUME, NULL); ++ } ++ } ++} ++ ++void vdpa_migration_register(VhostVdpaDevice *vdev) ++{ ++ vdev->vmstate = qdev_add_vm_change_state_handler(DEVICE(vdev), ++ vdpa_dev_vmstate_change, ++ DEVICE(vdev)); ++} ++ ++void vdpa_migration_unregister(VhostVdpaDevice *vdev) ++{ ++ qemu_del_vm_change_state_handler(vdev->vmstate); ++} +diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c +index d2b9278474..ed1506d3e0 100644 +--- a/hw/virtio/vhost.c ++++ b/hw/virtio/vhost.c +@@ -2201,3 +2201,141 @@ bool used_memslots_is_exceeded(void) + { + return used_memslots_exceeded; + } ++ ++int vhost_dev_resume(struct vhost_dev *hdev, VirtIODevice *vdev, bool vrings) ++{ ++ int i, r; ++ EventNotifier *e = &hdev->vqs[VHOST_QUEUE_NUM_CONFIG_INR].masked_config_notifier; ++ ++ /* should only be called after backend is connected */ ++ if (!hdev->vhost_ops) { ++ error_report("Missing vhost_ops! Operation not permitted!\n"); ++ return -EPERM; ++ } ++ ++ vdev->vhost_started = true; ++ hdev->started = true; ++ hdev->vdev = vdev; ++ ++ if (vhost_dev_has_iommu(hdev)) { ++ memory_listener_register(&hdev->iommu_listener, vdev->dma_as); ++ } ++ ++ r = hdev->vhost_ops->vhost_set_mem_table(hdev, hdev->mem); ++ if (r < 0) { ++ VHOST_OPS_DEBUG(r, "vhost_set_mem_table failed"); ++ goto fail_mem; ++ } ++ for (i = 0; i < hdev->nvqs; ++i) { ++ r = vhost_virtqueue_start(hdev, ++ vdev, ++ hdev->vqs + i, ++ hdev->vq_index + i); ++ if (r < 0) { ++ goto fail_vq; ++ } ++ } ++ ++ r = event_notifier_init(e, 0); ++ if (r < 0) { ++ return r; ++ } ++ event_notifier_test_and_clear(e); ++ if (!vdev->use_guest_notifier_mask) { ++ vhost_config_mask(hdev, vdev, true); ++ } ++ if (vrings) { ++ r = vhost_dev_set_vring_enable(hdev, true); ++ if (r) { ++ goto fail_vq; ++ } ++ } ++ if (hdev->vhost_ops->vhost_dev_resume) { ++ r = hdev->vhost_ops->vhost_dev_resume(hdev); ++ if (r) { ++ goto fail_start; ++ } ++ } ++ if (vhost_dev_has_iommu(hdev)) { ++ hdev->vhost_ops->vhost_set_iotlb_callback(hdev, true); ++ ++ /* ++ * Update used ring information for IOTLB to work correctly, ++ * vhost-kernel code requires for this. ++ */ ++ for (i = 0; i < hdev->nvqs; ++i) { ++ struct vhost_virtqueue *vq = hdev->vqs + i; ++ vhost_device_iotlb_miss(hdev, vq->used_phys, true); ++ } ++ } ++ vhost_start_config_intr(hdev); ++ return 0; ++fail_start: ++ if (vrings) { ++ vhost_dev_set_vring_enable(hdev, false); ++ } ++fail_vq: ++ while (--i >= 0) { ++ vhost_virtqueue_stop(hdev, ++ vdev, ++ hdev->vqs + i, ++ hdev->vq_index + i); ++ } ++ ++fail_mem: ++ vdev->vhost_started = false; ++ hdev->started = false; ++ return r; ++} ++ ++int vhost_dev_suspend(struct vhost_dev *hdev, VirtIODevice *vdev, bool vrings) ++{ ++ int i; ++ int ret = 0; ++ EventNotifier *e = &hdev->vqs[VHOST_QUEUE_NUM_CONFIG_INR].masked_config_notifier; ++ ++ /* should only be called after backend is connected */ ++ if (!hdev->vhost_ops) { ++ error_report("Missing vhost_ops! Operation not permitted!\n"); ++ return -EPERM; ++ } ++ ++ event_notifier_test_and_clear(e); ++ event_notifier_test_and_clear(&vdev->config_notifier); ++ ++ if (hdev->vhost_ops->vhost_dev_suspend) { ++ ret = hdev->vhost_ops->vhost_dev_suspend(hdev); ++ if (ret) { ++ goto fail_suspend; ++ } ++ } ++ if (vrings) { ++ ret = vhost_dev_set_vring_enable(hdev, false); ++ if (ret) { ++ goto fail_suspend; ++ } ++ } ++ for (i = 0; i < hdev->nvqs; ++i) { ++ vhost_virtqueue_stop(hdev, ++ vdev, ++ hdev->vqs + i, ++ hdev->vq_index + i); ++ } ++ ++ if (vhost_dev_has_iommu(hdev)) { ++ hdev->vhost_ops->vhost_set_iotlb_callback(hdev, false); ++ memory_listener_unregister(&hdev->iommu_listener); ++ } ++ vhost_stop_config_intr(hdev); ++ vhost_log_put(hdev, true); ++ hdev->started = false; ++ vdev->vhost_started = false; ++ hdev->vdev = NULL; ++ ++ return ret; ++ ++fail_suspend: ++ event_notifier_test_and_clear(e); ++ ++ return ret; ++} +diff --git a/include/hw/virtio/vdpa-dev-mig.h b/include/hw/virtio/vdpa-dev-mig.h +new file mode 100644 +index 0000000000..89665ca747 +--- /dev/null ++++ b/include/hw/virtio/vdpa-dev-mig.h +@@ -0,0 +1,16 @@ ++/* ++ * Vhost Vdpa Device Migration Header ++ * ++ * Copyright (c) Huawei Technologies Co., Ltd. 2023. All Rights Reserved. ++ */ ++ ++#ifndef _VHOST_VDPA_MIGRATION_H ++#define _VHOST_VDPA_MIGRATION_H ++ ++#include "hw/virtio/vdpa-dev.h" ++ ++void vdpa_migration_register(VhostVdpaDevice *vdev); ++ ++void vdpa_migration_unregister(VhostVdpaDevice *vdev); ++ ++#endif /* _VHOST_VDPA_MIGRATION_H */ +diff --git a/include/hw/virtio/vdpa-dev.h b/include/hw/virtio/vdpa-dev.h +index 4dbf98195c..43cbcef81b 100644 +--- a/include/hw/virtio/vdpa-dev.h ++++ b/include/hw/virtio/vdpa-dev.h +@@ -38,6 +38,7 @@ struct VhostVdpaDevice { + uint16_t queue_size; + bool started; + int (*post_init)(VhostVdpaDevice *v, Error **errp); ++ VMChangeStateEntry *vmstate; + }; + + #endif +diff --git a/include/hw/virtio/vhost.h b/include/hw/virtio/vhost.h +index 0491fe1ed7..9441b4c50e 100644 +--- a/include/hw/virtio/vhost.h ++++ b/include/hw/virtio/vhost.h +@@ -277,4 +277,8 @@ int vhost_dev_set_inflight(struct vhost_dev *dev, + int vhost_dev_get_inflight(struct vhost_dev *dev, uint16_t queue_size, + struct vhost_inflight *inflight); + bool used_memslots_is_exceeded(void); ++ ++int vhost_dev_resume(struct vhost_dev *hdev, VirtIODevice *vdev, bool vrings); ++int vhost_dev_suspend(struct vhost_dev *hdev, VirtIODevice *vdev, bool vrings); ++ + #endif +diff --git a/migration/migration.c b/migration/migration.c +index 2ec116f901..40e743b4e9 100644 +--- a/migration/migration.c ++++ b/migration/migration.c +@@ -178,7 +178,6 @@ static bool migration_object_check(MigrationState *ms, Error **errp); + static int migration_maybe_pause(MigrationState *s, + int *current_active_state, + int new_state); +-static void migrate_fd_cancel(MigrationState *s); + + static gint page_request_addr_cmp(gconstpointer ap, gconstpointer bp) + { +@@ -1914,7 +1913,7 @@ void migrate_fd_error(MigrationState *s, const Error *error) + migrate_set_error(s, error); + } + +-static void migrate_fd_cancel(MigrationState *s) ++void migrate_fd_cancel(MigrationState *s) + { + int old_state ; + QEMUFile *f = migrate_get_current()->to_dst_file; +diff --git a/migration/migration.h b/migration/migration.h +index 4ed4f555da..a87fd54d10 100644 +--- a/migration/migration.h ++++ b/migration/migration.h +@@ -393,4 +393,6 @@ void migration_cancel(const Error *error); + + void populate_vfio_info(MigrationInfo *info); + ++void migrate_fd_cancel(MigrationState *s); ++ + #endif +-- +2.27.0 + diff --git a/vhost-introduce-bytemap-for-vhost-backend-logging.patch b/vhost-introduce-bytemap-for-vhost-backend-logging.patch new file mode 100644 index 00000000..afa3d4d1 --- /dev/null +++ b/vhost-introduce-bytemap-for-vhost-backend-logging.patch @@ -0,0 +1,271 @@ +From e2f1953ad26a61e59f1d45892c6937d7454e65b5 Mon Sep 17 00:00:00 2001 +From: fangyi +Date: Mon, 4 Dec 2023 15:09:26 +0800 +Subject: [PATCH] vhost: introduce bytemap for vhost backend logging + +As vhost backend may use bytemap for logging, when get log_size +of vhost device, check whether vhost device support VHOST_BACKEND_F_BYTEMAPLOG. +If vhost device support, use bytemap for logging. + +By the way, add log_resize func pointer check and vhost_log_sync return +value check. + +Signed-off-by: jiangdongxu +Signed-off-by: fangyi +--- + hw/virtio/vhost.c | 144 ++++++++++++++++++++++++++++++++++++-- + include/hw/virtio/vhost.h | 1 + + 2 files changed, 139 insertions(+), 6 deletions(-) + +diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c +index 7930b37499..d2b9278474 100644 +--- a/hw/virtio/vhost.c ++++ b/hw/virtio/vhost.c +@@ -19,9 +19,11 @@ + #include "qemu/atomic.h" + #include "qemu/range.h" + #include "qemu/error-report.h" ++#include "cpu.h" + #include "qemu/memfd.h" + #include "qemu/log.h" + #include "standard-headers/linux/vhost_types.h" ++#include "exec/ram_addr.h" + #include "hw/virtio/virtio-bus.h" + #include "hw/virtio/virtio-access.h" + #include "migration/blocker.h" +@@ -30,6 +32,7 @@ + #include "sysemu/dma.h" + #include "sysemu/tcg.h" + #include "trace.h" ++#include "qapi/qapi-commands-migration.h" + + /* enabled until disconnected backend stabilizes */ + #define _VHOST_DEBUG 1 +@@ -45,6 +48,11 @@ + do { } while (0) + #endif + ++static inline bool vhost_bytemap_log_support(struct vhost_dev *dev) ++{ ++ return (dev->backend_cap & BIT_ULL(VHOST_BACKEND_F_BYTEMAPLOG)); ++} ++ + static struct vhost_log *vhost_log; + static struct vhost_log *vhost_log_shm; + +@@ -213,12 +221,93 @@ static int vhost_sync_dirty_bitmap(struct vhost_dev *dev, + return 0; + } + ++#define BYTES_PER_LONG (sizeof(unsigned long)) ++#define BYTE_WORD(nr) ((nr) / BYTES_PER_LONG) ++#define BYTES_TO_LONGS(nr) DIV_ROUND_UP(nr, BYTES_PER_LONG) ++ ++static inline int64_t _set_dirty_bytemap_atomic(unsigned long *bytemap, unsigned long cur_pfn) ++{ ++ char *byte_of_long = (char *)bytemap; ++ int i; ++ int64_t dirty_num = 0; ++ ++ for (i = 0; i < BYTES_PER_LONG; i++) { ++ if (byte_of_long[i]) { ++ cpu_physical_memory_set_dirty_range((cur_pfn + i) << TARGET_PAGE_BITS, ++ TARGET_PAGE_SIZE, ++ 1 << DIRTY_MEMORY_MIGRATION); ++ /* Per byte ops, no need to atomic_xchg */ ++ byte_of_long[i] = 0; ++ dirty_num++; ++ } ++ } ++ ++ return dirty_num; ++} ++ ++static inline int64_t cpu_physical_memory_set_dirty_bytemap(unsigned long *bytemap, ++ ram_addr_t start, ++ ram_addr_t pages) ++{ ++ unsigned long i; ++ unsigned long len = BYTES_TO_LONGS(pages); ++ unsigned long pfn = (start >> TARGET_PAGE_BITS) / ++ BYTES_PER_LONG * BYTES_PER_LONG; ++ int64_t dirty_mig_bits = 0; ++ ++ for (i = 0; i < len; i++) { ++ if (bytemap[i]) { ++ dirty_mig_bits += _set_dirty_bytemap_atomic(&bytemap[i], ++ pfn + BYTES_PER_LONG * i); ++ } ++ } ++ ++ return dirty_mig_bits; ++} ++ ++static int vhost_sync_dirty_bytemap(struct vhost_dev *dev, ++ MemoryRegionSection *section) ++{ ++ struct vhost_log *log = dev->log; ++ ++ ram_addr_t start = section->offset_within_region + ++ memory_region_get_ram_addr(section->mr); ++ ram_addr_t pages = int128_get64(section->size) >> TARGET_PAGE_BITS; ++ ++ hwaddr idx = BYTE_WORD( ++ section->offset_within_address_space >> TARGET_PAGE_BITS); ++ ++ return cpu_physical_memory_set_dirty_bytemap((unsigned long *)log->log + idx, ++ start, pages); ++} ++ + static void vhost_log_sync(MemoryListener *listener, + MemoryRegionSection *section) + { + struct vhost_dev *dev = container_of(listener, struct vhost_dev, + memory_listener); +- vhost_sync_dirty_bitmap(dev, section, 0x0, ~0x0ULL); ++ MigrationState *ms = migrate_get_current(); ++ ++ if (!dev->log_enabled || !dev->started) { ++ return; ++ } ++ ++ if (dev->vhost_ops->vhost_log_sync) { ++ int r = dev->vhost_ops->vhost_log_sync(dev); ++ if (r < 0) { ++ error_report("Failed to sync dirty log: 0x%x\n", r); ++ if (migration_is_running(ms->state)) { ++ qmp_migrate_cancel(NULL); ++ } ++ return; ++ } ++ } ++ ++ if (vhost_bytemap_log_support(dev)) { ++ vhost_sync_dirty_bytemap(dev, section); ++ } else { ++ vhost_sync_dirty_bitmap(dev, section, 0x0, ~0x0ULL); ++ } + } + + static void vhost_log_sync_range(struct vhost_dev *dev, +@@ -228,7 +317,11 @@ static void vhost_log_sync_range(struct vhost_dev *dev, + /* FIXME: this is N^2 in number of sections */ + for (i = 0; i < dev->n_mem_sections; ++i) { + MemoryRegionSection *section = &dev->mem_sections[i]; +- vhost_sync_dirty_bitmap(dev, section, first, last); ++ if (vhost_bytemap_log_support(dev)) { ++ vhost_sync_dirty_bytemap(dev, section); ++ } else { ++ vhost_sync_dirty_bitmap(dev, section, first, last); ++ } + } + } + +@@ -236,11 +329,19 @@ static uint64_t vhost_get_log_size(struct vhost_dev *dev) + { + uint64_t log_size = 0; + int i; ++ uint64_t vhost_log_chunk_size; ++ ++ if (vhost_bytemap_log_support(dev)) { ++ vhost_log_chunk_size = VHOST_LOG_CHUNK_BYTES; ++ } else { ++ vhost_log_chunk_size = VHOST_LOG_CHUNK; ++ } ++ + for (i = 0; i < dev->mem->nregions; ++i) { + struct vhost_memory_region *reg = dev->mem->regions + i; + uint64_t last = range_get_last(reg->guest_phys_addr, + reg->memory_size); +- log_size = MAX(log_size, last / VHOST_LOG_CHUNK + 1); ++ log_size = MAX(log_size, last / vhost_log_chunk_size + 1); + } + return log_size; + } +@@ -358,12 +459,21 @@ static bool vhost_dev_log_is_shared(struct vhost_dev *dev) + dev->vhost_ops->vhost_requires_shm_log(dev); + } + +-static inline void vhost_dev_log_resize(struct vhost_dev *dev, uint64_t size) ++static inline int vhost_dev_log_resize(struct vhost_dev *dev, uint64_t size) + { + struct vhost_log *log = vhost_log_get(size, vhost_dev_log_is_shared(dev)); +- uint64_t log_base = (uintptr_t)log->log; ++ uint64_t log_base; ++ int log_fd; + int r; + ++ if (!log) { ++ r = -ENOMEM; ++ goto out; ++ } ++ ++ log_base = (uint64_t)log->log; ++ log_fd = log_fd; ++ + /* inform backend of log switching, this must be done before + releasing the current log, to ensure no logging is lost */ + r = dev->vhost_ops->vhost_set_log_base(dev, log_base, log); +@@ -371,9 +481,19 @@ static inline void vhost_dev_log_resize(struct vhost_dev *dev, uint64_t size) + VHOST_OPS_DEBUG(r, "vhost_set_log_base failed"); + } + ++ if (dev->vhost_ops->vhost_set_log_size) { ++ r = dev->vhost_ops->vhost_set_log_size(dev, size, dev->log); ++ if (r < 0) { ++ VHOST_OPS_DEBUG(r, "vhost_set_log_size failed"); ++ } ++ } ++ + vhost_log_put(dev, true); + dev->log = log; + dev->log_size = size; ++ ++out: ++ return r; + } + + static void *vhost_memory_map(struct vhost_dev *dev, hwaddr addr, +@@ -990,7 +1110,11 @@ static int vhost_migration_log(MemoryListener *listener, bool enable) + } + vhost_log_put(dev, false); + } else { +- vhost_dev_log_resize(dev, vhost_get_log_size(dev)); ++ r = vhost_dev_log_resize(dev, vhost_get_log_size(dev)); ++ if ( r < 0 ) { ++ return r; ++ } ++ + r = vhost_dev_set_log(dev, true); + if (r < 0) { + goto check_dev_state; +@@ -1967,6 +2091,14 @@ int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev, bool vrings) + VHOST_OPS_DEBUG(r, "vhost_set_log_base failed"); + goto fail_log; + } ++ ++ if (hdev->vhost_ops->vhost_set_log_size) { ++ r = hdev->vhost_ops->vhost_set_log_size(hdev, hdev->log_size, hdev->log); ++ if (r < 0) { ++ VHOST_OPS_DEBUG(r, "vhost_set_log_size failed"); ++ goto fail_log; ++ } ++ } + } + if (vrings) { + r = vhost_dev_set_vring_enable(hdev, true); +diff --git a/include/hw/virtio/vhost.h b/include/hw/virtio/vhost.h +index 420f93e5cd..0491fe1ed7 100644 +--- a/include/hw/virtio/vhost.h ++++ b/include/hw/virtio/vhost.h +@@ -40,6 +40,7 @@ typedef unsigned long vhost_log_chunk_t; + #define VHOST_LOG_PAGE 0x1000 + #define VHOST_LOG_BITS (8 * sizeof(vhost_log_chunk_t)) + #define VHOST_LOG_CHUNK (VHOST_LOG_PAGE * VHOST_LOG_BITS) ++#define VHOST_LOG_CHUNK_BYTES (VHOST_LOG_PAGE * sizeof(vhost_log_chunk_t)) + #define VHOST_INVALID_FEATURE_BIT (0xff) + #define VHOST_QUEUE_NUM_CONFIG_INR 0 + +-- +2.27.0 + diff --git a/vhost-user-blk-propagate-error-return-from-generic-v.patch b/vhost-user-blk-propagate-error-return-from-generic-v.patch new file mode 100644 index 00000000..7894db57 --- /dev/null +++ b/vhost-user-blk-propagate-error-return-from-generic-v.patch @@ -0,0 +1,36 @@ +From 2a4dcc55ce71f1251d0dc0ccd293866bfe4dc071 Mon Sep 17 00:00:00 2001 +From: Luo Yifan +Date: Mon, 4 Dec 2023 11:15:58 +0800 +Subject: [PATCH] vhost-user-blk: propagate error return from generic vhost + +cherry picked from commit fb767859345506d747876c23d181155b183f8e94 + +Fix the only callsite that doesn't propagate the error code from the +generic vhost code. + +Signed-off-by: Roman Kagan +Message-Id: <20211111153354.18807-11-rvkagan@yandex-team.ru> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Reviewed-by: Raphael Norwitz +Signed-off-by: Luo Yifan +--- + hw/block/vhost-user-blk.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/hw/block/vhost-user-blk.c b/hw/block/vhost-user-blk.c +index eddc5588fa..f1a281a965 100644 +--- a/hw/block/vhost-user-blk.c ++++ b/hw/block/vhost-user-blk.c +@@ -104,7 +104,7 @@ static int vhost_user_blk_handle_config_change(struct vhost_dev *dev) + &local_err); + if (ret < 0) { + error_report_err(local_err); +- return -1; ++ return ret; + } + + /* valid for resize only */ +-- +2.27.0 + diff --git a/vhost-user-blk-reconnect-on-any-error-during-realize.patch b/vhost-user-blk-reconnect-on-any-error-during-realize.patch new file mode 100644 index 00000000..25eaab24 --- /dev/null +++ b/vhost-user-blk-reconnect-on-any-error-during-realize.patch @@ -0,0 +1,51 @@ +From a64c32378bd5a1119ea69d8c29f93b6365d3346b Mon Sep 17 00:00:00 2001 +From: Luo Yifan +Date: Mon, 4 Dec 2023 11:11:29 +0800 +Subject: [PATCH] vhost-user-blk: reconnect on any error during realize + +cherry picked from commit b7107e758f4ecdd8f07ede3f093cbbfdb623e865 + +vhost-user-blk realize only attempts to reconnect if the previous +connection attempt failed on "a problem with the connection and not an +error related to the content (which would fail again the same way in the +next attempt)". + +However this distinction is very subtle, and may be inadvertently broken +if the code changes somewhere deep down the stack and a new error gets +propagated up to here. + +OTOH now that the number of reconnection attempts is limited it seems +harmless to try reconnecting on any error. + +So relax the condition of whether to retry connecting to check for any +error. + +This patch amends a527e312b5 "vhost-user-blk: Implement reconnection +during realize". + +Signed-off-by: Roman Kagan +Message-Id: <20211111153354.18807-2-rvkagan@yandex-team.ru> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Reviewed-by: Raphael Norwitz +Signed-off-by: Luo Yifan +--- + hw/block/vhost-user-blk.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/hw/block/vhost-user-blk.c b/hw/block/vhost-user-blk.c +index eddc5588fa..a2236c5239 100644 +--- a/hw/block/vhost-user-blk.c ++++ b/hw/block/vhost-user-blk.c +@@ -516,7 +516,7 @@ static void vhost_user_blk_device_realize(DeviceState *dev, Error **errp) + *errp = NULL; + } + ret = vhost_user_blk_realize_connect(s, errp); +- } while (ret == -EPROTO && retries--); ++ } while (ret < 0 && retries--); + + if (ret < 0) { + goto virtio_err; +-- +2.27.0 + diff --git a/vhost-vdpa-add-VHOST_BACKEND_F_BYTEMAPLOG.patch b/vhost-vdpa-add-VHOST_BACKEND_F_BYTEMAPLOG.patch new file mode 100644 index 00000000..d40dd186 --- /dev/null +++ b/vhost-vdpa-add-VHOST_BACKEND_F_BYTEMAPLOG.patch @@ -0,0 +1,49 @@ +From b0c67874628455a869ca1afde0de44572c70d5b9 Mon Sep 17 00:00:00 2001 +From: fangyi +Date: Mon, 4 Dec 2023 14:49:53 +0800 +Subject: [PATCH] vhost-vdpa: add VHOST_BACKEND_F_BYTEMAPLOG + +support VHOST_BACKEND_F_BYTEMAPLOG to support vhost +device bytemap logging. + +Signed-off-by: libai +Signed-off-by: jiangdongxu +Signed-off-by: fangyi +--- + hw/virtio/vhost-vdpa.c | 7 ++++--- + include/standard-headers/linux/vhost_types.h | 2 ++ + 2 files changed, 6 insertions(+), 3 deletions(-) + +diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c +index 986fc795bf..e1c90cf6c2 100644 +--- a/hw/virtio/vhost-vdpa.c ++++ b/hw/virtio/vhost-vdpa.c +@@ -660,9 +660,10 @@ static int vhost_vdpa_set_features(struct vhost_dev *dev, + static int vhost_vdpa_set_backend_cap(struct vhost_dev *dev) + { + uint64_t features; +- uint64_t f = 0x1ULL << VHOST_BACKEND_F_IOTLB_MSG_V2 | +- 0x1ULL << VHOST_BACKEND_F_IOTLB_BATCH | +- 0x1ULL << VHOST_BACKEND_F_IOTLB_ASID; ++ uint64_t f = BIT_ULL(VHOST_BACKEND_F_IOTLB_MSG_V2) | ++ BIT_ULL(VHOST_BACKEND_F_IOTLB_BATCH) | ++ BIT_ULL(VHOST_BACKEND_F_IOTLB_ASID) | ++ BIT_ULL(VHOST_BACKEND_F_BYTEMAPLOG); + int r; + + if (vhost_vdpa_call(dev, VHOST_GET_BACKEND_FEATURES, &features)) { +diff --git a/include/standard-headers/linux/vhost_types.h b/include/standard-headers/linux/vhost_types.h +index 17833e320e..3801d95182 100644 +--- a/include/standard-headers/linux/vhost_types.h ++++ b/include/standard-headers/linux/vhost_types.h +@@ -157,5 +157,7 @@ struct vhost_vdpa_iova_range { + * message + */ + #define VHOST_BACKEND_F_IOTLB_ASID 0x3 ++/* device can use bytemap log */ ++#define VHOST_BACKEND_F_BYTEMAPLOG 0x3f + + #endif +-- +2.27.0 + diff --git a/vhost-vdpa-add-migration-log-ops-for-VhostOps.patch b/vhost-vdpa-add-migration-log-ops-for-VhostOps.patch new file mode 100644 index 00000000..9de17d74 --- /dev/null +++ b/vhost-vdpa-add-migration-log-ops-for-VhostOps.patch @@ -0,0 +1,129 @@ +From 51c8cb0fa2481be78282e7ea8f24a3f97083e2fd Mon Sep 17 00:00:00 2001 +From: fangyi +Date: Mon, 4 Dec 2023 15:04:25 +0800 +Subject: [PATCH] vhost-vdpa: add migration log ops for VhostOps + +Implement vhost_set_log_size for setting buffer size for logging. +Implement vhost_set_log_fd to specify an eventfd to signal on log write. +Implement vhost_log_sync for getting dirtymap logged by vhost backend. + +Signed-off-by: libai +Signed-off-by: jiangdongxu +Signed-off-by: fangyi +--- + hw/virtio/vhost-vdpa.c | 37 +++++++++++++++++++++++++++++++ + include/hw/virtio/vhost-backend.h | 8 +++++++ + linux-headers/linux/vhost.h | 4 ++++ + 3 files changed, 49 insertions(+) + +diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c +index e1c90cf6c2..7663d78b43 100644 +--- a/hw/virtio/vhost-vdpa.c ++++ b/hw/virtio/vhost-vdpa.c +@@ -1146,6 +1146,30 @@ static int vhost_vdpa_set_log_base(struct vhost_dev *dev, uint64_t base, + return vhost_vdpa_call(dev, VHOST_SET_LOG_BASE, &base); + } + ++static int vhost_vdpa_set_log_fd(struct vhost_dev *dev, int fd, ++ struct vhost_log *log) ++{ ++ struct vhost_vdpa *v = dev->opaque; ++ if (v->shadow_vqs_enabled || !vhost_vdpa_first_dev(dev)) { ++ return 0; ++ } ++ ++ return vhost_vdpa_call(dev, VHOST_SET_LOG_FD, &fd); ++} ++ ++static int vhost_vdpa_set_log_size(struct vhost_dev *dev, uint64_t size, ++ struct vhost_log *log) ++{ ++ struct vhost_vdpa *v = dev->opaque; ++ uint64_t logsize = size * sizeof(*(log->log)); ++ ++ if (v->shadow_vqs_enabled || !vhost_vdpa_first_dev(dev)) { ++ return 0; ++ } ++ ++ return vhost_vdpa_call(dev, VHOST_SET_LOG_SIZE, &logsize); ++} ++ + static int vhost_vdpa_set_vring_addr(struct vhost_dev *dev, + struct vhost_vring_addr *addr) + { +@@ -1294,11 +1318,23 @@ static unsigned int vhost_vdpa_get_used_memslots(void) + return vhost_vdpa_used_memslots; + } + ++static int vhost_vdpa_log_sync(struct vhost_dev *dev) ++{ ++ struct vhost_vdpa *v = dev->opaque; ++ if (v->shadow_vqs_enabled || !vhost_vdpa_first_dev(dev)) { ++ return 0; ++ } ++ ++ return vhost_vdpa_call(dev, VHOST_LOG_SYNC, NULL); ++} ++ + const VhostOps vdpa_ops = { + .backend_type = VHOST_BACKEND_TYPE_VDPA, + .vhost_backend_init = vhost_vdpa_init, + .vhost_backend_cleanup = vhost_vdpa_cleanup, + .vhost_set_log_base = vhost_vdpa_set_log_base, ++ .vhost_set_log_size = vhost_vdpa_set_log_size, ++ .vhost_set_log_fd = vhost_vdpa_set_log_fd, + .vhost_set_vring_addr = vhost_vdpa_set_vring_addr, + .vhost_set_vring_num = vhost_vdpa_set_vring_num, + .vhost_set_vring_base = vhost_vdpa_set_vring_base, +@@ -1326,6 +1362,7 @@ const VhostOps vdpa_ops = { + .vhost_get_device_id = vhost_vdpa_get_device_id, + .vhost_vq_get_addr = vhost_vdpa_vq_get_addr, + .vhost_force_iommu = vhost_vdpa_force_iommu, ++ .vhost_log_sync = vhost_vdpa_log_sync, + .vhost_set_config_call = vhost_vdpa_set_config_call, + .vhost_set_used_memslots = vhost_vdpa_set_used_memslots, + .vhost_get_used_memslots = vhost_vdpa_get_used_memslots, +diff --git a/include/hw/virtio/vhost-backend.h b/include/hw/virtio/vhost-backend.h +index bd1c7dfe4f..86154dd0b2 100644 +--- a/include/hw/virtio/vhost-backend.h ++++ b/include/hw/virtio/vhost-backend.h +@@ -53,6 +53,11 @@ typedef int (*vhost_scsi_get_abi_version_op)(struct vhost_dev *dev, + int *version); + typedef int (*vhost_set_log_base_op)(struct vhost_dev *dev, uint64_t base, + struct vhost_log *log); ++typedef int (*vhost_set_log_size_op)(struct vhost_dev *dev, uint64_t size, ++ struct vhost_log *log); ++typedef int (*vhost_set_log_fd_op)(struct vhost_dev *dev, int fd, ++ struct vhost_log *log); ++typedef int (*vhost_log_sync_op)(struct vhost_dev *dev); + typedef int (*vhost_set_mem_table_op)(struct vhost_dev *dev, + struct vhost_memory *mem); + typedef int (*vhost_set_vring_addr_op)(struct vhost_dev *dev, +@@ -141,6 +146,9 @@ typedef struct VhostOps { + vhost_scsi_clear_endpoint_op vhost_scsi_clear_endpoint; + vhost_scsi_get_abi_version_op vhost_scsi_get_abi_version; + vhost_set_log_base_op vhost_set_log_base; ++ vhost_set_log_size_op vhost_set_log_size; ++ vhost_set_log_fd_op vhost_set_log_fd; ++ vhost_log_sync_op vhost_log_sync; + vhost_set_mem_table_op vhost_set_mem_table; + vhost_set_vring_addr_op vhost_set_vring_addr; + vhost_set_vring_endian_op vhost_set_vring_endian; +diff --git a/linux-headers/linux/vhost.h b/linux-headers/linux/vhost.h +index b6ded7f831..65c6b49788 100644 +--- a/linux-headers/linux/vhost.h ++++ b/linux-headers/linux/vhost.h +@@ -43,6 +43,10 @@ + * The bit is set using an atomic 32 bit operation. */ + /* Set base address for logging. */ + #define VHOST_SET_LOG_BASE _IOW(VHOST_VIRTIO, 0x04, __u64) ++/* Set buffer size for logging */ ++#define VHOST_SET_LOG_SIZE _IOW(VHOST_VIRTIO, 0x05, __u64) ++/* Logging sync */ ++#define VHOST_LOG_SYNC _IO(VHOST_VIRTIO, 0x06) + /* Specify an eventfd file descriptor to signal on log write. */ + #define VHOST_SET_LOG_FD _IOW(VHOST_VIRTIO, 0x07, int) + +-- +2.27.0 + diff --git a/xen-pass-through-don-t-create-needless-register-grou.patch b/xen-pass-through-don-t-create-needless-register-grou.patch new file mode 100644 index 00000000..0c45f2be --- /dev/null +++ b/xen-pass-through-don-t-create-needless-register-grou.patch @@ -0,0 +1,63 @@ +From 125b3c3ef9db4cda5e6f08d2f1f5b3d1fe853ef7 Mon Sep 17 00:00:00 2001 +From: tangbinzy +Date: Fri, 24 Nov 2023 08:33:13 +0000 +Subject: [PATCH] xen/pass-through: don't create needless register group + mainline inclusion commit c0e86b7624cb9d6db03e0d48cf82659e5b89a6a6 category: + bugfix + +--------------------------------------------------------------- + +Currently we are creating a register group for the Intel IGD OpRegion +for every device we pass through, but the XEN_PCI_INTEL_OPREGION +register group is only valid for an Intel IGD. Add a check to make +sure the device is an Intel IGD and a check that the administrator has +enabled gfx_passthru in the xl domain configuration. Require both checks +to be true before creating the register group. Use the existing +is_igd_vga_passthrough() function to check for a graphics device from +any vendor and that the administrator enabled gfx_passthru in the xl +domain configuration, but further require that the vendor be Intel, +because only Intel IGD devices have an Intel OpRegion. These are the +same checks hvmloader and libxl do to determine if the Intel OpRegion +needs to be mapped into the guest's memory. Also, move the comment +about trapping 0xfc for the Intel OpRegion where it belongs after +applying this patch. + +Signed-off-by: Chuck Zmudzinski +Reviewed-by: Anthony PERARD +Message-Id: +Signed-off-by: Anthony PERARD + +Signed-off-by: tangbinzy +--- + hw/xen/xen_pt_config_init.c | 14 +++++++++----- + 1 file changed, 9 insertions(+), 5 deletions(-) + +diff --git a/hw/xen/xen_pt_config_init.c b/hw/xen/xen_pt_config_init.c +index e7bcbe4c4f..b9833d2fa7 100644 +--- a/hw/xen/xen_pt_config_init.c ++++ b/hw/xen/xen_pt_config_init.c +@@ -2031,12 +2031,16 @@ void xen_pt_config_init(XenPCIPassthroughState *s, Error **errp) + } + } + +- /* +- * By default we will trap up to 0x40 in the cfg space. +- * If an intel device is pass through we need to trap 0xfc, +- * therefore the size should be 0xff. +- */ + if (xen_pt_emu_reg_grps[i].grp_id == XEN_PCI_INTEL_OPREGION) { ++ if (!is_igd_vga_passthrough(&s->real_device) || ++ s->real_device.vendor_id != PCI_VENDOR_ID_INTEL) { ++ continue; ++ } ++ /* ++ * By default we will trap up to 0x40 in the cfg space. ++ * If an intel device is pass through we need to trap 0xfc, ++ * therefore the size should be 0xff. ++ */ + reg_grp_offset = XEN_PCI_INTEL_OPREGION; + } + +-- +2.27.0 + diff --git a/xen-pass-through-merge-emulated-bits-correctly.patch b/xen-pass-through-merge-emulated-bits-correctly.patch new file mode 100644 index 00000000..e4bc9c4a --- /dev/null +++ b/xen-pass-through-merge-emulated-bits-correctly.patch @@ -0,0 +1,67 @@ +From feec0d41c0737ce46860fd7b34324d41498fdb9d Mon Sep 17 00:00:00 2001 +From: tangbinzy +Date: Fri, 24 Nov 2023 08:20:17 +0000 +Subject: [PATCH] xen/pass-through: merge emulated bits correctly mainline + inclusion commit be9c61da9fc57eb7d293f380d0805ca6f46c2657 category: bugfix + +--------------------------------------------------------------- + +In xen_pt_config_reg_init(), there is an error in the merging of the +emulated data with the host value. With the current Qemu, instead of +merging the emulated bits with the host bits as defined by emu_mask, +the emulated bits are merged with the host bits as defined by the +inverse of emu_mask. In some cases, depending on the data in the +registers on the host, the way the registers are setup, and the +initial values of the emulated bits, the end result will be that +the register is initialized with the wrong value. + +To correct this error, use the XEN_PT_MERGE_VALUE macro to help ensure +the merge is done correctly. + +This correction is needed to resolve Qemu project issue #1061, which +describes the failure of Xen HVM Linux guests to boot in certain +configurations with passed through PCI devices, that is, when this error +disables instead of enables the PCI_STATUS_CAP_LIST bit of the +PCI_STATUS register of a passed through PCI device, which in turn +disables the MSI-X capability of the device in Linux guests with the end +result being that the Linux guest never completes the boot process. + +Fixes: 2e87512eccf3 ("xen/pt: Sync up the dev.config and data values") +Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1061 +Buglink: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=988333 + +Signed-off-by: Chuck Zmudzinski +Reviewed-by: Anthony PERARD +Message-Id: +Signed-off-by: Anthony PERARD + +Signed-off-by: tangbinzy +--- + hw/xen/xen_pt_config_init.c | 11 ++++++----- + 1 file changed, 6 insertions(+), 5 deletions(-) + +diff --git a/hw/xen/xen_pt_config_init.c b/hw/xen/xen_pt_config_init.c +index e7bcbe4c4f..d04c12ce3d 100644 +--- a/hw/xen/xen_pt_config_init.c ++++ b/hw/xen/xen_pt_config_init.c +@@ -1965,11 +1965,12 @@ static void xen_pt_config_reg_init(XenPCIPassthroughState *s, + + if ((data & host_mask) != (val & host_mask)) { + uint32_t new_val; +- +- /* Mask out host (including past size). */ +- new_val = val & host_mask; +- /* Merge emulated ones (excluding the non-emulated ones). */ +- new_val |= data & host_mask; ++ /* ++ * Merge the emulated bits (data) with the host bits (val) ++ * and mask out the bits past size to enable restoration ++ * of the proper value for logging below. ++ */ ++ new_val = XEN_PT_MERGE_VALUE(val, data, host_mask) & size_mask; + /* Leave intact host and emulated values past the size - even though + * we do not care as we write per reg->size granularity, but for the + * logging below lets have the proper value. */ +-- +2.27.0 + -- Gitee From 68fee7dc06a6beb5f69d951e22a7f16091f269ff Mon Sep 17 00:00:00 2001 From: Jiabo Feng Date: Fri, 22 Dec 2023 09:29:00 +0800 Subject: [PATCH 04/19] QEMU update to version 6.2.0-87(master) - vdpa: suspend function return 0 when the vdpa device is stopped - vdpa: don't suspend/resume device when vdpa device not started - vdpa: support vdpa device suspend/resume - vdpa: correct param passed in when unregister save - vdpa: set vring enable only if the vring address has already been set - shadow_dev: introduce shadow dev for virtio-net device - revert "tcg/loongarch64: Fix tcg_out_mov() Aborted" - migration: Set downtime_start even for postcopy - gdb-xml: fix duplicate register in arm-neon.xml - iotests: fix default machine type detection - migration: fix RAMBlock add NULL check - s390x: Fix spelling errors - ppc: spelling fixes - hw/scsi/vhost-scsi: don't double close vhostfd on error - virtio/vhost-vsock: don't double close vhostfd, remove redundant cleanup - hw/scsi/vhost-scsi: don't leak vqs on error - hw/i386/pc: Add missing property descriptions - pcie_aer: Don't trigger a LSI if none are defined - pci: Export the pci_intx() function - hw/qdev: Cosmetic around documentation - tests/unit: fix a -Wformat-truncation warning - tests/avocado: mark ReplayKernelNormal.test_mips64el_malta as flaky - i386/sev: Avoid SEV-ES crash due to missing MSR_EFER_LMA bit - ui/vnc-clipboard: fix inflate_buffer - hw/usb/hcd-xhci.c: spelling: tranfer Signed-off-by: Jiabo Feng --- ...x-duplicate-register-in-arm-neon.xml.patch | 36 +++ ...pc-Add-missing-property-descriptions.patch | 53 ++++ hw-qdev-Cosmetic-around-documentation.patch | 117 ++++++++ ...si-don-t-double-close-vhostfd-on-err.patch | 49 ++++ ...i-vhost-scsi-don-t-leak-vqs-on-error.patch | 55 ++++ hw-usb-hcd-xhci.c-spelling-tranfer.patch | 38 +++ ...EV-ES-crash-due-to-missing-MSR_EFER_.patch | 73 +++++ ...s-fix-default-machine-type-detection.patch | 40 +++ ...Set-downtime_start-even-for-postcopy.patch | 57 ++++ migration-fix-RAMBlock-add-NULL-check.patch | 41 +++ pci-Export-the-pci_intx-function.patch | 59 ++++ ...-t-trigger-a-LSI-if-none-are-defined.patch | 42 +++ ppc-spelling-fixes.patch | 271 ++++++++++++++++++ qemu.spec | 54 +++- ...-loongarch64-Fix-tcg_out_mov-Aborted.patch | 30 ++ s390x-Fix-spelling-errors.patch | 246 ++++++++++++++++ ...duce-shadow-dev-for-virtio-net-devic.patch | 195 +++++++++++++ ...rk-ReplayKernelNormal.test_mips64el_.patch | 48 ++++ ...nit-fix-a-Wformat-truncation-warning.patch | 53 ++++ ui-vnc-clipboard-fix-inflate_buffer.patch | 47 +++ ...param-passed-in-when-unregister-save.patch | 30 ++ ...nd-resume-device-when-vdpa-device-no.patch | 67 +++++ ...nable-only-if-the-vring-address-has-.patch | 44 +++ vdpa-support-vdpa-device-suspend-resume.patch | 119 ++++++++ ...ction-return-0-when-the-vdpa-device-.patch | 45 +++ ...ck-don-t-double-close-vhostfd-remove.patch | 57 ++++ 26 files changed, 1965 insertions(+), 1 deletion(-) create mode 100644 gdb-xml-fix-duplicate-register-in-arm-neon.xml.patch create mode 100644 hw-i386-pc-Add-missing-property-descriptions.patch create mode 100644 hw-qdev-Cosmetic-around-documentation.patch create mode 100644 hw-scsi-vhost-scsi-don-t-double-close-vhostfd-on-err.patch create mode 100644 hw-scsi-vhost-scsi-don-t-leak-vqs-on-error.patch create mode 100644 hw-usb-hcd-xhci.c-spelling-tranfer.patch create mode 100644 i386-sev-Avoid-SEV-ES-crash-due-to-missing-MSR_EFER_.patch create mode 100644 iotests-fix-default-machine-type-detection.patch create mode 100644 migration-Set-downtime_start-even-for-postcopy.patch create mode 100644 migration-fix-RAMBlock-add-NULL-check.patch create mode 100644 pci-Export-the-pci_intx-function.patch create mode 100644 pcie_aer-Don-t-trigger-a-LSI-if-none-are-defined.patch create mode 100644 ppc-spelling-fixes.patch create mode 100644 revert-tcg-loongarch64-Fix-tcg_out_mov-Aborted.patch create mode 100644 s390x-Fix-spelling-errors.patch create mode 100644 shadow_dev-introduce-shadow-dev-for-virtio-net-devic.patch create mode 100644 tests-avocado-mark-ReplayKernelNormal.test_mips64el_.patch create mode 100644 tests-unit-fix-a-Wformat-truncation-warning.patch create mode 100644 ui-vnc-clipboard-fix-inflate_buffer.patch create mode 100644 vdpa-correct-param-passed-in-when-unregister-save.patch create mode 100644 vdpa-don-t-suspend-resume-device-when-vdpa-device-no.patch create mode 100644 vdpa-set-vring-enable-only-if-the-vring-address-has-.patch create mode 100644 vdpa-support-vdpa-device-suspend-resume.patch create mode 100644 vdpa-suspend-function-return-0-when-the-vdpa-device-.patch create mode 100644 virtio-vhost-vsock-don-t-double-close-vhostfd-remove.patch diff --git a/gdb-xml-fix-duplicate-register-in-arm-neon.xml.patch b/gdb-xml-fix-duplicate-register-in-arm-neon.xml.patch new file mode 100644 index 00000000..792af946 --- /dev/null +++ b/gdb-xml-fix-duplicate-register-in-arm-neon.xml.patch @@ -0,0 +1,36 @@ +From 7010b0dd1b6f27b14a0c02c81944513fbd60deab Mon Sep 17 00:00:00 2001 +From: jipengfei_yewu +Date: Mon, 18 Dec 2023 09:58:38 +0000 +Subject: [PATCH] gdb-xml: fix duplicate register in arm-neon.xml +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +cheery-pick from 940bb5fa9ca9f71fcc0d06e9de9ac3ab7415d0f2 + +Signed-off-by: jipengfei_yewu +Reviewed-by: Richard Henderson +Fixes: 56aebc8916 ("Add GDB XML register description support") +Reviewed-by: Philippe Mathieu-Daudé +Signed-off-by: Alex Bennée +Message-Id: <20231106185112.2755262-3-alex.bennee@linaro.org> +--- + gdb-xml/arm-neon.xml | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/gdb-xml/arm-neon.xml b/gdb-xml/arm-neon.xml +index 9dce0a996f..d61f6b8549 100644 +--- a/gdb-xml/arm-neon.xml ++++ b/gdb-xml/arm-neon.xml +@@ -76,7 +76,7 @@ + + + +- ++ + + + +-- +2.27.0 + diff --git a/hw-i386-pc-Add-missing-property-descriptions.patch b/hw-i386-pc-Add-missing-property-descriptions.patch new file mode 100644 index 00000000..d5e699cb --- /dev/null +++ b/hw-i386-pc-Add-missing-property-descriptions.patch @@ -0,0 +1,53 @@ +From 5ce3662809ab7a594fcbe024eb81416e8556f5ea Mon Sep 17 00:00:00 2001 +From: boringandboring +Date: Thu, 7 Dec 2023 19:13:02 +0800 +Subject: [PATCH] hw/i386/pc: Add missing property descriptions + +cherry picked from 44bff3767ced18845adb2612a2cf9691d8769d41 + +When running "qemu-system-x86_64 -M pc,help" I noticed that some +properties were still missing their description. Add them now so +that users get at least a slightly better idea what they are all +about. + +Signed-off-by: Thomas Huth +Message-Id: <20211206134255.94784-1-thuth@redhat.com> +Reviewed-by: Igor Mammedov +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Signed-off-by: boringandboring +--- + hw/i386/pc.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/hw/i386/pc.c b/hw/i386/pc.c +index c5f430f83d..7003ea1a05 100644 +--- a/hw/i386/pc.c ++++ b/hw/i386/pc.c +@@ -1726,15 +1726,23 @@ static void pc_machine_class_init(ObjectClass *oc, void *data) + + object_class_property_add_bool(oc, PC_MACHINE_SMBUS, + pc_machine_get_smbus, pc_machine_set_smbus); ++ object_class_property_set_description(oc, PC_MACHINE_SMBUS, ++ "Enable/disable system management bus"); + + object_class_property_add_bool(oc, PC_MACHINE_SATA, + pc_machine_get_sata, pc_machine_set_sata); ++ object_class_property_set_description(oc, PC_MACHINE_SATA, ++ "Enable/disable Serial ATA bus"); + + object_class_property_add_bool(oc, PC_MACHINE_PIT, + pc_machine_get_pit, pc_machine_set_pit); ++ object_class_property_set_description(oc, PC_MACHINE_PIT, ++ "Enable/disable Intel 8254 programmable interval timer emulation"); + + object_class_property_add_bool(oc, "hpet", + pc_machine_get_hpet, pc_machine_set_hpet); ++ object_class_property_set_description(oc, "hpet", ++ "Enable/disable high precision event timer emulation"); + + object_class_property_add_bool(oc, "default-bus-bypass-iommu", + pc_machine_get_default_bus_bypass_iommu, +-- +2.27.0 + diff --git a/hw-qdev-Cosmetic-around-documentation.patch b/hw-qdev-Cosmetic-around-documentation.patch new file mode 100644 index 00000000..cacee6c6 --- /dev/null +++ b/hw-qdev-Cosmetic-around-documentation.patch @@ -0,0 +1,117 @@ +From 14c2249a3caa3afc6252ac61fb700378c4d32a40 Mon Sep 17 00:00:00 2001 +From: boringandboring +Date: Thu, 7 Dec 2023 11:13:33 +0800 +Subject: [PATCH] hw/qdev: Cosmetic around documentation +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +cherry picked from 694804ed7b26e66e114a2330887187d697a0d92b + +Add empty lines to have a clearer distinction between different +functions declarations. + +Signed-off-by: Philippe Mathieu-Daudé +Reviewed-by: Yanan Wang +Message-Id: <20211218130437.1516929-2-f4bug@amsat.org> +Signed-off-by: Philippe Mathieu-Daudé +Signed-off-by: boringandboring +--- + include/hw/qdev-core.h | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h +index 20d3066595..59a822ffce 100644 +--- a/include/hw/qdev-core.h ++++ b/include/hw/qdev-core.h +@@ -321,6 +321,7 @@ compat_props_add(GPtrArray *arr, + * The returned object has a reference count of 1. + */ + DeviceState *qdev_new(const char *name); ++ + /** + * qdev_try_new: Try to create a device on the heap + * @name: device type to create +@@ -329,6 +330,7 @@ DeviceState *qdev_new(const char *name); + * does not exist, rather than asserting. + */ + DeviceState *qdev_try_new(const char *name); ++ + /** + * qdev_realize: Realize @dev. + * @dev: device to realize +@@ -347,6 +349,7 @@ DeviceState *qdev_try_new(const char *name); + * qdev_realize_and_unref() instead. + */ + bool qdev_realize(DeviceState *dev, BusState *bus, Error **errp); ++ + /** + * qdev_realize_and_unref: Realize @dev and drop a reference + * @dev: device to realize +@@ -372,6 +375,7 @@ bool qdev_realize(DeviceState *dev, BusState *bus, Error **errp); + * would be incorrect. For that use case you want qdev_realize(). + */ + bool qdev_realize_and_unref(DeviceState *dev, BusState *bus, Error **errp); ++ + /** + * qdev_unrealize: Unrealize a device + * @dev: device to unrealize +@@ -450,6 +454,7 @@ typedef enum { + * For named input GPIO lines, use qdev_get_gpio_in_named(). + */ + qemu_irq qdev_get_gpio_in(DeviceState *dev, int n); ++ + /** + * qdev_get_gpio_in_named: Get one of a device's named input GPIO lines + * @dev: Device whose GPIO we want +@@ -497,6 +502,7 @@ qemu_irq qdev_get_gpio_in_named(DeviceState *dev, const char *name, int n); + * For named output GPIO lines, use qdev_connect_gpio_out_named(). + */ + void qdev_connect_gpio_out(DeviceState *dev, int n, qemu_irq pin); ++ + /** + * qdev_connect_gpio_out: Connect one of a device's anonymous output GPIO lines + * @dev: Device whose GPIO to connect +@@ -524,6 +530,7 @@ void qdev_connect_gpio_out(DeviceState *dev, int n, qemu_irq pin); + */ + void qdev_connect_gpio_out_named(DeviceState *dev, const char *name, int n, + qemu_irq pin); ++ + /** + * qdev_get_gpio_out_connector: Get the qemu_irq connected to an output GPIO + * @dev: Device whose output GPIO we are interested in +@@ -541,6 +548,7 @@ void qdev_connect_gpio_out_named(DeviceState *dev, const char *name, int n, + * by the platform-bus subsystem. + */ + qemu_irq qdev_get_gpio_out_connector(DeviceState *dev, const char *name, int n); ++ + /** + * qdev_intercept_gpio_out: Intercept an existing GPIO connection + * @dev: Device to intercept the outbound GPIO line from +@@ -582,6 +590,7 @@ BusState *qdev_get_child_bus(DeviceState *dev, const char *name); + * hold of an input GPIO line to manipulate it. + */ + void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n); ++ + /** + * qdev_init_gpio_out: create an array of anonymous output GPIO lines + * @dev: Device to create output GPIOs for +@@ -610,6 +619,7 @@ void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n); + * handler. + */ + void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n); ++ + /** + * qdev_init_gpio_out: create an array of named output GPIO lines + * @dev: Device to create output GPIOs for +@@ -623,6 +633,7 @@ void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n); + */ + void qdev_init_gpio_out_named(DeviceState *dev, qemu_irq *pins, + const char *name, int n); ++ + /** + * qdev_init_gpio_in_named_with_opaque: create an array of input GPIO lines + * for the specified device +-- +2.27.0 + diff --git a/hw-scsi-vhost-scsi-don-t-double-close-vhostfd-on-err.patch b/hw-scsi-vhost-scsi-don-t-double-close-vhostfd-on-err.patch new file mode 100644 index 00000000..84db1805 --- /dev/null +++ b/hw-scsi-vhost-scsi-don-t-double-close-vhostfd-on-err.patch @@ -0,0 +1,49 @@ +From 69f5f16cee63b0d07ee612b59a0d125780c13bdb Mon Sep 17 00:00:00 2001 +From: boringandboring +Date: Fri, 8 Dec 2023 09:13:42 +0800 +Subject: [PATCH] hw/scsi/vhost-scsi: don't double close vhostfd on error + +cherry picked from 539ba1acacb11a0f27a7e7ff7e2a7c1294e0a1ea + +vhost_dev_init calls vhost_dev_cleanup on error, which closes vhostfd, +don't double close it. + +Signed-off-by: Daniil Tatianin +Message-Id: <20211129132358.1110372-2-d-tatianin@yandex-team.ru> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Signed-off-by: boringandboring +--- + hw/scsi/vhost-scsi.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/hw/scsi/vhost-scsi.c b/hw/scsi/vhost-scsi.c +index b0a9c45e43..5536cc8a88 100644 +--- a/hw/scsi/vhost-scsi.c ++++ b/hw/scsi/vhost-scsi.c +@@ -220,6 +220,11 @@ static void vhost_scsi_realize(DeviceState *dev, Error **errp) + ret = vhost_dev_init(&vsc->dev, (void *)(uintptr_t)vhostfd, + VHOST_BACKEND_TYPE_KERNEL, 0, errp); + if (ret < 0) { ++ /* ++ * vhost_dev_init calls vhost_dev_cleanup on error, which closes ++ * vhostfd, don't double close it. ++ */ ++ vhostfd = -1; + goto free_vqs; + } + +@@ -240,7 +245,9 @@ static void vhost_scsi_realize(DeviceState *dev, Error **errp) + error_free(vsc->migration_blocker); + virtio_scsi_common_unrealize(dev); + close_fd: +- close(vhostfd); ++ if (vhostfd >= 0) { ++ close(vhostfd); ++ } + return; + } + +-- +2.27.0 + diff --git a/hw-scsi-vhost-scsi-don-t-leak-vqs-on-error.patch b/hw-scsi-vhost-scsi-don-t-leak-vqs-on-error.patch new file mode 100644 index 00000000..5d898ce5 --- /dev/null +++ b/hw-scsi-vhost-scsi-don-t-leak-vqs-on-error.patch @@ -0,0 +1,55 @@ +From ad55425ad09197b443c150828ac16dbf4242141f Mon Sep 17 00:00:00 2001 +From: boringandboring +Date: Thu, 7 Dec 2023 19:45:33 +0800 +Subject: [PATCH] hw/scsi/vhost-scsi: don't leak vqs on error + +cherry picked from b259772afc29ef6af4e911d8e695dd7e2ed31066 + +vhost_dev_init calls vhost_dev_cleanup in case of an error during +initialization, which zeroes out the entire vsc->dev as well as the +vsc->dev.vqs pointer. This prevents us from properly freeing it in free_vqs. +Keep a local copy of the pointer so we can free it later. + +Signed-off-by: Daniil Tatianin +Message-Id: <20211129132358.1110372-1-d-tatianin@yandex-team.ru> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Signed-off-by: boringandboring +--- + hw/scsi/vhost-scsi.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/hw/scsi/vhost-scsi.c b/hw/scsi/vhost-scsi.c +index b0a9c45e43..2fbc7f039d 100644 +--- a/hw/scsi/vhost-scsi.c ++++ b/hw/scsi/vhost-scsi.c +@@ -170,6 +170,7 @@ static void vhost_scsi_realize(DeviceState *dev, Error **errp) + Error *err = NULL; + int vhostfd = -1; + int ret; ++ struct vhost_virtqueue *vqs = NULL; + + if (!vs->conf.wwpn) { + error_setg(errp, "vhost-scsi: missing wwpn"); +@@ -213,7 +214,8 @@ static void vhost_scsi_realize(DeviceState *dev, Error **errp) + } + + vsc->dev.nvqs = VHOST_SCSI_VQ_NUM_FIXED + vs->conf.num_queues; +- vsc->dev.vqs = g_new0(struct vhost_virtqueue, vsc->dev.nvqs); ++ vqs = g_new0(struct vhost_virtqueue, vsc->dev.nvqs); ++ vsc->dev.vqs = vqs; + vsc->dev.vq_index = 0; + vsc->dev.backend_features = 0; + +@@ -232,7 +234,7 @@ static void vhost_scsi_realize(DeviceState *dev, Error **errp) + return; + + free_vqs: +- g_free(vsc->dev.vqs); ++ g_free(vqs); + if (!vsc->migratable) { + migrate_del_blocker(vsc->migration_blocker); + } +-- +2.27.0 + diff --git a/hw-usb-hcd-xhci.c-spelling-tranfer.patch b/hw-usb-hcd-xhci.c-spelling-tranfer.patch new file mode 100644 index 00000000..c5a5189d --- /dev/null +++ b/hw-usb-hcd-xhci.c-spelling-tranfer.patch @@ -0,0 +1,38 @@ +From 755899cd2cb3d808717da99fa1447c3c81cc0dce Mon Sep 17 00:00:00 2001 +From: zhujun2 +Date: Thu, 7 Dec 2023 18:03:12 -0800 +Subject: [PATCH] hw/usb/hcd-xhci.c: spelling: tranfer + +mainline inclusion +commit d68640f515320bf38617b68c970b569997cf0444 +category: bugfix + +--------------------------------------------------------------- + +Fixes: effaf5a240e03020f4ae953e10b764622c3e87cc +Signed-off-by: Michael Tokarev +Reviewed-by: Thomas Huth +Reviewed-by: Stefan Weil +Message-Id: <20221105114851.306206-1-mjt@msgid.tls.msk.ru> +Signed-off-by: Gerd Hoffmann +Signed-off-by: zhujun2 +--- + hw/usb/hcd-xhci.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c +index ac02548dcf..40300e1bcd 100644 +--- a/hw/usb/hcd-xhci.c ++++ b/hw/usb/hcd-xhci.c +@@ -775,7 +775,7 @@ static int xhci_ring_chain_length(XHCIState *xhci, const XHCIRing *ring) + */ + } while (length < TRB_LINK_LIMIT * 65536 / TRB_SIZE); + +- qemu_log_mask(LOG_GUEST_ERROR, "%s: exceeded maximum tranfer ring size!\n", ++ qemu_log_mask(LOG_GUEST_ERROR, "%s: exceeded maximum transfer ring size!\n", + __func__); + + return -1; +-- +2.27.0 + diff --git a/i386-sev-Avoid-SEV-ES-crash-due-to-missing-MSR_EFER_.patch b/i386-sev-Avoid-SEV-ES-crash-due-to-missing-MSR_EFER_.patch new file mode 100644 index 00000000..50fd9c46 --- /dev/null +++ b/i386-sev-Avoid-SEV-ES-crash-due-to-missing-MSR_EFER_.patch @@ -0,0 +1,73 @@ +From 92b95a2982e192b90b45a988afe81e253862690f Mon Sep 17 00:00:00 2001 +From: tangzhongrui +Date: Thu, 7 Dec 2023 20:06:08 +0800 +Subject: [PATCH] i386/sev: Avoid SEV-ES crash due to missing MSR_EFER_LMA + bit +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + + Commit 7191f24c7fcf ("accel/kvm/kvm-all: Handle register access errors") + added error checking for KVM_SET_SREGS/KVM_SET_SREGS2. In doing so, it + exposed a long-running bug in current KVM support for SEV-ES where the + kernel assumes that MSR_EFER_LMA will be set explicitly by the guest + kernel, in which case EFER write traps would result in KVM eventually + seeing MSR_EFER_LMA get set and recording it in such a way that it would + be subsequently visible when accessing it via KVM_GET_SREGS/etc. + + However, guest kernels currently rely on MSR_EFER_LMA getting set + automatically when MSR_EFER_LME is set and paging is enabled via + CR0_PG_MASK. As a result, the EFER write traps don't actually expose the + MSR_EFER_LMA bit, even though it is set internally, and when QEMU + subsequently tries to pass this EFER value back to KVM via + KVM_SET_SREGS* it will fail various sanity checks and return -EINVAL, + which is now considered fatal due to the aforementioned QEMU commit. + + This can be addressed by inferring the MSR_EFER_LMA bit being set when + paging is enabled and MSR_EFER_LME is set, and synthesizing it to ensure + the expected bits are all present in subsequent handling on the host + side. + + Ultimately, this handling will be implemented in the host kernel, but to + avoid breaking QEMU's SEV-ES support when using older host kernels, the + same handling can be done in QEMU just after fetching the register + values via KVM_GET_SREGS*. Implement that here. + + Cc: Paolo Bonzini + Cc: Marcelo Tosatti + Cc: Tom Lendacky + Cc: Akihiko Odaki + Cc: Philippe Mathieu-Daudé + Cc: Lara Lazier + Cc: Vitaly Kuznetsov + Cc: Maxim Levitsky + Cc: + Fixes: 7191f24c7fcf ("accel/kvm/kvm-all: Handle register access errors") + Signed-off-by: Michael Roth + Acked-by: Paolo Bonzini + Signed-off-by: Stefan Hajnoczi + Message-ID: <20231206155821.1194551-1-michael.roth@amd.com> + + Signed-off-by: Zhongrui Tang +--- + target/i386/kvm/kvm.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c +index 55ee75e844..54e48530ad 100644 +--- a/target/i386/kvm/kvm.c ++++ b/target/i386/kvm/kvm.c +@@ -3420,6 +3420,10 @@ static int kvm_get_sregs(X86CPU *cpu) + env->cr[4] = sregs.cr4; + + env->efer = sregs.efer; ++ if (sev_es_enabled() && env->efer & MSR_EFER_LME && ++ env->cr[0] & CR0_PG_MASK) { ++ env->efer |= MSR_EFER_LMA; ++ } + + /* changes to apic base and cr8/tpr are read back via kvm_arch_post_run */ + x86_update_hflags(env); +-- +2.27.0 + diff --git a/iotests-fix-default-machine-type-detection.patch b/iotests-fix-default-machine-type-detection.patch new file mode 100644 index 00000000..47910b76 --- /dev/null +++ b/iotests-fix-default-machine-type-detection.patch @@ -0,0 +1,40 @@ +From 1c60628eef43847595723a65ff9fd57f38cc70de Mon Sep 17 00:00:00 2001 +From: jipengfei_yewu +Date: Mon, 18 Dec 2023 09:57:38 +0000 +Subject: [PATCH] iotests: fix default machine type detection + +The machine type is being detected based on "-M help" output, and we're +searching for the line ending with " (default)". However, in downstream +one of the machine types s marked as deprecated might become the +default, in which case this logic breaks as the line would now end with +" (default) (deprecated)". To fix potential issues here, let's relax +that requirement and detect the mere presence of " (default)" line +instead. + +cheery-pick from 3b7094fe8329c5c7bb0d685e1876aa30f59bece6 + +Signed-off-by: jipengfei_yewu +Signed-off-by: Andrey Drobyshev +Message-ID: <20231122121538.32903-1-andrey.drobyshev@virtuozzo.com> +Reviewed-by: Kevin Wolf +Signed-off-by: Kevin Wolf +--- + tests/qemu-iotests/testenv.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tests/qemu-iotests/testenv.py b/tests/qemu-iotests/testenv.py +index 26ae6945cc..993e9c56be 100644 +--- a/tests/qemu-iotests/testenv.py ++++ b/tests/qemu-iotests/testenv.py +@@ -40,7 +40,7 @@ def get_default_machine(qemu_prog: str) -> str: + + machines = outp.split('\n') + try: +- default_machine = next(m for m in machines if m.endswith(' (default)')) ++ default_machine = next(m for m in machines if ' (default)' in m) + except StopIteration: + return '' + default_machine = default_machine.split(' ', 1)[0] +-- +2.27.0 + diff --git a/migration-Set-downtime_start-even-for-postcopy.patch b/migration-Set-downtime_start-even-for-postcopy.patch new file mode 100644 index 00000000..8aa72cb4 --- /dev/null +++ b/migration-Set-downtime_start-even-for-postcopy.patch @@ -0,0 +1,57 @@ +From 9708192479d7f6507392a338f8f43b3be4c8188d Mon Sep 17 00:00:00 2001 +From: qihao +Date: Mon, 18 Dec 2023 15:19:48 +0800 +Subject: [PATCH] migration: Set downtime_start even for postcopy + +cheery-pick from 62f5da7dd10a594fb30cebb5569dc738456f7131 + +Postcopy calculates its downtime separately. It always sets +MigrationState.downtime properly, but not MigrationState.downtime_start. + +Make postcopy do the same as other modes on properly recording the +timestamp when the VM is going to be stopped. Drop the temporary variable +in postcopy_start() along the way. + +Signed-off-by: Peter Xu +Reviewed-by: Fabiano Rosas +Reviewed-by: Juan Quintela +Signed-off-by: Juan Quintela +Message-ID: <20231030163346.765724-2-peterx@redhat.com> +Signed-off-by: qihao_yewu +--- + migration/migration.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/migration/migration.c b/migration/migration.c +index 6b5445853a..7ca5b58839 100644 +--- a/migration/migration.c ++++ b/migration/migration.c +@@ -2989,7 +2989,6 @@ static int postcopy_start(MigrationState *ms) + int ret; + QIOChannelBuffer *bioc; + QEMUFile *fb; +- int64_t time_at_stop = qemu_clock_get_ms(QEMU_CLOCK_REALTIME); + int64_t bandwidth = migrate_max_postcopy_bandwidth(); + bool restart_block = false; + int cur_state = MIGRATION_STATUS_ACTIVE; +@@ -3002,6 +3001,8 @@ static int postcopy_start(MigrationState *ms) + qemu_mutex_lock_iothread(); + trace_postcopy_start_set_run(); + ++ ms->downtime_start = qemu_clock_get_ms(QEMU_CLOCK_REALTIME); ++ + qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER, NULL); + global_state_store(); + ret = vm_stop_force_state(RUN_STATE_FINISH_MIGRATE); +@@ -3112,7 +3113,7 @@ static int postcopy_start(MigrationState *ms) + ms->postcopy_after_devices = true; + notifier_list_notify(&migration_state_notifiers, ms); + +- ms->downtime = qemu_clock_get_ms(QEMU_CLOCK_REALTIME) - time_at_stop; ++ ms->downtime = qemu_clock_get_ms(QEMU_CLOCK_REALTIME) - ms->downtime_start; + + qemu_mutex_unlock_iothread(); + +-- +2.27.0 + diff --git a/migration-fix-RAMBlock-add-NULL-check.patch b/migration-fix-RAMBlock-add-NULL-check.patch new file mode 100644 index 00000000..88cd6302 --- /dev/null +++ b/migration-fix-RAMBlock-add-NULL-check.patch @@ -0,0 +1,41 @@ +From 03569a14e7ae428bad59a4e11637c900ff436816 Mon Sep 17 00:00:00 2001 +From: jipengfei +Date: Mon, 18 Dec 2023 16:56:15 +0800 +Subject: [PATCH] migration: fix RAMBlock add NULL check + +qemu_ram_block_from_host() may return NULL, which will be dereferenced w/o +check. Usualy return value is checked for this function. +Found by Linux Verification Center (linuxtesting.org) with SVACE. + +cheery-pick from f75ed59f40bed3ce94adad4b3ebbb7bfacfdf4ab + +Signed-off-by: jipengfei_yewu +Signed-off-by: Dmitry Frolov +Reviewed-by: Fabiano Rosas +Reviewed-by: Peter Xu +Reviewed-by: Juan Quintela +Signed-off-by: Juan Quintela +Message-ID: <20231010104851.802947-1-frolov@swemel.ru> +--- + migration/ram.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/migration/ram.c b/migration/ram.c +index 862955f5b2..c245b04cf2 100644 +--- a/migration/ram.c ++++ b/migration/ram.c +@@ -4679,6 +4679,11 @@ static void ram_mig_ram_block_resized(RAMBlockNotifier *n, void *host, + RAMBlock *rb = qemu_ram_block_from_host(host, false, &offset); + Error *err = NULL; + ++ if (!rb) { ++ error_report("RAM block not found"); ++ return; ++ } ++ + if (ramblock_is_ignored(rb)) { + return; + } +-- +2.27.0 + diff --git a/pci-Export-the-pci_intx-function.patch b/pci-Export-the-pci_intx-function.patch new file mode 100644 index 00000000..732b6717 --- /dev/null +++ b/pci-Export-the-pci_intx-function.patch @@ -0,0 +1,59 @@ +From 0d74ea5e0426c6ebf8666e8b88469b838d03ea01 Mon Sep 17 00:00:00 2001 +From: boringandboring +Date: Thu, 7 Dec 2023 16:55:35 +0800 +Subject: [PATCH] pci: Export the pci_intx() function +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +cherry picked from 2fedf46e34d2377760b2d26cf85487b772bca6fa + +Move the pci_intx() definition to the PCI header file, so that it can +be called from other PCI files. It is used by the next patch. + +Signed-off-by: Frederic Barrat +Message-Id: <20211116170133.724751-3-fbarrat@linux.ibm.com> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Reviewed-by: Cédric Le Goater +Signed-off-by: boringandboring +--- + hw/pci/pci.c | 5 ----- + include/hw/pci/pci.h | 5 +++++ + 2 files changed, 5 insertions(+), 5 deletions(-) + +diff --git a/hw/pci/pci.c b/hw/pci/pci.c +index 7a62f0e1fc..9ea67dba31 100644 +--- a/hw/pci/pci.c ++++ b/hw/pci/pci.c +@@ -1504,11 +1504,6 @@ static void pci_irq_handler(void *opaque, int irq_num, int level) + pci_change_irq_level(pci_dev, irq_num, change); + } + +-static inline int pci_intx(PCIDevice *pci_dev) +-{ +- return pci_get_byte(pci_dev->config + PCI_INTERRUPT_PIN) - 1; +-} +- + qemu_irq pci_allocate_irq(PCIDevice *pci_dev) + { + int intx = pci_intx(pci_dev); +diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h +index 5b36334a28..483d5c7c72 100644 +--- a/include/hw/pci/pci.h ++++ b/include/hw/pci/pci.h +@@ -735,6 +735,11 @@ void lsi53c8xx_handle_legacy_cmdline(DeviceState *lsi_dev); + qemu_irq pci_allocate_irq(PCIDevice *pci_dev); + void pci_set_irq(PCIDevice *pci_dev, int level); + ++static inline int pci_intx(PCIDevice *pci_dev) ++{ ++ return pci_get_byte(pci_dev->config + PCI_INTERRUPT_PIN) - 1; ++} ++ + static inline void pci_irq_assert(PCIDevice *pci_dev) + { + pci_set_irq(pci_dev, 1); +-- +2.27.0 + diff --git a/pcie_aer-Don-t-trigger-a-LSI-if-none-are-defined.patch b/pcie_aer-Don-t-trigger-a-LSI-if-none-are-defined.patch new file mode 100644 index 00000000..c4462b72 --- /dev/null +++ b/pcie_aer-Don-t-trigger-a-LSI-if-none-are-defined.patch @@ -0,0 +1,42 @@ +From 77633ce67c1cff764fe4951a6837462f51ace8aa Mon Sep 17 00:00:00 2001 +From: boringandboring +Date: Thu, 7 Dec 2023 17:00:28 +0800 +Subject: [PATCH] pcie_aer: Don't trigger a LSI if none are defined +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +cherry picked from 20766514d602c50b870ae943aaa8e5b9e2e8a161 + +Skip triggering an LSI when the AER root error status is updated if no +LSI is defined for the device. We can have a root bridge with no LSI, +MSI and MSI-X defined, for example on POWER systems. + +Signed-off-by: Frederic Barrat +Message-Id: <20211116170133.724751-4-fbarrat@linux.ibm.com> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Reviewed-by: Cédric Le Goater +Signed-off-by: boringandboring +--- + hw/pci/pcie_aer.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/hw/pci/pcie_aer.c b/hw/pci/pcie_aer.c +index 27f9cc56af..e1a8a88c8c 100644 +--- a/hw/pci/pcie_aer.c ++++ b/hw/pci/pcie_aer.c +@@ -774,7 +774,9 @@ void pcie_aer_root_write_config(PCIDevice *dev, + uint32_t root_cmd = pci_get_long(aer_cap + PCI_ERR_ROOT_COMMAND); + /* 6.2.4.1.2 Interrupt Generation */ + if (!msix_enabled(dev) && !msi_enabled(dev)) { +- pci_set_irq(dev, !!(root_cmd & enabled_cmd)); ++ if (pci_intx(dev) != -1) { ++ pci_set_irq(dev, !!(root_cmd & enabled_cmd)); ++ } + return; + } + +-- +2.27.0 + diff --git a/ppc-spelling-fixes.patch b/ppc-spelling-fixes.patch new file mode 100644 index 00000000..127101b5 --- /dev/null +++ b/ppc-spelling-fixes.patch @@ -0,0 +1,271 @@ +From 0adb55804594e60380450c7644a05f9cfc4ebb8a Mon Sep 17 00:00:00 2001 +From: zhujun2 +Date: Sun, 26 Nov 2023 18:34:45 -0800 +Subject: [PATCH] ppc: spelling fixes +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +mainline inclusion +commit e6a19a6477407e57b4deb61aaa497a14d7db9626 +category: bugfix + +Signed-off-by: Michael Tokarev +Reviewed-by: Cédric Le Goater +Signed-off-by: zhujun2 +--- + hw/ppc/ppc.c | 2 +- + hw/ppc/prep_systemio.c | 2 +- + hw/ppc/spapr.c | 8 ++++---- + hw/ppc/spapr_hcall.c | 2 +- + hw/ppc/spapr_nvdimm.c | 2 +- + hw/ppc/spapr_pci_vfio.c | 2 +- + include/hw/ppc/openpic.h | 2 +- + include/hw/ppc/spapr.h | 2 +- + target/ppc/cpu-models.h | 4 ++-- + target/ppc/cpu.h | 2 +- + target/ppc/cpu_init.c | 2 +- + target/ppc/excp_helper.c | 2 +- + target/ppc/power8-pmu-regs.c.inc | 4 ++-- + target/ppc/translate/vmx-impl.c.inc | 4 ++-- + 14 files changed, 20 insertions(+), 20 deletions(-) + +diff --git a/hw/ppc/ppc.c b/hw/ppc/ppc.c +index cf90ab7805..6396bbe523 100644 +--- a/hw/ppc/ppc.c ++++ b/hw/ppc/ppc.c +@@ -745,7 +745,7 @@ target_ulong cpu_ppc_load_decr(CPUPPCState *env) + decr = _cpu_ppc_load_decr(env, tb_env->decr_next); + + /* +- * If large decrementer is enabled then the decrementer is signed extened ++ * If large decrementer is enabled then the decrementer is signed extended + * to 64 bits, otherwise it is a 32 bit value. + */ + if (env->spr[SPR_LPCR] & LPCR_LD) { +diff --git a/hw/ppc/prep_systemio.c b/hw/ppc/prep_systemio.c +index b2bd783248..e51da91de5 100644 +--- a/hw/ppc/prep_systemio.c ++++ b/hw/ppc/prep_systemio.c +@@ -39,7 +39,7 @@ + #define TYPE_PREP_SYSTEMIO "prep-systemio" + OBJECT_DECLARE_SIMPLE_TYPE(PrepSystemIoState, PREP_SYSTEMIO) + +-/* Bit as defined in PowerPC Reference Plaform v1.1, sect. 6.1.5, p. 132 */ ++/* Bit as defined in PowerPC Reference Platform v1.1, sect. 6.1.5, p. 132 */ + #define PREP_BIT(n) (1 << (7 - (n))) + + struct PrepSystemIoState { +diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c +index 3b5fd749be..7f352ceaaa 100644 +--- a/hw/ppc/spapr.c ++++ b/hw/ppc/spapr.c +@@ -2488,7 +2488,7 @@ static void spapr_set_vsmt_mode(SpaprMachineState *spapr, Error **errp) + return; + } + +- /* Detemine the VSMT mode to use: */ ++ /* Determine the VSMT mode to use: */ + if (vsmt_user) { + if (spapr->vsmt < smp_threads) { + error_setg(errp, "Cannot support VSMT mode %d" +@@ -3016,7 +3016,7 @@ static int spapr_kvm_type(MachineState *machine, const char *vm_type) + { + /* + * The use of g_ascii_strcasecmp() for 'hv' and 'pr' is to +- * accomodate the 'HV' and 'PV' formats that exists in the ++ * accommodate the 'HV' and 'PV' formats that exists in the + * wild. The 'auto' mode is being introduced already as + * lower-case, thus we don't need to bother checking for + * "AUTO". +@@ -4250,7 +4250,7 @@ spapr_cpu_index_to_props(MachineState *machine, unsigned cpu_index) + CPUArchId *core_slot; + MachineClass *mc = MACHINE_GET_CLASS(machine); + +- /* make sure possible_cpu are intialized */ ++ /* make sure possible_cpu are initialized */ + mc->possible_cpu_arch_ids(machine); + /* get CPU core slot containing thread that matches cpu_index */ + core_slot = spapr_find_cpu_slot(machine, cpu_index, NULL); +@@ -4870,7 +4870,7 @@ static void spapr_machine_2_12_class_options(MachineClass *mc) + + /* We depend on kvm_enabled() to choose a default value for the + * hpt-max-page-size capability. Of course we can't do it here +- * because this is too early and the HW accelerator isn't initialzed ++ * because this is too early and the HW accelerator isn't initialized + * yet. Postpone this to machine init (see default_caps_with_cpu()). + */ + smc->default_caps.caps[SPAPR_CAP_HPT_MAXPAGESIZE] = 0; +diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c +index 222c1b6bbd..5364bbcffa 100644 +--- a/hw/ppc/spapr_hcall.c ++++ b/hw/ppc/spapr_hcall.c +@@ -1532,7 +1532,7 @@ static void hypercall_register_types(void) + spapr_register_hypercall(H_GET_CPU_CHARACTERISTICS, + h_get_cpu_characteristics); + +- /* "debugger" hcalls (also used by SLOF). Note: We do -not- differenciate ++ /* "debugger" hcalls (also used by SLOF). Note: We do -not- differentiate + * here between the "CI" and the "CACHE" variants, they will use whatever + * mapping attributes qemu is using. When using KVM, the kernel will + * enforce the attributes more strongly +diff --git a/hw/ppc/spapr_nvdimm.c b/hw/ppc/spapr_nvdimm.c +index 91de1052f2..b111380a45 100644 +--- a/hw/ppc/spapr_nvdimm.c ++++ b/hw/ppc/spapr_nvdimm.c +@@ -336,7 +336,7 @@ static target_ulong h_scm_bind_mem(PowerPCCPU *cpu, SpaprMachineState *spapr, + + /* + * Currently continue token should be zero qemu has already bound +- * everything and this hcall doesnt return H_BUSY. ++ * everything and this hcall doesn't return H_BUSY. + */ + if (continue_token > 0) { + return H_P5; +diff --git a/hw/ppc/spapr_pci_vfio.c b/hw/ppc/spapr_pci_vfio.c +index 2a76b4e0b5..6326948143 100644 +--- a/hw/ppc/spapr_pci_vfio.c ++++ b/hw/ppc/spapr_pci_vfio.c +@@ -77,7 +77,7 @@ int spapr_phb_vfio_eeh_set_option(SpaprPhbState *sphb, + * call. Now we just need to check the validity of the PCI + * pass-through devices (vfio-pci) under this sphb bus. + * We have already validated that all the devices under this sphb +- * are from same iommu group (within same PE) before comming here. ++ * are from same iommu group (within same PE) before coming here. + * + * Prior to linux commit 98ba956f6a389 ("powerpc/pseries/eeh: + * Rework device EEH PE determination") kernel would call +diff --git a/include/hw/ppc/openpic.h b/include/hw/ppc/openpic.h +index ebdaf8a493..44976e6b07 100644 +--- a/include/hw/ppc/openpic.h ++++ b/include/hw/ppc/openpic.h +@@ -14,7 +14,7 @@ enum { + OPENPIC_OUTPUT_INT = 0, /* IRQ */ + OPENPIC_OUTPUT_CINT, /* critical IRQ */ + OPENPIC_OUTPUT_MCK, /* Machine check event */ +- OPENPIC_OUTPUT_DEBUG, /* Inconditional debug event */ ++ OPENPIC_OUTPUT_DEBUG, /* Unconditional debug event */ + OPENPIC_OUTPUT_RESET, /* Core reset event */ + OPENPIC_OUTPUT_NB, + }; +diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h +index ee7504b976..316b80318e 100644 +--- a/include/hw/ppc/spapr.h ++++ b/include/hw/ppc/spapr.h +@@ -179,7 +179,7 @@ struct SpaprMachineState { + SpaprResizeHpt resize_hpt; + void *htab; + uint32_t htab_shift; +- uint64_t patb_entry; /* Process tbl registed in H_REGISTER_PROC_TBL */ ++ uint64_t patb_entry; /* Process tbl registered in H_REGISTER_PROC_TBL */ + SpaprPendingHpt *pending_hpt; /* in-progress resize */ + + hwaddr rma_size; +diff --git a/target/ppc/cpu-models.h b/target/ppc/cpu-models.h +index 0952592759..75ea085bd5 100644 +--- a/target/ppc/cpu-models.h ++++ b/target/ppc/cpu-models.h +@@ -63,7 +63,7 @@ enum { + /* PowerPC 405 cores */ + CPU_POWERPC_405D2 = 0x20010000, + CPU_POWERPC_405D4 = 0x41810000, +- /* PowerPC 405 microcontrolers */ ++ /* PowerPC 405 microcontrollers */ + /* XXX: missing 0x200108a0 */ + CPU_POWERPC_405CRa = 0x40110041, + CPU_POWERPC_405CRb = 0x401100C5, +@@ -93,7 +93,7 @@ enum { + #define CPU_POWERPC_440 CPU_POWERPC_440GXf + /* PowerPC 440 cores */ + CPU_POWERPC_440_XILINX = 0x7ff21910, +- /* PowerPC 440 microcontrolers */ ++ /* PowerPC 440 microcontrollers */ + CPU_POWERPC_440EPa = 0x42221850, + CPU_POWERPC_440EPb = 0x422218D3, + CPU_POWERPC_440GPb = 0x40120440, +diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h +index e946da5f3a..26312f9d5f 100644 +--- a/target/ppc/cpu.h ++++ b/target/ppc/cpu.h +@@ -345,7 +345,7 @@ typedef struct ppc_v3_pate_t { + + /* PMU bits */ + #define MMCR0_FC PPC_BIT(32) /* Freeze Counters */ +-#define MMCR0_PMAO PPC_BIT(56) /* Perf Monitor Alert Ocurred */ ++#define MMCR0_PMAO PPC_BIT(56) /* Perf Monitor Alert Occurred */ + #define MMCR0_PMAE PPC_BIT(37) /* Perf Monitor Alert Enable */ + #define MMCR0_EBE PPC_BIT(43) /* Perf Monitor EBB Enable */ + #define MMCR0_FCECE PPC_BIT(38) /* FC on Enabled Cond or Event */ +diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c +index 6695985e9b..986d16a24d 100644 +--- a/target/ppc/cpu_init.c ++++ b/target/ppc/cpu_init.c +@@ -7023,7 +7023,7 @@ static void register_970_lpar_sprs(CPUPPCState *env) + static void register_power5p_lpar_sprs(CPUPPCState *env) + { + #if !defined(CONFIG_USER_ONLY) +- /* Logical partitionning */ ++ /* Logical partitioning */ + spr_register_kvm_hv(env, SPR_LPCR, "LPCR", + SPR_NOACCESS, SPR_NOACCESS, + SPR_NOACCESS, SPR_NOACCESS, +diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c +index 17607adbe4..f66063d55c 100644 +--- a/target/ppc/excp_helper.c ++++ b/target/ppc/excp_helper.c +@@ -312,7 +312,7 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) + + /* + * new interrupt handler msr preserves existing HV and ME unless +- * explicitly overriden ++ * explicitly overridden + */ + new_msr = env->msr & (((target_ulong)1 << MSR_ME) | MSR_HVB); + +diff --git a/target/ppc/power8-pmu-regs.c.inc b/target/ppc/power8-pmu-regs.c.inc +index 7391851238..c58874752b 100644 +--- a/target/ppc/power8-pmu-regs.c.inc ++++ b/target/ppc/power8-pmu-regs.c.inc +@@ -16,7 +16,7 @@ + * Checks whether the Group A SPR (MMCR0, MMCR2, MMCRA, and the + * PMCs) has problem state read access. + * +- * Read acccess is granted for all PMCC values but 0b01, where a ++ * Read access is granted for all PMCC values but 0b01, where a + * Facility Unavailable Interrupt will occur. + */ + static bool spr_groupA_read_allowed(DisasContext *ctx) +@@ -33,7 +33,7 @@ static bool spr_groupA_read_allowed(DisasContext *ctx) + * Checks whether the Group A SPR (MMCR0, MMCR2, MMCRA, and the + * PMCs) has problem state write access. + * +- * Write acccess is granted for PMCC values 0b10 and 0b11. Userspace ++ * Write access is granted for PMCC values 0b10 and 0b11. Userspace + * writing with PMCC 0b00 will generate a Hypervisor Emulation + * Assistance Interrupt. Userspace writing with PMCC 0b01 will + * generate a Facility Unavailable Interrupt. +diff --git a/target/ppc/translate/vmx-impl.c.inc b/target/ppc/translate/vmx-impl.c.inc +index 8eb8d3a067..f56f061d18 100644 +--- a/target/ppc/translate/vmx-impl.c.inc ++++ b/target/ppc/translate/vmx-impl.c.inc +@@ -127,7 +127,7 @@ static void gen_stve##name(DisasContext *ctx) \ + } + + GEN_VR_LDX(lvx, 0x07, 0x03); +-/* As we don't emulate the cache, lvxl is stricly equivalent to lvx */ ++/* As we don't emulate the cache, lvxl is strictly equivalent to lvx */ + GEN_VR_LDX(lvxl, 0x07, 0x0B); + + GEN_VR_LVE(bx, 0x07, 0x00, 1); +@@ -135,7 +135,7 @@ GEN_VR_LVE(hx, 0x07, 0x01, 2); + GEN_VR_LVE(wx, 0x07, 0x02, 4); + + GEN_VR_STX(svx, 0x07, 0x07); +-/* As we don't emulate the cache, stvxl is stricly equivalent to stvx */ ++/* As we don't emulate the cache, stvxl is strictly equivalent to stvx */ + GEN_VR_STX(svxl, 0x07, 0x0F); + + GEN_VR_STVE(bx, 0x07, 0x04, 1); +-- +2.27.0 + diff --git a/qemu.spec b/qemu.spec index bc9d629c..d773e3a6 100644 --- a/qemu.spec +++ b/qemu.spec @@ -3,7 +3,7 @@ Name: qemu Version: 6.2.0 -Release: 86 +Release: 87 Epoch: 10 Summary: QEMU is a generic and open source machine emulator and virtualizer License: GPLv2 and BSD and MIT and CC-BY-SA-4.0 @@ -832,6 +832,31 @@ Patch0817: vhost-implement-migration-state-notifier-for-vdpa-de.patch Patch0818: vhost-implement-post-resume-bh.patch Patch0819: vdpa-implement-vdpa-device-migration.patch Patch0820: vdpa-move-memory-listener-to-the-realize-stage.patch +Patch0821: hw-usb-hcd-xhci.c-spelling-tranfer.patch +Patch0822: ui-vnc-clipboard-fix-inflate_buffer.patch +Patch0823: i386-sev-Avoid-SEV-ES-crash-due-to-missing-MSR_EFER_.patch +Patch0824: tests-avocado-mark-ReplayKernelNormal.test_mips64el_.patch +Patch0825: tests-unit-fix-a-Wformat-truncation-warning.patch +Patch0826: hw-qdev-Cosmetic-around-documentation.patch +Patch0827: pci-Export-the-pci_intx-function.patch +Patch0828: pcie_aer-Don-t-trigger-a-LSI-if-none-are-defined.patch +Patch0829: hw-i386-pc-Add-missing-property-descriptions.patch +Patch0830: hw-scsi-vhost-scsi-don-t-leak-vqs-on-error.patch +Patch0831: virtio-vhost-vsock-don-t-double-close-vhostfd-remove.patch +Patch0832: hw-scsi-vhost-scsi-don-t-double-close-vhostfd-on-err.patch +Patch0833: ppc-spelling-fixes.patch +Patch0834: s390x-Fix-spelling-errors.patch +Patch0835: migration-fix-RAMBlock-add-NULL-check.patch +Patch0836: iotests-fix-default-machine-type-detection.patch +Patch0837: gdb-xml-fix-duplicate-register-in-arm-neon.xml.patch +Patch0838: migration-Set-downtime_start-even-for-postcopy.patch +Patch0839: revert-tcg-loongarch64-Fix-tcg_out_mov-Aborted.patch +Patch0840: shadow_dev-introduce-shadow-dev-for-virtio-net-devic.patch +Patch0841: vdpa-set-vring-enable-only-if-the-vring-address-has-.patch +Patch0842: vdpa-correct-param-passed-in-when-unregister-save.patch +Patch0843: vdpa-support-vdpa-device-suspend-resume.patch +Patch0844: vdpa-don-t-suspend-resume-device-when-vdpa-device-no.patch +Patch0845: vdpa-suspend-function-return-0-when-the-vdpa-device-.patch BuildRequires: flex @@ -1431,6 +1456,33 @@ getent passwd qemu >/dev/null || \ %endif %changelog +* Fri Dec 22 2023 - 10:6.2.0-87 +- vdpa: suspend function return 0 when the vdpa device is stopped +- vdpa: don't suspend/resume device when vdpa device not started +- vdpa: support vdpa device suspend/resume +- vdpa: correct param passed in when unregister save +- vdpa: set vring enable only if the vring address has already been set +- shadow_dev: introduce shadow dev for virtio-net device +- revert "tcg/loongarch64: Fix tcg_out_mov() Aborted" +- migration: Set downtime_start even for postcopy +- gdb-xml: fix duplicate register in arm-neon.xml +- iotests: fix default machine type detection +- migration: fix RAMBlock add NULL check +- s390x: Fix spelling errors +- ppc: spelling fixes +- hw/scsi/vhost-scsi: don't double close vhostfd on error +- virtio/vhost-vsock: don't double close vhostfd, remove redundant cleanup +- hw/scsi/vhost-scsi: don't leak vqs on error +- hw/i386/pc: Add missing property descriptions +- pcie_aer: Don't trigger a LSI if none are defined +- pci: Export the pci_intx() function +- hw/qdev: Cosmetic around documentation +- tests/unit: fix a -Wformat-truncation warning +- tests/avocado: mark ReplayKernelNormal.test_mips64el_malta as flaky +- i386/sev: Avoid SEV-ES crash due to missing MSR_EFER_LMA bit +- ui/vnc-clipboard: fix inflate_buffer +- hw/usb/hcd-xhci.c: spelling: tranfer + * Tue Dec 5 2023 - 10:6.2.0-86 - vdpa: move memory listener to the realize stage - vdpa: implement vdpa device migration diff --git a/revert-tcg-loongarch64-Fix-tcg_out_mov-Aborted.patch b/revert-tcg-loongarch64-Fix-tcg_out_mov-Aborted.patch new file mode 100644 index 00000000..cf0869e4 --- /dev/null +++ b/revert-tcg-loongarch64-Fix-tcg_out_mov-Aborted.patch @@ -0,0 +1,30 @@ +From 7eff40be327d0c591e4b842cd954ec5dabb75848 Mon Sep 17 00:00:00 2001 +From: xianglai li +Date: Tue, 19 Dec 2023 02:34:39 -0500 +Subject: [PATCH] revert "tcg/loongarch64: Fix tcg_out_mov() Aborted" + +openEuler loongarch64 does not support qemu tcg, +so no TCG-related patch is required for synchronization. + +Signed-off-by: xianglai li +--- + tcg/loongarch64/tcg-target.c.inc | 3 --- + 1 file changed, 3 deletions(-) + +diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc +index ee7d4d728d..0b28b30002 100644 +--- a/tcg/loongarch64/tcg-target.c.inc ++++ b/tcg/loongarch64/tcg-target.c.inc +@@ -255,9 +255,6 @@ static bool tcg_out_mov(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg) + */ + tcg_out_opc_or(s, ret, arg, TCG_REG_ZERO); + break; +- case TCG_TYPE_V128: +- tcg_out_opc_vori_b(s, ret, arg, 0); +- break; + default: + g_assert_not_reached(); + } +-- +2.27.0 + diff --git a/s390x-Fix-spelling-errors.patch b/s390x-Fix-spelling-errors.patch new file mode 100644 index 00000000..19265710 --- /dev/null +++ b/s390x-Fix-spelling-errors.patch @@ -0,0 +1,246 @@ +From 8f9bdcfe073479ba0170d3b01023d9a00f3b1e31 Mon Sep 17 00:00:00 2001 +From: zhujun2 +Date: Thu, 7 Dec 2023 17:47:34 -0800 +Subject: [PATCH] s390x: Fix spelling errors + +mainline inclusion +commit 44ee69ea16bd0390082ed88d4e82d6cea3a18b46 +category: bugfix + +--------------------------------------------------------------- + +Fix typos (discovered with the 'codespell' utility). +Note: Though "migrateable" still seems to be a valid spelling, we change +it to "migratable" since this is the way more common spelling here. + +Message-Id: <20221111182828.282251-1-thuth@redhat.com> +Reviewed-by: Stefan Weil +Reviewed-by: Ilya Leoshkevich +Signed-off-by: Thomas Huth +Signed-off-by: zhujun2 +--- + hw/s390x/ipl.h | 2 +- + hw/s390x/s390-virtio-ccw.c | 6 +++--- + pc-bios/s390-ccw/cio.h | 2 +- + pc-bios/s390-ccw/iplb.h | 2 +- + pc-bios/s390-ccw/start.S | 2 +- + target/s390x/cpu_models.h | 4 ++-- + target/s390x/ioinst.c | 2 +- + target/s390x/tcg/excp_helper.c | 2 +- + target/s390x/tcg/fpu_helper.c | 2 +- + target/s390x/tcg/misc_helper.c | 2 +- + target/s390x/tcg/translate.c | 4 ++-- + target/s390x/tcg/translate_vx.c.inc | 6 +++--- + 12 files changed, 18 insertions(+), 18 deletions(-) + +diff --git a/hw/s390x/ipl.h b/hw/s390x/ipl.h +index dfc6dfd89c..7fc86e7905 100644 +--- a/hw/s390x/ipl.h ++++ b/hw/s390x/ipl.h +@@ -140,7 +140,7 @@ void s390_ipl_clear_reset_request(void); + * have an offset of 4 + n * 8 bytes within the struct in order + * to keep it double-word aligned. + * The total size of the struct must never exceed 28 bytes. +- * This definition must be kept in sync with the defininition ++ * This definition must be kept in sync with the definition + * in pc-bios/s390-ccw/iplb.h. + */ + struct QemuIplParameters { +diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c +index 653587ea62..c84b89ba43 100644 +--- a/hw/s390x/s390-virtio-ccw.c ++++ b/hw/s390x/s390-virtio-ccw.c +@@ -345,7 +345,7 @@ static int s390_machine_protect(S390CcwMachineState *ms) + } + + error_setg(&pv_mig_blocker, +- "protected VMs are currently not migrateable."); ++ "protected VMs are currently not migratable."); + rc = migrate_add_blocker(pv_mig_blocker, &local_err); + if (rc) { + ram_block_discard_disable(false); +@@ -434,7 +434,7 @@ static void s390_machine_reset(MachineState *machine) + break; + case S390_RESET_MODIFIED_CLEAR: + /* +- * Susbsystem reset needs to be done before we unshare memory ++ * Subsystem reset needs to be done before we unshare memory + * and lose access to VIRTIO structures in guest memory. + */ + subsystem_reset(); +@@ -447,7 +447,7 @@ static void s390_machine_reset(MachineState *machine) + break; + case S390_RESET_LOAD_NORMAL: + /* +- * Susbsystem reset needs to be done before we unshare memory ++ * Subsystem reset needs to be done before we unshare memory + * and lose access to VIRTIO structures in guest memory. + */ + subsystem_reset(); +diff --git a/pc-bios/s390-ccw/cio.h b/pc-bios/s390-ccw/cio.h +index 1e5d4e92e1..88a88adfd2 100644 +--- a/pc-bios/s390-ccw/cio.h ++++ b/pc-bios/s390-ccw/cio.h +@@ -20,7 +20,7 @@ struct pmcw { + __u32 intparm; /* interruption parameter */ + __u32 qf:1; /* qdio facility */ + __u32 w:1; +- __u32 isc:3; /* interruption sublass */ ++ __u32 isc:3; /* interruption subclass */ + __u32 res5:3; /* reserved zeros */ + __u32 ena:1; /* enabled */ + __u32 lm:2; /* limit mode */ +diff --git a/pc-bios/s390-ccw/iplb.h b/pc-bios/s390-ccw/iplb.h +index 772d5c57c9..cb6ac8a880 100644 +--- a/pc-bios/s390-ccw/iplb.h ++++ b/pc-bios/s390-ccw/iplb.h +@@ -81,7 +81,7 @@ extern IplParameterBlock iplb __attribute__((__aligned__(PAGE_SIZE))); + #define QIPL_FLAG_BM_OPTS_ZIPL 0x40 + + /* +- * This definition must be kept in sync with the defininition ++ * This definition must be kept in sync with the definition + * in hw/s390x/ipl.h + */ + struct QemuIplParameters { +diff --git a/pc-bios/s390-ccw/start.S b/pc-bios/s390-ccw/start.S +index 4d5ad21653..6072906df4 100644 +--- a/pc-bios/s390-ccw/start.S ++++ b/pc-bios/s390-ccw/start.S +@@ -19,7 +19,7 @@ _start: + larl %r2, __bss_start + larl %r3, _end + slgr %r3, %r2 /* get sizeof bss */ +- ltgr %r3,%r3 /* bss emtpy? */ ++ ltgr %r3,%r3 /* bss empty? */ + jz done + aghi %r3,-1 + srlg %r4,%r3,8 /* how many 256 byte chunks? */ +diff --git a/target/s390x/cpu_models.h b/target/s390x/cpu_models.h +index 74d1f87e4f..fb1adc8b21 100644 +--- a/target/s390x/cpu_models.h ++++ b/target/s390x/cpu_models.h +@@ -24,13 +24,13 @@ struct S390CPUDef { + uint8_t gen; /* hw generation identification */ + uint16_t type; /* cpu type identification */ + uint8_t ec_ga; /* EC GA version (on which also the BC is based) */ +- uint8_t mha_pow; /* Maximum Host Adress Power, mha = 2^pow-1 */ ++ uint8_t mha_pow; /* maximum host address power, mha = 2^pow-1 */ + uint32_t hmfai; /* hypervisor-managed facilities */ + /* base/min features, must never be changed between QEMU versions */ + S390FeatBitmap base_feat; + /* used to init base_feat from generated data */ + S390FeatInit base_init; +- /* deafault features, QEMU version specific */ ++ /* default features, QEMU version specific */ + S390FeatBitmap default_feat; + /* used to init default_feat from generated data */ + S390FeatInit default_init; +diff --git a/target/s390x/ioinst.c b/target/s390x/ioinst.c +index bdae5090bc..e6347d1801 100644 +--- a/target/s390x/ioinst.c ++++ b/target/s390x/ioinst.c +@@ -285,7 +285,7 @@ void ioinst_handle_stsch(S390CPU *cpu, uint64_t reg1, uint32_t ipb, + /* + * As operand exceptions have a lower priority than access exceptions, + * we check whether the memory area is writeable (injecting the +- * access execption if it is not) first. ++ * access exception if it is not) first. + */ + if (!s390_cpu_virt_mem_check_write(cpu, addr, ar, sizeof(schib))) { + s390_program_interrupt(env, PGM_OPERAND, ra); +diff --git a/target/s390x/tcg/excp_helper.c b/target/s390x/tcg/excp_helper.c +index 4e7648f301..6a4f7585b8 100644 +--- a/target/s390x/tcg/excp_helper.c ++++ b/target/s390x/tcg/excp_helper.c +@@ -551,7 +551,7 @@ try_deliver: + /* don't trigger a cpu_loop_exit(), use an interrupt instead */ + cpu_interrupt(CPU(cpu), CPU_INTERRUPT_HALT); + } else if (cs->halted) { +- /* unhalt if we had a WAIT PSW somehwere in our injection chain */ ++ /* unhalt if we had a WAIT PSW somewhere in our injection chain */ + s390_cpu_unhalt(cpu); + } + } +diff --git a/target/s390x/tcg/fpu_helper.c b/target/s390x/tcg/fpu_helper.c +index 4067205405..be80b2373c 100644 +--- a/target/s390x/tcg/fpu_helper.c ++++ b/target/s390x/tcg/fpu_helper.c +@@ -89,7 +89,7 @@ static void handle_exceptions(CPUS390XState *env, bool XxC, uintptr_t retaddr) + /* + * invalid/divbyzero cannot coexist with other conditions. + * overflow/underflow however can coexist with inexact, we have to +- * handle it separatly. ++ * handle it separately. + */ + if (s390_exc & ~S390_IEEE_MASK_INEXACT) { + if (s390_exc & ~S390_IEEE_MASK_INEXACT & env->fpc >> 24) { +diff --git a/target/s390x/tcg/misc_helper.c b/target/s390x/tcg/misc_helper.c +index aab9c47747..7a975aaf94 100644 +--- a/target/s390x/tcg/misc_helper.c ++++ b/target/s390x/tcg/misc_helper.c +@@ -326,7 +326,7 @@ uint32_t HELPER(stsi)(CPUS390XState *env, uint64_t a0, uint64_t r0, uint64_t r1) + /* same as machine type number in STORE CPU ID, but in EBCDIC */ + snprintf(type, ARRAY_SIZE(type), "%X", cpu->model->def->type); + ebcdic_put(sysib.sysib_111.type, type, 4); +- /* model number (not stored in STORE CPU ID for z/Architecure) */ ++ /* model number (not stored in STORE CPU ID for z/Architecture) */ + ebcdic_put(sysib.sysib_111.model, "QEMU ", 16); + ebcdic_put(sysib.sysib_111.sequence, "QEMU ", 16); + ebcdic_put(sysib.sysib_111.plant, "QEMU", 4); +diff --git a/target/s390x/tcg/translate.c b/target/s390x/tcg/translate.c +index dcc249a197..62fbc90d5e 100644 +--- a/target/s390x/tcg/translate.c ++++ b/target/s390x/tcg/translate.c +@@ -434,7 +434,7 @@ static void gen_program_exception(DisasContext *s, int code) + { + TCGv_i32 tmp; + +- /* Remember what pgm exeption this was. */ ++ /* Remember what pgm exception this was. */ + tmp = tcg_const_i32(code); + tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUS390XState, int_pgm_code)); + tcg_temp_free_i32(tmp); +@@ -490,7 +490,7 @@ static TCGv_i64 get_address(DisasContext *s, int x2, int b2, int d2) + + /* + * Note that d2 is limited to 20 bits, signed. If we crop negative +- * displacements early we create larger immedate addends. ++ * displacements early we create larger immediate addends. + */ + if (b2 && x2) { + tcg_gen_add_i64(tmp, regs[b2], regs[x2]); +diff --git a/target/s390x/tcg/translate_vx.c.inc b/target/s390x/tcg/translate_vx.c.inc +index 28bf5a23b6..d1fe4df1b5 100644 +--- a/target/s390x/tcg/translate_vx.c.inc ++++ b/target/s390x/tcg/translate_vx.c.inc +@@ -797,7 +797,7 @@ static DisasJumpType op_vpk(DisasContext *s, DisasOps *o) + } + break; + case 0x94: +- /* If sources and destination dont't overlap -> fast path */ ++ /* If sources and destination don't overlap -> fast path */ + if (v1 != v2 && v1 != v3) { + const uint8_t src_es = get_field(s, m4); + const uint8_t dst_es = src_es - 1; +@@ -1793,7 +1793,7 @@ static DisasJumpType op_vmsl(DisasContext *s, DisasOps *o) + l2 = tcg_temp_new_i64(); + h2 = tcg_temp_new_i64(); + +- /* Multipy both even elements from v2 and v3 */ ++ /* Multiply both even elements from v2 and v3 */ + read_vec_element_i64(l1, get_field(s, v2), 0, ES_64); + read_vec_element_i64(h1, get_field(s, v3), 0, ES_64); + tcg_gen_mulu2_i64(l1, h1, l1, h1); +@@ -1802,7 +1802,7 @@ static DisasJumpType op_vmsl(DisasContext *s, DisasOps *o) + tcg_gen_add2_i64(l1, h1, l1, h1, l1, h1); + } + +- /* Multipy both odd elements from v2 and v3 */ ++ /* Multiply both odd elements from v2 and v3 */ + read_vec_element_i64(l2, get_field(s, v2), 1, ES_64); + read_vec_element_i64(h2, get_field(s, v3), 1, ES_64); + tcg_gen_mulu2_i64(l2, h2, l2, h2); +-- +2.27.0 + diff --git a/shadow_dev-introduce-shadow-dev-for-virtio-net-devic.patch b/shadow_dev-introduce-shadow-dev-for-virtio-net-devic.patch new file mode 100644 index 00000000..ef1164d6 --- /dev/null +++ b/shadow_dev-introduce-shadow-dev-for-virtio-net-devic.patch @@ -0,0 +1,195 @@ +From 0a6c08bd3a16543b8021c8b65a45f7ebb701a9aa Mon Sep 17 00:00:00 2001 +From: Dongxu Sun +Date: Fri, 15 Dec 2023 17:44:54 +0800 +Subject: [PATCH] shadow_dev: introduce shadow dev for virtio-net device + +for virtio net devices, create the shadow device for vlpi +bypass inject supported. + +Signed-off-by: Wang Haibin +Signed-off-by: Yu Zenghui +Signed-off-by: Chen Qun +Signed-off-by: KunKun Jiang +Signed-off-by: Dongxu Sun +--- + hw/virtio/virtio-pci.c | 32 ++++++++++++++++++++++++++ + include/sysemu/kvm.h | 5 +++++ + linux-headers/linux/kvm.h | 13 +++++++++++ + target/arm/kvm.c | 47 +++++++++++++++++++++++++++++++++++++++ + 4 files changed, 97 insertions(+) + +diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c +index 82706b8b32..6b45683280 100644 +--- a/hw/virtio/virtio-pci.c ++++ b/hw/virtio/virtio-pci.c +@@ -873,18 +873,44 @@ undo: + } + return ret; + } ++ ++#ifdef __aarch64__ ++int __attribute__((weak)) kvm_create_shadow_device(PCIDevice *dev) ++{ ++ return 0; ++} ++ ++int __attribute__((weak)) kvm_delete_shadow_device(PCIDevice *dev) ++{ ++ return 0; ++} ++#endif ++ + static int kvm_virtio_pci_vector_vq_use(VirtIOPCIProxy *proxy, int nvqs) + { + int queue_no; + int ret = 0; + VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); + ++#ifdef __aarch64__ ++ if (!strcmp(vdev->name, "virtio-net")) { ++ kvm_create_shadow_device(&proxy->pci_dev); ++ } ++#endif ++ + for (queue_no = 0; queue_no < nvqs; queue_no++) { + if (!virtio_queue_get_num(vdev, queue_no)) { + return -1; + } + ret = kvm_virtio_pci_vector_use_one(proxy, queue_no); + } ++ ++#ifdef __aarch64__ ++ if (!strcmp(vdev->name, "virtio-net") && ret != 0) { ++ kvm_delete_shadow_device(&proxy->pci_dev); ++ } ++#endif ++ + return ret; + } + +@@ -927,6 +953,12 @@ static void kvm_virtio_pci_vector_vq_release(VirtIOPCIProxy *proxy, int nvqs) + } + kvm_virtio_pci_vector_release_one(proxy, queue_no); + } ++ ++#ifdef __aarch64__ ++ if (!strcmp(vdev->name, "virtio-net")) { ++ kvm_delete_shadow_device(&proxy->pci_dev); ++ } ++#endif + } + + static void kvm_virtio_pci_vector_config_release(VirtIOPCIProxy *proxy) +diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h +index 1ec9432493..9f52d08ce0 100644 +--- a/include/sysemu/kvm.h ++++ b/include/sysemu/kvm.h +@@ -553,4 +553,9 @@ bool kvm_arch_cpu_check_are_resettable(void); + bool kvm_dirty_ring_enabled(void); + + uint32_t kvm_dirty_ring_size(void); ++ ++#ifdef __aarch64__ ++int kvm_create_shadow_device(PCIDevice *dev); ++int kvm_delete_shadow_device(PCIDevice *dev); ++#endif + #endif +diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h +index 2008fbc173..cd0885f523 100644 +--- a/linux-headers/linux/kvm.h ++++ b/linux-headers/linux/kvm.h +@@ -1127,6 +1127,8 @@ struct kvm_ppc_resize_hpt { + + #define KVM_CAP_ARM_CPU_FEATURE 555 + ++#define KVM_CAP_ARM_VIRT_MSI_BYPASS 799 ++ + #ifdef KVM_CAP_IRQ_ROUTING + + struct kvm_irq_routing_irqchip { +@@ -1431,6 +1433,17 @@ struct kvm_s390_ucas_mapping { + #define KVM_XEN_HVM_CONFIG _IOW(KVMIO, 0x7a, struct kvm_xen_hvm_config) + #define KVM_SET_CLOCK _IOW(KVMIO, 0x7b, struct kvm_clock_data) + #define KVM_GET_CLOCK _IOR(KVMIO, 0x7c, struct kvm_clock_data) ++ ++#ifdef __aarch64__ ++struct kvm_master_dev_info ++{ ++ __u32 nvectors; /* number of msi vectors */ ++ struct kvm_msi msi[0]; ++}; ++#define KVM_CREATE_SHADOW_DEV _IOW(KVMIO, 0xf0, struct kvm_master_dev_info) ++#define KVM_DEL_SHADOW_DEV _IOW(KVMIO, 0xf1, __u32) ++#endif ++ + /* Available with KVM_CAP_PIT_STATE2 */ + #define KVM_GET_PIT2 _IOR(KVMIO, 0x9f, struct kvm_pit_state2) + #define KVM_SET_PIT2 _IOW(KVMIO, 0xa0, struct kvm_pit_state2) +diff --git a/target/arm/kvm.c b/target/arm/kvm.c +index 22ac5bcb97..38d80adfb7 100644 +--- a/target/arm/kvm.c ++++ b/target/arm/kvm.c +@@ -27,6 +27,8 @@ + #include "trace.h" + #include "internals.h" + #include "hw/pci/pci.h" ++#include "hw/pci/msi.h" ++#include "hw/pci/msix.h" + #include "exec/memattrs.h" + #include "exec/address-spaces.h" + #include "hw/boards.h" +@@ -1075,6 +1077,51 @@ int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route, + return 0; + } + ++int kvm_create_shadow_device(PCIDevice *dev) ++{ ++ KVMState *s = kvm_state; ++ struct kvm_master_dev_info *mdi; ++ MSIMessage msg; ++ uint32_t vector, nvectors = msix_nr_vectors_allocated(dev); ++ uint32_t request_id; ++ int ret; ++ ++ if (!kvm_vm_check_extension(s, KVM_CAP_ARM_VIRT_MSI_BYPASS) || !nvectors) { ++ return 0; ++ } ++ ++ mdi = g_malloc0(sizeof(uint32_t) + sizeof(struct kvm_msi) * nvectors); ++ mdi->nvectors = nvectors; ++ request_id = pci_requester_id(dev); ++ ++ for (vector = 0; vector < nvectors; vector++) { ++ msg = msix_get_message(dev, vector); ++ mdi->msi[vector].address_lo = extract64(msg.address, 0, 32); ++ mdi->msi[vector].address_hi = extract64(msg.address, 32, 32); ++ mdi->msi[vector].data = le32_to_cpu(msg.data); ++ mdi->msi[vector].flags = KVM_MSI_VALID_DEVID; ++ mdi->msi[vector].devid = request_id; ++ memset(mdi->msi[vector].pad, 0, sizeof(mdi->msi[vector].pad)); ++ } ++ ++ ret = kvm_vm_ioctl(s, KVM_CREATE_SHADOW_DEV, mdi); ++ g_free(mdi); ++ return ret; ++} ++ ++int kvm_delete_shadow_device(PCIDevice *dev) ++{ ++ KVMState *s = kvm_state; ++ uint32_t request_id, nvectors = msix_nr_vectors_allocated(dev); ++ ++ if (!kvm_vm_check_extension(s, KVM_CAP_ARM_VIRT_MSI_BYPASS) || !nvectors) { ++ return 0; ++ } ++ ++ request_id = pci_requester_id(dev); ++ return kvm_vm_ioctl(s, KVM_DEL_SHADOW_DEV, &request_id); ++} ++ + int kvm_arch_add_msi_route_post(struct kvm_irq_routing_entry *route, + int vector, PCIDevice *dev) + { +-- +2.27.0 + diff --git a/tests-avocado-mark-ReplayKernelNormal.test_mips64el_.patch b/tests-avocado-mark-ReplayKernelNormal.test_mips64el_.patch new file mode 100644 index 00000000..bc8f81ae --- /dev/null +++ b/tests-avocado-mark-ReplayKernelNormal.test_mips64el_.patch @@ -0,0 +1,48 @@ +From b4d96f201027d930ef84c8751909f3770e3d21f9 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Alex=20Benn=C3=A9e?= +Date: Fri, 1 Dec 2023 20:10:27 +0000 +Subject: [PATCH] tests/avocado: mark ReplayKernelNormal.test_mips64el_malta as + flaky +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +I missed this when going through the recent failure logs. I can run +the test 30 times without failure locally but it seems to hang pretty +reliably on GitLab's CI infra-structure. + +Cc: Philippe Mathieu-Daudé +Signed-off-by: Alex Bennée +Reviewed-by: Philippe Mathieu-Daudé +Message-ID: <20231201201027.2689404-1-alex.bennee@linaro.org> +Signed-off-by: Philippe Mathieu-Daudé + +Signed-off-by: Zhongrui Tang +--- + tests/avocado/replay_kernel.py | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/tests/avocado/replay_kernel.py b/tests/avocado/replay_kernel.py +index c68a953730..16421b3407 100644 +--- a/tests/avocado/replay_kernel.py ++++ b/tests/avocado/replay_kernel.py +@@ -113,6 +113,8 @@ def test_mips_malta(self): + + self.run_rr(kernel_path, kernel_command_line, console_pattern, shift=5) + ++ # See https://gitlab.com/qemu-project/qemu/-/issues/2013 ++ @skipUnless(os.getenv('QEMU_TEST_FLAKY_TESTS'), 'Test is unstable on GitLab') + def test_mips64el_malta(self): + """ + This test requires the ar tool to extract "data.tar.gz" from +@@ -128,6 +130,7 @@ def test_mips64el_malta(self): + + :avocado: tags=arch:mips64el + :avocado: tags=machine:malta ++ :avocado: tags=flaky + """ + deb_url = ('http://snapshot.debian.org/archive/debian/' + '20130217T032700Z/pool/main/l/linux-2.6/' +-- +2.27.0 + diff --git a/tests-unit-fix-a-Wformat-truncation-warning.patch b/tests-unit-fix-a-Wformat-truncation-warning.patch new file mode 100644 index 00000000..40fb8d09 --- /dev/null +++ b/tests-unit-fix-a-Wformat-truncation-warning.patch @@ -0,0 +1,53 @@ +From 133b578fabea9f4cc5936da233c04463bf94b6db Mon Sep 17 00:00:00 2001 +From: boringandboring +Date: Thu, 7 Dec 2023 09:20:00 +0800 +Subject: [PATCH] tests/unit: fix a -Wformat-truncation warning +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +cherry picked from 6a54ac2a9737057dc19aa584d823a3011717423b + +../tests/test-qobject-input-visitor.c: In function ‘test_visitor_in_list’: +../tests/test-qobject-input-visitor.c:454:49: warning: ‘%d’ directive output may be truncated writing between 1 and 10 bytes into a region of size 6 [-Wformat-truncation=] + 454 | snprintf(string, sizeof(string), "string%d", i); + | ^~ +../tests/test-qobject-input-visitor.c:454:42: note: directive argument in the range [0, 2147483606] + 454 | snprintf(string, sizeof(string), "string%d", i); + | ^~~~~~~~~~ +../tests/test-qobject-input-visitor.c:454:9: note: ‘snprintf’ output between 8 and 17 bytes into a destination of size 12 + 454 | snprintf(string, sizeof(string), "string%d", i); + | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Rather than trying to be clever, since this is called 3 times during +tests, let's simply use g_strdup_printf(). + +Signed-off-by: Marc-André Lureau +Reviewed-by: Markus Armbruster +Message-id: 20220810121513.1356081-1-marcandre.lureau@redhat.com +Reviewed-by: Peter Maydell +[PMM: fixed commit message typos] +Signed-off-by: Peter Maydell +Signed-off-by: boringandboring +--- + tests/unit/test-qobject-input-visitor.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/tests/unit/test-qobject-input-visitor.c b/tests/unit/test-qobject-input-visitor.c +index 6f59a7f432..0f28d46a4a 100644 +--- a/tests/unit/test-qobject-input-visitor.c ++++ b/tests/unit/test-qobject-input-visitor.c +@@ -448,9 +448,8 @@ static void test_visitor_in_list(TestInputVisitorData *data, + g_assert(head != NULL); + + for (i = 0, item = head; item; item = item->next, i++) { +- char string[12]; ++ g_autofree char *string = g_strdup_printf("string%d", i); + +- snprintf(string, sizeof(string), "string%d", i); + g_assert_cmpstr(item->value->string, ==, string); + g_assert_cmpint(item->value->integer, ==, 42 + i); + } +-- +2.27.0 + diff --git a/ui-vnc-clipboard-fix-inflate_buffer.patch b/ui-vnc-clipboard-fix-inflate_buffer.patch new file mode 100644 index 00000000..f12ff9b4 --- /dev/null +++ b/ui-vnc-clipboard-fix-inflate_buffer.patch @@ -0,0 +1,47 @@ +From 7f19287be9b468b7065073a31d35c01b2632858d Mon Sep 17 00:00:00 2001 +From: qihao +Date: Tue, 5 Dec 2023 14:10:50 +0800 +Subject: [PATCH] ui/vnc-clipboard: fix inflate_buffer +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +cheery-pick from ebfbf394671163c14e2b24d98f3927a3151d1aff + +Commit d921fea338 ("ui/vnc-clipboard: fix infinite loop in +inflate_buffer (CVE-2023-3255)") removed this hunk, but it is still +required, because it can happen that stream.avail_in becomes zero +before coming across a return value of Z_STREAM_END in the loop. + +This fixes the host->guest direction of the clipboard with noVNC and +TigerVNC as clients. + +Fixes: d921fea338 ("ui/vnc-clipboard: fix infinite loop in inflate_buffer (CVE-2023-3255)") +Reported-by: Friedrich Weber +Signed-off-by: Fiona Ebner +Acked-by: Marc-André Lureau +Message-Id: <20231122125826.228189-1-f.ebner@proxmox.com> +Signed-off-by: qihao_yewu +--- + ui/vnc-clipboard.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/ui/vnc-clipboard.c b/ui/vnc-clipboard.c +index c84599cfdb..2bb1b07c40 100644 +--- a/ui/vnc-clipboard.c ++++ b/ui/vnc-clipboard.c +@@ -70,6 +70,11 @@ static uint8_t *inflate_buffer(uint8_t *in, uint32_t in_len, uint32_t *size) + } + } + ++ *size = stream.total_out; ++ inflateEnd(&stream); ++ ++ return out; ++ + err_end: + inflateEnd(&stream); + err: +-- +2.27.0 + diff --git a/vdpa-correct-param-passed-in-when-unregister-save.patch b/vdpa-correct-param-passed-in-when-unregister-save.patch new file mode 100644 index 00000000..3b7ce277 --- /dev/null +++ b/vdpa-correct-param-passed-in-when-unregister-save.patch @@ -0,0 +1,30 @@ +From 9f0b9d2d71b9fa21789981d68335ee417e18b025 Mon Sep 17 00:00:00 2001 +From: jiangdongxu +Date: Thu, 14 Dec 2023 11:22:54 +0800 +Subject: [PATCH] vdpa: correct param passed in when unregister save + +The idstr passed in the unregister_savevm function is inconsisten +with the idstr passed in when register_savevm_live registration. +Needs to be modified, otherwise migration will fail after hotunplug +all vdpa devices. + +Signed-off-by: jiangdongxu +--- + hw/virtio/vdpa-dev-mig.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/hw/virtio/vdpa-dev-mig.c b/hw/virtio/vdpa-dev-mig.c +index ee3e27f2bb..c71e71fd64 100644 +--- a/hw/virtio/vdpa-dev-mig.c ++++ b/hw/virtio/vdpa-dev-mig.c +@@ -400,6 +400,6 @@ void vdpa_migration_register(VhostVdpaDevice *vdev) + void vdpa_migration_unregister(VhostVdpaDevice *vdev) + { + remove_migration_state_change_notifier(&vdev->migration_state); +- unregister_savevm(VMSTATE_IF(&vdev->parent_obj.parent_obj), "vdpa", DEVICE(vdev)); ++ unregister_savevm(NULL, "vdpa", DEVICE(vdev)); + qemu_del_vm_change_state_handler(vdev->vmstate); + } +-- +2.27.0 + diff --git a/vdpa-don-t-suspend-resume-device-when-vdpa-device-no.patch b/vdpa-don-t-suspend-resume-device-when-vdpa-device-no.patch new file mode 100644 index 00000000..77e69328 --- /dev/null +++ b/vdpa-don-t-suspend-resume-device-when-vdpa-device-no.patch @@ -0,0 +1,67 @@ +From daab4fa364c508d793ed28a920d50cd76efe7633 Mon Sep 17 00:00:00 2001 +From: jiangdongxu +Date: Tue, 19 Dec 2023 20:32:00 +0800 +Subject: [PATCH] vdpa: don't suspend/resume device when vdpa device not + started + +When vdpa device not started, we don't need to suspend vdpa device +and send vdpa device state information. Therefore, add the suspended +flag of vdpa device to distinguish whether the device is suspended and +use it to determine whether the device needs to resume in dest qemu. + +Signed-off-by: jiangdongxu +--- + hw/virtio/vdpa-dev-mig.c | 23 +++++++++++++++-------- + 1 file changed, 15 insertions(+), 8 deletions(-) + +diff --git a/hw/virtio/vdpa-dev-mig.c b/hw/virtio/vdpa-dev-mig.c +index 4a45821892..9cd80f92eb 100644 +--- a/hw/virtio/vdpa-dev-mig.c ++++ b/hw/virtio/vdpa-dev-mig.c +@@ -296,10 +296,13 @@ static int vdpa_save_complete_precopy(QEMUFile *f, void *opaque) + int ret; + + qemu_put_be64(f, VDPA_MIG_FLAG_DEV_CONFIG_STATE); +- ret = vhost_vdpa_dev_buffer_save(hdev, f); +- if (ret) { +- error_report("Save vdpa device buffer failed: %d\n", ret); +- return ret; ++ qemu_put_be16(f, (uint16_t)vdev->suspended); ++ if (vdev->suspended) { ++ ret = vhost_vdpa_dev_buffer_save(hdev, f); ++ if (ret) { ++ error_report("Save vdpa device buffer failed: %d\n", ret); ++ return ret; ++ } + } + qemu_put_be64(f, VDPA_MIG_FLAG_END_OF_STATE); + +@@ -313,6 +316,7 @@ static int vdpa_load_state(QEMUFile *f, void *opaque, int version_id) + + int ret; + uint64_t data; ++ uint16_t suspended; + + data = qemu_get_be64(f); + while (data != VDPA_MIG_FLAG_END_OF_STATE) { +@@ -325,10 +329,13 @@ static int vdpa_load_state(QEMUFile *f, void *opaque, int version_id) + return -EINVAL; + } + } else if (data == VDPA_MIG_FLAG_DEV_CONFIG_STATE) { +- ret = vhost_vdpa_dev_buffer_load(hdev, f); +- if (ret) { +- error_report("fail to restore device buffer.\n"); +- return ret; ++ suspended = qemu_get_be16(f); ++ if (suspended) { ++ ret = vhost_vdpa_dev_buffer_load(hdev, f); ++ if (ret) { ++ error_report("fail to restore device buffer.\n"); ++ return ret; ++ } + } + } + +-- +2.27.0 + diff --git a/vdpa-set-vring-enable-only-if-the-vring-address-has-.patch b/vdpa-set-vring-enable-only-if-the-vring-address-has-.patch new file mode 100644 index 00000000..f3bc7b5c --- /dev/null +++ b/vdpa-set-vring-enable-only-if-the-vring-address-has-.patch @@ -0,0 +1,44 @@ +From 11c0e08a95c35adec07e3b40d1bd9452d7113236 Mon Sep 17 00:00:00 2001 +From: jiangdongxu +Date: Thu, 14 Dec 2023 11:05:52 +0800 +Subject: [PATCH] vdpa: set vring enable only if the vring address has already + been set + +Currently, vhost-vdpa does not determine the status of each vring when +performing the enable operation on vring. When the vBIOS(EDK2) is running, +the driver will not enable all vrings. In this case, setting all vrings +to enable is isconsistent with the actual situation. + +Add logic when enabling vring, make a judement on the vring status. If the +vring address is not set, the vring will not enabled. + +Signed-off-by: jiangdongxu +--- + hw/virtio/vhost-vdpa.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c +index c7aaff7f20..36ed0c9a99 100644 +--- a/hw/virtio/vhost-vdpa.c ++++ b/hw/virtio/vhost-vdpa.c +@@ -714,8 +714,17 @@ static int vhost_vdpa_get_vq_index(struct vhost_dev *dev, int idx) + static int vhost_vdpa_set_vring_ready(struct vhost_dev *dev) + { + int i; ++ int idx; ++ hwaddr addr; ++ + trace_vhost_vdpa_set_vring_ready(dev); + for (i = 0; i < dev->nvqs; ++i) { ++ idx = vhost_vdpa_get_vq_index(dev, dev->vq_index + i); ++ addr = virtio_queue_get_desc_addr(dev->vdev, idx); ++ if (addr == 0) { ++ continue; ++ } ++ + struct vhost_vring_state state = { + .index = dev->vq_index + i, + .num = 1, +-- +2.27.0 + diff --git a/vdpa-support-vdpa-device-suspend-resume.patch b/vdpa-support-vdpa-device-suspend-resume.patch new file mode 100644 index 00000000..2c94e7a3 --- /dev/null +++ b/vdpa-support-vdpa-device-suspend-resume.patch @@ -0,0 +1,119 @@ +From 06bb2d68ef70813167a633aa00779acf61c784b0 Mon Sep 17 00:00:00 2001 +From: jiangdongxu +Date: Tue, 19 Dec 2023 20:18:03 +0800 +Subject: [PATCH] vdpa: support vdpa device suspend/resume + +commit a21603f7ecfa 'vhost: implement vhost_vdpa_device_suspend/resume' +only implement suspend and resume interface used for migration. The +current implementation still has bugs when suspend/resume a virtual +machine. Fix it. + +Signed-off-by: jiangdongxu +--- + hw/virtio/vdpa-dev-mig.c | 16 +++++++++++----- + hw/virtio/vdpa-dev.c | 8 +------- + include/hw/virtio/vdpa-dev.h | 1 + + 3 files changed, 13 insertions(+), 12 deletions(-) + +diff --git a/hw/virtio/vdpa-dev-mig.c b/hw/virtio/vdpa-dev-mig.c +index c71e71fd64..4a45821892 100644 +--- a/hw/virtio/vdpa-dev-mig.c ++++ b/hw/virtio/vdpa-dev-mig.c +@@ -149,6 +149,7 @@ static int vhost_vdpa_device_suspend(VhostVdpaDevice *vdpa) + } + + vdpa->started = false; ++ vdpa->suspended = true; + + ret = vhost_dev_suspend(&vdpa->dev, vdev, false); + if (ret) { +@@ -171,6 +172,7 @@ set_guest_notifiers_fail: + } + + suspend_fail: ++ vdpa->suspended = false; + vdpa->started = true; + return ret; + } +@@ -207,6 +209,7 @@ static int vhost_vdpa_device_resume(VhostVdpaDevice *vdpa) + goto err_guest_notifiers; + } + vdpa->started = true; ++ vdpa->suspended = false; + + /* + * guest_notifier_mask/pending not used yet, so just unmask +@@ -247,7 +250,7 @@ static void vdpa_dev_vmstate_change(void *opaque, bool running, RunState state) + MigrationIncomingState *mis = migration_incoming_get_current(); + + if (!running) { +- if (ms->state == RUN_STATE_PAUSED) { ++ if (ms->state == MIGRATION_STATUS_ACTIVE || state == RUN_STATE_PAUSED) { + ret = vhost_vdpa_device_suspend(vdpa); + if (ret) { + error_report("suspend vdpa device failed: %d\n", ret); +@@ -257,16 +260,19 @@ static void vdpa_dev_vmstate_change(void *opaque, bool running, RunState state) + } + } + } else { +- if (ms->state == RUN_STATE_RESTORE_VM) { ++ if (vdpa->suspended) { + ret = vhost_vdpa_device_resume(vdpa); + if (ret) { +- error_report("migration dest resume device failed, abort!\n"); +- exit(EXIT_FAILURE); ++ error_report("vhost vdpa device resume failed: %d\n", ret); + } + } + + if (mis->state == RUN_STATE_RESTORE_VM) { +- vhost_vdpa_call(hdev, VHOST_VDPA_RESUME, NULL); ++ ret = vhost_vdpa_call(hdev, VHOST_VDPA_RESUME, NULL); ++ if (ret) { ++ error_report("migration dest resume device failed: %d\n", ret); ++ exit(EXIT_FAILURE); ++ } + /* post resume */ + mis->bh = qemu_bh_new(vdpa_dev_migration_handle_incoming_bh, + hdev); +diff --git a/hw/virtio/vdpa-dev.c b/hw/virtio/vdpa-dev.c +index 143dadc88d..04d8e96a5d 100644 +--- a/hw/virtio/vdpa-dev.c ++++ b/hw/virtio/vdpa-dev.c +@@ -315,7 +315,6 @@ static void vhost_vdpa_device_stop(VirtIODevice *vdev) + static void vhost_vdpa_device_set_status(VirtIODevice *vdev, uint8_t status) + { + VhostVdpaDevice *s = VHOST_VDPA_DEVICE(vdev); +- MigrationState *ms = migrate_get_current(); + bool should_start = virtio_device_started(vdev, status); + Error *local_err = NULL; + int ret; +@@ -324,12 +323,7 @@ static void vhost_vdpa_device_set_status(VirtIODevice *vdev, uint8_t status) + should_start = false; + } + +- if (s->started == should_start) { +- return; +- } +- +- if (ms->state == RUN_STATE_PAUSED || +- ms->state == RUN_STATE_RESTORE_VM) { ++ if (s->started == should_start || s->suspended) { + return; + } + +diff --git a/include/hw/virtio/vdpa-dev.h b/include/hw/virtio/vdpa-dev.h +index 20f50c76c6..60e9c3f3fe 100644 +--- a/include/hw/virtio/vdpa-dev.h ++++ b/include/hw/virtio/vdpa-dev.h +@@ -37,6 +37,7 @@ struct VhostVdpaDevice { + int config_size; + uint16_t queue_size; + bool started; ++ bool suspended; + int (*post_init)(VhostVdpaDevice *v, Error **errp); + VMChangeStateEntry *vmstate; + Notifier migration_state; +-- +2.27.0 + diff --git a/vdpa-suspend-function-return-0-when-the-vdpa-device-.patch b/vdpa-suspend-function-return-0-when-the-vdpa-device-.patch new file mode 100644 index 00000000..2c3c44a1 --- /dev/null +++ b/vdpa-suspend-function-return-0-when-the-vdpa-device-.patch @@ -0,0 +1,45 @@ +From bd3f62a0df7be244dcd7dab0632883354c476f17 Mon Sep 17 00:00:00 2001 +From: jiangdongxu +Date: Thu, 21 Dec 2023 11:03:37 +0800 +Subject: [PATCH] vdpa: suspend function return 0 when the vdpa device is + stopped + +When vhost vdpa device is stopped(vdpa->started is false), suspend +operation do nothing and return success, instead of return failure. + +The same goes for resume function. + +Signed-off-by: jiangdongxu +--- + hw/virtio/vdpa-dev-mig.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/hw/virtio/vdpa-dev-mig.c b/hw/virtio/vdpa-dev-mig.c +index 9cd80f92eb..679d37b182 100644 +--- a/hw/virtio/vdpa-dev-mig.c ++++ b/hw/virtio/vdpa-dev-mig.c +@@ -140,8 +140,8 @@ static int vhost_vdpa_device_suspend(VhostVdpaDevice *vdpa) + VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus); + int ret; + +- if (!vdpa->started) { +- return -EFAULT; ++ if (!vdpa->started || vdpa->suspended) { ++ return 0; + } + + if (!k->set_guest_notifiers) { +@@ -184,6 +184,10 @@ static int vhost_vdpa_device_resume(VhostVdpaDevice *vdpa) + VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus); + int i, ret; + ++ if (vdpa->started || !vdpa->suspended) { ++ return 0; ++ } ++ + if (!k->set_guest_notifiers) { + error_report("binding does not support guest notifiers\n"); + return -ENOSYS; +-- +2.27.0 + diff --git a/virtio-vhost-vsock-don-t-double-close-vhostfd-remove.patch b/virtio-vhost-vsock-don-t-double-close-vhostfd-remove.patch new file mode 100644 index 00000000..b554e7a1 --- /dev/null +++ b/virtio-vhost-vsock-don-t-double-close-vhostfd-remove.patch @@ -0,0 +1,57 @@ +From 1d888e71517be4a0793b5a03b4a2234c55953c8f Mon Sep 17 00:00:00 2001 +From: boringandboring +Date: Fri, 8 Dec 2023 10:02:51 +0800 +Subject: [PATCH] virtio/vhost-vsock: don't double close vhostfd, remove + redundant cleanup + +cherry picked from d731ab31196579144457c7f2fa3649338bfb21f2 + +In case of an error during initialization in vhost_dev_init, vhostfd is +closed in vhost_dev_cleanup. Remove close from err_virtio as it's both +redundant and causes a double close on vhostfd. + +Signed-off-by: Daniil Tatianin +Message-Id: <20211129125204.1108088-1-d-tatianin@yandex-team.ru> +Reviewed-by: Stefano Garzarella +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Signed-off-by: boringandboring +--- + hw/virtio/vhost-vsock.c | 11 +++++------ + 1 file changed, 5 insertions(+), 6 deletions(-) + +diff --git a/hw/virtio/vhost-vsock.c b/hw/virtio/vhost-vsock.c +index 478c0c9a87..433d42d897 100644 +--- a/hw/virtio/vhost-vsock.c ++++ b/hw/virtio/vhost-vsock.c +@@ -171,6 +171,10 @@ static void vhost_vsock_device_realize(DeviceState *dev, Error **errp) + ret = vhost_dev_init(&vvc->vhost_dev, (void *)(uintptr_t)vhostfd, + VHOST_BACKEND_TYPE_KERNEL, 0, errp); + if (ret < 0) { ++ /* ++ * vhostfd is closed by vhost_dev_cleanup, which is called ++ * by vhost_dev_init on initialization error. ++ */ + goto err_virtio; + } + +@@ -183,15 +187,10 @@ static void vhost_vsock_device_realize(DeviceState *dev, Error **errp) + return; + + err_vhost_dev: +- vhost_dev_cleanup(&vvc->vhost_dev); + /* vhost_dev_cleanup() closes the vhostfd passed to vhost_dev_init() */ +- vhostfd = -1; ++ vhost_dev_cleanup(&vvc->vhost_dev); + err_virtio: + vhost_vsock_common_unrealize(vdev); +- if (vhostfd >= 0) { +- close(vhostfd); +- } +- return; + } + + static void vhost_vsock_device_unrealize(DeviceState *dev) +-- +2.27.0 + -- Gitee From 2b6068aae3fe18cd0c948c22b4531b344c3e2b6c Mon Sep 17 00:00:00 2001 From: Jiabo Feng Date: Wed, 21 Feb 2024 09:42:29 +0800 Subject: [PATCH 05/19] QEMU update to version 6.2.0-88 - ui/vnc.c: Fixed a deadlock bug. - hw/i386: Fix comment style in topology.h - migration/multifd: Remove unnecessary usage of local Error - linux-user: fix sockaddr_in6 endianness - vhost_vdpa: fix the input in trace_vhost_vdpa_listener_region_del() - iotests: fix 194: filter out racy postcopy-active event - tests/avocado: fix waiting for vm shutdown in replay_linux - ui/vnc: fix debug output for invalid audio message Signed-off-by: Jiabo Feng --- hw-i386-Fix-comment-style-in-topology.h.patch | 145 ++++++++++++++++++ ...filter-out-racy-postcopy-active-even.patch | 55 +++++++ linux-user-fix-sockaddr_in6-endianness.patch | 42 +++++ ...d-Remove-unnecessary-usage-of-local-.patch | 61 ++++++++ qemu.spec | 21 ++- ...x-waiting-for-vm-shutdown-in-replay_.patch | 35 +++++ ...bug-output-for-invalid-audio-message.patch | 36 +++++ ui-vnc.c-Fixed-a-deadlock-bug.patch | 71 +++++++++ ...he-input-in-trace_vhost_vdpa_listene.patch | 37 +++++ 9 files changed, 501 insertions(+), 2 deletions(-) create mode 100644 hw-i386-Fix-comment-style-in-topology.h.patch create mode 100644 iotests-fix-194-filter-out-racy-postcopy-active-even.patch create mode 100644 linux-user-fix-sockaddr_in6-endianness.patch create mode 100644 migration-multifd-Remove-unnecessary-usage-of-local-.patch create mode 100644 tests-avocado-fix-waiting-for-vm-shutdown-in-replay_.patch create mode 100644 ui-vnc-fix-debug-output-for-invalid-audio-message.patch create mode 100644 ui-vnc.c-Fixed-a-deadlock-bug.patch create mode 100644 vhost_vdpa-fix-the-input-in-trace_vhost_vdpa_listene.patch diff --git a/hw-i386-Fix-comment-style-in-topology.h.patch b/hw-i386-Fix-comment-style-in-topology.h.patch new file mode 100644 index 00000000..562fda12 --- /dev/null +++ b/hw-i386-Fix-comment-style-in-topology.h.patch @@ -0,0 +1,145 @@ +From 92bf314bb73b4df9b94e68448c37a8bbeed7ae65 Mon Sep 17 00:00:00 2001 +From: Zhao Liu +Date: Tue, 24 Oct 2023 17:03:04 +0800 +Subject: [PATCH] hw/i386: Fix comment style in topology.h +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +mainline inclusion +commit 5f0d69b5a69f56d63a1afd5f927919b1584e5e9b +category: bugfix + +--------------------------------------------------------------- + +For function comments in this file, keep the comment style consistent +with other files in the directory. + +Signed-off-by: Zhao Liu +Reviewed-by: Philippe Mathieu-Daudé +Reviewed-by: Yanan Wang +Reviewed-by: Xiaoyao Li +Reviewed-by: Babu Moger +Tested-by: Babu Moger +Tested-by: Yongwei Ma +Acked-by: Michael S. Tsirkin +Message-ID: <20231024090323.1859210-2-zhao1.liu@linux.intel.com> +Signed-off-by: Philippe Mathieu-Daudé +Signed-off-by: zhujun2 +--- + include/hw/i386/topology.h | 33 +++++++++++++++++---------------- + 1 file changed, 17 insertions(+), 16 deletions(-) + +diff --git a/include/hw/i386/topology.h b/include/hw/i386/topology.h +index 81573f6cfd..5a19679f61 100644 +--- a/include/hw/i386/topology.h ++++ b/include/hw/i386/topology.h +@@ -24,7 +24,8 @@ + #ifndef HW_I386_TOPOLOGY_H + #define HW_I386_TOPOLOGY_H + +-/* This file implements the APIC-ID-based CPU topology enumeration logic, ++/* ++ * This file implements the APIC-ID-based CPU topology enumeration logic, + * documented at the following document: + * Intel® 64 Architecture Processor Topology Enumeration + * http://software.intel.com/en-us/articles/intel-64-architecture-processor-topology-enumeration/ +@@ -41,7 +42,8 @@ + + #include "qemu/bitops.h" + +-/* APIC IDs can be 32-bit, but beware: APIC IDs > 255 require x2APIC support ++/* ++ * APIC IDs can be 32-bit, but beware: APIC IDs > 255 require x2APIC support + */ + typedef uint32_t apic_id_t; + +@@ -58,8 +60,7 @@ typedef struct X86CPUTopoInfo { + unsigned threads_per_core; + } X86CPUTopoInfo; + +-/* Return the bit width needed for 'count' IDs +- */ ++/* Return the bit width needed for 'count' IDs */ + static unsigned apicid_bitwidth_for_count(unsigned count) + { + g_assert(count >= 1); +@@ -67,15 +68,13 @@ static unsigned apicid_bitwidth_for_count(unsigned count) + return count ? 32 - clz32(count) : 0; + } + +-/* Bit width of the SMT_ID (thread ID) field on the APIC ID +- */ ++/* Bit width of the SMT_ID (thread ID) field on the APIC ID */ + static inline unsigned apicid_smt_width(X86CPUTopoInfo *topo_info) + { + return apicid_bitwidth_for_count(topo_info->threads_per_core); + } + +-/* Bit width of the Core_ID field +- */ ++/* Bit width of the Core_ID field */ + static inline unsigned apicid_core_width(X86CPUTopoInfo *topo_info) + { + return apicid_bitwidth_for_count(topo_info->cores_per_die); +@@ -87,8 +86,7 @@ static inline unsigned apicid_die_width(X86CPUTopoInfo *topo_info) + return apicid_bitwidth_for_count(topo_info->dies_per_pkg); + } + +-/* Bit offset of the Core_ID field +- */ ++/* Bit offset of the Core_ID field */ + static inline unsigned apicid_core_offset(X86CPUTopoInfo *topo_info) + { + return apicid_smt_width(topo_info); +@@ -100,14 +98,14 @@ static inline unsigned apicid_die_offset(X86CPUTopoInfo *topo_info) + return apicid_core_offset(topo_info) + apicid_core_width(topo_info); + } + +-/* Bit offset of the Pkg_ID (socket ID) field +- */ ++/* Bit offset of the Pkg_ID (socket ID) field */ + static inline unsigned apicid_pkg_offset(X86CPUTopoInfo *topo_info) + { + return apicid_die_offset(topo_info) + apicid_die_width(topo_info); + } + +-/* Make APIC ID for the CPU based on Pkg_ID, Core_ID, SMT_ID ++/* ++ * Make APIC ID for the CPU based on Pkg_ID, Core_ID, SMT_ID + * + * The caller must make sure core_id < nr_cores and smt_id < nr_threads. + */ +@@ -120,7 +118,8 @@ static inline apic_id_t x86_apicid_from_topo_ids(X86CPUTopoInfo *topo_info, + topo_ids->smt_id; + } + +-/* Calculate thread/core/package IDs for a specific topology, ++/* ++ * Calculate thread/core/package IDs for a specific topology, + * based on (contiguous) CPU index + */ + static inline void x86_topo_ids_from_idx(X86CPUTopoInfo *topo_info, +@@ -137,7 +136,8 @@ static inline void x86_topo_ids_from_idx(X86CPUTopoInfo *topo_info, + topo_ids->smt_id = cpu_index % nr_threads; + } + +-/* Calculate thread/core/package IDs for a specific topology, ++/* ++ * Calculate thread/core/package IDs for a specific topology, + * based on APIC ID + */ + static inline void x86_topo_ids_from_apicid(apic_id_t apicid, +@@ -155,7 +155,8 @@ static inline void x86_topo_ids_from_apicid(apic_id_t apicid, + topo_ids->pkg_id = apicid >> apicid_pkg_offset(topo_info); + } + +-/* Make APIC ID for the CPU 'cpu_index' ++/* ++ * Make APIC ID for the CPU 'cpu_index' + * + * 'cpu_index' is a sequential, contiguous ID for the CPU. + */ +-- +2.27.0 + diff --git a/iotests-fix-194-filter-out-racy-postcopy-active-even.patch b/iotests-fix-194-filter-out-racy-postcopy-active-even.patch new file mode 100644 index 00000000..9acecfc9 --- /dev/null +++ b/iotests-fix-194-filter-out-racy-postcopy-active-even.patch @@ -0,0 +1,55 @@ +From fe75f8834809b41779366a852190715b33b2af5d Mon Sep 17 00:00:00 2001 +From: jipengfei_yewu +Date: Mon, 18 Dec 2023 11:56:32 +0000 +Subject: [PATCH] iotests: fix 194: filter out racy postcopy-active event + +The event is racy: it will not appear in the output if bitmap is +migrated during downtime period of migration and postcopy phase is not +started. + +cheery-pick from dcc28ab603f30df5cc8be1f759b423e94ae7d10f + +Fixes: ae00aa239847 "iotests: 194: test also migration of dirty bitmap" +Reported-by: Richard Henderson + +Signed-off-by: jipengfei_yewu +Signed-off-by: Vladimir Sementsov-Ogievskiy +Message-Id: <20230607143606.1557395-1-vsementsov@yandex-team.ru> +Reviewed-by: Richard Henderson +Signed-off-by: Richard Henderson +--- + tests/qemu-iotests/194 | 5 +++++ + tests/qemu-iotests/194.out | 1 - + 2 files changed, 5 insertions(+), 1 deletion(-) + +diff --git a/tests/qemu-iotests/194 b/tests/qemu-iotests/194 +index e44b8df728..4c8a952cd8 100755 +--- a/tests/qemu-iotests/194 ++++ b/tests/qemu-iotests/194 +@@ -74,6 +74,11 @@ with iotests.FilePath('source.img') as source_img_path, \ + + while True: + event1 = source_vm.event_wait('MIGRATION') ++ if event1['data']['status'] == 'postcopy-active': ++ # This event is racy, it depends do we really do postcopy or bitmap ++ # was migrated during downtime (and no data to migrate in postcopy ++ # phase). So, don't log it. ++ continue + iotests.log(event1, filters=[iotests.filter_qmp_event]) + if event1['data']['status'] in ('completed', 'failed'): + iotests.log('Gracefully ending the `drive-mirror` job on source...') +diff --git a/tests/qemu-iotests/194.out b/tests/qemu-iotests/194.out +index 4e6df1565a..376ed1d2e6 100644 +--- a/tests/qemu-iotests/194.out ++++ b/tests/qemu-iotests/194.out +@@ -14,7 +14,6 @@ Starting migration... + {"return": {}} + {"data": {"status": "setup"}, "event": "MIGRATION", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} + {"data": {"status": "active"}, "event": "MIGRATION", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} +-{"data": {"status": "postcopy-active"}, "event": "MIGRATION", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} + {"data": {"status": "completed"}, "event": "MIGRATION", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} + Gracefully ending the `drive-mirror` job on source... + {"return": {}} +-- +2.27.0 + diff --git a/linux-user-fix-sockaddr_in6-endianness.patch b/linux-user-fix-sockaddr_in6-endianness.patch new file mode 100644 index 00000000..104dfc95 --- /dev/null +++ b/linux-user-fix-sockaddr_in6-endianness.patch @@ -0,0 +1,42 @@ +From fd2a1eeeaeaba0ca23efd37fa00631ed39081d08 Mon Sep 17 00:00:00 2001 +From: jipengfei_yewu +Date: Mon, 18 Dec 2023 11:59:32 +0000 +Subject: [PATCH] linux-user: fix sockaddr_in6 endianness +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The sin6_scope_id field uses the host byte order, so there is a +conversion to be made when host and target endianness differ. + +cheery-pick from 44cf6731d6b9a48bcd57392e8cd6f0f712aaa677 + +Signed-off-by: jipengfei_yewu +Signed-off-by: Mathis Marion +Reviewed-by: Laurent Vivier +Reviewed-by: Philippe Mathieu-Daudé +Message-Id: <20230307154256.101528-2-Mathis.Marion@silabs.com> +Signed-off-by: Laurent Vivier +--- + linux-user/syscall.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/linux-user/syscall.c b/linux-user/syscall.c +index a544d04524..92df0f9d8c 100644 +--- a/linux-user/syscall.c ++++ b/linux-user/syscall.c +@@ -1701,6 +1701,11 @@ static inline abi_long target_to_host_sockaddr(int fd, struct sockaddr *addr, + lladdr = (struct target_sockaddr_ll *)addr; + lladdr->sll_ifindex = tswap32(lladdr->sll_ifindex); + lladdr->sll_hatype = tswap16(lladdr->sll_hatype); ++ } else if (sa_family == AF_INET6) { ++ struct sockaddr_in6 *in6addr; ++ ++ in6addr = (struct sockaddr_in6 *)addr; ++ in6addr->sin6_scope_id = tswap32(in6addr->sin6_scope_id); + } + unlock_user(target_saddr, target_addr, 0); + +-- +2.27.0 + diff --git a/migration-multifd-Remove-unnecessary-usage-of-local-.patch b/migration-multifd-Remove-unnecessary-usage-of-local-.patch new file mode 100644 index 00000000..7f7a04ee --- /dev/null +++ b/migration-multifd-Remove-unnecessary-usage-of-local-.patch @@ -0,0 +1,61 @@ +From 8046e5c70d22eba8a1ca71ba622fa8b8c74c355f Mon Sep 17 00:00:00 2001 +From: qihao +Date: Tue, 16 Jan 2024 17:52:03 +0800 +Subject: [PATCH] migration/multifd: Remove unnecessary usage of local Error +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +cheery-pick from 3fc58efa938338a82e4d5c0c031e7e9c98e9544f + +According to Error API, usage of ERRP_GUARD() or a local Error instead +of errp is needed if errp is passed to void functions, where it is later +dereferenced to see if an error occurred. + +There are several places in multifd.c that use local Error although it +is not needed. Change these places to use errp directly. + +Signed-off-by: Avihai Horon +Reviewed-by: Philippe Mathieu-Daudé +Link: https://lore.kernel.org/r/20231231093016.14204-12-avihaih@nvidia.com +Signed-off-by: Peter Xu +Signed-off-by: qihao_yewu +--- + migration/multifd.c | 8 ++------ + 1 file changed, 2 insertions(+), 6 deletions(-) + +diff --git a/migration/multifd.c b/migration/multifd.c +index 0d3f66537c..4befde5cad 100644 +--- a/migration/multifd.c ++++ b/migration/multifd.c +@@ -929,12 +929,10 @@ int multifd_save_setup(Error **errp) + + for (i = 0; i < thread_count; i++) { + MultiFDSendParams *p = &multifd_send_state->params[i]; +- Error *local_err = NULL; + int ret; + +- ret = multifd_send_state->ops->send_setup(p, &local_err); ++ ret = multifd_send_state->ops->send_setup(p, errp); + if (ret) { +- error_propagate(errp, local_err); + return ret; + } + } +@@ -1167,12 +1165,10 @@ int multifd_load_setup(Error **errp) + + for (i = 0; i < thread_count; i++) { + MultiFDRecvParams *p = &multifd_recv_state->params[i]; +- Error *local_err = NULL; + int ret; + +- ret = multifd_recv_state->ops->recv_setup(p, &local_err); ++ ret = multifd_recv_state->ops->recv_setup(p, errp); + if (ret) { +- error_propagate(errp, local_err); + return ret; + } + } +-- +2.27.0 + diff --git a/qemu.spec b/qemu.spec index d773e3a6..130ec0f8 100644 --- a/qemu.spec +++ b/qemu.spec @@ -3,7 +3,7 @@ Name: qemu Version: 6.2.0 -Release: 87 +Release: 88 Epoch: 10 Summary: QEMU is a generic and open source machine emulator and virtualizer License: GPLv2 and BSD and MIT and CC-BY-SA-4.0 @@ -857,7 +857,14 @@ Patch0842: vdpa-correct-param-passed-in-when-unregister-save.patch Patch0843: vdpa-support-vdpa-device-suspend-resume.patch Patch0844: vdpa-don-t-suspend-resume-device-when-vdpa-device-no.patch Patch0845: vdpa-suspend-function-return-0-when-the-vdpa-device-.patch - +Patch0846: ui-vnc-fix-debug-output-for-invalid-audio-message.patch +Patch0847: tests-avocado-fix-waiting-for-vm-shutdown-in-replay_.patch +Patch0848: iotests-fix-194-filter-out-racy-postcopy-active-even.patch +Patch0849: vhost_vdpa-fix-the-input-in-trace_vhost_vdpa_listene.patch +Patch0850: linux-user-fix-sockaddr_in6-endianness.patch +Patch0851: migration-multifd-Remove-unnecessary-usage-of-local-.patch +Patch0852: hw-i386-Fix-comment-style-in-topology.h.patch +Patch0853: ui-vnc.c-Fixed-a-deadlock-bug.patch BuildRequires: flex BuildRequires: gcc @@ -1456,6 +1463,16 @@ getent passwd qemu >/dev/null || \ %endif %changelog +* Wed Feb 21 2024 - 10:6.2.0-88 +- ui/vnc.c: Fixed a deadlock bug. +- hw/i386: Fix comment style in topology.h +- migration/multifd: Remove unnecessary usage of local Error +- linux-user: fix sockaddr_in6 endianness +- vhost_vdpa: fix the input in trace_vhost_vdpa_listener_region_del() +- iotests: fix 194: filter out racy postcopy-active event +- tests/avocado: fix waiting for vm shutdown in replay_linux +- ui/vnc: fix debug output for invalid audio message + * Fri Dec 22 2023 - 10:6.2.0-87 - vdpa: suspend function return 0 when the vdpa device is stopped - vdpa: don't suspend/resume device when vdpa device not started diff --git a/tests-avocado-fix-waiting-for-vm-shutdown-in-replay_.patch b/tests-avocado-fix-waiting-for-vm-shutdown-in-replay_.patch new file mode 100644 index 00000000..5c237216 --- /dev/null +++ b/tests-avocado-fix-waiting-for-vm-shutdown-in-replay_.patch @@ -0,0 +1,35 @@ +From 0242c2c743987efc6955fc4405b540140b1b678d Mon Sep 17 00:00:00 2001 +From: jipengfei_yewu +Date: Mon, 18 Dec 2023 11:57:38 +0000 +Subject: [PATCH] tests/avocado: fix waiting for vm shutdown in replay_linux + +This patch fixes the race condition in waiting for shutdown +of the replay linux test. + +cheery-pick from b821109583a035a17fa5b89c0ebd8917d09cc82d + +Signed-off-by: jipengfei_yewu +Signed-off-by: Pavel Dovgalyuk +Suggested-by: John Snow +Message-ID: <20230811070608.3383343-4-pavel.dovgalyuk@ispras.ru> +Signed-off-by: Thomas Huth +--- + tests/avocado/replay_linux.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tests/avocado/replay_linux.py b/tests/avocado/replay_linux.py +index 15953f9e49..897d5bad19 100644 +--- a/tests/avocado/replay_linux.py ++++ b/tests/avocado/replay_linux.py +@@ -82,7 +82,7 @@ def launch_and_wait(self, record, args, shift): + % os.path.getsize(replay_path)) + else: + vm.event_wait('SHUTDOWN', self.timeout) +- vm.shutdown(True) ++ vm.wait() + logger.info('successfully fihished the replay') + elapsed = time.time() - start_time + logger.info('elapsed time %.2f sec' % elapsed) +-- +2.27.0 + diff --git a/ui-vnc-fix-debug-output-for-invalid-audio-message.patch b/ui-vnc-fix-debug-output-for-invalid-audio-message.patch new file mode 100644 index 00000000..080d37fc --- /dev/null +++ b/ui-vnc-fix-debug-output-for-invalid-audio-message.patch @@ -0,0 +1,36 @@ +From 2677d371ed65941912149218fb5683f0b8db0760 Mon Sep 17 00:00:00 2001 +From: jipengfei_yewu +Date: Mon, 18 Dec 2023 09:57:38 +0000 +Subject: [PATCH] ui/vnc: fix debug output for invalid audio message +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The debug message was cut and pasted from the invalid audio format +case, but the audio message is at bytes 2-3. + +cheery-pick from 0cb9c5880e6b8dedc4e20026ce859dd1ea9aac84 + +Signed-off-by: jipengfei_yewu +Reviewed-by: Daniel P. Berrangé +Signed-off-by: Paolo Bonzini +--- + ui/vnc.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/ui/vnc.c b/ui/vnc.c +index f4322a9065..f8978b0e65 100644 +--- a/ui/vnc.c ++++ b/ui/vnc.c +@@ -2567,7 +2567,7 @@ static int protocol_client_msg(VncState *vs, uint8_t *data, size_t len) + vs, vs->ioc, vs->as.fmt, vs->as.nchannels, vs->as.freq); + break; + default: +- VNC_DEBUG("Invalid audio message %d\n", read_u8(data, 4)); ++ VNC_DEBUG("Invalid audio message %d\n", read_u8(data, 2)); + vnc_client_error(vs); + break; + } +-- +2.27.0 + diff --git a/ui-vnc.c-Fixed-a-deadlock-bug.patch b/ui-vnc.c-Fixed-a-deadlock-bug.patch new file mode 100644 index 00000000..a2f1fa4c --- /dev/null +++ b/ui-vnc.c-Fixed-a-deadlock-bug.patch @@ -0,0 +1,71 @@ +From c6e08e8f6e296ab2e8149c4362363a5fd31813f6 Mon Sep 17 00:00:00 2001 +From: Rao Lei +Date: Wed, 5 Jan 2022 10:08:08 +0800 +Subject: [PATCH] ui/vnc.c: Fixed a deadlock bug. +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The GDB statck is as follows: +(gdb) bt +0 __lll_lock_wait (futex=futex@entry=0x56211df20360, private=0) at lowlevellock.c:52 +1 0x00007f263caf20a3 in __GI___pthread_mutex_lock (mutex=0x56211df20360) at ../nptl/pthread_mutex_lock.c:80 +2 0x000056211a757364 in qemu_mutex_lock_impl (mutex=0x56211df20360, file=0x56211a804857 "../ui/vnc-jobs.h", line=60) + at ../util/qemu-thread-posix.c:80 +3 0x000056211a0ef8c7 in vnc_lock_output (vs=0x56211df14200) at ../ui/vnc-jobs.h:60 +4 0x000056211a0efcb7 in vnc_clipboard_send (vs=0x56211df14200, count=1, dwords=0x7ffdf1701338) at ../ui/vnc-clipboard.c:138 +5 0x000056211a0f0129 in vnc_clipboard_notify (notifier=0x56211df244c8, data=0x56211dd1bbf0) at ../ui/vnc-clipboard.c:209 +6 0x000056211a75dde8 in notifier_list_notify (list=0x56211afa17d0 , data=0x56211dd1bbf0) at ../util/notify.c:39 +7 0x000056211a0bf0e6 in qemu_clipboard_update (info=0x56211dd1bbf0) at ../ui/clipboard.c:50 +8 0x000056211a0bf05d in qemu_clipboard_peer_release (peer=0x56211df244c0, selection=QEMU_CLIPBOARD_SELECTION_CLIPBOARD) + at ../ui/clipboard.c:41 +9 0x000056211a0bef9b in qemu_clipboard_peer_unregister (peer=0x56211df244c0) at ../ui/clipboard.c:19 +10 0x000056211a0d45f3 in vnc_disconnect_finish (vs=0x56211df14200) at ../ui/vnc.c:1358 +11 0x000056211a0d4c9d in vnc_client_read (vs=0x56211df14200) at ../ui/vnc.c:1611 +12 0x000056211a0d4df8 in vnc_client_io (ioc=0x56211ce70690, condition=G_IO_IN, opaque=0x56211df14200) at ../ui/vnc.c:1649 +13 0x000056211a5b976c in qio_channel_fd_source_dispatch + (source=0x56211ce50a00, callback=0x56211a0d4d71 , user_data=0x56211df14200) at ../io/channel-watch.c:84 +14 0x00007f263ccede8e in g_main_context_dispatch () at /lib/x86_64-linux-gnu/libglib-2.0.so.0 +15 0x000056211a77d4a1 in glib_pollfds_poll () at ../util/main-loop.c:232 +16 0x000056211a77d51f in os_host_main_loop_wait (timeout=958545) at ../util/main-loop.c:255 +17 0x000056211a77d630 in main_loop_wait (nonblocking=0) at ../util/main-loop.c:531 +18 0x000056211a45bc8e in qemu_main_loop () at ../softmmu/runstate.c:726 +19 0x000056211a0b45fa in main (argc=69, argv=0x7ffdf1701778, envp=0x7ffdf17019a8) at ../softmmu/main.c:50 + +From the call trace, we can see it is a deadlock bug. +vnc_disconnect_finish will acquire the output_mutex. +But, the output_mutex will be acquired again in vnc_clipboard_send. +Repeated locking will cause deadlock. So, I move +qemu_clipboard_peer_unregister() behind vnc_unlock_output(); + +Fixes: 0bf41cab93e ("ui/vnc: clipboard support") +Signed-off-by: Lei Rao +Reviewed-by: Marc-André Lureau +Message-Id: <20220105020808.597325-1-lei.rao@intel.com> +Signed-off-by: Gerd Hoffmann +--- + ui/vnc.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/ui/vnc.c b/ui/vnc.c +index f8978b0e65..71e3627be2 100644 +--- a/ui/vnc.c ++++ b/ui/vnc.c +@@ -1354,12 +1354,12 @@ void vnc_disconnect_finish(VncState *vs) + /* last client gone */ + vnc_update_server_surface(vs->vd); + } ++ vnc_unlock_output(vs); ++ + if (vs->cbpeer.update.notify) { + qemu_clipboard_peer_unregister(&vs->cbpeer); + } + +- vnc_unlock_output(vs); +- + qemu_mutex_destroy(&vs->output_mutex); + if (vs->bh != NULL) { + qemu_bh_delete(vs->bh); +-- +2.27.0 + diff --git a/vhost_vdpa-fix-the-input-in-trace_vhost_vdpa_listene.patch b/vhost_vdpa-fix-the-input-in-trace_vhost_vdpa_listene.patch new file mode 100644 index 00000000..b842678e --- /dev/null +++ b/vhost_vdpa-fix-the-input-in-trace_vhost_vdpa_listene.patch @@ -0,0 +1,37 @@ +From 48b7b68cab05b9c614163935d0b42bb684e56ca9 Mon Sep 17 00:00:00 2001 +From: jipengfei_yewu +Date: Mon, 18 Dec 2023 11:58:32 +0000 +Subject: [PATCH] vhost_vdpa: fix the input in + trace_vhost_vdpa_listener_region_del() + +In trace_vhost_vdpa_listener_region_del, the value for llend +should change to int128_get64(int128_sub(llend, int128_one())) + +cheery-pick from 3d1e4d34a81a212e234f674e57e73c824d4b131a + +Signed-off-by:jipengfei_yewu +Signed-off-by: Cindy Lu +Message-Id: <20230510054631.2951812-3-lulu@redhat.com> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +--- + hw/virtio/vhost-vdpa.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c +index c7aaff7f20..22fd1b1e2f 100644 +--- a/hw/virtio/vhost-vdpa.c ++++ b/hw/virtio/vhost-vdpa.c +@@ -290,7 +290,8 @@ static void vhost_vdpa_listener_region_del(MemoryListener *listener, + iova = TARGET_PAGE_ALIGN(section->offset_within_address_space); + llend = vhost_vdpa_section_end(section); + +- trace_vhost_vdpa_listener_region_del(v, iova, int128_get64(llend)); ++ trace_vhost_vdpa_listener_region_del(v, iova, ++ int128_get64(int128_sub(llend, int128_one()))); + + if (int128_ge(int128_make64(iova), llend)) { + return; +-- +2.27.0 + -- Gitee From 18db08e0e64d982b88ad7f29ccd49b19e8c656f0 Mon Sep 17 00:00:00 2001 From: Jiabo Feng Date: Sat, 9 Mar 2024 14:37:51 +0800 Subject: [PATCH 06/19] QEMU update to version 6.2.0-89 - qga-win: Fix guest-get-fsinfo multi-disks collection - hw/timer: fix systick trace message - virtio-net: correctly copy vnet header when flushing TX (CVE-2023-6693) - ui/clipboard: mark type as not available when there is no data (CVE-2023-6683) - esp: restrict non-DMA transfer length to that of available data (CVE-2024-24474) - hw/scsi/lsi53c895a: add missing decrement of reentrancy counter - hw/scsi/lsi53c895a: Fix reentrancy issues in the LSI controller (CVE-2023-0330) - net: Update MemReentrancyGuard for NIC (CVE-2023-3019) - net: Provide MemReentrancyGuard * to qemu_new_nic() Signed-off-by: Jiabo Feng --- ...-DMA-transfer-length-to-that-of-avai.patch | 43 ++ ...5a-Fix-reentrancy-issues-in-the-LSI-.patch | 124 ++++ ...5a-add-missing-decrement-of-reentran.patch | 39 ++ hw-timer-fix-systick-trace-message.patch | 37 ++ memory-prevent-dma-reentracy-issues.patch | 132 ++++ ...e-MemReentrancyGuard-to-qemu_new_nic.patch | 604 ++++++++++++++++++ ...eentrancyGuard-for-NIC-CVE-2023-3019.patch | 85 +++ qemu.spec | 23 +- ...st-get-fsinfo-multi-disks-collection.patch | 40 ++ ...k-type-as-not-available-when-there-i.patch | 89 +++ ...ctly-copy-vnet-header-when-flushing-.patch | 72 +++ 11 files changed, 1287 insertions(+), 1 deletion(-) create mode 100644 esp-restrict-non-DMA-transfer-length-to-that-of-avai.patch create mode 100644 hw-scsi-lsi53c895a-Fix-reentrancy-issues-in-the-LSI-.patch create mode 100644 hw-scsi-lsi53c895a-add-missing-decrement-of-reentran.patch create mode 100644 hw-timer-fix-systick-trace-message.patch create mode 100644 memory-prevent-dma-reentracy-issues.patch create mode 100644 net-Provide-MemReentrancyGuard-to-qemu_new_nic.patch create mode 100644 net-Update-MemReentrancyGuard-for-NIC-CVE-2023-3019.patch create mode 100644 qga-win-Fix-guest-get-fsinfo-multi-disks-collection.patch create mode 100644 ui-clipboard-mark-type-as-not-available-when-there-i.patch create mode 100644 virtio-net-correctly-copy-vnet-header-when-flushing-.patch diff --git a/esp-restrict-non-DMA-transfer-length-to-that-of-avai.patch b/esp-restrict-non-DMA-transfer-length-to-that-of-avai.patch new file mode 100644 index 00000000..83040466 --- /dev/null +++ b/esp-restrict-non-DMA-transfer-length-to-that-of-avai.patch @@ -0,0 +1,43 @@ +From 67f1bc4fc4d1864a55f6c626967defe5467f5134 Mon Sep 17 00:00:00 2001 +From: Mark Cave-Ayland +Date: Wed, 13 Sep 2023 21:44:09 +0100 +Subject: [PATCH] esp: restrict non-DMA transfer length to that of available + data (CVE-2024-24474) + +In the case where a SCSI layer transfer is incorrectly terminated, it is +possible for a TI command to cause a SCSI buffer overflow due to the +expected transfer data length being less than the available data in the +FIFO. When this occurs the unsigned async_len variable underflows and +becomes a large offset which writes past the end of the allocated SCSI +buffer. + +Restrict the non-DMA transfer length to be the smallest of the expected +transfer length and the available FIFO data to ensure that it is no longer +possible for the SCSI buffer overflow to occur. + +Signed-off-by: Mark Cave-Ayland +Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1810 +Reviewed-by: Thomas Huth +Message-ID: <20230913204410.65650-3-mark.cave-ayland@ilande.co.uk> +Signed-off-by: Paolo Bonzini +--- + hw/scsi/esp.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/hw/scsi/esp.c b/hw/scsi/esp.c +index f38231f8cd..435a81bbfd 100644 +--- a/hw/scsi/esp.c ++++ b/hw/scsi/esp.c +@@ -754,7 +754,8 @@ static void esp_do_nodma(ESPState *s) + } + + if (to_device) { +- len = MIN(fifo8_num_used(&s->fifo), ESP_FIFO_SZ); ++ len = MIN(s->async_len, ESP_FIFO_SZ); ++ len = MIN(len, fifo8_num_used(&s->fifo)); + esp_fifo_pop_buf(&s->fifo, s->async_buf, len); + s->async_buf += len; + s->async_len -= len; +-- +2.27.0 + diff --git a/hw-scsi-lsi53c895a-Fix-reentrancy-issues-in-the-LSI-.patch b/hw-scsi-lsi53c895a-Fix-reentrancy-issues-in-the-LSI-.patch new file mode 100644 index 00000000..69170583 --- /dev/null +++ b/hw-scsi-lsi53c895a-Fix-reentrancy-issues-in-the-LSI-.patch @@ -0,0 +1,124 @@ +From ef9a2635bf418f2a625e2421d3bfe1fe58ac0bec Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Mon, 22 May 2023 11:10:11 +0200 +Subject: [PATCH] hw/scsi/lsi53c895a: Fix reentrancy issues in the LSI + controller (CVE-2023-0330) + +We cannot use the generic reentrancy guard in the LSI code, so +we have to manually prevent endless reentrancy here. The problematic +lsi_execute_script() function has already a way to detect whether +too many instructions have been executed - we just have to slightly +change the logic here that it also takes into account if the function +has been called too often in a reentrant way. + +The code in fuzz-lsi53c895a-test.c has been taken from an earlier +patch by Mauro Matteo Cascella. + +Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1563 +Message-Id: <20230522091011.1082574-1-thuth@redhat.com> +Reviewed-by: Stefan Hajnoczi +Reviewed-by: Alexander Bulekov +Signed-off-by: Thomas Huth +Signed-off-by: liuxiangdong +--- + hw/scsi/lsi53c895a.c | 23 +++++++++++++++------ + tests/qtest/fuzz-lsi53c895a-test.c | 32 ++++++++++++++++++++++++++++++ + 2 files changed, 49 insertions(+), 6 deletions(-) + +diff --git a/hw/scsi/lsi53c895a.c b/hw/scsi/lsi53c895a.c +index b9c9eb0dac..f7559051c5 100644 +--- a/hw/scsi/lsi53c895a.c ++++ b/hw/scsi/lsi53c895a.c +@@ -1134,15 +1134,24 @@ static void lsi_execute_script(LSIState *s) + uint32_t addr, addr_high; + int opcode; + int insn_processed = 0; ++ static int reentrancy_level; ++ ++ reentrancy_level++; + + s->istat1 |= LSI_ISTAT1_SRUN; + again: +- if (++insn_processed > LSI_MAX_INSN) { +- /* Some windows drivers make the device spin waiting for a memory +- location to change. If we have been executed a lot of code then +- assume this is the case and force an unexpected device disconnect. +- This is apparently sufficient to beat the drivers into submission. +- */ ++ /* ++ * Some windows drivers make the device spin waiting for a memory location ++ * to change. If we have executed more than LSI_MAX_INSN instructions then ++ * assume this is the case and force an unexpected device disconnect. This ++ * is apparently sufficient to beat the drivers into submission. ++ * ++ * Another issue (CVE-2023-0330) can occur if the script is programmed to ++ * trigger itself again and again. Avoid this problem by stopping after ++ * being called multiple times in a reentrant way (8 is an arbitrary value ++ * which should be enough for all valid use cases). ++ */ ++ if (++insn_processed > LSI_MAX_INSN || reentrancy_level > 8) { + if (!(s->sien0 & LSI_SIST0_UDC)) { + qemu_log_mask(LOG_GUEST_ERROR, + "lsi_scsi: inf. loop with UDC masked"); +@@ -1596,6 +1605,8 @@ again: + } + } + trace_lsi_execute_script_stop(); ++ ++ reentrancy_level--; + } + + static uint8_t lsi_reg_readb(LSIState *s, int offset) +diff --git a/tests/qtest/fuzz-lsi53c895a-test.c b/tests/qtest/fuzz-lsi53c895a-test.c +index 0f968024c8..9c50958796 100644 +--- a/tests/qtest/fuzz-lsi53c895a-test.c ++++ b/tests/qtest/fuzz-lsi53c895a-test.c +@@ -8,6 +8,36 @@ + #include "qemu/osdep.h" + #include "libqos/libqtest.h" + ++/* ++ * This used to trigger a DMA reentrancy issue ++ * leading to memory corruption bugs like stack ++ * overflow or use-after-free ++ * https://gitlab.com/qemu-project/qemu/-/issues/1563 ++ */ ++static void test_lsi_dma_reentrancy(void) ++{ ++ QTestState *s; ++ ++ s = qtest_init("-M q35 -m 512M -nodefaults " ++ "-blockdev driver=null-co,node-name=null0 " ++ "-device lsi53c810 -device scsi-cd,drive=null0"); ++ ++ qtest_outl(s, 0xcf8, 0x80000804); /* PCI Command Register */ ++ qtest_outw(s, 0xcfc, 0x7); /* Enables accesses */ ++ qtest_outl(s, 0xcf8, 0x80000814); /* Memory Bar 1 */ ++ qtest_outl(s, 0xcfc, 0xff100000); /* Set MMIO Address*/ ++ qtest_outl(s, 0xcf8, 0x80000818); /* Memory Bar 2 */ ++ qtest_outl(s, 0xcfc, 0xff000000); /* Set RAM Address*/ ++ qtest_writel(s, 0xff000000, 0xc0000024); ++ qtest_writel(s, 0xff000114, 0x00000080); ++ qtest_writel(s, 0xff00012c, 0xff000000); ++ qtest_writel(s, 0xff000004, 0xff000114); ++ qtest_writel(s, 0xff000008, 0xff100014); ++ qtest_writel(s, 0xff10002f, 0x000000ff); ++ ++ qtest_quit(s); ++} ++ + /* + * This used to trigger a UAF in lsi_do_msgout() + * https://gitlab.com/qemu-project/qemu/-/issues/972 +@@ -121,6 +151,8 @@ int main(int argc, char **argv) + test_lsi_do_dma_empty_queue); + qtest_add_func("fuzz/lsi53c895a/lsi_do_msgout_cancel_req", + test_lsi_do_msgout_cancel_req); ++ qtest_add_func("fuzz/lsi53c895a/lsi_dma_reentrancy", ++ test_lsi_dma_reentrancy); + } + + return g_test_run(); +-- +2.27.0 + diff --git a/hw-scsi-lsi53c895a-add-missing-decrement-of-reentran.patch b/hw-scsi-lsi53c895a-add-missing-decrement-of-reentran.patch new file mode 100644 index 00000000..6d286a60 --- /dev/null +++ b/hw-scsi-lsi53c895a-add-missing-decrement-of-reentran.patch @@ -0,0 +1,39 @@ +From 19692eed451101e16399673cd5c3ee9c684cfde0 Mon Sep 17 00:00:00 2001 +From: Sven Schnelle +Date: Sun, 28 Jan 2024 21:22:14 +0100 +Subject: [PATCH] hw/scsi/lsi53c895a: add missing decrement of reentrancy + counter + +When the maximum count of SCRIPTS instructions is reached, the code +stops execution and returns, but fails to decrement the reentrancy +counter. This effectively renders the SCSI controller unusable +because on next entry the reentrancy counter is still above the limit. + +This bug was seen on HP-UX 10.20 which seems to trigger SCRIPTS +loops. + +Fixes: b987718bbb ("hw/scsi/lsi53c895a: Fix reentrancy issues in the LSI controller (CVE-2023-0330)") +Signed-off-by: Sven Schnelle +Message-ID: <20240128202214.2644768-1-svens@stackframe.org> +Reviewed-by: Thomas Huth +Tested-by: Helge Deller +Signed-off-by: Thomas Huth +--- + hw/scsi/lsi53c895a.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/hw/scsi/lsi53c895a.c b/hw/scsi/lsi53c895a.c +index f7559051c5..71f1505227 100644 +--- a/hw/scsi/lsi53c895a.c ++++ b/hw/scsi/lsi53c895a.c +@@ -1159,6 +1159,7 @@ again: + lsi_script_scsi_interrupt(s, LSI_SIST0_UDC, 0); + lsi_disconnect(s); + trace_lsi_execute_script_stop(); ++ reentrancy_level--; + return; + } + insn = read_dword(s, s->dsp); +-- +2.27.0 + diff --git a/hw-timer-fix-systick-trace-message.patch b/hw-timer-fix-systick-trace-message.patch new file mode 100644 index 00000000..42e6a26a --- /dev/null +++ b/hw-timer-fix-systick-trace-message.patch @@ -0,0 +1,37 @@ +From 81e188ec0547708416c0cfc426ba9ffcd56fcfc2 Mon Sep 17 00:00:00 2001 +From: qihao +Date: Thu, 8 Feb 2024 11:31:02 +0800 +Subject: [PATCH] hw/timer: fix systick trace message +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +cheery-pick from 7c8faaf2a4fa8ad2d291662ac7e7eeea1fe8d47c + +Signed-off-by: Samuel Tardieu +Reviewed-by: Philippe Mathieu-Daudé +Reviewed-by: Laurent Vivier +Message-id: 20240109184508.3189599-1-sam@rfc1149.net +Fixes: ff68dacbc786 ("armv7m: Split systick out from NVIC") +Signed-off-by: Peter Maydell +Signed-off-by: qihao_yewu +--- + hw/timer/trace-events | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/hw/timer/trace-events b/hw/timer/trace-events +index 3eccef8385..8145e18e3d 100644 +--- a/hw/timer/trace-events ++++ b/hw/timer/trace-events +@@ -35,7 +35,7 @@ aspeed_timer_read(uint64_t offset, unsigned size, uint64_t value) "From 0x%" PRI + + # armv7m_systick.c + systick_reload(void) "systick reload" +-systick_timer_tick(void) "systick reload" ++systick_timer_tick(void) "systick tick" + systick_read(uint64_t addr, uint32_t value, unsigned size) "systick read addr 0x%" PRIx64 " data 0x%" PRIx32 " size %u" + systick_write(uint64_t addr, uint32_t value, unsigned size) "systick write addr 0x%" PRIx64 " data 0x%" PRIx32 " size %u" + +-- +2.27.0 + diff --git a/memory-prevent-dma-reentracy-issues.patch b/memory-prevent-dma-reentracy-issues.patch new file mode 100644 index 00000000..913dd18b --- /dev/null +++ b/memory-prevent-dma-reentracy-issues.patch @@ -0,0 +1,132 @@ +From 26bda91b2bc6d880f75344f0a8efd3f3af8a358f Mon Sep 17 00:00:00 2001 +From: Alexander Bulekov +Date: Thu, 27 Apr 2023 17:10:06 -0400 +Subject: [PATCH] memory: prevent dma-reentracy issues + +Add a flag to the DeviceState, when a device is engaged in PIO/MMIO/DMA. +This flag is set/checked prior to calling a device's MemoryRegion +handlers, and set when device code initiates DMA. The purpose of this +flag is to prevent two types of DMA-based reentrancy issues: + +1.) mmio -> dma -> mmio case +2.) bh -> dma write -> mmio case + +These issues have led to problems such as stack-exhaustion and +use-after-frees. + +Summary of the problem from Peter Maydell: +https://lore.kernel.org/qemu-devel/CAFEAcA_23vc7hE3iaM-JVA6W38LK4hJoWae5KcknhPRD5fPBZA@mail.gmail.com + +Resolves: https://gitlab.com/qemu-project/qemu/-/issues/62 +Resolves: https://gitlab.com/qemu-project/qemu/-/issues/540 +Resolves: https://gitlab.com/qemu-project/qemu/-/issues/541 +Resolves: https://gitlab.com/qemu-project/qemu/-/issues/556 +Resolves: https://gitlab.com/qemu-project/qemu/-/issues/557 +Resolves: https://gitlab.com/qemu-project/qemu/-/issues/827 +Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1282 +Resolves: CVE-2023-0330 + +Signed-off-by: Alexander Bulekov +Reviewed-by: Thomas Huth +Message-Id: <20230427211013.2994127-2-alxndr@bu.edu> +[thuth: Replace warn_report() with warn_report_once()] +Signed-off-by: Thomas Huth +Signed-off-by: liuxiangdong +--- + include/exec/memory.h | 5 +++++ + include/hw/qdev-core.h | 7 +++++++ + softmmu/memory.c | 16 ++++++++++++++++ + 3 files changed, 28 insertions(+) + +diff --git a/include/exec/memory.h b/include/exec/memory.h +index abb838f194..bbf1468d59 100644 +--- a/include/exec/memory.h ++++ b/include/exec/memory.h +@@ -737,6 +737,8 @@ struct MemoryRegion { + bool is_iommu; + RAMBlock *ram_block; + Object *owner; ++ /* owner as TYPE_DEVICE. Used for re-entrancy checks in MR access hotpath */ ++ DeviceState *dev; + + const MemoryRegionOps *ops; + void *opaque; +@@ -760,6 +762,9 @@ struct MemoryRegion { + unsigned ioeventfd_nb; + MemoryRegionIoeventfd *ioeventfds; + RamDiscardManager *rdm; /* Only for RAM */ ++ ++ /* For devices designed to perform re-entrant IO into their own IO MRs */ ++ bool disable_reentrancy_guard; + }; + + struct IOMMUMemoryRegion { +diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h +index 83774a1c68..45b1aec86b 100644 +--- a/include/hw/qdev-core.h ++++ b/include/hw/qdev-core.h +@@ -162,6 +162,10 @@ struct NamedClockList { + QLIST_ENTRY(NamedClockList) node; + }; + ++typedef struct { ++ bool engaged_in_io; ++} MemReentrancyGuard; ++ + /** + * DeviceState: + * @realized: Indicates whether the device has been fully constructed. +@@ -193,6 +197,9 @@ struct DeviceState { + int instance_id_alias; + int alias_required_for_version; + ResettableState reset; ++ ++ /* Is the device currently in mmio/pio/dma? Used to prevent re-entrancy */ ++ MemReentrancyGuard mem_reentrancy_guard; + }; + + struct DeviceListener { +diff --git a/softmmu/memory.c b/softmmu/memory.c +index 7340e19ff5..102f0a4248 100644 +--- a/softmmu/memory.c ++++ b/softmmu/memory.c +@@ -541,6 +541,18 @@ static MemTxResult access_with_adjusted_size(hwaddr addr, + access_size_max = 4; + } + ++ /* Do not allow more than one simultaneous access to a device's IO Regions */ ++ if (mr->dev && !mr->disable_reentrancy_guard && ++ !mr->ram_device && !mr->ram && !mr->rom_device && !mr->readonly) { ++ if (mr->dev->mem_reentrancy_guard.engaged_in_io) { ++ warn_report_once("Blocked re-entrant IO on MemoryRegion: " ++ "%s at addr: 0x%" HWADDR_PRIX, ++ memory_region_name(mr), addr); ++ return MEMTX_ACCESS_ERROR; ++ } ++ mr->dev->mem_reentrancy_guard.engaged_in_io = true; ++ } ++ + /* FIXME: support unaligned access? */ + access_size = MAX(MIN(size, access_size_max), access_size_min); + access_mask = MAKE_64BIT_MASK(0, access_size * 8); +@@ -555,6 +567,9 @@ static MemTxResult access_with_adjusted_size(hwaddr addr, + access_mask, attrs); + } + } ++ if (mr->dev) { ++ mr->dev->mem_reentrancy_guard.engaged_in_io = false; ++ } + return r; + } + +@@ -1169,6 +1184,7 @@ static void memory_region_do_init(MemoryRegion *mr, + } + mr->name = g_strdup(name); + mr->owner = owner; ++ mr->dev = (DeviceState *) object_dynamic_cast(mr->owner, TYPE_DEVICE); + mr->ram_block = NULL; + + if (name) { +-- +2.27.0 + diff --git a/net-Provide-MemReentrancyGuard-to-qemu_new_nic.patch b/net-Provide-MemReentrancyGuard-to-qemu_new_nic.patch new file mode 100644 index 00000000..d913ff6d --- /dev/null +++ b/net-Provide-MemReentrancyGuard-to-qemu_new_nic.patch @@ -0,0 +1,604 @@ +From cfb14ba8c266935afd660bcada152a36cafce521 Mon Sep 17 00:00:00 2001 +From: Akihiko Odaki +Date: Thu, 1 Jun 2023 12:18:58 +0900 +Subject: [PATCH] net: Provide MemReentrancyGuard * to qemu_new_nic() + +Recently MemReentrancyGuard was added to DeviceState to record that the +device is engaging in I/O. The network device backend needs to update it +when delivering a packet to a device. + +In preparation for such a change, add MemReentrancyGuard * as a +parameter of qemu_new_nic(). + +Signed-off-by: Akihiko Odaki +Reviewed-by: Alexander Bulekov +Signed-off-by: Jason Wang +Signed-off-by: liuxiangdong +--- + hw/arm/musicpal.c | 3 ++- + hw/net/allwinner-sun8i-emac.c | 3 ++- + hw/net/allwinner_emac.c | 3 ++- + hw/net/cadence_gem.c | 3 ++- + hw/net/dp8393x.c | 3 ++- + hw/net/e1000.c | 3 ++- + hw/net/e1000e.c | 2 +- + hw/net/eepro100.c | 4 +++- + hw/net/etraxfs_eth.c | 3 ++- + hw/net/fsl_etsec/etsec.c | 3 ++- + hw/net/ftgmac100.c | 3 ++- + hw/net/i82596.c | 2 +- + hw/net/imx_fec.c | 2 +- + hw/net/lan9118.c | 3 ++- + hw/net/mcf_fec.c | 3 ++- + hw/net/mipsnet.c | 3 ++- + hw/net/msf2-emac.c | 3 ++- + hw/net/ne2000-isa.c | 3 ++- + hw/net/ne2000-pci.c | 3 ++- + hw/net/npcm7xx_emc.c | 3 ++- + hw/net/opencores_eth.c | 3 ++- + hw/net/pcnet.c | 3 ++- + hw/net/rocker/rocker_fp.c | 4 ++-- + hw/net/rtl8139.c | 3 ++- + hw/net/smc91c111.c | 3 ++- + hw/net/spapr_llan.c | 3 ++- + hw/net/stellaris_enet.c | 3 ++- + hw/net/sungem.c | 2 +- + hw/net/sunhme.c | 3 ++- + hw/net/tulip.c | 3 ++- + hw/net/virtio-net.c | 6 ++++-- + hw/net/vmxnet3.c | 2 +- + hw/net/xen_nic.c | 2 +- + hw/net/xgmac.c | 3 ++- + hw/net/xilinx_axienet.c | 3 ++- + hw/net/xilinx_ethlite.c | 3 ++- + hw/usb/dev-network.c | 3 ++- + include/net/net.h | 1 + + net/net.c | 1 + + 39 files changed, 73 insertions(+), 39 deletions(-) + +diff --git a/hw/arm/musicpal.c b/hw/arm/musicpal.c +index 2680ec55b5..15fc7fee41 100644 +--- a/hw/arm/musicpal.c ++++ b/hw/arm/musicpal.c +@@ -418,7 +418,8 @@ static void mv88w8618_eth_realize(DeviceState *dev, Error **errp) + + address_space_init(&s->dma_as, s->dma_mr, "emac-dma"); + s->nic = qemu_new_nic(&net_mv88w8618_info, &s->conf, +- object_get_typename(OBJECT(dev)), dev->id, s); ++ object_get_typename(OBJECT(dev)), dev->id, ++ &dev->mem_reentrancy_guard, s); + } + + static const VMStateDescription mv88w8618_eth_vmsd = { +diff --git a/hw/net/allwinner-sun8i-emac.c b/hw/net/allwinner-sun8i-emac.c +index ecc0245fe8..cf93b2fdac 100644 +--- a/hw/net/allwinner-sun8i-emac.c ++++ b/hw/net/allwinner-sun8i-emac.c +@@ -816,7 +816,8 @@ static void allwinner_sun8i_emac_realize(DeviceState *dev, Error **errp) + + qemu_macaddr_default_if_unset(&s->conf.macaddr); + s->nic = qemu_new_nic(&net_allwinner_sun8i_emac_info, &s->conf, +- object_get_typename(OBJECT(dev)), dev->id, s); ++ object_get_typename(OBJECT(dev)), dev->id, ++ &dev->mem_reentrancy_guard, s); + qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a); + } + +diff --git a/hw/net/allwinner_emac.c b/hw/net/allwinner_emac.c +index ddddf35c45..b3d73143bf 100644 +--- a/hw/net/allwinner_emac.c ++++ b/hw/net/allwinner_emac.c +@@ -453,7 +453,8 @@ static void aw_emac_realize(DeviceState *dev, Error **errp) + + qemu_macaddr_default_if_unset(&s->conf.macaddr); + s->nic = qemu_new_nic(&net_aw_emac_info, &s->conf, +- object_get_typename(OBJECT(dev)), dev->id, s); ++ object_get_typename(OBJECT(dev)), dev->id, ++ &dev->mem_reentrancy_guard, s); + qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a); + + fifo8_create(&s->rx_fifo, RX_FIFO_SIZE); +diff --git a/hw/net/cadence_gem.c b/hw/net/cadence_gem.c +index 21e1bd091f..bd7585c018 100644 +--- a/hw/net/cadence_gem.c ++++ b/hw/net/cadence_gem.c +@@ -1633,7 +1633,8 @@ static void gem_realize(DeviceState *dev, Error **errp) + qemu_macaddr_default_if_unset(&s->conf.macaddr); + + s->nic = qemu_new_nic(&net_gem_info, &s->conf, +- object_get_typename(OBJECT(dev)), dev->id, s); ++ object_get_typename(OBJECT(dev)), dev->id, ++ &dev->mem_reentrancy_guard, s); + + if (s->jumbo_max_len > MAX_FRAME_SIZE) { + error_setg(errp, "jumbo-max-len is greater than %d", +diff --git a/hw/net/dp8393x.c b/hw/net/dp8393x.c +index 45b954e46c..abfcc6f69f 100644 +--- a/hw/net/dp8393x.c ++++ b/hw/net/dp8393x.c +@@ -943,7 +943,8 @@ static void dp8393x_realize(DeviceState *dev, Error **errp) + "dp8393x-regs", SONIC_REG_COUNT << s->it_shift); + + s->nic = qemu_new_nic(&net_dp83932_info, &s->conf, +- object_get_typename(OBJECT(dev)), dev->id, s); ++ object_get_typename(OBJECT(dev)), dev->id, ++ &dev->mem_reentrancy_guard, s); + qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a); + + s->watchdog = timer_new_ns(QEMU_CLOCK_VIRTUAL, dp8393x_watchdog, s); +diff --git a/hw/net/e1000.c b/hw/net/e1000.c +index e26e0a64c1..33cd33a8ff 100644 +--- a/hw/net/e1000.c ++++ b/hw/net/e1000.c +@@ -1736,7 +1736,8 @@ static void pci_e1000_realize(PCIDevice *pci_dev, Error **errp) + macaddr); + + d->nic = qemu_new_nic(&net_e1000_info, &d->conf, +- object_get_typename(OBJECT(d)), dev->id, d); ++ object_get_typename(OBJECT(d)), dev->id, ++ &dev->mem_reentrancy_guard, d); + + qemu_format_nic_info_str(qemu_get_queue(d->nic), macaddr); + +diff --git a/hw/net/e1000e.c b/hw/net/e1000e.c +index ac96f7665a..b6e9b0e178 100644 +--- a/hw/net/e1000e.c ++++ b/hw/net/e1000e.c +@@ -328,7 +328,7 @@ e1000e_init_net_peer(E1000EState *s, PCIDevice *pci_dev, uint8_t *macaddr) + int i; + + s->nic = qemu_new_nic(&net_e1000e_info, &s->conf, +- object_get_typename(OBJECT(s)), dev->id, s); ++ object_get_typename(OBJECT(s)), dev->id, &dev->mem_reentrancy_guard, s); + + s->core.max_queue_num = s->conf.peers.queues ? s->conf.peers.queues - 1 : 0; + +diff --git a/hw/net/eepro100.c b/hw/net/eepro100.c +index 9c178c1448..074d54ec97 100644 +--- a/hw/net/eepro100.c ++++ b/hw/net/eepro100.c +@@ -1886,7 +1886,9 @@ static void e100_nic_realize(PCIDevice *pci_dev, Error **errp) + nic_reset(s); + + s->nic = qemu_new_nic(&net_eepro100_info, &s->conf, +- object_get_typename(OBJECT(pci_dev)), pci_dev->qdev.id, s); ++ object_get_typename(OBJECT(pci_dev)), ++ pci_dev->qdev.id, ++ &pci_dev->qdev.mem_reentrancy_guard, s); + + qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a); + TRACE(OTHER, logout("%s\n", qemu_get_queue(s->nic)->info_str)); +diff --git a/hw/net/etraxfs_eth.c b/hw/net/etraxfs_eth.c +index 1b82aec794..ba57a978d1 100644 +--- a/hw/net/etraxfs_eth.c ++++ b/hw/net/etraxfs_eth.c +@@ -618,7 +618,8 @@ static void etraxfs_eth_realize(DeviceState *dev, Error **errp) + + qemu_macaddr_default_if_unset(&s->conf.macaddr); + s->nic = qemu_new_nic(&net_etraxfs_info, &s->conf, +- object_get_typename(OBJECT(s)), dev->id, s); ++ object_get_typename(OBJECT(s)), dev->id, ++ &dev->mem_reentrancy_guard, s); + qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a); + + s->phy.read = tdk_read; +diff --git a/hw/net/fsl_etsec/etsec.c b/hw/net/fsl_etsec/etsec.c +index bd9d62b559..f790613b52 100644 +--- a/hw/net/fsl_etsec/etsec.c ++++ b/hw/net/fsl_etsec/etsec.c +@@ -391,7 +391,8 @@ static void etsec_realize(DeviceState *dev, Error **errp) + eTSEC *etsec = ETSEC_COMMON(dev); + + etsec->nic = qemu_new_nic(&net_etsec_info, &etsec->conf, +- object_get_typename(OBJECT(dev)), dev->id, etsec); ++ object_get_typename(OBJECT(dev)), dev->id, ++ &dev->mem_reentrancy_guard, etsec); + qemu_format_nic_info_str(qemu_get_queue(etsec->nic), etsec->conf.macaddr.a); + + etsec->ptimer = ptimer_init(etsec_timer_hit, etsec, PTIMER_POLICY_DEFAULT); +diff --git a/hw/net/ftgmac100.c b/hw/net/ftgmac100.c +index d3bf14be53..be2cf63c08 100644 +--- a/hw/net/ftgmac100.c ++++ b/hw/net/ftgmac100.c +@@ -1118,7 +1118,8 @@ static void ftgmac100_realize(DeviceState *dev, Error **errp) + qemu_macaddr_default_if_unset(&s->conf.macaddr); + + s->nic = qemu_new_nic(&net_ftgmac100_info, &s->conf, +- object_get_typename(OBJECT(dev)), dev->id, s); ++ object_get_typename(OBJECT(dev)), dev->id, ++ &dev->mem_reentrancy_guard, s); + qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a); + } + +diff --git a/hw/net/i82596.c b/hw/net/i82596.c +index ec21e2699a..dc64246f75 100644 +--- a/hw/net/i82596.c ++++ b/hw/net/i82596.c +@@ -743,7 +743,7 @@ void i82596_common_init(DeviceState *dev, I82596State *s, NetClientInfo *info) + qemu_macaddr_default_if_unset(&s->conf.macaddr); + } + s->nic = qemu_new_nic(info, &s->conf, object_get_typename(OBJECT(dev)), +- dev->id, s); ++ dev->id, &dev->mem_reentrancy_guard, s); + qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a); + + if (USE_TIMER) { +diff --git a/hw/net/imx_fec.c b/hw/net/imx_fec.c +index 0db9aaf76a..74e7e0d122 100644 +--- a/hw/net/imx_fec.c ++++ b/hw/net/imx_fec.c +@@ -1318,7 +1318,7 @@ static void imx_eth_realize(DeviceState *dev, Error **errp) + + s->nic = qemu_new_nic(&imx_eth_net_info, &s->conf, + object_get_typename(OBJECT(dev)), +- dev->id, s); ++ dev->id, &dev->mem_reentrancy_guard, s); + + qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a); + } +diff --git a/hw/net/lan9118.c b/hw/net/lan9118.c +index 6aff424cbe..942bce9ae6 100644 +--- a/hw/net/lan9118.c ++++ b/hw/net/lan9118.c +@@ -1354,7 +1354,8 @@ static void lan9118_realize(DeviceState *dev, Error **errp) + qemu_macaddr_default_if_unset(&s->conf.macaddr); + + s->nic = qemu_new_nic(&net_lan9118_info, &s->conf, +- object_get_typename(OBJECT(dev)), dev->id, s); ++ object_get_typename(OBJECT(dev)), dev->id, ++ &dev->mem_reentrancy_guard, s); + qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a); + s->eeprom[0] = 0xa5; + for (i = 0; i < 6; i++) { +diff --git a/hw/net/mcf_fec.c b/hw/net/mcf_fec.c +index 25e3e453ab..a6be7bf413 100644 +--- a/hw/net/mcf_fec.c ++++ b/hw/net/mcf_fec.c +@@ -643,7 +643,8 @@ static void mcf_fec_realize(DeviceState *dev, Error **errp) + mcf_fec_state *s = MCF_FEC_NET(dev); + + s->nic = qemu_new_nic(&net_mcf_fec_info, &s->conf, +- object_get_typename(OBJECT(dev)), dev->id, s); ++ object_get_typename(OBJECT(dev)), dev->id, ++ &dev->mem_reentrancy_guard, s); + qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a); + } + +diff --git a/hw/net/mipsnet.c b/hw/net/mipsnet.c +index 2ade72dea0..8e925de867 100644 +--- a/hw/net/mipsnet.c ++++ b/hw/net/mipsnet.c +@@ -255,7 +255,8 @@ static void mipsnet_realize(DeviceState *dev, Error **errp) + sysbus_init_irq(sbd, &s->irq); + + s->nic = qemu_new_nic(&net_mipsnet_info, &s->conf, +- object_get_typename(OBJECT(dev)), dev->id, s); ++ object_get_typename(OBJECT(dev)), dev->id, ++ &dev->mem_reentrancy_guard, s); + qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a); + } + +diff --git a/hw/net/msf2-emac.c b/hw/net/msf2-emac.c +index 9278fdce0b..1efa3dbf01 100644 +--- a/hw/net/msf2-emac.c ++++ b/hw/net/msf2-emac.c +@@ -527,7 +527,8 @@ static void msf2_emac_realize(DeviceState *dev, Error **errp) + + qemu_macaddr_default_if_unset(&s->conf.macaddr); + s->nic = qemu_new_nic(&net_msf2_emac_info, &s->conf, +- object_get_typename(OBJECT(dev)), dev->id, s); ++ object_get_typename(OBJECT(dev)), dev->id, ++ &dev->mem_reentrancy_guard, s); + qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a); + } + +diff --git a/hw/net/ne2000-isa.c b/hw/net/ne2000-isa.c +index dd6f6e34d3..30bd20c293 100644 +--- a/hw/net/ne2000-isa.c ++++ b/hw/net/ne2000-isa.c +@@ -74,7 +74,8 @@ static void isa_ne2000_realizefn(DeviceState *dev, Error **errp) + ne2000_reset(s); + + s->nic = qemu_new_nic(&net_ne2000_isa_info, &s->c, +- object_get_typename(OBJECT(dev)), dev->id, s); ++ object_get_typename(OBJECT(dev)), dev->id, ++ &dev->mem_reentrancy_guard, s); + qemu_format_nic_info_str(qemu_get_queue(s->nic), s->c.macaddr.a); + } + +diff --git a/hw/net/ne2000-pci.c b/hw/net/ne2000-pci.c +index 9e5d10859a..4f8a699081 100644 +--- a/hw/net/ne2000-pci.c ++++ b/hw/net/ne2000-pci.c +@@ -71,7 +71,8 @@ static void pci_ne2000_realize(PCIDevice *pci_dev, Error **errp) + + s->nic = qemu_new_nic(&net_ne2000_info, &s->c, + object_get_typename(OBJECT(pci_dev)), +- pci_dev->qdev.id, s); ++ pci_dev->qdev.id, ++ &pci_dev->qdev.mem_reentrancy_guard, s); + qemu_format_nic_info_str(qemu_get_queue(s->nic), s->c.macaddr.a); + } + +diff --git a/hw/net/npcm7xx_emc.c b/hw/net/npcm7xx_emc.c +index 9a2328935c..cafda78772 100644 +--- a/hw/net/npcm7xx_emc.c ++++ b/hw/net/npcm7xx_emc.c +@@ -804,7 +804,8 @@ static void npcm7xx_emc_realize(DeviceState *dev, Error **errp) + + qemu_macaddr_default_if_unset(&emc->conf.macaddr); + emc->nic = qemu_new_nic(&net_npcm7xx_emc_info, &emc->conf, +- object_get_typename(OBJECT(dev)), dev->id, emc); ++ object_get_typename(OBJECT(dev)), dev->id, ++ &dev->mem_reentrancy_guard, emc); + qemu_format_nic_info_str(qemu_get_queue(emc->nic), emc->conf.macaddr.a); + } + +diff --git a/hw/net/opencores_eth.c b/hw/net/opencores_eth.c +index 0b3dc3146e..f96d6ea2cc 100644 +--- a/hw/net/opencores_eth.c ++++ b/hw/net/opencores_eth.c +@@ -732,7 +732,8 @@ static void sysbus_open_eth_realize(DeviceState *dev, Error **errp) + sysbus_init_irq(sbd, &s->irq); + + s->nic = qemu_new_nic(&net_open_eth_info, &s->conf, +- object_get_typename(OBJECT(s)), dev->id, s); ++ object_get_typename(OBJECT(s)), dev->id, ++ &dev->mem_reentrancy_guard, s); + } + + static void qdev_open_eth_reset(DeviceState *dev) +diff --git a/hw/net/pcnet.c b/hw/net/pcnet.c +index dcd3fc4948..da910a70bf 100644 +--- a/hw/net/pcnet.c ++++ b/hw/net/pcnet.c +@@ -1718,7 +1718,8 @@ void pcnet_common_init(DeviceState *dev, PCNetState *s, NetClientInfo *info) + s->poll_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, pcnet_poll_timer, s); + + qemu_macaddr_default_if_unset(&s->conf.macaddr); +- s->nic = qemu_new_nic(info, &s->conf, object_get_typename(OBJECT(dev)), dev->id, s); ++ s->nic = qemu_new_nic(info, &s->conf, object_get_typename(OBJECT(dev)), ++ dev->id, &dev->mem_reentrancy_guard, s); + qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a); + + /* Initialize the PROM */ +diff --git a/hw/net/rocker/rocker_fp.c b/hw/net/rocker/rocker_fp.c +index cbeed65bd5..0d21948ada 100644 +--- a/hw/net/rocker/rocker_fp.c ++++ b/hw/net/rocker/rocker_fp.c +@@ -241,8 +241,8 @@ FpPort *fp_port_alloc(Rocker *r, char *sw_name, + port->conf.bootindex = -1; + port->conf.peers = *peers; + +- port->nic = qemu_new_nic(&fp_port_info, &port->conf, +- sw_name, NULL, port); ++ port->nic = qemu_new_nic(&fp_port_info, &port->conf, sw_name, NULL, ++ &DEVICE(r)->mem_reentrancy_guard, port); + qemu_format_nic_info_str(qemu_get_queue(port->nic), + port->conf.macaddr.a); + +diff --git a/hw/net/rtl8139.c b/hw/net/rtl8139.c +index 90b4fc63ce..43d65d7252 100644 +--- a/hw/net/rtl8139.c ++++ b/hw/net/rtl8139.c +@@ -3398,7 +3398,8 @@ static void pci_rtl8139_realize(PCIDevice *dev, Error **errp) + s->eeprom.contents[9] = s->conf.macaddr.a[4] | s->conf.macaddr.a[5] << 8; + + s->nic = qemu_new_nic(&net_rtl8139_info, &s->conf, +- object_get_typename(OBJECT(dev)), d->id, s); ++ object_get_typename(OBJECT(dev)), d->id, ++ &d->mem_reentrancy_guard, s); + qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a); + + s->cplus_txbuffer = NULL; +diff --git a/hw/net/smc91c111.c b/hw/net/smc91c111.c +index ad778cd8fc..4eda971ef3 100644 +--- a/hw/net/smc91c111.c ++++ b/hw/net/smc91c111.c +@@ -783,7 +783,8 @@ static void smc91c111_realize(DeviceState *dev, Error **errp) + sysbus_init_irq(sbd, &s->irq); + qemu_macaddr_default_if_unset(&s->conf.macaddr); + s->nic = qemu_new_nic(&net_smc91c111_info, &s->conf, +- object_get_typename(OBJECT(dev)), dev->id, s); ++ object_get_typename(OBJECT(dev)), dev->id, ++ &dev->mem_reentrancy_guard, s); + qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a); + /* ??? Save/restore. */ + } +diff --git a/hw/net/spapr_llan.c b/hw/net/spapr_llan.c +index a6876a936d..475d5f3a34 100644 +--- a/hw/net/spapr_llan.c ++++ b/hw/net/spapr_llan.c +@@ -325,7 +325,8 @@ static void spapr_vlan_realize(SpaprVioDevice *sdev, Error **errp) + memcpy(&dev->perm_mac.a, &dev->nicconf.macaddr.a, sizeof(dev->perm_mac.a)); + + dev->nic = qemu_new_nic(&net_spapr_vlan_info, &dev->nicconf, +- object_get_typename(OBJECT(sdev)), sdev->qdev.id, dev); ++ object_get_typename(OBJECT(sdev)), sdev->qdev.id, ++ &sdev->qdev.mem_reentrancy_guard, dev); + qemu_format_nic_info_str(qemu_get_queue(dev->nic), dev->nicconf.macaddr.a); + + dev->rxp_timer = timer_new_us(QEMU_CLOCK_VIRTUAL, spapr_vlan_flush_rx_queue, +diff --git a/hw/net/stellaris_enet.c b/hw/net/stellaris_enet.c +index 8dd60783d8..6768a6912f 100644 +--- a/hw/net/stellaris_enet.c ++++ b/hw/net/stellaris_enet.c +@@ -492,7 +492,8 @@ static void stellaris_enet_realize(DeviceState *dev, Error **errp) + qemu_macaddr_default_if_unset(&s->conf.macaddr); + + s->nic = qemu_new_nic(&net_stellaris_enet_info, &s->conf, +- object_get_typename(OBJECT(dev)), dev->id, s); ++ object_get_typename(OBJECT(dev)), dev->id, ++ &dev->mem_reentrancy_guard, s); + qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a); + } + +diff --git a/hw/net/sungem.c b/hw/net/sungem.c +index 3684a4d733..c12d44e9dc 100644 +--- a/hw/net/sungem.c ++++ b/hw/net/sungem.c +@@ -1361,7 +1361,7 @@ static void sungem_realize(PCIDevice *pci_dev, Error **errp) + qemu_macaddr_default_if_unset(&s->conf.macaddr); + s->nic = qemu_new_nic(&net_sungem_info, &s->conf, + object_get_typename(OBJECT(dev)), +- dev->id, s); ++ dev->id, &dev->mem_reentrancy_guard, s); + qemu_format_nic_info_str(qemu_get_queue(s->nic), + s->conf.macaddr.a); + } +diff --git a/hw/net/sunhme.c b/hw/net/sunhme.c +index fc34905f87..fa98528d71 100644 +--- a/hw/net/sunhme.c ++++ b/hw/net/sunhme.c +@@ -892,7 +892,8 @@ static void sunhme_realize(PCIDevice *pci_dev, Error **errp) + + qemu_macaddr_default_if_unset(&s->conf.macaddr); + s->nic = qemu_new_nic(&net_sunhme_info, &s->conf, +- object_get_typename(OBJECT(d)), d->id, s); ++ object_get_typename(OBJECT(d)), d->id, ++ &d->mem_reentrancy_guard, s); + qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a); + } + +diff --git a/hw/net/tulip.c b/hw/net/tulip.c +index b9e42c322a..d319f9fb80 100644 +--- a/hw/net/tulip.c ++++ b/hw/net/tulip.c +@@ -985,7 +985,8 @@ static void pci_tulip_realize(PCIDevice *pci_dev, Error **errp) + + s->nic = qemu_new_nic(&net_tulip_info, &s->c, + object_get_typename(OBJECT(pci_dev)), +- pci_dev->qdev.id, s); ++ pci_dev->qdev.id, ++ &pci_dev->qdev.mem_reentrancy_guard, s); + qemu_format_nic_info_str(qemu_get_queue(s->nic), s->c.macaddr.a); + } + +diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c +index 3e1fa6adf3..d7405c3bf1 100644 +--- a/hw/net/virtio-net.c ++++ b/hw/net/virtio-net.c +@@ -3585,10 +3585,12 @@ static void virtio_net_device_realize(DeviceState *dev, Error **errp) + * Happen when virtio_net_set_netclient_name has been called. + */ + n->nic = qemu_new_nic(&net_virtio_info, &n->nic_conf, +- n->netclient_type, n->netclient_name, n); ++ n->netclient_type, n->netclient_name, ++ &dev->mem_reentrancy_guard, n); + } else { + n->nic = qemu_new_nic(&net_virtio_info, &n->nic_conf, +- object_get_typename(OBJECT(dev)), dev->id, n); ++ object_get_typename(OBJECT(dev)), dev->id, ++ &dev->mem_reentrancy_guard, n); + } + + for (i = 0; i < n->max_queue_pairs; i++) { +diff --git a/hw/net/vmxnet3.c b/hw/net/vmxnet3.c +index a2037583bf..2a32ab32ea 100644 +--- a/hw/net/vmxnet3.c ++++ b/hw/net/vmxnet3.c +@@ -2080,7 +2080,7 @@ static void vmxnet3_net_init(VMXNET3State *s) + + s->nic = qemu_new_nic(&net_vmxnet3_info, &s->conf, + object_get_typename(OBJECT(s)), +- d->id, s); ++ d->id, &d->mem_reentrancy_guard, s); + + s->peer_has_vhdr = vmxnet3_peer_has_vnet_hdr(s); + s->tx_sop = true; +diff --git a/hw/net/xen_nic.c b/hw/net/xen_nic.c +index 5c815b4f0c..712fe6706d 100644 +--- a/hw/net/xen_nic.c ++++ b/hw/net/xen_nic.c +@@ -294,7 +294,7 @@ static int net_init(struct XenLegacyDevice *xendev) + } + + netdev->nic = qemu_new_nic(&net_xen_info, &netdev->conf, +- "xen", NULL, netdev); ++ "xen", NULL, &xendev->qdev.mem_reentrancy_guard, netdev); + + snprintf(qemu_get_queue(netdev->nic)->info_str, + sizeof(qemu_get_queue(netdev->nic)->info_str), +diff --git a/hw/net/xgmac.c b/hw/net/xgmac.c +index 0ab6ae91aa..1f4f277d84 100644 +--- a/hw/net/xgmac.c ++++ b/hw/net/xgmac.c +@@ -402,7 +402,8 @@ static void xgmac_enet_realize(DeviceState *dev, Error **errp) + + qemu_macaddr_default_if_unset(&s->conf.macaddr); + s->nic = qemu_new_nic(&net_xgmac_enet_info, &s->conf, +- object_get_typename(OBJECT(dev)), dev->id, s); ++ object_get_typename(OBJECT(dev)), dev->id, ++ &dev->mem_reentrancy_guard, s); + qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a); + + s->regs[XGMAC_ADDR_HIGH(0)] = (s->conf.macaddr.a[5] << 8) | +diff --git a/hw/net/xilinx_axienet.c b/hw/net/xilinx_axienet.c +index 990ff3a1c2..8a34243803 100644 +--- a/hw/net/xilinx_axienet.c ++++ b/hw/net/xilinx_axienet.c +@@ -968,7 +968,8 @@ static void xilinx_enet_realize(DeviceState *dev, Error **errp) + + qemu_macaddr_default_if_unset(&s->conf.macaddr); + s->nic = qemu_new_nic(&net_xilinx_enet_info, &s->conf, +- object_get_typename(OBJECT(dev)), dev->id, s); ++ object_get_typename(OBJECT(dev)), dev->id, ++ &dev->mem_reentrancy_guard, s); + qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a); + + tdk_init(&s->TEMAC.phy); +diff --git a/hw/net/xilinx_ethlite.c b/hw/net/xilinx_ethlite.c +index 6e09f7e422..80cb869e22 100644 +--- a/hw/net/xilinx_ethlite.c ++++ b/hw/net/xilinx_ethlite.c +@@ -235,7 +235,8 @@ static void xilinx_ethlite_realize(DeviceState *dev, Error **errp) + + qemu_macaddr_default_if_unset(&s->conf.macaddr); + s->nic = qemu_new_nic(&net_xilinx_ethlite_info, &s->conf, +- object_get_typename(OBJECT(dev)), dev->id, s); ++ object_get_typename(OBJECT(dev)), dev->id, ++ &dev->mem_reentrancy_guard, s); + qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a); + } + +diff --git a/hw/usb/dev-network.c b/hw/usb/dev-network.c +index 6c49c16015..ae447a8bc3 100644 +--- a/hw/usb/dev-network.c ++++ b/hw/usb/dev-network.c +@@ -1362,7 +1362,8 @@ static void usb_net_realize(USBDevice *dev, Error **errp) + + qemu_macaddr_default_if_unset(&s->conf.macaddr); + s->nic = qemu_new_nic(&net_usbnet_info, &s->conf, +- object_get_typename(OBJECT(s)), s->dev.qdev.id, s); ++ object_get_typename(OBJECT(s)), s->dev.qdev.id, ++ &s->dev.qdev.mem_reentrancy_guard, s); + qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a); + snprintf(s->usbstring_mac, sizeof(s->usbstring_mac), + "%02x%02x%02x%02x%02x%02x", +diff --git a/include/net/net.h b/include/net/net.h +index 81d0b21def..f5313b7e4e 100644 +--- a/include/net/net.h ++++ b/include/net/net.h +@@ -151,6 +151,7 @@ NICState *qemu_new_nic(NetClientInfo *info, + NICConf *conf, + const char *model, + const char *name, ++ MemReentrancyGuard *reentrancy_guard, + void *opaque); + void qemu_del_nic(NICState *nic); + NetClientState *qemu_get_subqueue(NICState *nic, int queue_index); +diff --git a/net/net.c b/net/net.c +index daad8784ec..e4e4cf45a2 100644 +--- a/net/net.c ++++ b/net/net.c +@@ -299,6 +299,7 @@ NICState *qemu_new_nic(NetClientInfo *info, + NICConf *conf, + const char *model, + const char *name, ++ MemReentrancyGuard *reentrancy_guard, + void *opaque) + { + NetClientState **peers = conf->peers.ncs; +-- +2.27.0 + diff --git a/net-Update-MemReentrancyGuard-for-NIC-CVE-2023-3019.patch b/net-Update-MemReentrancyGuard-for-NIC-CVE-2023-3019.patch new file mode 100644 index 00000000..88ce75f3 --- /dev/null +++ b/net-Update-MemReentrancyGuard-for-NIC-CVE-2023-3019.patch @@ -0,0 +1,85 @@ +From e69961a3c833e79dbcaca3f651b6f0ebfc86c93b Mon Sep 17 00:00:00 2001 +From: Akihiko Odaki +Date: Thu, 1 Jun 2023 12:18:59 +0900 +Subject: [PATCH] net: Update MemReentrancyGuard for NIC (CVE-2023-3019) + +Recently MemReentrancyGuard was added to DeviceState to record that the +device is engaging in I/O. The network device backend needs to update it +when delivering a packet to a device. + +This implementation follows what bottom half does, but it does not add +a tracepoint for the case that the network device backend started +delivering a packet to a device which is already engaging in I/O. This +is because such reentrancy frequently happens for +qemu_flush_queued_packets() and is insignificant. + +Fixes: CVE-2023-3019 +Reported-by: Alexander Bulekov +Signed-off-by: Akihiko Odaki +Acked-by: Alexander Bulekov +Signed-off-by: Jason Wang +--- + include/net/net.h | 1 + + net/net.c | 14 ++++++++++++++ + 2 files changed, 15 insertions(+) + +diff --git a/include/net/net.h b/include/net/net.h +index f5313b7e4e..b55f6cf698 100644 +--- a/include/net/net.h ++++ b/include/net/net.h +@@ -118,6 +118,7 @@ struct NetClientState { + typedef struct NICState { + NetClientState *ncs; + NICConf *conf; ++ MemReentrancyGuard *reentrancy_guard; + void *opaque; + bool peer_deleted; + } NICState; +diff --git a/net/net.c b/net/net.c +index e4e4cf45a2..abdb9dfdc5 100644 +--- a/net/net.c ++++ b/net/net.c +@@ -312,6 +312,7 @@ NICState *qemu_new_nic(NetClientInfo *info, + nic = g_malloc0(info->size + sizeof(NetClientState) * queues); + nic->ncs = (void *)nic + info->size; + nic->conf = conf; ++ nic->reentrancy_guard = reentrancy_guard, + nic->opaque = opaque; + + for (i = 0; i < queues; i++) { +@@ -767,6 +768,7 @@ static ssize_t qemu_deliver_packet_iov(NetClientState *sender, + int iovcnt, + void *opaque) + { ++ MemReentrancyGuard *owned_reentrancy_guard; + NetClientState *nc = opaque; + int ret; + +@@ -779,12 +781,24 @@ static ssize_t qemu_deliver_packet_iov(NetClientState *sender, + return 0; + } + ++ if (nc->info->type != NET_CLIENT_DRIVER_NIC || ++ qemu_get_nic(nc)->reentrancy_guard->engaged_in_io) { ++ owned_reentrancy_guard = NULL; ++ } else { ++ owned_reentrancy_guard = qemu_get_nic(nc)->reentrancy_guard; ++ owned_reentrancy_guard->engaged_in_io = true; ++ } ++ + if (nc->info->receive_iov && !(flags & QEMU_NET_PACKET_FLAG_RAW)) { + ret = nc->info->receive_iov(nc, iov, iovcnt); + } else { + ret = nc_sendv_compat(nc, iov, iovcnt, flags); + } + ++ if (owned_reentrancy_guard) { ++ owned_reentrancy_guard->engaged_in_io = false; ++ } ++ + if (ret == 0) { + nc->receive_disabled = 1; + } +-- +2.27.0 + diff --git a/qemu.spec b/qemu.spec index 130ec0f8..9faf51e8 100644 --- a/qemu.spec +++ b/qemu.spec @@ -3,7 +3,7 @@ Name: qemu Version: 6.2.0 -Release: 88 +Release: 89 Epoch: 10 Summary: QEMU is a generic and open source machine emulator and virtualizer License: GPLv2 and BSD and MIT and CC-BY-SA-4.0 @@ -865,6 +865,16 @@ Patch0850: linux-user-fix-sockaddr_in6-endianness.patch Patch0851: migration-multifd-Remove-unnecessary-usage-of-local-.patch Patch0852: hw-i386-Fix-comment-style-in-topology.h.patch Patch0853: ui-vnc.c-Fixed-a-deadlock-bug.patch +Patch0854: memory-prevent-dma-reentracy-issues.patch +Patch0855: net-Provide-MemReentrancyGuard-to-qemu_new_nic.patch +Patch0856: net-Update-MemReentrancyGuard-for-NIC-CVE-2023-3019.patch +Patch0857: hw-scsi-lsi53c895a-Fix-reentrancy-issues-in-the-LSI-.patch +Patch0858: hw-scsi-lsi53c895a-add-missing-decrement-of-reentran.patch +Patch0859: esp-restrict-non-DMA-transfer-length-to-that-of-avai.patch +Patch0860: ui-clipboard-mark-type-as-not-available-when-there-i.patch +Patch0861: virtio-net-correctly-copy-vnet-header-when-flushing-.patch +Patch0862: hw-timer-fix-systick-trace-message.patch +Patch0863: qga-win-Fix-guest-get-fsinfo-multi-disks-collection.patch BuildRequires: flex BuildRequires: gcc @@ -1463,6 +1473,17 @@ getent passwd qemu >/dev/null || \ %endif %changelog +* Sat Mar 9 2024 - 10:6.2.0-89 +- qga-win: Fix guest-get-fsinfo multi-disks collection +- hw/timer: fix systick trace message +- virtio-net: correctly copy vnet header when flushing TX (CVE-2023-6693) +- ui/clipboard: mark type as not available when there is no data (CVE-2023-6683) +- esp: restrict non-DMA transfer length to that of available data (CVE-2024-24474) +- hw/scsi/lsi53c895a: add missing decrement of reentrancy counter +- hw/scsi/lsi53c895a: Fix reentrancy issues in the LSI controller (CVE-2023-0330) +- net: Update MemReentrancyGuard for NIC (CVE-2023-3019) +- net: Provide MemReentrancyGuard * to qemu_new_nic() + * Wed Feb 21 2024 - 10:6.2.0-88 - ui/vnc.c: Fixed a deadlock bug. - hw/i386: Fix comment style in topology.h diff --git a/qga-win-Fix-guest-get-fsinfo-multi-disks-collection.patch b/qga-win-Fix-guest-get-fsinfo-multi-disks-collection.patch new file mode 100644 index 00000000..2683affb --- /dev/null +++ b/qga-win-Fix-guest-get-fsinfo-multi-disks-collection.patch @@ -0,0 +1,40 @@ +From bf48c640251cfe8d9ed7744bc88f5a858b694275 Mon Sep 17 00:00:00 2001 +From: qihao +Date: Wed, 7 Feb 2024 17:26:58 +0800 +Subject: [PATCH] qga-win: Fix guest-get-fsinfo multi-disks collection + +cheery-pick from 7c4486350a79532580a37d42abdeb1dc7e4fa6c9 + +When a volume has more than one disk, all disks cannot be +returned correctly because there is not enough malloced memory +for disk extents, so before executing DeviceIoControl for the +second time, get the correct size of the required memory space +to store all disk extents. + +Details: +https://learn.microsoft.com/en-us/windows/win32/api/winioctl/ns-winioctl-volume_disk_extents + +Signed-off-by: Peng Ji +Reviewed-by: Konstantin Kostiuk +Signed-off-by: Konstantin Kostiuk +Signed-off-by: qihao_yewu +--- + qga/commands-win32.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/qga/commands-win32.c b/qga/commands-win32.c +index 4e84afd83b..30e50f1769 100644 +--- a/qga/commands-win32.c ++++ b/qga/commands-win32.c +@@ -904,6 +904,8 @@ static GuestDiskAddressList *build_guest_disk_info(char *guid, Error **errp) + DWORD last_err = GetLastError(); + if (last_err == ERROR_MORE_DATA) { + /* Try once more with big enough buffer */ ++ size = sizeof(VOLUME_DISK_EXTENTS) + ++ (sizeof(DISK_EXTENT) * (extents->NumberOfDiskExtents - 1)); + g_free(extents); + extents = g_malloc0(size); + if (!DeviceIoControl( +-- +2.27.0 + diff --git a/ui-clipboard-mark-type-as-not-available-when-there-i.patch b/ui-clipboard-mark-type-as-not-available-when-there-i.patch new file mode 100644 index 00000000..e698dec1 --- /dev/null +++ b/ui-clipboard-mark-type-as-not-available-when-there-i.patch @@ -0,0 +1,89 @@ +From 6c61db85b2410480a203febabd12130a81f6f975 Mon Sep 17 00:00:00 2001 +From: Fiona Ebner +Date: Wed, 24 Jan 2024 11:57:48 +0100 +Subject: [PATCH] ui/clipboard: mark type as not available when there is no + data (CVE-2023-6683) +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +With VNC, a client can send a non-extended VNC_MSG_CLIENT_CUT_TEXT +message with len=0. In qemu_clipboard_set_data(), the clipboard info +will be updated setting data to NULL (because g_memdup(data, size) +returns NULL when size is 0). If the client does not set the +VNC_ENCODING_CLIPBOARD_EXT feature when setting up the encodings, then +the 'request' callback for the clipboard peer is not initialized. +Later, because data is NULL, qemu_clipboard_request() can be reached +via vdagent_chr_write() and vdagent_clipboard_recv_request() and +there, the clipboard owner's 'request' callback will be attempted to +be called, but that is a NULL pointer. + +In particular, this can happen when using the KRDC (22.12.3) VNC +client. + +Another scenario leading to the same issue is with two clients (say +noVNC and KRDC): + +The noVNC client sets the extension VNC_FEATURE_CLIPBOARD_EXT and +initializes its cbpeer. + +The KRDC client does not, but triggers a vnc_client_cut_text() (note +it's not the _ext variant)). There, a new clipboard info with it as +the 'owner' is created and via qemu_clipboard_set_data() is called, +which in turn calls qemu_clipboard_update() with that info. + +In qemu_clipboard_update(), the notifier for the noVNC client will be +called, i.e. vnc_clipboard_notify() and also set vs->cbinfo for the +noVNC client. The 'owner' in that clipboard info is the clipboard peer +for the KRDC client, which did not initialize the 'request' function. +That sounds correct to me, it is the owner of that clipboard info. + +Then when noVNC sends a VNC_MSG_CLIENT_CUT_TEXT message (it did set +the VNC_FEATURE_CLIPBOARD_EXT feature correctly, so a check for it +passes), that clipboard info is passed to qemu_clipboard_request() and +the original segfault still happens. + +Fix the issue by handling updates with size 0 differently. In +particular, mark in the clipboard info that the type is not available. + +While at it, switch to g_memdup2(), because g_memdup() is deprecated. + +Cc: qemu-stable@nongnu.org +Fixes: CVE-2023-6683 +Reported-by: Markus Frank +Suggested-by: Marc-André Lureau +Signed-off-by: Fiona Ebner +Reviewed-by: Marc-André Lureau +Tested-by: Markus Frank +Message-ID: <20240124105749.204610-1-f.ebner@proxmox.com> +Signed-off-by: liuxiangdong +--- + ui/clipboard.c | 12 +++++++++--- + 1 file changed, 9 insertions(+), 3 deletions(-) + +diff --git a/ui/clipboard.c b/ui/clipboard.c +index d7b008d62a..6721852cb6 100644 +--- a/ui/clipboard.c ++++ b/ui/clipboard.c +@@ -123,9 +123,15 @@ void qemu_clipboard_set_data(QemuClipboardPeer *peer, + } + + g_free(info->types[type].data); +- info->types[type].data = g_memdup(data, size); +- info->types[type].size = size; +- info->types[type].available = true; ++ if (size) { ++ info->types[type].data = g_memdup(data, size); ++ info->types[type].size = size; ++ info->types[type].available = true; ++ } else { ++ info->types[type].data = NULL; ++ info->types[type].size = 0; ++ info->types[type].available = false; ++ } + + if (update) { + qemu_clipboard_update(info); +-- +2.27.0 + diff --git a/virtio-net-correctly-copy-vnet-header-when-flushing-.patch b/virtio-net-correctly-copy-vnet-header-when-flushing-.patch new file mode 100644 index 00000000..850fb293 --- /dev/null +++ b/virtio-net-correctly-copy-vnet-header-when-flushing-.patch @@ -0,0 +1,72 @@ +From 15f89b0447956d16f9ff20e243fa9076e5dd9af1 Mon Sep 17 00:00:00 2001 +From: Jason Wang +Date: Tue, 2 Jan 2024 11:29:01 +0800 +Subject: [PATCH] virtio-net: correctly copy vnet header when flushing TX + (CVE-2023-6693) + +When HASH_REPORT is negotiated, the guest_hdr_len might be larger than +the size of the mergeable rx buffer header. Using +virtio_net_hdr_mrg_rxbuf during the header swap might lead a stack +overflow in this case. Fixing this by using virtio_net_hdr_v1_hash +instead. + +Reported-by: Xiao Lei +Cc: Yuri Benditovich +Cc: qemu-stable@nongnu.org +Cc: Mauro Matteo Cascella +Fixes: CVE-2023-6693 +Fixes: e22f0603fb2f ("virtio-net: reference implementation of hash report") +Reviewed-by: Michael Tokarev +Signed-off-by: Jason Wang +--- + hw/net/virtio-net.c | 13 +++++++++---- + 1 file changed, 9 insertions(+), 4 deletions(-) + +diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c +index d7405c3bf1..cdf1313053 100644 +--- a/hw/net/virtio-net.c ++++ b/hw/net/virtio-net.c +@@ -600,6 +600,11 @@ static void virtio_net_set_mrg_rx_bufs(VirtIONet *n, int mergeable_rx_bufs, + + n->mergeable_rx_bufs = mergeable_rx_bufs; + ++ /* ++ * Note: when extending the vnet header, please make sure to ++ * change the vnet header copying logic in virtio_net_flush_tx() ++ * as well. ++ */ + if (version_1) { + n->guest_hdr_len = hash_report ? + sizeof(struct virtio_net_hdr_v1_hash) : +@@ -2586,7 +2591,7 @@ static int32_t virtio_net_flush_tx(VirtIONetQueue *q) + ssize_t ret; + unsigned int out_num; + struct iovec sg[VIRTQUEUE_MAX_SIZE], sg2[VIRTQUEUE_MAX_SIZE + 1], *out_sg; +- struct virtio_net_hdr_mrg_rxbuf mhdr; ++ struct virtio_net_hdr_v1_hash vhdr; + + elem = virtqueue_pop(q->tx_vq, sizeof(VirtQueueElement)); + if (!elem) { +@@ -2603,7 +2608,7 @@ static int32_t virtio_net_flush_tx(VirtIONetQueue *q) + } + + if (n->has_vnet_hdr) { +- if (iov_to_buf(out_sg, out_num, 0, &mhdr, n->guest_hdr_len) < ++ if (iov_to_buf(out_sg, out_num, 0, &vhdr, n->guest_hdr_len) < + n->guest_hdr_len) { + virtio_error(vdev, "virtio-net header incorrect"); + virtqueue_detach_element(q->tx_vq, elem, 0); +@@ -2611,8 +2616,8 @@ static int32_t virtio_net_flush_tx(VirtIONetQueue *q) + return -EINVAL; + } + if (n->needs_vnet_hdr_swap) { +- virtio_net_hdr_swap(vdev, (void *) &mhdr); +- sg2[0].iov_base = &mhdr; ++ virtio_net_hdr_swap(vdev, (void *) &vhdr); ++ sg2[0].iov_base = &vhdr; + sg2[0].iov_len = n->guest_hdr_len; + out_num = iov_copy(&sg2[1], ARRAY_SIZE(sg2) - 1, + out_sg, out_num, +-- +2.27.0 + -- Gitee From 5d1a5160936dce1757c09050d97d12f42642794b Mon Sep 17 00:00:00 2001 From: Jiabo Feng Date: Sat, 16 Mar 2024 14:59:18 +0800 Subject: [PATCH 07/19] QEMU update to version 6.2.0-90 - i386/cpuid: Move leaf 7 to correct group - i386/cpuid: Decrease cpuid_i when skipping CPUID leaf 1F - i386/cpu: Mask with XCR0/XSS mask for FEAT_XSAVE_XCR0_HI and FEAT_XSAVE_XSS_HI leafs - i386/cpu: Clear FEAT_XSAVE_XSS_LO/HI leafs when CPUID_EXT_XSAVE is not available - target/i386: Change wrong XFRM value in SGX CPUID leaf - target/i386: Enable support for XSAVES based features - target/i386: Add kvm_get_one_msr helper - hw/block/hd-geometry: Do not override specified bios-chs-trans mainline inclusion commit fd8a68ad6823d33bedeba20a22857867a1c3890e category: bugfix - linux-user/riscv: Align signal frame to 16 bytes mainline inclusion commit 1eaa63429a9944265c92efdb94c02fabb231f564 category: bugfix - ipmi:smbus: Add a check around a memcpy mainline inclusion commit 3fde641e7286f9b968bdb3b4b922c6465f2a9abc category: bugfix - tests/tcg/linux-test: Fix random hangs in test_socket mainline inclusion commit b9e6074fc5b429b1e956e9c60db7e284a91e0f3d category: bugfix - qemu-options.hx: Don't claim "-serial" has limit of 4 serial ports Before v2.12, the implementation of serial ports was limited to a value of MAX_SERIAL_PORTS = 4. We now dynamically allocate the data structures for serial ports, so this limit is no longer present, but the documentation for the -serial options still reads: - target/ppc: Modify the uncorrect value irq to n_IRQ - block-migration: Ensure we don't crash during migration cleanup - target/s390x: fix handling of zeroes in vfmin/vfmax mainline inclusion commit 13c59eb09bd6d1fbc13f08b708226421f14a232b category: bugfix - hw/virtio/virtio-iommu: Enforce power-of-two notify for both MAP and UNMAP mainline inclusion commit 0522be9a0c0094088ccef7aab352c57f483ca250 category: bugfix - configure: Add missing POSIX-required space mainline inclusion commit 35a7a6fc5624b1df828d82f2dfa74d0e4188b3b2 category: bugfix - vga: fix incorrect line height in 640x200x2 mode mainline inclusion commit 37e7b86766244b62a406747bb78e049390d0b528 category: bugfix - hw/ide/core: set ERR_STAT in unsupported command completion - linux-user/flatload.c: Fix setting of image_info::end_code mainline inclusion commit 734a659ad264ac080457167e845ffabbaaa66d0e category: bugfix - load_elf: fix iterator's type for elf file processing - hw/misc/mps2-scc: Free MPS2SCC::oscclk[] array on finalize() - hw/nvram/xlnx-efuse: Free XlnxEFuse::ro_bits[] array on finalize() - hw/nvram/xlnx-efuse-ctrl: Free XlnxVersalEFuseCtrl[] "pg0-lock" array - chardev/char.c: fix "abstract device type" error message - block/rbd: fix handling of holes in .bdrv_co_block_status - qga: treat get-guest-fsinfo as "best effort" mainline inclusion commit bbb0151cf2e82489120a15df5e2eb9653312b0ec category: bugfix - usb/hcd-xhci: check slotid in xhci_wakeup_endpoint() mainline inclusion commit 84218892f05515d20347fde4506e1944eb11cb25 category: bugfix - hw/display/bcm2835_fb: Fix framebuffer allocation address mainline inclusion commit 5865d99fe88d8c8fa437c18c6b63fb2a8165634f category: bugfix - block/parallels: Fix buffer-based write call mainline inclusion commit eba088f91d21d9e42a81bef847173da30c5da961 category: bugfix - vl: Improve error message for conflicting -incoming and -loadvm - hw/smbios: Fix OEM strings table option validation Signed-off-by: Jiabo Feng --- ...Ensure-we-don-t-crash-during-migrati.patch | 67 ++++ ...arallels-Fix-buffer-based-write-call.patch | 48 +++ ...ndling-of-holes-in-.bdrv_co_block_st.patch | 52 ++++ ...ix-abstract-device-type-error-messag.patch | 37 +++ ...ure-Add-missing-POSIX-required-space.patch | 44 +++ ...etry-Do-not-override-specified-bios-.patch | 63 ++++ ...35_fb-Fix-framebuffer-allocation-add.patch | 53 ++++ ...ERR_STAT-in-unsupported-command-comp.patch | 60 ++++ ...-Free-MPS2SCC-oscclk-array-on-finali.patch | 63 ++++ ...use-Free-XlnxEFuse-ro_bits-array-on-.patch | 64 ++++ ...use-ctrl-Free-XlnxVersalEFuseCtrl-pg.patch | 65 ++++ ...-OEM-strings-table-option-validation.patch | 51 ++++ ...-iommu-Enforce-power-of-two-notify-f.patch | 113 +++++++ ...EAT_XSAVE_XSS_LO-HI-leafs-when-CPUID.patch | 41 +++ ...th-XCR0-XSS-mask-for-FEAT_XSAVE_XCR0.patch | 45 +++ ...ase-cpuid_i-when-skipping-CPUID-leaf.patch | 41 +++ i386-cpuid-Move-leaf-7-to-correct-group.patch | 53 ++++ ipmi-smbus-Add-a-check-around-a-memcpy.patch | 47 +++ ...oad.c-Fix-setting-of-image_info-end_.patch | 47 +++ ...riscv-Align-signal-frame-to-16-bytes.patch | 39 +++ ...rator-s-type-for-elf-file-processing.patch | 42 +++ ...Don-t-claim-serial-has-limit-of-4-se.patch | 41 +++ qemu.spec | 68 ++++- ...reat-get-guest-fsinfo-as-best-effort.patch | 56 ++++ target-i386-Add-kvm_get_one_msr-helper.patch | 123 ++++++++ ...ge-wrong-XFRM-value-in-SGX-CPUID-lea.patch | 46 +++ ...le-support-for-XSAVES-based-features.patch | 286 ++++++++++++++++++ ...ify-the-uncorrect-value-irq-to-n_IRQ.patch | 28 ++ ...ix-handling-of-zeroes-in-vfmin-vfmax.patch | 51 ++++ ...test-Fix-random-hangs-in-test_socket.patch | 41 +++ ...check-slotid-in-xhci_wakeup_endpoint.patch | 39 +++ ...orrect-line-height-in-640x200x2-mode.patch | 45 +++ ...-message-for-conflicting-incoming-an.patch | 47 +++ 33 files changed, 2005 insertions(+), 1 deletion(-) create mode 100644 block-migration-Ensure-we-don-t-crash-during-migrati.patch create mode 100644 block-parallels-Fix-buffer-based-write-call.patch create mode 100644 block-rbd-fix-handling-of-holes-in-.bdrv_co_block_st.patch create mode 100644 chardev-char.c-fix-abstract-device-type-error-messag.patch create mode 100644 configure-Add-missing-POSIX-required-space.patch create mode 100644 hw-block-hd-geometry-Do-not-override-specified-bios-.patch create mode 100644 hw-display-bcm2835_fb-Fix-framebuffer-allocation-add.patch create mode 100644 hw-ide-core-set-ERR_STAT-in-unsupported-command-comp.patch create mode 100644 hw-misc-mps2-scc-Free-MPS2SCC-oscclk-array-on-finali.patch create mode 100644 hw-nvram-xlnx-efuse-Free-XlnxEFuse-ro_bits-array-on-.patch create mode 100644 hw-nvram-xlnx-efuse-ctrl-Free-XlnxVersalEFuseCtrl-pg.patch create mode 100644 hw-smbios-Fix-OEM-strings-table-option-validation.patch create mode 100644 hw-virtio-virtio-iommu-Enforce-power-of-two-notify-f.patch create mode 100644 i386-cpu-Clear-FEAT_XSAVE_XSS_LO-HI-leafs-when-CPUID.patch create mode 100644 i386-cpu-Mask-with-XCR0-XSS-mask-for-FEAT_XSAVE_XCR0.patch create mode 100644 i386-cpuid-Decrease-cpuid_i-when-skipping-CPUID-leaf.patch create mode 100644 i386-cpuid-Move-leaf-7-to-correct-group.patch create mode 100644 ipmi-smbus-Add-a-check-around-a-memcpy.patch create mode 100644 linux-user-flatload.c-Fix-setting-of-image_info-end_.patch create mode 100644 linux-user-riscv-Align-signal-frame-to-16-bytes.patch create mode 100644 load_elf-fix-iterator-s-type-for-elf-file-processing.patch create mode 100644 qemu-options.hx-Don-t-claim-serial-has-limit-of-4-se.patch create mode 100644 qga-treat-get-guest-fsinfo-as-best-effort.patch create mode 100644 target-i386-Add-kvm_get_one_msr-helper.patch create mode 100644 target-i386-Change-wrong-XFRM-value-in-SGX-CPUID-lea.patch create mode 100644 target-i386-Enable-support-for-XSAVES-based-features.patch create mode 100644 target-ppc-Modify-the-uncorrect-value-irq-to-n_IRQ.patch create mode 100644 target-s390x-fix-handling-of-zeroes-in-vfmin-vfmax.patch create mode 100644 tests-tcg-linux-test-Fix-random-hangs-in-test_socket.patch create mode 100644 usb-hcd-xhci-check-slotid-in-xhci_wakeup_endpoint.patch create mode 100644 vga-fix-incorrect-line-height-in-640x200x2-mode.patch create mode 100644 vl-Improve-error-message-for-conflicting-incoming-an.patch diff --git a/block-migration-Ensure-we-don-t-crash-during-migrati.patch b/block-migration-Ensure-we-don-t-crash-during-migrati.patch new file mode 100644 index 00000000..ff1918d8 --- /dev/null +++ b/block-migration-Ensure-we-don-t-crash-during-migrati.patch @@ -0,0 +1,67 @@ +From 98d4a8d9d5823d7d43ea816208a35372124a749f Mon Sep 17 00:00:00 2001 +From: zhujun2 +Date: Sun, 10 Mar 2024 22:52:08 -0700 +Subject: [PATCH] block-migration: Ensure we don't crash during migration + cleanup + +We can fail the blk_insert_bs() at init_blk_migration(), leaving the +BlkMigDevState without a dirty_bitmap and BlockDriverState. Account +for the possibly missing elements when doing cleanup. + +Fix the following crashes: + +Thread 1 "qemu-system-x86" received signal SIGSEGV, Segmentation fault. +0x0000555555ec83ef in bdrv_release_dirty_bitmap (bitmap=0x0) at ../block/dirty-bitmap.c:359 +359 BlockDriverState *bs = bitmap->bs; + +Thread 1 "qemu-system-x86" received signal SIGSEGV, Segmentation fault. +0x0000555555e971ff in bdrv_op_unblock (bs=0x0, op=BLOCK_OP_TYPE_BACKUP_SOURCE, reason=0x0) at ../block.c:7073 +7073 QLIST_FOREACH_SAFE(blocker, &bs->op_blockers[op], list, next) { + +Signed-off-by: Fabiano Rosas +Message-id: 20230731203338.27581-1-farosas@suse.de> +Signed-off-by: Stefan Hajnoczi +(cherry picked from commit f187609f27b261702a17f79d20bf252ee0d4f9cd) +Signed-off-by: zhujun2 +--- + migration/block.c | 11 +++++++++-- + 1 file changed, 9 insertions(+), 2 deletions(-) + +diff --git a/migration/block.c b/migration/block.c +index a950977855..391f8169fd 100644 +--- a/migration/block.c ++++ b/migration/block.c +@@ -376,7 +376,9 @@ static void unset_dirty_tracking(void) + BlkMigDevState *bmds; + + QSIMPLEQ_FOREACH(bmds, &block_mig_state.bmds_list, entry) { +- bdrv_release_dirty_bitmap(bmds->dirty_bitmap); ++ if (bmds->dirty_bitmap) { ++ bdrv_release_dirty_bitmap(bmds->dirty_bitmap); ++ } + } + } + +@@ -684,13 +686,18 @@ static int64_t get_remaining_dirty(void) + static void block_migration_cleanup_bmds(void) + { + BlkMigDevState *bmds; ++ BlockDriverState *bs; + AioContext *ctx; + + unset_dirty_tracking(); + + while ((bmds = QSIMPLEQ_FIRST(&block_mig_state.bmds_list)) != NULL) { + QSIMPLEQ_REMOVE_HEAD(&block_mig_state.bmds_list, entry); +- bdrv_op_unblock_all(blk_bs(bmds->blk), bmds->blocker); ++ ++ bs = blk_bs(bmds->blk); ++ if (bs) { ++ bdrv_op_unblock_all(bs,bmds->blocker); ++ } + error_free(bmds->blocker); + + /* Save ctx, because bmds->blk can disappear during blk_unref. */ +-- +2.27.0 + diff --git a/block-parallels-Fix-buffer-based-write-call.patch b/block-parallels-Fix-buffer-based-write-call.patch new file mode 100644 index 00000000..ac0b003e --- /dev/null +++ b/block-parallels-Fix-buffer-based-write-call.patch @@ -0,0 +1,48 @@ +From 38de3be1e41bff18bf21cbf16a1dc585359dd4bd Mon Sep 17 00:00:00 2001 +From: tangbinzy +Date: Fri, 8 Mar 2024 05:39:12 +0000 +Subject: [PATCH] block/parallels: Fix buffer-based write call mainline + inclusion commit eba088f91d21d9e42a81bef847173da30c5da961 category: bugfix + +--------------------------------------------------------------- + +Commit a4072543ccdddbd241d5962d9237b8b41fd006bf has changed the I/O here +from working on a local one-element I/O vector to just using the buffer +directly (using the bdrv_co_pread()/bdrv_co_pwrite() helper functions +introduced shortly before). + +However, it only changed the bdrv_co_preadv() call to bdrv_co_pread() - +the subsequent bdrv_co_pwritev() call stayed this way, and so still +expects a QEMUIOVector pointer instead of a plain buffer. We must +change that to be a bdrv_co_pwrite() call. + +Fixes: a4072543ccdddbd241d5962d ("block/parallels: use buffer-based io") +Signed-off-by: Hanna Reitz +Reviewed-by: Denis V. Lunev +Reviewed-by: Vladimir Sementsov-Ogievskiy +Message-Id: <20220714132801.72464-2-hreitz@redhat.com> +Signed-off-by: Vladimir Sementsov-Ogievskiy + +Signed-off-by: tangbinzy +--- + block/parallels.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/block/parallels.c b/block/parallels.c +index 6ebad2a2bb..f3352b6aa7 100644 +--- a/block/parallels.c ++++ b/block/parallels.c +@@ -240,8 +240,8 @@ static int64_t allocate_clusters(BlockDriverState *bs, int64_t sector_num, + return ret; + } + +- ret = bdrv_co_pwritev(bs->file, s->data_end * BDRV_SECTOR_SIZE, +- nb_cow_bytes, buf, 0); ++ ret = bdrv_co_pwrite(bs->file, s->data_end * BDRV_SECTOR_SIZE, ++ nb_cow_bytes, buf, 0); + qemu_vfree(buf); + if (ret < 0) { + return ret; +-- +2.27.0 + diff --git a/block-rbd-fix-handling-of-holes-in-.bdrv_co_block_st.patch b/block-rbd-fix-handling-of-holes-in-.bdrv_co_block_st.patch new file mode 100644 index 00000000..b3e2b5d9 --- /dev/null +++ b/block-rbd-fix-handling-of-holes-in-.bdrv_co_block_st.patch @@ -0,0 +1,52 @@ +From 3e4478d7b2669063f7b2b1caf80c73535f35b5a4 Mon Sep 17 00:00:00 2001 +From: Luo Yifan +Date: Thu, 7 Mar 2024 17:51:57 +0800 +Subject: [PATCH] block/rbd: fix handling of holes in .bdrv_co_block_status + +cherry picked from commit 9e302f64bb407a9bb097b626da97228c2654cfee + +the assumption that we can't hit a hole if we do not diff against a snapshot was wrong. + +We can see a hole in an image if we diff against base if there exists an older snapshot +of the image and we have discarded blocks in the image where the snapshot has data. + +Fix this by simply handling a hole like an unallocated area. There are no callbacks +for unallocated areas so just bail out if we hit a hole. + +Fixes: 0347a8fd4c3faaedf119be04c197804be40a384b +Suggested-by: Ilya Dryomov +Cc: qemu-stable@nongnu.org +Signed-off-by: Peter Lieven +Message-Id: <20220113144426.4036493-2-pl@kamp.de> +Reviewed-by: Ilya Dryomov +Reviewed-by: Stefano Garzarella +Signed-off-by: Kevin Wolf +Signed-off-by: Luo Yifan +--- + block/rbd.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/block/rbd.c b/block/rbd.c +index ccb14efd55..6caf35cbba 100644 +--- a/block/rbd.c ++++ b/block/rbd.c +@@ -1281,11 +1281,11 @@ static int qemu_rbd_diff_iterate_cb(uint64_t offs, size_t len, + RBDDiffIterateReq *req = opaque; + + assert(req->offs + req->bytes <= offs); +- /* +- * we do not diff against a snapshot so we should never receive a callback +- * for a hole. +- */ +- assert(exists); ++ ++ /* treat a hole like an unallocated area and bail out */ ++ if (!exists) { ++ return 0; ++ } + + if (!req->exists && offs > req->offs) { + /* +-- +2.27.0 + diff --git a/chardev-char.c-fix-abstract-device-type-error-messag.patch b/chardev-char.c-fix-abstract-device-type-error-messag.patch new file mode 100644 index 00000000..657052b7 --- /dev/null +++ b/chardev-char.c-fix-abstract-device-type-error-messag.patch @@ -0,0 +1,37 @@ +From 3f9bed27de471be4d88ef9eb8270e1d362dccc4a Mon Sep 17 00:00:00 2001 +From: zhujun2 +Date: Mon, 4 Mar 2024 02:02:23 -0800 +Subject: [PATCH] chardev/char.c: fix "abstract device type" error message + +Current error message: + +qemu-system-x86_64: -chardev spice,id=foo: Parameter 'driver' expects an abstract device type + +while in fact the meaning is in reverse, -chardev expects +a non-abstract device type. + +Fixes: 777357d758d9 ("chardev: qom-ify" 2016-12-07) +Signed-off-by: Michael Tokarev +Reviewed-by: Zhao Liu +(cherry picked from commit 4ad87cd4b2254197b7ac12e3da824854e6a90f8f) +Signed-off-by: zhujun2 +--- + chardev/char.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/chardev/char.c b/chardev/char.c +index 0169d8dde4..6bb99bd485 100644 +--- a/chardev/char.c ++++ b/chardev/char.c +@@ -519,7 +519,7 @@ static const ChardevClass *char_get_class(const char *driver, Error **errp) + + if (object_class_is_abstract(oc)) { + error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "driver", +- "an abstract device type"); ++ "a non-abstract device type"); + return NULL; + } + +-- +2.27.0 + diff --git a/configure-Add-missing-POSIX-required-space.patch b/configure-Add-missing-POSIX-required-space.patch new file mode 100644 index 00000000..66fc46d4 --- /dev/null +++ b/configure-Add-missing-POSIX-required-space.patch @@ -0,0 +1,44 @@ +From 466653e339135572946a31d212205078854500da Mon Sep 17 00:00:00 2001 +From: tangbinzy +Date: Wed, 13 Mar 2024 03:11:08 +0000 +Subject: [PATCH] configure: Add missing POSIX-required space mainline + inclusion commit 35a7a6fc5624b1df828d82f2dfa74d0e4188b3b2 category: bugfix + +--------------------------------------------------------------- + +In commit 7d7dbf9dc15be6e1 we added a line to the configure script +which is not valid POSIX shell syntax, because it is missing a space +after a '!' character. shellcheck diagnoses this: + +if !(GIT="$git" "$source_path/scripts/git-submodule.sh" "$git_submodules_action" "$git_submodules"); then + ^-- SC1035: You are missing a required space after the !. + +and the OpenBSD shell will not correctly handle this without the space. + +Fixes: 7d7dbf9dc15be6e1 ("configure: replace --enable/disable-git-update with --with-git-submodules") +Signed-off-by: Peter Maydell +Reviewed-by: Thomas Huth +Tested-by: Dr. David Alan Gilbert +Message-id: 20220720152631.450903-2-peter.maydell@linaro.org + +Signed-off-by: tangbinzy +--- + configure | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/configure b/configure +index d7a4502a8b..8c9abd0e6e 100755 +--- a/configure ++++ b/configure +@@ -3337,7 +3337,7 @@ else + cxx= + fi + +-if !(GIT="$git" "$source_path/scripts/git-submodule.sh" "$git_submodules_action" "$git_submodules"); then ++if ! (GIT="$git" "$source_path/scripts/git-submodule.sh" "$git_submodules_action" "$git_submodules"); then + exit 1 + fi + +-- +2.27.0 + diff --git a/hw-block-hd-geometry-Do-not-override-specified-bios-.patch b/hw-block-hd-geometry-Do-not-override-specified-bios-.patch new file mode 100644 index 00000000..2193ed3d --- /dev/null +++ b/hw-block-hd-geometry-Do-not-override-specified-bios-.patch @@ -0,0 +1,63 @@ +From 0f13c505e833761a336bc4619b05afc373ebfdaa Mon Sep 17 00:00:00 2001 +From: tangbinzy +Date: Thu, 21 Mar 2024 05:59:43 +0000 +Subject: [PATCH] hw/block/hd-geometry: Do not override specified + bios-chs-trans mainline inclusion commit + fd8a68ad6823d33bedeba20a22857867a1c3890e category: bugfix + +--------------------------------------------------------------- + +For small disk images (<4 GiB), QEMU and SeaBIOS default to the +LARGE/ECHS disk translation method, but it is not uncommon for other +BIOS software to use LBA in these cases as well. Some operating +system boot loaders (e.g., NT 4) do not handle LARGE translations +outside of fixed configurations. See, e.g., Q154052: + +"When starting an x86 based computer, Ntdetect.com retrieves and +stores Interrupt 13 information. . . If the disk controller is using a +32 sector/64 head translation scheme, this boundary will be 1 GB. If +the controller uses 63 sector/255 head translation [AUTHOR: i.e., +LBA], the limit will be 4 GB." + +To accommodate these situations, hd_geometry_guess() now follows the +disk translation specified by the user even when the ATA disk geometry +is guessed. + +hd_geometry_guess(): +* Only set the disk translation when translation is AUTO. +* Show the soon-to-be active translation (*ptrans) in the trace rather + than what was guessed. + +Resolves: https://gitlab.com/qemu-project/qemu/-/issues/56 +Buglink: https://bugs.launchpad.net/qemu/+bug/1745312 + +Signed-off-by: Lev Kujawski +Message-Id: <20220707204045.999544-1-lkujaw@member.fsf.org> +Signed-off-by: Kevin Wolf + +Signed-off-by: tangbinzy +--- + hw/block/hd-geometry.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/hw/block/hd-geometry.c b/hw/block/hd-geometry.c +index dcbccee294..67462f1752 100644 +--- a/hw/block/hd-geometry.c ++++ b/hw/block/hd-geometry.c +@@ -150,7 +150,12 @@ void hd_geometry_guess(BlockBackend *blk, + translation = BIOS_ATA_TRANSLATION_NONE; + } + if (ptrans) { +- *ptrans = translation; ++ if (*ptrans == BIOS_ATA_TRANSLATION_AUTO) { ++ *ptrans = translation; ++ } else { ++ /* Defer to the translation specified by the user. */ ++ translation = *ptrans; ++ } + } + trace_hd_geometry_guess(blk, *pcyls, *pheads, *psecs, translation); + } +-- +2.27.0 + diff --git a/hw-display-bcm2835_fb-Fix-framebuffer-allocation-add.patch b/hw-display-bcm2835_fb-Fix-framebuffer-allocation-add.patch new file mode 100644 index 00000000..7ebc6f54 --- /dev/null +++ b/hw-display-bcm2835_fb-Fix-framebuffer-allocation-add.patch @@ -0,0 +1,53 @@ +From 5a8be2987986a0191b9d8a7a1a59f491e657ebad Mon Sep 17 00:00:00 2001 +From: tangbinzy +Date: Fri, 8 Mar 2024 04:12:58 +0000 +Subject: [PATCH] hw/display/bcm2835_fb: Fix framebuffer allocation address + mainline inclusion commit 5865d99fe88d8c8fa437c18c6b63fb2a8165634f category: + bugfix + +--------------------------------------------------------------- + +This patch fixes the dedicated framebuffer mailbox interface by +removing an unneeded offset. This means that we pick the framebuffer +address in the same way that we do if the guest code uses the buffer +allocate mechanism of the bcm2835_property interface (case +0x00040001: /* Allocate buffer */ in bcm2835_property.c). + +The documentation of this mailbox interface doesn't say anything +about using parts of the request buffer address to affect the +chosen framebuffer address: +https://github.com/raspberrypi/firmware/wiki/Mailbox-framebuffer-interface + +Some baremetal applications like the Screen01/Screen02 examples from +Baking Pi tutorial[1] didn't work before this patch. + +[1] https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/screen01.html + +Signed-off-by: Alan Jian +Message-id: 20220725145838.8412-1-alanjian85@outlook.com +[PMM: tweaked commit message] +Reviewed-by: Peter Maydell +Signed-off-by: Peter Maydell + +Signed-off-by: tangbinzy +--- + hw/display/bcm2835_fb.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/hw/display/bcm2835_fb.c b/hw/display/bcm2835_fb.c +index 2be77bdd3a..ac17c472a5 100644 +--- a/hw/display/bcm2835_fb.c ++++ b/hw/display/bcm2835_fb.c +@@ -279,8 +279,7 @@ static void bcm2835_fb_mbox_push(BCM2835FBState *s, uint32_t value) + newconf.xoffset = ldl_le_phys(&s->dma_as, value + 24); + newconf.yoffset = ldl_le_phys(&s->dma_as, value + 28); + +- newconf.base = s->vcram_base | (value & 0xc0000000); +- newconf.base += BCM2835_FB_OFFSET; ++ newconf.base = s->vcram_base + BCM2835_FB_OFFSET; + + /* Copy fields which we don't want to change from the existing config */ + newconf.pixo = s->config.pixo; +-- +2.27.0 + diff --git a/hw-ide-core-set-ERR_STAT-in-unsupported-command-comp.patch b/hw-ide-core-set-ERR_STAT-in-unsupported-command-comp.patch new file mode 100644 index 00000000..b41a3716 --- /dev/null +++ b/hw-ide-core-set-ERR_STAT-in-unsupported-command-comp.patch @@ -0,0 +1,60 @@ +From c2fe51f5e42bbb95209318e8e766212fe832aa9b Mon Sep 17 00:00:00 2001 +From: zhujun2 +Date: Sun, 10 Mar 2024 20:15:39 -0700 +Subject: [PATCH] hw/ide/core: set ERR_STAT in unsupported command completion +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Currently, the first time sending an unsupported command +(e.g. READ LOG DMA EXT) will not have ERR_STAT set in the completion. +Sending the unsupported command again, will correctly have ERR_STAT set. + +When ide_cmd_permitted() returns false, it calls ide_abort_command(). +ide_abort_command() first calls ide_transfer_stop(), which will call +ide_transfer_halt() and ide_cmd_done(), after that ide_abort_command() +sets ERR_STAT in status. + +ide_cmd_done() for AHCI will call ahci_write_fis_d2h() which writes the +current status in the FIS, and raises an IRQ. (The status here will not +have ERR_STAT set!). + +Thus, we cannot call ide_transfer_stop() before setting ERR_STAT, as +ide_transfer_stop() will result in the FIS being written and an IRQ +being raised. + +The reason why it works the second time, is that ERR_STAT will still +be set from the previous command, so when writing the FIS, the +completion will correctly have ERR_STAT set. + +Set ERR_STAT before writing the FIS (calling cmd_done), so that we will +raise an error IRQ correctly when receiving an unsupported command. + +Signed-off-by: Niklas Cassel +Reviewed-by: Philippe Mathieu-Daudé +Message-id: 20230609140844.202795-3-nks@flawful.org +Signed-off-by: John Snow +(cherry picked from commit c3461c6264a7c8ca15b117e91fe5da786924a784) +Signed-off-by: zhujun2 +--- + hw/ide/core.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/hw/ide/core.c b/hw/ide/core.c +index 15138225be..0d925c5ca5 100644 +--- a/hw/ide/core.c ++++ b/hw/ide/core.c +@@ -528,9 +528,9 @@ BlockAIOCB *ide_issue_trim( + + void ide_abort_command(IDEState *s) + { +- ide_transfer_stop(s); + s->status = READY_STAT | ERR_STAT; + s->error = ABRT_ERR; ++ ide_transfer_stop(s); + } + + static void ide_set_retry(IDEState *s) +-- +2.27.0 + diff --git a/hw-misc-mps2-scc-Free-MPS2SCC-oscclk-array-on-finali.patch b/hw-misc-mps2-scc-Free-MPS2SCC-oscclk-array-on-finali.patch new file mode 100644 index 00000000..987d9a68 --- /dev/null +++ b/hw-misc-mps2-scc-Free-MPS2SCC-oscclk-array-on-finali.patch @@ -0,0 +1,63 @@ +From 8ae86aa13df2128b46b421df14f6000f81312795 Mon Sep 17 00:00:00 2001 +From: zhujun2 +Date: Mon, 4 Mar 2024 01:19:55 -0800 +Subject: [PATCH] hw/misc/mps2-scc: Free MPS2SCC::oscclk[] array on finalize() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Commit 0be6bfac62 ("qdev: Implement variable length array properties") +added the DEFINE_PROP_ARRAY() macro with the following comment: + +* It is the responsibility of the device deinit code to free the +* @_arrayfield memory. + +Commit 4fb013afcc added: + +DEFINE_PROP_ARRAY("oscclk", MPS2SCC, num_oscclk, oscclk_reset, + qdev_prop_uint32, uint32_t), + +but forgot to free the 'oscclk_reset' array. Do it in the +instance_finalize() handler. + +Cc: qemu-stable@nongnu.org +Fixes: 4fb013afcc ("hw/misc/mps2-scc: Support configurable number of OSCCLK values") # v6.0.0+ +Signed-off-by: Philippe Mathieu-Daudé +Message-id: 20231121174051.63038-4-philmd@linaro.org +Reviewed-by: Peter Maydell +Signed-off-by: Peter Maydell +(cherry picked from commit 896dd6ff7b9f2575f1a908a07f26a70b58d8b675) +Signed-off-by: zhujun2 +--- + hw/misc/mps2-scc.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/hw/misc/mps2-scc.c b/hw/misc/mps2-scc.c +index b3b42a792c..fe5034db14 100644 +--- a/hw/misc/mps2-scc.c ++++ b/hw/misc/mps2-scc.c +@@ -329,6 +329,13 @@ static void mps2_scc_realize(DeviceState *dev, Error **errp) + s->oscclk = g_new0(uint32_t, s->num_oscclk); + } + ++static void mps2_scc_finalize(Object *obj) ++{ ++ MPS2SCC *s = MPS2_SCC(obj); ++ ++ g_free(s->oscclk_reset); ++} ++ + static const VMStateDescription mps2_scc_vmstate = { + .name = "mps2-scc", + .version_id = 3, +@@ -385,6 +392,7 @@ static const TypeInfo mps2_scc_info = { + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(MPS2SCC), + .instance_init = mps2_scc_init, ++ .instance_finalize = mps2_scc_finalize, + .class_init = mps2_scc_class_init, + }; + +-- +2.27.0 + diff --git a/hw-nvram-xlnx-efuse-Free-XlnxEFuse-ro_bits-array-on-.patch b/hw-nvram-xlnx-efuse-Free-XlnxEFuse-ro_bits-array-on-.patch new file mode 100644 index 00000000..2a444268 --- /dev/null +++ b/hw-nvram-xlnx-efuse-Free-XlnxEFuse-ro_bits-array-on-.patch @@ -0,0 +1,64 @@ +From aec47cbfa3ad713883d783cd86d3d6fe3413a585 Mon Sep 17 00:00:00 2001 +From: zhujun2 +Date: Mon, 4 Mar 2024 01:26:37 -0800 +Subject: [PATCH] hw/nvram/xlnx-efuse: Free XlnxEFuse::ro_bits[] array on + finalize() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Commit 0be6bfac62 ("qdev: Implement variable length array properties") +added the DEFINE_PROP_ARRAY() macro with the following comment: + +* It is the responsibility of the device deinit code to free the +* @_arrayfield memory. + +Commit 68fbcc344e added: + +DEFINE_PROP_ARRAY("read-only", XlnxEFuse, ro_bits_cnt, ro_bits, + qdev_prop_uint32, uint32_t), + +but forgot to free the 'ro_bits' array. Do it in the instance_finalize +handler. + +Cc: qemu-stable@nongnu.org +Fixes: 68fbcc344e ("hw/nvram: Introduce Xilinx eFuse QOM") # v6.2.0+ +Signed-off-by: Philippe Mathieu-Daudé +Message-id: 20231121174051.63038-5-philmd@linaro.org +Reviewed-by: Peter Maydell +Signed-off-by: Peter Maydell +(cherry picked from commit 49b3e28b7bdfe771150d05c4b5860aa7854a4232) +Signed-off-by: zhujun2 +--- + hw/nvram/xlnx-efuse.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/hw/nvram/xlnx-efuse.c b/hw/nvram/xlnx-efuse.c +index a0fd77b586..5b131e89b1 100644 +--- a/hw/nvram/xlnx-efuse.c ++++ b/hw/nvram/xlnx-efuse.c +@@ -217,6 +217,13 @@ static void efuse_realize(DeviceState *dev, Error **errp) + } + } + ++static void efuse_finalize(Object *obj) ++{ ++ XlnxEFuse *s = XLNX_EFUSE(obj); ++ ++ g_free(s->ro_bits); ++} ++ + static void efuse_prop_set_drive(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) + { +@@ -273,6 +280,7 @@ static const TypeInfo efuse_info = { + .name = TYPE_XLNX_EFUSE, + .parent = TYPE_DEVICE, + .instance_size = sizeof(XlnxEFuse), ++ .instance_finalize = efuse_finalize, + .class_init = efuse_class_init, + }; + +-- +2.27.0 + diff --git a/hw-nvram-xlnx-efuse-ctrl-Free-XlnxVersalEFuseCtrl-pg.patch b/hw-nvram-xlnx-efuse-ctrl-Free-XlnxVersalEFuseCtrl-pg.patch new file mode 100644 index 00000000..67899193 --- /dev/null +++ b/hw-nvram-xlnx-efuse-ctrl-Free-XlnxVersalEFuseCtrl-pg.patch @@ -0,0 +1,65 @@ +From d8685a2aca40ad07ecab1da84ec97f6384b26a66 Mon Sep 17 00:00:00 2001 +From: zhujun2 +Date: Mon, 4 Mar 2024 01:46:13 -0800 +Subject: [PATCH] hw/nvram/xlnx-efuse-ctrl: Free XlnxVersalEFuseCtrl[] + "pg0-lock" array +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Commit 0be6bfac62 ("qdev: Implement variable length array properties") +added the DEFINE_PROP_ARRAY() macro with the following comment: + +* It is the responsibility of the device deinit code to free the +* @_arrayfield memory. + +Commit 9e4aa1fafe added: + +DEFINE_PROP_ARRAY("pg0-lock", + XlnxVersalEFuseCtrl, extra_pg0_lock_n16, + extra_pg0_lock_spec, qdev_prop_uint16, uint16_t), + +but forgot to free the 'extra_pg0_lock_spec' array. Do it in the +instance_finalize() handler. + +Cc: qemu-stable@nongnu.org +Fixes: 9e4aa1fafe ("hw/nvram: Xilinx Versal eFuse device") # v6.2.0+ +Signed-off-by: Philippe Mathieu-Daudé +Message-id: 20231121174051.63038-6-philmd@linaro.org +Reviewed-by: Peter Maydell +Signed-off-by: Peter Maydell +(cherry picked from commit 4f10c66077e39969940d928077560665e155cac8) +Signed-off-by: zhujun2 +--- + hw/nvram/xlnx-versal-efuse-ctrl.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/hw/nvram/xlnx-versal-efuse-ctrl.c b/hw/nvram/xlnx-versal-efuse-ctrl.c +index b35ba65ab5..2d2dc09526 100644 +--- a/hw/nvram/xlnx-versal-efuse-ctrl.c ++++ b/hw/nvram/xlnx-versal-efuse-ctrl.c +@@ -725,6 +725,13 @@ static void efuse_ctrl_init(Object *obj) + sysbus_init_irq(sbd, &s->irq_efuse_imr); + } + ++static void efuse_ctrl_finalize(Object *obj) ++{ ++ XlnxVersalEFuseCtrl *s = XLNX_VERSAL_EFUSE_CTRL(obj); ++ ++ g_free(s->extra_pg0_lock_spec); ++} ++ + static const VMStateDescription vmstate_efuse_ctrl = { + .name = TYPE_XLNX_VERSAL_EFUSE_CTRL, + .version_id = 1, +@@ -762,6 +769,7 @@ static const TypeInfo efuse_ctrl_info = { + .instance_size = sizeof(XlnxVersalEFuseCtrl), + .class_init = efuse_ctrl_class_init, + .instance_init = efuse_ctrl_init, ++ .instance_finalize = efuse_ctrl_finalize, + }; + + static void efuse_ctrl_register_types(void) +-- +2.27.0 + diff --git a/hw-smbios-Fix-OEM-strings-table-option-validation.patch b/hw-smbios-Fix-OEM-strings-table-option-validation.patch new file mode 100644 index 00000000..08e51f68 --- /dev/null +++ b/hw-smbios-Fix-OEM-strings-table-option-validation.patch @@ -0,0 +1,51 @@ +From 7a332d757d2bec6d1c5433a807ceceb0cf96e00c Mon Sep 17 00:00:00 2001 +From: qihao +Date: Tue, 27 Feb 2024 10:22:18 +0800 +Subject: [PATCH] hw/smbios: Fix OEM strings table option validation + +cheery-pick from e8ddec58053e9361b2cc18ec6d17b6c95590bf3c + +qemu_smbios_type11_opts did not have the list terminator and that +resulted in out-of-bound memory access. It also needs to have an element +for the type option. + +Cc: qemu-stable@nongnu.org +Fixes: 2d6dcbf93fb0 ("smbios: support setting OEM strings table") +Signed-off-by: Akihiko Odaki +Reviewed-by: Michael Tokarev +Message-Id: <20240129-smbios-v2-1-9ee6fede0d10@daynix.com> +Reviewed-by: Ani Sinha +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Signed-off-by: qihao_yewu +--- + hw/smbios/smbios.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/hw/smbios/smbios.c b/hw/smbios/smbios.c +index 66be9aee09..f73b9417c8 100644 +--- a/hw/smbios/smbios.c ++++ b/hw/smbios/smbios.c +@@ -332,6 +332,11 @@ static const QemuOptDesc qemu_smbios_type4_opts[] = { + }; + + static const QemuOptDesc qemu_smbios_type11_opts[] = { ++ { ++ .name = "type", ++ .type = QEMU_OPT_NUMBER, ++ .help = "SMBIOS element type", ++ }, + { + .name = "value", + .type = QEMU_OPT_STRING, +@@ -342,6 +347,7 @@ static const QemuOptDesc qemu_smbios_type11_opts[] = { + .type = QEMU_OPT_STRING, + .help = "OEM string data from file", + }, ++ { /* end of list */ } + }; + + static const QemuOptDesc qemu_smbios_type17_opts[] = { +-- +2.27.0 + diff --git a/hw-virtio-virtio-iommu-Enforce-power-of-two-notify-f.patch b/hw-virtio-virtio-iommu-Enforce-power-of-two-notify-f.patch new file mode 100644 index 00000000..1d33773e --- /dev/null +++ b/hw-virtio-virtio-iommu-Enforce-power-of-two-notify-f.patch @@ -0,0 +1,113 @@ +From 89376545e23d5fa3b6e3f9d404edf0382c6f5ad3 Mon Sep 17 00:00:00 2001 +From: tangbinzy +Date: Wed, 13 Mar 2024 03:28:06 +0000 +Subject: [PATCH] hw/virtio/virtio-iommu: Enforce power-of-two notify for both + MAP and UNMAP mainline inclusion commit + 0522be9a0c0094088ccef7aab352c57f483ca250 category: bugfix + +--------------------------------------------------------------- + +Currently we only enforce power-of-two mappings (required by the QEMU +notifier) for UNMAP requests. A MAP request not aligned on a +power-of-two may be successfully handled by VFIO, and then the +corresponding UNMAP notify will fail because it will attempt to split +that mapping. Ensure MAP and UNMAP notifications are consistent. + +Fixes: dde3f08b5cab ("virtio-iommu: Handle non power of 2 range invalidations") +Reported-by: Tina Zhang +Signed-off-by: Jean-Philippe Brucker +Message-Id: <20220718135636.338264-1-jean-philippe@linaro.org> +Tested-by: Tina Zhang +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin + +Signed-off-by: tangbinzy +--- + hw/virtio/virtio-iommu.c | 47 ++++++++++++++++++++++++---------------- + 1 file changed, 28 insertions(+), 19 deletions(-) + +diff --git a/hw/virtio/virtio-iommu.c b/hw/virtio/virtio-iommu.c +index ae33d93b11..190ec2579a 100644 +--- a/hw/virtio/virtio-iommu.c ++++ b/hw/virtio/virtio-iommu.c +@@ -125,6 +125,32 @@ static gint interval_cmp(gconstpointer a, gconstpointer b, gpointer user_data) + } + } + ++static void virtio_iommu_notify_map_unmap(IOMMUMemoryRegion *mr, ++ IOMMUTLBEvent *event, ++ hwaddr virt_start, hwaddr virt_end) ++{ ++ uint64_t delta = virt_end - virt_start; ++ ++ event->entry.iova = virt_start; ++ event->entry.addr_mask = delta; ++ ++ if (delta == UINT64_MAX) { ++ memory_region_notify_iommu(mr, 0, *event); ++ } ++ ++ while (virt_start != virt_end + 1) { ++ uint64_t mask = dma_aligned_pow2_mask(virt_start, virt_end, 64); ++ ++ event->entry.addr_mask = mask; ++ event->entry.iova = virt_start; ++ memory_region_notify_iommu(mr, 0, *event); ++ virt_start += mask + 1; ++ if (event->entry.perm != IOMMU_NONE) { ++ event->entry.translated_addr += mask + 1; ++ } ++ } ++} ++ + static void virtio_iommu_notify_map(IOMMUMemoryRegion *mr, hwaddr virt_start, + hwaddr virt_end, hwaddr paddr, + uint32_t flags) +@@ -143,19 +169,16 @@ static void virtio_iommu_notify_map(IOMMUMemoryRegion *mr, hwaddr virt_start, + + event.type = IOMMU_NOTIFIER_MAP; + event.entry.target_as = &address_space_memory; +- event.entry.addr_mask = virt_end - virt_start; +- event.entry.iova = virt_start; + event.entry.perm = perm; + event.entry.translated_addr = paddr; + +- memory_region_notify_iommu(mr, 0, event); ++ virtio_iommu_notify_map_unmap(mr, &event, virt_start, virt_end); + } + + static void virtio_iommu_notify_unmap(IOMMUMemoryRegion *mr, hwaddr virt_start, + hwaddr virt_end) + { + IOMMUTLBEvent event; +- uint64_t delta = virt_end - virt_start; + + if (!(mr->iommu_notify_flags & IOMMU_NOTIFIER_UNMAP)) { + return; +@@ -167,22 +190,8 @@ static void virtio_iommu_notify_unmap(IOMMUMemoryRegion *mr, hwaddr virt_start, + event.entry.target_as = &address_space_memory; + event.entry.perm = IOMMU_NONE; + event.entry.translated_addr = 0; +- event.entry.addr_mask = delta; +- event.entry.iova = virt_start; +- +- if (delta == UINT64_MAX) { +- memory_region_notify_iommu(mr, 0, event); +- } + +- +- while (virt_start != virt_end + 1) { +- uint64_t mask = dma_aligned_pow2_mask(virt_start, virt_end, 64); +- +- event.entry.addr_mask = mask; +- event.entry.iova = virt_start; +- memory_region_notify_iommu(mr, 0, event); +- virt_start += mask + 1; +- } ++ virtio_iommu_notify_map_unmap(mr, &event, virt_start, virt_end); + } + + static gboolean virtio_iommu_notify_unmap_cb(gpointer key, gpointer value, +-- +2.27.0 + diff --git a/i386-cpu-Clear-FEAT_XSAVE_XSS_LO-HI-leafs-when-CPUID.patch b/i386-cpu-Clear-FEAT_XSAVE_XSS_LO-HI-leafs-when-CPUID.patch new file mode 100644 index 00000000..b82f3c9e --- /dev/null +++ b/i386-cpu-Clear-FEAT_XSAVE_XSS_LO-HI-leafs-when-CPUID.patch @@ -0,0 +1,41 @@ +From fb069ba131d312e4f4008c95710d0150c4039acf Mon Sep 17 00:00:00 2001 +From: Xiaoyao Li +Date: Mon, 15 Jan 2024 04:13:24 -0500 +Subject: [PATCH] i386/cpu: Clear FEAT_XSAVE_XSS_LO/HI leafs when + CPUID_EXT_XSAVE is not available + +commit 81f5cad3858f27623b1b14467926032d229b76cc upstream. + +Leaf FEAT_XSAVE_XSS_LO and FEAT_XSAVE_XSS_HI also need to be cleared +when CPUID_EXT_XSAVE is not set. + +Intel-SIG: commit 81f5cad3858f i386/cpu: Clear FEAT_XSAVE_XSS_LO/HI leafs when CPUID_EXT_XSAVE is not available +Backport i386/cpu bugfixes + +Fixes: 301e90675c3f ("target/i386: Enable support for XSAVES based features") +Signed-off-by: Xiaoyao Li +Reviewed-by: Yang Weijiang +Message-ID: <20240115091325.1904229-2-xiaoyao.li@intel.com> +Cc: qemu-stable@nongnu.org +Signed-off-by: Paolo Bonzini +Signed-off-by: Jason Zeng +--- + target/i386/cpu.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index 9ab8ef3bd1..ba8a3f4f2f 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -6479,6 +6479,8 @@ static void x86_cpu_enable_xsave_components(X86CPU *cpu) + if (!(env->features[FEAT_1_ECX] & CPUID_EXT_XSAVE)) { + env->features[FEAT_XSAVE_XCR0_LO] = 0; + env->features[FEAT_XSAVE_XCR0_HI] = 0; ++ env->features[FEAT_XSAVE_XSS_LO] = 0; ++ env->features[FEAT_XSAVE_XSS_HI] = 0; + return; + } + +-- +2.27.0 + diff --git a/i386-cpu-Mask-with-XCR0-XSS-mask-for-FEAT_XSAVE_XCR0.patch b/i386-cpu-Mask-with-XCR0-XSS-mask-for-FEAT_XSAVE_XCR0.patch new file mode 100644 index 00000000..15e34d6a --- /dev/null +++ b/i386-cpu-Mask-with-XCR0-XSS-mask-for-FEAT_XSAVE_XCR0.patch @@ -0,0 +1,45 @@ +From a4497d44e8124a7a5ee4ae403fde058651155ca9 Mon Sep 17 00:00:00 2001 +From: Xiaoyao Li +Date: Mon, 15 Jan 2024 04:13:25 -0500 +Subject: [PATCH] i386/cpu: Mask with XCR0/XSS mask for FEAT_XSAVE_XCR0_HI and + FEAT_XSAVE_XSS_HI leafs + +commit a11a365159b944e05be76f3ec3b98c8b38cb70fd upstream. + +The value of FEAT_XSAVE_XCR0_HI leaf and FEAT_XSAVE_XSS_HI leaf also +need to be masked by XCR0 and XSS mask respectively, to make it +logically correct. + +Intel-SIG: commit a11a365159b9 i386/cpu: Mask with XCR0/XSS mask for FEAT_XSAVE_XCR0_HI and FEAT_XSAVE_XSS_HI leafs +Backport i36/cpu bugfixes + +Fixes: 301e90675c3f ("target/i386: Enable support for XSAVES based features") +Signed-off-by: Xiaoyao Li +Reviewed-by: Yang Weijiang +Message-ID: <20240115091325.1904229-3-xiaoyao.li@intel.com> +Cc: qemu-stable@nongnu.org +Signed-off-by: Paolo Bonzini +Signed-off-by: Jason Zeng +--- + target/i386/cpu.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index ba8a3f4f2f..62ac5ed005 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -6499,9 +6499,9 @@ static void x86_cpu_enable_xsave_components(X86CPU *cpu) + } + + env->features[FEAT_XSAVE_XCR0_LO] = mask & CPUID_XSTATE_XCR0_MASK; +- env->features[FEAT_XSAVE_XCR0_HI] = mask >> 32; ++ env->features[FEAT_XSAVE_XCR0_HI] = (mask & CPUID_XSTATE_XCR0_MASK) >> 32; + env->features[FEAT_XSAVE_XSS_LO] = mask & CPUID_XSTATE_XSS_MASK; +- env->features[FEAT_XSAVE_XSS_HI] = mask >> 32; ++ env->features[FEAT_XSAVE_XSS_HI] = (mask & CPUID_XSTATE_XSS_MASK) >> 32; + } + + /***** Steps involved on loading and filtering CPUID data +-- +2.27.0 + diff --git a/i386-cpuid-Decrease-cpuid_i-when-skipping-CPUID-leaf.patch b/i386-cpuid-Decrease-cpuid_i-when-skipping-CPUID-leaf.patch new file mode 100644 index 00000000..beb0cb16 --- /dev/null +++ b/i386-cpuid-Decrease-cpuid_i-when-skipping-CPUID-leaf.patch @@ -0,0 +1,41 @@ +From 3b70aff18c50fc36dde1a0d305acfd1872f57141 Mon Sep 17 00:00:00 2001 +From: Xiaoyao Li +Date: Wed, 24 Jan 2024 21:40:14 -0500 +Subject: [PATCH] i386/cpuid: Decrease cpuid_i when skipping CPUID leaf 1F + +commit 10f92799af8ba3c3cef2352adcd4780f13fbab31 upstream. + +Existing code misses a decrement of cpuid_i when skip leaf 0x1F. +There's a blank CPUID entry(with leaf, subleaf as 0, and all fields +stuffed 0s) left in the CPUID array. + +It conflicts with correct CPUID leaf 0. + +Intel-SIG: commit 10f92799af8b i386/cpuid: Decrease cpuid_i when skipping CPUID leaf 1F +Backport i386/cpu bugfixes + +Signed-off-by: Xiaoyao Li +Reviewed-by:Yang Weijiang +Message-ID: <20240125024016.2521244-2-xiaoyao.li@intel.com> +Cc: qemu-stable@nongnu.org +Signed-off-by: Paolo Bonzini +Signed-off-by: Jason Zeng +--- + target/i386/kvm/kvm.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c +index e1601422bc..0927d1f515 100644 +--- a/target/i386/kvm/kvm.c ++++ b/target/i386/kvm/kvm.c +@@ -1759,6 +1759,7 @@ int kvm_arch_init_vcpu(CPUState *cs) + } + case 0x1f: + if (env->nr_dies < 2) { ++ cpuid_i--; + break; + } + /* fallthrough */ +-- +2.27.0 + diff --git a/i386-cpuid-Move-leaf-7-to-correct-group.patch b/i386-cpuid-Move-leaf-7-to-correct-group.patch new file mode 100644 index 00000000..93ea8dc7 --- /dev/null +++ b/i386-cpuid-Move-leaf-7-to-correct-group.patch @@ -0,0 +1,53 @@ +From 83beaa72ec488c7bb35fbca3efd84ecaa0d88071 Mon Sep 17 00:00:00 2001 +From: Xiaoyao Li +Date: Wed, 24 Jan 2024 21:40:16 -0500 +Subject: [PATCH] i386/cpuid: Move leaf 7 to correct group + +commit 0729857c707535847d7fe31d3d91eb8b2a118e3c upstream. + +CPUID leaf 7 was grouped together with SGX leaf 0x12 by commit +b9edbadefb9e ("i386: Propagate SGX CPUID sub-leafs to KVM") by mistake. + +SGX leaf 0x12 has its specific logic to check if subleaf (starting from 2) +is valid or not by checking the bit 0:3 of corresponding EAX is 1 or +not. + +Leaf 7 follows the logic that EAX of subleaf 0 enumerates the maximum +valid subleaf. + +Intel-SIG: commit 0729857c7075 i386/cpuid: Move leaf 7 to correct group +Backport i386/cpu bugfixes + +Fixes: b9edbadefb9e ("i386: Propagate SGX CPUID sub-leafs to KVM") +Signed-off-by: Xiaoyao Li +Message-ID: <20240125024016.2521244-4-xiaoyao.li@intel.com> +Cc: qemu-stable@nongnu.org +Signed-off-by: Paolo Bonzini +Signed-off-by: Jason Zeng +--- + target/i386/kvm/kvm.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c +index 0927d1f515..99be7f6155 100644 +--- a/target/i386/kvm/kvm.c ++++ b/target/i386/kvm/kvm.c +@@ -1800,7 +1800,6 @@ int kvm_arch_init_vcpu(CPUState *cs) + c = &cpuid_data.entries[cpuid_i++]; + } + break; +- case 0x7: + case 0x12: + for (j = 0; ; j++) { + c->function = i; +@@ -1820,6 +1819,7 @@ int kvm_arch_init_vcpu(CPUState *cs) + c = &cpuid_data.entries[cpuid_i++]; + } + break; ++ case 0x7: + case 0x14: + case 0x1d: + case 0x1e: { +-- +2.27.0 + diff --git a/ipmi-smbus-Add-a-check-around-a-memcpy.patch b/ipmi-smbus-Add-a-check-around-a-memcpy.patch new file mode 100644 index 00000000..219260e2 --- /dev/null +++ b/ipmi-smbus-Add-a-check-around-a-memcpy.patch @@ -0,0 +1,47 @@ +From d9f1221c0f4ff778e5e11d71519dfe1fe2f37e28 Mon Sep 17 00:00:00 2001 +From: tangbinzy +Date: Thu, 21 Mar 2024 03:16:54 +0000 +Subject: [PATCH] ipmi:smbus: Add a check around a memcpy mainline inclusion + commit 3fde641e7286f9b968bdb3b4b922c6465f2a9abc category: bugfix + +--------------------------------------------------------------- + +In one case: + + memcpy(sid->inmsg + sid->inlen, buf, len); + +if len == 0 then sid->inmsg + sig->inlen can point to one past the inmsg +array if the array is full. We have to allow len == 0 due to some +vagueness in the spec, but we don't have to call memcpy. + +Found by Coverity. This is not a problem in practice, but the results +are technically (maybe) undefined. So make Coverity happy. + +Reported-by: Peter Maydell +Signed-off-by: Corey Minyard +Acked-by: Michael S. Tsirkin +Reviewed-by: Peter Maydell + +Signed-off-by: tangbinzy +--- + hw/ipmi/smbus_ipmi.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/hw/ipmi/smbus_ipmi.c b/hw/ipmi/smbus_ipmi.c +index 1fdf0a66b6..1591211a86 100644 +--- a/hw/ipmi/smbus_ipmi.c ++++ b/hw/ipmi/smbus_ipmi.c +@@ -280,7 +280,9 @@ static int ipmi_write_data(SMBusDevice *dev, uint8_t *buf, uint8_t len) + */ + send = true; + } +- memcpy(sid->inmsg + sid->inlen, buf, len); ++ if (len > 0) { ++ memcpy(sid->inmsg + sid->inlen, buf, len); ++ } + sid->inlen += len; + break; + } +-- +2.27.0 + diff --git a/linux-user-flatload.c-Fix-setting-of-image_info-end_.patch b/linux-user-flatload.c-Fix-setting-of-image_info-end_.patch new file mode 100644 index 00000000..8cb2793f --- /dev/null +++ b/linux-user-flatload.c-Fix-setting-of-image_info-end_.patch @@ -0,0 +1,47 @@ +From 28654c3906e23d26dd740a3a300832345c9e0325 Mon Sep 17 00:00:00 2001 +From: tangbinzy +Date: Wed, 13 Mar 2024 02:33:21 +0000 +Subject: [PATCH] linux-user/flatload.c: Fix setting of image_info::end_code + mainline inclusion commit 734a659ad264ac080457167e845ffabbaaa66d0e category: + bugfix + +--------------------------------------------------------------- + +The flatload loader sets the end_code field in the image_info struct +incorrectly, due to a typo. + +This is a very long-standing bug (dating all the way back to when +the bFLT loader was added in 2006), but has gone unnoticed because +(a) most people don't use bFLT binaries +(b) we don't actually do anything with the end_code field, except + print it in debugging traces and pass it to TCG plugins + +Fix the typo. + +Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1119 +Signed-off-by: Peter Maydell +Reviewed-by: Richard Henderson +Message-Id: <20220728151406.2262862-1-peter.maydell@linaro.org> +Signed-off-by: Laurent Vivier + +Signed-off-by: tangbinzy +--- + linux-user/flatload.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/linux-user/flatload.c b/linux-user/flatload.c +index e4c2f89a22..e99570ca18 100644 +--- a/linux-user/flatload.c ++++ b/linux-user/flatload.c +@@ -808,7 +808,7 @@ int load_flt_binary(struct linux_binprm *bprm, struct image_info *info) + + /* Stash our initial stack pointer into the mm structure */ + info->start_code = libinfo[0].start_code; +- info->end_code = libinfo[0].start_code = libinfo[0].text_len; ++ info->end_code = libinfo[0].start_code + libinfo[0].text_len; + info->start_data = libinfo[0].start_data; + info->end_data = libinfo[0].end_data; + info->start_brk = libinfo[0].start_brk; +-- +2.27.0 + diff --git a/linux-user-riscv-Align-signal-frame-to-16-bytes.patch b/linux-user-riscv-Align-signal-frame-to-16-bytes.patch new file mode 100644 index 00000000..f975d609 --- /dev/null +++ b/linux-user-riscv-Align-signal-frame-to-16-bytes.patch @@ -0,0 +1,39 @@ +From e011a861479e486201feb0760a5fd2f449270f4d Mon Sep 17 00:00:00 2001 +From: tangbinzy +Date: Thu, 21 Mar 2024 05:38:28 +0000 +Subject: [PATCH] linux-user/riscv: Align signal frame to 16 bytes mainline + inclusion commit 1eaa63429a9944265c92efdb94c02fabb231f564 category: bugfix + +--------------------------------------------------------------- + +Follow the kernel's alignment, as we already noted. + +Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1093 +Signed-off-by: Richard Henderson +Reviewed-by: Alistair Francis +Message-Id: <20220729201942.30738-1-richard.henderson@linaro.org> +Signed-off-by: Alistair Francis + +Signed-off-by: tangbinzy +--- + linux-user/riscv/signal.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/linux-user/riscv/signal.c b/linux-user/riscv/signal.c +index a0f9542ce3..c50ac6d0aa 100644 +--- a/linux-user/riscv/signal.c ++++ b/linux-user/riscv/signal.c +@@ -64,9 +64,7 @@ static abi_ulong get_sigframe(struct target_sigaction *ka, + + /* This is the X/Open sanctioned signal stack switching. */ + sp = target_sigsp(sp, ka) - framesize; +- +- /* XXX: kernel aligns with 0xf ? */ +- sp &= ~3UL; /* align sp on 4-byte boundary */ ++ sp &= ~0xf; + + return sp; + } +-- +2.27.0 + diff --git a/load_elf-fix-iterator-s-type-for-elf-file-processing.patch b/load_elf-fix-iterator-s-type-for-elf-file-processing.patch new file mode 100644 index 00000000..5c3383e2 --- /dev/null +++ b/load_elf-fix-iterator-s-type-for-elf-file-processing.patch @@ -0,0 +1,42 @@ +From 5ae048bf81cea4b992649fda03ebc7fa21effaa6 Mon Sep 17 00:00:00 2001 +From: zhujun2 +Date: Sun, 3 Mar 2024 23:06:14 -0800 +Subject: [PATCH] load_elf: fix iterator's type for elf file processing + +j is used while loading an ELF file to byteswap segments' +data. If data is larger than 2GB an overflow may happen. +So j should be elf_word. + +This commit fixes a minor bug: it's unlikely anybody is trying to +load ELF files with 2GB+ segments for wrong-endianness targets, +but if they did, it wouldn't work correctly. + +Found by Linux Verification Center (linuxtesting.org) with SVACE. + +Cc: qemu-stable@nongnu.org +Fixes: 7ef295ea5b ("loader: Add data swap option to load-elf") +Signed-off-by: Anastasia Belova +Reviewed-by: Peter Maydell +Signed-off-by: Peter Maydell +(cherry picked from commit 410c2a4d75f52f6a2fe978eda5a9b6f854afe5ea) +Signed-off-by: zhujun2 +--- + include/hw/elf_ops.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/include/hw/elf_ops.h b/include/hw/elf_ops.h +index 7c3b1d0f6c..ea17fe9fb5 100644 +--- a/include/hw/elf_ops.h ++++ b/include/hw/elf_ops.h +@@ -499,7 +499,7 @@ static ssize_t glue(load_elf, SZ)(const char *name, int fd, + } + + if (data_swab) { +- int j; ++ elf_word j; + for (j = 0; j < file_size; j += (1 << data_swab)) { + uint8_t *dp = data + j; + switch (data_swab) { +-- +2.27.0 + diff --git a/qemu-options.hx-Don-t-claim-serial-has-limit-of-4-se.patch b/qemu-options.hx-Don-t-claim-serial-has-limit-of-4-se.patch new file mode 100644 index 00000000..25626c4b --- /dev/null +++ b/qemu-options.hx-Don-t-claim-serial-has-limit-of-4-se.patch @@ -0,0 +1,41 @@ +From c80641ae418a782544304adf64260487ca581c19 Mon Sep 17 00:00:00 2001 +From: guping +Date: Wed, 6 Mar 2024 09:57:24 +0000 +Subject: [PATCH] qemu-options.hx: Don't claim "-serial" has limit of 4 serial + ports Before v2.12, the implementation of serial ports was limited to a value + of MAX_SERIAL_PORTS = 4. We now dynamically allocate the data structures for + serial ports, so this limit is no longer present, but the documentation for + the -serial options still reads: + + "This option can be used several times to simulate up to 4 serial ports." + +Update to "This option can be used several times to simulate +multiple serial ports." to avoid misleading. + +Signed-off-by: default avatarSteven Shen +Message-id: 20240305013016.2268-1-steven.shen@jaguarmicro.com +Reviewed-by: default avatarPeter Maydell +[PMM: tweaked commit message] +Signed-off-by: default avatarPeter Maydell + +Signed-off-by: guping +--- + qemu-options.hx | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/qemu-options.hx b/qemu-options.hx +index e25b76771d..d940b4aea5 100644 +--- a/qemu-options.hx ++++ b/qemu-options.hx +@@ -3783,7 +3783,7 @@ SRST + default device is ``vc`` in graphical mode and ``stdio`` in non + graphical mode. + +- This option can be used several times to simulate up to 4 serial ++ This option can be used several times to simulate multiple serial + ports. + + Use ``-serial none`` to disable all serial ports. +-- +2.27.0 + diff --git a/qemu.spec b/qemu.spec index 9faf51e8..66569a64 100644 --- a/qemu.spec +++ b/qemu.spec @@ -3,7 +3,7 @@ Name: qemu Version: 6.2.0 -Release: 89 +Release: 90 Epoch: 10 Summary: QEMU is a generic and open source machine emulator and virtualizer License: GPLv2 and BSD and MIT and CC-BY-SA-4.0 @@ -875,6 +875,38 @@ Patch0860: ui-clipboard-mark-type-as-not-available-when-there-i.patch Patch0861: virtio-net-correctly-copy-vnet-header-when-flushing-.patch Patch0862: hw-timer-fix-systick-trace-message.patch Patch0863: qga-win-Fix-guest-get-fsinfo-multi-disks-collection.patch +Patch0864: hw-smbios-Fix-OEM-strings-table-option-validation.patch +Patch0865: vl-Improve-error-message-for-conflicting-incoming-an.patch +Patch0866: block-parallels-Fix-buffer-based-write-call.patch +Patch0867: hw-display-bcm2835_fb-Fix-framebuffer-allocation-add.patch +Patch0868: usb-hcd-xhci-check-slotid-in-xhci_wakeup_endpoint.patch +Patch0869: qga-treat-get-guest-fsinfo-as-best-effort.patch +Patch0870: block-rbd-fix-handling-of-holes-in-.bdrv_co_block_st.patch +Patch0871: chardev-char.c-fix-abstract-device-type-error-messag.patch +Patch0872: hw-nvram-xlnx-efuse-ctrl-Free-XlnxVersalEFuseCtrl-pg.patch +Patch0873: hw-nvram-xlnx-efuse-Free-XlnxEFuse-ro_bits-array-on-.patch +Patch0874: hw-misc-mps2-scc-Free-MPS2SCC-oscclk-array-on-finali.patch +Patch0875: load_elf-fix-iterator-s-type-for-elf-file-processing.patch +Patch0876: linux-user-flatload.c-Fix-setting-of-image_info-end_.patch +Patch0877: hw-ide-core-set-ERR_STAT-in-unsupported-command-comp.patch +Patch0878: vga-fix-incorrect-line-height-in-640x200x2-mode.patch +Patch0879: configure-Add-missing-POSIX-required-space.patch +Patch0880: hw-virtio-virtio-iommu-Enforce-power-of-two-notify-f.patch +Patch0881: target-s390x-fix-handling-of-zeroes-in-vfmin-vfmax.patch +Patch0882: block-migration-Ensure-we-don-t-crash-during-migrati.patch +Patch0883: target-ppc-Modify-the-uncorrect-value-irq-to-n_IRQ.patch +Patch0884: qemu-options.hx-Don-t-claim-serial-has-limit-of-4-se.patch +Patch0885: tests-tcg-linux-test-Fix-random-hangs-in-test_socket.patch +Patch0886: ipmi-smbus-Add-a-check-around-a-memcpy.patch +Patch0887: linux-user-riscv-Align-signal-frame-to-16-bytes.patch +Patch0888: hw-block-hd-geometry-Do-not-override-specified-bios-.patch +Patch0889: target-i386-Add-kvm_get_one_msr-helper.patch +Patch0890: target-i386-Enable-support-for-XSAVES-based-features.patch +Patch0891: target-i386-Change-wrong-XFRM-value-in-SGX-CPUID-lea.patch +Patch0892: i386-cpu-Clear-FEAT_XSAVE_XSS_LO-HI-leafs-when-CPUID.patch +Patch0893: i386-cpu-Mask-with-XCR0-XSS-mask-for-FEAT_XSAVE_XCR0.patch +Patch0894: i386-cpuid-Decrease-cpuid_i-when-skipping-CPUID-leaf.patch +Patch0895: i386-cpuid-Move-leaf-7-to-correct-group.patch BuildRequires: flex BuildRequires: gcc @@ -1473,6 +1505,40 @@ getent passwd qemu >/dev/null || \ %endif %changelog +* Sat Mar 23 2024 - 10:6.2.0-90 +- i386/cpuid: Move leaf 7 to correct group +- i386/cpuid: Decrease cpuid_i when skipping CPUID leaf 1F +- i386/cpu: Mask with XCR0/XSS mask for FEAT_XSAVE_XCR0_HI and FEAT_XSAVE_XSS_HI leafs +- i386/cpu: Clear FEAT_XSAVE_XSS_LO/HI leafs when CPUID_EXT_XSAVE is not available +- target/i386: Change wrong XFRM value in SGX CPUID leaf +- target/i386: Enable support for XSAVES based features +- target/i386: Add kvm_get_one_msr helper +- hw/block/hd-geometry: Do not override specified bios-chs-trans mainline inclusion commit fd8a68ad6823d33bedeba20a22857867a1c3890e category: bugfix +- linux-user/riscv: Align signal frame to 16 bytes mainline inclusion commit 1eaa63429a9944265c92efdb94c02fabb231f564 category: bugfix +- ipmi:smbus: Add a check around a memcpy mainline inclusion commit 3fde641e7286f9b968bdb3b4b922c6465f2a9abc category: bugfix +- tests/tcg/linux-test: Fix random hangs in test_socket mainline inclusion commit b9e6074fc5b429b1e956e9c60db7e284a91e0f3d category: bugfix +- qemu-options.hx: Don't claim "-serial" has limit of 4 serial ports Before v2.12, the implementation of serial ports was limited to a value of MAX_SERIAL_PORTS = 4. We now dynamically allocate the data structures for serial ports, so this limit is no longer present, but the documentation for the -serial options still reads: +- target/ppc: Modify the uncorrect value irq to n_IRQ +- block-migration: Ensure we don't crash during migration cleanup +- target/s390x: fix handling of zeroes in vfmin/vfmax mainline inclusion commit 13c59eb09bd6d1fbc13f08b708226421f14a232b category: bugfix +- hw/virtio/virtio-iommu: Enforce power-of-two notify for both MAP and UNMAP mainline inclusion commit 0522be9a0c0094088ccef7aab352c57f483ca250 category: bugfix +- configure: Add missing POSIX-required space mainline inclusion commit 35a7a6fc5624b1df828d82f2dfa74d0e4188b3b2 category: bugfix +- vga: fix incorrect line height in 640x200x2 mode mainline inclusion commit 37e7b86766244b62a406747bb78e049390d0b528 category: bugfix +- hw/ide/core: set ERR_STAT in unsupported command completion +- linux-user/flatload.c: Fix setting of image_info::end_code mainline inclusion commit 734a659ad264ac080457167e845ffabbaaa66d0e category: bugfix +- load_elf: fix iterator's type for elf file processing +- hw/misc/mps2-scc: Free MPS2SCC::oscclk[] array on finalize() +- hw/nvram/xlnx-efuse: Free XlnxEFuse::ro_bits[] array on finalize() +- hw/nvram/xlnx-efuse-ctrl: Free XlnxVersalEFuseCtrl[] "pg0-lock" array +- chardev/char.c: fix "abstract device type" error message +- block/rbd: fix handling of holes in .bdrv_co_block_status +- qga: treat get-guest-fsinfo as "best effort" mainline inclusion commit bbb0151cf2e82489120a15df5e2eb9653312b0ec category: bugfix +- usb/hcd-xhci: check slotid in xhci_wakeup_endpoint() mainline inclusion commit 84218892f05515d20347fde4506e1944eb11cb25 category: bugfix +- hw/display/bcm2835_fb: Fix framebuffer allocation address mainline inclusion commit 5865d99fe88d8c8fa437c18c6b63fb2a8165634f category: bugfix +- block/parallels: Fix buffer-based write call mainline inclusion commit eba088f91d21d9e42a81bef847173da30c5da961 category: bugfix +- vl: Improve error message for conflicting -incoming and -loadvm +- hw/smbios: Fix OEM strings table option validation + * Sat Mar 9 2024 - 10:6.2.0-89 - qga-win: Fix guest-get-fsinfo multi-disks collection - hw/timer: fix systick trace message diff --git a/qga-treat-get-guest-fsinfo-as-best-effort.patch b/qga-treat-get-guest-fsinfo-as-best-effort.patch new file mode 100644 index 00000000..abbf2a4c --- /dev/null +++ b/qga-treat-get-guest-fsinfo-as-best-effort.patch @@ -0,0 +1,56 @@ +From 2e6562a5c390407e89eb7ab903ab4cc09651bbcb Mon Sep 17 00:00:00 2001 +From: tangbinzy +Date: Fri, 8 Mar 2024 02:48:34 +0000 +Subject: [PATCH] qga: treat get-guest-fsinfo as "best effort" mainline + inclusion commit bbb0151cf2e82489120a15df5e2eb9653312b0ec category: bugfix +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +--------------------------------------------------------------- + +In some container environments, there may be references to block devices +witnessable from a container through /proc/self/mountinfo that reference +devices we simply don't have access to in the container, and cannot +provide information about. + +Instead of failing the entire fsinfo command, return stub information +for these failed lookups. + +This allows test-qga to pass under docker tests, which are in turn used +by the CentOS VM tests. + +Signed-off-by: John Snow +Reviewed-by: Marc-André Lureau +Message-Id: <20220708153503.18864-2-jsnow@redhat.com> +Signed-off-by: Thomas Huth + +Signed-off-by: tangbinzy +--- + qga/commands-posix.c | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +diff --git a/qga/commands-posix.c b/qga/commands-posix.c +index 4e06271889..bee7a47ed2 100644 +--- a/qga/commands-posix.c ++++ b/qga/commands-posix.c +@@ -1201,7 +1201,15 @@ static void build_guest_fsinfo_for_device(char const *devpath, + + syspath = realpath(devpath, NULL); + if (!syspath) { +- error_setg_errno(errp, errno, "realpath(\"%s\")", devpath); ++ if (errno != ENOENT) { ++ error_setg_errno(errp, errno, "realpath(\"%s\")", devpath); ++ return; ++ } ++ ++ /* ENOENT: This devpath may not exist because of container config */ ++ if (!fs->name) { ++ fs->name = g_path_get_basename(devpath); ++ } + return; + } + +-- +2.27.0 + diff --git a/target-i386-Add-kvm_get_one_msr-helper.patch b/target-i386-Add-kvm_get_one_msr-helper.patch new file mode 100644 index 00000000..f3b23616 --- /dev/null +++ b/target-i386-Add-kvm_get_one_msr-helper.patch @@ -0,0 +1,123 @@ +From 66d093c4b3fbb3dcb232b38852c47fe1d7d5e1c1 Mon Sep 17 00:00:00 2001 +From: Yang Weijiang +Date: Tue, 15 Feb 2022 14:52:53 -0500 +Subject: [PATCH] target/i386: Add kvm_get_one_msr helper + +commit 5a778a5f820fdd907b95e93560637a61f6ea3c71 upstream. + +When try to get one msr from KVM, I found there's no such kind of +existing interface while kvm_put_one_msr() is there. So here comes +the patch. It'll remove redundant preparation code before finally +call KVM_GET_MSRS IOCTL. + +No functional change intended. + +Intel-SIG: commit 5a778a5f820f target/i386: Add kvm_get_one_msr helper +Backport i386/cpu bugfixes + +Signed-off-by: Yang Weijiang +Message-Id: <20220215195258.29149-4-weijiang.yang@intel.com> +Signed-off-by: Paolo Bonzini +Signed-off-by: Jason Zeng +--- + target/i386/kvm/kvm.c | 46 ++++++++++++++++++++++++------------------- + 1 file changed, 26 insertions(+), 20 deletions(-) + +diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c +index 54e48530ad..e1601422bc 100644 +--- a/target/i386/kvm/kvm.c ++++ b/target/i386/kvm/kvm.c +@@ -138,6 +138,7 @@ static struct kvm_msr_list *kvm_feature_msrs; + + #define BUS_LOCK_SLICE_TIME 1000000000ULL /* ns */ + static RateLimit bus_lock_ratelimit_ctrl; ++static int kvm_get_one_msr(X86CPU *cpu, int index, uint64_t *value); + + int kvm_has_pit_state2(void) + { +@@ -208,28 +209,21 @@ static int kvm_get_tsc(CPUState *cs) + { + X86CPU *cpu = X86_CPU(cs); + CPUX86State *env = &cpu->env; +- struct { +- struct kvm_msrs info; +- struct kvm_msr_entry entries[1]; +- } msr_data = {}; ++ uint64_t value; + int ret; + + if (env->tsc_valid) { + return 0; + } + +- memset(&msr_data, 0, sizeof(msr_data)); +- msr_data.info.nmsrs = 1; +- msr_data.entries[0].index = MSR_IA32_TSC; + env->tsc_valid = !runstate_is_running(); + +- ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_MSRS, &msr_data); ++ ret = kvm_get_one_msr(cpu, MSR_IA32_TSC, &value); + if (ret < 0) { + return ret; + } + +- assert(ret == 1); +- env->tsc = msr_data.entries[0].data; ++ env->tsc = value; + return 0; + } + +@@ -1529,21 +1523,14 @@ static int hyperv_init_vcpu(X86CPU *cpu) + * the kernel doesn't support setting vp_index; assert that its value + * is in sync + */ +- struct { +- struct kvm_msrs info; +- struct kvm_msr_entry entries[1]; +- } msr_data = { +- .info.nmsrs = 1, +- .entries[0].index = HV_X64_MSR_VP_INDEX, +- }; ++ uint64_t value; + +- ret = kvm_vcpu_ioctl(cs, KVM_GET_MSRS, &msr_data); ++ ret = kvm_get_one_msr(cpu, HV_X64_MSR_VP_INDEX, &value); + if (ret < 0) { + return ret; + } +- assert(ret == 1); + +- if (msr_data.entries[0].data != hyperv_vp_index(CPU(cpu))) { ++ if (value != hyperv_vp_index(CPU(cpu))) { + error_report("kernel's vp_index != QEMU's vp_index"); + return -ENXIO; + } +@@ -2766,6 +2753,25 @@ static int kvm_put_one_msr(X86CPU *cpu, int index, uint64_t value) + return kvm_vcpu_ioctl(CPU(cpu), KVM_SET_MSRS, cpu->kvm_msr_buf); + } + ++static int kvm_get_one_msr(X86CPU *cpu, int index, uint64_t *value) ++{ ++ int ret; ++ struct { ++ struct kvm_msrs info; ++ struct kvm_msr_entry entries[1]; ++ } msr_data = { ++ .info.nmsrs = 1, ++ .entries[0].index = index, ++ }; ++ ++ ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_MSRS, &msr_data); ++ if (ret < 0) { ++ return ret; ++ } ++ assert(ret == 1); ++ *value = msr_data.entries[0].data; ++ return ret; ++} + void kvm_put_apicbase(X86CPU *cpu, uint64_t value) + { + int ret; +-- +2.27.0 + diff --git a/target-i386-Change-wrong-XFRM-value-in-SGX-CPUID-lea.patch b/target-i386-Change-wrong-XFRM-value-in-SGX-CPUID-lea.patch new file mode 100644 index 00000000..9affcbf6 --- /dev/null +++ b/target-i386-Change-wrong-XFRM-value-in-SGX-CPUID-lea.patch @@ -0,0 +1,46 @@ +From ad727933a766e952b5054bfd53c93ad43fdb6dec Mon Sep 17 00:00:00 2001 +From: Yang Zhong +Date: Thu, 6 Apr 2023 02:40:41 -0400 +Subject: [PATCH] target/i386: Change wrong XFRM value in SGX CPUID leaf +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +commit 72497cff896fecf74306ed33626c30e43633cdd6 upstream. + +The previous patch wrongly replaced FEAT_XSAVE_XCR0_{LO|HI} with +FEAT_XSAVE_XSS_{LO|HI} in CPUID(EAX=12,ECX=1):{ECX,EDX}. As a result, +SGX enclaves only supported SSE and x87 feature (xfrm=0x3). + +Intel-SIG: commit 72497cff896f target/i386: Change wrong XFRM value in SGX CPUID leaf +Backport i386/cpu bugfixes + +Fixes: 301e90675c3f ("target/i386: Enable support for XSAVES based features") +Signed-off-by: Yang Zhong +Reviewed-by: Yang Weijiang +Reviewed-by: Kai Huang +Message-Id: <20230406064041.420039-1-yang.zhong@linux.intel.com> +Signed-off-by: Paolo Bonzini +Signed-off-by: Jason Zeng +--- + target/i386/cpu.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index 6b098cc832..9ab8ef3bd1 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -5951,8 +5951,8 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, + } else { + *eax &= env->features[FEAT_SGX_12_1_EAX]; + *ebx &= 0; /* ebx reserve */ +- *ecx &= env->features[FEAT_XSAVE_XSS_LO]; +- *edx &= env->features[FEAT_XSAVE_XSS_HI]; ++ *ecx &= env->features[FEAT_XSAVE_XCR0_LO]; ++ *edx &= env->features[FEAT_XSAVE_XCR0_HI]; + + /* FP and SSE are always allowed regardless of XSAVE/XCR0. */ + *ecx |= XSTATE_FP_MASK | XSTATE_SSE_MASK; +-- +2.27.0 + diff --git a/target-i386-Enable-support-for-XSAVES-based-features.patch b/target-i386-Enable-support-for-XSAVES-based-features.patch new file mode 100644 index 00000000..41cc0dbd --- /dev/null +++ b/target-i386-Enable-support-for-XSAVES-based-features.patch @@ -0,0 +1,286 @@ +From 0a83478189efce4e6775977dc3c76a5750b52fb4 Mon Sep 17 00:00:00 2001 +From: Yang Weijiang +Date: Tue, 15 Feb 2022 14:52:54 -0500 +Subject: [PATCH] target/i386: Enable support for XSAVES based features + +commit 301e90675c3fed6cdc48682021a1ab42bc0e0d76 upstream. + +There're some new features, including Arch LBR, depending +on XSAVES/XRSTORS support, the new instructions will +save/restore data based on feature bits enabled in XCR0 | XSS. +This patch adds the basic support for related CPUID enumeration +and meanwhile changes the name from FEAT_XSAVE_COMP_{LO|HI} to +FEAT_XSAVE_XCR0_{LO|HI} to differentiate clearly the feature +bits in XCR0 and those in XSS. + +Intel-SIG: commit 301e90675c3f target/i386: Enable support for XSAVES based features +Backport i386/cpu bugfixes + +Signed-off-by: Yang Weijiang +Message-Id: <20220215195258.29149-5-weijiang.yang@intel.com> +Signed-off-by: Paolo Bonzini +Signed-off-by: Jason Zeng +--- + target/i386/cpu.c | 104 +++++++++++++++++++++++++++++++++++----------- + target/i386/cpu.h | 14 ++++++- + 2 files changed, 92 insertions(+), 26 deletions(-) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index 53a7484ca8..6b098cc832 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -977,6 +977,34 @@ FeatureWordInfo feature_word_info[FEATURE_WORDS] = { + }, + .tcg_features = TCG_XSAVE_FEATURES, + }, ++ [FEAT_XSAVE_XSS_LO] = { ++ .type = CPUID_FEATURE_WORD, ++ .feat_names = { ++ NULL, NULL, NULL, NULL, ++ NULL, NULL, NULL, NULL, ++ NULL, NULL, NULL, NULL, ++ NULL, NULL, NULL, NULL, ++ NULL, NULL, NULL, NULL, ++ NULL, NULL, NULL, NULL, ++ NULL, NULL, NULL, NULL, ++ NULL, NULL, NULL, NULL, ++ }, ++ .cpuid = { ++ .eax = 0xD, ++ .needs_ecx = true, ++ .ecx = 1, ++ .reg = R_ECX, ++ }, ++ }, ++ [FEAT_XSAVE_XSS_HI] = { ++ .type = CPUID_FEATURE_WORD, ++ .cpuid = { ++ .eax = 0xD, ++ .needs_ecx = true, ++ .ecx = 1, ++ .reg = R_EDX ++ }, ++ }, + [FEAT_6_EAX] = { + .type = CPUID_FEATURE_WORD, + .feat_names = { +@@ -992,7 +1020,7 @@ FeatureWordInfo feature_word_info[FEATURE_WORDS] = { + .cpuid = { .eax = 6, .reg = R_EAX, }, + .tcg_features = TCG_6_EAX_FEATURES, + }, +- [FEAT_XSAVE_COMP_LO] = { ++ [FEAT_XSAVE_XCR0_LO] = { + .type = CPUID_FEATURE_WORD, + .cpuid = { + .eax = 0xD, +@@ -1005,7 +1033,7 @@ FeatureWordInfo feature_word_info[FEATURE_WORDS] = { + XSTATE_OPMASK_MASK | XSTATE_ZMM_Hi256_MASK | XSTATE_Hi16_ZMM_MASK | + XSTATE_PKRU_MASK, + }, +- [FEAT_XSAVE_COMP_HI] = { ++ [FEAT_XSAVE_XCR0_HI] = { + .type = CPUID_FEATURE_WORD, + .cpuid = { + .eax = 0xD, +@@ -1422,6 +1450,9 @@ static const X86RegisterInfo32 x86_reg_info_32[CPU_NB_REGS32] = { + }; + #undef REGISTER + ++/* CPUID feature bits available in XSS */ ++#define CPUID_XSTATE_XSS_MASK (0) ++ + ExtSaveArea x86_ext_save_areas[XSAVE_STATE_AREA_COUNT] = { + [XSTATE_FP_BIT] = { + /* x87 FP state component is always enabled if XSAVE is supported */ +@@ -1464,15 +1495,18 @@ ExtSaveArea x86_ext_save_areas[XSAVE_STATE_AREA_COUNT] = { + }, + }; + +-static uint32_t xsave_area_size(uint64_t mask) ++static uint32_t xsave_area_size(uint64_t mask, bool compacted) + { ++ uint64_t ret = x86_ext_save_areas[0].size; ++ const ExtSaveArea *esa; ++ uint32_t offset = 0; + int i; +- uint64_t ret = 0; + +- for (i = 0; i < ARRAY_SIZE(x86_ext_save_areas); i++) { +- const ExtSaveArea *esa = &x86_ext_save_areas[i]; ++ for (i = 2; i < ARRAY_SIZE(x86_ext_save_areas); i++) { ++ esa = &x86_ext_save_areas[i]; + if ((mask >> i) & 1) { +- ret = MAX(ret, esa->offset + esa->size); ++ offset = compacted ? ret : esa->offset; ++ ret = MAX(ret, offset + esa->size); + } + } + return ret; +@@ -1483,10 +1517,10 @@ static inline bool accel_uses_host_cpuid(void) + return kvm_enabled() || hvf_enabled(); + } + +-static inline uint64_t x86_cpu_xsave_components(X86CPU *cpu) ++static inline uint64_t x86_cpu_xsave_xcr0_components(X86CPU *cpu) + { +- return ((uint64_t)cpu->env.features[FEAT_XSAVE_COMP_HI]) << 32 | +- cpu->env.features[FEAT_XSAVE_COMP_LO]; ++ return ((uint64_t)cpu->env.features[FEAT_XSAVE_XCR0_HI]) << 32 | ++ cpu->env.features[FEAT_XSAVE_XCR0_LO]; + } + + /* Return name of 32-bit register, from a R_* constant */ +@@ -1498,6 +1532,12 @@ static const char *get_register_name_32(unsigned int reg) + return x86_reg_info_32[reg].name; + } + ++static inline uint64_t x86_cpu_xsave_xss_components(X86CPU *cpu) ++{ ++ return ((uint64_t)cpu->env.features[FEAT_XSAVE_XSS_HI]) << 32 | ++ cpu->env.features[FEAT_XSAVE_XSS_LO]; ++} ++ + /* + * Returns the set of feature flags that are supported and migratable by + * QEMU, for a given FeatureWord. +@@ -4940,8 +4980,8 @@ static const char *x86_cpu_feature_name(FeatureWord w, int bitnr) + /* XSAVE components are automatically enabled by other features, + * so return the original feature name instead + */ +- if (w == FEAT_XSAVE_COMP_LO || w == FEAT_XSAVE_COMP_HI) { +- int comp = (w == FEAT_XSAVE_COMP_HI) ? bitnr + 32 : bitnr; ++ if (w == FEAT_XSAVE_XCR0_LO || w == FEAT_XSAVE_XCR0_HI) { ++ int comp = (w == FEAT_XSAVE_XCR0_HI) ? bitnr + 32 : bitnr; + + if (comp < ARRAY_SIZE(x86_ext_save_areas) && + x86_ext_save_areas[comp].bits) { +@@ -5831,25 +5871,36 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, + } + + if (count == 0) { +- *ecx = xsave_area_size(x86_cpu_xsave_components(cpu)); +- *eax = env->features[FEAT_XSAVE_COMP_LO]; +- *edx = env->features[FEAT_XSAVE_COMP_HI]; ++ *ecx = xsave_area_size(x86_cpu_xsave_xcr0_components(cpu), false); ++ *eax = env->features[FEAT_XSAVE_XCR0_LO]; ++ *edx = env->features[FEAT_XSAVE_XCR0_HI]; + /* + * The initial value of xcr0 and ebx == 0, On host without kvm + * commit 412a3c41(e.g., CentOS 6), the ebx's value always == 0 + * even through guest update xcr0, this will crash some legacy guest + * (e.g., CentOS 6), So set ebx == ecx to workaroud it. + */ +- *ebx = kvm_enabled() ? *ecx : xsave_area_size(env->xcr0); ++ *ebx = kvm_enabled() ? *ecx : xsave_area_size(env->xcr0, false); + } else if (count == 1) { ++ uint64_t xstate = x86_cpu_xsave_xcr0_components(cpu) | ++ x86_cpu_xsave_xss_components(cpu); ++ + *eax = env->features[FEAT_XSAVE]; ++ *ebx = xsave_area_size(xstate, true); ++ *ecx = env->features[FEAT_XSAVE_XSS_LO]; ++ *edx = env->features[FEAT_XSAVE_XSS_HI]; + } else if (count < ARRAY_SIZE(x86_ext_save_areas)) { +- if ((x86_cpu_xsave_components(cpu) >> count) & 1) { +- const ExtSaveArea *esa = &x86_ext_save_areas[count]; ++ const ExtSaveArea *esa = &x86_ext_save_areas[count]; ++ ++ if (x86_cpu_xsave_xcr0_components(cpu) & (1ULL << count)) { + *eax = esa->size; + *ebx = esa->offset; + *ecx = esa->ecx & + (ESA_FEATURE_ALIGN64_MASK | ESA_FEATURE_XFD_MASK); ++ } else if (x86_cpu_xsave_xss_components(cpu) & (1ULL << count)) { ++ *eax = esa->size; ++ *ebx = 0; ++ *ecx = 1; + } + } + break; +@@ -5900,8 +5951,8 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, + } else { + *eax &= env->features[FEAT_SGX_12_1_EAX]; + *ebx &= 0; /* ebx reserve */ +- *ecx &= env->features[FEAT_XSAVE_COMP_LO]; +- *edx &= env->features[FEAT_XSAVE_COMP_HI]; ++ *ecx &= env->features[FEAT_XSAVE_XSS_LO]; ++ *edx &= env->features[FEAT_XSAVE_XSS_HI]; + + /* FP and SSE are always allowed regardless of XSAVE/XCR0. */ + *ecx |= XSTATE_FP_MASK | XSTATE_SSE_MASK; +@@ -6306,6 +6357,9 @@ static void x86_cpu_reset(DeviceState *dev) + } + for (i = 2; i < ARRAY_SIZE(x86_ext_save_areas); i++) { + const ExtSaveArea *esa = &x86_ext_save_areas[i]; ++ if (!((1 << i) & CPUID_XSTATE_XCR0_MASK)) { ++ continue; ++ } + if (env->features[esa->feature] & esa->bits) { + xcr0 |= 1ull << i; + } +@@ -6423,8 +6477,8 @@ static void x86_cpu_enable_xsave_components(X86CPU *cpu) + static bool request_perm; + + if (!(env->features[FEAT_1_ECX] & CPUID_EXT_XSAVE)) { +- env->features[FEAT_XSAVE_COMP_LO] = 0; +- env->features[FEAT_XSAVE_COMP_HI] = 0; ++ env->features[FEAT_XSAVE_XCR0_LO] = 0; ++ env->features[FEAT_XSAVE_XCR0_HI] = 0; + return; + } + +@@ -6442,8 +6496,10 @@ static void x86_cpu_enable_xsave_components(X86CPU *cpu) + request_perm = true; + } + +- env->features[FEAT_XSAVE_COMP_LO] = mask; +- env->features[FEAT_XSAVE_COMP_HI] = mask >> 32; ++ env->features[FEAT_XSAVE_XCR0_LO] = mask & CPUID_XSTATE_XCR0_MASK; ++ env->features[FEAT_XSAVE_XCR0_HI] = mask >> 32; ++ env->features[FEAT_XSAVE_XSS_LO] = mask & CPUID_XSTATE_XSS_MASK; ++ env->features[FEAT_XSAVE_XSS_HI] = mask >> 32; + } + + /***** Steps involved on loading and filtering CPUID data +diff --git a/target/i386/cpu.h b/target/i386/cpu.h +index 32ecec5fa7..e8322a928b 100644 +--- a/target/i386/cpu.h ++++ b/target/i386/cpu.h +@@ -565,6 +565,14 @@ typedef enum X86Seg { + #define ESA_FEATURE_XFD_MASK (1U << ESA_FEATURE_XFD_BIT) + + ++/* CPUID feature bits available in XCR0 */ ++#define CPUID_XSTATE_XCR0_MASK (XSTATE_FP_MASK | XSTATE_SSE_MASK | \ ++ XSTATE_YMM_MASK | XSTATE_BNDREGS_MASK | \ ++ XSTATE_BNDCSR_MASK | XSTATE_OPMASK_MASK | \ ++ XSTATE_ZMM_Hi256_MASK | \ ++ XSTATE_Hi16_ZMM_MASK | XSTATE_PKRU_MASK | \ ++ XSTATE_XTILE_CFG_MASK | XSTATE_XTILE_DATA_MASK) ++ + /* CPUID feature words */ + typedef enum FeatureWord { + FEAT_1_EDX, /* CPUID[1].EDX */ +@@ -583,8 +591,8 @@ typedef enum FeatureWord { + FEAT_SVM, /* CPUID[8000_000A].EDX */ + FEAT_XSAVE, /* CPUID[EAX=0xd,ECX=1].EAX */ + FEAT_6_EAX, /* CPUID[6].EAX */ +- FEAT_XSAVE_COMP_LO, /* CPUID[EAX=0xd,ECX=0].EAX */ +- FEAT_XSAVE_COMP_HI, /* CPUID[EAX=0xd,ECX=0].EDX */ ++ FEAT_XSAVE_XCR0_LO, /* CPUID[EAX=0xd,ECX=0].EAX */ ++ FEAT_XSAVE_XCR0_HI, /* CPUID[EAX=0xd,ECX=0].EDX */ + FEAT_ARCH_CAPABILITIES, + FEAT_CORE_CAPABILITY, + FEAT_PERF_CAPABILITIES, +@@ -601,6 +609,8 @@ typedef enum FeatureWord { + FEAT_SGX_12_0_EAX, /* CPUID[EAX=0x12,ECX=0].EAX (SGX) */ + FEAT_SGX_12_0_EBX, /* CPUID[EAX=0x12,ECX=0].EBX (SGX MISCSELECT[31:0]) */ + FEAT_SGX_12_1_EAX, /* CPUID[EAX=0x12,ECX=1].EAX (SGX ATTRIBUTES[31:0]) */ ++ FEAT_XSAVE_XSS_LO, /* CPUID[EAX=0xd,ECX=1].ECX */ ++ FEAT_XSAVE_XSS_HI, /* CPUID[EAX=0xd,ECX=1].EDX */ + FEAT_7_1_EDX, /* CPUID[EAX=7,ECX=1].EDX */ + FEAT_7_2_EDX, /* CPUID[EAX=7,ECX=2].EDX */ + FEATURE_WORDS, +-- +2.27.0 + diff --git a/target-ppc-Modify-the-uncorrect-value-irq-to-n_IRQ.patch b/target-ppc-Modify-the-uncorrect-value-irq-to-n_IRQ.patch new file mode 100644 index 00000000..bb6b40c8 --- /dev/null +++ b/target-ppc-Modify-the-uncorrect-value-irq-to-n_IRQ.patch @@ -0,0 +1,28 @@ +From 7ccba831f3a42e95eb06e997b9b85fddf3cd724c Mon Sep 17 00:00:00 2001 +From: JianChunfu +Date: Fri, 15 Mar 2024 14:22:45 +0800 +Subject: [PATCH] target/ppc: Modify the uncorrect value irq to n_IRQ + +Modify the uncorrect value "irq" to "n_IRQ" submitted before. + +Signed-off-by: JianChunfu +--- + hw/ppc/ppc.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/hw/ppc/ppc.c b/hw/ppc/ppc.c +index 6396bbe523..dedd56263d 100644 +--- a/hw/ppc/ppc.c ++++ b/hw/ppc/ppc.c +@@ -67,7 +67,7 @@ void ppc_set_irq(PowerPCCPU *cpu, int n_IRQ, int level) + + if (old_pending != env->pending_interrupts) { + if (kvm_enabled()) { +- kvmppc_set_interrupt(cpu, irq, level); ++ kvmppc_set_interrupt(cpu, n_IRQ, level); + } + } + +-- +2.27.0 + diff --git a/target-s390x-fix-handling-of-zeroes-in-vfmin-vfmax.patch b/target-s390x-fix-handling-of-zeroes-in-vfmin-vfmax.patch new file mode 100644 index 00000000..d6d29f01 --- /dev/null +++ b/target-s390x-fix-handling-of-zeroes-in-vfmin-vfmax.patch @@ -0,0 +1,51 @@ +From 81d20b4ec93e9689bff056a0a8bf6ff260da0c68 Mon Sep 17 00:00:00 2001 +From: tangbinzy +Date: Wed, 13 Mar 2024 05:40:28 +0000 +Subject: [PATCH] target/s390x: fix handling of zeroes in vfmin/vfmax mainline + inclusion commit 13c59eb09bd6d1fbc13f08b708226421f14a232b category: bugfix + +--------------------------------------------------------------- + +vfmin_res() / vfmax_res() are trying to check whether a and b are both +zeroes, but in reality they check that they are the same kind of zero. +This causes incorrect results when comparing positive and negative +zeroes. + +Fixes: da4807527f3b ("s390x/tcg: Implement VECTOR FP (MAXIMUM|MINIMUM)") +Co-developed-by: Ulrich Weigand +Signed-off-by: Ilya Leoshkevich +Reviewed-by: Richard Henderson +Reviewed-by: David Hildenbrand +Message-Id: <20220713182612.3780050-2-iii@linux.ibm.com> +Signed-off-by: Thomas Huth + +Signed-off-by: tangbinzy +--- + target/s390x/tcg/vec_fpu_helper.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/target/s390x/tcg/vec_fpu_helper.c b/target/s390x/tcg/vec_fpu_helper.c +index 1a77993471..d1249706f9 100644 +--- a/target/s390x/tcg/vec_fpu_helper.c ++++ b/target/s390x/tcg/vec_fpu_helper.c +@@ -794,7 +794,7 @@ static S390MinMaxRes vfmin_res(uint16_t dcmask_a, uint16_t dcmask_b, + default: + g_assert_not_reached(); + } +- } else if (unlikely(dcmask_a & dcmask_b & DCMASK_ZERO)) { ++ } else if (unlikely((dcmask_a & DCMASK_ZERO) && (dcmask_b & DCMASK_ZERO))) { + switch (type) { + case S390_MINMAX_TYPE_JAVA: + return neg_a ? S390_MINMAX_RES_A : S390_MINMAX_RES_B; +@@ -844,7 +844,7 @@ static S390MinMaxRes vfmax_res(uint16_t dcmask_a, uint16_t dcmask_b, + default: + g_assert_not_reached(); + } +- } else if (unlikely(dcmask_a & dcmask_b & DCMASK_ZERO)) { ++ } else if (unlikely((dcmask_a & DCMASK_ZERO) && (dcmask_b & DCMASK_ZERO))) { + const bool neg_a = dcmask_a & DCMASK_NEGATIVE; + + switch (type) { +-- +2.27.0 + diff --git a/tests-tcg-linux-test-Fix-random-hangs-in-test_socket.patch b/tests-tcg-linux-test-Fix-random-hangs-in-test_socket.patch new file mode 100644 index 00000000..a6f3986c --- /dev/null +++ b/tests-tcg-linux-test-Fix-random-hangs-in-test_socket.patch @@ -0,0 +1,41 @@ +From e4bfb1b17a1e548bdc96228a80e85c97eedf0299 Mon Sep 17 00:00:00 2001 +From: tangbinzy +Date: Thu, 21 Mar 2024 02:57:07 +0000 +Subject: [PATCH] tests/tcg/linux-test: Fix random hangs in test_socket + mainline inclusion commit b9e6074fc5b429b1e956e9c60db7e284a91e0f3d category: + bugfix + +--------------------------------------------------------------- + +test_socket hangs randomly in connect(), especially when run without +qemu. Apparently the reason is that linux started treating backlog +value of 0 literally instead of rounding it up since v4.4 (commit +ef547f2ac16b). + +So set it to 1 instead. + +Signed-off-by: Ilya Leoshkevich +Message-Id: <20220725144251.192720-1-iii@linux.ibm.com> +Signed-off-by: Thomas Huth + +Signed-off-by: tangbinzy +--- + tests/tcg/multiarch/linux/linux-test.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tests/tcg/multiarch/linux/linux-test.c b/tests/tcg/multiarch/linux/linux-test.c +index 78c68540ef..64f57cb287 100644 +--- a/tests/tcg/multiarch/linux/linux-test.c ++++ b/tests/tcg/multiarch/linux/linux-test.c +@@ -263,7 +263,7 @@ static int server_socket(void) + sockaddr.sin_port = htons(0); /* choose random ephemeral port) */ + sockaddr.sin_addr.s_addr = 0; + chk_error(bind(fd, (struct sockaddr *)&sockaddr, sizeof(sockaddr))); +- chk_error(listen(fd, 0)); ++ chk_error(listen(fd, 1)); + return fd; + + } +-- +2.27.0 + diff --git a/usb-hcd-xhci-check-slotid-in-xhci_wakeup_endpoint.patch b/usb-hcd-xhci-check-slotid-in-xhci_wakeup_endpoint.patch new file mode 100644 index 00000000..c8178eb5 --- /dev/null +++ b/usb-hcd-xhci-check-slotid-in-xhci_wakeup_endpoint.patch @@ -0,0 +1,39 @@ +From d43f2a9725a1211a0db657b9911a54d58ba26b36 Mon Sep 17 00:00:00 2001 +From: tangbinzy +Date: Fri, 8 Mar 2024 03:10:14 +0000 +Subject: [PATCH] usb/hcd-xhci: check slotid in xhci_wakeup_endpoint() + mainline inclusion commit 84218892f05515d20347fde4506e1944eb11cb25 category: + bugfix + +--------------------------------------------------------------- + +This prevents an OOB read (followed by an assertion failure in +xhci_kick_ep) when slotid > xhci->numslots. + +Reported-by: Soul Chen +Signed-off-by: Mauro Matteo Cascella +Message-Id: <20220705174734.2348829-1-mcascell@redhat.com> +Signed-off-by: Gerd Hoffmann + +Signed-off-by: tangbinzy +--- + hw/usb/hcd-xhci.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c +index 40300e1bcd..29636795be 100644 +--- a/hw/usb/hcd-xhci.c ++++ b/hw/usb/hcd-xhci.c +@@ -3288,7 +3288,8 @@ static void xhci_wakeup_endpoint(USBBus *bus, USBEndpoint *ep, + + DPRINTF("%s\n", __func__); + slotid = ep->dev->addr; +- if (slotid == 0 || !xhci->slots[slotid-1].enabled) { ++ if (slotid == 0 || slotid > xhci->numslots || ++ !xhci->slots[slotid - 1].enabled) { + DPRINTF("%s: oops, no slot for dev %d\n", __func__, ep->dev->addr); + return; + } +-- +2.27.0 + diff --git a/vga-fix-incorrect-line-height-in-640x200x2-mode.patch b/vga-fix-incorrect-line-height-in-640x200x2-mode.patch new file mode 100644 index 00000000..48451c15 --- /dev/null +++ b/vga-fix-incorrect-line-height-in-640x200x2-mode.patch @@ -0,0 +1,45 @@ +From d996226ded0190b96cce09169291cc696a390832 Mon Sep 17 00:00:00 2001 +From: tangbinzy +Date: Wed, 13 Mar 2024 02:51:28 +0000 +Subject: [PATCH] vga: fix incorrect line height in 640x200x2 mode mainline + inclusion commit 37e7b86766244b62a406747bb78e049390d0b528 category: bugfix + +--------------------------------------------------------------- + +When in CGA modes, QEMU wants to ignore the maximum scan field (bits 0..4) of +the maximum scan length register in the CRTC. It is not clear why this is +needed---for example, Bochs ignores bit 7 instead. The issue is that the +CGA modes are not detected correctly, and in particular mode 6 results in +multi_scan==3 according to how SeaBIOS programs it. The right way to check +for CGA graphics modes is to check whether bit 13 of the address is special +cased by the CRT controller to achieve line interleaving, i.e. whether bit 0 +of the CRTC mode control register is clear. + +Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1020 +Reported-by: Korneliusz Osmenda +Signed-off-by: Paolo Bonzini + +Signed-off-by: tangbinzy +--- + hw/display/vga.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/hw/display/vga.c b/hw/display/vga.c +index 9d1f66af40..33765148d9 100644 +--- a/hw/display/vga.c ++++ b/hw/display/vga.c +@@ -1514,9 +1514,10 @@ static void vga_draw_graphic(VGACommonState *s, int full_update) + force_shadow = true; + } + ++ /* bits 5-6: 0 = 16-color mode, 1 = 4-color mode, 2 = 256-color mode. */ + shift_control = (s->gr[VGA_GFX_MODE] >> 5) & 3; + double_scan = (s->cr[VGA_CRTC_MAX_SCAN] >> 7); +- if (shift_control != 1) { ++ if (s->cr[VGA_CRTC_MODE] & 1) { + multi_scan = (((s->cr[VGA_CRTC_MAX_SCAN] & 0x1f) + 1) << double_scan) + - 1; + } else { +-- +2.27.0 + diff --git a/vl-Improve-error-message-for-conflicting-incoming-an.patch b/vl-Improve-error-message-for-conflicting-incoming-an.patch new file mode 100644 index 00000000..31615396 --- /dev/null +++ b/vl-Improve-error-message-for-conflicting-incoming-an.patch @@ -0,0 +1,47 @@ +From 2971bbb88efe921f7b3e1ee80295e16ae5954e67 Mon Sep 17 00:00:00 2001 +From: zhujun2 +Date: Sun, 3 Mar 2024 22:41:52 -0800 +Subject: [PATCH] vl: Improve error message for conflicting -incoming and + -loadvm + +Currently, the conflict between -incoming and -loadvm is only detected +when loading the snapshot fails because the image is still inactive for +the incoming migration. This results in a suboptimal error message: + +$ ./qemu-system-x86_64 -hda /tmp/test.qcow2 -loadvm foo -incoming defer +qemu-system-x86_64: Device 'ide0-hd0' is writable but does not support snapshots + +Catch the situation already in qemu_validate_options() to improve the +message: + +$ ./qemu-system-x86_64 -hda /tmp/test.qcow2 -loadvm foo -incoming defer +qemu-system-x86_64: 'incoming' and 'loadvm' options are mutually exclusive + +Signed-off-by: Kevin Wolf +Message-ID: <20231201142520.32255-3-kwolf@redhat.com> +Signed-off-by: Kevin Wolf +(cherry picked from commit 5a7f21efaf99c60614fe1967be1c0f9aa46c526e) + +Signed-off-by: zhujun2 +--- + softmmu/vl.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/softmmu/vl.c b/softmmu/vl.c +index e34c8a0646..9dcbc3b266 100644 +--- a/softmmu/vl.c ++++ b/softmmu/vl.c +@@ -2474,6 +2474,10 @@ static void qemu_validate_options(const QDict *machine_opts) + } + } + ++ if (loadvm && incoming) { ++ error_report("'incoming' and 'loadvm' options are mutually exclusive"); ++ exit(EXIT_FAILURE); ++ } + if (loadvm && preconfig_requested) { + error_report("'preconfig' and 'loadvm' options are " + "mutually exclusive"); +-- +2.27.0 + -- Gitee From bf54b48c2963c869dfdc89977c57be4bd9e772aa Mon Sep 17 00:00:00 2001 From: Jiabo Feng Date: Mon, 22 Apr 2024 10:37:40 +0800 Subject: [PATCH 08/19] QEMU update to version 6.2.0-91 - hw/virtio/virtio-crypto: Protect from DMA re-entrancy bugs(CVE-2024-3446) - hw/char/virtio-serial-bus: Protect from DMA re-entrancy bugs(CVE-2024-3446) - hw/display/virtio-gpu: Protect from DMA re-entrancy bugs(CVE-2024-3446) - hw/virtio: Introduce virtio_bh_new_guarded() helper - hw: replace most qemu_bh_new calls with qemu_bh_new_guarded - checkpatch: add qemu_bh_new/aio_bh_new checks - async: avoid use-after-free on re-entrancy guard - async: Add an optional reentrancy guard to the BH API - hw/sd/sdhci: Do not update TRNMOD when Command Inhibit (DAT) is set(CVE-2024-3447) - rtl8139: Remove unused variable - tulip: Remove unused variable - virtio-mem: Fix the bitmap index of the section offset - virtio-mem: Fix the iterator variable in a vmem->rdl_list loop - system/memory: use ldn_he_p/stn_he_p - block: Fix crash when loading snapshot on inactive node - smmu: Clear SMMUPciBus pointer cache when system reset - block/mirror: Fix NULL s->job in active writes - amd_iommu: Fix APIC address check - virtio-crypto: fix NULL pointer dereference in virtio_crypto_free_reques - libqos/virtio.c: Correct 'flags' reading in qvirtqueue_kick cherry-pick from 66e411885a23c96ff73742d06b793fec3ceaebb7 - ivshmem-test.c: enable test_ivshmem_server for ppc64 arch - ivshmem.c: change endianness to LITTLE_ENDIAN - hw/ppc/mac.h: Remove MAX_CPUS macro - configure: remove dead variables - virtio-gpu: do not byteswap padding - hw/intc: clean-up error reporting for failed ITS cmd - qemu-iotests: Discard stderr when probing devices - linux-user: un-parent OBJECT(cpu) when closing thread - hw/net/rocker: Avoid undefined shifts with more than 31 ports - contrib/vhost-user-blk: Clean up deallocation of VuVirtqElement - scsi-disk: fix overflow when block size is not a multiple of BDRV_SECTOR_SIZE Signed-off-by: Jiabo Feng --- amd_iommu-Fix-APIC-address-check.patch | 57 +++ ...ional-reentrancy-guard-to-the-BH-API.patch | 214 +++++++++ ...-use-after-free-on-re-entrancy-guard.patch | 52 +++ ...when-loading-snapshot-on-inactive-no.patch | 49 ++ ...rror-Fix-NULL-s-job-in-active-writes.patch | 66 +++ ...ch-add-qemu_bh_new-aio_bh_new-checks.patch | 37 ++ configure-remove-dead-variables.patch | 46 ++ ...er-blk-Clean-up-deallocation-of-VuVi.patch | 68 +++ ...erial-bus-Protect-from-DMA-re-entran.patch | 42 ++ ...o-gpu-Protect-from-DMA-re-entrancy-b.patch | 143 ++++++ ...p-error-reporting-for-failed-ITS-cmd.patch | 94 ++++ ...oid-undefined-shifts-with-more-than-.patch | 55 +++ hw-ppc-mac.h-Remove-MAX_CPUS-macro.patch | 79 ++++ ...qemu_bh_new-calls-with-qemu_bh_new_g.patch | 427 ++++++++++++++++++ ...ot-update-TRNMOD-when-Command-Inhibi.patch | 135 ++++++ ...troduce-virtio_bh_new_guarded-helper.patch | 68 +++ ...-crypto-Protect-from-DMA-re-entrancy.patch | 43 ++ ...nable-test_ivshmem_server-for-ppc64-.patch | 69 +++ ...c-change-endianness-to-LITTLE_ENDIAN.patch | 56 +++ ...Correct-flags-reading-in-qvirtqueue_.patch | 40 ++ ...arent-OBJECT-cpu-when-closing-thread.patch | 65 +++ ...-Discard-stderr-when-probing-devices.patch | 68 +++ qemu.spec | 66 ++- rtl8139-Remove-unused-variable.patch | 44 ++ ...erflow-when-block-size-is-not-a-mult.patch | 59 +++ ...ciBus-pointer-cache-when-system-rese.patch | 41 ++ system-memory-use-ldn_he_p-stn_he_p.patch | 78 ++++ tulip-Remove-unused-variable.patch | 48 ++ ...x-NULL-pointer-dereference-in-virtio.patch | 56 +++ virtio-gpu-do-not-byteswap-padding.patch | 41 ++ ...he-bitmap-index-of-the-section-offse.patch | 47 ++ ...he-iterator-variable-in-a-vmem-rdl_l.patch | 39 ++ 32 files changed, 2491 insertions(+), 1 deletion(-) create mode 100644 amd_iommu-Fix-APIC-address-check.patch create mode 100644 async-Add-an-optional-reentrancy-guard-to-the-BH-API.patch create mode 100644 async-avoid-use-after-free-on-re-entrancy-guard.patch create mode 100644 block-Fix-crash-when-loading-snapshot-on-inactive-no.patch create mode 100644 block-mirror-Fix-NULL-s-job-in-active-writes.patch create mode 100644 checkpatch-add-qemu_bh_new-aio_bh_new-checks.patch create mode 100644 configure-remove-dead-variables.patch create mode 100644 contrib-vhost-user-blk-Clean-up-deallocation-of-VuVi.patch create mode 100644 hw-char-virtio-serial-bus-Protect-from-DMA-re-entran.patch create mode 100644 hw-display-virtio-gpu-Protect-from-DMA-re-entrancy-b.patch create mode 100644 hw-intc-clean-up-error-reporting-for-failed-ITS-cmd.patch create mode 100644 hw-net-rocker-Avoid-undefined-shifts-with-more-than-.patch create mode 100644 hw-ppc-mac.h-Remove-MAX_CPUS-macro.patch create mode 100644 hw-replace-most-qemu_bh_new-calls-with-qemu_bh_new_g.patch create mode 100644 hw-sd-sdhci-Do-not-update-TRNMOD-when-Command-Inhibi.patch create mode 100644 hw-virtio-Introduce-virtio_bh_new_guarded-helper.patch create mode 100644 hw-virtio-virtio-crypto-Protect-from-DMA-re-entrancy.patch create mode 100644 ivshmem-test.c-enable-test_ivshmem_server-for-ppc64-.patch create mode 100644 ivshmem.c-change-endianness-to-LITTLE_ENDIAN.patch create mode 100644 libqos-virtio.c-Correct-flags-reading-in-qvirtqueue_.patch create mode 100644 linux-user-un-parent-OBJECT-cpu-when-closing-thread.patch create mode 100644 qemu-iotests-Discard-stderr-when-probing-devices.patch create mode 100644 rtl8139-Remove-unused-variable.patch create mode 100644 scsi-disk-fix-overflow-when-block-size-is-not-a-mult.patch create mode 100644 smmu-Clear-SMMUPciBus-pointer-cache-when-system-rese.patch create mode 100644 system-memory-use-ldn_he_p-stn_he_p.patch create mode 100644 tulip-Remove-unused-variable.patch create mode 100644 virtio-crypto-fix-NULL-pointer-dereference-in-virtio.patch create mode 100644 virtio-gpu-do-not-byteswap-padding.patch create mode 100644 virtio-mem-Fix-the-bitmap-index-of-the-section-offse.patch create mode 100644 virtio-mem-Fix-the-iterator-variable-in-a-vmem-rdl_l.patch diff --git a/amd_iommu-Fix-APIC-address-check.patch b/amd_iommu-Fix-APIC-address-check.patch new file mode 100644 index 00000000..3c3012e5 --- /dev/null +++ b/amd_iommu-Fix-APIC-address-check.patch @@ -0,0 +1,57 @@ +From ea8049e63b663cab607d1f900ce593547485b33b Mon Sep 17 00:00:00 2001 +From: zhujun2 +Date: Wed, 10 Apr 2024 20:02:38 -0700 +Subject: [PATCH] amd_iommu: Fix APIC address check + +An MSI from I/O APIC may not exactly equal to APIC_DEFAULT_ADDRESS. In +fact, Windows 17763.3650 configures I/O APIC to set the dest_mode bit. +Cover the range assigned to APIC. + +Fixes: 577c470f43 ("x86_iommu/amd: Prepare for interrupt remap support") +Signed-off-by: Akihiko Odaki +Message-Id: <20230921114612.40671-1-akihiko.odaki@daynix.com> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +(cherry picked from commit 0114c4513095598cdf1cd8d7dacdfff757628121) +Signed-off-by: zhujun2 +--- + hw/i386/amd_iommu.c | 9 ++------- + hw/i386/amd_iommu.h | 2 -- + 2 files changed, 2 insertions(+), 9 deletions(-) + +diff --git a/hw/i386/amd_iommu.c b/hw/i386/amd_iommu.c +index 4d13d8e697..dfb9a2d8e6 100644 +--- a/hw/i386/amd_iommu.c ++++ b/hw/i386/amd_iommu.c +@@ -1245,13 +1245,8 @@ static int amdvi_int_remap_msi(AMDVIState *iommu, + return -AMDVI_IR_ERR; + } + +- if (origin->address & AMDVI_MSI_ADDR_HI_MASK) { +- trace_amdvi_err("MSI address high 32 bits non-zero when " +- "Interrupt Remapping enabled."); +- return -AMDVI_IR_ERR; +- } +- +- if ((origin->address & AMDVI_MSI_ADDR_LO_MASK) != APIC_DEFAULT_ADDRESS) { ++ if (origin->address < AMDVI_INT_ADDR_FIRST || ++ origin->address + sizeof(origin->data) > AMDVI_INT_ADDR_LAST + 1) { + trace_amdvi_err("MSI is not from IOAPIC."); + return -AMDVI_IR_ERR; + } +diff --git a/hw/i386/amd_iommu.h b/hw/i386/amd_iommu.h +index 79d38a3e41..210a37dfb1 100644 +--- a/hw/i386/amd_iommu.h ++++ b/hw/i386/amd_iommu.h +@@ -210,8 +210,6 @@ + #define AMDVI_INT_ADDR_FIRST 0xfee00000 + #define AMDVI_INT_ADDR_LAST 0xfeefffff + #define AMDVI_INT_ADDR_SIZE (AMDVI_INT_ADDR_LAST - AMDVI_INT_ADDR_FIRST + 1) +-#define AMDVI_MSI_ADDR_HI_MASK (0xffffffff00000000ULL) +-#define AMDVI_MSI_ADDR_LO_MASK (0x00000000ffffffffULL) + + /* SB IOAPIC is always on this device in AMD systems */ + #define AMDVI_IOAPIC_SB_DEVID PCI_BUILD_BDF(0, PCI_DEVFN(0x14, 0)) +-- +2.27.0 + diff --git a/async-Add-an-optional-reentrancy-guard-to-the-BH-API.patch b/async-Add-an-optional-reentrancy-guard-to-the-BH-API.patch new file mode 100644 index 00000000..dad79037 --- /dev/null +++ b/async-Add-an-optional-reentrancy-guard-to-the-BH-API.patch @@ -0,0 +1,214 @@ +From 2a9e9bb0201c513a085d51cb1d7b2cc83cad1d3b Mon Sep 17 00:00:00 2001 +From: Alexander Bulekov +Date: Thu, 27 Apr 2023 17:10:07 -0400 +Subject: [PATCH] async: Add an optional reentrancy guard to the BH API + +Devices can pass their MemoryReentrancyGuard (from their DeviceState), +when creating new BHes. Then, the async API will toggle the guard +before/after calling the BH call-back. This prevents bh->mmio reentrancy +issues. + +Signed-off-by: Alexander Bulekov +Reviewed-by: Darren Kenny +Message-Id: <20230427211013.2994127-3-alxndr@bu.edu> +[thuth: Fix "line over 90 characters" checkpatch.pl error] +Signed-off-by: Thomas Huth +Signed-off-by: liuxiangdong +--- + docs/devel/multiple-iothreads.txt | 7 +++++++ + include/block/aio.h | 18 ++++++++++++++++-- + include/qemu/main-loop.h | 7 +++++-- + tests/unit/ptimer-test-stubs.c | 3 ++- + util/async.c | 18 +++++++++++++++++- + util/main-loop.c | 6 ++++-- + util/trace-events | 1 + + 7 files changed, 52 insertions(+), 8 deletions(-) + +diff --git a/docs/devel/multiple-iothreads.txt b/docs/devel/multiple-iothreads.txt +index aeb997bed5..a11576bc74 100644 +--- a/docs/devel/multiple-iothreads.txt ++++ b/docs/devel/multiple-iothreads.txt +@@ -61,6 +61,7 @@ There are several old APIs that use the main loop AioContext: + * LEGACY qemu_aio_set_event_notifier() - monitor an event notifier + * LEGACY timer_new_ms() - create a timer + * LEGACY qemu_bh_new() - create a BH ++ * LEGACY qemu_bh_new_guarded() - create a BH with a device re-entrancy guard + * LEGACY qemu_aio_wait() - run an event loop iteration + + Since they implicitly work on the main loop they cannot be used in code that +@@ -72,8 +73,14 @@ Instead, use the AioContext functions directly (see include/block/aio.h): + * aio_set_event_notifier() - monitor an event notifier + * aio_timer_new() - create a timer + * aio_bh_new() - create a BH ++ * aio_bh_new_guarded() - create a BH with a device re-entrancy guard + * aio_poll() - run an event loop iteration + ++The qemu_bh_new_guarded/aio_bh_new_guarded APIs accept a "MemReentrancyGuard" ++argument, which is used to check for and prevent re-entrancy problems. For ++BHs associated with devices, the reentrancy-guard is contained in the ++corresponding DeviceState and named "mem_reentrancy_guard". ++ + The AioContext can be obtained from the IOThread using + iothread_get_aio_context() or for the main loop using qemu_get_aio_context(). + Code that takes an AioContext argument works both in IOThreads or the main +diff --git a/include/block/aio.h b/include/block/aio.h +index 47fbe9d81f..c7da152985 100644 +--- a/include/block/aio.h ++++ b/include/block/aio.h +@@ -22,6 +22,8 @@ + #include "qemu/event_notifier.h" + #include "qemu/thread.h" + #include "qemu/timer.h" ++#include "hw/qdev-core.h" ++ + + typedef struct BlockAIOCB BlockAIOCB; + typedef void BlockCompletionFunc(void *opaque, int ret); +@@ -321,9 +323,11 @@ void aio_bh_schedule_oneshot_full(AioContext *ctx, QEMUBHFunc *cb, void *opaque, + * is opaque and must be allocated prior to its use. + * + * @name: A human-readable identifier for debugging purposes. ++ * @reentrancy_guard: A guard set when entering a cb to prevent ++ * device-reentrancy issues + */ + QEMUBH *aio_bh_new_full(AioContext *ctx, QEMUBHFunc *cb, void *opaque, +- const char *name); ++ const char *name, MemReentrancyGuard *reentrancy_guard); + + /** + * aio_bh_new: Allocate a new bottom half structure +@@ -332,7 +336,17 @@ QEMUBH *aio_bh_new_full(AioContext *ctx, QEMUBHFunc *cb, void *opaque, + * string. + */ + #define aio_bh_new(ctx, cb, opaque) \ +- aio_bh_new_full((ctx), (cb), (opaque), (stringify(cb))) ++ aio_bh_new_full((ctx), (cb), (opaque), (stringify(cb)), NULL) ++ ++/** ++ * aio_bh_new_guarded: Allocate a new bottom half structure with a ++ * reentrancy_guard ++ * ++ * A convenience wrapper for aio_bh_new_full() that uses the cb as the name ++ * string. ++ */ ++#define aio_bh_new_guarded(ctx, cb, opaque, guard) \ ++ aio_bh_new_full((ctx), (cb), (opaque), (stringify(cb)), guard) + + /** + * aio_notify: Force processing of pending events. +diff --git a/include/qemu/main-loop.h b/include/qemu/main-loop.h +index 8dbc6fcb89..85dd5ada9e 100644 +--- a/include/qemu/main-loop.h ++++ b/include/qemu/main-loop.h +@@ -294,9 +294,12 @@ void qemu_cond_timedwait_iothread(QemuCond *cond, int ms); + + void qemu_fd_register(int fd); + ++#define qemu_bh_new_guarded(cb, opaque, guard) \ ++ qemu_bh_new_full((cb), (opaque), (stringify(cb)), guard) + #define qemu_bh_new(cb, opaque) \ +- qemu_bh_new_full((cb), (opaque), (stringify(cb))) +-QEMUBH *qemu_bh_new_full(QEMUBHFunc *cb, void *opaque, const char *name); ++ qemu_bh_new_full((cb), (opaque), (stringify(cb)), NULL) ++QEMUBH *qemu_bh_new_full(QEMUBHFunc *cb, void *opaque, const char *name, ++ MemReentrancyGuard *reentrancy_guard); + void qemu_bh_schedule_idle(QEMUBH *bh); + + enum { +diff --git a/tests/unit/ptimer-test-stubs.c b/tests/unit/ptimer-test-stubs.c +index 2a3ef58799..a7a2d08e7e 100644 +--- a/tests/unit/ptimer-test-stubs.c ++++ b/tests/unit/ptimer-test-stubs.c +@@ -108,7 +108,8 @@ int64_t qemu_clock_deadline_ns_all(QEMUClockType type, int attr_mask) + return deadline; + } + +-QEMUBH *qemu_bh_new_full(QEMUBHFunc *cb, void *opaque, const char *name) ++QEMUBH *qemu_bh_new_full(QEMUBHFunc *cb, void *opaque, const char *name, ++ MemReentrancyGuard *reentrancy_guard) + { + QEMUBH *bh = g_new(QEMUBH, 1); + +diff --git a/util/async.c b/util/async.c +index 6f6717a34b..3eb6b50163 100644 +--- a/util/async.c ++++ b/util/async.c +@@ -62,6 +62,7 @@ struct QEMUBH { + void *opaque; + QSLIST_ENTRY(QEMUBH) next; + unsigned flags; ++ MemReentrancyGuard *reentrancy_guard; + }; + + /* Called concurrently from any thread */ +@@ -123,7 +124,7 @@ void aio_bh_schedule_oneshot_full(AioContext *ctx, QEMUBHFunc *cb, + } + + QEMUBH *aio_bh_new_full(AioContext *ctx, QEMUBHFunc *cb, void *opaque, +- const char *name) ++ const char *name, MemReentrancyGuard *reentrancy_guard) + { + QEMUBH *bh; + bh = g_new(QEMUBH, 1); +@@ -132,13 +133,28 @@ QEMUBH *aio_bh_new_full(AioContext *ctx, QEMUBHFunc *cb, void *opaque, + .cb = cb, + .opaque = opaque, + .name = name, ++ .reentrancy_guard = reentrancy_guard, + }; + return bh; + } + + void aio_bh_call(QEMUBH *bh) + { ++ bool last_engaged_in_io = false; ++ ++ if (bh->reentrancy_guard) { ++ last_engaged_in_io = bh->reentrancy_guard->engaged_in_io; ++ if (bh->reentrancy_guard->engaged_in_io) { ++ trace_reentrant_aio(bh->ctx, bh->name); ++ } ++ bh->reentrancy_guard->engaged_in_io = true; ++ } ++ + bh->cb(bh->opaque); ++ ++ if (bh->reentrancy_guard) { ++ bh->reentrancy_guard->engaged_in_io = last_engaged_in_io; ++ } + } + + /* Multiple occurrences of aio_bh_poll cannot be called concurrently. */ +diff --git a/util/main-loop.c b/util/main-loop.c +index 06b18b195c..1eacf04691 100644 +--- a/util/main-loop.c ++++ b/util/main-loop.c +@@ -544,9 +544,11 @@ void main_loop_wait(int nonblocking) + + /* Functions to operate on the main QEMU AioContext. */ + +-QEMUBH *qemu_bh_new_full(QEMUBHFunc *cb, void *opaque, const char *name) ++QEMUBH *qemu_bh_new_full(QEMUBHFunc *cb, void *opaque, const char *name, ++ MemReentrancyGuard *reentrancy_guard) + { +- return aio_bh_new_full(qemu_aio_context, cb, opaque, name); ++ return aio_bh_new_full(qemu_aio_context, cb, opaque, name, ++ reentrancy_guard); + } + + /* +diff --git a/util/trace-events b/util/trace-events +index c8f53d7d9f..dc3b1eb3bf 100644 +--- a/util/trace-events ++++ b/util/trace-events +@@ -11,6 +11,7 @@ poll_remove(void *ctx, void *node, int fd) "ctx %p node %p fd %d" + # async.c + aio_co_schedule(void *ctx, void *co) "ctx %p co %p" + aio_co_schedule_bh_cb(void *ctx, void *co) "ctx %p co %p" ++reentrant_aio(void *ctx, const char *name) "ctx %p name %s" + + # thread-pool.c + thread_pool_submit(void *pool, void *req, void *opaque) "pool %p req %p opaque %p" +-- +2.27.0 + diff --git a/async-avoid-use-after-free-on-re-entrancy-guard.patch b/async-avoid-use-after-free-on-re-entrancy-guard.patch new file mode 100644 index 00000000..49598bae --- /dev/null +++ b/async-avoid-use-after-free-on-re-entrancy-guard.patch @@ -0,0 +1,52 @@ +From b2b00599451de0c9fe4dcdf7c47fb1d585ab7d23 Mon Sep 17 00:00:00 2001 +From: Alexander Bulekov +Date: Mon, 1 May 2023 10:19:56 -0400 +Subject: [PATCH] async: avoid use-after-free on re-entrancy guard + +A BH callback can free the BH, causing a use-after-free in aio_bh_call. +Fix that by keeping a local copy of the re-entrancy guard pointer. + +Buglink: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=58513 +Fixes: 9c86c97f12 ("async: Add an optional reentrancy guard to the BH API") +Signed-off-by: Alexander Bulekov +Message-Id: <20230501141956.3444868-1-alxndr@bu.edu> +Reviewed-by: Thomas Huth +Signed-off-by: Thomas Huth +--- + util/async.c | 14 ++++++++------ + 1 file changed, 8 insertions(+), 6 deletions(-) + +diff --git a/util/async.c b/util/async.c +index 3eb6b50163..760ad73404 100644 +--- a/util/async.c ++++ b/util/async.c +@@ -142,18 +142,20 @@ void aio_bh_call(QEMUBH *bh) + { + bool last_engaged_in_io = false; + +- if (bh->reentrancy_guard) { +- last_engaged_in_io = bh->reentrancy_guard->engaged_in_io; +- if (bh->reentrancy_guard->engaged_in_io) { ++ /* Make a copy of the guard-pointer as cb may free the bh */ ++ MemReentrancyGuard *reentrancy_guard = bh->reentrancy_guard; ++ if (reentrancy_guard) { ++ last_engaged_in_io = reentrancy_guard->engaged_in_io; ++ if (reentrancy_guard->engaged_in_io) { + trace_reentrant_aio(bh->ctx, bh->name); + } +- bh->reentrancy_guard->engaged_in_io = true; ++ reentrancy_guard->engaged_in_io = true; + } + + bh->cb(bh->opaque); + +- if (bh->reentrancy_guard) { +- bh->reentrancy_guard->engaged_in_io = last_engaged_in_io; ++ if (reentrancy_guard) { ++ reentrancy_guard->engaged_in_io = last_engaged_in_io; + } + } + +-- +2.27.0 + diff --git a/block-Fix-crash-when-loading-snapshot-on-inactive-no.patch b/block-Fix-crash-when-loading-snapshot-on-inactive-no.patch new file mode 100644 index 00000000..518beecc --- /dev/null +++ b/block-Fix-crash-when-loading-snapshot-on-inactive-no.patch @@ -0,0 +1,49 @@ +From aad76e8af00e2d507de9a2e562bdbc43a3bc2bc8 Mon Sep 17 00:00:00 2001 +From: zhujun2 +Date: Mon, 8 Apr 2024 00:42:25 -0700 +Subject: [PATCH] block: Fix crash when loading snapshot on inactive node + +bdrv_is_read_only() only checks if the node is configured to be +read-only eventually, but even if it returns false, writing to the node +may not be permitted at the moment (because it's inactive). + +bdrv_is_writable() checks that the node can be written to right now, and +this is what the snapshot operations really need. + +Change bdrv_can_snapshot() to use bdrv_is_writable() to fix crashes like +the following: + +$ ./qemu-system-x86_64 -hda /tmp/test.qcow2 -loadvm foo -incoming defer +qemu-system-x86_64: ../block/io.c:1990: int bdrv_co_write_req_prepare(BdrvChild *, int64_t, int64_t, BdrvTrackedRequest *, int): Assertion `!(bs->open_flags & BDRV_O_INACTIVE)' failed. + +The resulting error message after this patch isn't perfect yet, but at +least it doesn't crash any more: + +$ ./qemu-system-x86_64 -hda /tmp/test.qcow2 -loadvm foo -incoming defer +qemu-system-x86_64: Device 'ide0-hd0' is writable but does not support snapshots + +Signed-off-by: Kevin Wolf +Message-ID: <20231201142520.32255-2-kwolf@redhat.com> +Signed-off-by: Kevin Wolf +(cherry picked from commit d3007d348adaaf04ee8b099a475282034a662414) +Signed-off-by: zhujun2 +--- + block/snapshot.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/block/snapshot.c b/block/snapshot.c +index ccacda8bd5..f5703aa28b 100644 +--- a/block/snapshot.c ++++ b/block/snapshot.c +@@ -200,7 +200,7 @@ static BlockDriverState *bdrv_snapshot_fallback(BlockDriverState *bs) + int bdrv_can_snapshot(BlockDriverState *bs) + { + BlockDriver *drv = bs->drv; +- if (!drv || !bdrv_is_inserted(bs) || bdrv_is_read_only(bs)) { ++ if (!drv || !bdrv_is_inserted(bs) || !bdrv_is_writable(bs)) { + return 0; + } + +-- +2.27.0 + diff --git a/block-mirror-Fix-NULL-s-job-in-active-writes.patch b/block-mirror-Fix-NULL-s-job-in-active-writes.patch new file mode 100644 index 00000000..f5762251 --- /dev/null +++ b/block-mirror-Fix-NULL-s-job-in-active-writes.patch @@ -0,0 +1,66 @@ +From ed1ffd883ab3bfbcd3a11d63a7aba6a3a3f53372 Mon Sep 17 00:00:00 2001 +From: zhujun2 +Date: Thu, 11 Apr 2024 01:04:58 -0700 +Subject: [PATCH] block/mirror: Fix NULL s->job in active writes + +There is a small gap in mirror_start_job() before putting the mirror +filter node into the block graph (bdrv_append() call) and the actual job +being created. Before the job is created, MirrorBDSOpaque.job is NULL. + +It is possible that requests come in when bdrv_drained_end() is called, +and those requests would see MirrorBDSOpaque.job == NULL. Have our +filter node handle that case gracefully. + +Signed-off-by: Hanna Reitz +Message-Id: <20221109165452.67927-4-hreitz@redhat.com> +Reviewed-by: Kevin Wolf +Signed-off-by: Kevin Wolf +(cherry picked from commit da93d5c84e56e6b4e84aa8e98b6b984c9b6bb528) +Signed-off-by: zhujun2 +--- + block/mirror.c | 20 ++++++++++++-------- + 1 file changed, 12 insertions(+), 8 deletions(-) + +diff --git a/block/mirror.c b/block/mirror.c +index d1863565c4..de020bdb3e 100644 +--- a/block/mirror.c ++++ b/block/mirror.c +@@ -1420,11 +1420,13 @@ static int coroutine_fn bdrv_mirror_top_do_write(BlockDriverState *bs, + MirrorOp *op = NULL; + MirrorBDSOpaque *s = bs->opaque; + int ret = 0; +- bool copy_to_target; ++ bool copy_to_target = false; + +- copy_to_target = s->job->ret >= 0 && +- !job_is_cancelled(&s->job->common.job) && +- s->job->copy_mode == MIRROR_COPY_MODE_WRITE_BLOCKING; ++ if (s->job) { ++ copy_to_target = s->job->ret >= 0 && ++ !job_is_cancelled(&s->job->common.job) && ++ s->job->copy_mode == MIRROR_COPY_MODE_WRITE_BLOCKING; ++ } + + if (copy_to_target) { + op = active_write_prepare(s->job, offset, bytes); +@@ -1469,11 +1471,13 @@ static int coroutine_fn bdrv_mirror_top_pwritev(BlockDriverState *bs, + QEMUIOVector bounce_qiov; + void *bounce_buf; + int ret = 0; +- bool copy_to_target; ++ bool copy_to_target = false; + +- copy_to_target = s->job->ret >= 0 && +- !job_is_cancelled(&s->job->common.job) && +- s->job->copy_mode == MIRROR_COPY_MODE_WRITE_BLOCKING; ++ if (s->job) { ++ copy_to_target = s->job->ret >= 0 && ++ !job_is_cancelled(&s->job->common.job) && ++ s->job->copy_mode == MIRROR_COPY_MODE_WRITE_BLOCKING; ++ } + + if (copy_to_target) { + /* The guest might concurrently modify the data to write; but +-- +2.27.0 + diff --git a/checkpatch-add-qemu_bh_new-aio_bh_new-checks.patch b/checkpatch-add-qemu_bh_new-aio_bh_new-checks.patch new file mode 100644 index 00000000..23550518 --- /dev/null +++ b/checkpatch-add-qemu_bh_new-aio_bh_new-checks.patch @@ -0,0 +1,37 @@ +From f537178e29501b93349362bc46a0463550ff2206 Mon Sep 17 00:00:00 2001 +From: Alexander Bulekov +Date: Thu, 27 Apr 2023 17:10:08 -0400 +Subject: [PATCH] checkpatch: add qemu_bh_new/aio_bh_new checks + +Advise authors to use the _guarded versions of the APIs, instead. + +Signed-off-by: Alexander Bulekov +Reviewed-by: Darren Kenny +Message-Id: <20230427211013.2994127-4-alxndr@bu.edu> +Signed-off-by: Thomas Huth +--- + scripts/checkpatch.pl | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl +index cb8eff233e..b2428e80cc 100755 +--- a/scripts/checkpatch.pl ++++ b/scripts/checkpatch.pl +@@ -2858,6 +2858,14 @@ sub process { + if ($line =~ /\bsignal\s*\(/ && !($line =~ /SIG_(?:IGN|DFL)/)) { + ERROR("use sigaction to establish signal handlers; signal is not portable\n" . $herecurr); + } ++# recommend qemu_bh_new_guarded instead of qemu_bh_new ++ if ($realfile =~ /.*\/hw\/.*/ && $line =~ /\bqemu_bh_new\s*\(/) { ++ ERROR("use qemu_bh_new_guarded() instead of qemu_bh_new() to avoid reentrancy problems\n" . $herecurr); ++ } ++# recommend aio_bh_new_guarded instead of aio_bh_new ++ if ($realfile =~ /.*\/hw\/.*/ && $line =~ /\baio_bh_new\s*\(/) { ++ ERROR("use aio_bh_new_guarded() instead of aio_bh_new() to avoid reentrancy problems\n" . $herecurr); ++ } + # check for module_init(), use category-specific init macros explicitly please + if ($line =~ /^module_init\s*\(/) { + ERROR("please use block_init(), type_init() etc. instead of module_init()\n" . $herecurr); +-- +2.27.0 + diff --git a/configure-remove-dead-variables.patch b/configure-remove-dead-variables.patch new file mode 100644 index 00000000..e941f441 --- /dev/null +++ b/configure-remove-dead-variables.patch @@ -0,0 +1,46 @@ +From 259d232f7273fca7e703fc03a449516e1ab3aa7f Mon Sep 17 00:00:00 2001 +From: Luo Yifan +Date: Thu, 28 Mar 2024 11:00:36 +0800 +Subject: [PATCH] configure: remove dead variables + +cherry picked from commit cbe08c35cfa8f96125512a8aa3e1bf251b1410a5 + +Signed-off-by: Paolo Bonzini +Signed-off-by: Luo Yifan +--- + configure | 5 ----- + 1 file changed, 5 deletions(-) + +diff --git a/configure b/configure +index 8c9abd0e6e..991fe67886 100755 +--- a/configure ++++ b/configure +@@ -630,7 +630,6 @@ fi + case $targetos in + MINGW32*) + mingw32="yes" +- supported_os="yes" + plugins="no" + pie="no" + ;; +@@ -672,7 +671,6 @@ SunOS) + QEMU_CFLAGS="-D__EXTENSIONS__ $QEMU_CFLAGS" + ;; + Haiku) +- haiku="yes" + pie="no" + QEMU_CFLAGS="-DB_USE_POSITIVE_POSIX_ERRORS -D_BSD_SOURCE -fPIC $QEMU_CFLAGS" + ;; +@@ -3388,9 +3386,6 @@ fi + if test "$solaris" = "yes" ; then + echo "CONFIG_SOLARIS=y" >> $config_host_mak + fi +-if test "$haiku" = "yes" ; then +- echo "CONFIG_HAIKU=y" >> $config_host_mak +-fi + if test "$static" = "yes" ; then + echo "CONFIG_STATIC=y" >> $config_host_mak + fi +-- +2.27.0 + diff --git a/contrib-vhost-user-blk-Clean-up-deallocation-of-VuVi.patch b/contrib-vhost-user-blk-Clean-up-deallocation-of-VuVi.patch new file mode 100644 index 00000000..c3766297 --- /dev/null +++ b/contrib-vhost-user-blk-Clean-up-deallocation-of-VuVi.patch @@ -0,0 +1,68 @@ +From 37e47eef108920f6afad0c575bc658520bf5f3e2 Mon Sep 17 00:00:00 2001 +From: tangbinzy +Date: Mon, 25 Mar 2024 08:43:30 +0000 +Subject: [PATCH] contrib/vhost-user-blk: Clean up deallocation of VuVirtqElement + mainline inclusion + commit a32086de4919b9affb2ab2d0112d400eaf89f607 + category: bugfix + +--------------------------------------------------------------- + +We allocate VuVirtqElement with g_malloc() in +virtqueue_alloc_element(), but free it with free() in +vhost-user-blk.c. Harmless, but use g_free() anyway. + +One of the calls is guarded by a "not null" condition. Useless, +because it cannot be null (it's dereferenced right before), and even +it it could be, free() and g_free() do the right thing. Drop the +conditional. + +Fixes: Coverity CID 1490290 +Signed-off-by: Markus Armbruster +Reviewed-by: Raphael Norwitz +Acked-by: Michael S. Tsirkin +Message-Id: <20220630085219.1305519-1-armbru@redhat.com> +Signed-off-by: Laurent Vivier + +Signed-off-by: tangbinzy +--- + contrib/vhost-user-blk/vhost-user-blk.c | 9 +++------ + 1 file changed, 3 insertions(+), 6 deletions(-) + +diff --git a/contrib/vhost-user-blk/vhost-user-blk.c b/contrib/vhost-user-blk/vhost-user-blk.c +index d14b2896bf..91c4462659 100644 +--- a/contrib/vhost-user-blk/vhost-user-blk.c ++++ b/contrib/vhost-user-blk/vhost-user-blk.c +@@ -106,10 +106,7 @@ static void vub_req_complete(VubReq *req) + req->size + 1); + vu_queue_notify(vu_dev, req->vq); + +- if (req->elem) { +- free(req->elem); +- } +- ++ g_free(req->elem); + g_free(req); + } + +@@ -243,7 +240,7 @@ static int vub_virtio_process_req(VubDev *vdev_blk, + /* refer to hw/block/virtio_blk.c */ + if (elem->out_num < 1 || elem->in_num < 1) { + fprintf(stderr, "virtio-blk request missing headers\n"); +- free(elem); ++ g_free(elem); + return -1; + } + +@@ -325,7 +322,7 @@ static int vub_virtio_process_req(VubDev *vdev_blk, + return 0; + + err: +- free(elem); ++ g_free(elem); + g_free(req); + return -1; + } +-- +2.27.0 + diff --git a/hw-char-virtio-serial-bus-Protect-from-DMA-re-entran.patch b/hw-char-virtio-serial-bus-Protect-from-DMA-re-entran.patch new file mode 100644 index 00000000..151825ee --- /dev/null +++ b/hw-char-virtio-serial-bus-Protect-from-DMA-re-entran.patch @@ -0,0 +1,42 @@ +From 4d1cd3fcaa2939da851e39e419c433adcd672145 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Thu, 4 Apr 2024 20:56:35 +0200 +Subject: [PATCH] hw/char/virtio-serial-bus: Protect from DMA re-entrancy + bugs(CVE-2024-3446) +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Replace qemu_bh_new_guarded() by virtio_bh_new_guarded() +so the bus and device use the same guard. Otherwise the +DMA-reentrancy protection can be bypassed. + +Fixes: CVE-2024-3446 +Cc: qemu-stable@nongnu.org +Suggested-by: Alexander Bulekov +Reviewed-by: Gerd Hoffmann +Acked-by: Michael S. Tsirkin +Signed-off-by: Philippe Mathieu-Daudé +Reviewed-by: Michael S. Tsirkin +Message-Id: <20240409105537.18308-4-philmd@linaro.org> +--- + hw/char/virtio-serial-bus.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/hw/char/virtio-serial-bus.c b/hw/char/virtio-serial-bus.c +index 14716b66cc..e7f3e1eb87 100644 +--- a/hw/char/virtio-serial-bus.c ++++ b/hw/char/virtio-serial-bus.c +@@ -990,8 +990,7 @@ static void virtser_port_device_realize(DeviceState *dev, Error **errp) + return; + } + +- port->bh = qemu_bh_new_guarded(flush_queued_data_bh, port, +- &dev->mem_reentrancy_guard); ++ port->bh = virtio_bh_new_guarded(dev, flush_queued_data_bh, port); + port->elem = NULL; + } + +-- +2.27.0 + diff --git a/hw-display-virtio-gpu-Protect-from-DMA-re-entrancy-b.patch b/hw-display-virtio-gpu-Protect-from-DMA-re-entrancy-b.patch new file mode 100644 index 00000000..219ea010 --- /dev/null +++ b/hw-display-virtio-gpu-Protect-from-DMA-re-entrancy-b.patch @@ -0,0 +1,143 @@ +From c2f82029db6fe278c45e421ba6fece412f084516 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Thu, 4 Apr 2024 20:56:27 +0200 +Subject: [PATCH] hw/display/virtio-gpu: Protect from DMA re-entrancy + bugs(CVE-2024-3446) +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Replace qemu_bh_new_guarded() by virtio_bh_new_guarded() +so the bus and device use the same guard. Otherwise the +DMA-reentrancy protection can be bypassed: + + $ cat << EOF | qemu-system-i386 -display none -nodefaults \ + -machine q35,accel=qtest \ + -m 512M \ + -device virtio-gpu \ + -qtest stdio + outl 0xcf8 0x80000820 + outl 0xcfc 0xe0004000 + outl 0xcf8 0x80000804 + outw 0xcfc 0x06 + write 0xe0004030 0x4 0x024000e0 + write 0xe0004028 0x1 0xff + write 0xe0004020 0x4 0x00009300 + write 0xe000401c 0x1 0x01 + write 0x101 0x1 0x04 + write 0x103 0x1 0x1c + write 0x9301c8 0x1 0x18 + write 0x105 0x1 0x1c + write 0x107 0x1 0x1c + write 0x109 0x1 0x1c + write 0x10b 0x1 0x00 + write 0x10d 0x1 0x00 + write 0x10f 0x1 0x00 + write 0x111 0x1 0x00 + write 0x113 0x1 0x00 + write 0x115 0x1 0x00 + write 0x117 0x1 0x00 + write 0x119 0x1 0x00 + write 0x11b 0x1 0x00 + write 0x11d 0x1 0x00 + write 0x11f 0x1 0x00 + write 0x121 0x1 0x00 + write 0x123 0x1 0x00 + write 0x125 0x1 0x00 + write 0x127 0x1 0x00 + write 0x129 0x1 0x00 + write 0x12b 0x1 0x00 + write 0x12d 0x1 0x00 + write 0x12f 0x1 0x00 + write 0x131 0x1 0x00 + write 0x133 0x1 0x00 + write 0x135 0x1 0x00 + write 0x137 0x1 0x00 + write 0x139 0x1 0x00 + write 0xe0007003 0x1 0x00 + EOF + ... + ================================================================= + ==276099==ERROR: AddressSanitizer: heap-use-after-free on address 0x60d000011178 + at pc 0x562cc3b736c7 bp 0x7ffed49dee60 sp 0x7ffed49dee58 + READ of size 8 at 0x60d000011178 thread T0 + #0 0x562cc3b736c6 in virtio_gpu_ctrl_response hw/display/virtio-gpu.c:180:42 + #1 0x562cc3b7c40b in virtio_gpu_ctrl_response_nodata hw/display/virtio-gpu.c:192:5 + #2 0x562cc3b7c40b in virtio_gpu_simple_process_cmd hw/display/virtio-gpu.c:1015:13 + #3 0x562cc3b82873 in virtio_gpu_process_cmdq hw/display/virtio-gpu.c:1050:9 + #4 0x562cc4a85514 in aio_bh_call util/async.c:169:5 + #5 0x562cc4a85c52 in aio_bh_poll util/async.c:216:13 + #6 0x562cc4a1a79b in aio_dispatch util/aio-posix.c:423:5 + #7 0x562cc4a8a2da in aio_ctx_dispatch util/async.c:358:5 + #8 0x7f36840547a8 in g_main_context_dispatch (/lib/x86_64-linux-gnu/libglib-2.0.so.0+0x547a8) + #9 0x562cc4a8b753 in glib_pollfds_poll util/main-loop.c:290:9 + #10 0x562cc4a8b753 in os_host_main_loop_wait util/main-loop.c:313:5 + #11 0x562cc4a8b753 in main_loop_wait util/main-loop.c:592:11 + #12 0x562cc3938186 in qemu_main_loop system/runstate.c:782:9 + #13 0x562cc43b7af5 in qemu_default_main system/main.c:37:14 + #14 0x7f3683a6c189 in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16 + #15 0x7f3683a6c244 in __libc_start_main csu/../csu/libc-start.c:381:3 + #16 0x562cc2a58ac0 in _start (qemu-system-i386+0x231bac0) + + 0x60d000011178 is located 56 bytes inside of 136-byte region [0x60d000011140,0x60d0000111c8) + freed by thread T0 here: + #0 0x562cc2adb662 in __interceptor_free (qemu-system-i386+0x239e662) + #1 0x562cc3b86b21 in virtio_gpu_reset hw/display/virtio-gpu.c:1524:9 + #2 0x562cc416e20e in virtio_reset hw/virtio/virtio.c:2145:9 + #3 0x562cc37c5644 in virtio_pci_reset hw/virtio/virtio-pci.c:2249:5 + #4 0x562cc4233758 in memory_region_write_accessor system/memory.c:497:5 + #5 0x562cc4232eea in access_with_adjusted_size system/memory.c:573:18 + + previously allocated by thread T0 here: + #0 0x562cc2adb90e in malloc (qemu-system-i386+0x239e90e) + #1 0x7f368405a678 in g_malloc (/lib/x86_64-linux-gnu/libglib-2.0.so.0+0x5a678) + #2 0x562cc4163ffc in virtqueue_split_pop hw/virtio/virtio.c:1612:12 + #3 0x562cc4163ffc in virtqueue_pop hw/virtio/virtio.c:1783:16 + #4 0x562cc3b91a95 in virtio_gpu_handle_ctrl hw/display/virtio-gpu.c:1112:15 + #5 0x562cc4a85514 in aio_bh_call util/async.c:169:5 + #6 0x562cc4a85c52 in aio_bh_poll util/async.c:216:13 + #7 0x562cc4a1a79b in aio_dispatch util/aio-posix.c:423:5 + + SUMMARY: AddressSanitizer: heap-use-after-free hw/display/virtio-gpu.c:180:42 in virtio_gpu_ctrl_response + +With this change, the same reproducer triggers: + + qemu-system-i386: warning: Blocked re-entrant IO on MemoryRegion: virtio-pci-common-virtio-gpu at addr: 0x6 + +Fixes: CVE-2024-3446 +Cc: qemu-stable@nongnu.org +Reported-by: Alexander Bulekov +Reported-by: Yongkang Jia +Reported-by: Xiao Lei +Reported-by: Yiming Tao +Buglink: https://bugs.launchpad.net/qemu/+bug/1888606 +Reviewed-by: Gerd Hoffmann +Acked-by: Michael S. Tsirkin +Signed-off-by: Philippe Mathieu-Daudé +Reviewed-by: Michael S. Tsirkin +Message-Id: <20240409105537.18308-3-philmd@linaro.org> +Signed-off-by: liuxiangdong +--- + hw/display/virtio-gpu.c | 6 ++---- + 1 file changed, 2 insertions(+), 4 deletions(-) + +diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c +index 897042c3dc..0e5f5045b5 100644 +--- a/hw/display/virtio-gpu.c ++++ b/hw/display/virtio-gpu.c +@@ -1335,10 +1335,8 @@ void virtio_gpu_device_realize(DeviceState *qdev, Error **errp) + + g->ctrl_vq = virtio_get_queue(vdev, 0); + g->cursor_vq = virtio_get_queue(vdev, 1); +- g->ctrl_bh = qemu_bh_new_guarded(virtio_gpu_ctrl_bh, g, +- &qdev->mem_reentrancy_guard); +- g->cursor_bh = qemu_bh_new_guarded(virtio_gpu_cursor_bh, g, +- &qdev->mem_reentrancy_guard); ++ g->ctrl_bh = virtio_bh_new_guarded(qdev, virtio_gpu_ctrl_bh, g); ++ g->cursor_bh = virtio_bh_new_guarded(qdev, virtio_gpu_cursor_bh, g); + QTAILQ_INIT(&g->reslist); + QTAILQ_INIT(&g->cmdq); + QTAILQ_INIT(&g->fenceq); +-- +2.27.0 + diff --git a/hw-intc-clean-up-error-reporting-for-failed-ITS-cmd.patch b/hw-intc-clean-up-error-reporting-for-failed-ITS-cmd.patch new file mode 100644 index 00000000..21ecbfa6 --- /dev/null +++ b/hw-intc-clean-up-error-reporting-for-failed-ITS-cmd.patch @@ -0,0 +1,94 @@ +From 227f7f8b076ac11ff5959ddebc16569665b68e21 Mon Sep 17 00:00:00 2001 +From: Luo Yifan +Date: Thu, 28 Mar 2024 10:17:35 +0800 +Subject: [PATCH] hw/intc: clean-up error reporting for failed ITS cmd +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +cherry picked from commit 229c57b1986484ea2cd1eb744e3492af7eee063e + +While trying to debug a GIC ITS failure I saw some guest errors that +had poor formatting as well as leaving me confused as to what failed. +As most of the checks aren't possible without a valid dte split that +check apart and then check the other conditions in steps. This avoids +us relying on undefined data. + +I still get a failure with the current kvm-unit-tests but at least I +know (partially) why now: + + Exception return from AArch64 EL1 to AArch64 EL1 PC 0x40080588 + PASS: gicv3: its-trigger: inv/invall: dev2/eventid=20 now triggers an LPI + ITS: MAPD devid=2 size = 0x8 itt=0x40430000 valid=0 + INT dev_id=2 event_id=20 + process_its_cmd: invalid command attributes: invalid dte: 0 for 2 (MEM_TX: 0) + PASS: gicv3: its-trigger: mapd valid=false: no LPI after device unmap + SUMMARY: 6 tests, 1 unexpected failures + +Signed-off-by: Alex Bennée +Reviewed-by: Peter Maydell +Message-id: 20211112170454.3158925-1-alex.bennee@linaro.org +Cc: Shashi Mallela +Cc: Peter Maydell +Signed-off-by: Peter Maydell +Signed-off-by: Luo Yifan +--- + hw/intc/arm_gicv3_its.c | 39 +++++++++++++++++++++++++++------------ + 1 file changed, 27 insertions(+), 12 deletions(-) + +diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c +index c929a9cb5c..b99e63d58f 100644 +--- a/hw/intc/arm_gicv3_its.c ++++ b/hw/intc/arm_gicv3_its.c +@@ -274,21 +274,36 @@ static bool process_its_cmd(GICv3ITSState *s, uint64_t value, uint32_t offset, + if (res != MEMTX_OK) { + return result; + } ++ } else { ++ qemu_log_mask(LOG_GUEST_ERROR, ++ "%s: invalid command attributes: " ++ "invalid dte: %"PRIx64" for %d (MEM_TX: %d)\n", ++ __func__, dte, devid, res); ++ return result; + } + +- if ((devid > s->dt.maxids.max_devids) || !dte_valid || !ite_valid || +- !cte_valid || (eventid > max_eventid)) { ++ ++ /* ++ * In this implementation, in case of guest errors we ignore the ++ * command and move onto the next command in the queue. ++ */ ++ if (devid > s->dt.maxids.max_devids) { + qemu_log_mask(LOG_GUEST_ERROR, +- "%s: invalid command attributes " +- "devid %d or eventid %d or invalid dte %d or" +- "invalid cte %d or invalid ite %d\n", +- __func__, devid, eventid, dte_valid, cte_valid, +- ite_valid); +- /* +- * in this implementation, in case of error +- * we ignore this command and move onto the next +- * command in the queue +- */ ++ "%s: invalid command attributes: devid %d>%d", ++ __func__, devid, s->dt.maxids.max_devids); ++ ++ } else if (!dte_valid || !ite_valid || !cte_valid) { ++ qemu_log_mask(LOG_GUEST_ERROR, ++ "%s: invalid command attributes: " ++ "dte: %s, ite: %s, cte: %s\n", ++ __func__, ++ dte_valid ? "valid" : "invalid", ++ ite_valid ? "valid" : "invalid", ++ cte_valid ? "valid" : "invalid"); ++ } else if (eventid > max_eventid) { ++ qemu_log_mask(LOG_GUEST_ERROR, ++ "%s: invalid command attributes: eventid %d > %d\n", ++ __func__, eventid, max_eventid); + } else { + /* + * Current implementation only supports rdbase == procnum +-- +2.27.0 + diff --git a/hw-net-rocker-Avoid-undefined-shifts-with-more-than-.patch b/hw-net-rocker-Avoid-undefined-shifts-with-more-than-.patch new file mode 100644 index 00000000..a82e37f6 --- /dev/null +++ b/hw-net-rocker-Avoid-undefined-shifts-with-more-than-.patch @@ -0,0 +1,55 @@ +From 4b01fe41d731409b8bf2b569a38aa5959ed473c4 Mon Sep 17 00:00:00 2001 +From: tangbinzy +Date: Mon, 25 Mar 2024 08:58:38 +0000 +Subject: [PATCH] hw/net/rocker: Avoid undefined shifts with more than 31 ports + mainline inclusion + commit 7cf745dd9c25f0740dc1009598b58dd8dd989876 + category: bugfix + +--------------------------------------------------------------- + +In rocker_port_phys_link_status() and rocker_port_phys_enable_read() +we construct a 64-bit value with one bit per front-panel port. +However we accidentally do the shift as 32-bit arithmetic, which +means that if there are more than 31 front-panel ports this is +undefined behaviour. + +Fix the problem by ensuring we use 64-bit arithmetic for the whole +calculation. (We won't ever shift off the 64-bit value because +ROCKER_FP_PORTS_MAX is 62.) + +Resolves: Coverity CID 1487121, 1487160 +Reviewed-by: Richard Henderson +Signed-off-by: Peter Maydell +Signed-off-by: Jason Wang + +Signed-off-by: tangbinzy +--- + hw/net/rocker/rocker.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/hw/net/rocker/rocker.c b/hw/net/rocker/rocker.c +index 31f2340fb9..d8f3f16fe8 100644 +--- a/hw/net/rocker/rocker.c ++++ b/hw/net/rocker/rocker.c +@@ -1010,7 +1010,7 @@ static uint64_t rocker_port_phys_link_status(Rocker *r) + FpPort *port = r->fp_port[i]; + + if (fp_port_get_link_up(port)) { +- status |= 1 << (i + 1); ++ status |= 1ULL << (i + 1); + } + } + return status; +@@ -1025,7 +1025,7 @@ static uint64_t rocker_port_phys_enable_read(Rocker *r) + FpPort *port = r->fp_port[i]; + + if (fp_port_enabled(port)) { +- ret |= 1 << (i + 1); ++ ret |= 1ULL << (i + 1); + } + } + return ret; +-- +2.27.0 + diff --git a/hw-ppc-mac.h-Remove-MAX_CPUS-macro.patch b/hw-ppc-mac.h-Remove-MAX_CPUS-macro.patch new file mode 100644 index 00000000..292aa1de --- /dev/null +++ b/hw-ppc-mac.h-Remove-MAX_CPUS-macro.patch @@ -0,0 +1,79 @@ +From a2c1183a858ff592e0efb1886bbe6941b4ce018b Mon Sep 17 00:00:00 2001 +From: Luo Yifan +Date: Thu, 28 Mar 2024 13:54:29 +0800 +Subject: [PATCH] hw/ppc/mac.h: Remove MAX_CPUS macro +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +cherry picked from commit 83234b8289e64fc359a5bf02d886a333d65b8f8c + +The mac.h header defines a MAX_CPUS macro. This is confusingly named, +because it suggests it's a generic setting, but in fact it's used +by only the g3beige and mac99 machines. It's also using a single +macro for two values which aren't inherently the same -- if one +of these two machines was updated to support SMP configurations +then it would want a different max_cpus value to the other. + +Since the macro is used in only two places, just expand it out +and get rid of it. If hypothetical future work to support SMP +in these boards needs a compile-time-known limit on the number +of CPUs, we can give it a suitable name at that point. + +Signed-off-by: Peter Maydell +Reviewed-by: Philippe Mathieu-Daudé +Reviewed-by: Cédric Le Goater +Message-Id: <20211105184216.120972-1-peter.maydell@linaro.org> +Signed-off-by: Cédric Le Goater +Signed-off-by: Luo Yifan +--- + hw/ppc/mac.h | 3 --- + hw/ppc/mac_newworld.c | 3 ++- + hw/ppc/mac_oldworld.c | 3 ++- + 3 files changed, 4 insertions(+), 5 deletions(-) + +diff --git a/hw/ppc/mac.h b/hw/ppc/mac.h +index 22c8408078..a1fa8f8e41 100644 +--- a/hw/ppc/mac.h ++++ b/hw/ppc/mac.h +@@ -36,9 +36,6 @@ + #include "hw/pci-host/uninorth.h" + #include "qom/object.h" + +-/* SMP is not enabled, for now */ +-#define MAX_CPUS 1 +- + #define NVRAM_SIZE 0x2000 + #define PROM_FILENAME "openbios-ppc" + +diff --git a/hw/ppc/mac_newworld.c b/hw/ppc/mac_newworld.c +index 7bb7ac3997..4bddb529c2 100644 +--- a/hw/ppc/mac_newworld.c ++++ b/hw/ppc/mac_newworld.c +@@ -581,7 +581,8 @@ static void core99_machine_class_init(ObjectClass *oc, void *data) + mc->desc = "Mac99 based PowerMAC"; + mc->init = ppc_core99_init; + mc->block_default_type = IF_IDE; +- mc->max_cpus = MAX_CPUS; ++ /* SMP is not supported currently */ ++ mc->max_cpus = 1; + mc->default_boot_order = "cd"; + mc->default_display = "std"; + mc->kvm_type = core99_kvm_type; +diff --git a/hw/ppc/mac_oldworld.c b/hw/ppc/mac_oldworld.c +index de2be960e6..7016979a7c 100644 +--- a/hw/ppc/mac_oldworld.c ++++ b/hw/ppc/mac_oldworld.c +@@ -423,7 +423,8 @@ static void heathrow_class_init(ObjectClass *oc, void *data) + mc->desc = "Heathrow based PowerMAC"; + mc->init = ppc_heathrow_init; + mc->block_default_type = IF_IDE; +- mc->max_cpus = MAX_CPUS; ++ /* SMP is not supported currently */ ++ mc->max_cpus = 1; + #ifndef TARGET_PPC64 + mc->is_default = true; + #endif +-- +2.27.0 + diff --git a/hw-replace-most-qemu_bh_new-calls-with-qemu_bh_new_g.patch b/hw-replace-most-qemu_bh_new-calls-with-qemu_bh_new_g.patch new file mode 100644 index 00000000..d5f9e115 --- /dev/null +++ b/hw-replace-most-qemu_bh_new-calls-with-qemu_bh_new_g.patch @@ -0,0 +1,427 @@ +From 458b3f30a4e5d7b6361e6040061c9e30b4d75d1d Mon Sep 17 00:00:00 2001 +From: Alexander Bulekov +Date: Thu, 27 Apr 2023 17:10:09 -0400 +Subject: [PATCH] hw: replace most qemu_bh_new calls with qemu_bh_new_guarded + +This protects devices from bh->mmio reentrancy issues. + +Thanks: Thomas Huth for diagnosing OS X test failure. +Signed-off-by: Alexander Bulekov +Reviewed-by: Darren Kenny +Reviewed-by: Stefan Hajnoczi +Reviewed-by: Michael S. Tsirkin +Reviewed-by: Paul Durrant +Reviewed-by: Thomas Huth +Message-Id: <20230427211013.2994127-5-alxndr@bu.edu> +Signed-off-by: Thomas Huth +Signed-off-by: liuxiangdong +--- + hw/9pfs/xen-9p-backend.c | 5 ++++- + hw/block/dataplane/virtio-blk.c | 3 ++- + hw/block/dataplane/xen-block.c | 5 +++-- + hw/char/virtio-serial-bus.c | 3 ++- + hw/display/qxl.c | 9 ++++++--- + hw/display/virtio-gpu.c | 6 ++++-- + hw/ide/ahci.c | 3 ++- + hw/ide/ahci_internal.h | 1 + + hw/ide/core.c | 4 +++- + hw/misc/imx_rngc.c | 6 ++++-- + hw/misc/macio/mac_dbdma.c | 2 +- + hw/net/virtio-net.c | 3 ++- + hw/scsi/mptsas.c | 3 ++- + hw/scsi/scsi-bus.c | 3 ++- + hw/scsi/vmw_pvscsi.c | 3 ++- + hw/usb/dev-uas.c | 3 ++- + hw/usb/hcd-dwc2.c | 3 ++- + hw/usb/hcd-ehci.c | 3 ++- + hw/usb/hcd-uhci.c | 2 +- + hw/usb/host-libusb.c | 6 ++++-- + hw/usb/redirect.c | 6 ++++-- + hw/usb/xen-usb.c | 3 ++- + hw/virtio/virtio-balloon.c | 5 +++-- + hw/virtio/virtio-crypto.c | 3 ++- + 24 files changed, 62 insertions(+), 31 deletions(-) + +diff --git a/hw/9pfs/xen-9p-backend.c b/hw/9pfs/xen-9p-backend.c +index 65c4979c3c..09f7c13588 100644 +--- a/hw/9pfs/xen-9p-backend.c ++++ b/hw/9pfs/xen-9p-backend.c +@@ -60,6 +60,7 @@ typedef struct Xen9pfsDev { + + int num_rings; + Xen9pfsRing *rings; ++ MemReentrancyGuard mem_reentrancy_guard; + } Xen9pfsDev; + + static void xen_9pfs_disconnect(struct XenLegacyDevice *xendev); +@@ -441,7 +442,9 @@ static int xen_9pfs_connect(struct XenLegacyDevice *xendev) + xen_9pdev->rings[i].ring.out = xen_9pdev->rings[i].data + + XEN_FLEX_RING_SIZE(ring_order); + +- xen_9pdev->rings[i].bh = qemu_bh_new(xen_9pfs_bh, &xen_9pdev->rings[i]); ++ xen_9pdev->rings[i].bh = qemu_bh_new_guarded(xen_9pfs_bh, ++ &xen_9pdev->rings[i], ++ &xen_9pdev->mem_reentrancy_guard); + xen_9pdev->rings[i].out_cons = 0; + xen_9pdev->rings[i].out_size = 0; + xen_9pdev->rings[i].inprogress = false; +diff --git a/hw/block/dataplane/virtio-blk.c b/hw/block/dataplane/virtio-blk.c +index ee5a5352dc..5f0de7da1e 100644 +--- a/hw/block/dataplane/virtio-blk.c ++++ b/hw/block/dataplane/virtio-blk.c +@@ -127,7 +127,8 @@ bool virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *conf, + } else { + s->ctx = qemu_get_aio_context(); + } +- s->bh = aio_bh_new(s->ctx, notify_guest_bh, s); ++ s->bh = aio_bh_new_guarded(s->ctx, notify_guest_bh, s, ++ &DEVICE(vdev)->mem_reentrancy_guard); + s->batch_notify_vqs = bitmap_new(conf->num_queues); + + *dataplane = s; +diff --git a/hw/block/dataplane/xen-block.c b/hw/block/dataplane/xen-block.c +index 860787580a..07855feea6 100644 +--- a/hw/block/dataplane/xen-block.c ++++ b/hw/block/dataplane/xen-block.c +@@ -631,8 +631,9 @@ XenBlockDataPlane *xen_block_dataplane_create(XenDevice *xendev, + } else { + dataplane->ctx = qemu_get_aio_context(); + } +- dataplane->bh = aio_bh_new(dataplane->ctx, xen_block_dataplane_bh, +- dataplane); ++ dataplane->bh = aio_bh_new_guarded(dataplane->ctx, xen_block_dataplane_bh, ++ dataplane, ++ &DEVICE(xendev)->mem_reentrancy_guard); + + return dataplane; + } +diff --git a/hw/char/virtio-serial-bus.c b/hw/char/virtio-serial-bus.c +index edb7a44ee9..14716b66cc 100644 +--- a/hw/char/virtio-serial-bus.c ++++ b/hw/char/virtio-serial-bus.c +@@ -990,7 +990,8 @@ static void virtser_port_device_realize(DeviceState *dev, Error **errp) + return; + } + +- port->bh = qemu_bh_new(flush_queued_data_bh, port); ++ port->bh = qemu_bh_new_guarded(flush_queued_data_bh, port, ++ &dev->mem_reentrancy_guard); + port->elem = NULL; + } + +diff --git a/hw/display/qxl.c b/hw/display/qxl.c +index bcd9e8716a..0f663b9912 100644 +--- a/hw/display/qxl.c ++++ b/hw/display/qxl.c +@@ -2206,11 +2206,14 @@ static void qxl_realize_common(PCIQXLDevice *qxl, Error **errp) + + qemu_add_vm_change_state_handler(qxl_vm_change_state_handler, qxl); + +- qxl->update_irq = qemu_bh_new(qxl_update_irq_bh, qxl); ++ qxl->update_irq = qemu_bh_new_guarded(qxl_update_irq_bh, qxl, ++ &DEVICE(qxl)->mem_reentrancy_guard); + qxl_reset_state(qxl); + +- qxl->update_area_bh = qemu_bh_new(qxl_render_update_area_bh, qxl); +- qxl->ssd.cursor_bh = qemu_bh_new(qemu_spice_cursor_refresh_bh, &qxl->ssd); ++ qxl->update_area_bh = qemu_bh_new_guarded(qxl_render_update_area_bh, qxl, ++ &DEVICE(qxl)->mem_reentrancy_guard); ++ qxl->ssd.cursor_bh = qemu_bh_new_guarded(qemu_spice_cursor_refresh_bh, &qxl->ssd, ++ &DEVICE(qxl)->mem_reentrancy_guard); + } + + static void qxl_realize_primary(PCIDevice *dev, Error **errp) +diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c +index 9ccc0575e3..897042c3dc 100644 +--- a/hw/display/virtio-gpu.c ++++ b/hw/display/virtio-gpu.c +@@ -1335,8 +1335,10 @@ void virtio_gpu_device_realize(DeviceState *qdev, Error **errp) + + g->ctrl_vq = virtio_get_queue(vdev, 0); + g->cursor_vq = virtio_get_queue(vdev, 1); +- g->ctrl_bh = qemu_bh_new(virtio_gpu_ctrl_bh, g); +- g->cursor_bh = qemu_bh_new(virtio_gpu_cursor_bh, g); ++ g->ctrl_bh = qemu_bh_new_guarded(virtio_gpu_ctrl_bh, g, ++ &qdev->mem_reentrancy_guard); ++ g->cursor_bh = qemu_bh_new_guarded(virtio_gpu_cursor_bh, g, ++ &qdev->mem_reentrancy_guard); + QTAILQ_INIT(&g->reslist); + QTAILQ_INIT(&g->cmdq); + QTAILQ_INIT(&g->fenceq); +diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c +index 1e482738de..36d050aafc 100644 +--- a/hw/ide/ahci.c ++++ b/hw/ide/ahci.c +@@ -1510,7 +1510,8 @@ static void ahci_cmd_done(const IDEDMA *dma) + ahci_write_fis_d2h(ad); + + if (ad->port_regs.cmd_issue && !ad->check_bh) { +- ad->check_bh = qemu_bh_new(ahci_check_cmd_bh, ad); ++ ad->check_bh = qemu_bh_new_guarded(ahci_check_cmd_bh, ad, ++ &ad->mem_reentrancy_guard); + qemu_bh_schedule(ad->check_bh); + } + } +diff --git a/hw/ide/ahci_internal.h b/hw/ide/ahci_internal.h +index 109de9e2d1..a7768dd69e 100644 +--- a/hw/ide/ahci_internal.h ++++ b/hw/ide/ahci_internal.h +@@ -321,6 +321,7 @@ struct AHCIDevice { + bool init_d2h_sent; + AHCICmdHdr *cur_cmd; + NCQTransferState ncq_tfs[AHCI_MAX_CMDS]; ++ MemReentrancyGuard mem_reentrancy_guard; + }; + + struct AHCIPCIState { +diff --git a/hw/ide/core.c b/hw/ide/core.c +index 0d925c5ca5..14283a84a5 100644 +--- a/hw/ide/core.c ++++ b/hw/ide/core.c +@@ -510,6 +510,7 @@ BlockAIOCB *ide_issue_trim( + BlockCompletionFunc *cb, void *cb_opaque, void *opaque) + { + IDEState *s = opaque; ++ IDEDevice *dev = s->unit ? s->bus->slave : s->bus->master; + TrimAIOCB *iocb; + + /* Paired with a decrement in ide_trim_bh_cb() */ +@@ -517,7 +518,8 @@ BlockAIOCB *ide_issue_trim( + + iocb = blk_aio_get(&trim_aiocb_info, s->blk, cb, cb_opaque); + iocb->s = s; +- iocb->bh = qemu_bh_new(ide_trim_bh_cb, iocb); ++ iocb->bh = qemu_bh_new_guarded(ide_trim_bh_cb, iocb, ++ &DEVICE(dev)->mem_reentrancy_guard); + iocb->ret = 0; + iocb->qiov = qiov; + iocb->i = -1; +diff --git a/hw/misc/imx_rngc.c b/hw/misc/imx_rngc.c +index 632c03779c..082c6980ad 100644 +--- a/hw/misc/imx_rngc.c ++++ b/hw/misc/imx_rngc.c +@@ -228,8 +228,10 @@ static void imx_rngc_realize(DeviceState *dev, Error **errp) + sysbus_init_mmio(sbd, &s->iomem); + + sysbus_init_irq(sbd, &s->irq); +- s->self_test_bh = qemu_bh_new(imx_rngc_self_test, s); +- s->seed_bh = qemu_bh_new(imx_rngc_seed, s); ++ s->self_test_bh = qemu_bh_new_guarded(imx_rngc_self_test, s, ++ &dev->mem_reentrancy_guard); ++ s->seed_bh = qemu_bh_new_guarded(imx_rngc_seed, s, ++ &dev->mem_reentrancy_guard); + } + + static void imx_rngc_reset(DeviceState *dev) +diff --git a/hw/misc/macio/mac_dbdma.c b/hw/misc/macio/mac_dbdma.c +index efcc02609f..cc7e02203d 100644 +--- a/hw/misc/macio/mac_dbdma.c ++++ b/hw/misc/macio/mac_dbdma.c +@@ -914,7 +914,7 @@ static void mac_dbdma_realize(DeviceState *dev, Error **errp) + { + DBDMAState *s = MAC_DBDMA(dev); + +- s->bh = qemu_bh_new(DBDMA_run_bh, s); ++ s->bh = qemu_bh_new_guarded(DBDMA_run_bh, s, &dev->mem_reentrancy_guard); + } + + static void mac_dbdma_class_init(ObjectClass *oc, void *data) +diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c +index cdf1313053..f3fb9393b3 100644 +--- a/hw/net/virtio-net.c ++++ b/hw/net/virtio-net.c +@@ -2812,7 +2812,8 @@ static void virtio_net_add_queue(VirtIONet *n, int index) + n->vqs[index].tx_vq = + virtio_add_queue(vdev, n->net_conf.tx_queue_size, + virtio_net_handle_tx_bh); +- n->vqs[index].tx_bh = qemu_bh_new(virtio_net_tx_bh, &n->vqs[index]); ++ n->vqs[index].tx_bh = qemu_bh_new_guarded(virtio_net_tx_bh, &n->vqs[index], ++ &DEVICE(vdev)->mem_reentrancy_guard); + } + + n->vqs[index].tx_waiting = 0; +diff --git a/hw/scsi/mptsas.c b/hw/scsi/mptsas.c +index 5181b0c0b0..8487138cb6 100644 +--- a/hw/scsi/mptsas.c ++++ b/hw/scsi/mptsas.c +@@ -1321,7 +1321,8 @@ static void mptsas_scsi_realize(PCIDevice *dev, Error **errp) + } + s->max_devices = MPTSAS_NUM_PORTS; + +- s->request_bh = qemu_bh_new(mptsas_fetch_requests, s); ++ s->request_bh = qemu_bh_new_guarded(mptsas_fetch_requests, s, ++ &DEVICE(dev)->mem_reentrancy_guard); + + scsi_bus_init(&s->bus, sizeof(s->bus), &dev->qdev, &mptsas_scsi_info); + } +diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c +index 2b613ad2b3..89c4693cc2 100644 +--- a/hw/scsi/scsi-bus.c ++++ b/hw/scsi/scsi-bus.c +@@ -199,7 +199,8 @@ static void scsi_dma_restart_cb(void *opaque, bool running, RunState state) + AioContext *ctx = blk_get_aio_context(s->conf.blk); + /* The reference is dropped in scsi_dma_restart_bh.*/ + object_ref(OBJECT(s)); +- s->bh = aio_bh_new(ctx, scsi_dma_restart_bh, s); ++ s->bh = aio_bh_new_guarded(ctx, scsi_dma_restart_bh, s, ++ &DEVICE(s)->mem_reentrancy_guard); + qemu_bh_schedule(s->bh); + } + } +diff --git a/hw/scsi/vmw_pvscsi.c b/hw/scsi/vmw_pvscsi.c +index 4d9969f3b1..d5c6293a21 100644 +--- a/hw/scsi/vmw_pvscsi.c ++++ b/hw/scsi/vmw_pvscsi.c +@@ -1184,7 +1184,8 @@ pvscsi_realizefn(PCIDevice *pci_dev, Error **errp) + pcie_endpoint_cap_init(pci_dev, PVSCSI_EXP_EP_OFFSET); + } + +- s->completion_worker = qemu_bh_new(pvscsi_process_completion_queue, s); ++ s->completion_worker = qemu_bh_new_guarded(pvscsi_process_completion_queue, s, ++ &DEVICE(pci_dev)->mem_reentrancy_guard); + + scsi_bus_init(&s->bus, sizeof(s->bus), DEVICE(pci_dev), &pvscsi_scsi_info); + /* override default SCSI bus hotplug-handler, with pvscsi's one */ +diff --git a/hw/usb/dev-uas.c b/hw/usb/dev-uas.c +index c9f295e7e4..67bcfac626 100644 +--- a/hw/usb/dev-uas.c ++++ b/hw/usb/dev-uas.c +@@ -936,7 +936,8 @@ static void usb_uas_realize(USBDevice *dev, Error **errp) + + QTAILQ_INIT(&uas->results); + QTAILQ_INIT(&uas->requests); +- uas->status_bh = qemu_bh_new(usb_uas_send_status_bh, uas); ++ uas->status_bh = qemu_bh_new_guarded(usb_uas_send_status_bh, uas, ++ &d->mem_reentrancy_guard); + + dev->flags |= (1 << USB_DEV_FLAG_IS_SCSI_STORAGE); + scsi_bus_init(&uas->bus, sizeof(uas->bus), DEVICE(dev), &usb_uas_scsi_info); +diff --git a/hw/usb/hcd-dwc2.c b/hw/usb/hcd-dwc2.c +index 8755e9cbb0..a0c4e782b2 100644 +--- a/hw/usb/hcd-dwc2.c ++++ b/hw/usb/hcd-dwc2.c +@@ -1364,7 +1364,8 @@ static void dwc2_realize(DeviceState *dev, Error **errp) + s->fi = USB_FRMINTVL - 1; + s->eof_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, dwc2_frame_boundary, s); + s->frame_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, dwc2_work_timer, s); +- s->async_bh = qemu_bh_new(dwc2_work_bh, s); ++ s->async_bh = qemu_bh_new_guarded(dwc2_work_bh, s, ++ &dev->mem_reentrancy_guard); + + sysbus_init_irq(sbd, &s->irq); + } +diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c +index f9aa567f5d..3fbb06e248 100644 +--- a/hw/usb/hcd-ehci.c ++++ b/hw/usb/hcd-ehci.c +@@ -2535,7 +2535,8 @@ void usb_ehci_realize(EHCIState *s, DeviceState *dev, Error **errp) + } + + s->frame_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, ehci_work_timer, s); +- s->async_bh = qemu_bh_new(ehci_work_bh, s); ++ s->async_bh = qemu_bh_new_guarded(ehci_work_bh, s, ++ &dev->mem_reentrancy_guard); + s->device = dev; + + s->vmstate = qemu_add_vm_change_state_handler(usb_ehci_vm_state_change, s); +diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c +index 693c68f445..00a8de2fba 100644 +--- a/hw/usb/hcd-uhci.c ++++ b/hw/usb/hcd-uhci.c +@@ -1236,7 +1236,7 @@ void usb_uhci_common_realize(PCIDevice *dev, Error **errp) + USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL); + } + } +- s->bh = qemu_bh_new(uhci_bh, s); ++ s->bh = qemu_bh_new_guarded(uhci_bh, s, &DEVICE(dev)->mem_reentrancy_guard); + s->frame_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, uhci_frame_timer, s); + s->num_ports_vmstate = NB_PORTS; + s->frame_time = NANOSECONDS_PER_SECOND / uhci_frame_timer_freq; +diff --git a/hw/usb/host-libusb.c b/hw/usb/host-libusb.c +index 3394b04f50..13e83a3050 100644 +--- a/hw/usb/host-libusb.c ++++ b/hw/usb/host-libusb.c +@@ -1178,7 +1178,8 @@ static void usb_host_nodev_bh(void *opaque) + static void usb_host_nodev(USBHostDevice *s) + { + if (!s->bh_nodev) { +- s->bh_nodev = qemu_bh_new(usb_host_nodev_bh, s); ++ s->bh_nodev = qemu_bh_new_guarded(usb_host_nodev_bh, s, ++ &DEVICE(s)->mem_reentrancy_guard); + } + qemu_bh_schedule(s->bh_nodev); + } +@@ -1776,7 +1777,8 @@ static int usb_host_post_load(void *opaque, int version_id) + USBHostDevice *dev = opaque; + + if (!dev->bh_postld) { +- dev->bh_postld = qemu_bh_new(usb_host_post_load_bh, dev); ++ dev->bh_postld = qemu_bh_new_guarded(usb_host_post_load_bh, dev, ++ &DEVICE(dev)->mem_reentrancy_guard); + } + qemu_bh_schedule(dev->bh_postld); + dev->bh_postld_pending = true; +diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c +index 5f0ef9cb3b..59cd3cd7c4 100644 +--- a/hw/usb/redirect.c ++++ b/hw/usb/redirect.c +@@ -1437,8 +1437,10 @@ static void usbredir_realize(USBDevice *udev, Error **errp) + } + } + +- dev->chardev_close_bh = qemu_bh_new(usbredir_chardev_close_bh, dev); +- dev->device_reject_bh = qemu_bh_new(usbredir_device_reject_bh, dev); ++ dev->chardev_close_bh = qemu_bh_new_guarded(usbredir_chardev_close_bh, dev, ++ &DEVICE(dev)->mem_reentrancy_guard); ++ dev->device_reject_bh = qemu_bh_new_guarded(usbredir_device_reject_bh, dev, ++ &DEVICE(dev)->mem_reentrancy_guard); + dev->attach_timer = timer_new_ms(QEMU_CLOCK_VIRTUAL, usbredir_do_attach, dev); + + packet_id_queue_init(&dev->cancelled, dev, "cancelled"); +diff --git a/hw/usb/xen-usb.c b/hw/usb/xen-usb.c +index 0f7369e7ed..dec91294ad 100644 +--- a/hw/usb/xen-usb.c ++++ b/hw/usb/xen-usb.c +@@ -1021,7 +1021,8 @@ static void usbback_alloc(struct XenLegacyDevice *xendev) + + QTAILQ_INIT(&usbif->req_free_q); + QSIMPLEQ_INIT(&usbif->hotplug_q); +- usbif->bh = qemu_bh_new(usbback_bh, usbif); ++ usbif->bh = qemu_bh_new_guarded(usbback_bh, usbif, ++ &DEVICE(xendev)->mem_reentrancy_guard); + } + + static int usbback_free(struct XenLegacyDevice *xendev) +diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c +index 9a4f491b54..f503572e27 100644 +--- a/hw/virtio/virtio-balloon.c ++++ b/hw/virtio/virtio-balloon.c +@@ -917,8 +917,9 @@ static void virtio_balloon_device_realize(DeviceState *dev, Error **errp) + precopy_add_notifier(&s->free_page_hint_notify); + + object_ref(OBJECT(s->iothread)); +- s->free_page_bh = aio_bh_new(iothread_get_aio_context(s->iothread), +- virtio_ballloon_get_free_page_hints, s); ++ s->free_page_bh = aio_bh_new_guarded(iothread_get_aio_context(s->iothread), ++ virtio_ballloon_get_free_page_hints, s, ++ &dev->mem_reentrancy_guard); + } + + if (virtio_has_feature(s->host_features, VIRTIO_BALLOON_F_REPORTING)) { +diff --git a/hw/virtio/virtio-crypto.c b/hw/virtio/virtio-crypto.c +index 8c2047f4e0..bcca4fb72a 100644 +--- a/hw/virtio/virtio-crypto.c ++++ b/hw/virtio/virtio-crypto.c +@@ -829,7 +829,8 @@ static void virtio_crypto_device_realize(DeviceState *dev, Error **errp) + vcrypto->vqs[i].dataq = + virtio_add_queue(vdev, 1024, virtio_crypto_handle_dataq_bh); + vcrypto->vqs[i].dataq_bh = +- qemu_bh_new(virtio_crypto_dataq_bh, &vcrypto->vqs[i]); ++ qemu_bh_new_guarded(virtio_crypto_dataq_bh, &vcrypto->vqs[i], ++ &dev->mem_reentrancy_guard); + vcrypto->vqs[i].vcrypto = vcrypto; + } + +-- +2.27.0 + diff --git a/hw-sd-sdhci-Do-not-update-TRNMOD-when-Command-Inhibi.patch b/hw-sd-sdhci-Do-not-update-TRNMOD-when-Command-Inhibi.patch new file mode 100644 index 00000000..f30b3108 --- /dev/null +++ b/hw-sd-sdhci-Do-not-update-TRNMOD-when-Command-Inhibi.patch @@ -0,0 +1,135 @@ +From da4d478b1ae6082b6ca333ece1985e014f58fd5b Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Tue, 9 Apr 2024 16:19:27 +0200 +Subject: [PATCH] hw/sd/sdhci: Do not update TRNMOD when Command Inhibit (DAT) + is set(CVE-2024-3447) +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Per "SD Host Controller Standard Specification Version 3.00": + + * 2.2.5 Transfer Mode Register (Offset 00Ch) + + Writes to this register shall be ignored when the Command + Inhibit (DAT) in the Present State register is 1. + +Do not update the TRNMOD register when Command Inhibit (DAT) +bit is set to avoid the present-status register going out of +sync, leading to malicious guest using DMA mode and overflowing +the FIFO buffer: + + $ cat << EOF | qemu-system-i386 \ + -display none -nographic -nodefaults \ + -machine accel=qtest -m 512M \ + -device sdhci-pci,sd-spec-version=3 \ + -device sd-card,drive=mydrive \ + -drive if=none,index=0,file=null-co://,format=raw,id=mydrive \ + -qtest stdio + outl 0xcf8 0x80001013 + outl 0xcfc 0x91 + outl 0xcf8 0x80001001 + outl 0xcfc 0x06000000 + write 0x9100002c 0x1 0x05 + write 0x91000058 0x1 0x16 + write 0x91000005 0x1 0x04 + write 0x91000028 0x1 0x08 + write 0x16 0x1 0x21 + write 0x19 0x1 0x20 + write 0x9100000c 0x1 0x01 + write 0x9100000e 0x1 0x20 + write 0x9100000f 0x1 0x00 + write 0x9100000c 0x1 0x00 + write 0x91000020 0x1 0x00 + EOF + +Stack trace (part): +================================================================= +==89993==ERROR: AddressSanitizer: heap-buffer-overflow on address +0x615000029900 at pc 0x55d5f885700d bp 0x7ffc1e1e9470 sp 0x7ffc1e1e9468 +WRITE of size 1 at 0x615000029900 thread T0 + #0 0x55d5f885700c in sdhci_write_dataport hw/sd/sdhci.c:564:39 + #1 0x55d5f8849150 in sdhci_write hw/sd/sdhci.c:1223:13 + #2 0x55d5fa01db63 in memory_region_write_accessor system/memory.c:497:5 + #3 0x55d5fa01d245 in access_with_adjusted_size system/memory.c:573:18 + #4 0x55d5fa01b1a9 in memory_region_dispatch_write system/memory.c:1521:16 + #5 0x55d5fa09f5c9 in flatview_write_continue system/physmem.c:2711:23 + #6 0x55d5fa08f78b in flatview_write system/physmem.c:2753:12 + #7 0x55d5fa08f258 in address_space_write system/physmem.c:2860:18 + ... +0x615000029900 is located 0 bytes to the right of 512-byte region +[0x615000029700,0x615000029900) allocated by thread T0 here: + #0 0x55d5f7237b27 in __interceptor_calloc + #1 0x7f9e36dd4c50 in g_malloc0 + #2 0x55d5f88672f7 in sdhci_pci_realize hw/sd/sdhci-pci.c:36:5 + #3 0x55d5f844b582 in pci_qdev_realize hw/pci/pci.c:2092:9 + #4 0x55d5fa2ee74b in device_set_realized hw/core/qdev.c:510:13 + #5 0x55d5fa325bfb in property_set_bool qom/object.c:2358:5 + #6 0x55d5fa31ea45 in object_property_set qom/object.c:1472:5 + #7 0x55d5fa332509 in object_property_set_qobject om/qom-qobject.c:28:10 + #8 0x55d5fa31f6ed in object_property_set_bool qom/object.c:1541:15 + #9 0x55d5fa2e2948 in qdev_realize hw/core/qdev.c:292:12 + #10 0x55d5f8eed3f1 in qdev_device_add_from_qdict system/qdev-monitor.c:719:10 + #11 0x55d5f8eef7ff in qdev_device_add system/qdev-monitor.c:738:11 + #12 0x55d5f8f211f0 in device_init_func system/vl.c:1200:11 + #13 0x55d5fad0877d in qemu_opts_foreach util/qemu-option.c:1135:14 + #14 0x55d5f8f0df9c in qemu_create_cli_devices system/vl.c:2638:5 + #15 0x55d5f8f0db24 in qmp_x_exit_preconfig system/vl.c:2706:5 + #16 0x55d5f8f14dc0 in qemu_init system/vl.c:3737:9 + ... +SUMMARY: AddressSanitizer: heap-buffer-overflow hw/sd/sdhci.c:564:39 +in sdhci_write_dataport + +Add assertions to ensure the fifo_buffer[] is not overflowed by +malicious accesses to the Buffer Data Port register. + +Fixes: CVE-2024-3447 +Cc: qemu-stable@nongnu.org +Fixes: d7dfca0807 ("hw/sdhci: introduce standard SD host controller") +Buglink: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=58813 +Reported-by: Alexander Bulekov +Reported-by: Chuhong Yuan +Signed-off-by: Peter Maydell +Message-Id: +Signed-off-by: Philippe Mathieu-Daudé +Message-Id: <20240409145524.27913-1-philmd@linaro.org> +--- + hw/sd/sdhci.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c +index e0bbc90344..211daa4bb0 100644 +--- a/hw/sd/sdhci.c ++++ b/hw/sd/sdhci.c +@@ -471,6 +471,7 @@ static uint32_t sdhci_read_dataport(SDHCIState *s, unsigned size) + } + + for (i = 0; i < size; i++) { ++ assert(s->data_count < s->buf_maxsz); + value |= s->fifo_buffer[s->data_count] << i * 8; + s->data_count++; + /* check if we've read all valid data (blksize bytes) from buffer */ +@@ -559,6 +560,7 @@ static void sdhci_write_dataport(SDHCIState *s, uint32_t value, unsigned size) + } + + for (i = 0; i < size; i++) { ++ assert(s->data_count < s->buf_maxsz); + s->fifo_buffer[s->data_count] = value & 0xFF; + s->data_count++; + value >>= 8; +@@ -1184,6 +1186,12 @@ sdhci_write(void *opaque, hwaddr offset, uint64_t val, unsigned size) + if (!(s->capareg & R_SDHC_CAPAB_SDMA_MASK)) { + value &= ~SDHC_TRNS_DMA; + } ++ ++ /* TRNMOD writes are inhibited while Command Inhibit (DAT) is true */ ++ if (s->prnsts & SDHC_DATA_INHIBIT) { ++ mask |= 0xffff; ++ } ++ + MASKED_WRITE(s->trnmod, mask, value & SDHC_TRNMOD_MASK); + MASKED_WRITE(s->cmdreg, mask >> 16, value >> 16); + +-- +2.27.0 + diff --git a/hw-virtio-Introduce-virtio_bh_new_guarded-helper.patch b/hw-virtio-Introduce-virtio_bh_new_guarded-helper.patch new file mode 100644 index 00000000..07c4d574 --- /dev/null +++ b/hw-virtio-Introduce-virtio_bh_new_guarded-helper.patch @@ -0,0 +1,68 @@ +From 53203b7c0c933bd0ce07c58bdd7113e2fba62fa3 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Thu, 4 Apr 2024 20:56:11 +0200 +Subject: [PATCH] hw/virtio: Introduce virtio_bh_new_guarded() helper +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Introduce virtio_bh_new_guarded(), similar to qemu_bh_new_guarded() +but using the transport memory guard, instead of the device one +(there can only be one virtio device per virtio bus). + +Inspired-by: Gerd Hoffmann +Reviewed-by: Gerd Hoffmann +Acked-by: Michael S. Tsirkin +Signed-off-by: Philippe Mathieu-Daudé +Reviewed-by: Michael S. Tsirkin +Message-Id: <20240409105537.18308-2-philmd@linaro.org> +Signed-off-by: liuxiangdong +--- + hw/virtio/virtio.c | 10 ++++++++++ + include/hw/virtio/virtio.h | 7 +++++++ + 2 files changed, 17 insertions(+) + +diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c +index e3f392fc59..80156bfbd5 100644 +--- a/hw/virtio/virtio.c ++++ b/hw/virtio/virtio.c +@@ -3960,3 +3960,13 @@ static void virtio_register_types(void) + } + + type_init(virtio_register_types) ++ ++QEMUBH *virtio_bh_new_guarded_full(DeviceState *dev, ++ QEMUBHFunc *cb, void *opaque, ++ const char *name) ++{ ++ DeviceState *transport = qdev_get_parent_bus(dev)->parent; ++ ++ return qemu_bh_new_full(cb, opaque, name, ++ &transport->mem_reentrancy_guard); ++} +diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h +index 43509b33ff..4cc278f12c 100644 +--- a/include/hw/virtio/virtio.h ++++ b/include/hw/virtio/virtio.h +@@ -23,6 +23,7 @@ + #include "standard-headers/linux/virtio_ring.h" + #include "qom/object.h" + #include "hw/virtio/vhost.h" ++#include "block/aio.h" + + /* A guest should never accept this. It implies negotiation is broken. */ + #define VIRTIO_F_BAD_FEATURE 30 +@@ -409,4 +410,10 @@ static inline bool virtio_device_disabled(VirtIODevice *vdev) + bool virtio_legacy_allowed(VirtIODevice *vdev); + bool virtio_legacy_check_disabled(VirtIODevice *vdev); + ++QEMUBH *virtio_bh_new_guarded_full(DeviceState *dev, ++ QEMUBHFunc *cb, void *opaque, ++ const char *name); ++#define virtio_bh_new_guarded(dev, cb, opaque) \ ++ virtio_bh_new_guarded_full((dev), (cb), (opaque), (stringify(cb))) ++ + #endif +-- +2.27.0 + diff --git a/hw-virtio-virtio-crypto-Protect-from-DMA-re-entrancy.patch b/hw-virtio-virtio-crypto-Protect-from-DMA-re-entrancy.patch new file mode 100644 index 00000000..8ad27f24 --- /dev/null +++ b/hw-virtio-virtio-crypto-Protect-from-DMA-re-entrancy.patch @@ -0,0 +1,43 @@ +From 13eea576219af3919ac31f7e63818b46c4fcbab6 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Thu, 4 Apr 2024 20:56:41 +0200 +Subject: [PATCH] hw/virtio/virtio-crypto: Protect from DMA re-entrancy + bugs(CVE-2024-3446) +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Replace qemu_bh_new_guarded() by virtio_bh_new_guarded() +so the bus and device use the same guard. Otherwise the +DMA-reentrancy protection can be bypassed. + +Fixes: CVE-2024-3446 +Cc: qemu-stable@nongnu.org +Suggested-by: Alexander Bulekov +Reviewed-by: Gerd Hoffmann +Acked-by: Michael S. Tsirkin +Signed-off-by: Philippe Mathieu-Daudé +Reviewed-by: Michael S. Tsirkin +Message-Id: <20240409105537.18308-5-philmd@linaro.org> +--- + hw/virtio/virtio-crypto.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/hw/virtio/virtio-crypto.c b/hw/virtio/virtio-crypto.c +index bcca4fb72a..07566f0d46 100644 +--- a/hw/virtio/virtio-crypto.c ++++ b/hw/virtio/virtio-crypto.c +@@ -829,8 +829,8 @@ static void virtio_crypto_device_realize(DeviceState *dev, Error **errp) + vcrypto->vqs[i].dataq = + virtio_add_queue(vdev, 1024, virtio_crypto_handle_dataq_bh); + vcrypto->vqs[i].dataq_bh = +- qemu_bh_new_guarded(virtio_crypto_dataq_bh, &vcrypto->vqs[i], +- &dev->mem_reentrancy_guard); ++ virtio_bh_new_guarded(dev, virtio_crypto_dataq_bh, ++ &vcrypto->vqs[i]); + vcrypto->vqs[i].vcrypto = vcrypto; + } + +-- +2.27.0 + diff --git a/ivshmem-test.c-enable-test_ivshmem_server-for-ppc64-.patch b/ivshmem-test.c-enable-test_ivshmem_server-for-ppc64-.patch new file mode 100644 index 00000000..2753460f --- /dev/null +++ b/ivshmem-test.c-enable-test_ivshmem_server-for-ppc64-.patch @@ -0,0 +1,69 @@ +From d193565aa9b9b293337a82f347fa1c877814d871 Mon Sep 17 00:00:00 2001 +From: Luo Yifan +Date: Thu, 28 Mar 2024 14:00:37 +0800 +Subject: [PATCH] ivshmem-test.c: enable test_ivshmem_server for ppc64 arch +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +cherry picked from commit d04aeb6862a18540b7f72617b05be19846e1b047 + +This test, if enabled by hand, was failing when the ivhsmem device was +being declared as DEVICE_NATIVE_ENDIAN with the following error: + +/ppc64/ivshmem/pair: OK +/ppc64/ivshmem/server: +** +ERROR:/home/danielhb/qemu/tests/qtest/ivshmem-test.c:367:test_ivshmem_server: +assertion failed (ret != 0): (0 != 0) +Aborted + +After the endianness change done in the previous patch, we can verify in +both a a Power 9 little-endian host and in a Power 8 big-endian host +that this test is now passing: + +$ QTEST_QEMU_BINARY=./ppc64-softmmu/qemu-system-ppc64 ./tests/qtest/ivshmem-test -m slow +/ppc64/ivshmem/single: OK +/ppc64/ivshmem/hotplug: OK +/ppc64/ivshmem/memdev: OK +/ppc64/ivshmem/pair: OK +/ppc64/ivshmem/server: OK + +Let's keep it that way by officially enabling it for ppc64. + +Acked-by: Thomas Huth +Signed-off-by: Daniel Henrique Barboza +Reviewed-by: Philippe Mathieu-Daudé +Message-Id: <20211124092948.335389-3-danielhb413@gmail.com> +Signed-off-by: Cédric Le Goater +Signed-off-by: Luo Yifan +--- + tests/qtest/ivshmem-test.c | 5 +---- + 1 file changed, 1 insertion(+), 4 deletions(-) + +diff --git a/tests/qtest/ivshmem-test.c b/tests/qtest/ivshmem-test.c +index dfa69424ed..fe94dd3b96 100644 +--- a/tests/qtest/ivshmem-test.c ++++ b/tests/qtest/ivshmem-test.c +@@ -463,7 +463,6 @@ static gchar *mktempshm(int size, int *fd) + int main(int argc, char **argv) + { + int ret, fd; +- const char *arch = qtest_get_arch(); + gchar dir[] = "/tmp/ivshmem-test.XXXXXX"; + + g_test_init(&argc, &argv, NULL); +@@ -488,9 +487,7 @@ int main(int argc, char **argv) + qtest_add_func("/ivshmem/memdev", test_ivshmem_memdev); + if (g_test_slow()) { + qtest_add_func("/ivshmem/pair", test_ivshmem_pair); +- if (strcmp(arch, "ppc64") != 0) { +- qtest_add_func("/ivshmem/server", test_ivshmem_server); +- } ++ qtest_add_func("/ivshmem/server", test_ivshmem_server); + } + + out: +-- +2.27.0 + diff --git a/ivshmem.c-change-endianness-to-LITTLE_ENDIAN.patch b/ivshmem.c-change-endianness-to-LITTLE_ENDIAN.patch new file mode 100644 index 00000000..80cc63a9 --- /dev/null +++ b/ivshmem.c-change-endianness-to-LITTLE_ENDIAN.patch @@ -0,0 +1,56 @@ +From b2120f0a316470369451103d9d1b50b2d13cd68b Mon Sep 17 00:00:00 2001 +From: Luo Yifan +Date: Thu, 28 Mar 2024 13:58:20 +0800 +Subject: [PATCH] ivshmem.c: change endianness to LITTLE_ENDIAN +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +cherry picked from commit ef80a708b57ddc8f605d9982bfaa0536e720ed9f + +The ivshmem device, as with most PCI devices, uses little endian byte +order. However, the endianness of its mmio_ops is marked as +DEVICE_NATIVE_ENDIAN. This presents not only the usual problems with big +endian hosts but also with PowerPC little endian hosts as well, since +the Power architecture in QEMU uses big endian hardware (XIVE controller, +PCI Host Bridges, etc) even if the host is in little endian byte order. + +As it is today, the IVPosition of the device will be byte swapped when +running in Power BE and LE. This can be seen by changing the existing +qtest 'ivshmem-test' to run in ppc64 hosts and printing the IVPOSITION +regs in test_ivshmem_server() right after the VM ids assert. For x86_64 +the VM id values read are '0' and '1', for ppc64 (tested in a Power8 +RHEL 7.9 BE server) and ppc64le (tested in a Power9 RHEL 8.6 LE server) +the ids will be '0' and '0x1000000'. + +Change this device to LITTLE_ENDIAN fixes the issue for Power hosts of +both endianness, and every other big-endian architecture that might use +this device, without impacting x86 users. + +Fixes: cb06608e17f8 ("ivshmem: convert to memory API") +Resolves: https://gitlab.com/qemu-project/qemu/-/issues/168 +Signed-off-by: Daniel Henrique Barboza +Reviewed-by: Philippe Mathieu-Daudé +Message-Id: <20211124092948.335389-2-danielhb413@gmail.com> +Signed-off-by: Cédric Le Goater +Signed-off-by: Luo Yifan +--- + hw/misc/ivshmem.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/hw/misc/ivshmem.c b/hw/misc/ivshmem.c +index 05f06ed6cf..4093c59079 100644 +--- a/hw/misc/ivshmem.c ++++ b/hw/misc/ivshmem.c +@@ -243,7 +243,7 @@ static uint64_t ivshmem_io_read(void *opaque, hwaddr addr, + static const MemoryRegionOps ivshmem_mmio_ops = { + .read = ivshmem_io_read, + .write = ivshmem_io_write, +- .endianness = DEVICE_NATIVE_ENDIAN, ++ .endianness = DEVICE_LITTLE_ENDIAN, + .impl = { + .min_access_size = 4, + .max_access_size = 4, +-- +2.27.0 + diff --git a/libqos-virtio.c-Correct-flags-reading-in-qvirtqueue_.patch b/libqos-virtio.c-Correct-flags-reading-in-qvirtqueue_.patch new file mode 100644 index 00000000..f0d1b080 --- /dev/null +++ b/libqos-virtio.c-Correct-flags-reading-in-qvirtqueue_.patch @@ -0,0 +1,40 @@ +From c4acd87e379d6b6c3a9b8e381c91af255d96aeaa Mon Sep 17 00:00:00 2001 +From: guping +Date: Sat, 30 Mar 2024 14:59:51 +0000 +Subject: [PATCH] libqos/virtio.c: Correct 'flags' reading in qvirtqueue_kick + cherry-pick from 66e411885a23c96ff73742d06b793fec3ceaebb7 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +In qvirtqueue_kick(), the 'flags' were previously being incorrectly read from +vq->avail instead of the correct vq->used location. This update ensures 'flags' +are read from the correct location as per the virtio standard. + +Signed-off-by: default avatarZheyu Ma +Reviewed-by: default avatarPhilippe Mathieu-Daudé +Reviewed-by: Stefan Hajnoczi's avatarStefan Hajnoczi +Message-ID: <20240320090442.267525-1-zheyuma97@gmail.com> +Signed-off-by: Thomas Huth's avatarThomas Huth + +Signed-off-by: guping +--- + tests/qtest/libqos/virtio.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tests/qtest/libqos/virtio.c b/tests/qtest/libqos/virtio.c +index 6fe7bf9555..08e5bcdca1 100644 +--- a/tests/qtest/libqos/virtio.c ++++ b/tests/qtest/libqos/virtio.c +@@ -377,7 +377,7 @@ void qvirtqueue_kick(QTestState *qts, QVirtioDevice *d, QVirtQueue *vq, + qvirtio_writew(d, qts, vq->avail + 2, idx + 1); + + /* Must read after idx is updated */ +- flags = qvirtio_readw(d, qts, vq->avail); ++ flags = qvirtio_readw(d, qts, vq->used); + avail_event = qvirtio_readw(d, qts, vq->used + 4 + + sizeof(struct vring_used_elem) * vq->size); + +-- +2.27.0 + diff --git a/linux-user-un-parent-OBJECT-cpu-when-closing-thread.patch b/linux-user-un-parent-OBJECT-cpu-when-closing-thread.patch new file mode 100644 index 00000000..7a0045ab --- /dev/null +++ b/linux-user-un-parent-OBJECT-cpu-when-closing-thread.patch @@ -0,0 +1,65 @@ +From 41f426180f0d5d5a1720166a77a0d741fd072680 Mon Sep 17 00:00:00 2001 +From: tangbinzy +Date: Mon, 25 Mar 2024 09:32:04 +0000 +Subject: [PATCH] linux-user: un-parent OBJECT(cpu) when closing thread + mainline inclusion + commit 52f0c1607671293afcdb2acc2f83e9bccbfa74bb + category: bugfix +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +--------------------------------------------------------------- + +While forcing the CPU to unrealize by hand does trigger the clean-up +code we never fully free resources because refcount never reaches +zero. This is because QOM automatically added objects without an +explicit parent to /unattached/, incrementing the refcount. + +Instead of manually triggering unrealization just unparent the object +and let the device machinery deal with that for us. + +Resolves: https://gitlab.com/qemu-project/qemu/-/issues/866 +Signed-off-by: Alex Bennée +Reviewed-by: Laurent Vivier +Message-Id: <20220811151413.3350684-2-alex.bennee@linaro.org> + +Signed-off-by: tangbinzy +--- + linux-user/syscall.c | 13 +++++++------ + 1 file changed, 7 insertions(+), 6 deletions(-) + +diff --git a/linux-user/syscall.c b/linux-user/syscall.c +index 92df0f9d8c..a5fe399277 100644 +--- a/linux-user/syscall.c ++++ b/linux-user/syscall.c +@@ -8345,7 +8345,13 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, + if (CPU_NEXT(first_cpu)) { + TaskState *ts = cpu->opaque; + +- object_property_set_bool(OBJECT(cpu), "realized", false, NULL); ++ if (ts->child_tidptr) { ++ put_user_u32(0, ts->child_tidptr); ++ do_sys_futex(g2h(cpu, ts->child_tidptr), ++ FUTEX_WAKE, INT_MAX, NULL, NULL, 0); ++ } ++ ++ object_unparent(OBJECT(cpu)); + object_unref(OBJECT(cpu)); + /* + * At this point the CPU should be unrealized and removed +@@ -8355,11 +8361,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, + + pthread_mutex_unlock(&clone_lock); + +- if (ts->child_tidptr) { +- put_user_u32(0, ts->child_tidptr); +- do_sys_futex(g2h(cpu, ts->child_tidptr), +- FUTEX_WAKE, INT_MAX, NULL, NULL, 0); +- } + thread_cpu = NULL; + g_free(ts); + rcu_unregister_thread(); +-- +2.27.0 + diff --git a/qemu-iotests-Discard-stderr-when-probing-devices.patch b/qemu-iotests-Discard-stderr-when-probing-devices.patch new file mode 100644 index 00000000..a926687c --- /dev/null +++ b/qemu-iotests-Discard-stderr-when-probing-devices.patch @@ -0,0 +1,68 @@ +From ae868555000f3f9a37df2faf2551825381a86b45 Mon Sep 17 00:00:00 2001 +From: tangbinzy +Date: Mon, 25 Mar 2024 10:07:25 +0000 +Subject: [PATCH] qemu-iotests: Discard stderr when probing devices + mainline inclusion + commit e13fe274bfbc4c5b338854a3519a64b84c2d5517 + category: bugfix + +--------------------------------------------------------------- + +qemu-iotests fails in the following setup: + + ./configure --enable-modules --enable-smartcard \ + --target-list=x86_64-softmmu,s390x-softmmu + make + cd build + QEMU_PROG=`pwd`/s390x-softmmu/qemu-system-s390x \ + ../tests/check-block.sh qcow2 + ... + --- /home/crobinso/src/qemu/tests/qemu-iotests/127.out + +++ /home/crobinso/src/qemu/build/tests/qemu-iotests/scratch/127.out.bad + //@@ -1,4 +1,18 @@ + QA output created by 127 + +Failed to open module: /home/crobinso/src/qemu/build/hw-usb-smartcard.so: undefined symbol: ccid_card_ccid_attach + ... + --- /home/crobinso/src/qemu/tests/qemu-iotests/267.out + +++ /home/crobinso/src/qemu/build/tests/qemu-iotests/scratch/267.out.bad + //@@ -1,4 +1,11 @@ + QA output created by 267 + +Failed to open module: /home/crobinso/src/qemu/build/hw-usb-smartcard.so: undefined symbol: ccid_card_ccid_attach + +The stderr spew is its own known issue, but seems like iotests should +be discarding stderr in this case. + +Signed-off-by: Cole Robinson +Reviewed-by: Thomas Huth +Signed-off-by: Kevin Wolf + +Signed-off-by: tangbinzy +--- + tests/qemu-iotests/common.rc | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc +index d8582454de..4c468675d3 100644 +--- a/tests/qemu-iotests/common.rc ++++ b/tests/qemu-iotests/common.rc +@@ -973,7 +973,7 @@ _require_large_file() + # + _require_devices() + { +- available=$($QEMU -M none -device help | \ ++ available=$($QEMU -M none -device help 2> /dev/null | \ + grep ^name | sed -e 's/^name "//' -e 's/".*$//') + for device + do +@@ -985,7 +985,7 @@ _require_devices() + + _require_one_device_of() + { +- available=$($QEMU -M none -device help | \ ++ available=$($QEMU -M none -device help 2> /dev/null | \ + grep ^name | sed -e 's/^name "//' -e 's/".*$//') + for device + do +-- +2.27.0 + diff --git a/qemu.spec b/qemu.spec index 66569a64..ca2f21a6 100644 --- a/qemu.spec +++ b/qemu.spec @@ -3,7 +3,7 @@ Name: qemu Version: 6.2.0 -Release: 90 +Release: 91 Epoch: 10 Summary: QEMU is a generic and open source machine emulator and virtualizer License: GPLv2 and BSD and MIT and CC-BY-SA-4.0 @@ -907,6 +907,37 @@ Patch0892: i386-cpu-Clear-FEAT_XSAVE_XSS_LO-HI-leafs-when-CPUID.patch Patch0893: i386-cpu-Mask-with-XCR0-XSS-mask-for-FEAT_XSAVE_XCR0.patch Patch0894: i386-cpuid-Decrease-cpuid_i-when-skipping-CPUID-leaf.patch Patch0895: i386-cpuid-Move-leaf-7-to-correct-group.patch +Patch0896: scsi-disk-fix-overflow-when-block-size-is-not-a-mult.patch +Patch0897: contrib-vhost-user-blk-Clean-up-deallocation-of-VuVi.patch +Patch0898: hw-net-rocker-Avoid-undefined-shifts-with-more-than-.patch +Patch0899: linux-user-un-parent-OBJECT-cpu-when-closing-thread.patch +Patch0900: qemu-iotests-Discard-stderr-when-probing-devices.patch +Patch0901: hw-intc-clean-up-error-reporting-for-failed-ITS-cmd.patch +Patch0902: virtio-gpu-do-not-byteswap-padding.patch +Patch0903: configure-remove-dead-variables.patch +Patch0904: hw-ppc-mac.h-Remove-MAX_CPUS-macro.patch +Patch0905: ivshmem.c-change-endianness-to-LITTLE_ENDIAN.patch +Patch0906: ivshmem-test.c-enable-test_ivshmem_server-for-ppc64-.patch +Patch0907: libqos-virtio.c-Correct-flags-reading-in-qvirtqueue_.patch +Patch0908: virtio-crypto-fix-NULL-pointer-dereference-in-virtio.patch +Patch0909: amd_iommu-Fix-APIC-address-check.patch +Patch0910: block-mirror-Fix-NULL-s-job-in-active-writes.patch +Patch0911: smmu-Clear-SMMUPciBus-pointer-cache-when-system-rese.patch +Patch0912: block-Fix-crash-when-loading-snapshot-on-inactive-no.patch +Patch0913: system-memory-use-ldn_he_p-stn_he_p.patch +Patch0914: virtio-mem-Fix-the-iterator-variable-in-a-vmem-rdl_l.patch +Patch0915: virtio-mem-Fix-the-bitmap-index-of-the-section-offse.patch +Patch0916: tulip-Remove-unused-variable.patch +Patch0917: rtl8139-Remove-unused-variable.patch +Patch0918: hw-sd-sdhci-Do-not-update-TRNMOD-when-Command-Inhibi.patch +Patch0919: async-Add-an-optional-reentrancy-guard-to-the-BH-API.patch +Patch0920: async-avoid-use-after-free-on-re-entrancy-guard.patch +Patch0921: checkpatch-add-qemu_bh_new-aio_bh_new-checks.patch +Patch0922: hw-replace-most-qemu_bh_new-calls-with-qemu_bh_new_g.patch +Patch0923: hw-virtio-Introduce-virtio_bh_new_guarded-helper.patch +Patch0924: hw-display-virtio-gpu-Protect-from-DMA-re-entrancy-b.patch +Patch0925: hw-char-virtio-serial-bus-Protect-from-DMA-re-entran.patch +Patch0926: hw-virtio-virtio-crypto-Protect-from-DMA-re-entrancy.patch BuildRequires: flex BuildRequires: gcc @@ -1505,6 +1536,39 @@ getent passwd qemu >/dev/null || \ %endif %changelog +* Mon Apr 22 2024 - 10:6.2.0-91 +- hw/virtio/virtio-crypto: Protect from DMA re-entrancy bugs(CVE-2024-3446) +- hw/char/virtio-serial-bus: Protect from DMA re-entrancy bugs(CVE-2024-3446) +- hw/display/virtio-gpu: Protect from DMA re-entrancy bugs(CVE-2024-3446) +- hw/virtio: Introduce virtio_bh_new_guarded() helper +- hw: replace most qemu_bh_new calls with qemu_bh_new_guarded +- checkpatch: add qemu_bh_new/aio_bh_new checks +- async: avoid use-after-free on re-entrancy guard +- async: Add an optional reentrancy guard to the BH API +- hw/sd/sdhci: Do not update TRNMOD when Command Inhibit (DAT) is set(CVE-2024-3447) +- rtl8139: Remove unused variable +- tulip: Remove unused variable +- virtio-mem: Fix the bitmap index of the section offset +- virtio-mem: Fix the iterator variable in a vmem->rdl_list loop +- system/memory: use ldn_he_p/stn_he_p +- block: Fix crash when loading snapshot on inactive node +- smmu: Clear SMMUPciBus pointer cache when system reset +- block/mirror: Fix NULL s->job in active writes +- amd_iommu: Fix APIC address check +- virtio-crypto: fix NULL pointer dereference in virtio_crypto_free_reques +- libqos/virtio.c: Correct 'flags' reading in qvirtqueue_kick +- ivshmem-test.c: enable test_ivshmem_server for ppc64 arch +- ivshmem.c: change endianness to LITTLE_ENDIAN +- hw/ppc/mac.h: Remove MAX_CPUS macro +- configure: remove dead variables +- virtio-gpu: do not byteswap padding +- hw/intc: clean-up error reporting for failed ITS cmd +- qemu-iotests: Discard stderr when probing devices +- linux-user: un-parent OBJECT(cpu) when closing thread +- hw/net/rocker: Avoid undefined shifts with more than 31 ports +- contrib/vhost-user-blk: Clean up deallocation of VuVirtqElement +- scsi-disk: fix overflow when block size is not a multiple of BDRV_SECTOR_SIZE + * Sat Mar 23 2024 - 10:6.2.0-90 - i386/cpuid: Move leaf 7 to correct group - i386/cpuid: Decrease cpuid_i when skipping CPUID leaf 1F diff --git a/rtl8139-Remove-unused-variable.patch b/rtl8139-Remove-unused-variable.patch new file mode 100644 index 00000000..f3c89776 --- /dev/null +++ b/rtl8139-Remove-unused-variable.patch @@ -0,0 +1,44 @@ +From 9058e3d3fcb3fcb397d72caca54a4d6a8cacbd50 Mon Sep 17 00:00:00 2001 +From: zhujun2 +Date: Thu, 11 Apr 2024 00:58:48 -0700 +Subject: [PATCH] rtl8139: Remove unused variable + +Variable send_count used in rtl8139_cplus_transmit_one function is only +incremented but never read. This causes 'Unused but set variable' warning +on Clang 15.0.1 compiler. + +Removing the variable to prevent the warning. + +Signed-off-by: Miroslav Rezanina +Reviewed-by: Thomas Huth +Message-Id: <15a32dd06c492216cbf27cd3ddcbe1e9afb8d8f5.1668009030.git.mrezanin@redhat.com> +Signed-off-by: Thomas Huth +(cherry picked from commit 7d7238c72b983cff5064734349d2d45be9c6282c) +Signed-off-by: zhujun2 +--- + hw/net/rtl8139.c | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/hw/net/rtl8139.c b/hw/net/rtl8139.c +index 43d65d7252..8af396cf06 100644 +--- a/hw/net/rtl8139.c ++++ b/hw/net/rtl8139.c +@@ -2156,7 +2156,6 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s) + ip_data_len, saved_size - ETH_HLEN, large_send_mss); + + int tcp_send_offset = 0; +- int send_count = 0; + + /* maximum IP header length is 60 bytes */ + uint8_t saved_ip_header[60]; +@@ -2261,7 +2260,6 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s) + /* add transferred count to TCP sequence number */ + stl_be_p(&p_tcp_hdr->th_seq, + chunk_size + ldl_be_p(&p_tcp_hdr->th_seq)); +- ++send_count; + } + + /* Stop sending this frame */ +-- +2.27.0 + diff --git a/scsi-disk-fix-overflow-when-block-size-is-not-a-mult.patch b/scsi-disk-fix-overflow-when-block-size-is-not-a-mult.patch new file mode 100644 index 00000000..e4e4594e --- /dev/null +++ b/scsi-disk-fix-overflow-when-block-size-is-not-a-mult.patch @@ -0,0 +1,59 @@ +From 53b627a98b78ac06e7cba29c3614464469e7c11f Mon Sep 17 00:00:00 2001 +From: tangbinzy +Date: Mon, 25 Mar 2024 08:14:12 +0000 +Subject: [PATCH] scsi-disk: fix overflow when block size is not a multiple of BDRV_SECTOR_SIZE + mainline inclusion + commit 54a53a006ed9c1fe027fd89045d6de1e9128d7f4 + category: bugfix + +--------------------------------------------------------------- + +In scsi_disk_emulate_write_same() the number of host sectors to transfer is +calculated as (s->qdev.blocksize / BDRV_SECTOR_SIZE) which is then used to +copy data in block size chunks to the iov buffer. + +Since the loop copying the data to the iov buffer uses a fixed increment of +s->qdev.blocksize then using a block size that isn't a multiple of +BDRV_SECTOR_SIZE introduces a rounding error in the iov buffer size calculation +such that the iov buffer copy overflows the space allocated. + +Update the iov buffer copy for() loop so that it will use the smallest of either +the current block size or the remaining transfer count to prevent the overflow. + +Signed-off-by: Mark Cave-Ayland +Message-Id: <20220730122656.253448-2-mark.cave-ayland@ilande.co.uk> +Signed-off-by: Paolo Bonzini + +Signed-off-by: tangbinzy +--- + hw/scsi/scsi-disk.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c +index a66d2b0a98..edd2f895e7 100644 +--- a/hw/scsi/scsi-disk.c ++++ b/hw/scsi/scsi-disk.c +@@ -1800,7 +1800,7 @@ static void scsi_disk_emulate_write_same(SCSIDiskReq *r, uint8_t *inbuf) + uint32_t nb_sectors = scsi_data_cdb_xfer(r->req.cmd.buf); + WriteSameCBData *data; + uint8_t *buf; +- int i; ++ int i, l; + + /* Fail if PBDATA=1 or LBDATA=1 or ANCHOR=1. */ + if (nb_sectors == 0 || (req->cmd.buf[1] & 0x16)) { +@@ -1842,8 +1842,9 @@ static void scsi_disk_emulate_write_same(SCSIDiskReq *r, uint8_t *inbuf) + data->iov.iov_len); + qemu_iovec_init_external(&data->qiov, &data->iov, 1); + +- for (i = 0; i < data->iov.iov_len; i += s->qdev.blocksize) { +- memcpy(&buf[i], inbuf, s->qdev.blocksize); ++ for (i = 0; i < data->iov.iov_len; i += l) { ++ l = MIN(s->qdev.blocksize, data->iov.iov_len - i); ++ memcpy(&buf[i], inbuf, l); + } + + scsi_req_ref(&r->req); +-- +2.27.0 + diff --git a/smmu-Clear-SMMUPciBus-pointer-cache-when-system-rese.patch b/smmu-Clear-SMMUPciBus-pointer-cache-when-system-rese.patch new file mode 100644 index 00000000..d07ac4f9 --- /dev/null +++ b/smmu-Clear-SMMUPciBus-pointer-cache-when-system-rese.patch @@ -0,0 +1,41 @@ +From c7b0d41391267e278a3d7e9297041b29888a461e Mon Sep 17 00:00:00 2001 +From: zhujun2 +Date: Mon, 8 Apr 2024 00:12:40 -0700 +Subject: [PATCH] smmu: Clear SMMUPciBus pointer cache when system reset + +s->smmu_pcibus_by_bus_num is a SMMUPciBus pointer cache indexed +by bus number, bus number may not always be a fixed value, +i.e., guest reboot to different kernel which set bus number with +different algorithm. + +This could lead to smmu_iommu_mr() providing the wrong iommu MR. + +Suggested-by: Eric Auger +Signed-off-by: Zhenzhong Duan +Message-Id: <20240125073706.339369-3-zhenzhong.duan@intel.com> +Reviewed-by: Eric Auger +Tested-by: Eric Auger +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +(cherry picked from commit 8a6b3f4dc95a064e88adaca86374108da0ecb38d) +Signed-off-by: zhujun2 +--- + hw/arm/smmu-common.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/hw/arm/smmu-common.c b/hw/arm/smmu-common.c +index e09b9c13b7..d8fc81c102 100644 +--- a/hw/arm/smmu-common.c ++++ b/hw/arm/smmu-common.c +@@ -530,6 +530,8 @@ static void smmu_base_reset(DeviceState *dev) + { + SMMUState *s = ARM_SMMU(dev); + ++ memset(s->smmu_pcibus_by_bus_num, 0, sizeof(s->smmu_pcibus_by_bus_num)); ++ + g_hash_table_remove_all(s->configs); + g_hash_table_remove_all(s->iotlb); + } +-- +2.27.0 + diff --git a/system-memory-use-ldn_he_p-stn_he_p.patch b/system-memory-use-ldn_he_p-stn_he_p.patch new file mode 100644 index 00000000..dee36f98 --- /dev/null +++ b/system-memory-use-ldn_he_p-stn_he_p.patch @@ -0,0 +1,78 @@ +From 8a0a03a259eec5879a514363e3a80fea5039510f Mon Sep 17 00:00:00 2001 +From: zhujun2 +Date: Mon, 8 Apr 2024 01:09:55 -0700 +Subject: [PATCH] system/memory: use ldn_he_p/stn_he_p +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Using direct pointer dereferencing can allow for unaligned accesses, +which was seen during execution with sanitizers enabled. + +Cc: qemu-stable@nongnu.org +Reviewed-by: Chris Rauer +Reviewed-by: Peter Foley +Signed-off-by: Patrick Venture +Reviewed-by: Philippe Mathieu-Daudé o +Reviewed-by: David Hildenbrand +Message-ID: <20231116163633.276671-1-venture@google.com> +Signed-off-by: Philippe Mathieu-Daudé o +(cherry picked from commit 2b8fe81b3c2e76d241510a9a85496d544e42f5ec) +Signed-off-by: zhujun2 +--- + softmmu/memory.c | 32 ++------------------------------ + 1 file changed, 2 insertions(+), 30 deletions(-) + +diff --git a/softmmu/memory.c b/softmmu/memory.c +index 102f0a4248..0bf37f11aa 100644 +--- a/softmmu/memory.c ++++ b/softmmu/memory.c +@@ -1325,22 +1325,7 @@ static uint64_t memory_region_ram_device_read(void *opaque, + hwaddr addr, unsigned size) + { + MemoryRegion *mr = opaque; +- uint64_t data = (uint64_t)~0; +- +- switch (size) { +- case 1: +- data = *(uint8_t *)(mr->ram_block->host + addr); +- break; +- case 2: +- data = *(uint16_t *)(mr->ram_block->host + addr); +- break; +- case 4: +- data = *(uint32_t *)(mr->ram_block->host + addr); +- break; +- case 8: +- data = *(uint64_t *)(mr->ram_block->host + addr); +- break; +- } ++ uint64_t data = ldn_he_p(mr->ram_block->host + addr, size); + + trace_memory_region_ram_device_read(get_cpu_index(), mr, addr, data, size); + +@@ -1354,20 +1339,7 @@ static void memory_region_ram_device_write(void *opaque, hwaddr addr, + + trace_memory_region_ram_device_write(get_cpu_index(), mr, addr, data, size); + +- switch (size) { +- case 1: +- *(uint8_t *)(mr->ram_block->host + addr) = (uint8_t)data; +- break; +- case 2: +- *(uint16_t *)(mr->ram_block->host + addr) = (uint16_t)data; +- break; +- case 4: +- *(uint32_t *)(mr->ram_block->host + addr) = (uint32_t)data; +- break; +- case 8: +- *(uint64_t *)(mr->ram_block->host + addr) = data; +- break; +- } ++ stn_he_p(mr->ram_block->host + addr, size, data); + } + + static const MemoryRegionOps ram_device_mem_ops = { +-- +2.27.0 + diff --git a/tulip-Remove-unused-variable.patch b/tulip-Remove-unused-variable.patch new file mode 100644 index 00000000..b203113d --- /dev/null +++ b/tulip-Remove-unused-variable.patch @@ -0,0 +1,48 @@ +From 743ade13f9b675b4a5aa8631235d681fd66ee854 Mon Sep 17 00:00:00 2001 +From: zhujun2 +Date: Thu, 11 Apr 2024 00:53:25 -0700 +Subject: [PATCH] tulip: Remove unused variable + +Variable n used in tulip_idblock_crc function is only incremented but never read. +This causes 'Unused but set variable' warning on Clang 15.0.1 compiler. + +Removing the variable to prevent the warning. + +Signed-off-by: Miroslav Rezanina +Reviewed-by: Thomas Huth +Message-Id: <02e1560d115c208df32236df8916fed98429fda1.1668009030.git.mrezanin@redhat.com> +Signed-off-by: Thomas Huth +(cherry picked from commit 6083dcad80743718620a3f8a72fb76ea8b7c28ca) +Signed-off-by: zhujun2 +--- + hw/net/tulip.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/hw/net/tulip.c b/hw/net/tulip.c +index d319f9fb80..956093abd7 100644 +--- a/hw/net/tulip.c ++++ b/hw/net/tulip.c +@@ -870,11 +870,10 @@ static const MemoryRegionOps tulip_ops = { + + static void tulip_idblock_crc(TULIPState *s, uint16_t *srom) + { +- int word, n; ++ int word; + int bit; + unsigned char bitval, crc; + const int len = 9; +- n = 0; + crc = -1; + + for (word = 0; word < len; word++) { +@@ -887,7 +886,6 @@ static void tulip_idblock_crc(TULIPState *s, uint16_t *srom) + srom[len - 1] = (srom[len - 1] & 0xff00) | (unsigned short)crc; + break; + } +- n++; + bitval = ((srom[word] >> bit) & 1) ^ ((crc >> 7) & 1); + crc = crc << 1; + if (bitval == 1) { +-- +2.27.0 + diff --git a/virtio-crypto-fix-NULL-pointer-dereference-in-virtio.patch b/virtio-crypto-fix-NULL-pointer-dereference-in-virtio.patch new file mode 100644 index 00000000..c8cf82e7 --- /dev/null +++ b/virtio-crypto-fix-NULL-pointer-dereference-in-virtio.patch @@ -0,0 +1,56 @@ +From 7e0e009f5e5b39fc59aaa082cc092cb6438e5842 Mon Sep 17 00:00:00 2001 +From: zhujun2 +Date: Wed, 10 Apr 2024 23:03:47 -0700 +Subject: [PATCH] virtio-crypto: fix NULL pointer dereference in + virtio_crypto_free_reques + +Ensure op_info is not NULL in case of QCRYPTODEV_BACKEND_ALG_SYM algtype. + +Fixes: 0e660a6f90a ("crypto: Introduce RSA algorithm") +Signed-off-by: Mauro Matteo Cascella +Reported-by: Yiming Tao +Message-Id: <20230509075317.1132301-1-mcascell@redhat.com> +Reviewed-by: Gonglei +Reviewed-by: zhenwei pi +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +(cherry picked from commit 3e69908907f8d3dd20d5753b0777a6e3824ba824) +Signed-off-by: zhujun2 +--- + hw/virtio/virtio-crypto.c | 20 +++++++++++--------- + 1 file changed, 11 insertions(+), 9 deletions(-) + +diff --git a/hw/virtio/virtio-crypto.c b/hw/virtio/virtio-crypto.c +index 61b421aab3..8c2047f4e0 100644 +--- a/hw/virtio/virtio-crypto.c ++++ b/hw/virtio/virtio-crypto.c +@@ -349,15 +349,17 @@ static void virtio_crypto_free_request(VirtIOCryptoReq *req) + size_t max_len; + CryptoDevBackendSymOpInfo *op_info = req->u.sym_op_info; + +- max_len = op_info->iv_len + +- op_info->aad_len + +- op_info->src_len + +- op_info->dst_len + +- op_info->digest_result_len; +- +- /* Zeroize and free request data structure */ +- memset(op_info, 0, sizeof(*op_info) + max_len); +- g_free(op_info); ++ if (op_info) { ++ max_len = op_info->iv_len + ++ op_info->aad_len + ++ op_info->src_len + ++ op_info->dst_len + ++ op_info->digest_result_len; ++ ++ /* Zeroize and free request data structure */ ++ memset(op_info, 0, sizeof(*op_info) + max_len); ++ g_free(op_info); ++ } + } + g_free(req); + } +-- +2.27.0 + diff --git a/virtio-gpu-do-not-byteswap-padding.patch b/virtio-gpu-do-not-byteswap-padding.patch new file mode 100644 index 00000000..fe758c20 --- /dev/null +++ b/virtio-gpu-do-not-byteswap-padding.patch @@ -0,0 +1,41 @@ +From 365d14a81001ac41fd4aa2134b11a23d4a4a0656 Mon Sep 17 00:00:00 2001 +From: Luo Yifan +Date: Thu, 28 Mar 2024 10:38:37 +0800 +Subject: [PATCH] virtio-gpu: do not byteswap padding +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +cherry picked from commit a4663f1a5506626175fc64c86e52135587c36872 + +In Linux 5.16, the padding of struct virtio_gpu_ctrl_hdr has become a +single-byte field followed by a uint8_t[3] array of padding bytes, +and virtio_gpu_ctrl_hdr_bswap does not compile anymore. + +Signed-off-by: Paolo Bonzini +Acked-by: Cornelia Huck +Reviewed-by: Alex Bennée +Reviewed-by: Michael S. Tsirkin +Reviewed-by: Philippe Mathieu-Daudé +Message-Id: <20211111110604.207376-2-pbonzini@redhat.com> +Signed-off-by: Paolo Bonzini +Signed-off-by: Luo Yifan +--- + include/hw/virtio/virtio-gpu-bswap.h | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/include/hw/virtio/virtio-gpu-bswap.h b/include/hw/virtio/virtio-gpu-bswap.h +index e2bee8f595..5faac0d8d5 100644 +--- a/include/hw/virtio/virtio-gpu-bswap.h ++++ b/include/hw/virtio/virtio-gpu-bswap.h +@@ -24,7 +24,6 @@ virtio_gpu_ctrl_hdr_bswap(struct virtio_gpu_ctrl_hdr *hdr) + le32_to_cpus(&hdr->flags); + le64_to_cpus(&hdr->fence_id); + le32_to_cpus(&hdr->ctx_id); +- le32_to_cpus(&hdr->padding); + } + + static inline void +-- +2.27.0 + diff --git a/virtio-mem-Fix-the-bitmap-index-of-the-section-offse.patch b/virtio-mem-Fix-the-bitmap-index-of-the-section-offse.patch new file mode 100644 index 00000000..7cda05e2 --- /dev/null +++ b/virtio-mem-Fix-the-bitmap-index-of-the-section-offse.patch @@ -0,0 +1,47 @@ +From a1afd7b993903510f946a979ff31ccf21b34006c Mon Sep 17 00:00:00 2001 +From: zhujun2 +Date: Thu, 11 Apr 2024 00:39:56 -0700 +Subject: [PATCH] virtio-mem: Fix the bitmap index of the section offset + +vmem->bitmap indexes the memory region of the virtio-mem backend at a +granularity of block_size. To calculate the index of target section offset, +the block_size should be divided instead of the bitmap_size. + +Fixes: 2044969f0b ("virtio-mem: Implement RamDiscardManager interface") +Signed-off-by: Chenyi Qiang +Message-Id: <20221216062231.11181-1-chenyi.qiang@intel.com> +Reviewed-by: David Hildenbrand +Reviewed-by: Michael S. Tsirkin +Cc: qemu-stable@nongnu.org +Signed-off-by: David Hildenbrand +(cherry picked from commit b11cf32e07a2f7ff0d171b89497381a04c9d07e0) +Signed-off-by: zhujun2 +--- + hw/virtio/virtio-mem.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/hw/virtio/virtio-mem.c b/hw/virtio/virtio-mem.c +index becac0d93b..4dac2c051b 100644 +--- a/hw/virtio/virtio-mem.c ++++ b/hw/virtio/virtio-mem.c +@@ -205,7 +205,7 @@ static int virtio_mem_for_each_plugged_section(const VirtIOMEM *vmem, + uint64_t offset, size; + int ret = 0; + +- first_bit = s->offset_within_region / vmem->bitmap_size; ++ first_bit = s->offset_within_region / vmem->block_size; + first_bit = find_next_bit(vmem->bitmap, vmem->bitmap_size, first_bit); + while (first_bit < vmem->bitmap_size) { + MemoryRegionSection tmp = *s; +@@ -237,7 +237,7 @@ static int virtio_mem_for_each_unplugged_section(const VirtIOMEM *vmem, + uint64_t offset, size; + int ret = 0; + +- first_bit = s->offset_within_region / vmem->bitmap_size; ++ first_bit = s->offset_within_region / vmem->block_size; + first_bit = find_next_zero_bit(vmem->bitmap, vmem->bitmap_size, first_bit); + while (first_bit < vmem->bitmap_size) { + MemoryRegionSection tmp = *s; +-- +2.27.0 + diff --git a/virtio-mem-Fix-the-iterator-variable-in-a-vmem-rdl_l.patch b/virtio-mem-Fix-the-iterator-variable-in-a-vmem-rdl_l.patch new file mode 100644 index 00000000..c4bb1065 --- /dev/null +++ b/virtio-mem-Fix-the-iterator-variable-in-a-vmem-rdl_l.patch @@ -0,0 +1,39 @@ +From 9fb38321dbddc7e0e8c18c2cde47bc0261bd8058 Mon Sep 17 00:00:00 2001 +From: zhujun2 +Date: Thu, 11 Apr 2024 00:31:44 -0700 +Subject: [PATCH] virtio-mem: Fix the iterator variable in a vmem->rdl_list + loop +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +It should be the variable rdl2 to revert the already-notified listeners. + +Fixes: 2044969f0b ("virtio-mem: Implement RamDiscardManager interface") +Signed-off-by: Chenyi Qiang +Message-Id: <20221228090312.17276-1-chenyi.qiang@intel.com> +Cc: qemu-stable@nongnu.org +Reviewed-by: Philippe Mathieu-Daudé +Signed-off-by: David Hildenbrand +(cherry picked from commit 29f1b328e3b767cba2661920a8470738469b9e36) +Signed-off-by: zhujun2 +--- + hw/virtio/virtio-mem.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/hw/virtio/virtio-mem.c b/hw/virtio/virtio-mem.c +index becac0d93b..ddf7e2ec12 100644 +--- a/hw/virtio/virtio-mem.c ++++ b/hw/virtio/virtio-mem.c +@@ -311,7 +311,7 @@ static int virtio_mem_notify_plug(VirtIOMEM *vmem, uint64_t offset, + if (ret) { + /* Notify all already-notified listeners. */ + QLIST_FOREACH(rdl2, &vmem->rdl_list, next) { +- MemoryRegionSection tmp = *rdl->section; ++ MemoryRegionSection tmp = *rdl2->section; + + if (rdl2 == rdl) { + break; +-- +2.27.0 + -- Gitee From fd572f85f0a21782f489f61c1e5477b452a5b2cb Mon Sep 17 00:00:00 2001 From: Jiabo Feng Date: Thu, 13 Jun 2024 14:32:49 +0800 Subject: [PATCH 09/19] QEMU update to version 6.2.0-92: - s390x/sclp: Simplify get_sclp_device() - target/ppc: Remove msr_pr macro - docs/system/target-arm: Re-alphabetize board list - migration: Extend query-migrate to provide dirty page limit info - migration: Implement dirty-limit convergence algo - migration: Put the detection logic before auto-converge checking - migration: Refactor auto-converge capability logic - migration: Introduce dirty-limit capability - qapi/migration: Introduce vcpu-dirty-limit parameters - qapi/migration: Introduce x-vcpu-dirty-limit-period parameter - Change the value of no_ged from true to false - Allow UNIX socket option for VNC websocket - tpm_emulator: Avoid double initialization during - chardev/char-socket: Update AF_UNIX for Windows - KVM: dirty ring: add missing memory barrier - i386: reset KVM nested state upon CPU reset - esp: Handle CMD_BUSRESET by resetting the SCSI bus - dbus-vmstate: Restrict error checks to registered proxies in dbus_get_proxies - vfio/pci: Add Ascend310b scend910b support - target/i386: Export RFDS bit to guests - target/i386: Add new CPU model SierraForest - target/i386: Introduce Icelake-Server-v7 to enable TSX - hw/virtio: handle un-configured shutdown in virtio-pci - target/s390x: display deprecation status in '-cpu help' - target/i386: display deprecation status in '-cpu help' - pc-bios/s390-ccw: Fix booting with logical block size < physical block size Signed-off-by: Jiabo Feng (cherry picked from commit 90057151bbb0e2253cdd9ff86a81736e6efc5561) --- ...UNIX-socket-option-for-VNC-websocket.patch | 57 ++++ ...e-value-of-no_ged-from-true-to-false.patch | 29 ++ ...irty-ring-add-missing-memory-barrier.patch | 45 +++ ...ar-socket-Update-AF_UNIX-for-Windows.patch | 56 ++++ ...trict-error-checks-to-registered-pro.patch | 67 +++++ ...target-arm-Re-alphabetize-board-list.patch | 54 ++++ ...D_BUSRESET-by-resetting-the-SCSI-bus.patch | 53 ++++ ...-un-configured-shutdown-in-virtio-pc.patch | 51 ++++ ...eset-KVM-nested-state-upon-CPU-reset.patch | 90 ++++++ ...-query-migrate-to-provide-dirty-page.patch | 176 +++++++++++ ...plement-dirty-limit-convergence-algo.patch | 183 ++++++++++++ ...ion-Introduce-dirty-limit-capability.patch | 183 ++++++++++++ ...e-detection-logic-before-auto-conver.patch | 61 ++++ ...actor-auto-converge-capability-logic.patch | 45 +++ ...-Fix-booting-with-logical-block-size.patch | 60 ++++ ...ntroduce-vcpu-dirty-limit-parameters.patch | 200 +++++++++++++ ...ntroduce-x-vcpu-dirty-limit-period-p.patch | 273 ++++++++++++++++++ qemu.spec | 56 +++- s390x-sclp-Simplify-get_sclp_device.patch | 46 +++ ...-i386-Add-new-CPU-model-SierraForest.patch | 212 ++++++++++++++ target-i386-Export-RFDS-bit-to-guests.patch | 47 +++ ...oduce-Icelake-Server-v7-to-enable-TS.patch | 64 ++++ ...splay-deprecation-status-in-cpu-help.patch | 42 +++ target-ppc-Remove-msr_pr-macro.patch | 236 +++++++++++++++ ...splay-deprecation-status-in-cpu-help.patch | 67 +++++ ...id-double-initialization-during-migr.patch | 58 ++++ ...pci-Add-Ascend310b-scend910b-support.patch | 134 +++++++++ 27 files changed, 2644 insertions(+), 1 deletion(-) create mode 100644 Allow-UNIX-socket-option-for-VNC-websocket.patch create mode 100644 Change-the-value-of-no_ged-from-true-to-false.patch create mode 100644 KVM-dirty-ring-add-missing-memory-barrier.patch create mode 100644 chardev-char-socket-Update-AF_UNIX-for-Windows.patch create mode 100644 dbus-vmstate-Restrict-error-checks-to-registered-pro.patch create mode 100644 docs-system-target-arm-Re-alphabetize-board-list.patch create mode 100644 esp-Handle-CMD_BUSRESET-by-resetting-the-SCSI-bus.patch create mode 100644 hw-virtio-handle-un-configured-shutdown-in-virtio-pc.patch create mode 100644 i386-reset-KVM-nested-state-upon-CPU-reset.patch create mode 100644 migration-Extend-query-migrate-to-provide-dirty-page.patch create mode 100644 migration-Implement-dirty-limit-convergence-algo.patch create mode 100644 migration-Introduce-dirty-limit-capability.patch create mode 100644 migration-Put-the-detection-logic-before-auto-conver.patch create mode 100644 migration-Refactor-auto-converge-capability-logic.patch create mode 100644 pc-bios-s390-ccw-Fix-booting-with-logical-block-size.patch create mode 100644 qapi-migration-Introduce-vcpu-dirty-limit-parameters.patch create mode 100644 qapi-migration-Introduce-x-vcpu-dirty-limit-period-p.patch create mode 100644 s390x-sclp-Simplify-get_sclp_device.patch create mode 100644 target-i386-Add-new-CPU-model-SierraForest.patch create mode 100644 target-i386-Export-RFDS-bit-to-guests.patch create mode 100644 target-i386-Introduce-Icelake-Server-v7-to-enable-TS.patch create mode 100644 target-i386-display-deprecation-status-in-cpu-help.patch create mode 100644 target-ppc-Remove-msr_pr-macro.patch create mode 100644 target-s390x-display-deprecation-status-in-cpu-help.patch create mode 100644 tpm_emulator-Avoid-double-initialization-during-migr.patch create mode 100644 vfio-pci-Add-Ascend310b-scend910b-support.patch diff --git a/Allow-UNIX-socket-option-for-VNC-websocket.patch b/Allow-UNIX-socket-option-for-VNC-websocket.patch new file mode 100644 index 00000000..da5947b6 --- /dev/null +++ b/Allow-UNIX-socket-option-for-VNC-websocket.patch @@ -0,0 +1,57 @@ +From b149e82858eb16bcede32b86518a7a2f6f259b5b Mon Sep 17 00:00:00 2001 +From: dinglimin +Date: Thu, 23 May 2024 16:45:25 +0800 +Subject: [PATCH] Allow UNIX socket option for VNC websocket +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +cheery-pick from 41582637b1577c261f19634bdd1bb5e7ed6e258d + +- Remove unix socket option limitation for VNC websocket +- Reflect websocket option changes in documentation + +Signed-off-by: Sergii Zasenko +Reviewed-by: Marc-André Lureau +Message-Id: <20230724100353.16628-1-sergii@zasenko.name> + +Signed-off-by: dinglimin +--- + qemu-options.hx | 4 ++++ + ui/vnc.c | 5 ----- + 2 files changed, 4 insertions(+), 5 deletions(-) + +diff --git a/qemu-options.hx b/qemu-options.hx +index d940b4aea5..ab82ad4150 100644 +--- a/qemu-options.hx ++++ b/qemu-options.hx +@@ -2339,6 +2339,10 @@ SRST + host. It is possible to control the websocket listen address + independently, using the syntax ``websocket``\ =host:port. + ++ Websocket could be allowed over UNIX domain socket, using the syntax ++ ``websocket``\ =unix:path, where path is the location of a unix socket ++ to listen for connections on. ++ + If no TLS credentials are provided, the websocket connection + runs in unencrypted mode. If TLS credentials are provided, the + websocket connection requires encrypted client connections. +diff --git a/ui/vnc.c b/ui/vnc.c +index 71e3627be2..3cb24badf6 100644 +--- a/ui/vnc.c ++++ b/ui/vnc.c +@@ -3725,11 +3725,6 @@ static int vnc_display_get_address(const char *addrstr, + addr->type = SOCKET_ADDRESS_TYPE_UNIX; + addr->u.q_unix.path = g_strdup(addrstr + 5); + +- if (websocket) { +- error_setg(errp, "UNIX sockets not supported with websock"); +- goto cleanup; +- } +- + if (to) { + error_setg(errp, "Port range not support with UNIX socket"); + goto cleanup; +-- +2.27.0 + diff --git a/Change-the-value-of-no_ged-from-true-to-false.patch b/Change-the-value-of-no_ged-from-true-to-false.patch new file mode 100644 index 00000000..ea634a6b --- /dev/null +++ b/Change-the-value-of-no_ged-from-true-to-false.patch @@ -0,0 +1,29 @@ +From 96e753e741a21d8bc1f59120dd70ce140129b737 Mon Sep 17 00:00:00 2001 +From: weishaokun +Date: Fri, 31 May 2024 13:48:59 +0800 +Subject: [PATCH] Change the value of no_ged from true to false + +It fixes the issue of the `no_ged` parameter mismatch +when migrating a virtual machine started with QEMU 4.1 to a QEMU 6.2 + +Signed-off-by: Shaokun Wei +--- + hw/arm/virt.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/hw/arm/virt.c b/hw/arm/virt.c +index 93554cccf1..eadba9535e 100644 +--- a/hw/arm/virt.c ++++ b/hw/arm/virt.c +@@ -3290,7 +3290,7 @@ static void virt_machine_4_1_options(MachineClass *mc) + + virt_machine_4_2_options(mc); + compat_props_add(mc->compat_props, hw_compat_4_1, hw_compat_4_1_len); +- vmc->no_ged = true; ++ vmc->no_ged = false; + mc->auto_enable_numa_with_memhp = false; + } + DEFINE_VIRT_MACHINE(4, 1) +-- +2.27.0 + diff --git a/KVM-dirty-ring-add-missing-memory-barrier.patch b/KVM-dirty-ring-add-missing-memory-barrier.patch new file mode 100644 index 00000000..27e6c879 --- /dev/null +++ b/KVM-dirty-ring-add-missing-memory-barrier.patch @@ -0,0 +1,45 @@ +From 63d3efed81ddf36acfec73910a84dee426450012 Mon Sep 17 00:00:00 2001 +From: tangbinzy +Date: Wed, 15 May 2024 01:03:38 +0000 +Subject: [PATCH] KVM: dirty ring: add missing memory barrier mainline + inclusion commit 4802bf910eee98312c4a9777ac2567e6a0445c46 category: bugfix +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +--------------------------------------------------------------- + +The KVM_DIRTY_GFN_F_DIRTY flag ensures that the entry is valid. If +the read of the fields are not ordered after the read of the flag, +QEMU might see stale values. + +Cc: Gavin Shan +Reviewed-by: Philippe Mathieu-Daudé +Reviewed-by: Peter Xu +Signed-off-by: Paolo Bonzini + +Signed-off-by: tangbinzy +--- + accel/kvm/kvm-all.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c +index c477f7a635..e55b2b6a16 100644 +--- a/accel/kvm/kvm-all.c ++++ b/accel/kvm/kvm-all.c +@@ -661,7 +661,11 @@ static void kvm_dirty_ring_mark_page(KVMState *s, uint32_t as_id, + + static bool dirty_gfn_is_dirtied(struct kvm_dirty_gfn *gfn) + { +- return gfn->flags == KVM_DIRTY_GFN_F_DIRTY; ++ /* ++ * Read the flags before the value. Pairs with barrier in ++ * KVM's kvm_dirty_ring_push() function. ++ */ ++ return qatomic_load_acquire(&gfn->flags) == KVM_DIRTY_GFN_F_DIRTY; + } + + static void dirty_gfn_set_collected(struct kvm_dirty_gfn *gfn) +-- +2.27.0 + diff --git a/chardev-char-socket-Update-AF_UNIX-for-Windows.patch b/chardev-char-socket-Update-AF_UNIX-for-Windows.patch new file mode 100644 index 00000000..a16b4940 --- /dev/null +++ b/chardev-char-socket-Update-AF_UNIX-for-Windows.patch @@ -0,0 +1,56 @@ +From 83a0636d6eb42c223ca4d6c0d26ca3a2075de532 Mon Sep 17 00:00:00 2001 +From: tangbinzy +Date: Wed, 15 May 2024 01:21:57 +0000 +Subject: [PATCH] chardev/char-socket: Update AF_UNIX for Windows mainline + inclusion commit 120fa5e0e6ebacd811e4d830cff8a405806d305c category: bugfix +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +--------------------------------------------------------------- + +Now that AF_UNIX has come to Windows, update the existing logic in +qemu_chr_compute_filename() and qmp_chardev_open_socket() for Windows. + +Signed-off-by: Bin Meng +Reviewed-by: Marc-André Lureau +Message-Id: <20220802075200.907360-4-bmeng.cn@gmail.com> + +Signed-off-by: tangbinzy +--- + chardev/char-socket.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/chardev/char-socket.c b/chardev/char-socket.c +index ef5d3053f3..278190dd93 100644 +--- a/chardev/char-socket.c ++++ b/chardev/char-socket.c +@@ -632,12 +632,10 @@ static char *qemu_chr_compute_filename(SocketChardev *s) + const char *left = "", *right = ""; + + switch (ss->ss_family) { +-#ifndef _WIN32 + case AF_UNIX: + return g_strdup_printf("unix:%s%s", + ((struct sockaddr_un *)(ss))->sun_path, + s->is_listen ? ",server=on" : ""); +-#endif + case AF_INET6: + left = "["; + right = "]"; +@@ -1450,10 +1448,12 @@ static void qmp_chardev_open_socket(Chardev *chr, + } + + qemu_chr_set_feature(chr, QEMU_CHAR_FEATURE_RECONNECTABLE); ++#ifndef _WIN32 + /* TODO SOCKET_ADDRESS_FD where fd has AF_UNIX */ + if (addr->type == SOCKET_ADDRESS_TYPE_UNIX) { + qemu_chr_set_feature(chr, QEMU_CHAR_FEATURE_FD_PASS); + } ++#endif + + /* + * In the chardev-change special-case, we shouldn't register a new yank +-- +2.27.0 + diff --git a/dbus-vmstate-Restrict-error-checks-to-registered-pro.patch b/dbus-vmstate-Restrict-error-checks-to-registered-pro.patch new file mode 100644 index 00000000..f6d29b94 --- /dev/null +++ b/dbus-vmstate-Restrict-error-checks-to-registered-pro.patch @@ -0,0 +1,67 @@ +From a5a46593ade242686a670756530026914ed51eaf Mon Sep 17 00:00:00 2001 +From: tangbinzy +Date: Tue, 14 May 2024 09:27:10 +0000 +Subject: [PATCH] dbus-vmstate: Restrict error checks to registered proxies in + dbus_get_proxies mainline inclusion commit + 2748583211d6e4d14f8862c65276b2d6cc1681ad category: bugfix +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +--------------------------------------------------------------- + +The purpose of dbus_get_proxies to construct the proxies corresponding to the +IDs registered to dbus-vmstate. + +Currenty, this function returns an error in case there is any failure +while instantiating proxy for "all" the names on dbus. + +Ideally this function should error out only if it is not able to find and +validate the proxies registered to the backend otherwise any offending +process(for eg: the process purposefully may not export its Id property on +the dbus) may connect to the dbus and can lead to migration failures. + +This commit ensures that dbus_get_proxies returns an error if it is not +able to find and validate the proxies of interest(the IDs registered +during the dbus-vmstate instantiation). + +Signed-off-by: Priyankar Jain +Reviewed-by: Marc-André Lureau +Message-Id: <1637936117-37977-1-git-send-email-priyankar.jain@nutanix.com> + +Signed-off-by: tangbinzy +--- + backends/dbus-vmstate.c | 13 +++++++++---- + 1 file changed, 9 insertions(+), 4 deletions(-) + +diff --git a/backends/dbus-vmstate.c b/backends/dbus-vmstate.c +index 9cfd758c42..57369ec0f2 100644 +--- a/backends/dbus-vmstate.c ++++ b/backends/dbus-vmstate.c +@@ -114,14 +114,19 @@ dbus_get_proxies(DBusVMState *self, GError **err) + "org.qemu.VMState1", + NULL, err); + if (!proxy) { +- return NULL; ++ if (err != NULL && *err != NULL) { ++ warn_report("%s: Failed to create proxy: %s", ++ __func__, (*err)->message); ++ g_clear_error(err); ++ } ++ continue; + } + + result = g_dbus_proxy_get_cached_property(proxy, "Id"); + if (!result) { +- g_set_error_literal(err, G_IO_ERROR, G_IO_ERROR_FAILED, +- "VMState Id property is missing."); +- return NULL; ++ warn_report("%s: VMState Id property is missing.", __func__); ++ g_clear_object(&proxy); ++ continue; + } + + id = g_variant_dup_string(result, &size); +-- +2.27.0 + diff --git a/docs-system-target-arm-Re-alphabetize-board-list.patch b/docs-system-target-arm-Re-alphabetize-board-list.patch new file mode 100644 index 00000000..757fcc67 --- /dev/null +++ b/docs-system-target-arm-Re-alphabetize-board-list.patch @@ -0,0 +1,54 @@ +From 5f9795e17706aa4bcac46724330761c74cc767c4 Mon Sep 17 00:00:00 2001 +From: tangzhongrui +Date: Mon, 3 Jun 2024 20:58:36 +0800 +Subject: [PATCH] docs/system/target-arm: Re-alphabetize board list +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The board list in target-arm.rst is supposed to be in alphabetical +order by the title text of each file (which is not the same as +alphabetical order by filename). A few items had got out of order; +correct them. + +The entry for +"Facebook Yosemite v3.5 Platform and CraterLake Server (fby35)" +remains out-of-order, because this is not its own file +but is currently part of the aspeed.rst file. + +Signed-off-by: Peter Maydell +Reviewed-by: Richard Henderson +Reviewed-by: Philippe Mathieu-Daudé +Message-id: 20240520141421.1895138-1-peter.maydell@linaro.org + +Signed-off-by: Zhongrui Tang +--- + docs/system/target-arm.rst | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/docs/system/target-arm.rst b/docs/system/target-arm.rst +index 91ebc26c6d..d3d2c28417 100644 +--- a/docs/system/target-arm.rst ++++ b/docs/system/target-arm.rst +@@ -84,16 +84,16 @@ undocumented; you can get a complete list by running + arm/vexpress + arm/aspeed + arm/sabrelite ++ arm/highbank + arm/digic + arm/cubieboard + arm/emcraft-sf2 +- arm/highbank + arm/musicpal + arm/gumstix + arm/mainstone + arm/kzm +- arm/nrf + arm/nseries ++ arm/nrf + arm/nuvoton + arm/imx25-pdk + arm/orangepi +-- +2.27.0 + diff --git a/esp-Handle-CMD_BUSRESET-by-resetting-the-SCSI-bus.patch b/esp-Handle-CMD_BUSRESET-by-resetting-the-SCSI-bus.patch new file mode 100644 index 00000000..5172defb --- /dev/null +++ b/esp-Handle-CMD_BUSRESET-by-resetting-the-SCSI-bus.patch @@ -0,0 +1,53 @@ +From 3f186cb242429e6d19f95e259e226658f0d605a9 Mon Sep 17 00:00:00 2001 +From: tangbinzy +Date: Tue, 14 May 2024 09:53:37 +0000 +Subject: [PATCH] esp: Handle CMD_BUSRESET by resetting the SCSI bus mainline + inclusion commit c6e51f1bb28ed762d2039c063cbb71a8ad29762d category: bugfix + +--------------------------------------------------------------- + +Per investigation on the linked ticket, SunOS issues a SCSI bus reset +to the ESP as part of its boot sequence. If this ESP command doesn't +cause devices to assert sense flag UNIT ATTENTION, SunOS will consider +the CD-ROM device to be non-compliant with Common Command Set (CCS). +In this condition, the SunOS installer's early userspace doesn't set +the installation source location to sr0 and the miniroot copy fails. + +Signed-off-by: John Millikin +Suggested-by: Bill Paul +Buglink: https://gitlab.com/qemu-project/qemu/-/issues/1127 +Message-Id: <20220817053846.699310-1-john@john-millikin.com> +Signed-off-by: Paolo Bonzini + +Signed-off-by: tangbinzy +--- + hw/scsi/esp.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/hw/scsi/esp.c b/hw/scsi/esp.c +index 435a81bbfd..9f071e7218 100644 +--- a/hw/scsi/esp.c ++++ b/hw/scsi/esp.c +@@ -912,6 +912,11 @@ static void esp_soft_reset(ESPState *s) + esp_hard_reset(s); + } + ++static void esp_bus_reset(ESPState *s) ++{ ++ qbus_reset_all(BUS(&s->bus)); ++} ++ + static void parent_esp_reset(ESPState *s, int irq, int level) + { + if (level) { +@@ -1040,6 +1045,7 @@ void esp_reg_write(ESPState *s, uint32_t saddr, uint64_t val) + break; + case CMD_BUSRESET: + trace_esp_mem_writeb_cmd_bus_reset(val); ++ esp_bus_reset(s); + if (!(s->wregs[ESP_CFG1] & CFG1_RESREPT)) { + s->rregs[ESP_RINTR] |= INTR_RST; + esp_raise_irq(s); +-- +2.27.0 + diff --git a/hw-virtio-handle-un-configured-shutdown-in-virtio-pc.patch b/hw-virtio-handle-un-configured-shutdown-in-virtio-pc.patch new file mode 100644 index 00000000..ac5e28bf --- /dev/null +++ b/hw-virtio-handle-un-configured-shutdown-in-virtio-pc.patch @@ -0,0 +1,51 @@ +From 8e15820dcf4f343ad21e01d8a6c9516b79ee4e7c Mon Sep 17 00:00:00 2001 +From: tangbinzy +Date: Tue, 30 Apr 2024 09:42:08 +0000 +Subject: [PATCH] hw/virtio: handle un-configured shutdown in virtio-pci + mainline inclusion commit 5a9d5f09b1f61bc7072c2389ba5b11350ae76b0d category: + bugfix +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +--------------------------------------------------------------- + +The assert() protecting against leakage is a little aggressive and +causes needless crashes if a device is shutdown without having been +configured. In this case no descriptors are lost because none have +been assigned. + +Signed-off-by: Alex Bennée +Message-Id: <20220728135503.1060062-4-alex.bennee@linaro.org> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin + +Signed-off-by: tangbinzy +--- + hw/virtio/virtio-pci.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c +index 6b45683280..389a8db0ec 100644 +--- a/hw/virtio/virtio-pci.c ++++ b/hw/virtio/virtio-pci.c +@@ -1213,9 +1213,14 @@ static int virtio_pci_set_guest_notifiers(DeviceState *d, int nvqs, bool assign) + + nvqs = MIN(nvqs, VIRTIO_QUEUE_MAX); + +- /* When deassigning, pass a consistent nvqs value +- * to avoid leaking notifiers. ++ /* ++ * When deassigning, pass a consistent nvqs value to avoid leaking ++ * notifiers. But first check we've actually been configured, exit ++ * early if we haven't. + */ ++ if (!assign && !proxy->nvqs_with_notifiers) { ++ return 0; ++ } + assert(assign || nvqs == proxy->nvqs_with_notifiers); + + proxy->nvqs_with_notifiers = nvqs; +-- +2.27.0 + diff --git a/i386-reset-KVM-nested-state-upon-CPU-reset.patch b/i386-reset-KVM-nested-state-upon-CPU-reset.patch new file mode 100644 index 00000000..0705a2ce --- /dev/null +++ b/i386-reset-KVM-nested-state-upon-CPU-reset.patch @@ -0,0 +1,90 @@ +From 6257f125bc58952f49cbbc28210099a6333152a8 Mon Sep 17 00:00:00 2001 +From: tangbinzy +Date: Tue, 14 May 2024 10:05:16 +0000 +Subject: [PATCH] i386: reset KVM nested state upon CPU reset mainline + inclusion commit 3cafdb67504a34a0305260f0c86a73d5a3fb000b category: bugfix + +--------------------------------------------------------------- + +Make sure env->nested_state is cleaned up when a vCPU is reset, it may +be stale after an incoming migration, kvm_arch_put_registers() may +end up failing or putting vCPU in a weird state. + +Reviewed-by: Maxim Levitsky +Signed-off-by: Vitaly Kuznetsov +Message-Id: <20220818150113.479917-2-vkuznets@redhat.com> +Signed-off-by: Paolo Bonzini + +Signed-off-by: tangbinzy +--- + target/i386/kvm/kvm.c | 37 +++++++++++++++++++++++++++---------- + 1 file changed, 27 insertions(+), 10 deletions(-) + +diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c +index 99be7f6155..9f3ddd5da2 100644 +--- a/target/i386/kvm/kvm.c ++++ b/target/i386/kvm/kvm.c +@@ -1623,6 +1623,30 @@ static void kvm_init_xsave(CPUX86State *env) + env->xsave_buf_len); + } + ++static void kvm_init_nested_state(CPUX86State *env) ++{ ++ struct kvm_vmx_nested_state_hdr *vmx_hdr; ++ uint32_t size; ++ ++ if (!env->nested_state) { ++ return; ++ } ++ ++ size = env->nested_state->size; ++ ++ memset(env->nested_state, 0, size); ++ env->nested_state->size = size; ++ ++ if (cpu_has_vmx(env)) { ++ env->nested_state->format = KVM_STATE_NESTED_FORMAT_VMX; ++ vmx_hdr = &env->nested_state->hdr.vmx; ++ vmx_hdr->vmxon_pa = -1ull; ++ vmx_hdr->vmcs12_pa = -1ull; ++ } else if (cpu_has_svm(env)) { ++ env->nested_state->format = KVM_STATE_NESTED_FORMAT_SVM; ++ } ++} ++ + int kvm_arch_init_vcpu(CPUState *cs) + { + struct { +@@ -2051,19 +2075,10 @@ int kvm_arch_init_vcpu(CPUState *cs) + assert(max_nested_state_len >= offsetof(struct kvm_nested_state, data)); + + if (cpu_has_vmx(env) || cpu_has_svm(env)) { +- struct kvm_vmx_nested_state_hdr *vmx_hdr; +- + env->nested_state = g_malloc0(max_nested_state_len); + env->nested_state->size = max_nested_state_len; + +- if (cpu_has_vmx(env)) { +- env->nested_state->format = KVM_STATE_NESTED_FORMAT_VMX; +- vmx_hdr = &env->nested_state->hdr.vmx; +- vmx_hdr->vmxon_pa = -1ull; +- vmx_hdr->vmcs12_pa = -1ull; +- } else { +- env->nested_state->format = KVM_STATE_NESTED_FORMAT_SVM; +- } ++ kvm_init_nested_state(env); + } + } + +@@ -2126,6 +2141,8 @@ void kvm_arch_reset_vcpu(X86CPU *cpu) + /* enabled by default */ + env->poll_control_msr = 1; + ++ kvm_init_nested_state(env); ++ + sev_es_set_reset_vector(CPU(cpu)); + } + +-- +2.27.0 + diff --git a/migration-Extend-query-migrate-to-provide-dirty-page.patch b/migration-Extend-query-migrate-to-provide-dirty-page.patch new file mode 100644 index 00000000..4c72a4fa --- /dev/null +++ b/migration-Extend-query-migrate-to-provide-dirty-page.patch @@ -0,0 +1,176 @@ +From ba8973a75fffa55977dfa12a850827e11081280f Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Hyman=20Huang=28=E9=BB=84=E5=8B=87=29?= + +Date: Thu, 8 Jun 2023 00:21:58 +0800 +Subject: [PATCH] migration: Extend query-migrate to provide dirty page limit + info +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +There is a conflict when merging patches in qemu-6.2.0, and there is a phenomenon that the corresponding files and functions cannot be found.Merge after modifying the patch by wangguochun@kylinos.cn + +Extend query-migrate to provide throttle time and estimated +ring full time with dirty-limit capability enabled, through which +we can observe if dirty limit take effect during live migration. + +Signed-off-by: Hyman Huang(黄勇) +Reviewed-by: Markus Armbruster +Reviewed-by: Juan Quintela +Message-ID: <168733225273.5845.15871826788879741674-8@git.sr.ht> +Signed-off-by: Juan Quintela +--- + include/sysemu/dirtylimit.h | 2 ++ + migration/migration.c | 10 ++++++++++ + monitor/hmp-cmds.c | 10 ++++++++++ + qapi/migration.json | 16 ++++++++++++++- + softmmu/dirtylimit.c | 39 +++++++++++++++++++++++++++++++++++++ + 5 files changed, 76 insertions(+), 1 deletion(-) + +diff --git a/include/sysemu/dirtylimit.h b/include/sysemu/dirtylimit.h +index 8d2c1f3a6b..d11ebbbbdb 100644 +--- a/include/sysemu/dirtylimit.h ++++ b/include/sysemu/dirtylimit.h +@@ -34,4 +34,6 @@ void dirtylimit_set_vcpu(int cpu_index, + void dirtylimit_set_all(uint64_t quota, + bool enable); + void dirtylimit_vcpu_execute(CPUState *cpu); ++uint64_t dirtylimit_throttle_time_per_round(void); ++uint64_t dirtylimit_ring_full_time(void); + #endif +diff --git a/migration/migration.c b/migration/migration.c +index e6a2e48f7a..3da2ed37f3 100644 +--- a/migration/migration.c ++++ b/migration/migration.c +@@ -61,6 +61,7 @@ + #include "sysemu/cpus.h" + #include "yank_functions.h" + #include "sysemu/kvm.h" ++#include "sysemu/dirtylimit.h" + + #define MAX_THROTTLE (128 << 20) /* Migration transfer speed throttling */ + +@@ -1060,6 +1061,15 @@ static void populate_ram_info(MigrationInfo *info, MigrationState *s) + info->ram->remaining = ram_bytes_remaining(); + info->ram->dirty_pages_rate = ram_counters.dirty_pages_rate; + } ++ ++ if (migrate_dirty_limit() && dirtylimit_in_service()) { ++ info->has_dirty_limit_throttle_time_per_round = true; ++ info->dirty_limit_throttle_time_per_round = ++ dirtylimit_throttle_time_per_round(); ++ ++ info->has_dirty_limit_ring_full_time = true; ++ info->dirty_limit_ring_full_time = dirtylimit_ring_full_time(); ++ } + } + + static void populate_disk_info(MigrationInfo *info) +diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c +index 01493cd2c0..c139e8087e 100644 +--- a/monitor/hmp-cmds.c ++++ b/monitor/hmp-cmds.c +@@ -339,6 +339,16 @@ void hmp_info_migrate(Monitor *mon, const QDict *qdict) + info->cpu_throttle_percentage); + } + ++ if (info->has_dirty_limit_throttle_time_per_round) { ++ monitor_printf(mon, "dirty-limit throttle time: %" PRIu64 " us\n", ++ info->dirty_limit_throttle_time_per_round); ++ } ++ ++ if (info->has_dirty_limit_ring_full_time) { ++ monitor_printf(mon, "dirty-limit ring full time: %" PRIu64 " us\n", ++ info->dirty_limit_ring_full_time); ++ } ++ + if (info->has_postcopy_blocktime) { + monitor_printf(mon, "postcopy blocktime: %u\n", + info->postcopy_blocktime); +diff --git a/qapi/migration.json b/qapi/migration.json +index 4751c5ee53..a36a4e943b 100644 +--- a/qapi/migration.json ++++ b/qapi/migration.json +@@ -228,6 +228,18 @@ + # Present and non-empty when migration is blocked. + # (since 6.0) + # ++# @dirty-limit-throttle-time-per-round: Maximum throttle time (in microseconds) of virtual ++# CPUs each dirty ring full round, which shows how ++# MigrationCapability dirty-limit affects the guest ++# during live migration. (since 8.1) ++# ++# @dirty-limit-ring-full-time: Estimated average dirty ring full time (in microseconds) ++# each dirty ring full round, note that the value equals ++# dirty ring memory size divided by average dirty page rate ++# of virtual CPU, which can be used to observe the average ++# memory load of virtual CPU indirectly. Note that zero ++# means guest doesn't dirty memory (since 8.1) ++# + # Since: 0.14 + ## + { 'struct': 'MigrationInfo', +@@ -245,7 +257,9 @@ + '*postcopy-blocktime' : 'uint32', + '*postcopy-vcpu-blocktime': ['uint32'], + '*compression': 'CompressionStats', +- '*socket-address': ['SocketAddress'] } } ++ '*socket-address': ['SocketAddress'], ++ '*dirty-limit-throttle-time-per-round': 'uint64', ++ '*dirty-limit-ring-full-time': 'uint64'} } + + ## + # @query-migrate: +diff --git a/softmmu/dirtylimit.c b/softmmu/dirtylimit.c +index a3337c0e20..5e6e5aba67 100644 +--- a/softmmu/dirtylimit.c ++++ b/softmmu/dirtylimit.c +@@ -564,6 +564,45 @@ out: + hmp_handle_error(mon, err); + } + ++/* Return the max throttle time of each virtual CPU */ ++uint64_t dirtylimit_throttle_time_per_round(void) ++{ ++ CPUState *cpu; ++ int64_t max = 0; ++ ++ CPU_FOREACH(cpu) { ++ if (cpu->throttle_us_per_full > max) { ++ max = cpu->throttle_us_per_full; ++ } ++ } ++ ++ return max; ++} ++ ++/* ++ * Estimate average dirty ring full time of each virtaul CPU. ++ * Return 0 if guest doesn't dirty memory. ++ */ ++uint64_t dirtylimit_ring_full_time(void) ++{ ++ CPUState *cpu; ++ uint64_t curr_rate = 0; ++ int nvcpus = 0; ++ ++ CPU_FOREACH(cpu) { ++ if (cpu->running) { ++ nvcpus++; ++ curr_rate += vcpu_dirty_rate_get(cpu->cpu_index); ++ } ++ } ++ ++ if (!curr_rate || !nvcpus) { ++ return 0; ++ } ++ ++ return dirtylimit_dirty_ring_full_time(curr_rate / nvcpus); ++} ++ + static struct DirtyLimitInfo *dirtylimit_query_vcpu(int cpu_index) + { + DirtyLimitInfo *info = NULL; +-- +2.27.0 + diff --git a/migration-Implement-dirty-limit-convergence-algo.patch b/migration-Implement-dirty-limit-convergence-algo.patch new file mode 100644 index 00000000..febfe486 --- /dev/null +++ b/migration-Implement-dirty-limit-convergence-algo.patch @@ -0,0 +1,183 @@ +From 39cdcd0405657abfd81563d1f3801252e0ea8707 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Hyman=20Huang=28=E9=BB=84=E5=8B=87=29?= + +Date: Thu, 8 Jun 2023 00:12:40 +0800 +Subject: [PATCH] migration: Implement dirty-limit convergence algo +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Implement dirty-limit convergence algo for live migration, +which is kind of like auto-converge algo but using dirty-limit +instead of cpu throttle to make migration convergent. + +Enable dirty page limit if dirty_rate_high_cnt greater than 2 +when dirty-limit capability enabled, Disable dirty-limit if +migration be canceled. + +Note that "set_vcpu_dirty_limit", "cancel_vcpu_dirty_limit" +commands are not allowed during dirty-limit live migration. + +Signed-off-by: Hyman Huang(黄勇) +Reviewed-by: Markus Armbruster +Message-ID: <168733225273.5845.15871826788879741674-7@git.sr.ht> +Reviewed-by: Juan Quintela +Signed-off-by: Juan Quintela +--- + migration/migration.c | 3 +++ + migration/ram.c | 36 ++++++++++++++++++++++++++++++++++++ + migration/trace-events | 1 + + softmmu/dirtylimit.c | 29 +++++++++++++++++++++++++++++ + 4 files changed, 69 insertions(+) + +diff --git a/migration/migration.c b/migration/migration.c +index 50c33fecf3..e6a2e48f7a 100644 +--- a/migration/migration.c ++++ b/migration/migration.c +@@ -224,6 +224,9 @@ void migration_cancel(const Error *error) + if (error) { + migrate_set_error(current_migration, error); + } ++ if (migrate_dirty_limit()) { ++ qmp_cancel_vcpu_dirty_limit(false, -1, NULL); ++ } + migrate_fd_cancel(current_migration); + } + +diff --git a/migration/ram.c b/migration/ram.c +index 20f228e6bb..998ee96e63 100644 +--- a/migration/ram.c ++++ b/migration/ram.c +@@ -43,6 +43,7 @@ + #include "qapi/error.h" + #include "qapi/qapi-types-migration.h" + #include "qapi/qapi-events-migration.h" ++#include "qapi/qapi-commands-migration.h" + #include "qapi/qmp/qerror.h" + #include "trace.h" + #include "exec/ram_addr.h" +@@ -55,6 +56,8 @@ + #include "qemu/iov.h" + #include "multifd.h" + #include "sysemu/runstate.h" ++#include "sysemu/dirtylimit.h" ++#include "sysemu/kvm.h" + + #include "hw/boards.h" /* for machine_dump_guest_core() */ + +@@ -1399,6 +1402,37 @@ static void migration_update_rates(RAMState *rs, int64_t end_time) + } + } + ++/* ++ * Enable dirty-limit to throttle down the guest ++ */ ++static void migration_dirty_limit_guest(void) ++{ ++ /* ++ * dirty page rate quota for all vCPUs fetched from ++ * migration parameter 'vcpu_dirty_limit' ++ */ ++ static int64_t quota_dirtyrate; ++ MigrationState *s = migrate_get_current(); ++ ++ /* ++ * If dirty limit already enabled and migration parameter ++ * vcpu-dirty-limit untouched. ++ */ ++ if (dirtylimit_in_service() && ++ quota_dirtyrate == s->parameters.vcpu_dirty_limit) { ++ return; ++ } ++ ++ quota_dirtyrate = s->parameters.vcpu_dirty_limit; ++ ++ /* ++ * Set all vCPU a quota dirtyrate, note that the second ++ * parameter will be ignored if setting all vCPU for the vm ++ */ ++ qmp_set_vcpu_dirty_limit(false, -1, quota_dirtyrate, NULL); ++ trace_migration_dirty_limit_guest(quota_dirtyrate); ++} ++ + static void migration_trigger_throttle(RAMState *rs) + { + MigrationState *s = migrate_get_current(); +@@ -1429,6 +1463,8 @@ static void migration_trigger_throttle(RAMState *rs) + trace_migration_throttle(); + mig_throttle_guest_down(bytes_dirty_period, + bytes_dirty_threshold); ++ } else if (migrate_dirty_limit()) { ++ migration_dirty_limit_guest(); + } + } + } +diff --git a/migration/trace-events b/migration/trace-events +index b48d873b8a..246710f488 100644 +--- a/migration/trace-events ++++ b/migration/trace-events +@@ -92,6 +92,7 @@ migration_bitmap_sync_start(void) "" + migration_bitmap_sync_end(uint64_t dirty_pages) "dirty_pages %" PRIu64 + migration_bitmap_clear_dirty(char *str, uint64_t start, uint64_t size, unsigned long page) "rb %s start 0x%"PRIx64" size 0x%"PRIx64" page 0x%lx" + migration_throttle(void) "" ++migration_dirty_limit_guest(int64_t dirtyrate) "guest dirty page rate limit %" PRIi64 " MB/s" + ram_discard_range(const char *rbname, uint64_t start, size_t len) "%s: start: %" PRIx64 " %zx" + ram_load_loop(const char *rbname, uint64_t addr, int flags, void *host) "%s: addr: 0x%" PRIx64 " flags: 0x%x host: %p" + ram_load_postcopy_loop(uint64_t addr, int flags) "@%" PRIx64 " %x" +diff --git a/softmmu/dirtylimit.c b/softmmu/dirtylimit.c +index 4d770aaba4..a3337c0e20 100644 +--- a/softmmu/dirtylimit.c ++++ b/softmmu/dirtylimit.c +@@ -435,6 +435,23 @@ static void dirtylimit_cleanup(void) + dirtylimit_state_finalize(); + } + ++/* ++ * dirty page rate limit is not allowed to set if migration ++ * is running with dirty-limit capability enabled. ++ */ ++static bool dirtylimit_is_allowed(void) ++{ ++ MigrationState *ms = migrate_get_current(); ++ ++ if (migration_is_running(ms->state) && ++ (!qemu_thread_is_self(&ms->thread)) && ++ migrate_dirty_limit() && ++ dirtylimit_in_service()) { ++ return false; ++ } ++ return true; ++} ++ + void qmp_cancel_vcpu_dirty_limit(bool has_cpu_index, + int64_t cpu_index, + Error **errp) +@@ -448,6 +465,12 @@ void qmp_cancel_vcpu_dirty_limit(bool has_cpu_index, + return; + } + ++ if (!dirtylimit_is_allowed()) { ++ error_setg(errp, "can't cancel dirty page rate limit while" ++ " migration is running"); ++ return; ++ } ++ + if (!dirtylimit_in_service()) { + return; + } +@@ -498,6 +521,12 @@ void qmp_set_vcpu_dirty_limit(bool has_cpu_index, + return; + } + ++ if (!dirtylimit_is_allowed()) { ++ error_setg(errp, "can't set dirty page rate limit while" ++ " migration is running"); ++ return; ++ } ++ + if (!dirty_rate) { + qmp_cancel_vcpu_dirty_limit(has_cpu_index, cpu_index, errp); + return; +-- +2.27.0 + diff --git a/migration-Introduce-dirty-limit-capability.patch b/migration-Introduce-dirty-limit-capability.patch new file mode 100644 index 00000000..79f0c99a --- /dev/null +++ b/migration-Introduce-dirty-limit-capability.patch @@ -0,0 +1,183 @@ +From c7ae0b39eec728d7f88029f932fdd6d3bfda6e68 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Hyman=20Huang=28=E9=BB=84=E5=8B=87=29?= + +Date: Wed, 7 Jun 2023 23:30:50 +0800 +Subject: [PATCH] migration: Introduce dirty-limit capability +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +There is a conflict when merging patches in qemu-6.2.0, and there is a phenomenon that the corresponding files and functions cannot be found.Merge after modifying the patch by wangguochun@kylinos.cn + +Introduce migration dirty-limit capability, which can +be turned on before live migration and limit dirty +page rate durty live migration. + +Introduce migrate_dirty_limit function to help check +if dirty-limit capability enabled during live migration. + +Meanwhile, refactor vcpu_dirty_rate_stat_collect +so that period can be configured instead of hardcoded. + +dirty-limit capability is kind of like auto-converge +but using dirty limit instead of traditional cpu-throttle +to throttle guest down. To enable this feature, turn on +the dirty-limit capability before live migration using +migrate-set-capabilities, and set the parameters +"x-vcpu-dirty-limit-period", "vcpu-dirty-limit" suitably +to speed up convergence. + +Signed-off-by: Hyman Huang(黄勇) +Acked-by: Peter Xu +Reviewed-by: Juan Quintela +Message-Id: <168618975839.6361.17407633874747688653-4@git.sr.ht> +Signed-off-by: Juan Quintela +--- + migration/migration.c | 25 +++++++++++++++++++++++++ + migration/migration.h | 1 + + qapi/migration.json | 13 ++++++++++++- + softmmu/dirtylimit.c | 17 +++++++++++++---- + 4 files changed, 51 insertions(+), 5 deletions(-) + +diff --git a/migration/migration.c b/migration/migration.c +index 06d9b6a15d..50c33fecf3 100644 +--- a/migration/migration.c ++++ b/migration/migration.c +@@ -60,6 +60,7 @@ + #include "qemu/yank.h" + #include "sysemu/cpus.h" + #include "yank_functions.h" ++#include "sysemu/kvm.h" + + #define MAX_THROTTLE (128 << 20) /* Migration transfer speed throttling */ + +@@ -1265,6 +1266,20 @@ static bool migrate_caps_check(bool *cap_list, + error_setg(errp, "multifd is not supported by current protocol"); + return false; + } ++ ++ if (cap_list[MIGRATION_CAPABILITY_DIRTY_LIMIT]) { ++ if (cap_list[MIGRATION_CAPABILITY_AUTO_CONVERGE]) { ++ error_setg(errp, "dirty-limit conflicts with auto-converge" ++ " either of then available currently"); ++ return false; ++ } ++ ++ if (!kvm_enabled() || !kvm_dirty_ring_enabled()) { ++ error_setg(errp, "dirty-limit requires KVM with accelerator" ++ " property 'dirty-ring-size' set"); ++ return false; ++ } ++ } + + return true; + } +@@ -2550,6 +2565,15 @@ bool migrate_dirty_bitmaps(void) + return s->enabled_capabilities[MIGRATION_CAPABILITY_DIRTY_BITMAPS]; + } + ++bool migrate_dirty_limit(void) ++{ ++ MigrationState *s; ++ ++ s = migrate_get_current(); ++ ++ return s->enabled_capabilities[MIGRATION_CAPABILITY_DIRTY_LIMIT]; ++} ++ + bool migrate_ignore_shared(void) + { + MigrationState *s; +@@ -4316,6 +4340,7 @@ static Property migration_properties[] = { + DEFINE_PROP_UINT64("vcpu-dirty-limit", MigrationState, + parameters.vcpu_dirty_limit, + DEFAULT_MIGRATE_VCPU_DIRTY_LIMIT), ++ DEFINE_PROP_MIG_CAP("x-dirty-limit", MIGRATION_CAPABILITY_DIRTY_LIMIT), + + /* Migration capabilities */ + DEFINE_PROP_MIG_CAP("x-xbzrle", MIGRATION_CAPABILITY_XBZRLE), +diff --git a/migration/migration.h b/migration/migration.h +index 6b546a6ac7..9ce1fc8ea0 100644 +--- a/migration/migration.h ++++ b/migration/migration.h +@@ -329,6 +329,7 @@ bool migrate_release_ram(void); + bool migrate_postcopy_ram(void); + bool migrate_zero_blocks(void); + bool migrate_dirty_bitmaps(void); ++bool migrate_dirty_limit(void); + bool migrate_ignore_shared(void); + bool migrate_validate_uuid(void); + +diff --git a/qapi/migration.json b/qapi/migration.json +index f35f0377dc..4751c5ee53 100644 +--- a/qapi/migration.json ++++ b/qapi/migration.json +@@ -452,6 +452,16 @@ + # procedure starts. The VM RAM is saved with running VM. + # (since 6.0) + # ++# @dirty-limit: If enabled, migration will use the dirty-limit algo to ++# throttle down guest instead of auto-converge algo. ++# Throttle algo only works when vCPU's dirtyrate greater ++# than 'vcpu-dirty-limit', read processes in guest os ++# aren't penalized any more, so this algo can improve ++# performance of vCPU during live migration. This is an ++# optional performance feature and should not affect the ++# correctness of the existing auto-converge algo. ++# (since 8.1) ++# + # Features: + # @unstable: Members @x-colo and @x-ignore-shared are experimental. + # +@@ -465,7 +475,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', ++ 'dirty-limit'] } + + ## + # @MigrationCapabilityStatus: +diff --git a/softmmu/dirtylimit.c b/softmmu/dirtylimit.c +index 5041c230d0..4d770aaba4 100644 +--- a/softmmu/dirtylimit.c ++++ b/softmmu/dirtylimit.c +@@ -24,6 +24,8 @@ + #include "hw/boards.h" + #include "sysemu/kvm.h" + #include "trace.h" ++#include "migration/misc.h" ++#include "migration/migration.h" + + /* + * Dirtylimit stop working if dirty page rate error +@@ -75,14 +77,21 @@ static bool dirtylimit_quit; + + static void vcpu_dirty_rate_stat_collect(void) + { ++ MigrationState *s = migrate_get_current(); + VcpuStat stat; + int i = 0; ++ int64_t period = DIRTYLIMIT_CALC_TIME_MS; ++ ++ if (migrate_dirty_limit() && ++ migration_is_active(s)) { ++ period = s->parameters.x_vcpu_dirty_limit_period; ++ } + + /* calculate vcpu dirtyrate */ +- vcpu_calculate_dirtyrate(DIRTYLIMIT_CALC_TIME_MS, +- &stat, +- GLOBAL_DIRTY_LIMIT, +- false); ++ vcpu_calculate_dirtyrate(period, ++ &stat, ++ GLOBAL_DIRTY_LIMIT, ++ false); + + for (i = 0; i < stat.nvcpu; i++) { + vcpu_dirty_rate_stat->stat.rates[i].id = i; +-- +2.27.0 + diff --git a/migration-Put-the-detection-logic-before-auto-conver.patch b/migration-Put-the-detection-logic-before-auto-conver.patch new file mode 100644 index 00000000..e45bd479 --- /dev/null +++ b/migration-Put-the-detection-logic-before-auto-conver.patch @@ -0,0 +1,61 @@ +From 0f564d8940367ccdfb39b33be048f1b85e097e89 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Hyman=20Huang=28=E9=BB=84=E5=8B=87=29?= + +Date: Thu, 15 Jun 2023 21:29:44 +0800 +Subject: [PATCH] migration: Put the detection logic before auto-converge + checking +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This commit is prepared for the implementation of dirty-limit +convergence algo. + +The detection logic of throttling condition can apply to both +auto-converge and dirty-limit algo, putting it's position +before the checking logic for auto-converge feature. + +Signed-off-by: Hyman Huang(黄勇) +Reviewed-by: Juan Quintela +Message-ID: <168733225273.5845.15871826788879741674-6@git.sr.ht> +Signed-off-by: Juan Quintela +--- + migration/ram.c | 21 +++++++++++---------- + 1 file changed, 11 insertions(+), 10 deletions(-) + +diff --git a/migration/ram.c b/migration/ram.c +index 87e551913c..20f228e6bb 100644 +--- a/migration/ram.c ++++ b/migration/ram.c +@@ -1415,17 +1415,18 @@ static void migration_trigger_throttle(RAMState *rs) + return; + } + +- if (migrate_auto_converge()) { +- /* The following detection logic can be refined later. For now: +- Check to see if the ratio between dirtied bytes and the approx. +- amount of bytes that just got transferred since the last time +- we were in this routine reaches the threshold. If that happens +- twice, start or increase throttling. */ +- +- if ((bytes_dirty_period > bytes_dirty_threshold) && +- (++rs->dirty_rate_high_cnt >= 2)) { ++ /* ++ * The following detection logic can be refined later. For now: ++ * Check to see if the ratio between dirtied bytes and the approx. ++ * amount of bytes that just got transferred since the last time ++ * we were in this routine reaches the threshold. If that happens ++ * twice, start or increase throttling. ++ */ ++ if ((bytes_dirty_period > bytes_dirty_threshold) && ++ (++rs->dirty_rate_high_cnt >= 2)) { ++ rs->dirty_rate_high_cnt = 0; ++ if (migrate_auto_converge()) { + trace_migration_throttle(); +- rs->dirty_rate_high_cnt = 0; + mig_throttle_guest_down(bytes_dirty_period, + bytes_dirty_threshold); + } +-- +2.27.0 + diff --git a/migration-Refactor-auto-converge-capability-logic.patch b/migration-Refactor-auto-converge-capability-logic.patch new file mode 100644 index 00000000..ecf095ab --- /dev/null +++ b/migration-Refactor-auto-converge-capability-logic.patch @@ -0,0 +1,45 @@ +From b4f95f541ce2d428956508d8ce874377499c200c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Hyman=20Huang=28=E9=BB=84=E5=8B=87=29?= + +Date: Wed, 7 Jun 2023 23:32:51 +0800 +Subject: [PATCH] migration: Refactor auto-converge capability logic +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Check if block migration is running before throttling +guest down in auto-converge way. + +Note that this modification is kind of like code clean, +because block migration does not depend on auto-converge +capability, so the order of checks can be adjusted. + +Signed-off-by: Hyman Huang(黄勇) +Acked-by: Peter Xu +Reviewed-by: Juan Quintela +Message-Id: <168618975839.6361.17407633874747688653-5@git.sr.ht> +Signed-off-by: Juan Quintela +--- + migration/ram.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/migration/ram.c b/migration/ram.c +index c245b04cf2..87e551913c 100644 +--- a/migration/ram.c ++++ b/migration/ram.c +@@ -1411,7 +1411,11 @@ static void migration_trigger_throttle(RAMState *rs) + /* During block migration the auto-converge logic incorrectly detects + * that ram migration makes no progress. Avoid this by disabling the + * throttling logic during the bulk phase of block migration. */ +- if (migrate_auto_converge() && !blk_mig_bulk_active()) { ++ if (blk_mig_bulk_active()) { ++ return; ++ } ++ ++ if (migrate_auto_converge()) { + /* The following detection logic can be refined later. For now: + Check to see if the ratio between dirtied bytes and the approx. + amount of bytes that just got transferred since the last time +-- +2.27.0 + diff --git a/pc-bios-s390-ccw-Fix-booting-with-logical-block-size.patch b/pc-bios-s390-ccw-Fix-booting-with-logical-block-size.patch new file mode 100644 index 00000000..1e08b025 --- /dev/null +++ b/pc-bios-s390-ccw-Fix-booting-with-logical-block-size.patch @@ -0,0 +1,60 @@ +From e254e3404d9eedcc028c16933052c3fed37eb651 Mon Sep 17 00:00:00 2001 +From: tangbinzy +Date: Tue, 30 Apr 2024 08:32:41 +0000 +Subject: [PATCH] pc-bios/s390-ccw: Fix booting with logical block size < + physical block size mainline inclusion commit + 393296de19650e1400ca265914cfdeb313725363 category: bugfix + +--------------------------------------------------------------- + +For accessing single blocks during boot, it's the logical block size that +matters. (Physical block sizes are rather interesting e.g. for creating +file systems with the correct alignment for speed reasons etc.). +So the s390-ccw bios has to use the logical block size for calculating +sector numbers during the boot phase, the "physical_block_exp" shift +value must not be taken into account. This change fixes the boot process +when the guest hast been installed on a disk where the logical block size +differs from the physical one, e.g. if the guest has been installed +like this: + + qemu-system-s390x -nographic -accel kvm -m 2G \ + -drive if=none,id=d1,file=fedora.iso,format=raw,media=cdrom \ + -device virtio-scsi -device scsi-cd,drive=d1 \ + -drive if=none,id=d2,file=test.qcow2,format=qcow2 + -device virtio-blk,drive=d2,physical_block_size=4096,logical_block_size=512 + +Linux correctly uses the logical block size of 512 for the installation, +but the s390-ccw bios tries to boot from a disk with 4096 block size so +far, as long as this patch has not been applied yet (well, it used to work +by accident in the past due to the virtio_assume_scsi() hack that used to +enforce 512 byte sectors on all virtio-block disks, but that hack has been +well removed in commit 5447de2619050a0a4d to fix other scenarios). + +Fixes: 5447de2619 ("pc-bios/s390-ccw/virtio-blkdev: Remove virtio_assume_scsi()") +Buglink: https://bugzilla.redhat.com/show_bug.cgi?id=2112303 +Message-Id: <20220805094214.285223-1-thuth@redhat.com> +Reviewed-by: Cornelia Huck +Reviewed-by: Eric Farman +Signed-off-by: Thomas Huth + +Signed-off-by: tangbinzy +--- + pc-bios/s390-ccw/virtio-blkdev.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/pc-bios/s390-ccw/virtio-blkdev.c b/pc-bios/s390-ccw/virtio-blkdev.c +index 7d35050292..263a84d391 100644 +--- a/pc-bios/s390-ccw/virtio-blkdev.c ++++ b/pc-bios/s390-ccw/virtio-blkdev.c +@@ -214,7 +214,7 @@ int virtio_get_block_size(void) + + switch (vdev->senseid.cu_model) { + case VIRTIO_ID_BLOCK: +- return vdev->config.blk.blk_size << vdev->config.blk.physical_block_exp; ++ return vdev->config.blk.blk_size; + case VIRTIO_ID_SCSI: + return vdev->scsi_block_size; + } +-- +2.27.0 + diff --git a/qapi-migration-Introduce-vcpu-dirty-limit-parameters.patch b/qapi-migration-Introduce-vcpu-dirty-limit-parameters.patch new file mode 100644 index 00000000..a66bf9f0 --- /dev/null +++ b/qapi-migration-Introduce-vcpu-dirty-limit-parameters.patch @@ -0,0 +1,200 @@ +From 52201bf437125bb73deb8945491f7f823bdeb64a Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Hyman=20Huang=28=E9=BB=84=E5=8B=87=29?= + +Date: Wed, 7 Jun 2023 22:58:32 +0800 +Subject: [PATCH] qapi/migration: Introduce vcpu-dirty-limit parameters +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +There is a conflict when merging patches in qemu-6.2.0, and there is a phenomenon that the corresponding files and functions cannot be found.Merge after modifying the patch by wangguochun@kylinos.cn + +Introduce "vcpu-dirty-limit" migration parameter used +to limit dirty page rate during live migration. + +"vcpu-dirty-limit" and "x-vcpu-dirty-limit-period" are +two dirty-limit-related migration parameters, which can +be set before and during live migration by qmp +migrate-set-parameters. + +This two parameters are used to help implement the dirty +page rate limit algo of migration. + +Signed-off-by: Hyman Huang(黄勇) +Acked-by: Peter Xu +Reviewed-by: Juan Quintela +Message-Id: <168618975839.6361.17407633874747688653-3@git.sr.ht> +Signed-off-by: Juan Quintela +--- + migration/migration.c | 21 +++++++++++++++++++++ + monitor/hmp-cmds.c | 8 ++++++++ + qapi/migration.json | 18 +++++++++++++++--- + 3 files changed, 44 insertions(+), 3 deletions(-) + +diff --git a/migration/migration.c b/migration/migration.c +index 9672266e16..06d9b6a15d 100644 +--- a/migration/migration.c ++++ b/migration/migration.c +@@ -117,6 +117,7 @@ + #define DEFAULT_MIGRATE_ANNOUNCE_STEP 100 + + #define DEFAULT_MIGRATE_VCPU_DIRTY_LIMIT_PERIOD 1000 /* milliseconds */ ++#define DEFAULT_MIGRATE_VCPU_DIRTY_LIMIT 1 /* MB/s */ + + static NotifierList migration_state_notifiers = + NOTIFIER_LIST_INITIALIZER(migration_state_notifiers); +@@ -920,6 +921,8 @@ MigrationParameters *qmp_query_migrate_parameters(Error **errp) + + params->has_x_vcpu_dirty_limit_period = true; + params->x_vcpu_dirty_limit_period = s->parameters.x_vcpu_dirty_limit_period; ++ params->has_vcpu_dirty_limit = true; ++ params->vcpu_dirty_limit = s->parameters.vcpu_dirty_limit; + + return params; + } +@@ -1513,6 +1516,14 @@ static bool migrate_params_check(MigrationParameters *params, Error **errp) + return false; + } + ++ if (params->has_vcpu_dirty_limit && ++ (params->vcpu_dirty_limit < 1)) { ++ error_setg(errp, QERR_INVALID_PARAMETER_VALUE, ++ "vcpu_dirty_limit", ++ "is invalid, it must greater then 1 MB/s"); ++ return false; ++ } ++ + return true; + } + +@@ -1621,6 +1632,9 @@ static void migrate_params_test_apply(MigrateSetParameters *params, + dest->x_vcpu_dirty_limit_period = + params->x_vcpu_dirty_limit_period; + } ++ if (params->has_vcpu_dirty_limit) { ++ dest->vcpu_dirty_limit = params->vcpu_dirty_limit; ++ } + } + + static void migrate_params_apply(MigrateSetParameters *params, Error **errp) +@@ -1752,6 +1766,9 @@ static void migrate_params_apply(MigrateSetParameters *params, Error **errp) + s->parameters.x_vcpu_dirty_limit_period = + params->x_vcpu_dirty_limit_period; + } ++ if (params->has_vcpu_dirty_limit) { ++ s->parameters.vcpu_dirty_limit = params->vcpu_dirty_limit; ++ } + } + + void qmp_migrate_set_parameters(MigrateSetParameters *params, Error **errp) +@@ -4296,6 +4313,9 @@ static Property migration_properties[] = { + DEFINE_PROP_UINT64("x-vcpu-dirty-limit-period", MigrationState, + parameters.x_vcpu_dirty_limit_period, + DEFAULT_MIGRATE_VCPU_DIRTY_LIMIT_PERIOD), ++ DEFINE_PROP_UINT64("vcpu-dirty-limit", MigrationState, ++ parameters.vcpu_dirty_limit, ++ DEFAULT_MIGRATE_VCPU_DIRTY_LIMIT), + + /* Migration capabilities */ + DEFINE_PROP_MIG_CAP("x-xbzrle", MIGRATION_CAPABILITY_XBZRLE), +@@ -4372,6 +4392,7 @@ void migrate_params_init(MigrationParameters *params) + params->has_announce_rounds = true; + params->has_announce_step = true; + params->has_x_vcpu_dirty_limit_period = true; ++ params->has_vcpu_dirty_limit = true; + } + + +diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c +index 680696ddd5..01493cd2c0 100644 +--- a/monitor/hmp-cmds.c ++++ b/monitor/hmp-cmds.c +@@ -520,6 +520,10 @@ void hmp_info_migrate_parameters(Monitor *mon, const QDict *qdict) + monitor_printf(mon, "%s: %" PRIu64 " ms\n", + MigrationParameter_str(MIGRATION_PARAMETER_X_VCPU_DIRTY_LIMIT_PERIOD), + params->x_vcpu_dirty_limit_period); ++ ++ monitor_printf(mon, "%s: %" PRIu64 " MB/s\n", ++ MigrationParameter_str(MIGRATION_PARAMETER_VCPU_DIRTY_LIMIT), ++ params->vcpu_dirty_limit); + } + + qapi_free_MigrationParameters(params); +@@ -1353,6 +1357,10 @@ void hmp_migrate_set_parameter(Monitor *mon, const QDict *qdict) + p->has_x_vcpu_dirty_limit_period = true; + visit_type_size(v, param, &p->x_vcpu_dirty_limit_period, &err); + break; ++ case MIGRATION_PARAMETER_VCPU_DIRTY_LIMIT: ++ p->has_vcpu_dirty_limit = true; ++ visit_type_size(v, param, &p->vcpu_dirty_limit, &err); ++ break; + default: + assert(0); + } +diff --git a/qapi/migration.json b/qapi/migration.json +index b7dc85f7c1..f35f0377dc 100644 +--- a/qapi/migration.json ++++ b/qapi/migration.json +@@ -770,6 +770,9 @@ + # live migration. Should be in the range 1 to 1000ms, + # defaults to 1000ms. (Since 8.1) + # ++# @vcpu-dirty-limit: Dirtyrate limit (MB/s) during live migration. ++# Defaults to 1. (Since 8.1) ++# + # Features: + # @unstable: Members @x-checkpoint-delay and @x-vcpu-dirty-limit-period + # are experimental. +@@ -791,7 +794,8 @@ + 'max-cpu-throttle', 'multifd-compression', + 'multifd-zlib-level', 'multifd-zstd-level', + 'block-bitmap-mapping', +- { 'name': 'x-vcpu-dirty-limit-period', 'features': ['unstable'] } ] } ++ { 'name': 'x-vcpu-dirty-limit-period', 'features': ['unstable'] }, ++ 'vcpu-dirty-limit'] } + + ## + # @MigrateSetParameters: +@@ -943,6 +947,9 @@ + # live migration. Should be in the range 1 to 1000ms, + # defaults to 1000ms. (Since 8.1) + # ++# @vcpu-dirty-limit: Dirtyrate limit (MB/s) during live migration. ++# Defaults to 1. (Since 8.1) ++# + # Features: + # @unstable: Members @x-checkpoint-delay and @x-vcpu-dirty-limit-period + # are experimental. +@@ -982,7 +989,8 @@ + '*multifd-zstd-level': 'uint8', + '*block-bitmap-mapping': [ 'BitmapMigrationNodeAlias' ], + '*x-vcpu-dirty-limit-period': { 'type': 'uint64', +- 'features': [ 'unstable' ] } } } ++ 'features': [ 'unstable' ] }, ++ '*vcpu-dirty-limit': 'uint64'} } + + ## + # @migrate-set-parameters: +@@ -1154,6 +1162,9 @@ + # live migration. Should be in the range 1 to 1000ms, + # defaults to 1000ms. (Since 8.1) + # ++# @vcpu-dirty-limit: Dirtyrate limit (MB/s) during live migration. ++# Defaults to 1. (Since 8.1) ++# + # Features: + # @unstable: Members @x-checkpoint-delay and @x-vcpu-dirty-limit-period + # are experimental. +@@ -1191,7 +1202,8 @@ + '*multifd-zstd-level': 'uint8', + '*block-bitmap-mapping': [ 'BitmapMigrationNodeAlias' ], + '*x-vcpu-dirty-limit-period': { 'type': 'uint64', +- 'features': [ 'unstable' ] } } } ++ 'features': [ 'unstable' ] }, ++ '*vcpu-dirty-limit': 'uint64'} } + + ## + # @query-migrate-parameters: +-- +2.27.0 + diff --git a/qapi-migration-Introduce-x-vcpu-dirty-limit-period-p.patch b/qapi-migration-Introduce-x-vcpu-dirty-limit-period-p.patch new file mode 100644 index 00000000..5a3427da --- /dev/null +++ b/qapi-migration-Introduce-x-vcpu-dirty-limit-period-p.patch @@ -0,0 +1,273 @@ +From 6a9933b302c0fb396c6ede78fdef75385e1436e0 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Hyman=20Huang=28=E9=BB=84=E5=8B=87=29?= + +Date: Wed, 7 Jun 2023 21:32:59 +0800 +Subject: [PATCH] qapi/migration: Introduce x-vcpu-dirty-limit-period parameter +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +There is a conflict when merging patches in qemu-6.2.0, and there is a phenomenon that the corresponding files and functions cannot be found.Merge after modifying the patch by wangguochun@kylinos.cn + +Introduce "x-vcpu-dirty-limit-period" migration experimental +parameter, which is in the range of 1 to 1000ms and used to +make dirtyrate calculation period configurable. + +Currently with the "x-vcpu-dirty-limit-period" varies, the +total time of live migration changes, test results show the +optimal value of "x-vcpu-dirty-limit-period" ranges from +500ms to 1000 ms. "x-vcpu-dirty-limit-period" should be made +stable once it proves best value can not be determined with +developer's experiments. + +Signed-off-by: Hyman Huang(黄勇) +Reviewed-by: Markus Armbruster +Reviewed-by: Juan Quintela +Message-Id: <168618975839.6361.17407633874747688653-2@git.sr.ht> +Signed-off-by: Juan Quintela +--- + migration/migration.c | 53 +++++++++++++++++++++++++++++++++++-------- + migration/migration.h | 1 + + monitor/hmp-cmds.c | 8 +++++++ + qapi/migration.json | 35 +++++++++++++++++++++------- + 4 files changed, 79 insertions(+), 18 deletions(-) + +diff --git a/migration/migration.c b/migration/migration.c +index 7ca5b58839..9672266e16 100644 +--- a/migration/migration.c ++++ b/migration/migration.c +@@ -116,6 +116,8 @@ + #define DEFAULT_MIGRATE_ANNOUNCE_ROUNDS 5 + #define DEFAULT_MIGRATE_ANNOUNCE_STEP 100 + ++#define DEFAULT_MIGRATE_VCPU_DIRTY_LIMIT_PERIOD 1000 /* milliseconds */ ++ + static NotifierList migration_state_notifiers = + NOTIFIER_LIST_INITIALIZER(migration_state_notifiers); + +@@ -916,6 +918,9 @@ MigrationParameters *qmp_query_migrate_parameters(Error **errp) + s->parameters.block_bitmap_mapping); + } + ++ params->has_x_vcpu_dirty_limit_period = true; ++ params->x_vcpu_dirty_limit_period = s->parameters.x_vcpu_dirty_limit_period; ++ + return params; + } + +@@ -1499,6 +1504,15 @@ static bool migrate_params_check(MigrationParameters *params, Error **errp) + return false; + } + ++ if (params->has_x_vcpu_dirty_limit_period && ++ (params->x_vcpu_dirty_limit_period < 1 || ++ params->x_vcpu_dirty_limit_period > 1000)) { ++ error_setg(errp, QERR_INVALID_PARAMETER_VALUE, ++ "x-vcpu-dirty-limit-period", ++ "a value between 1 and 1000"); ++ return false; ++ } ++ + return true; + } + +@@ -1602,6 +1616,11 @@ static void migrate_params_test_apply(MigrateSetParameters *params, + dest->has_block_bitmap_mapping = true; + dest->block_bitmap_mapping = params->block_bitmap_mapping; + } ++ ++ if (params->has_x_vcpu_dirty_limit_period) { ++ dest->x_vcpu_dirty_limit_period = ++ params->x_vcpu_dirty_limit_period; ++ } + } + + static void migrate_params_apply(MigrateSetParameters *params, Error **errp) +@@ -1728,6 +1747,11 @@ static void migrate_params_apply(MigrateSetParameters *params, Error **errp) + QAPI_CLONE(BitmapMigrationNodeAliasList, + params->block_bitmap_mapping); + } ++ ++ if (params->has_x_vcpu_dirty_limit_period) { ++ s->parameters.x_vcpu_dirty_limit_period = ++ params->x_vcpu_dirty_limit_period; ++ } + } + + void qmp_migrate_set_parameters(MigrateSetParameters *params, Error **errp) +@@ -4269,6 +4293,9 @@ static Property migration_properties[] = { + DEFINE_PROP_SIZE("announce-step", MigrationState, + parameters.announce_step, + DEFAULT_MIGRATE_ANNOUNCE_STEP), ++ DEFINE_PROP_UINT64("x-vcpu-dirty-limit-period", MigrationState, ++ parameters.x_vcpu_dirty_limit_period, ++ DEFAULT_MIGRATE_VCPU_DIRTY_LIMIT_PERIOD), + + /* Migration capabilities */ + DEFINE_PROP_MIG_CAP("x-xbzrle", MIGRATION_CAPABILITY_XBZRLE), +@@ -4315,17 +4342,8 @@ static void migration_instance_finalize(Object *obj) + error_free(ms->error); + } + +-static void migration_instance_init(Object *obj) ++void migrate_params_init(MigrationParameters *params) + { +- MigrationState *ms = MIGRATION_OBJ(obj); +- MigrationParameters *params = &ms->parameters; +- +- ms->state = MIGRATION_STATUS_NONE; +- ms->mbps = -1; +- ms->pages_per_second = -1; +- qemu_sem_init(&ms->pause_sem, 0); +- qemu_mutex_init(&ms->error_mutex); +- + params->tls_hostname = g_strdup(""); + params->tls_creds = g_strdup(""); + +@@ -4353,6 +4371,21 @@ static void migration_instance_init(Object *obj) + params->has_announce_max = true; + params->has_announce_rounds = true; + params->has_announce_step = true; ++ params->has_x_vcpu_dirty_limit_period = true; ++} ++ ++ ++static void migration_instance_init(Object *obj) ++{ ++ MigrationState *ms = MIGRATION_OBJ(obj); ++ ++ ms->state = MIGRATION_STATUS_NONE; ++ ms->mbps = -1; ++ ms->pages_per_second = -1; ++ qemu_sem_init(&ms->pause_sem, 0); ++ qemu_mutex_init(&ms->error_mutex); ++ ++ migrate_params_init(&ms->parameters); + + qemu_sem_init(&ms->postcopy_pause_sem, 0); + qemu_sem_init(&ms->postcopy_pause_rp_sem, 0); +diff --git a/migration/migration.h b/migration/migration.h +index a87fd54d10..6b546a6ac7 100644 +--- a/migration/migration.h ++++ b/migration/migration.h +@@ -317,6 +317,7 @@ bool migration_is_setup_or_active(int state); + bool migration_is_running(int state); + + void migrate_init(MigrationState *s); ++void migrate_params_init(MigrationParameters *params); + bool migration_is_blocked(Error **errp); + /* True if outgoing migration has entered postcopy phase */ + bool migration_in_postcopy(void); +diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c +index 5246c82e14..680696ddd5 100644 +--- a/monitor/hmp-cmds.c ++++ b/monitor/hmp-cmds.c +@@ -516,6 +516,10 @@ void hmp_info_migrate_parameters(Monitor *mon, const QDict *qdict) + } + } + } ++ ++ monitor_printf(mon, "%s: %" PRIu64 " ms\n", ++ MigrationParameter_str(MIGRATION_PARAMETER_X_VCPU_DIRTY_LIMIT_PERIOD), ++ params->x_vcpu_dirty_limit_period); + } + + qapi_free_MigrationParameters(params); +@@ -1345,6 +1349,10 @@ void hmp_migrate_set_parameter(Monitor *mon, const QDict *qdict) + error_setg(&err, "The block-bitmap-mapping parameter can only be set " + "through QMP"); + break; ++ case MIGRATION_PARAMETER_X_VCPU_DIRTY_LIMIT_PERIOD: ++ p->has_x_vcpu_dirty_limit_period = true; ++ visit_type_size(v, param, &p->x_vcpu_dirty_limit_period, &err); ++ break; + default: + assert(0); + } +diff --git a/qapi/migration.json b/qapi/migration.json +index e965f4329b..b7dc85f7c1 100644 +--- a/qapi/migration.json ++++ b/qapi/migration.json +@@ -766,9 +766,13 @@ + # block device name if there is one, and to their node name + # otherwise. (Since 5.2) + # +-# Features: +-# @unstable: Member @x-checkpoint-delay is experimental. ++# @x-vcpu-dirty-limit-period: Periodic time (in milliseconds) of dirty limit during ++# live migration. Should be in the range 1 to 1000ms, ++# defaults to 1000ms. (Since 8.1) + # ++# Features: ++# @unstable: Members @x-checkpoint-delay and @x-vcpu-dirty-limit-period ++# are experimental. + # Since: 2.4 + ## + { 'enum': 'MigrationParameter', +@@ -785,8 +789,9 @@ + 'multifd-channels', + 'xbzrle-cache-size', 'max-postcopy-bandwidth', + 'max-cpu-throttle', 'multifd-compression', +- 'multifd-zlib-level' ,'multifd-zstd-level', +- 'block-bitmap-mapping' ] } ++ 'multifd-zlib-level', 'multifd-zstd-level', ++ 'block-bitmap-mapping', ++ { 'name': 'x-vcpu-dirty-limit-period', 'features': ['unstable'] } ] } + + ## + # @MigrateSetParameters: +@@ -934,8 +939,13 @@ + # block device name if there is one, and to their node name + # otherwise. (Since 5.2) + # ++# @x-vcpu-dirty-limit-period: Periodic time (in milliseconds) of dirty limit during ++# live migration. Should be in the range 1 to 1000ms, ++# defaults to 1000ms. (Since 8.1) ++# + # Features: +-# @unstable: Member @x-checkpoint-delay is experimental. ++# @unstable: Members @x-checkpoint-delay and @x-vcpu-dirty-limit-period ++# are experimental. + # + # Since: 2.4 + ## +@@ -970,7 +980,9 @@ + '*multifd-compression': 'MultiFDCompression', + '*multifd-zlib-level': 'uint8', + '*multifd-zstd-level': 'uint8', +- '*block-bitmap-mapping': [ 'BitmapMigrationNodeAlias' ] } } ++ '*block-bitmap-mapping': [ 'BitmapMigrationNodeAlias' ], ++ '*x-vcpu-dirty-limit-period': { 'type': 'uint64', ++ 'features': [ 'unstable' ] } } } + + ## + # @migrate-set-parameters: +@@ -1138,8 +1150,13 @@ + # block device name if there is one, and to their node name + # otherwise. (Since 5.2) + # ++# @x-vcpu-dirty-limit-period: Periodic time (in milliseconds) of dirty limit during ++# live migration. Should be in the range 1 to 1000ms, ++# defaults to 1000ms. (Since 8.1) ++# + # Features: +-# @unstable: Member @x-checkpoint-delay is experimental. ++# @unstable: Members @x-checkpoint-delay and @x-vcpu-dirty-limit-period ++# are experimental. + # + # Since: 2.4 + ## +@@ -1172,7 +1189,9 @@ + '*multifd-compression': 'MultiFDCompression', + '*multifd-zlib-level': 'uint8', + '*multifd-zstd-level': 'uint8', +- '*block-bitmap-mapping': [ 'BitmapMigrationNodeAlias' ] } } ++ '*block-bitmap-mapping': [ 'BitmapMigrationNodeAlias' ], ++ '*x-vcpu-dirty-limit-period': { 'type': 'uint64', ++ 'features': [ 'unstable' ] } } } + + ## + # @query-migrate-parameters: +-- +2.27.0 + diff --git a/qemu.spec b/qemu.spec index ca2f21a6..d4b1dec9 100644 --- a/qemu.spec +++ b/qemu.spec @@ -3,7 +3,7 @@ Name: qemu Version: 6.2.0 -Release: 91 +Release: 92 Epoch: 10 Summary: QEMU is a generic and open source machine emulator and virtualizer License: GPLv2 and BSD and MIT and CC-BY-SA-4.0 @@ -938,6 +938,32 @@ Patch0923: hw-virtio-Introduce-virtio_bh_new_guarded-helper.patch Patch0924: hw-display-virtio-gpu-Protect-from-DMA-re-entrancy-b.patch Patch0925: hw-char-virtio-serial-bus-Protect-from-DMA-re-entran.patch Patch0926: hw-virtio-virtio-crypto-Protect-from-DMA-re-entrancy.patch +Patch0927: pc-bios-s390-ccw-Fix-booting-with-logical-block-size.patch +Patch0928: target-i386-display-deprecation-status-in-cpu-help.patch +Patch0929: target-s390x-display-deprecation-status-in-cpu-help.patch +Patch0930: hw-virtio-handle-un-configured-shutdown-in-virtio-pc.patch +Patch0931: target-i386-Introduce-Icelake-Server-v7-to-enable-TS.patch +Patch0932: target-i386-Add-new-CPU-model-SierraForest.patch +Patch0933: target-i386-Export-RFDS-bit-to-guests.patch +Patch0934: vfio-pci-Add-Ascend310b-scend910b-support.patch +Patch0935: dbus-vmstate-Restrict-error-checks-to-registered-pro.patch +Patch0936: esp-Handle-CMD_BUSRESET-by-resetting-the-SCSI-bus.patch +Patch0937: i386-reset-KVM-nested-state-upon-CPU-reset.patch +Patch0938: KVM-dirty-ring-add-missing-memory-barrier.patch +Patch0939: chardev-char-socket-Update-AF_UNIX-for-Windows.patch +Patch0940: tpm_emulator-Avoid-double-initialization-during-migr.patch +Patch0941: Allow-UNIX-socket-option-for-VNC-websocket.patch +Patch0942: Change-the-value-of-no_ged-from-true-to-false.patch +Patch0943: qapi-migration-Introduce-x-vcpu-dirty-limit-period-p.patch +Patch0944: qapi-migration-Introduce-vcpu-dirty-limit-parameters.patch +Patch0945: migration-Introduce-dirty-limit-capability.patch +Patch0946: migration-Refactor-auto-converge-capability-logic.patch +Patch0947: migration-Put-the-detection-logic-before-auto-conver.patch +Patch0948: migration-Implement-dirty-limit-convergence-algo.patch +Patch0949: migration-Extend-query-migrate-to-provide-dirty-page.patch +Patch0950: docs-system-target-arm-Re-alphabetize-board-list.patch +Patch0951: target-ppc-Remove-msr_pr-macro.patch +Patch0952: s390x-sclp-Simplify-get_sclp_device.patch BuildRequires: flex BuildRequires: gcc @@ -1536,6 +1562,34 @@ getent passwd qemu >/dev/null || \ %endif %changelog +* Thu Jun 13 2024 - 10:6.2.0-92 +- s390x/sclp: Simplify get_sclp_device() +- target/ppc: Remove msr_pr macro +- docs/system/target-arm: Re-alphabetize board list +- migration: Extend query-migrate to provide dirty page limit info +- migration: Implement dirty-limit convergence algo +- migration: Put the detection logic before auto-converge checking +- migration: Refactor auto-converge capability logic +- migration: Introduce dirty-limit capability +- qapi/migration: Introduce vcpu-dirty-limit parameters +- qapi/migration: Introduce x-vcpu-dirty-limit-period parameter +- Change the value of no_ged from true to false +- Allow UNIX socket option for VNC websocket +- tpm_emulator: Avoid double initialization during +- chardev/char-socket: Update AF_UNIX for Windows +- KVM: dirty ring: add missing memory barrier +- i386: reset KVM nested state upon CPU reset +- esp: Handle CMD_BUSRESET by resetting the SCSI bus +- dbus-vmstate: Restrict error checks to registered proxies in dbus_get_proxies +- vfio/pci: Add Ascend310b scend910b support +- target/i386: Export RFDS bit to guests +- target/i386: Add new CPU model SierraForest +- target/i386: Introduce Icelake-Server-v7 to enable TSX +- hw/virtio: handle un-configured shutdown in virtio-pci +- target/s390x: display deprecation status in '-cpu help' +- target/i386: display deprecation status in '-cpu help' +- pc-bios/s390-ccw: Fix booting with logical block size < physical block size + * Mon Apr 22 2024 - 10:6.2.0-91 - hw/virtio/virtio-crypto: Protect from DMA re-entrancy bugs(CVE-2024-3446) - hw/char/virtio-serial-bus: Protect from DMA re-entrancy bugs(CVE-2024-3446) diff --git a/s390x-sclp-Simplify-get_sclp_device.patch b/s390x-sclp-Simplify-get_sclp_device.patch new file mode 100644 index 00000000..839a659f --- /dev/null +++ b/s390x-sclp-Simplify-get_sclp_device.patch @@ -0,0 +1,46 @@ +From d25446c995e2c562d62d832bc8da58d13b731974 Mon Sep 17 00:00:00 2001 +From: dinglimin +Date: Mon, 10 Jun 2024 20:00:42 +0800 +Subject: [PATCH] s390x/sclp: Simplify get_sclp_device() cheery-pick from + 3d9836e46dbe1e46c39fe76a62d3085a71ddbf7a get_sclp_device() scans the whole + machine to find a TYPE_SCLP object. Now that the SCLPDevice instance is + available under the machine state, use it to simplify the lookup. While at + it, remove the inline to let the compiler decide on how to optimize. +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Cédric Le Goater +Message-ID: <20240502131533.377719-4-clg@redhat.com> +Reviewed-by: Thomas Huth +Signed-off-by: Thomas Huth + +Signed-off-by: dinglimin +--- + hw/s390x/sclp.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/hw/s390x/sclp.c b/hw/s390x/sclp.c +index 89c30a8a91..24e29e8cda 100644 +--- a/hw/s390x/sclp.c ++++ b/hw/s390x/sclp.c +@@ -20,13 +20,14 @@ + #include "hw/s390x/event-facility.h" + #include "hw/s390x/s390-pci-bus.h" + #include "hw/s390x/ipl.h" ++#include "hw/s390x/s390-virtio-ccw.h" + +-static inline SCLPDevice *get_sclp_device(void) ++static SCLPDevice *get_sclp_device(void) + { + static SCLPDevice *sclp; + + if (!sclp) { +- sclp = SCLP(object_resolve_path_type("", TYPE_SCLP, NULL)); ++ sclp = S390_CCW_MACHINE(qdev_get_machine())->sclp; + } + return sclp; + } +-- +2.27.0 + diff --git a/target-i386-Add-new-CPU-model-SierraForest.patch b/target-i386-Add-new-CPU-model-SierraForest.patch new file mode 100644 index 00000000..657e14e8 --- /dev/null +++ b/target-i386-Add-new-CPU-model-SierraForest.patch @@ -0,0 +1,212 @@ +From f315e08911bcfdbbb287aa35453acc71867ccd1e Mon Sep 17 00:00:00 2001 +From: Tao Su +Date: Wed, 20 Mar 2024 10:10:44 +0800 +Subject: [PATCH] target/i386: Add new CPU model SierraForest +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +commit 6e82d3b6220777667968a04c87e1667f164ebe88 upstream. + +According to table 1-2 in Intel Architecture Instruction Set Extensions and +Future Features (rev 051) [1], SierraForest has the following new features +which have already been virtualized: + +- CMPCCXADD CPUID.(EAX=7,ECX=1):EAX[bit 7] +- AVX-IFMA CPUID.(EAX=7,ECX=1):EAX[bit 23] +- AVX-VNNI-INT8 CPUID.(EAX=7,ECX=1):EDX[bit 4] +- AVX-NE-CONVERT CPUID.(EAX=7,ECX=1):EDX[bit 5] + +Add above features to new CPU model SierraForest. Comparing with GraniteRapids +CPU model, SierraForest bare-metal removes the following features: + +- HLE CPUID.(EAX=7,ECX=0):EBX[bit 4] +- RTM CPUID.(EAX=7,ECX=0):EBX[bit 11] +- AVX512F CPUID.(EAX=7,ECX=0):EBX[bit 16] +- AVX512DQ CPUID.(EAX=7,ECX=0):EBX[bit 17] +- AVX512_IFMA CPUID.(EAX=7,ECX=0):EBX[bit 21] +- AVX512CD CPUID.(EAX=7,ECX=0):EBX[bit 28] +- AVX512BW CPUID.(EAX=7,ECX=0):EBX[bit 30] +- AVX512VL CPUID.(EAX=7,ECX=0):EBX[bit 31] +- AVX512_VBMI CPUID.(EAX=7,ECX=0):ECX[bit 1] +- AVX512_VBMI2 CPUID.(EAX=7,ECX=0):ECX[bit 6] +- AVX512_VNNI CPUID.(EAX=7,ECX=0):ECX[bit 11] +- AVX512_BITALG CPUID.(EAX=7,ECX=0):ECX[bit 12] +- AVX512_VPOPCNTDQ CPUID.(EAX=7,ECX=0):ECX[bit 14] +- LA57 CPUID.(EAX=7,ECX=0):ECX[bit 16] +- TSXLDTRK CPUID.(EAX=7,ECX=0):EDX[bit 16] +- AMX-BF16 CPUID.(EAX=7,ECX=0):EDX[bit 22] +- AVX512_FP16 CPUID.(EAX=7,ECX=0):EDX[bit 23] +- AMX-TILE CPUID.(EAX=7,ECX=0):EDX[bit 24] +- AMX-INT8 CPUID.(EAX=7,ECX=0):EDX[bit 25] +- AVX512_BF16 CPUID.(EAX=7,ECX=1):EAX[bit 5] +- fast zero-length MOVSB CPUID.(EAX=7,ECX=1):EAX[bit 10] +- fast short CMPSB, SCASB CPUID.(EAX=7,ECX=1):EAX[bit 12] +- AMX-FP16 CPUID.(EAX=7,ECX=1):EAX[bit 21] +- PREFETCHI CPUID.(EAX=7,ECX=1):EDX[bit 14] +- XFD CPUID.(EAX=0xD,ECX=1):EAX[bit 4] +- EPT_PAGE_WALK_LENGTH_5 VMX_EPT_VPID_CAP(0x48c)[bit 7] + +Add all features of GraniteRapids CPU model except above features to +SierraForest CPU model. + +SierraForest doesn’t support TSX and RTM but supports TAA_NO. When RTM is +not enabled in host, KVM will not report TAA_NO. So, just don't include +TAA_NO in SierraForest CPU model. + +[1] https://cdrdv2.intel.com/v1/dl/getContent/671368 + +Intel-SIG: commit 6e82d3b62207 target/i386: Add new CPU model SierraForest. +6.2.0-Add SRF CPU module support + +Reviewed-by: Zhao Liu +Reviewed-by: Xiaoyao Li +Signed-off-by: Tao Su +Message-ID: <20240320021044.508263-1-tao1.su@linux.intel.com> +Signed-off-by: Paolo Bonzini +[ Quanxian Wang: amend commit log ] +Signed-off-by: Quanxian Wang +--- + target/i386/cpu.c | 126 ++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 126 insertions(+) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index b5bf5ce7aa..eb7fda0299 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -3893,6 +3893,132 @@ static const X86CPUDefinition builtin_x86_defs[] = { + { /* end of list */ }, + }, + }, ++ { ++ .name = "SierraForest", ++ .level = 0x23, ++ .vendor = CPUID_VENDOR_INTEL, ++ .family = 6, ++ .model = 175, ++ .stepping = 0, ++ /* ++ * please keep the ascending order so that we can have a clear view of ++ * bit position of each feature. ++ */ ++ .features[FEAT_1_EDX] = ++ CPUID_FP87 | CPUID_VME | CPUID_DE | CPUID_PSE | CPUID_TSC | ++ CPUID_MSR | CPUID_PAE | CPUID_MCE | CPUID_CX8 | CPUID_APIC | ++ CPUID_SEP | CPUID_MTRR | CPUID_PGE | CPUID_MCA | CPUID_CMOV | ++ CPUID_PAT | CPUID_PSE36 | CPUID_CLFLUSH | CPUID_MMX | CPUID_FXSR | ++ CPUID_SSE | CPUID_SSE2, ++ .features[FEAT_1_ECX] = ++ CPUID_EXT_SSE3 | CPUID_EXT_PCLMULQDQ | CPUID_EXT_SSSE3 | ++ CPUID_EXT_FMA | CPUID_EXT_CX16 | CPUID_EXT_PCID | CPUID_EXT_SSE41 | ++ CPUID_EXT_SSE42 | CPUID_EXT_X2APIC | CPUID_EXT_MOVBE | ++ CPUID_EXT_POPCNT | CPUID_EXT_TSC_DEADLINE_TIMER | CPUID_EXT_AES | ++ CPUID_EXT_XSAVE | CPUID_EXT_AVX | CPUID_EXT_F16C | CPUID_EXT_RDRAND, ++ .features[FEAT_8000_0001_EDX] = ++ CPUID_EXT2_SYSCALL | CPUID_EXT2_NX | CPUID_EXT2_PDPE1GB | ++ CPUID_EXT2_RDTSCP | CPUID_EXT2_LM, ++ .features[FEAT_8000_0001_ECX] = ++ CPUID_EXT3_LAHF_LM | CPUID_EXT3_ABM | CPUID_EXT3_3DNOWPREFETCH, ++ .features[FEAT_8000_0008_EBX] = ++ CPUID_8000_0008_EBX_WBNOINVD, ++ .features[FEAT_7_0_EBX] = ++ CPUID_7_0_EBX_FSGSBASE | CPUID_7_0_EBX_BMI1 | CPUID_7_0_EBX_AVX2 | ++ CPUID_7_0_EBX_SMEP | CPUID_7_0_EBX_BMI2 | CPUID_7_0_EBX_ERMS | ++ CPUID_7_0_EBX_INVPCID | CPUID_7_0_EBX_RDSEED | CPUID_7_0_EBX_ADX | ++ CPUID_7_0_EBX_SMAP | CPUID_7_0_EBX_CLFLUSHOPT | CPUID_7_0_EBX_CLWB | ++ CPUID_7_0_EBX_SHA_NI, ++ .features[FEAT_7_0_ECX] = ++ CPUID_7_0_ECX_UMIP | CPUID_7_0_ECX_PKU | CPUID_7_0_ECX_GFNI | ++ CPUID_7_0_ECX_VAES | CPUID_7_0_ECX_VPCLMULQDQ | ++ CPUID_7_0_ECX_RDPID | CPUID_7_0_ECX_BUS_LOCK_DETECT, ++ .features[FEAT_7_0_EDX] = ++ CPUID_7_0_EDX_FSRM | CPUID_7_0_EDX_SERIALIZE | ++ CPUID_7_0_EDX_SPEC_CTRL | CPUID_7_0_EDX_ARCH_CAPABILITIES | ++ CPUID_7_0_EDX_SPEC_CTRL_SSBD, ++ .features[FEAT_ARCH_CAPABILITIES] = ++ MSR_ARCH_CAP_RDCL_NO | MSR_ARCH_CAP_IBRS_ALL | ++ MSR_ARCH_CAP_SKIP_L1DFL_VMENTRY | MSR_ARCH_CAP_MDS_NO | ++ MSR_ARCH_CAP_PSCHANGE_MC_NO | MSR_ARCH_CAP_SBDR_SSDP_NO | ++ MSR_ARCH_CAP_FBSDP_NO | MSR_ARCH_CAP_PSDP_NO | ++ MSR_ARCH_CAP_PBRSB_NO, ++ .features[FEAT_XSAVE] = ++ CPUID_XSAVE_XSAVEOPT | CPUID_XSAVE_XSAVEC | ++ CPUID_XSAVE_XGETBV1 | CPUID_XSAVE_XSAVES, ++ .features[FEAT_6_EAX] = ++ CPUID_6_EAX_ARAT, ++ .features[FEAT_7_1_EAX] = ++ CPUID_7_1_EAX_AVX_VNNI | CPUID_7_1_EAX_CMPCCXADD | ++ CPUID_7_1_EAX_FSRS | CPUID_7_1_EAX_AVX_IFMA, ++ .features[FEAT_7_1_EDX] = ++ CPUID_7_1_EDX_AVX_VNNI_INT8 | CPUID_7_1_EDX_AVX_NE_CONVERT, ++ .features[FEAT_7_2_EDX] = ++ CPUID_7_2_EDX_MCDT_NO, ++ .features[FEAT_VMX_BASIC] = ++ MSR_VMX_BASIC_INS_OUTS | MSR_VMX_BASIC_TRUE_CTLS, ++ .features[FEAT_VMX_ENTRY_CTLS] = ++ VMX_VM_ENTRY_LOAD_DEBUG_CONTROLS | VMX_VM_ENTRY_IA32E_MODE | ++ VMX_VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL | ++ VMX_VM_ENTRY_LOAD_IA32_PAT | VMX_VM_ENTRY_LOAD_IA32_EFER, ++ .features[FEAT_VMX_EPT_VPID_CAPS] = ++ MSR_VMX_EPT_EXECONLY | MSR_VMX_EPT_PAGE_WALK_LENGTH_4 | ++ MSR_VMX_EPT_WB | MSR_VMX_EPT_2MB | MSR_VMX_EPT_1GB | ++ MSR_VMX_EPT_INVEPT | MSR_VMX_EPT_AD_BITS | ++ MSR_VMX_EPT_INVEPT_SINGLE_CONTEXT | MSR_VMX_EPT_INVEPT_ALL_CONTEXT | ++ MSR_VMX_EPT_INVVPID | MSR_VMX_EPT_INVVPID_SINGLE_ADDR | ++ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT | ++ MSR_VMX_EPT_INVVPID_ALL_CONTEXT | ++ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT_NOGLOBALS, ++ .features[FEAT_VMX_EXIT_CTLS] = ++ VMX_VM_EXIT_SAVE_DEBUG_CONTROLS | ++ VMX_VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL | ++ VMX_VM_EXIT_ACK_INTR_ON_EXIT | VMX_VM_EXIT_SAVE_IA32_PAT | ++ VMX_VM_EXIT_LOAD_IA32_PAT | VMX_VM_EXIT_SAVE_IA32_EFER | ++ VMX_VM_EXIT_LOAD_IA32_EFER | VMX_VM_EXIT_SAVE_VMX_PREEMPTION_TIMER, ++ .features[FEAT_VMX_MISC] = ++ MSR_VMX_MISC_STORE_LMA | MSR_VMX_MISC_ACTIVITY_HLT | ++ MSR_VMX_MISC_VMWRITE_VMEXIT, ++ .features[FEAT_VMX_PINBASED_CTLS] = ++ VMX_PIN_BASED_EXT_INTR_MASK | VMX_PIN_BASED_NMI_EXITING | ++ VMX_PIN_BASED_VIRTUAL_NMIS | VMX_PIN_BASED_VMX_PREEMPTION_TIMER | ++ VMX_PIN_BASED_POSTED_INTR, ++ .features[FEAT_VMX_PROCBASED_CTLS] = ++ VMX_CPU_BASED_VIRTUAL_INTR_PENDING | ++ VMX_CPU_BASED_USE_TSC_OFFSETING | VMX_CPU_BASED_HLT_EXITING | ++ VMX_CPU_BASED_INVLPG_EXITING | VMX_CPU_BASED_MWAIT_EXITING | ++ VMX_CPU_BASED_RDPMC_EXITING | VMX_CPU_BASED_RDTSC_EXITING | ++ VMX_CPU_BASED_CR3_LOAD_EXITING | VMX_CPU_BASED_CR3_STORE_EXITING | ++ VMX_CPU_BASED_CR8_LOAD_EXITING | VMX_CPU_BASED_CR8_STORE_EXITING | ++ VMX_CPU_BASED_TPR_SHADOW | VMX_CPU_BASED_VIRTUAL_NMI_PENDING | ++ VMX_CPU_BASED_MOV_DR_EXITING | VMX_CPU_BASED_UNCOND_IO_EXITING | ++ VMX_CPU_BASED_USE_IO_BITMAPS | VMX_CPU_BASED_MONITOR_TRAP_FLAG | ++ VMX_CPU_BASED_USE_MSR_BITMAPS | VMX_CPU_BASED_MONITOR_EXITING | ++ VMX_CPU_BASED_PAUSE_EXITING | ++ VMX_CPU_BASED_ACTIVATE_SECONDARY_CONTROLS, ++ .features[FEAT_VMX_SECONDARY_CTLS] = ++ VMX_SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES | ++ VMX_SECONDARY_EXEC_ENABLE_EPT | VMX_SECONDARY_EXEC_DESC | ++ VMX_SECONDARY_EXEC_RDTSCP | ++ VMX_SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE | ++ VMX_SECONDARY_EXEC_ENABLE_VPID | VMX_SECONDARY_EXEC_WBINVD_EXITING | ++ VMX_SECONDARY_EXEC_UNRESTRICTED_GUEST | ++ VMX_SECONDARY_EXEC_APIC_REGISTER_VIRT | ++ VMX_SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY | ++ VMX_SECONDARY_EXEC_RDRAND_EXITING | ++ VMX_SECONDARY_EXEC_ENABLE_INVPCID | ++ VMX_SECONDARY_EXEC_ENABLE_VMFUNC | VMX_SECONDARY_EXEC_SHADOW_VMCS | ++ VMX_SECONDARY_EXEC_RDSEED_EXITING | VMX_SECONDARY_EXEC_ENABLE_PML | ++ VMX_SECONDARY_EXEC_XSAVES, ++ .features[FEAT_VMX_VMFUNC] = ++ MSR_VMX_VMFUNC_EPT_SWITCHING, ++ .xlevel = 0x80000008, ++ .model_id = "Intel Xeon Processor (SierraForest)", ++ .versions = (X86CPUVersionDefinition[]) { ++ { .version = 1 }, ++ { /* end of list */ }, ++ }, ++ }, + { + .name = "Denverton", + .level = 21, +-- +2.27.0 + diff --git a/target-i386-Export-RFDS-bit-to-guests.patch b/target-i386-Export-RFDS-bit-to-guests.patch new file mode 100644 index 00000000..76d592bf --- /dev/null +++ b/target-i386-Export-RFDS-bit-to-guests.patch @@ -0,0 +1,47 @@ +From 2ddb661f2566d8835103c0beedf24e36adc2608d Mon Sep 17 00:00:00 2001 +From: Pawan Gupta +Date: Wed, 13 Mar 2024 07:53:23 -0700 +Subject: [PATCH] target/i386: Export RFDS bit to guests + +commit 41bdd9812863c150284a9339a048ed88c40f4df7 upstream. + +Register File Data Sampling (RFDS) is a CPU side-channel vulnerability +that may expose stale register value. CPUs that set RFDS_NO bit in MSR +IA32_ARCH_CAPABILITIES indicate that they are not vulnerable to RFDS. +Similarly, RFDS_CLEAR indicates that CPU is affected by RFDS, and has +the microcode to help mitigate RFDS. + +Make RFDS_CLEAR and RFDS_NO bits available to guests. + +Intel-SIG: commit 41bdd9812863 target/i386: Export RFDS bit to guests. +6.2.0-Add SRF CPU module support + +Signed-off-by: Pawan Gupta +Reviewed-by: Xiaoyao Li +Reviewed-by: Zhao Liu +Message-ID: <9a38877857392b5c2deae7e7db1b170d15510314.1710341348.git.pawan.kumar.gupta@linux.intel.com> +Signed-off-by: Paolo Bonzini +[ Quanxian Wang: amend commit log ] +Signed-off-by: Quanxian Wang +--- + target/i386/cpu.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index eb7fda0299..a11f3373ea 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -1052,8 +1052,8 @@ FeatureWordInfo feature_word_info[FEATURE_WORDS] = { + NULL, "sbdr-ssdp-no", "fbsdp-no", "psdp-no", + NULL, "fb-clear", NULL, NULL, + NULL, NULL, NULL, NULL, +- "pbrsb-no", NULL, "gds-no", NULL, +- NULL, NULL, NULL, NULL, ++ "pbrsb-no", NULL, "gds-no", "rfds-no", ++ "rfds-clear", NULL, NULL, NULL, + }, + .msr = { + .index = MSR_IA32_ARCH_CAPABILITIES, +-- +2.27.0 + diff --git a/target-i386-Introduce-Icelake-Server-v7-to-enable-TS.patch b/target-i386-Introduce-Icelake-Server-v7-to-enable-TS.patch new file mode 100644 index 00000000..6d1e85f5 --- /dev/null +++ b/target-i386-Introduce-Icelake-Server-v7-to-enable-TS.patch @@ -0,0 +1,64 @@ +From 2f722c0308c72223e1fe13caf1a3e5843635c98e Mon Sep 17 00:00:00 2001 +From: Zhenzhong Duan +Date: Wed, 20 Mar 2024 17:31:38 +0800 +Subject: [PATCH] target/i386: Introduce Icelake-Server-v7 to enable TSX + +commit c895fa54e3060c5ac6f3888dce96c9b78626072b upstream. + +When start L2 guest with both L1/L2 using Icelake-Server-v3 or above, +QEMU reports below warning: + +"warning: host doesn't support requested feature: MSR(10AH).taa-no [bit 8]" + +Reason is QEMU Icelake-Server-v3 has TSX feature disabled but enables taa-no +bit. It's meaningless that TSX isn't supported but still claim TSX is secure. +So L1 KVM doesn't expose taa-no to L2 if TSX is unsupported, then starting L2 +triggers the warning. + +Fix it by introducing a new version Icelake-Server-v7 which has both TSX +and taa-no features. Then guest can use TSX securely when it see taa-no. + +This matches the production Icelake which supports TSX and isn't susceptible +to TSX Async Abort (TAA) vulnerabilities, a.k.a, taa-no. + +Ideally, TSX should have being enabled together with taa-no since v3, but for +compatibility, we'd better to add v7 to enable it. + +Fixes: d965dc35592d ("target/i386: Add ARCH_CAPABILITIES related bits into Icelake-Server CPU model") +Intel-SIG: commit c895fa54e306 target/i386: Introduce Icelake-Server-v7 to enable TSX. +6.2.0-Add SRF CPU module support + +Tested-by: Xiangfei Ma +Signed-off-by: Zhenzhong Duan +Message-ID: <20240320093138.80267-2-zhenzhong.duan@intel.com> +Signed-off-by: Paolo Bonzini +[ Quanxian Wang: amend commit log ] +Signed-off-by: Quanxian Wang +--- + target/i386/cpu.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index 62ac5ed005..b5bf5ce7aa 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -3606,6 +3606,16 @@ static const X86CPUDefinition builtin_x86_defs[] = { + { /* end of list */ } + }, + }, ++ { ++ .version = 7, ++ .note = "TSX, taa-no", ++ .props = (PropValue[]) { ++ /* Restore TSX features removed by -v2 above */ ++ { "hle", "on" }, ++ { "rtm", "on" }, ++ { /* end of list */ } ++ }, ++ }, + { /* end of list */ } + } + }, +-- +2.27.0 + diff --git a/target-i386-display-deprecation-status-in-cpu-help.patch b/target-i386-display-deprecation-status-in-cpu-help.patch new file mode 100644 index 00000000..7821487e --- /dev/null +++ b/target-i386-display-deprecation-status-in-cpu-help.patch @@ -0,0 +1,42 @@ +From 7df11d09bea98ef7ef90518030ab6d694b832418 Mon Sep 17 00:00:00 2001 +From: tangbinzy +Date: Tue, 30 Apr 2024 09:04:20 +0000 +Subject: [PATCH] target/i386: display deprecation status in '-cpu help' + mainline inclusion commit 5dfa9e8689d08c529bf772fc199597efa947fa27 category: + bugfix +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +--------------------------------------------------------------- + +When the user queries CPU models via QMP there is a 'deprecated' flag +present, however, this is not done for the CLI '-cpu help' command. + +Reviewed-by: Cornelia Huck +Signed-off-by: Daniel P. Berrangé + +Signed-off-by: tangbinzy +--- + target/i386/cpu.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index 62ac5ed005..f4b010c249 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -5255,6 +5255,11 @@ static void x86_cpu_list_entry(gpointer data, gpointer user_data) + desc = g_strdup_printf("%s", model_id); + } + ++ if (cc->model && cc->model->cpudef->deprecation_note) { ++ g_autofree char *olddesc = desc; ++ desc = g_strdup_printf("%s (deprecated)", olddesc); ++ } ++ + qemu_printf("x86 %-20s %s\n", name, desc); + } + +-- +2.27.0 + diff --git a/target-ppc-Remove-msr_pr-macro.patch b/target-ppc-Remove-msr_pr-macro.patch new file mode 100644 index 00000000..b6cff378 --- /dev/null +++ b/target-ppc-Remove-msr_pr-macro.patch @@ -0,0 +1,236 @@ +From d83a066d969070373afe68f32f8584c66f2ee747 Mon Sep 17 00:00:00 2001 +From: dinglimin +Date: Sun, 9 Jun 2024 14:04:03 +0800 +Subject: [PATCH] target/ppc: Remove msr_pr macro cheery-pick from + d41ccf6eea918ec121cd38eda6e2526b446013f4 msr_pr macro hides the usage of + env->msr, which is a bad behavior Substitute it with FIELD_EX64 calls that + explicitly use env->msr as a parameter. +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Suggested-by: Richard Henderson +Signed-off-by: Víctor Colombo +Reviewed-by: Richard Henderson +Message-Id: <20220504210541.115256-4-victor.colombo@eldorado.org.br> +Signed-off-by: Daniel Henrique Barboza +Signed-off-by: dinglimin +--- + hw/ppc/pegasos2.c | 2 +- + hw/ppc/spapr.c | 2 +- + target/ppc/cpu.h | 4 +++- + target/ppc/cpu_init.c | 4 ++-- + target/ppc/excp_helper.c | 3 ++- + target/ppc/mem_helper.c | 5 +++-- + target/ppc/mmu-radix64.c | 5 +++-- + target/ppc/mmu_common.c | 24 +++++++++++++----------- + 8 files changed, 28 insertions(+), 21 deletions(-) + +diff --git a/hw/ppc/pegasos2.c b/hw/ppc/pegasos2.c +index 298e6b93e2..7b7eb38152 100644 +--- a/hw/ppc/pegasos2.c ++++ b/hw/ppc/pegasos2.c +@@ -457,7 +457,7 @@ static void pegasos2_hypercall(PPCVirtualHypervisor *vhyp, PowerPCCPU *cpu) + /* The TCG path should also be holding the BQL at this point */ + g_assert(qemu_mutex_iothread_locked()); + +- if (msr_pr) { ++ if (FIELD_EX64(env->msr, MSR, PR)) { + qemu_log_mask(LOG_GUEST_ERROR, "Hypercall made with MSR[PR]=1\n"); + env->gpr[3] = H_PRIVILEGE; + } else if (env->gpr[3] == KVMPPC_H_RTAS) { +diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c +index 7f352ceaaa..d1fbea16e3 100644 +--- a/hw/ppc/spapr.c ++++ b/hw/ppc/spapr.c +@@ -1268,7 +1268,7 @@ static void emulate_spapr_hypercall(PPCVirtualHypervisor *vhyp, + /* The TCG path should also be holding the BQL at this point */ + g_assert(qemu_mutex_iothread_locked()); + +- if (msr_pr) { ++ if (FIELD_EX64(env->msr, MSR, PR)) { + hcall_dprintf("Hypercall made with MSR[PR]=1\n"); + env->gpr[3] = H_PRIVILEGE; + } else { +diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h +index 26312f9d5f..8b214b2cc1 100644 +--- a/target/ppc/cpu.h ++++ b/target/ppc/cpu.h +@@ -24,6 +24,7 @@ + #include "exec/cpu-defs.h" + #include "cpu-qom.h" + #include "qom/object.h" ++#include "hw/registerfields.h" + + #define TCG_GUEST_DEFAULT_MO 0 + +@@ -343,6 +344,8 @@ typedef struct ppc_v3_pate_t { + #define MSR_RI 1 /* Recoverable interrupt 1 */ + #define MSR_LE 0 /* Little-endian mode 1 hflags */ + ++FIELD(MSR, PR, MSR_PR, 1) ++ + /* PMU bits */ + #define MMCR0_FC PPC_BIT(32) /* Freeze Counters */ + #define MMCR0_PMAO PPC_BIT(56) /* Perf Monitor Alert Occurred */ +@@ -443,7 +446,6 @@ typedef struct ppc_v3_pate_t { + #define msr_ce ((env->msr >> MSR_CE) & 1) + #define msr_ile ((env->msr >> MSR_ILE) & 1) + #define msr_ee ((env->msr >> MSR_EE) & 1) +-#define msr_pr ((env->msr >> MSR_PR) & 1) + #define msr_fp ((env->msr >> MSR_FP) & 1) + #define msr_me ((env->msr >> MSR_ME) & 1) + #define msr_fe0 ((env->msr >> MSR_FE0) & 1) +diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c +index 986d16a24d..d3b283dcd2 100644 +--- a/target/ppc/cpu_init.c ++++ b/target/ppc/cpu_init.c +@@ -7961,7 +7961,7 @@ static bool cpu_has_work_POWER9(CPUState *cs) + if ((env->pending_interrupts & (1u << PPC_INTERRUPT_EXT)) && + (env->spr[SPR_LPCR] & LPCR_EEE)) { + bool heic = !!(env->spr[SPR_LPCR] & LPCR_HEIC); +- if (heic == 0 || !msr_hv || msr_pr) { ++ if (!heic || !msr_hv || FIELD_EX64(env->msr, MSR, PR)) { + return true; + } + } +@@ -8170,7 +8170,7 @@ static bool cpu_has_work_POWER10(CPUState *cs) + if ((env->pending_interrupts & (1u << PPC_INTERRUPT_EXT)) && + (env->spr[SPR_LPCR] & LPCR_EEE)) { + bool heic = !!(env->spr[SPR_LPCR] & LPCR_HEIC); +- if (heic == 0 || !msr_hv || msr_pr) { ++ if (!heic || !msr_hv || FIELD_EX64(env->msr, MSR, PR)) { + return true; + } + } +diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c +index f66063d55c..3576e87b28 100644 +--- a/target/ppc/excp_helper.c ++++ b/target/ppc/excp_helper.c +@@ -976,7 +976,8 @@ static void ppc_hw_interrupt(CPUPPCState *env) + bool lpes0 = !!(env->spr[SPR_LPCR] & LPCR_LPES0); + bool heic = !!(env->spr[SPR_LPCR] & LPCR_HEIC); + /* HEIC blocks delivery to the hypervisor */ +- if ((async_deliver && !(heic && msr_hv && !msr_pr)) || ++ if ((async_deliver && !(heic && msr_hv && ++ !FIELD_EX64(env->msr, MSR, PR))) || + (env->has_hv_mode && msr_hv == 0 && !lpes0)) { + powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_EXTERNAL); + return; +diff --git a/target/ppc/mem_helper.c b/target/ppc/mem_helper.c +index 39945d9ea5..ceb4aa41d7 100644 +--- a/target/ppc/mem_helper.c ++++ b/target/ppc/mem_helper.c +@@ -613,10 +613,11 @@ void helper_tbegin(CPUPPCState *env) + (1ULL << TEXASR_FAILURE_PERSISTENT) | + (1ULL << TEXASR_NESTING_OVERFLOW) | + (msr_hv << TEXASR_PRIVILEGE_HV) | +- (msr_pr << TEXASR_PRIVILEGE_PR) | ++ (FIELD_EX64(env->msr, MSR, PR) << TEXASR_PRIVILEGE_PR) | + (1ULL << TEXASR_FAILURE_SUMMARY) | + (1ULL << TEXASR_TFIAR_EXACT); +- env->spr[SPR_TFIAR] = env->nip | (msr_hv << 1) | msr_pr; ++ env->spr[SPR_TFIAR] = env->nip | (msr_hv << 1) | ++ FIELD_EX64(env->msr, MSR, PR); + env->spr[SPR_TFHAR] = env->nip + 4; + env->crf[0] = 0xB; /* 0b1010 = transaction failure */ + } +diff --git a/target/ppc/mmu-radix64.c b/target/ppc/mmu-radix64.c +index 5b0e62e676..3f016730cd 100644 +--- a/target/ppc/mmu-radix64.c ++++ b/target/ppc/mmu-radix64.c +@@ -171,12 +171,13 @@ static bool ppc_radix64_check_prot(PowerPCCPU *cpu, MMUAccessType access_type, + } + + /* Determine permissions allowed by Encoded Access Authority */ +- if (!partition_scoped && (pte & R_PTE_EAA_PRIV) && msr_pr) { ++ if (!partition_scoped && (pte & R_PTE_EAA_PRIV) && ++ FIELD_EX64(env->msr, MSR, PR)) { + *prot = 0; + } else if (mmuidx_pr(mmu_idx) || (pte & R_PTE_EAA_PRIV) || + partition_scoped) { + *prot = ppc_radix64_get_prot_eaa(pte); +- } else { /* !msr_pr && !(pte & R_PTE_EAA_PRIV) && !partition_scoped */ ++ } else { /* !MSR_PR && !(pte & R_PTE_EAA_PRIV) && !partition_scoped */ + *prot = ppc_radix64_get_prot_eaa(pte); + *prot &= ppc_radix64_get_prot_amr(cpu); /* Least combined permissions */ + } +diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c +index 754509e556..fb1059bcf2 100644 +--- a/target/ppc/mmu_common.c ++++ b/target/ppc/mmu_common.c +@@ -292,8 +292,8 @@ static inline void bat_size_prot(CPUPPCState *env, target_ulong *blp, + bl = (*BATu & 0x00001FFC) << 15; + valid = 0; + prot = 0; +- if (((msr_pr == 0) && (*BATu & 0x00000002)) || +- ((msr_pr != 0) && (*BATu & 0x00000001))) { ++ if ((!FIELD_EX64(env->msr, MSR, PR) && (*BATu & 0x00000002)) || ++ (FIELD_EX64(env->msr, MSR, PR) && (*BATu & 0x00000001))) { + valid = 1; + pp = *BATl & 0x00000003; + if (pp != 0) { +@@ -386,16 +386,17 @@ static int get_segment_6xx_tlb(CPUPPCState *env, mmu_ctx_t *ctx, + PowerPCCPU *cpu = env_archcpu(env); + hwaddr hash; + target_ulong vsid; +- int ds, pr, target_page_bits; ++ int ds, target_page_bits; ++ bool pr; + int ret; + target_ulong sr, pgidx; + +- pr = msr_pr; ++ pr = FIELD_EX64(env->msr, MSR, PR); + ctx->eaddr = eaddr; + + sr = env->sr[eaddr >> 28]; +- ctx->key = (((sr & 0x20000000) && (pr != 0)) || +- ((sr & 0x40000000) && (pr == 0))) ? 1 : 0; ++ ctx->key = (((sr & 0x20000000) && pr) || ++ ((sr & 0x40000000) && !pr)) ? 1 : 0; + ds = sr & 0x80000000 ? 1 : 0; + ctx->nx = sr & 0x10000000 ? 1 : 0; + vsid = sr & 0x00FFFFFF; +@@ -404,8 +405,9 @@ static int get_segment_6xx_tlb(CPUPPCState *env, mmu_ctx_t *ctx, + "Check segment v=" TARGET_FMT_lx " %d " TARGET_FMT_lx + " nip=" TARGET_FMT_lx " lr=" TARGET_FMT_lx + " ir=%d dr=%d pr=%d %d t=%d\n", +- eaddr, (int)(eaddr >> 28), sr, env->nip, env->lr, (int)msr_ir, +- (int)msr_dr, pr != 0 ? 1 : 0, access_type == MMU_DATA_STORE, type); ++ eaddr, (int)(eaddr >> 28), sr, env->nip, env->lr, ++ (int)msr_ir, (int)msr_dr, pr ? 1 : 0, ++ access_type == MMU_DATA_STORE, type); + pgidx = (eaddr & ~SEGMENT_MASK_256M) >> target_page_bits; + hash = vsid ^ pgidx; + ctx->ptem = (vsid << 7) | (pgidx >> 10); +@@ -566,7 +568,7 @@ static int mmu40x_get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx, + + ret = -1; + raddr = (hwaddr)-1ULL; +- pr = msr_pr; ++ pr = FIELD_EX64(env->msr, MSR, PR); + for (i = 0; i < env->nb_tlb; i++) { + tlb = &env->tlb.tlbe[i]; + if (ppcemb_tlb_check(env, tlb, &raddr, address, +@@ -651,7 +653,7 @@ static int mmubooke_check_tlb(CPUPPCState *env, ppcemb_tlb_t *tlb, + + found_tlb: + +- if (msr_pr != 0) { ++ if (FIELD_EX64(env->msr, MSR, PR)) { + prot2 = tlb->prot & 0xF; + } else { + prot2 = (tlb->prot >> 4) & 0xF; +@@ -799,7 +801,7 @@ static bool mmubooke206_get_as(CPUPPCState *env, + return true; + } else { + *as_out = msr_ds; +- *pr_out = msr_pr; ++ *pr_out = FIELD_EX64(env->msr, MSR, PR); + return false; + } + } +-- +2.27.0 + diff --git a/target-s390x-display-deprecation-status-in-cpu-help.patch b/target-s390x-display-deprecation-status-in-cpu-help.patch new file mode 100644 index 00000000..2a639a0f --- /dev/null +++ b/target-s390x-display-deprecation-status-in-cpu-help.patch @@ -0,0 +1,67 @@ +From 054d100649c34dd4e5a13140b09b8c080e85ffde Mon Sep 17 00:00:00 2001 +From: tangbinzy +Date: Tue, 30 Apr 2024 09:24:09 +0000 +Subject: [PATCH] target/s390x: display deprecation status in '-cpu help' + mainline inclusion commit 738cdc2f6ea1ce22bb3f2a4e0fc84fc8121896fb category: + bugfix +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +--------------------------------------------------------------- + +When the user queries CPU models via QMP there is a 'deprecated' flag +present, however, this is not done for the CLI '-cpu help' command. + +Reviewed-by: Cornelia Huck +Signed-off-by: Daniel P. Berrangé + +Signed-off-by: tangbinzy +--- + target/s390x/cpu_models.c | 23 ++++++++++++++++++----- + 1 file changed, 18 insertions(+), 5 deletions(-) + +diff --git a/target/s390x/cpu_models.c b/target/s390x/cpu_models.c +index 11e06cc51f..65908c6d36 100644 +--- a/target/s390x/cpu_models.c ++++ b/target/s390x/cpu_models.c +@@ -334,18 +334,31 @@ const S390CPUDef *s390_find_cpu_def(uint16_t type, uint8_t gen, uint8_t ec_ga, + static void s390_print_cpu_model_list_entry(gpointer data, gpointer user_data) + { + const S390CPUClass *scc = S390_CPU_CLASS((ObjectClass *)data); ++ CPUClass *cc = CPU_CLASS(scc); + char *name = g_strdup(object_class_get_name((ObjectClass *)data)); +- const char *details = ""; ++ g_autoptr(GString) details = g_string_new(""); + + if (scc->is_static) { +- details = "(static, migration-safe)"; +- } else if (scc->is_migration_safe) { +- details = "(migration-safe)"; ++ g_string_append(details, "static, "); ++ } ++ if (scc->is_migration_safe) { ++ g_string_append(details, "migration-safe, "); ++ } ++ if (cc->deprecation_note) { ++ g_string_append(details, "deprecated, "); ++ } ++ if (details->len) { ++ /* cull trailing ', ' */ ++ g_string_truncate(details, details->len - 2); + } + + /* strip off the -s390x-cpu */ + g_strrstr(name, "-" TYPE_S390_CPU)[0] = 0; +- qemu_printf("s390 %-15s %-35s %s\n", name, scc->desc, details); ++ if (details->len) { ++ qemu_printf("s390 %-15s %-35s (%s)\n", name, scc->desc, details->str); ++ } else { ++ qemu_printf("s390 %-15s %-35s\n", name, scc->desc); ++ } + g_free(name); + } + +-- +2.27.0 + diff --git a/tpm_emulator-Avoid-double-initialization-during-migr.patch b/tpm_emulator-Avoid-double-initialization-during-migr.patch new file mode 100644 index 00000000..aff54f80 --- /dev/null +++ b/tpm_emulator-Avoid-double-initialization-during-migr.patch @@ -0,0 +1,58 @@ +From 65582eea0238d4b833934281fc6580a28cc82694 Mon Sep 17 00:00:00 2001 +From: tangbinzy +Date: Wed, 15 May 2024 01:33:59 +0000 +Subject: [PATCH] tpm_emulator: Avoid double initialization during migration + mainline inclusion commit a0bcec03761477371ff7c2e80dc07fff14222d92 category: + bugfix +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +--------------------------------------------------------------- + +When resuming after a migration, the backend sends CMD_INIT to the +emulator from the startup callback, then it sends the migration state +from the vmstate to the emulator, then it sends CMD_INIT again. Skip the +first CMD_INIT during a migration to avoid initializing the TPM twice. + +Signed-off-by: Ross Lagerwall +Reviewed-by: Marc-André Lureau +Tested-by: Stefan Berger +Signed-off-by: Stefan Berger + +Signed-off-by: tangbinzy +--- + backends/tpm/tpm_emulator.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/backends/tpm/tpm_emulator.c b/backends/tpm/tpm_emulator.c +index 87d061e9bb..9b50c5b3e2 100644 +--- a/backends/tpm/tpm_emulator.c ++++ b/backends/tpm/tpm_emulator.c +@@ -32,6 +32,7 @@ + #include "qemu/sockets.h" + #include "qemu/lockable.h" + #include "io/channel-socket.h" ++#include "sysemu/runstate.h" + #include "sysemu/tpm_backend.h" + #include "sysemu/tpm_util.h" + #include "tpm_int.h" +@@ -383,6 +384,15 @@ err_exit: + + static int tpm_emulator_startup_tpm(TPMBackend *tb, size_t buffersize) + { ++ /* TPM startup will be done from post_load hook */ ++ if (runstate_check(RUN_STATE_INMIGRATE)) { ++ if (buffersize != 0) { ++ return tpm_emulator_set_buffer_size(tb, buffersize, NULL); ++ } ++ ++ return 0; ++ } ++ + return tpm_emulator_startup_tpm_resume(tb, buffersize, false); + } + +-- +2.27.0 + diff --git a/vfio-pci-Add-Ascend310b-scend910b-support.patch b/vfio-pci-Add-Ascend310b-scend910b-support.patch new file mode 100644 index 00000000..197bd0ca --- /dev/null +++ b/vfio-pci-Add-Ascend310b-scend910b-support.patch @@ -0,0 +1,134 @@ +From 0cc777f65565e77100e0a767f6165217246b0226 Mon Sep 17 00:00:00 2001 +From: yuxiating +Date: Tue, 14 May 2024 11:19:02 +0800 +Subject: [PATCH] vfio/pci: Add Ascend310b scend910b support + +Reference:https://support.huawei.com/enterprise/zh/doc/EDOC1100349016/63b881f2 + +Signed-off-by: yuxiating +--- + hw/vfio/pci-quirks.c | 72 ++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 72 insertions(+) + +diff --git a/hw/vfio/pci-quirks.c b/hw/vfio/pci-quirks.c +index a911e04a79..d83ed21387 100644 +--- a/hw/vfio/pci-quirks.c ++++ b/hw/vfio/pci-quirks.c +@@ -1211,7 +1211,9 @@ int vfio_pci_igd_opregion_init(VFIOPCIDevice *vdev, + + #define PCI_VENDOR_ID_HUAWEI 0x19e5 + #define PCI_DEVICE_ID_ASCEND910 0xd801 ++#define PCI_DEVICE_ID_ASCEND910B 0xd802 + #define PCI_DEVICE_ID_ASCEND710 0xd500 ++#define PCI_DEVICE_ID_ASCEND310B 0xd105 + #define PCI_DEVICE_ID_ASCEND310 0xd100 + #define PCI_SUB_DEVICE_ID_ASCEND710_1P_MIN 0x100 + #define PCI_SUB_DEVICE_ID_ASCEND710_1P_MAX 0x10f +@@ -1219,11 +1221,15 @@ int vfio_pci_igd_opregion_init(VFIOPCIDevice *vdev, + #define PCI_SUB_DEVICE_ID_ASCEND710_2P_MAX 0x11f + #define ASCEND910_XLOADER_SIZE 4 + #define ASCEND910_XLOADER_OFFSET 0x80400 ++#define ASCEND910B_XLOADER_SIZE 4 ++#define ASCEND910B_XLOADER_OFFSET 0x18208430 + #define ASCEND710_2P_BASE (128 * 1024 * 1024) + #define ASCEND710_1P_DEVNUM 1 + #define ASCEND710_2P_DEVNUM 2 + #define ASCEND710_XLOADER_SIZE 4 + #define ASCEND710_XLOADER_OFFSET 0x100430 ++#define ASCEND310B_XLOADER_SIZE 4 ++#define ASCEND310B_XLOADER_OFFSET 0x4430 + #define ASCEND310_XLOADER_SIZE 4 + #define ASCEND310_XLOADER_OFFSET 0x400 + +@@ -1263,6 +1269,38 @@ static const MemoryRegionOps vfio_ascend_intercept_regs_quirk = { + .endianness = DEVICE_LITTLE_ENDIAN, + }; + ++static void vfio_probe_ascend910b_bar2_quirk(VFIOPCIDevice *vdev, int nr) ++{ ++ VFIOQuirk *quirk; ++ VFIOAscendBarQuirk *bar2_quirk; ++ ++ if (vdev->vendor_id != PCI_VENDOR_ID_HUAWEI || nr != 2 ++ || vdev->device_id != PCI_DEVICE_ID_ASCEND910B) { ++ return; ++ } ++ ++ quirk = g_malloc0(sizeof(*quirk)); ++ quirk->nr_mem = 1; ++ quirk->mem = g_new0(MemoryRegion, quirk->nr_mem); ++ bar2_quirk = quirk->data = g_new0(typeof(*bar2_quirk), quirk->nr_mem); ++ bar2_quirk[0].vdev = vdev; ++ bar2_quirk[0].offset = ASCEND910B_XLOADER_OFFSET; ++ bar2_quirk[0].bar = nr; ++ ++ /* intercept w/r to the xloader-updating register, ++ * so the vm can't enable xloader-updating ++ */ ++ memory_region_init_io(&quirk->mem[0], OBJECT(vdev), ++ &vfio_ascend_intercept_regs_quirk, ++ &bar2_quirk[0], ++ "vfio-ascend910b-bar2-intercept-regs-quirk", ++ ASCEND910B_XLOADER_SIZE); ++ memory_region_add_subregion_overlap(vdev->bars[nr].region.mem, ++ bar2_quirk[0].offset, ++ &quirk->mem[0], 1); ++ QLIST_INSERT_HEAD(&vdev->bars[nr].quirks, quirk, next); ++} ++ + static void vfio_probe_ascend910_bar0_quirk(VFIOPCIDevice *vdev, int nr) + { + VFIOQuirk *quirk; +@@ -1360,6 +1398,38 @@ static void vfio_probe_ascend710_bar2_quirk(VFIOPCIDevice *vdev, int nr) + QLIST_INSERT_HEAD(&vdev->bars[nr].quirks, quirk, next); + } + ++static void vfio_probe_ascend310b_bar2_quirk(VFIOPCIDevice *vdev, int nr) ++{ ++ VFIOQuirk *quirk; ++ VFIOAscendBarQuirk *bar2_quirk; ++ ++ if (vdev->vendor_id != PCI_VENDOR_ID_HUAWEI || nr != 2 ++ || vdev->device_id != PCI_DEVICE_ID_ASCEND310B) { ++ return; ++ } ++ ++ quirk = g_malloc0(sizeof(*quirk)); ++ quirk->nr_mem = 1; ++ quirk->mem = g_new0(MemoryRegion, quirk->nr_mem); ++ bar2_quirk = quirk->data = g_new0(typeof(*bar2_quirk), quirk->nr_mem); ++ bar2_quirk[0].vdev = vdev; ++ bar2_quirk[0].offset = ASCEND310B_XLOADER_OFFSET; ++ bar2_quirk[0].bar = nr; ++ ++ /* intercept w/r to the xloader-updating register, ++ * so the vm can't enable xloader-updating ++ */ ++ memory_region_init_io(&quirk->mem[0], OBJECT(vdev), ++ &vfio_ascend_intercept_regs_quirk, ++ &bar2_quirk[0], ++ "vfio-ascend310b-bar2-intercept-regs-quirk", ++ ASCEND310B_XLOADER_SIZE); ++ memory_region_add_subregion_overlap(vdev->bars[nr].region.mem, ++ bar2_quirk[0].offset, ++ &quirk->mem[0], 1); ++ QLIST_INSERT_HEAD(&vdev->bars[nr].quirks, quirk, next); ++} ++ + static void vfio_probe_ascend310_bar4_quirk(VFIOPCIDevice *vdev, int nr) + { + VFIOQuirk *quirk; +@@ -1445,8 +1515,10 @@ void vfio_bar_quirk_setup(VFIOPCIDevice *vdev, int nr) + #ifdef CONFIG_VFIO_IGD + vfio_probe_igd_bar4_quirk(vdev, nr); + #endif ++ vfio_probe_ascend910b_bar2_quirk(vdev, nr); + vfio_probe_ascend910_bar0_quirk(vdev, nr); + vfio_probe_ascend710_bar2_quirk(vdev, nr); ++ vfio_probe_ascend310b_bar2_quirk(vdev, nr); + vfio_probe_ascend310_bar4_quirk(vdev, nr); + } + +-- +2.27.0 + -- Gitee From 77124461a97c48ebae480617aa9474ae1083a2c3 Mon Sep 17 00:00:00 2001 From: Jiabo Feng Date: Sat, 15 Jun 2024 09:23:23 +0800 Subject: [PATCH 10/19] QEMU update to version 8.2.0-93: - cvm: bug-fix for macro isolation - tests/qtest: ahci-test: add test exposing reset issue with pending callback (Fix CVE-2023-5088) - hw/ide: reset: cancel async DMA operation before resetting state (Fix CVE-2023-5088) - Add support for the virtcca cvm feature. Signed-off-by: Jiabo Feng (cherry picked from commit 018c8095574117546ef4dfde1b4c0bc6d77a1e4e) --- Add-support-for-the-virtcca-cvm-feature.patch | 994 ++++++++++++++++++ cvm-bug-fix-for-macro-isolation.patch | 48 + ...cel-async-DMA-operation-before-reset.patch | 110 ++ qemu.spec | 12 +- ...-test-add-test-exposing-reset-issue-.patch | 132 +++ 5 files changed, 1295 insertions(+), 1 deletion(-) create mode 100644 Add-support-for-the-virtcca-cvm-feature.patch create mode 100644 cvm-bug-fix-for-macro-isolation.patch create mode 100644 hw-ide-reset-cancel-async-DMA-operation-before-reset.patch create mode 100644 tests-qtest-ahci-test-add-test-exposing-reset-issue-.patch diff --git a/Add-support-for-the-virtcca-cvm-feature.patch b/Add-support-for-the-virtcca-cvm-feature.patch new file mode 100644 index 00000000..f365ce8a --- /dev/null +++ b/Add-support-for-the-virtcca-cvm-feature.patch @@ -0,0 +1,994 @@ +From 12d0d099aecbebefc7d221ae645283984bf8f649 Mon Sep 17 00:00:00 2001 +From: liupingwei +Date: Fri, 31 May 2024 15:07:20 +0800 +Subject: [PATCH] Add support for the virtcca cvm feature. With this commit,we + can append new startup parameters :"cma=64M cvm_guest=1" and "kvm_type=cvm" + to use virtcca cvm feature. Here is a full example of the append parameters + for a cvm : -M virt,gic-version=3,accel=kvm,kernel_irqchip=on,kvm_type=cvm \ + -append "swiotlb=force console=tty0 console=ttyAMA0 kaslr.disabled=1 cma=64M + cvm_guest=1 rodata=off rootfstype=ext4 root=/dev/vad rw" \ + +Additionally,the SVE and PMU are optional configurations for cvm,here is +an example: +-object tmm-guest,id=tmm0,sve-vector-length=128,num-pmu-counters=1 +Signed-off-by: liupingwei +--- + accel/kvm/kvm-all.c | 36 ++++ + hw/arm/boot.c | 49 +++++ + hw/arm/virt.c | 51 ++++- + include/hw/arm/boot.h | 1 + + include/hw/arm/virt.h | 1 + + include/sysemu/kvm.h | 8 + + linux-headers/asm-arm64/kvm.h | 62 ++++++ + linux-headers/linux/kvm.h | 31 ++- + qapi/qom.json | 30 ++- + target/arm/kvm-tmm.c | 344 ++++++++++++++++++++++++++++++++++ + target/arm/kvm.c | 6 +- + target/arm/kvm64.c | 5 + + target/arm/kvm_arm.h | 10 + + target/arm/meson.build | 1 + + 14 files changed, 628 insertions(+), 7 deletions(-) + create mode 100644 target/arm/kvm-tmm.c + +diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c +index e55b2b6a16..381e3c8552 100644 +--- a/accel/kvm/kvm-all.c ++++ b/accel/kvm/kvm-all.c +@@ -49,6 +49,8 @@ + + #include "hw/boards.h" + ++#include "sysemu/kvm.h" ++ + /* This check must be after config-host.h is included */ + #ifdef CONFIG_EVENTFD + #include +@@ -79,6 +81,9 @@ struct KVMParkedVcpu { + }; + + KVMState *kvm_state; ++ ++bool virtcca_cvm_allowed = false; ++ + bool kvm_kernel_irqchip; + bool kvm_split_irqchip; + bool kvm_async_interrupts_allowed; +@@ -2272,6 +2277,11 @@ uint32_t kvm_dirty_ring_size(void) + return kvm_state->kvm_dirty_ring_size; + } + ++static inline bool kvm_is_virtcca_cvm_type(int type) ++{ ++ return type & VIRTCCA_CVM_TYPE; ++} ++ + static int kvm_init(MachineState *ms) + { + MachineClass *mc = MACHINE_GET_CLASS(ms); +@@ -2356,6 +2366,10 @@ static int kvm_init(MachineState *ms) + type = mc->kvm_type(ms, NULL); + } + ++ if (kvm_is_virtcca_cvm_type(type)) { ++ virtcca_cvm_allowed = true; ++ } ++ + do { + ret = kvm_ioctl(s, KVM_CREATE_VM, type); + } while (ret == -EINTR); +@@ -3455,6 +3469,28 @@ int kvm_get_one_reg(CPUState *cs, uint64_t id, void *target) + return r; + } + ++int kvm_load_user_data(hwaddr loader_start, hwaddr image_end, hwaddr initrd_start, hwaddr dtb_end, hwaddr ram_size, ++ struct kvm_numa_info *numa_info) ++{ ++ KVMState *state = kvm_state; ++ struct kvm_user_data data; ++ int ret; ++ ++ data.loader_start = loader_start; ++ data.image_end = image_end; ++ data.initrd_start = initrd_start; ++ data.dtb_end = dtb_end; ++ data.ram_size = ram_size; ++ memcpy(&data.numa_info, numa_info, sizeof(struct kvm_numa_info)); ++ ++ ret = kvm_vm_ioctl(state, KVM_LOAD_USER_DATA, &data); ++ if (ret < 0) { ++ error_report("%s: KVM_LOAD_USER_DATA failed!\n", __func__); ++ } ++ ++ return ret; ++} ++ + static bool kvm_accel_has_memory(MachineState *ms, AddressSpace *as, + hwaddr start_addr, hwaddr size) + { +diff --git a/hw/arm/boot.c b/hw/arm/boot.c +index 3d45de1772..db69ec648a 100644 +--- a/hw/arm/boot.c ++++ b/hw/arm/boot.c +@@ -27,6 +27,7 @@ + #include "qemu/config-file.h" + #include "qemu/option.h" + #include "qemu/units.h" ++#include "kvm_arm.h" + + /* Kernel boot protocol is specified in the kernel docs + * Documentation/arm/Booting and Documentation/arm64/booting.txt +@@ -1255,6 +1256,16 @@ static void arm_setup_direct_kernel_boot(ARMCPU *cpu, + for (cs = first_cpu; cs; cs = CPU_NEXT(cs)) { + ARM_CPU(cs)->env.boot_info = info; + } ++ ++ if (kvm_enabled() && virtcca_cvm_enabled()) { ++ if (info->dtb_limit == 0) { ++ info->dtb_limit = info->dtb_start + 0x200000; ++ } ++ kvm_load_user_data(info->loader_start, image_high_addr, info->initrd_start, ++ info->dtb_limit, info->ram_size, (struct kvm_numa_info *)info->numa_info); ++ tmm_add_ram_region(info->loader_start, image_high_addr - info->loader_start, ++ info->initrd_start, info->dtb_limit - info->initrd_start, true); ++ } + } + + static void arm_setup_firmware_boot(ARMCPU *cpu, struct arm_boot_info *info) +@@ -1344,6 +1355,39 @@ void arm_load_kernel(ARMCPU *cpu, MachineState *ms, struct arm_boot_info *info) + info->initrd_filename = ms->initrd_filename; + info->dtb_filename = ms->dtb; + info->dtb_limit = 0; ++ if (kvm_enabled() && virtcca_cvm_enabled()) { ++ info->ram_size = ms->ram_size; ++ info->numa_info = g_malloc(sizeof(struct kvm_numa_info)); ++ struct kvm_numa_info *numa_info = (struct kvm_numa_info *) info->numa_info; ++ if (ms->numa_state != NULL && ms->numa_state->num_nodes > 0) { ++ numa_info->numa_cnt = ms->numa_state->num_nodes; ++ uint64_t mem_base = info->loader_start; ++ for (int64_t i = 0; i < ms->numa_state->num_nodes && i < MAX_NUMA_NODE; i++) { ++ uint64_t mem_len = ms->numa_state->nodes[i].node_mem; ++ numa_info->numa_nodes[i].numa_id = i; ++ numa_info->numa_nodes[i].ipa_start = mem_base; ++ numa_info->numa_nodes[i].ipa_size = mem_len; ++ memcpy(numa_info->numa_nodes[i].host_numa_nodes, ms->numa_state->nodes[i].node_memdev->host_nodes, ++ MAX_NODES / BITS_PER_LONG * sizeof(uint64_t)); ++ mem_base += mem_len; ++ } ++ } else { ++ numa_info->numa_cnt = 1; ++ numa_info->numa_nodes[0].numa_id = 0; ++ numa_info->numa_nodes[0].ipa_start = info->loader_start; ++ numa_info->numa_nodes[0].ipa_size = info->ram_size; ++ memset(numa_info->numa_nodes[0].host_numa_nodes, 0, MAX_NODES / BITS_PER_LONG * sizeof(uint64_t)); ++ } ++ ++ for (int cpu = ms->smp.cpus - 1; cpu >= 0; cpu--) { ++ ARMCPU *armcpu = ARM_CPU(qemu_get_cpu(cpu)); ++ CPUState *cs = CPU(armcpu); ++ uint64_t node_id = 0; ++ if (ms->possible_cpus->cpus[cs->cpu_index].props.has_node_id) ++ node_id = ms->possible_cpus->cpus[cs->cpu_index].props.node_id; ++ bitmap_set((unsigned long *)numa_info->numa_nodes[node_id].cpu_id, cpu, 1); ++ } ++ } + + /* Load the kernel. */ + if (!info->kernel_filename || info->firmware_loaded) { +@@ -1352,6 +1396,11 @@ void arm_load_kernel(ARMCPU *cpu, MachineState *ms, struct arm_boot_info *info) + arm_setup_direct_kernel_boot(cpu, info); + } + ++ if (kvm_enabled() && virtcca_cvm_enabled()) { ++ g_free(info->numa_info); ++ info->numa_info = NULL; ++ } ++ + if (!info->skip_dtb_autoload && have_dtb(info)) { + if (arm_load_dtb(info->dtb_start, info, info->dtb_limit, as, ms) < 0) { + exit(1); +diff --git a/hw/arm/virt.c b/hw/arm/virt.c +index 93554cccf1..26dc5681c2 100644 +--- a/hw/arm/virt.c ++++ b/hw/arm/virt.c +@@ -1801,6 +1801,19 @@ static void virt_set_memmap(VirtMachineState *vms) + vms->memmap[i] = base_memmap[i]; + } + ++ /* fix VIRT_MEM range */ ++ if (object_property_find(OBJECT(current_machine), "kvm-type")) { ++ g_autofree char *kvm_type = object_property_get_str(OBJECT(current_machine), ++ "kvm-type", &error_abort); ++ ++ if (!strcmp(kvm_type, "cvm")) { ++ vms->memmap[VIRT_MEM].base = 3 * GiB; ++ vms->memmap[VIRT_MEM].size = ms->ram_size; ++ info_report("[qemu] fix VIRT_MEM range 0x%llx - 0x%llx\n", (unsigned long long)(vms->memmap[VIRT_MEM].base), ++ (unsigned long long)(vms->memmap[VIRT_MEM].base + ms->ram_size)); ++ } ++ } ++ + if (ms->ram_slots > ACPI_MAX_RAM_SLOTS) { + error_report("unsupported number of memory slots: %"PRIu64, + ms->ram_slots); +@@ -2072,7 +2085,7 @@ static void machvirt_init(MachineState *machine) + */ + if (vms->secure && firmware_loaded) { + vms->psci_conduit = QEMU_PSCI_CONDUIT_DISABLED; +- } else if (vms->virt) { ++ } else if (vms->virt || virtcca_cvm_enabled()) { + vms->psci_conduit = QEMU_PSCI_CONDUIT_SMC; + } else { + vms->psci_conduit = QEMU_PSCI_CONDUIT_HVC; +@@ -2118,6 +2131,13 @@ static void machvirt_init(MachineState *machine) + exit(1); + } + ++ if (virtcca_cvm_enabled()) { ++ int ret = kvm_arm_tmm_init(machine->cgs, &error_fatal); ++ if (ret != 0) { ++ error_report("fail to initialize TMM"); ++ exit(1); ++ } ++ } + create_fdt(vms); + qemu_log("cpu init start\n"); + +@@ -2991,6 +3011,15 @@ static HotplugHandler *virt_machine_get_hotplug_handler(MachineState *machine, + static int virt_kvm_type(MachineState *ms, const char *type_str) + { + VirtMachineState *vms = VIRT_MACHINE(ms); ++ int virtcca_cvm_type = 0; ++ if (object_property_find(OBJECT(current_machine), "kvm-type")) { ++ g_autofree char *kvm_type = object_property_get_str(OBJECT(current_machine), ++ "kvm-type", &error_abort); ++ ++ if (!strcmp(kvm_type, "cvm")) { ++ virtcca_cvm_type = VIRTCCA_CVM_TYPE; ++ } ++ } + int max_vm_pa_size, requested_pa_size; + bool fixed_ipa; + +@@ -3020,7 +3049,9 @@ static int virt_kvm_type(MachineState *ms, const char *type_str) + * the implicit legacy 40b IPA setting, in which case the kvm_type + * must be 0. + */ +- return fixed_ipa ? 0 : requested_pa_size; ++ return strcmp(type_str, "cvm") == 0 ? ++ ((fixed_ipa ? 0 : requested_pa_size) | virtcca_cvm_type) : ++ (fixed_ipa ? 0 : requested_pa_size); + } + + static void virt_machine_class_init(ObjectClass *oc, void *data) +@@ -3143,6 +3174,19 @@ static void virt_machine_class_init(ObjectClass *oc, void *data) + + } + ++static char *virt_get_kvm_type(Object *obj, Error **errp G_GNUC_UNUSED) ++{ ++ VirtMachineState *vms = VIRT_MACHINE(obj); ++ return g_strdup(vms->kvm_type); ++} ++ ++static void virt_set_kvm_type(Object *obj, const char *value, Error **errp G_GNUC_UNUSED) ++{ ++ VirtMachineState *vms = VIRT_MACHINE(obj); ++ g_free(vms->kvm_type); ++ vms->kvm_type = g_strdup(value); ++} ++ + static void virt_instance_init(Object *obj) + { + VirtMachineState *vms = VIRT_MACHINE(obj); +@@ -3194,6 +3238,9 @@ static void virt_instance_init(Object *obj) + + vms->oem_id = g_strndup(ACPI_BUILD_APPNAME6, 6); + vms->oem_table_id = g_strndup(ACPI_BUILD_APPNAME8, 8); ++ ++ object_property_add_str(obj, "kvm-type", virt_get_kvm_type, virt_set_kvm_type); ++ object_property_set_description(obj, "kvm-type", "CVM or Normal VM"); + } + + static const TypeInfo virt_machine_info = { +diff --git a/include/hw/arm/boot.h b/include/hw/arm/boot.h +index c3c4d3ea79..36aa5dd5c6 100644 +--- a/include/hw/arm/boot.h ++++ b/include/hw/arm/boot.h +@@ -36,6 +36,7 @@ void armv7m_load_kernel(ARMCPU *cpu, const char *kernel_filename, int mem_size); + /* arm_boot.c */ + struct arm_boot_info { + uint64_t ram_size; ++ void *numa_info; + const char *kernel_filename; + const char *kernel_cmdline; + const char *initrd_filename; +diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h +index 4ddee19b18..3fc1adcb42 100644 +--- a/include/hw/arm/virt.h ++++ b/include/hw/arm/virt.h +@@ -176,6 +176,7 @@ struct VirtMachineState { + PCIBus *bus; + char *oem_id; + char *oem_table_id; ++ char *kvm_type; + }; + + #define VIRT_ECAM_ID(high) (high ? VIRT_HIGH_PCIE_ECAM : VIRT_PCIE_ECAM) +diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h +index 9f52d08ce0..0b5319b4e3 100644 +--- a/include/sysemu/kvm.h ++++ b/include/sysemu/kvm.h +@@ -19,6 +19,7 @@ + #include "exec/memattrs.h" + #include "qemu/accel.h" + #include "qom/object.h" ++#include "linux-headers/linux/kvm.h" + + #ifdef NEED_CPU_H + # ifdef CONFIG_KVM +@@ -32,6 +33,7 @@ + #ifdef CONFIG_KVM_IS_POSSIBLE + + extern bool kvm_allowed; ++extern bool virtcca_cvm_allowed; + extern bool kvm_kernel_irqchip; + extern bool kvm_split_irqchip; + extern bool kvm_async_interrupts_allowed; +@@ -48,6 +50,8 @@ extern bool kvm_ioeventfd_any_length_allowed; + extern bool kvm_msi_use_devid; + + #define kvm_enabled() (kvm_allowed) ++#define virtcca_cvm_enabled() (virtcca_cvm_allowed) ++#define VIRTCCA_CVM_TYPE (1UL << 8) + /** + * kvm_irqchip_in_kernel: + * +@@ -170,6 +174,7 @@ extern bool kvm_msi_use_devid; + #else + + #define kvm_enabled() (0) ++#define virtcca_cvm_enabled() (0) + #define kvm_irqchip_in_kernel() (false) + #define kvm_irqchip_is_split() (false) + #define kvm_async_interrupts_enabled() (false) +@@ -554,6 +559,9 @@ bool kvm_dirty_ring_enabled(void); + + uint32_t kvm_dirty_ring_size(void); + ++int kvm_load_user_data(hwaddr loader_start, hwaddr image_end, hwaddr initrd_start, hwaddr dtb_end, hwaddr ram_size, ++ struct kvm_numa_info *numa_info); ++ + #ifdef __aarch64__ + int kvm_create_shadow_device(PCIDevice *dev); + int kvm_delete_shadow_device(PCIDevice *dev); +diff --git a/linux-headers/asm-arm64/kvm.h b/linux-headers/asm-arm64/kvm.h +index 3d2ce9912d..4e98a829f7 100644 +--- a/linux-headers/asm-arm64/kvm.h ++++ b/linux-headers/asm-arm64/kvm.h +@@ -106,6 +106,7 @@ struct kvm_regs { + #define KVM_ARM_VCPU_SVE 4 /* enable SVE for this CPU */ + #define KVM_ARM_VCPU_PTRAUTH_ADDRESS 5 /* VCPU uses address authentication */ + #define KVM_ARM_VCPU_PTRAUTH_GENERIC 6 /* VCPU uses generic authentication */ ++#define KVM_ARM_VCPU_TEC 8 /* VCPU TEC state as part of cvm */ + + struct kvm_vcpu_init { + __u32 target; +@@ -411,6 +412,67 @@ struct kvm_arm_copy_mte_tags { + #define KVM_PSCI_RET_INVAL PSCI_RET_INVALID_PARAMS + #define KVM_PSCI_RET_DENIED PSCI_RET_DENIED + ++/* KVM_CAP_ARM_TMM on VM fd */ ++#define KVM_CAP_ARM_TMM_CONFIG_CVM 0 ++#define KVM_CAP_ARM_TMM_CREATE_RD 1 ++#define KVM_CAP_ARM_TMM_POPULATE_CVM 2 ++#define KVM_CAP_ARM_TMM_ACTIVATE_CVM 3 ++ ++#define KVM_CAP_ARM_TMM_MEASUREMENT_ALGO_SHA256 0 ++#define KVM_CAP_ARM_TMM_MEASUREMENT_ALGO_SHA512 1 ++ ++#define KVM_CAP_ARM_TMM_RPV_SIZE 64 ++ ++/* List of configuration items accepted for KVM_CAP_ARM_RME_CONFIG_REALM */ ++#define KVM_CAP_ARM_TMM_CFG_RPV 0 ++#define KVM_CAP_ARM_TMM_CFG_HASH_ALGO 1 ++#define KVM_CAP_ARM_TMM_CFG_SVE 2 ++#define KVM_CAP_ARM_TMM_CFG_DBG 3 ++#define KVM_CAP_ARM_TMM_CFG_PMU 4 ++ ++struct kvm_cap_arm_tmm_config_item { ++ __u32 cfg; ++ union { ++ /* cfg == KVM_CAP_ARM_TMM_CFG_RPV */ ++ struct { ++ __u8 rpv[KVM_CAP_ARM_TMM_RPV_SIZE]; ++ }; ++ ++ /* cfg == KVM_CAP_ARM_TMM_CFG_HASH_ALGO */ ++ struct { ++ __u32 hash_algo; ++ }; ++ ++ /* cfg == KVM_CAP_ARM_TMM_CFG_SVE */ ++ struct { ++ __u32 sve_vq; ++ }; ++ ++ /* cfg == KVM_CAP_ARM_TMM_CFG_DBG */ ++ struct { ++ __u32 num_brps; ++ __u32 num_wrps; ++ }; ++ ++ /* cfg == KVM_CAP_ARM_TMM_CFG_PMU */ ++ struct { ++ __u32 num_pmu_cntrs; ++ }; ++ /* Fix the size of the union */ ++ __u8 reserved[256]; ++ }; ++}; ++ ++#define KVM_ARM_TMM_POPULATE_FLAGS_MEASURE (1U << 0) ++struct kvm_cap_arm_tmm_populate_region_args { ++ __u64 populate_ipa_base1; ++ __u64 populate_ipa_size1; ++ __u64 populate_ipa_base2; ++ __u64 populate_ipa_size2; ++ __u32 flags; ++ __u32 reserved[3]; ++}; ++ + #endif + + #endif /* __ARM_KVM_H__ */ +diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h +index cd0885f523..fa22d85adf 100644 +--- a/linux-headers/linux/kvm.h ++++ b/linux-headers/linux/kvm.h +@@ -14,6 +14,8 @@ + #include + #include + ++#include "sysemu/numa.h" ++ + #define KVM_API_VERSION 12 + + /* *** Deprecated interfaces *** */ +@@ -1126,6 +1128,7 @@ struct kvm_ppc_resize_hpt { + #define KVM_CAP_X86_NOTIFY_VMEXIT 219 + + #define KVM_CAP_ARM_CPU_FEATURE 555 ++#define KVM_CAP_ARM_TMM 300 + + #define KVM_CAP_ARM_VIRT_MSI_BYPASS 799 + +@@ -1370,6 +1373,32 @@ struct kvm_vfio_spapr_tce { + __s32 tablefd; + }; + ++#define MAX_NUMA_NODE 8 ++#define MAX_CPU_BIT_MAP 4 ++#define MAX_NODE_BIT_MAP (MAX_NODES / BITS_PER_LONG) ++ ++struct kvm_numa_node { ++ __u64 numa_id; ++ __u64 ipa_start; ++ __u64 ipa_size; ++ __u64 host_numa_nodes[MAX_NODE_BIT_MAP]; ++ __u64 cpu_id[MAX_CPU_BIT_MAP]; ++}; ++ ++struct kvm_numa_info { ++ __u64 numa_cnt; ++ struct kvm_numa_node numa_nodes[MAX_NUMA_NODE]; ++}; ++ ++struct kvm_user_data { ++ __u64 loader_start; ++ __u64 image_end; ++ __u64 initrd_start; ++ __u64 dtb_end; ++ __u64 ram_size; ++ struct kvm_numa_info numa_info; ++}; ++ + /* + * ioctls for VM fds + */ +@@ -1388,7 +1417,7 @@ struct kvm_vfio_spapr_tce { + struct kvm_userspace_memory_region) + #define KVM_SET_TSS_ADDR _IO(KVMIO, 0x47) + #define KVM_SET_IDENTITY_MAP_ADDR _IOW(KVMIO, 0x48, __u64) +- ++#define KVM_LOAD_USER_DATA _IOW(KVMIO, 0x49, struct kvm_user_data) + /* enable ucontrol for s390 */ + struct kvm_s390_ucas_mapping { + __u64 user_addr; +diff --git a/qapi/qom.json b/qapi/qom.json +index eeb5395ff3..a0450f7494 100644 +--- a/qapi/qom.json ++++ b/qapi/qom.json +@@ -785,6 +785,30 @@ + 'reduced-phys-bits': 'uint32', + '*kernel-hashes': 'bool' } } + ++## ++# @TmmGuestMeasurementAlgo: ++# ++# Algorithm to use for cvm measurements ++# ++# Since: FIXME ++## ++{ 'enum': 'TmmGuestMeasurementAlgo', ++'data': ['default', 'sha256', 'sha512'] } ++ ++## ++# @TmmGuestProperties: ++# ++# Properties for tmm-guest objects. ++# ++# @sve-vector-length: SVE vector length (default: 0, SVE disabled) ++# ++# Since: FIXME ++## ++{ 'struct': 'TmmGuestProperties', ++ 'data': { '*sve-vector-length': 'uint32', ++ '*num-pmu-counters': 'uint32', ++ '*measurement-algo': 'TmmGuestMeasurementAlgo' } } ++ + ## + # @ObjectType: + # +@@ -842,7 +866,8 @@ + 'tls-creds-psk', + 'tls-creds-x509', + 'tls-cipher-suites', +- { 'name': 'x-remote-object', 'features': [ 'unstable' ] } ++ { 'name': 'x-remote-object', 'features': [ 'unstable' ] }, ++ 'tmm-guest' + ] } + + ## +@@ -905,7 +930,8 @@ + 'tls-creds-psk': 'TlsCredsPskProperties', + 'tls-creds-x509': 'TlsCredsX509Properties', + 'tls-cipher-suites': 'TlsCredsProperties', +- 'x-remote-object': 'RemoteObjectProperties' ++ 'x-remote-object': 'RemoteObjectProperties', ++ 'tmm-guest': 'TmmGuestProperties' + } } + + ## +diff --git a/target/arm/kvm-tmm.c b/target/arm/kvm-tmm.c +new file mode 100644 +index 0000000000..e7df485979 +--- /dev/null ++++ b/target/arm/kvm-tmm.c +@@ -0,0 +1,344 @@ ++/* ++ * QEMU add virtcca cvm feature. ++ * ++ * Copyright (c) Huawei Technologies Co., Ltd. 2023-2024. All rights reserved. ++ * ++ * This work is licensed under the terms of the GNU GPL, version 2 or later. ++ * See the COPYING file in the top-level directory. ++ * ++ */ ++ ++#include "qemu/osdep.h" ++#include "exec/confidential-guest-support.h" ++#include "hw/boards.h" ++#include "hw/core/cpu.h" ++#include "kvm_arm.h" ++#include "migration/blocker.h" ++#include "qapi/error.h" ++#include "qom/object_interfaces.h" ++#include "sysemu/kvm.h" ++#include "sysemu/runstate.h" ++#include "hw/loader.h" ++ ++#define TYPE_TMM_GUEST "tmm-guest" ++OBJECT_DECLARE_SIMPLE_TYPE(TmmGuest, TMM_GUEST) ++ ++#define TMM_PAGE_SIZE qemu_real_host_page_size ++#define TMM_MAX_PMU_CTRS 0x20 ++#define TMM_MAX_CFG 5 ++ ++struct TmmGuest { ++ ConfidentialGuestSupport parent_obj; ++ GSList *ram_regions; ++ TmmGuestMeasurementAlgo measurement_algo; ++ uint32_t sve_vl; ++ uint32_t num_pmu_cntrs; ++}; ++ ++typedef struct { ++ hwaddr base1; ++ hwaddr len1; ++ hwaddr base2; ++ hwaddr len2; ++ bool populate; ++} TmmRamRegion; ++ ++static TmmGuest *tmm_guest; ++ ++bool kvm_arm_tmm_enabled(void) ++{ ++ return !!tmm_guest; ++} ++ ++static int tmm_configure_one(TmmGuest *guest, uint32_t cfg, Error **errp) ++{ ++ int ret = 1; ++ const char *cfg_str; ++ struct kvm_cap_arm_tmm_config_item args = { ++ .cfg = cfg, ++ }; ++ ++ switch (cfg) { ++ case KVM_CAP_ARM_TMM_CFG_RPV: ++ return 0; ++ case KVM_CAP_ARM_TMM_CFG_HASH_ALGO: ++ switch (guest->measurement_algo) { ++ case TMM_GUEST_MEASUREMENT_ALGO_DEFAULT: ++ return 0; ++ case TMM_GUEST_MEASUREMENT_ALGO_SHA256: ++ args.hash_algo = KVM_CAP_ARM_TMM_MEASUREMENT_ALGO_SHA256; ++ break; ++ case TMM_GUEST_MEASUREMENT_ALGO_SHA512: ++ args.hash_algo = KVM_CAP_ARM_TMM_MEASUREMENT_ALGO_SHA512; ++ break; ++ default: ++ g_assert_not_reached(); ++ } ++ cfg_str = "hash algorithm"; ++ break; ++ case KVM_CAP_ARM_TMM_CFG_SVE: ++ if (!guest->sve_vl) { ++ return 0; ++ } ++ args.sve_vq = guest->sve_vl / 128; ++ cfg_str = "SVE"; ++ break; ++ case KVM_CAP_ARM_TMM_CFG_DBG: ++ return 0; ++ case KVM_CAP_ARM_TMM_CFG_PMU: ++ if (!guest->num_pmu_cntrs) { ++ return 0; ++ } ++ args.num_pmu_cntrs = guest->num_pmu_cntrs; ++ cfg_str = "PMU"; ++ break; ++ default: ++ g_assert_not_reached(); ++ } ++ ++ ret = kvm_vm_enable_cap(kvm_state, KVM_CAP_ARM_TMM, 0, ++ KVM_CAP_ARM_TMM_CONFIG_CVM, (intptr_t)&args); ++ if (ret) { ++ error_setg_errno(errp, -ret, "TMM: failed to configure %s", cfg_str); ++ } ++ ++ return ret; ++} ++ ++static gint tmm_compare_ram_regions(gconstpointer a, gconstpointer b) ++{ ++ const TmmRamRegion *ra = a; ++ const TmmRamRegion *rb = b; ++ ++ g_assert(ra->base1 != rb->base1); ++ return ra->base1 < rb->base1 ? -1 : 1; ++} ++ ++void tmm_add_ram_region(hwaddr base1, hwaddr len1, hwaddr base2, hwaddr len2, bool populate) ++{ ++ TmmRamRegion *region; ++ ++ region = g_new0(TmmRamRegion, 1); ++ region->base1 = QEMU_ALIGN_DOWN(base1, TMM_PAGE_SIZE); ++ region->len1 = QEMU_ALIGN_UP(len1, TMM_PAGE_SIZE); ++ region->base2 = QEMU_ALIGN_DOWN(base2, TMM_PAGE_SIZE); ++ region->len2 = QEMU_ALIGN_UP(len2, TMM_PAGE_SIZE); ++ region->populate = populate; ++ ++ tmm_guest->ram_regions = g_slist_insert_sorted(tmm_guest->ram_regions, ++ region, tmm_compare_ram_regions); ++} ++ ++static void tmm_populate_region(gpointer data, gpointer unused) ++{ ++ int ret; ++ const TmmRamRegion *region = data; ++ struct kvm_cap_arm_tmm_populate_region_args populate_args = { ++ .populate_ipa_base1 = region->base1, ++ .populate_ipa_size1 = region->len1, ++ .populate_ipa_base2 = region->base2, ++ .populate_ipa_size2 = region->len2, ++ .flags = KVM_ARM_TMM_POPULATE_FLAGS_MEASURE, ++ }; ++ ++ if (!region->populate) { ++ return; ++ } ++ ++ ret = kvm_vm_enable_cap(kvm_state, KVM_CAP_ARM_TMM, 0, ++ KVM_CAP_ARM_TMM_POPULATE_CVM, ++ (intptr_t)&populate_args); ++ if (ret) { ++ error_report("TMM: failed to populate cvm region (0x%"HWADDR_PRIx", 0x%"HWADDR_PRIx", 0x%"HWADDR_PRIx", 0x%"HWADDR_PRIx"): %s", ++ region->base1, region->len1, region->base2, region->len2, strerror(-ret)); ++ exit(1); ++ } ++} ++ ++static int tmm_create_rd(Error **errp) ++{ ++ int ret = kvm_vm_enable_cap(kvm_state, KVM_CAP_ARM_TMM, 0, ++ KVM_CAP_ARM_TMM_CREATE_RD); ++ if (ret) { ++ error_setg_errno(errp, -ret, "TMM: failed to create tmm Descriptor"); ++ } ++ return ret; ++} ++ ++static void tmm_vm_state_change(void *opaque, bool running, RunState state) ++{ ++ int ret; ++ CPUState *cs; ++ ++ if (!running) { ++ return; ++ } ++ ++ g_slist_foreach(tmm_guest->ram_regions, tmm_populate_region, NULL); ++ g_slist_free_full(g_steal_pointer(&tmm_guest->ram_regions), g_free); ++ ++ CPU_FOREACH(cs) { ++ ret = kvm_arm_vcpu_finalize(cs, KVM_ARM_VCPU_TEC); ++ if (ret) { ++ error_report("TMM: failed to finalize vCPU: %s", strerror(-ret)); ++ exit(1); ++ } ++ } ++ ++ ret = kvm_vm_enable_cap(kvm_state, KVM_CAP_ARM_TMM, 0, ++ KVM_CAP_ARM_TMM_ACTIVATE_CVM); ++ if (ret) { ++ error_report("TMM: failed to activate cvm: %s", strerror(-ret)); ++ exit(1); ++ } ++} ++ ++int kvm_arm_tmm_init(ConfidentialGuestSupport *cgs, Error **errp) ++{ ++ int ret; ++ int cfg; ++ ++ if (!tmm_guest) { ++ return -ENODEV; ++ } ++ ++ if (!kvm_check_extension(kvm_state, KVM_CAP_ARM_TMM)) { ++ error_setg(errp, "KVM does not support TMM"); ++ return -ENODEV; ++ } ++ ++ for (cfg = 0; cfg < TMM_MAX_CFG; cfg++) { ++ ret = tmm_configure_one(tmm_guest, cfg, &error_abort); ++ if (ret) { ++ return ret; ++ } ++ } ++ ++ ret = tmm_create_rd(&error_abort); ++ if (ret) { ++ return ret; ++ } ++ ++ qemu_add_vm_change_state_handler(tmm_vm_state_change, NULL); ++ return 0; ++} ++ ++static void tmm_get_sve_vl(Object *obj, Visitor *v, const char *name, ++ void *opaque, Error **errp) ++{ ++ TmmGuest *guest = TMM_GUEST(obj); ++ ++ visit_type_uint32(v, name, &guest->sve_vl, errp); ++} ++ ++static void tmm_set_sve_vl(Object *obj, Visitor *v, const char *name, ++ void *opaque, Error **errp) ++{ ++ TmmGuest *guest = TMM_GUEST(obj); ++ uint32_t value; ++ ++ if (!visit_type_uint32(v, name, &value, errp)) { ++ return; ++ } ++ ++ if (value & 0x7f || value >= ARM_MAX_VQ * 128) { ++ error_setg(errp, "invalid SVE vector length"); ++ return; ++ } ++ ++ guest->sve_vl = value; ++} ++ ++static void tmm_get_num_pmu_cntrs(Object *obj, Visitor *v, const char *name, ++ void *opaque, Error **errp) ++{ ++ TmmGuest *guest = TMM_GUEST(obj); ++ ++ visit_type_uint32(v, name, &guest->num_pmu_cntrs, errp); ++} ++ ++static void tmm_set_num_pmu_cntrs(Object *obj, Visitor *v, const char *name, ++ void *opaque, Error **errp) ++{ ++ TmmGuest *guest = TMM_GUEST(obj); ++ uint32_t value; ++ ++ if (!visit_type_uint32(v, name, &value, errp)) { ++ return; ++ } ++ ++ if (value >= TMM_MAX_PMU_CTRS) { ++ error_setg(errp, "invalid number of PMU counters"); ++ return; ++ } ++ ++ guest->num_pmu_cntrs = value; ++} ++ ++static int tmm_get_measurement_algo(Object *obj, Error **errp G_GNUC_UNUSED) ++{ ++ TmmGuest *guest = TMM_GUEST(obj); ++ ++ return guest->measurement_algo; ++} ++ ++static void tmm_set_measurement_algo(Object *obj, int algo, Error **errp G_GNUC_UNUSED) ++{ ++ TmmGuest *guest = TMM_GUEST(obj); ++ ++ guest->measurement_algo = algo; ++} ++ ++static void tmm_guest_class_init(ObjectClass *oc, void *data) ++{ ++ object_class_property_add_enum(oc, "measurement-algo", ++ "TmmGuestMeasurementAlgo", ++ &TmmGuestMeasurementAlgo_lookup, ++ tmm_get_measurement_algo, ++ tmm_set_measurement_algo); ++ object_class_property_set_description(oc, "measurement-algo", ++ "cvm measurement algorithm ('sha256', 'sha512')"); ++ /* ++ * This is not ideal. Normally SVE parameters are given to -cpu, but the ++ * cvm parameters are needed much earlier than CPU initialization. We also ++ * don't have a way to discover what is supported at the moment, the idea is ++ * that the user knows exactly what hardware it is running on because these ++ * parameters are part of the measurement and play in the attestation. ++ */ ++ object_class_property_add(oc, "sve-vector-length", "uint32", tmm_get_sve_vl, ++ tmm_set_sve_vl, NULL, NULL); ++ object_class_property_set_description(oc, "sve-vector-length", ++ "SVE vector length. 0 disables SVE (the default)"); ++ object_class_property_add(oc, "num-pmu-counters", "uint32", ++ tmm_get_num_pmu_cntrs, tmm_set_num_pmu_cntrs, ++ NULL, NULL); ++ object_class_property_set_description(oc, "num-pmu-counters", ++ "Number of PMU counters"); ++} ++ ++static void tmm_guest_instance_init(Object *obj) ++{ ++ if (tmm_guest) { ++ error_report("a single instance of TmmGuest is supported"); ++ exit(1); ++ } ++ tmm_guest = TMM_GUEST(obj); ++} ++ ++static const TypeInfo tmm_guest_info = { ++ .parent = TYPE_CONFIDENTIAL_GUEST_SUPPORT, ++ .name = TYPE_TMM_GUEST, ++ .instance_size = sizeof(struct TmmGuest), ++ .instance_init = tmm_guest_instance_init, ++ .class_init = tmm_guest_class_init, ++ .interfaces = (InterfaceInfo[]) { ++ { TYPE_USER_CREATABLE }, ++ { } ++ } ++}; ++ ++static void tmm_register_types(void) ++{ ++ type_register_static(&tmm_guest_info); ++} ++type_init(tmm_register_types); +diff --git a/target/arm/kvm.c b/target/arm/kvm.c +index 38d80adfb7..f62d9ece3c 100644 +--- a/target/arm/kvm.c ++++ b/target/arm/kvm.c +@@ -605,7 +605,9 @@ bool write_list_to_kvmstate(ARMCPU *cpu, int level) + if (kvm_arm_cpreg_level(regidx) > level) { + continue; + } +- ++ if (virtcca_cvm_enabled() && regidx == KVM_REG_ARM_TIMER_CNT) { ++ continue; ++ } + r.id = regidx; + switch (regidx & KVM_REG_SIZE_MASK) { + case KVM_REG_SIZE_U32: +@@ -1140,7 +1142,7 @@ int kvm_arch_msi_data_to_gsi(uint32_t data) + + bool kvm_arch_cpu_check_are_resettable(void) + { +- return true; ++ return !virtcca_cvm_enabled(); + } + + void kvm_arch_accel_class_init(ObjectClass *oc) +diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c +index 0f67b8ba96..38d519846c 100644 +--- a/target/arm/kvm64.c ++++ b/target/arm/kvm64.c +@@ -818,6 +818,11 @@ static int kvm_arm_sve_set_vls(CPUState *cs) + + assert(cpu->sve_max_vq <= KVM_ARM64_SVE_VQ_MAX); + ++ if (virtcca_cvm_enabled()) { ++ /* Already set through tmm config */ ++ return 0; ++ } ++ + for (vq = 1; vq <= cpu->sve_max_vq; ++vq) { + if (test_bit(vq - 1, cpu->sve_vq_map)) { + i = (vq - 1) / 64; +diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h +index 8b644b3924..5a49383031 100644 +--- a/target/arm/kvm_arm.h ++++ b/target/arm/kvm_arm.h +@@ -377,6 +377,11 @@ void kvm_arm_pvtime_init(CPUState *cs, uint64_t ipa); + + int kvm_arm_set_irq(int cpu, int irqtype, int irq, int level); + ++void tmm_add_ram_region(hwaddr base1, hwaddr len1, hwaddr base2, hwaddr len2, bool populate); ++ ++int kvm_arm_tmm_init(ConfidentialGuestSupport *cgs, Error **errp); ++bool kvm_arm_tmm_enabled(void); ++ + int kvm_arm_get_one_reg(ARMCPU *cpu, uint64_t regidx, uint64_t *target); + int kvm_arm_set_one_reg(ARMCPU *cpu, uint64_t regidx, uint64_t *source); + +@@ -471,6 +476,11 @@ static inline int kvm_arm_set_one_reg(ARMCPU *cpu, uint64_t regidx, + g_assert_not_reached(); + } + ++static inline int kvm_arm_tmm_init(ConfidentialGuestSupport *cgs, Error **errp G_GNUC_UNUSED) ++{ ++ g_assert_not_reached(); ++} ++ + #endif + + static inline const char *gic_class_name(void) +diff --git a/target/arm/meson.build b/target/arm/meson.build +index 50f152214a..bb950fbffe 100644 +--- a/target/arm/meson.build ++++ b/target/arm/meson.build +@@ -39,6 +39,7 @@ arm_ss.add(files( + arm_ss.add(zlib) + + arm_ss.add(when: 'CONFIG_KVM', if_true: files('kvm.c', 'kvm64.c'), if_false: files('kvm-stub.c')) ++arm_ss.add(when: 'CONFIG_KVM', if_true: files('kvm.c', 'kvm64.c', 'kvm-tmm.c'), if_false: files('kvm-stub.c')) + + arm_ss.add(when: 'TARGET_AARCH64', if_true: files( + 'cpu64.c', +-- +2.41.0.windows.1 + diff --git a/cvm-bug-fix-for-macro-isolation.patch b/cvm-bug-fix-for-macro-isolation.patch new file mode 100644 index 00000000..d1dadec3 --- /dev/null +++ b/cvm-bug-fix-for-macro-isolation.patch @@ -0,0 +1,48 @@ +From c3e350aa92bbce2954b908a6bd8481adf222c840 Mon Sep 17 00:00:00 2001 +From: fuju +Date: Sat, 15 Jun 2024 16:42:19 +0800 +Subject: [PATCH] cvm: bug-fix for macro isolation + +1. add else branch for CONFIG_KVM_IS_POSSIBLE macro isolation. +2. add else branch for CONFIG_KVM macro isolation. + +Fixes: 12d0d099aecb("Add support for the virtcca cvm feature") + +Signed-off-by: Fu Ju +--- + include/sysemu/kvm.h | 1 + + target/arm/kvm_arm.h | 6 ++++++ + 2 files changed, 7 insertions(+) + +diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h +index 0b5319b4e3..5860228034 100644 +--- a/include/sysemu/kvm.h ++++ b/include/sysemu/kvm.h +@@ -175,6 +175,7 @@ extern bool kvm_msi_use_devid; + + #define kvm_enabled() (0) + #define virtcca_cvm_enabled() (0) ++#define VIRTCCA_CVM_TYPE (0) + #define kvm_irqchip_in_kernel() (false) + #define kvm_irqchip_is_split() (false) + #define kvm_async_interrupts_enabled() (false) +diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h +index 5a49383031..475531dad4 100644 +--- a/target/arm/kvm_arm.h ++++ b/target/arm/kvm_arm.h +@@ -481,6 +481,12 @@ static inline int kvm_arm_tmm_init(ConfidentialGuestSupport *cgs, Error **errp G + g_assert_not_reached(); + } + ++static inline void tmm_add_ram_region(hwaddr base1, hwaddr len1, hwaddr base2, ++ hwaddr len2, bool populate) ++{ ++ g_assert_not_reached(); ++} ++ + #endif + + static inline const char *gic_class_name(void) +-- +2.41.0.windows.1 + diff --git a/hw-ide-reset-cancel-async-DMA-operation-before-reset.patch b/hw-ide-reset-cancel-async-DMA-operation-before-reset.patch new file mode 100644 index 00000000..97913a51 --- /dev/null +++ b/hw-ide-reset-cancel-async-DMA-operation-before-reset.patch @@ -0,0 +1,110 @@ +From fac003085b4e294ae60c579a2e74087ea019f4b7 Mon Sep 17 00:00:00 2001 +From: Fiona Ebner +Date: Wed, 6 Sep 2023 15:09:21 +0200 +Subject: [PATCH] hw/ide: reset: cancel async DMA operation before resetting + state (Fix CVE-2023-5088) +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +If there is a pending DMA operation during ide_bus_reset(), the fact +that the IDEState is already reset before the operation is canceled +can be problematic. In particular, ide_dma_cb() might be called and +then use the reset IDEState which contains the signature after the +reset. When used to construct the IO operation this leads to +ide_get_sector() returning 0 and nsector being 1. This is particularly +bad, because a write command will thus destroy the first sector which +often contains a partition table or similar. + +Traces showing the unsolicited write happening with IDEState +0x5595af6949d0 being used after reset: + +> ahci_port_write ahci(0x5595af6923f0)[0]: port write [reg:PxSCTL] @ 0x2c: 0x00000300 +> ahci_reset_port ahci(0x5595af6923f0)[0]: reset port +> ide_reset IDEstate 0x5595af6949d0 +> ide_reset IDEstate 0x5595af694da8 +> ide_bus_reset_aio aio_cancel +> dma_aio_cancel dbs=0x7f64600089a0 +> dma_blk_cb dbs=0x7f64600089a0 ret=0 +> dma_complete dbs=0x7f64600089a0 ret=0 cb=0x5595acd40b30 +> ahci_populate_sglist ahci(0x5595af6923f0)[0] +> ahci_dma_prepare_buf ahci(0x5595af6923f0)[0]: prepare buf limit=512 prepared=512 +> ide_dma_cb IDEState 0x5595af6949d0; sector_num=0 n=1 cmd=DMA WRITE +> dma_blk_io dbs=0x7f6420802010 bs=0x5595ae2c6c30 offset=0 to_dev=1 +> dma_blk_cb dbs=0x7f6420802010 ret=0 + +> (gdb) p *qiov +> $11 = {iov = 0x7f647c76d840, niov = 1, {{nalloc = 1, local_iov = {iov_base = 0x0, +> iov_len = 512}}, {__pad = "\001\000\000\000\000\000\000\000\000\000\000", +> size = 512}}} +> (gdb) bt +> #0 blk_aio_pwritev (blk=0x5595ae2c6c30, offset=0, qiov=0x7f6420802070, flags=0, +> cb=0x5595ace6f0b0 , opaque=0x7f6420802010) +> at ../block/block-backend.c:1682 +> #1 0x00005595ace6f185 in dma_blk_cb (opaque=0x7f6420802010, ret=) +> at ../softmmu/dma-helpers.c:179 +> #2 0x00005595ace6f778 in dma_blk_io (ctx=0x5595ae0609f0, +> sg=sg@entry=0x5595af694d00, offset=offset@entry=0, align=align@entry=512, +> io_func=io_func@entry=0x5595ace6ee30 , +> io_func_opaque=io_func_opaque@entry=0x5595ae2c6c30, +> cb=0x5595acd40b30 , opaque=0x5595af6949d0, +> dir=DMA_DIRECTION_TO_DEVICE) at ../softmmu/dma-helpers.c:244 +> #3 0x00005595ace6f90a in dma_blk_write (blk=0x5595ae2c6c30, +> sg=sg@entry=0x5595af694d00, offset=offset@entry=0, align=align@entry=512, +> cb=cb@entry=0x5595acd40b30 , opaque=opaque@entry=0x5595af6949d0) +> at ../softmmu/dma-helpers.c:280 +> #4 0x00005595acd40e18 in ide_dma_cb (opaque=0x5595af6949d0, ret=) +> at ../hw/ide/core.c:953 +> #5 0x00005595ace6f319 in dma_complete (ret=0, dbs=0x7f64600089a0) +> at ../softmmu/dma-helpers.c:107 +> #6 dma_blk_cb (opaque=0x7f64600089a0, ret=0) at ../softmmu/dma-helpers.c:127 +> #7 0x00005595ad12227d in blk_aio_complete (acb=0x7f6460005b10) +> at ../block/block-backend.c:1527 +> #8 blk_aio_complete (acb=0x7f6460005b10) at ../block/block-backend.c:1524 +> #9 blk_aio_write_entry (opaque=0x7f6460005b10) at ../block/block-backend.c:1594 +> #10 0x00005595ad258cfb in coroutine_trampoline (i0=, +> i1=) at ../util/coroutine-ucontext.c:177 + +Signed-off-by: Fiona Ebner +Reviewed-by: Philippe Mathieu-Daudé +Tested-by: simon.rowe@nutanix.com +Message-ID: <20230906130922.142845-1-f.ebner@proxmox.com> +Signed-off-by: Philippe Mathieu-Daudé +--- + hw/ide/core.c | 14 +++++++------- + 1 file changed, 7 insertions(+), 7 deletions(-) + +diff --git a/hw/ide/core.c b/hw/ide/core.c +index 14283a84a5..5e5c6e2cf3 100644 +--- a/hw/ide/core.c ++++ b/hw/ide/core.c +@@ -2456,19 +2456,19 @@ static void ide_dummy_transfer_stop(IDEState *s) + + void ide_bus_reset(IDEBus *bus) + { +- bus->unit = 0; +- bus->cmd = 0; +- ide_reset(&bus->ifs[0]); +- ide_reset(&bus->ifs[1]); +- ide_clear_hob(bus); +- +- /* pending async DMA */ ++ /* pending async DMA - needs the IDEState before it is reset */ + if (bus->dma->aiocb) { + trace_ide_bus_reset_aio(); + blk_aio_cancel(bus->dma->aiocb); + bus->dma->aiocb = NULL; + } + ++ bus->unit = 0; ++ bus->cmd = 0; ++ ide_reset(&bus->ifs[0]); ++ ide_reset(&bus->ifs[1]); ++ ide_clear_hob(bus); ++ + /* reset dma provider too */ + if (bus->dma->ops->reset) { + bus->dma->ops->reset(bus->dma); +-- +2.41.0.windows.1 + diff --git a/qemu.spec b/qemu.spec index d4b1dec9..127617a8 100644 --- a/qemu.spec +++ b/qemu.spec @@ -3,7 +3,7 @@ Name: qemu Version: 6.2.0 -Release: 92 +Release: 93 Epoch: 10 Summary: QEMU is a generic and open source machine emulator and virtualizer License: GPLv2 and BSD and MIT and CC-BY-SA-4.0 @@ -964,6 +964,10 @@ Patch0949: migration-Extend-query-migrate-to-provide-dirty-page.patch Patch0950: docs-system-target-arm-Re-alphabetize-board-list.patch Patch0951: target-ppc-Remove-msr_pr-macro.patch Patch0952: s390x-sclp-Simplify-get_sclp_device.patch +Patch0953: Add-support-for-the-virtcca-cvm-feature.patch +Patch0954: hw-ide-reset-cancel-async-DMA-operation-before-reset.patch +Patch0955: tests-qtest-ahci-test-add-test-exposing-reset-issue-.patch +Patch0956: cvm-bug-fix-for-macro-isolation.patch BuildRequires: flex BuildRequires: gcc @@ -1562,6 +1566,12 @@ getent passwd qemu >/dev/null || \ %endif %changelog +* Sat Jun 15 2024 - 10:6.2.0-93 +- cvm: bug-fix for macro isolation +- tests/qtest: ahci-test: add test exposing reset issue with pending callback (Fix CVE-2023-5088) +- hw/ide: reset: cancel async DMA operation before resetting state (Fix CVE-2023-5088) +- Add support for the virtcca cvm feature. + * Thu Jun 13 2024 - 10:6.2.0-92 - s390x/sclp: Simplify get_sclp_device() - target/ppc: Remove msr_pr macro diff --git a/tests-qtest-ahci-test-add-test-exposing-reset-issue-.patch b/tests-qtest-ahci-test-add-test-exposing-reset-issue-.patch new file mode 100644 index 00000000..b2e7a2d6 --- /dev/null +++ b/tests-qtest-ahci-test-add-test-exposing-reset-issue-.patch @@ -0,0 +1,132 @@ +From dd38a2080df3aa42519dc94168e37381016ed6cb Mon Sep 17 00:00:00 2001 +From: Fiona Ebner +Date: Wed, 6 Sep 2023 15:09:22 +0200 +Subject: [PATCH] tests/qtest: ahci-test: add test exposing reset issue with + pending callback (Fix CVE-2023-5088) +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Before commit "hw/ide: reset: cancel async DMA operation before +resetting state", this test would fail, because a reset with a +pending write operation would lead to an unsolicited write to the +first sector of the disk. + +The test writes a pattern to the beginning of the disk and verifies +that it is still intact after a reset with a pending operation. It +also checks that the pending operation actually completes correctly. + +Signed-off-by: Fiona Ebner +Message-ID: <20230906130922.142845-2-f.ebner@proxmox.com> +Signed-off-by: Philippe Mathieu-Daudé +--- + tests/qtest/ahci-test.c | 86 ++++++++++++++++++++++++++++++++++++++++- + 1 file changed, 85 insertions(+), 1 deletion(-) + +diff --git a/tests/qtest/ahci-test.c b/tests/qtest/ahci-test.c +index f7f69dc4bd..c8657cbdb3 100644 +--- a/tests/qtest/ahci-test.c ++++ b/tests/qtest/ahci-test.c +@@ -1425,6 +1425,89 @@ static void test_reset(void) + ahci_shutdown(ahci); + } + ++static void test_reset_pending_callback(void) ++{ ++ AHCIQState *ahci; ++ AHCICommand *cmd; ++ uint8_t port; ++ uint64_t ptr1; ++ uint64_t ptr2; ++ ++ int bufsize = 4 * 1024; ++ int speed = bufsize + (bufsize / 2); ++ int offset1 = 0; ++ int offset2 = bufsize / AHCI_SECTOR_SIZE; ++ ++ g_autofree unsigned char *tx1 = g_malloc(bufsize); ++ g_autofree unsigned char *tx2 = g_malloc(bufsize); ++ g_autofree unsigned char *rx1 = g_malloc0(bufsize); ++ g_autofree unsigned char *rx2 = g_malloc0(bufsize); ++ ++ /* Uses throttling to make test independent of specific environment. */ ++ ahci = ahci_boot_and_enable("-drive if=none,id=drive0,file=%s," ++ "cache=writeback,format=%s," ++ "throttling.bps-write=%d " ++ "-M q35 " ++ "-device ide-hd,drive=drive0 ", ++ tmp_path, imgfmt, speed); ++ ++ port = ahci_port_select(ahci); ++ ahci_port_clear(ahci, port); ++ ++ ptr1 = ahci_alloc(ahci, bufsize); ++ ptr2 = ahci_alloc(ahci, bufsize); ++ ++ g_assert(ptr1 && ptr2); ++ ++ /* Need two different patterns. */ ++ do { ++ generate_pattern(tx1, bufsize, AHCI_SECTOR_SIZE); ++ generate_pattern(tx2, bufsize, AHCI_SECTOR_SIZE); ++ } while (memcmp(tx1, tx2, bufsize) == 0); ++ ++ qtest_bufwrite(ahci->parent->qts, ptr1, tx1, bufsize); ++ qtest_bufwrite(ahci->parent->qts, ptr2, tx2, bufsize); ++ ++ /* Write to beginning of disk to check it wasn't overwritten later. */ ++ ahci_guest_io(ahci, port, CMD_WRITE_DMA_EXT, ptr1, bufsize, offset1); ++ ++ /* Issue asynchronously to get a pending callback during reset. */ ++ cmd = ahci_command_create(CMD_WRITE_DMA_EXT); ++ ahci_command_adjust(cmd, offset2, ptr2, bufsize, 0); ++ ahci_command_commit(ahci, cmd, port); ++ ahci_command_issue_async(ahci, cmd); ++ ++ ahci_set(ahci, AHCI_GHC, AHCI_GHC_HR); ++ ++ ahci_command_free(cmd); ++ ++ /* Wait for throttled write to finish. */ ++ sleep(1); ++ ++ /* Start again. */ ++ ahci_clean_mem(ahci); ++ ahci_pci_enable(ahci); ++ ahci_hba_enable(ahci); ++ port = ahci_port_select(ahci); ++ ahci_port_clear(ahci, port); ++ ++ /* Read and verify. */ ++ ahci_guest_io(ahci, port, CMD_READ_DMA_EXT, ptr1, bufsize, offset1); ++ qtest_bufread(ahci->parent->qts, ptr1, rx1, bufsize); ++ g_assert_cmphex(memcmp(tx1, rx1, bufsize), ==, 0); ++ ++ ahci_guest_io(ahci, port, CMD_READ_DMA_EXT, ptr2, bufsize, offset2); ++ qtest_bufread(ahci->parent->qts, ptr2, rx2, bufsize); ++ g_assert_cmphex(memcmp(tx2, rx2, bufsize), ==, 0); ++ ++ ahci_free(ahci, ptr1); ++ ahci_free(ahci, ptr2); ++ ++ ahci_clean_mem(ahci); ++ ++ ahci_shutdown(ahci); ++} ++ + static void test_ncq_simple(void) + { + AHCIQState *ahci; +@@ -1929,7 +2012,8 @@ int main(int argc, char **argv) + qtest_add_func("/ahci/migrate/dma/halted", test_migrate_halted_dma); + + qtest_add_func("/ahci/max", test_max); +- qtest_add_func("/ahci/reset", test_reset); ++ qtest_add_func("/ahci/reset/simple", test_reset); ++ qtest_add_func("/ahci/reset/pending_callback", test_reset_pending_callback); + + qtest_add_func("/ahci/io/ncq/simple", test_ncq_simple); + qtest_add_func("/ahci/migrate/ncq/simple", test_migrate_ncq); +-- +2.41.0.windows.1 + -- Gitee From dc351cd68565e7718f0fef9ae78bb00488f46a3d Mon Sep 17 00:00:00 2001 From: tujipei Date: Tue, 18 Jun 2024 10:27:55 +0800 Subject: [PATCH 11/19] QEMU update to version 6.2.0-94 - hw/arm/virt: Disable DTB randomness for confidential VMs Signed-off-by: liupingwei (cherry picked from commit c85e7c13d4af40380dedc26c5412742c2c5ef36d) --- ...ble-DTB-randomness-for-confidential-.patch | 35 +++++++++++++++++++ qemu.spec | 6 +++- 2 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 hw-arm-virt-Disable-DTB-randomness-for-confidential-.patch diff --git a/hw-arm-virt-Disable-DTB-randomness-for-confidential-.patch b/hw-arm-virt-Disable-DTB-randomness-for-confidential-.patch new file mode 100644 index 00000000..dd787017 --- /dev/null +++ b/hw-arm-virt-Disable-DTB-randomness-for-confidential-.patch @@ -0,0 +1,35 @@ +From 2830db7bec600915e88bb22847a66d99b047a308 Mon Sep 17 00:00:00 2001 +From: liupingwei +Date: Mon, 17 Jun 2024 19:56:48 +0800 +Subject: [PATCH] hw/arm/virt:Disable DTB randomness for confidential VMs + +The dtb-randomness feature,which adds random seeds to the DTB,isn't +really compatible with confidential VMs since it randomizes the +TMM.Enabling it is not an error,but it prevents attestation.It also +isn't useful to TMM,which dosn't trust host input. + +Fixes:12d0d099aecb("Add support for the virtcca cvm feature") + +Signed-off-by: liupingwei +--- + hw/arm/virt.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/hw/arm/virt.c b/hw/arm/virt.c +index f20775f44c..e0de08e2c1 100644 +--- a/hw/arm/virt.c ++++ b/hw/arm/virt.c +@@ -261,7 +261,9 @@ static void create_fdt(VirtMachineState *vms) + + /* /chosen must exist for load_dtb to fill in necessary properties later */ + qemu_fdt_add_subnode(fdt, "/chosen"); +- create_kaslr_seed(ms, "/chosen"); ++ if (!virtcca_cvm_enabled()) { ++ create_kaslr_seed(ms, "/chosen"); ++ } + + if (vms->secure) { + qemu_fdt_add_subnode(fdt, "/secure-chosen"); +-- +2.31.1.windows.1 + diff --git a/qemu.spec b/qemu.spec index 127617a8..e7ec5243 100644 --- a/qemu.spec +++ b/qemu.spec @@ -3,7 +3,7 @@ Name: qemu Version: 6.2.0 -Release: 93 +Release: 94 Epoch: 10 Summary: QEMU is a generic and open source machine emulator and virtualizer License: GPLv2 and BSD and MIT and CC-BY-SA-4.0 @@ -968,6 +968,7 @@ Patch0953: Add-support-for-the-virtcca-cvm-feature.patch Patch0954: hw-ide-reset-cancel-async-DMA-operation-before-reset.patch Patch0955: tests-qtest-ahci-test-add-test-exposing-reset-issue-.patch Patch0956: cvm-bug-fix-for-macro-isolation.patch +Patch0957: hw-arm-virt-Disable-DTB-randomness-for-confidential-.patch BuildRequires: flex BuildRequires: gcc @@ -1566,6 +1567,9 @@ getent passwd qemu >/dev/null || \ %endif %changelog +* Tue Jun 18 2024 - 10:6.2.0-94 +- hw/arm/virt: Disable DTB randomness for confidential VMs + * Sat Jun 15 2024 - 10:6.2.0-93 - cvm: bug-fix for macro isolation - tests/qtest: ahci-test: add test exposing reset issue with pending callback (Fix CVE-2023-5088) -- Gitee From 5534354b8a42525f1ed2651ff44bca138ae02127 Mon Sep 17 00:00:00 2001 From: liupingwei Date: Fri, 21 Jun 2024 09:48:48 +0800 Subject: [PATCH 12/19] QEMU update to version 6.2.0-95 - cvm: bug-fix for disable DTB randomness for confidential VMs Signed-off-by: liupingwei (cherry picked from commit bad58948c08a6c98afadb6bfc894abfc5eda1f91) --- ...disable-DTB-randomness-for-confident.patch | 40 +++++++++++++++++++ qemu.spec | 6 ++- 2 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 cvm-bug-fix-for-disable-DTB-randomness-for-confident.patch diff --git a/cvm-bug-fix-for-disable-DTB-randomness-for-confident.patch b/cvm-bug-fix-for-disable-DTB-randomness-for-confident.patch new file mode 100644 index 00000000..9273085a --- /dev/null +++ b/cvm-bug-fix-for-disable-DTB-randomness-for-confident.patch @@ -0,0 +1,40 @@ +From 892657386e36e72395c23cec61457dfa0e1bb8f4 Mon Sep 17 00:00:00 2001 +From: liupingwei +Date: Wed, 19 Jun 2024 17:43:35 +0800 +Subject: [PATCH] cvm: bug-fix for disable DTB randomness for confidential VMs + +The previous condition relied on virtcca_cvm_enabled,which was not +initialized in time. +Now,we directly check the KVM type and disable DTB randomness if the +type is "cvm". + +Fixes:2830db7bec600915e88bb22847a66d99b047a308("hw/arm/virt:Disable DTB +randomness for confidential VMs") + +Signed-off-by: liupingwei +--- + hw/arm/virt.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/hw/arm/virt.c b/hw/arm/virt.c +index e0de08e2c1..dc119732f0 100644 +--- a/hw/arm/virt.c ++++ b/hw/arm/virt.c +@@ -261,7 +261,13 @@ static void create_fdt(VirtMachineState *vms) + + /* /chosen must exist for load_dtb to fill in necessary properties later */ + qemu_fdt_add_subnode(fdt, "/chosen"); +- if (!virtcca_cvm_enabled()) { ++ ++ g_autofree char *kvm_type = NULL; ++ if (object_property_find(OBJECT(current_machine), "kvm-type")) { ++ kvm_type = object_property_get_str(OBJECT(current_machine), ++ "kvm-type", &error_abort); ++ } ++ if (!(kvm_type && !strcmp(kvm_type, "cvm"))) { + create_kaslr_seed(ms, "/chosen"); + } + +-- +2.31.1.windows.1 + diff --git a/qemu.spec b/qemu.spec index e7ec5243..2aae97a5 100644 --- a/qemu.spec +++ b/qemu.spec @@ -3,7 +3,7 @@ Name: qemu Version: 6.2.0 -Release: 94 +Release: 95 Epoch: 10 Summary: QEMU is a generic and open source machine emulator and virtualizer License: GPLv2 and BSD and MIT and CC-BY-SA-4.0 @@ -969,6 +969,7 @@ Patch0954: hw-ide-reset-cancel-async-DMA-operation-before-reset.patch Patch0955: tests-qtest-ahci-test-add-test-exposing-reset-issue-.patch Patch0956: cvm-bug-fix-for-macro-isolation.patch Patch0957: hw-arm-virt-Disable-DTB-randomness-for-confidential-.patch +Patch0958: cvm-bug-fix-for-disable-DTB-randomness-for-confident.patch BuildRequires: flex BuildRequires: gcc @@ -1567,6 +1568,9 @@ getent passwd qemu >/dev/null || \ %endif %changelog +* Fri Jun 21 2024 - 10:6.2.0-95 +- cvm: bug-fix for disable DTB randomness for confidential VMs + * Tue Jun 18 2024 - 10:6.2.0-94 - hw/arm/virt: Disable DTB randomness for confidential VMs -- Gitee From 0dd8f840c7323b3ccface3cad5215639bb0b74a7 Mon Sep 17 00:00:00 2001 From: Jiabo Feng Date: Thu, 11 Jul 2024 14:25:27 +0800 Subject: [PATCH 13/19] QEMU update to verssion 6.2.0-96: - vdpa: Fix bug where vdpa appliance migration does not resume after rollback - block: Parse filenames only when explicitly requested (CVE-2024-4467) - block: introduce bdrv_open_file_child() helper - iotests/270: Don't store data-file with json: prefix in image (CVE-2024-4467) - iotests/244: Don't store data-file with protocol in image (CVE-2024-4467) - qcow2: Don't open data_file with BDRV_O_NO_IO (CVE-2024-4467) - qcow2: Do not reopen data_file in invalidate_cache - hw/intc/arm_gic: Fix deactivation of SPI lines chery-pick from 7175a562f157d39725ab396e39c1e8e410d206b3 - vhost-user: Skip unnecessary duplicated VHOST_USER_SET_LOG_BASE requests - target/ppc: Split off common embedded TLB init cheery-pick from 581eea5d656b73c6532109f4ced4c73fd4e5fd47` - vdpa: fix vdpa device migrate rollback wrong when suspend device failed 1. - hw/virtio/virtio-pci:Support shadow device for virtio-net/blk/scsi devices Signed-off-by: Jiabo Feng (cherry picked from commit ad45062d44e901468eeb8c4ac0729587daaa1e1f) --- ...names-only-when-explicitly-requested.patch | 229 ++++++++ ...ntroduce-bdrv_open_file_child-helper.patch | 542 ++++++++++++++++++ ...rm_gic-Fix-deactivation-of-SPI-lines.patch | 62 ++ ...-pci-Support-shadow-device-for-virti.patch | 64 +++ ...t-store-data-file-with-protocol-in-i.patch | 52 ++ ...t-store-data-file-with-json-prefix-i.patch | 54 ++ ...reopen-data_file-in-invalidate_cache.patch | 221 +++++++ ...-data_file-with-BDRV_O_NO_IO-CVE-202.patch | 108 ++++ qemu.spec | 28 +- ...c-Split-off-common-embedded-TLB-init.patch | 118 ++++ ...re-vdpa-appliance-migration-does-not.patch | 38 ++ ...vice-migrate-rollback-wrong-when-sus.patch | 140 +++++ ...unnecessary-duplicated-VHOST_USER_SE.patch | 31 + 13 files changed, 1686 insertions(+), 1 deletion(-) create mode 100644 block-Parse-filenames-only-when-explicitly-requested.patch create mode 100644 block-introduce-bdrv_open_file_child-helper.patch create mode 100644 hw-intc-arm_gic-Fix-deactivation-of-SPI-lines.patch create mode 100644 hw-virtio-virtio-pci-Support-shadow-device-for-virti.patch create mode 100644 iotests-244-Don-t-store-data-file-with-protocol-in-i.patch create mode 100644 iotests-270-Don-t-store-data-file-with-json-prefix-i.patch create mode 100644 qcow2-Do-not-reopen-data_file-in-invalidate_cache.patch create mode 100644 qcow2-Don-t-open-data_file-with-BDRV_O_NO_IO-CVE-202.patch create mode 100644 target-ppc-Split-off-common-embedded-TLB-init.patch create mode 100644 vdpa-Fix-bug-where-vdpa-appliance-migration-does-not.patch create mode 100644 vdpa-fix-vdpa-device-migrate-rollback-wrong-when-sus.patch create mode 100644 vhost-user-Skip-unnecessary-duplicated-VHOST_USER_SE.patch diff --git a/block-Parse-filenames-only-when-explicitly-requested.patch b/block-Parse-filenames-only-when-explicitly-requested.patch new file mode 100644 index 00000000..c5aa88b6 --- /dev/null +++ b/block-Parse-filenames-only-when-explicitly-requested.patch @@ -0,0 +1,229 @@ +From effc2c56f7b5390fbe6041d3a6ecf4026371bc25 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Thu, 25 Apr 2024 14:56:02 +0200 +Subject: [PATCH] block: Parse filenames only when explicitly requested + (CVE-2024-4467) + +When handling image filenames from legacy options such as -drive or from +tools, these filenames are parsed for protocol prefixes, including for +the json:{} pseudo-protocol. + +This behaviour is intended for filenames that come directly from the +command line and for backing files, which may come from the image file +itself. Higher level management tools generally take care to verify that +untrusted images don't contain a bad (or any) backing file reference; +'qemu-img info' is a suitable tool for this. + +However, for other files that can be referenced in images, such as +qcow2 data files or VMDK extents, the string from the image file is +usually not verified by management tools - and 'qemu-img info' wouldn't +be suitable because in contrast to backing files, it already opens these +other referenced files. So here the string should be interpreted as a +literal local filename. More complex configurations need to be specified +explicitly on the command line or in QMP. + +This patch changes bdrv_open_inherit() so that it only parses filenames +if a new parameter parse_filename is true. It is set for the top level +in bdrv_open(), for the file child and for the backing file child. All +other callers pass false and disable filename parsing this way. + +Cc: qemu-stable@nongnu.org +Signed-off-by: Kevin Wolf +Reviewed-by: Eric Blake +Reviewed-by: Stefan Hajnoczi +Reviewed-by: Hanna Czenczek +Signed-off-by: liuxiangdong +--- + block.c | 75 ++++++++++++++++++++++++++++++++++++++------------------- + 1 file changed, 50 insertions(+), 25 deletions(-) + +diff --git a/block.c b/block.c +index 7b58fe57f8..a91117abda 100644 +--- a/block.c ++++ b/block.c +@@ -85,6 +85,7 @@ static BlockDriverState *bdrv_open_inherit(const char *filename, + BlockDriverState *parent, + const BdrvChildClass *child_class, + BdrvChildRole child_role, ++ bool parse_filename, + Error **errp); + + static bool bdrv_recurse_has_child(BlockDriverState *bs, +@@ -1929,7 +1930,8 @@ static void parse_json_protocol(QDict *options, const char **pfilename, + * block driver has been specified explicitly. + */ + static int bdrv_fill_options(QDict **options, const char *filename, +- int *flags, Error **errp) ++ int *flags, bool allow_parse_filename, ++ Error **errp) + { + const char *drvname; + bool protocol = *flags & BDRV_O_PROTOCOL; +@@ -1969,7 +1971,7 @@ static int bdrv_fill_options(QDict **options, const char *filename, + if (protocol && filename) { + if (!qdict_haskey(*options, "filename")) { + qdict_put_str(*options, "filename", filename); +- parse_filename = true; ++ parse_filename = allow_parse_filename; + } else { + error_setg(errp, "Can't specify 'file' and 'filename' options at " + "the same time"); +@@ -3442,7 +3444,8 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *parent_options, + } + + backing_hd = bdrv_open_inherit(backing_filename, reference, options, 0, bs, +- &child_of_bds, bdrv_backing_role(bs), errp); ++ &child_of_bds, bdrv_backing_role(bs), true, ++ errp); + if (!backing_hd) { + bs->open_flags |= BDRV_O_NO_BACKING; + error_prepend(errp, "Could not open backing file: "); +@@ -3475,7 +3478,8 @@ free_exit: + static BlockDriverState * + bdrv_open_child_bs(const char *filename, QDict *options, const char *bdref_key, + BlockDriverState *parent, const BdrvChildClass *child_class, +- BdrvChildRole child_role, bool allow_none, Error **errp) ++ BdrvChildRole child_role, bool allow_none, ++ bool parse_filename, Error **errp) + { + BlockDriverState *bs = NULL; + QDict *image_options; +@@ -3506,7 +3510,8 @@ bdrv_open_child_bs(const char *filename, QDict *options, const char *bdref_key, + } + + bs = bdrv_open_inherit(filename, reference, image_options, 0, +- parent, child_class, child_role, errp); ++ parent, child_class, child_role, parse_filename, ++ errp); + if (!bs) { + goto done; + } +@@ -3516,6 +3521,26 @@ done: + return bs; + } + ++static BdrvChild *bdrv_open_child_common(const char *filename, ++ QDict *options, const char *bdref_key, ++ BlockDriverState *parent, ++ const BdrvChildClass *child_class, ++ BdrvChildRole child_role, ++ bool allow_none, bool parse_filename, ++ Error **errp) ++{ ++ BlockDriverState *bs; ++ ++ bs = bdrv_open_child_bs(filename, options, bdref_key, parent, child_class, ++ child_role, allow_none, parse_filename, errp); ++ if (bs == NULL) { ++ return NULL; ++ } ++ ++ return bdrv_attach_child(parent, bs, bdref_key, child_class, child_role, ++ errp); ++} ++ + /* + * Opens a disk image whose options are given as BlockdevRef in another block + * device's options. +@@ -3537,20 +3562,15 @@ BdrvChild *bdrv_open_child(const char *filename, + BdrvChildRole child_role, + bool allow_none, Error **errp) + { +- BlockDriverState *bs; +- +- bs = bdrv_open_child_bs(filename, options, bdref_key, parent, child_class, +- child_role, allow_none, errp); +- if (bs == NULL) { +- return NULL; +- } +- +- return bdrv_attach_child(parent, bs, bdref_key, child_class, child_role, +- errp); ++ return bdrv_open_child_common(filename, options, bdref_key, parent, ++ child_class, child_role, allow_none, false, ++ errp); + } + + /* +- * Wrapper on bdrv_open_child() for most popular case: open primary child of bs. ++ * This does mostly the same as bdrv_open_child(), but for opening the primary ++ * child of a node. A notable difference from bdrv_open_child() is that it ++ * enables filename parsing for protocol names (including json:). + */ + int bdrv_open_file_child(const char *filename, + QDict *options, const char *bdref_key, +@@ -3561,8 +3581,8 @@ int bdrv_open_file_child(const char *filename, + role = parent->drv->is_filter ? + (BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY) : BDRV_CHILD_IMAGE; + +- parent->file = bdrv_open_child(filename, options, bdref_key, parent, +- &child_of_bds, role, false, errp); ++ parent->file = bdrv_open_child_common(filename, options, bdref_key, parent, ++ &child_of_bds, role, false, true, errp); + + return parent->file ? 0 : -EINVAL; + } +@@ -3602,7 +3622,8 @@ BlockDriverState *bdrv_open_blockdev_ref(BlockdevRef *ref, Error **errp) + + } + +- bs = bdrv_open_inherit(NULL, reference, qdict, 0, NULL, NULL, 0, errp); ++ bs = bdrv_open_inherit(NULL, reference, qdict, 0, NULL, NULL, 0, false, ++ errp); + obj = NULL; + qobject_unref(obj); + visit_free(v); +@@ -3693,6 +3714,7 @@ static BlockDriverState *bdrv_open_inherit(const char *filename, + BlockDriverState *parent, + const BdrvChildClass *child_class, + BdrvChildRole child_role, ++ bool parse_filename, + Error **errp) + { + int ret; +@@ -3736,9 +3758,11 @@ static BlockDriverState *bdrv_open_inherit(const char *filename, + } + + /* json: syntax counts as explicit options, as if in the QDict */ +- parse_json_protocol(options, &filename, &local_err); +- if (local_err) { +- goto fail; ++ if (parse_filename) { ++ parse_json_protocol(options, &filename, &local_err); ++ if (local_err) { ++ goto fail; ++ } + } + + bs->explicit_options = qdict_clone_shallow(options); +@@ -3763,7 +3787,8 @@ static BlockDriverState *bdrv_open_inherit(const char *filename, + parent->open_flags, parent->options); + } + +- ret = bdrv_fill_options(&options, filename, &flags, &local_err); ++ ret = bdrv_fill_options(&options, filename, &flags, parse_filename, ++ &local_err); + if (ret < 0) { + goto fail; + } +@@ -3832,7 +3857,7 @@ static BlockDriverState *bdrv_open_inherit(const char *filename, + + file_bs = bdrv_open_child_bs(filename, options, "file", bs, + &child_of_bds, BDRV_CHILD_IMAGE, +- true, &local_err); ++ true, true, &local_err); + if (local_err) { + goto fail; + } +@@ -3977,7 +4002,7 @@ BlockDriverState *bdrv_open(const char *filename, const char *reference, + QDict *options, int flags, Error **errp) + { + return bdrv_open_inherit(filename, reference, options, flags, NULL, +- NULL, 0, errp); ++ NULL, 0, true, errp); + } + + /* Return true if the NULL-terminated @list contains @str */ +-- +2.41.0.windows.1 + diff --git a/block-introduce-bdrv_open_file_child-helper.patch b/block-introduce-bdrv_open_file_child-helper.patch new file mode 100644 index 00000000..4179b9f6 --- /dev/null +++ b/block-introduce-bdrv_open_file_child-helper.patch @@ -0,0 +1,542 @@ +From 4045020d37da7a7a70b5175b3fb7d022e0bdb47f Mon Sep 17 00:00:00 2001 +From: Vladimir Sementsov-Ogievskiy +Date: Tue, 26 Jul 2022 23:11:21 +0300 +Subject: [PATCH] block: introduce bdrv_open_file_child() helper + +Almost all drivers call bdrv_open_child() similarly. Let's create a +helper for this. + +The only not updated drivers that call bdrv_open_child() to set +bs->file are raw-format and snapshot-access: + raw-format sometimes want to have filtered child but + don't set drv->is_filter to true. + snapshot-access wants only DATA | PRIMARY + +Possibly we should implement drv->is_filter_func() handler, to consider +raw-format as filter when it works as filter.. But it's another story. + +Note also, that we decrease assignments to bs->file in code: it helps +us restrict modifying this field in further commit. + +Signed-off-by: Vladimir Sementsov-Ogievskiy +Reviewed-by: Hanna Reitz +Message-Id: <20220726201134.924743-3-vsementsov@yandex-team.ru> +Reviewed-by: Kevin Wolf +Signed-off-by: Kevin Wolf +Signed-off-by: liuxiangdong +--- + block.c | 18 ++++++++++++++++++ + block/blkdebug.c | 9 +++------ + block/blklogwrites.c | 7 ++----- + block/blkreplay.c | 7 ++----- + block/blkverify.c | 9 +++------ + block/bochs.c | 7 +++---- + block/cloop.c | 7 +++---- + block/copy-before-write.c | 9 ++++----- + block/copy-on-read.c | 9 ++++----- + block/crypto.c | 11 ++++++----- + block/dmg.c | 7 +++---- + block/filter-compress.c | 8 +++----- + block/parallels.c | 7 +++---- + block/preallocate.c | 9 ++++----- + block/qcow.c | 6 ++---- + block/qcow2.c | 8 ++++---- + block/qed.c | 8 ++++---- + block/replication.c | 8 +++----- + block/throttle.c | 8 +++----- + block/vdi.c | 7 +++---- + block/vhdx.c | 7 +++---- + block/vmdk.c | 7 +++---- + block/vpc.c | 7 +++---- + include/block/block.h | 3 +++ + 24 files changed, 92 insertions(+), 101 deletions(-) + +diff --git a/block.c b/block.c +index 75083139d1..7b58fe57f8 100644 +--- a/block.c ++++ b/block.c +@@ -3549,6 +3549,24 @@ BdrvChild *bdrv_open_child(const char *filename, + errp); + } + ++/* ++ * Wrapper on bdrv_open_child() for most popular case: open primary child of bs. ++ */ ++int bdrv_open_file_child(const char *filename, ++ QDict *options, const char *bdref_key, ++ BlockDriverState *parent, Error **errp) ++{ ++ BdrvChildRole role; ++ ++ role = parent->drv->is_filter ? ++ (BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY) : BDRV_CHILD_IMAGE; ++ ++ parent->file = bdrv_open_child(filename, options, bdref_key, parent, ++ &child_of_bds, role, false, errp); ++ ++ return parent->file ? 0 : -EINVAL; ++} ++ + /* + * TODO Future callers may need to specify parent/child_class in order for + * option inheritance to work. Existing callers use it for the root node. +diff --git a/block/blkdebug.c b/block/blkdebug.c +index bbf2948703..5fcfc8ac6f 100644 +--- a/block/blkdebug.c ++++ b/block/blkdebug.c +@@ -503,12 +503,9 @@ static int blkdebug_open(BlockDriverState *bs, QDict *options, int flags, + } + + /* Open the image file */ +- bs->file = bdrv_open_child(qemu_opt_get(opts, "x-image"), options, "image", +- bs, &child_of_bds, +- BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY, +- false, errp); +- if (!bs->file) { +- ret = -EINVAL; ++ ret = bdrv_open_file_child(qemu_opt_get(opts, "x-image"), options, "image", ++ bs, errp); ++ if (ret < 0) { + goto out; + } + +diff --git a/block/blklogwrites.c b/block/blklogwrites.c +index f7a251e91f..f66a617eb3 100644 +--- a/block/blklogwrites.c ++++ b/block/blklogwrites.c +@@ -155,11 +155,8 @@ static int blk_log_writes_open(BlockDriverState *bs, QDict *options, int flags, + } + + /* Open the file */ +- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds, +- BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY, false, +- errp); +- if (!bs->file) { +- ret = -EINVAL; ++ ret = bdrv_open_file_child(NULL, options, "file", bs, errp); ++ if (ret < 0) { + goto fail; + } + +diff --git a/block/blkreplay.c b/block/blkreplay.c +index dcbe780ddb..76a0b8d12a 100644 +--- a/block/blkreplay.c ++++ b/block/blkreplay.c +@@ -26,11 +26,8 @@ static int blkreplay_open(BlockDriverState *bs, QDict *options, int flags, + int ret; + + /* Open the image file */ +- bs->file = bdrv_open_child(NULL, options, "image", bs, &child_of_bds, +- BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY, +- false, errp); +- if (!bs->file) { +- ret = -EINVAL; ++ ret = bdrv_open_file_child(NULL, options, "image", bs, errp); ++ if (ret < 0) { + goto fail; + } + +diff --git a/block/blkverify.c b/block/blkverify.c +index d1facf5ba9..920e891684 100644 +--- a/block/blkverify.c ++++ b/block/blkverify.c +@@ -121,12 +121,9 @@ static int blkverify_open(BlockDriverState *bs, QDict *options, int flags, + } + + /* Open the raw file */ +- bs->file = bdrv_open_child(qemu_opt_get(opts, "x-raw"), options, "raw", +- bs, &child_of_bds, +- BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY, +- false, errp); +- if (!bs->file) { +- ret = -EINVAL; ++ ret = bdrv_open_file_child(qemu_opt_get(opts, "x-raw"), options, "raw", ++ bs, errp); ++ if (ret < 0) { + goto fail; + } + +diff --git a/block/bochs.c b/block/bochs.c +index 4d68658087..b2dc06bbfd 100644 +--- a/block/bochs.c ++++ b/block/bochs.c +@@ -110,10 +110,9 @@ static int bochs_open(BlockDriverState *bs, QDict *options, int flags, + return ret; + } + +- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds, +- BDRV_CHILD_IMAGE, false, errp); +- if (!bs->file) { +- return -EINVAL; ++ ret = bdrv_open_file_child(NULL, options, "file", bs, errp); ++ if (ret < 0) { ++ return ret; + } + + ret = bdrv_pread(bs->file, 0, &bochs, sizeof(bochs)); +diff --git a/block/cloop.c b/block/cloop.c +index b8c6d0eccd..bee87da173 100644 +--- a/block/cloop.c ++++ b/block/cloop.c +@@ -71,10 +71,9 @@ static int cloop_open(BlockDriverState *bs, QDict *options, int flags, + return ret; + } + +- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds, +- BDRV_CHILD_IMAGE, false, errp); +- if (!bs->file) { +- return -EINVAL; ++ ret = bdrv_open_file_child(NULL, options, "file", bs, errp); ++ if (ret < 0) { ++ return ret; + } + + /* read header */ +diff --git a/block/copy-before-write.c b/block/copy-before-write.c +index c30a5ff8de..8aa2cb6a85 100644 +--- a/block/copy-before-write.c ++++ b/block/copy-before-write.c +@@ -150,12 +150,11 @@ static int cbw_open(BlockDriverState *bs, QDict *options, int flags, + { + BDRVCopyBeforeWriteState *s = bs->opaque; + BdrvDirtyBitmap *copy_bitmap; ++ int ret; + +- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds, +- BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY, +- false, errp); +- if (!bs->file) { +- return -EINVAL; ++ ret = bdrv_open_file_child(NULL, options, "file", bs, errp); ++ if (ret < 0) { ++ return ret; + } + + s->target = bdrv_open_child(NULL, options, "target", bs, &child_of_bds, +diff --git a/block/copy-on-read.c b/block/copy-on-read.c +index 1fc7fb3333..815ac1d835 100644 +--- a/block/copy-on-read.c ++++ b/block/copy-on-read.c +@@ -41,12 +41,11 @@ static int cor_open(BlockDriverState *bs, QDict *options, int flags, + BDRVStateCOR *state = bs->opaque; + /* Find a bottom node name, if any */ + const char *bottom_node = qdict_get_try_str(options, "bottom"); ++ int ret; + +- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds, +- BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY, +- false, errp); +- if (!bs->file) { +- return -EINVAL; ++ ret = bdrv_open_file_child(NULL, options, "file", bs, errp); ++ if (ret < 0) { ++ return ret; + } + + bs->supported_read_flags = BDRV_REQ_PREFETCH; +diff --git a/block/crypto.c b/block/crypto.c +index c8ba4681e2..abfce39230 100644 +--- a/block/crypto.c ++++ b/block/crypto.c +@@ -260,15 +260,14 @@ static int block_crypto_open_generic(QCryptoBlockFormat format, + { + BlockCrypto *crypto = bs->opaque; + QemuOpts *opts = NULL; +- int ret = -EINVAL; ++ int ret; + QCryptoBlockOpenOptions *open_opts = NULL; + unsigned int cflags = 0; + QDict *cryptoopts = NULL; + +- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds, +- BDRV_CHILD_IMAGE, false, errp); +- if (!bs->file) { +- return -EINVAL; ++ ret = bdrv_open_file_child(NULL, options, "file", bs, errp); ++ if (ret < 0) { ++ return ret; + } + + bs->supported_write_flags = BDRV_REQ_FUA & +@@ -276,6 +275,7 @@ static int block_crypto_open_generic(QCryptoBlockFormat format, + + opts = qemu_opts_create(opts_spec, NULL, 0, &error_abort); + if (!qemu_opts_absorb_qdict(opts, options, errp)) { ++ ret = -EINVAL; + goto cleanup; + } + +@@ -284,6 +284,7 @@ static int block_crypto_open_generic(QCryptoBlockFormat format, + + open_opts = block_crypto_open_opts_init(cryptoopts, errp); + if (!open_opts) { ++ ret = -EINVAL; + goto cleanup; + } + +diff --git a/block/dmg.c b/block/dmg.c +index 447901fbb8..38c363dd39 100644 +--- a/block/dmg.c ++++ b/block/dmg.c +@@ -439,10 +439,9 @@ static int dmg_open(BlockDriverState *bs, QDict *options, int flags, + return ret; + } + +- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds, +- BDRV_CHILD_IMAGE, false, errp); +- if (!bs->file) { +- return -EINVAL; ++ ret = bdrv_open_file_child(NULL, options, "file", bs, errp); ++ if (ret < 0) { ++ return ret; + } + + block_module_load_one("dmg-bz2"); +diff --git a/block/filter-compress.c b/block/filter-compress.c +index d5be538619..305716c86c 100644 +--- a/block/filter-compress.c ++++ b/block/filter-compress.c +@@ -30,11 +30,9 @@ + static int compress_open(BlockDriverState *bs, QDict *options, int flags, + Error **errp) + { +- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds, +- BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY, +- false, errp); +- if (!bs->file) { +- return -EINVAL; ++ int ret = bdrv_open_file_child(NULL, options, "file", bs, errp); ++ if (ret < 0) { ++ return ret; + } + + if (!bs->file->bs->drv || !block_driver_can_compress(bs->file->bs->drv)) { +diff --git a/block/parallels.c b/block/parallels.c +index f3352b6aa7..ae3f324bb5 100644 +--- a/block/parallels.c ++++ b/block/parallels.c +@@ -735,10 +735,9 @@ static int parallels_open(BlockDriverState *bs, QDict *options, int flags, + Error *local_err = NULL; + char *buf; + +- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds, +- BDRV_CHILD_IMAGE, false, errp); +- if (!bs->file) { +- return -EINVAL; ++ ret = bdrv_open_file_child(NULL, options, "file", bs, errp); ++ if (ret < 0) { ++ return ret; + } + + ret = bdrv_pread(bs->file, 0, &ph, sizeof(ph)); +diff --git a/block/preallocate.c b/block/preallocate.c +index 1d4233f730..332408bdc9 100644 +--- a/block/preallocate.c ++++ b/block/preallocate.c +@@ -134,6 +134,7 @@ static int preallocate_open(BlockDriverState *bs, QDict *options, int flags, + Error **errp) + { + BDRVPreallocateState *s = bs->opaque; ++ int ret; + + /* + * s->data_end and friends should be initialized on permission update. +@@ -141,11 +142,9 @@ static int preallocate_open(BlockDriverState *bs, QDict *options, int flags, + */ + s->file_end = s->zero_start = s->data_end = -EINVAL; + +- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds, +- BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY, +- false, errp); +- if (!bs->file) { +- return -EINVAL; ++ ret = bdrv_open_file_child(NULL, options, "file", bs, errp); ++ if (ret < 0) { ++ return ret; + } + + if (!preallocate_absorb_opts(&s->opts, options, bs->file->bs, errp)) { +diff --git a/block/qcow.c b/block/qcow.c +index c39940f33e..544a17261f 100644 +--- a/block/qcow.c ++++ b/block/qcow.c +@@ -120,10 +120,8 @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags, + qdict_extract_subqdict(options, &encryptopts, "encrypt."); + encryptfmt = qdict_get_try_str(encryptopts, "format"); + +- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds, +- BDRV_CHILD_IMAGE, false, errp); +- if (!bs->file) { +- ret = -EINVAL; ++ ret = bdrv_open_file_child(NULL, options, "file", bs, errp); ++ if (ret < 0) { + goto fail; + } + +diff --git a/block/qcow2.c b/block/qcow2.c +index af1e94f2e2..7b1e870919 100644 +--- a/block/qcow2.c ++++ b/block/qcow2.c +@@ -1910,11 +1910,11 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags, + .errp = errp, + .ret = -EINPROGRESS + }; ++ int ret; + +- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds, +- BDRV_CHILD_IMAGE, false, errp); +- if (!bs->file) { +- return -EINVAL; ++ ret = bdrv_open_file_child(NULL, options, "file", bs, errp); ++ if (ret < 0) { ++ return ret; + } + + /* Initialise locks */ +diff --git a/block/qed.c b/block/qed.c +index 558d3646c4..e3b06a3d00 100644 +--- a/block/qed.c ++++ b/block/qed.c +@@ -558,11 +558,11 @@ static int bdrv_qed_open(BlockDriverState *bs, QDict *options, int flags, + .errp = errp, + .ret = -EINPROGRESS + }; ++ int ret; + +- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds, +- BDRV_CHILD_IMAGE, false, errp); +- if (!bs->file) { +- return -EINVAL; ++ ret = bdrv_open_file_child(NULL, options, "file", bs, errp); ++ if (ret < 0) { ++ return ret; + } + + bdrv_qed_init_state(bs); +diff --git a/block/replication.c b/block/replication.c +index 55c8f894aa..2f17397764 100644 +--- a/block/replication.c ++++ b/block/replication.c +@@ -88,11 +88,9 @@ static int replication_open(BlockDriverState *bs, QDict *options, + const char *mode; + const char *top_id; + +- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds, +- BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY, +- false, errp); +- if (!bs->file) { +- return -EINVAL; ++ ret = bdrv_open_file_child(NULL, options, "file", bs, errp); ++ if (ret < 0) { ++ return ret; + } + + ret = -EINVAL; +diff --git a/block/throttle.c b/block/throttle.c +index 6e8d52fa24..4fb5798c27 100644 +--- a/block/throttle.c ++++ b/block/throttle.c +@@ -78,11 +78,9 @@ static int throttle_open(BlockDriverState *bs, QDict *options, + char *group; + int ret; + +- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds, +- BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY, +- false, errp); +- if (!bs->file) { +- return -EINVAL; ++ ret = bdrv_open_file_child(NULL, options, "file", bs, errp); ++ if (ret < 0) { ++ return ret; + } + bs->supported_write_flags = bs->file->bs->supported_write_flags | + BDRV_REQ_WRITE_UNCHANGED; +diff --git a/block/vdi.c b/block/vdi.c +index bdc58d726e..c50c0ed61f 100644 +--- a/block/vdi.c ++++ b/block/vdi.c +@@ -376,10 +376,9 @@ static int vdi_open(BlockDriverState *bs, QDict *options, int flags, + int ret; + QemuUUID uuid_link, uuid_parent; + +- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds, +- BDRV_CHILD_IMAGE, false, errp); +- if (!bs->file) { +- return -EINVAL; ++ ret = bdrv_open_file_child(NULL, options, "file", bs, errp); ++ if (ret < 0) { ++ return ret; + } + + logout("\n"); +diff --git a/block/vhdx.c b/block/vhdx.c +index 356ec4c455..e7d6d7509a 100644 +--- a/block/vhdx.c ++++ b/block/vhdx.c +@@ -996,10 +996,9 @@ static int vhdx_open(BlockDriverState *bs, QDict *options, int flags, + uint64_t signature; + Error *local_err = NULL; + +- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds, +- BDRV_CHILD_IMAGE, false, errp); +- if (!bs->file) { +- return -EINVAL; ++ ret = bdrv_open_file_child(NULL, options, "file", bs, errp); ++ if (ret < 0) { ++ return ret; + } + + s->bat = NULL; +diff --git a/block/vmdk.c b/block/vmdk.c +index 0dfab6e941..7d7e56b36c 100644 +--- a/block/vmdk.c ++++ b/block/vmdk.c +@@ -1262,10 +1262,9 @@ static int vmdk_open(BlockDriverState *bs, QDict *options, int flags, + BDRVVmdkState *s = bs->opaque; + uint32_t magic; + +- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds, +- BDRV_CHILD_IMAGE, false, errp); +- if (!bs->file) { +- return -EINVAL; ++ ret = bdrv_open_file_child(NULL, options, "file", bs, errp); ++ if (ret < 0) { ++ return ret; + } + + buf = vmdk_read_desc(bs->file, 0, errp); +diff --git a/block/vpc.c b/block/vpc.c +index 297a26262a..430cab1cbb 100644 +--- a/block/vpc.c ++++ b/block/vpc.c +@@ -232,10 +232,9 @@ static int vpc_open(BlockDriverState *bs, QDict *options, int flags, + int ret; + int64_t bs_size; + +- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds, +- BDRV_CHILD_IMAGE, false, errp); +- if (!bs->file) { +- return -EINVAL; ++ ret = bdrv_open_file_child(NULL, options, "file", bs, errp); ++ if (ret < 0) { ++ return ret; + } + + opts = qemu_opts_create(&vpc_runtime_opts, NULL, 0, &error_abort); +diff --git a/include/block/block.h b/include/block/block.h +index e5dd22b034..f885f113ef 100644 +--- a/include/block/block.h ++++ b/include/block/block.h +@@ -376,6 +376,9 @@ BdrvChild *bdrv_open_child(const char *filename, + const BdrvChildClass *child_class, + BdrvChildRole child_role, + bool allow_none, Error **errp); ++int bdrv_open_file_child(const char *filename, ++ QDict *options, const char *bdref_key, ++ BlockDriverState *parent, Error **errp); + BlockDriverState *bdrv_open_blockdev_ref(BlockdevRef *ref, Error **errp); + int bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd, + Error **errp); +-- +2.41.0.windows.1 + diff --git a/hw-intc-arm_gic-Fix-deactivation-of-SPI-lines.patch b/hw-intc-arm_gic-Fix-deactivation-of-SPI-lines.patch new file mode 100644 index 00000000..124e06ce --- /dev/null +++ b/hw-intc-arm_gic-Fix-deactivation-of-SPI-lines.patch @@ -0,0 +1,62 @@ +From 1a52d742851a68772aeb1d6d18bb57e58d78b2d2 Mon Sep 17 00:00:00 2001 +From: guping +Date: Tue, 25 Jun 2024 11:33:54 +0000 +Subject: [PATCH] hw/intc/arm_gic: Fix deactivation of SPI lines chery-pick + from 7175a562f157d39725ab396e39c1e8e410d206b3 + +Julien reported that he has seen strange behaviour when running +Xen on QEMU using GICv2. When Xen migrates a guest's vCPU from +one pCPU to another while the vCPU is handling an interrupt, the +guest is unable to properly deactivate interrupts. + +Looking at it a little closer, our GICv2 model treats +deactivation of SPI lines as if they were PPI's, i.e banked per +CPU core. The state for active interrupts should only be banked +for PPI lines, not for SPI lines. + +Make deactivation of SPI lines unbanked, similar to how we +handle writes to GICD_ICACTIVER. + +Reported-by: default avatarJulien Grall +Signed-off-by: default avatarEdgar E. Iglesias +Message-id: 20240605143044.2029444-2-edgar.iglesias@gmail.com +Reviewed-by: default avatarPeter Maydell +Signed-off-by: default avatarPeter Maydell + +Signed-off-by: guping +--- + hw/intc/gic_internal.h | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/hw/intc/gic_internal.h b/hw/intc/gic_internal.h +index 8d29b40ca1..8ddbf554c6 100644 +--- a/hw/intc/gic_internal.h ++++ b/hw/intc/gic_internal.h +@@ -280,6 +280,8 @@ static inline void gic_set_active(GICState *s, int irq, int cpu) + + static inline void gic_clear_active(GICState *s, int irq, int cpu) + { ++ unsigned int cm; ++ + if (gic_is_vcpu(cpu)) { + uint32_t *entry = gic_get_lr_entry(s, irq, cpu); + GICH_LR_CLEAR_ACTIVE(*entry); +@@ -301,11 +303,13 @@ static inline void gic_clear_active(GICState *s, int irq, int cpu) + * the GIC is secure. + */ + if (!s->security_extn || GIC_DIST_TEST_GROUP(phys_irq, 1 << rcpu)) { +- GIC_DIST_CLEAR_ACTIVE(phys_irq, 1 << rcpu); ++ cm = phys_irq < GIC_INTERNAL ? 1 << rcpu : ALL_CPU_MASK; ++ GIC_DIST_CLEAR_ACTIVE(phys_irq, cm); + } + } + } else { +- GIC_DIST_CLEAR_ACTIVE(irq, 1 << cpu); ++ cm = irq < GIC_INTERNAL ? 1 << cpu : ALL_CPU_MASK; ++ GIC_DIST_CLEAR_ACTIVE(irq, cm); + } + } + +-- +2.41.0.windows.1 + diff --git a/hw-virtio-virtio-pci-Support-shadow-device-for-virti.patch b/hw-virtio-virtio-pci-Support-shadow-device-for-virti.patch new file mode 100644 index 00000000..59511f49 --- /dev/null +++ b/hw-virtio-virtio-pci-Support-shadow-device-for-virti.patch @@ -0,0 +1,64 @@ +From 38c0538c8d847a2e39a9bae19f5b204abcf46b3b Mon Sep 17 00:00:00 2001 +From: Yanan Wang +Date: Mon, 17 Jun 2024 20:42:22 +0800 +Subject: [PATCH] hw/virtio/virtio-pci:Support shadow device for + virtio-net/blk/scsi devices + +Currently we only support shadow device for "virtio-net", now let's +extend this feature to support "virtio-blk" and "virtio-scsi" devices. + +Signed-off-by: Yanan Wang +--- + hw/virtio/virtio-pci.c | 15 ++++++++++++--- + 1 file changed, 12 insertions(+), 3 deletions(-) + +diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c +index 389a8db0ec..d675526016 100644 +--- a/hw/virtio/virtio-pci.c ++++ b/hw/virtio/virtio-pci.c +@@ -886,6 +886,15 @@ int __attribute__((weak)) kvm_delete_shadow_device(PCIDevice *dev) + } + #endif + ++#ifdef __aarch64__ ++static bool shadow_device_supported(VirtIODevice *vdev) ++{ ++ return !strcmp(vdev->name, "virtio-net") || ++ !strcmp(vdev->name, "virtio-blk") || ++ !strcmp(vdev->name, "virtio-scsi"); ++} ++#endif ++ + static int kvm_virtio_pci_vector_vq_use(VirtIOPCIProxy *proxy, int nvqs) + { + int queue_no; +@@ -893,7 +902,7 @@ static int kvm_virtio_pci_vector_vq_use(VirtIOPCIProxy *proxy, int nvqs) + VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); + + #ifdef __aarch64__ +- if (!strcmp(vdev->name, "virtio-net")) { ++ if (shadow_device_supported(vdev)) { + kvm_create_shadow_device(&proxy->pci_dev); + } + #endif +@@ -906,7 +915,7 @@ static int kvm_virtio_pci_vector_vq_use(VirtIOPCIProxy *proxy, int nvqs) + } + + #ifdef __aarch64__ +- if (!strcmp(vdev->name, "virtio-net") && ret != 0) { ++ if (shadow_device_supported(vdev) && ret != 0) { + kvm_delete_shadow_device(&proxy->pci_dev); + } + #endif +@@ -955,7 +964,7 @@ static void kvm_virtio_pci_vector_vq_release(VirtIOPCIProxy *proxy, int nvqs) + } + + #ifdef __aarch64__ +- if (!strcmp(vdev->name, "virtio-net")) { ++ if (shadow_device_supported(vdev)) { + kvm_delete_shadow_device(&proxy->pci_dev); + } + #endif +-- +2.41.0.windows.1 + diff --git a/iotests-244-Don-t-store-data-file-with-protocol-in-i.patch b/iotests-244-Don-t-store-data-file-with-protocol-in-i.patch new file mode 100644 index 00000000..787d8105 --- /dev/null +++ b/iotests-244-Don-t-store-data-file-with-protocol-in-i.patch @@ -0,0 +1,52 @@ +From e3feddf508a6c118e321b3a1c761068772487225 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Thu, 25 Apr 2024 14:49:40 +0200 +Subject: [PATCH] iotests/244: Don't store data-file with protocol in image + (CVE-2024-4467) + +We want to disable filename parsing for data files because it's too easy +to abuse in malicious image files. Make the test ready for the change by +passing the data file explicitly in command line options. + +Cc: qemu-stable@nongnu.org +Signed-off-by: Kevin Wolf +Reviewed-by: Eric Blake +Reviewed-by: Stefan Hajnoczi +Reviewed-by: Hanna Czenczek +--- + tests/qemu-iotests/244 | 19 ++++++++++++++++--- + 1 file changed, 16 insertions(+), 3 deletions(-) + +diff --git a/tests/qemu-iotests/244 b/tests/qemu-iotests/244 +index 3e61fa25bb..bb9cc6512f 100755 +--- a/tests/qemu-iotests/244 ++++ b/tests/qemu-iotests/244 +@@ -215,9 +215,22 @@ $QEMU_IMG convert -f $IMGFMT -O $IMGFMT -n -C "$TEST_IMG.src" "$TEST_IMG" + $QEMU_IMG compare -f $IMGFMT -F $IMGFMT "$TEST_IMG.src" "$TEST_IMG" + + # blkdebug doesn't support copy offloading, so this tests the error path +-$QEMU_IMG amend -f $IMGFMT -o "data_file=blkdebug::$TEST_IMG.data" "$TEST_IMG" +-$QEMU_IMG convert -f $IMGFMT -O $IMGFMT -n -C "$TEST_IMG.src" "$TEST_IMG" +-$QEMU_IMG compare -f $IMGFMT -F $IMGFMT "$TEST_IMG.src" "$TEST_IMG" ++test_img_with_blkdebug="json:{ ++ 'driver': 'qcow2', ++ 'file': { ++ 'driver': 'file', ++ 'filename': '$TEST_IMG' ++ }, ++ 'data-file': { ++ 'driver': 'blkdebug', ++ 'image': { ++ 'driver': 'file', ++ 'filename': '$TEST_IMG.data' ++ } ++ } ++}" ++$QEMU_IMG convert -f $IMGFMT -O $IMGFMT -n -C "$TEST_IMG.src" "$test_img_with_blkdebug" ++$QEMU_IMG compare -f $IMGFMT -F $IMGFMT "$TEST_IMG.src" "$test_img_with_blkdebug" + + echo + echo "=== Flushing should flush the data file ===" +-- +2.41.0.windows.1 + diff --git a/iotests-270-Don-t-store-data-file-with-json-prefix-i.patch b/iotests-270-Don-t-store-data-file-with-json-prefix-i.patch new file mode 100644 index 00000000..0a50f70a --- /dev/null +++ b/iotests-270-Don-t-store-data-file-with-json-prefix-i.patch @@ -0,0 +1,54 @@ +From 7ee281f59878c1f7a95e0a2a3f674c252d0c9f92 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Thu, 25 Apr 2024 14:49:40 +0200 +Subject: [PATCH] iotests/270: Don't store data-file with json: prefix in image + (CVE-2024-4467) + +We want to disable filename parsing for data files because it's too easy +to abuse in malicious image files. Make the test ready for the change by +passing the data file explicitly in command line options. + +Cc: qemu-stable@nongnu.org +Signed-off-by: Kevin Wolf +Reviewed-by: Eric Blake +Reviewed-by: Stefan Hajnoczi +Reviewed-by: Hanna Czenczek +--- + tests/qemu-iotests/270 | 14 +++++++++++--- + 1 file changed, 11 insertions(+), 3 deletions(-) + +diff --git a/tests/qemu-iotests/270 b/tests/qemu-iotests/270 +index 74352342db..c37b674aa2 100755 +--- a/tests/qemu-iotests/270 ++++ b/tests/qemu-iotests/270 +@@ -60,8 +60,16 @@ _make_test_img -o cluster_size=2M,data_file="$TEST_IMG.orig" \ + # "write" 2G of data without using any space. + # (qemu-img create does not like it, though, because null-co does not + # support image creation.) +-$QEMU_IMG amend -o data_file="json:{'driver':'null-co',,'size':'4294967296'}" \ +- "$TEST_IMG" ++test_img_with_null_data="json:{ ++ 'driver': '$IMGFMT', ++ 'file': { ++ 'filename': '$TEST_IMG' ++ }, ++ 'data-file': { ++ 'driver': 'null-co', ++ 'size':'4294967296' ++ } ++}" + + # This gives us a range of: + # 2^31 - 512 + 768 - 1 = 2^31 + 255 > 2^31 +@@ -74,7 +82,7 @@ $QEMU_IMG amend -o data_file="json:{'driver':'null-co',,'size':'4294967296'}" \ + # on L2 boundaries, we need large L2 tables; hence the cluster size of + # 2 MB. (Anything from 256 kB should work, though, because then one L2 + # table covers 8 GB.) +-$QEMU_IO -c "write 768 $((2 ** 31 - 512))" "$TEST_IMG" | _filter_qemu_io ++$QEMU_IO -c "write 768 $((2 ** 31 - 512))" "$test_img_with_null_data" | _filter_qemu_io + + _check_test_img + +-- +2.41.0.windows.1 + diff --git a/qcow2-Do-not-reopen-data_file-in-invalidate_cache.patch b/qcow2-Do-not-reopen-data_file-in-invalidate_cache.patch new file mode 100644 index 00000000..141702f7 --- /dev/null +++ b/qcow2-Do-not-reopen-data_file-in-invalidate_cache.patch @@ -0,0 +1,221 @@ +From d21b395997737618116926cb2680e85d79e14d19 Mon Sep 17 00:00:00 2001 +From: Hanna Reitz +Date: Wed, 27 Apr 2022 13:40:55 +0200 +Subject: [PATCH] qcow2: Do not reopen data_file in invalidate_cache + +qcow2_co_invalidate_cache() closes and opens the qcow2 file, by calling +qcow2_close() and qcow2_do_open(). These two functions must thus be +usable from both a global-state and an I/O context. + +As they are, they are not safe to call in an I/O context, because they +use bdrv_unref_child() and bdrv_open_child() to close/open the data_file +child, respectively, both of which are global-state functions. When +used from qcow2_co_invalidate_cache(), we do not need to close/open the +data_file child, though (we do not do this for bs->file or bs->backing +either), and so we should skip it in the qcow2_co_invalidate_cache() +path. + +To do so, add a parameter to qcow2_do_open() and qcow2_close() to make +them skip handling s->data_file, and have qcow2_co_invalidate_cache() +exempt it from the memset() on the BDRVQcow2State. + +(Note that the QED driver similarly closes/opens the QED image by +invoking bdrv_qed_close()+bdrv_qed_do_open(), but both functions seem +safe to use in an I/O context.) + +Fixes: https://gitlab.com/qemu-project/qemu/-/issues/945 +Signed-off-by: Hanna Reitz +Message-Id: <20220427114057.36651-3-hreitz@redhat.com> +Reviewed-by: Eric Blake +Signed-off-by: Kevin Wolf +--- + block/qcow2.c | 104 ++++++++++++++++++++++++++++++-------------------- + 1 file changed, 62 insertions(+), 42 deletions(-) + +diff --git a/block/qcow2.c b/block/qcow2.c +index be90a898e3..4a6b0a3ea9 100644 +--- a/block/qcow2.c ++++ b/block/qcow2.c +@@ -1296,7 +1296,8 @@ static int validate_compression_type(BDRVQcow2State *s, Error **errp) + + /* Called with s->lock held. */ + static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options, +- int flags, Error **errp) ++ int flags, bool open_data_file, ++ Error **errp) + { + ERRP_GUARD(); + BDRVQcow2State *s = bs->opaque; +@@ -1614,50 +1615,52 @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options, + goto fail; + } + +- /* Open external data file */ +- s->data_file = bdrv_open_child(NULL, options, "data-file", bs, +- &child_of_bds, BDRV_CHILD_DATA, +- true, errp); +- if (*errp) { +- ret = -EINVAL; +- goto fail; +- } ++ if (open_data_file) { ++ /* Open external data file */ ++ s->data_file = bdrv_open_child(NULL, options, "data-file", bs, ++ &child_of_bds, BDRV_CHILD_DATA, ++ true, errp); ++ if (*errp) { ++ ret = -EINVAL; ++ goto fail; ++ } + +- if (s->incompatible_features & QCOW2_INCOMPAT_DATA_FILE) { +- if (!s->data_file && s->image_data_file) { +- s->data_file = bdrv_open_child(s->image_data_file, options, +- "data-file", bs, &child_of_bds, +- BDRV_CHILD_DATA, false, errp); ++ if (s->incompatible_features & QCOW2_INCOMPAT_DATA_FILE) { ++ if (!s->data_file && s->image_data_file) { ++ s->data_file = bdrv_open_child(s->image_data_file, options, ++ "data-file", bs, &child_of_bds, ++ BDRV_CHILD_DATA, false, errp); ++ if (!s->data_file) { ++ ret = -EINVAL; ++ goto fail; ++ } ++ } + if (!s->data_file) { ++ error_setg(errp, "'data-file' is required for this image"); + ret = -EINVAL; + goto fail; + } +- } +- if (!s->data_file) { +- error_setg(errp, "'data-file' is required for this image"); +- ret = -EINVAL; +- goto fail; +- } + +- /* No data here */ +- bs->file->role &= ~BDRV_CHILD_DATA; ++ /* No data here */ ++ bs->file->role &= ~BDRV_CHILD_DATA; + +- /* Must succeed because we have given up permissions if anything */ +- bdrv_child_refresh_perms(bs, bs->file, &error_abort); +- } else { +- if (s->data_file) { +- error_setg(errp, "'data-file' can only be set for images with an " +- "external data file"); +- ret = -EINVAL; +- goto fail; +- } ++ /* Must succeed because we have given up permissions if anything */ ++ bdrv_child_refresh_perms(bs, bs->file, &error_abort); ++ } else { ++ if (s->data_file) { ++ error_setg(errp, "'data-file' can only be set for images with " ++ "an external data file"); ++ ret = -EINVAL; ++ goto fail; ++ } + +- s->data_file = bs->file; ++ s->data_file = bs->file; + +- if (data_file_is_raw(bs)) { +- error_setg(errp, "data-file-raw requires a data file"); +- ret = -EINVAL; +- goto fail; ++ if (data_file_is_raw(bs)) { ++ error_setg(errp, "data-file-raw requires a data file"); ++ ret = -EINVAL; ++ goto fail; ++ } + } + } + +@@ -1839,7 +1842,7 @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options, + + fail: + g_free(s->image_data_file); +- if (has_data_file(bs)) { ++ if (open_data_file && has_data_file(bs)) { + bdrv_unref_child(bs, s->data_file); + s->data_file = NULL; + } +@@ -1876,7 +1879,8 @@ static void coroutine_fn qcow2_open_entry(void *opaque) + BDRVQcow2State *s = qoc->bs->opaque; + + qemu_co_mutex_lock(&s->lock); +- qoc->ret = qcow2_do_open(qoc->bs, qoc->options, qoc->flags, qoc->errp); ++ qoc->ret = qcow2_do_open(qoc->bs, qoc->options, qoc->flags, true, ++ qoc->errp); + qemu_co_mutex_unlock(&s->lock); + } + +@@ -2714,7 +2718,7 @@ static int qcow2_inactivate(BlockDriverState *bs) + return result; + } + +-static void qcow2_close(BlockDriverState *bs) ++static void qcow2_do_close(BlockDriverState *bs, bool close_data_file) + { + BDRVQcow2State *s = bs->opaque; + qemu_vfree(s->l1_table); +@@ -2740,7 +2744,7 @@ static void qcow2_close(BlockDriverState *bs) + g_free(s->image_backing_file); + g_free(s->image_backing_format); + +- if (has_data_file(bs)) { ++ if (close_data_file && has_data_file(bs)) { + bdrv_unref_child(bs, s->data_file); + s->data_file = NULL; + } +@@ -2749,11 +2753,17 @@ static void qcow2_close(BlockDriverState *bs) + qcow2_free_snapshots(bs); + } + ++static void qcow2_close(BlockDriverState *bs) ++{ ++ qcow2_do_close(bs, true); ++} ++ + static void coroutine_fn qcow2_co_invalidate_cache(BlockDriverState *bs, + Error **errp) + { + ERRP_GUARD(); + BDRVQcow2State *s = bs->opaque; ++ BdrvChild *data_file; + int flags = s->flags; + QCryptoBlock *crypto = NULL; + QDict *options; +@@ -2767,14 +2777,24 @@ static void coroutine_fn qcow2_co_invalidate_cache(BlockDriverState *bs, + crypto = s->crypto; + s->crypto = NULL; + +- qcow2_close(bs); ++ /* ++ * Do not reopen s->data_file (i.e., have qcow2_do_close() not close it, ++ * and then prevent qcow2_do_open() from opening it), because this function ++ * runs in the I/O path and as such we must not invoke global-state ++ * functions like bdrv_unref_child() and bdrv_open_child(). ++ */ + ++ qcow2_do_close(bs, false); ++ ++ data_file = s->data_file; + memset(s, 0, sizeof(BDRVQcow2State)); ++ s->data_file = data_file; ++ + options = qdict_clone_shallow(bs->options); + + flags &= ~BDRV_O_INACTIVE; + qemu_co_mutex_lock(&s->lock); +- ret = qcow2_do_open(bs, options, flags, errp); ++ ret = qcow2_do_open(bs, options, flags, false, errp); + qemu_co_mutex_unlock(&s->lock); + qobject_unref(options); + if (ret < 0) { +-- +2.41.0.windows.1 + diff --git a/qcow2-Don-t-open-data_file-with-BDRV_O_NO_IO-CVE-202.patch b/qcow2-Don-t-open-data_file-with-BDRV_O_NO_IO-CVE-202.patch new file mode 100644 index 00000000..a705165c --- /dev/null +++ b/qcow2-Don-t-open-data_file-with-BDRV_O_NO_IO-CVE-202.patch @@ -0,0 +1,108 @@ +From 6dc46edd6ebe051b181e04aa6929d46b8cbc70ba Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Thu, 11 Apr 2024 15:06:01 +0200 +Subject: [PATCH] qcow2: Don't open data_file with BDRV_O_NO_IO (CVE-2024-4467) + +One use case for 'qemu-img info' is verifying that untrusted images +don't reference an unwanted external file, be it as a backing file or an +external data file. To make sure that calling 'qemu-img info' can't +already have undesired side effects with a malicious image, just don't +open the data file at all with BDRV_O_NO_IO. If nothing ever tries to do +I/O, we don't need to have it open. + +This changes the output of iotests case 061, which used 'qemu-img info' +to show that opening an image with an invalid data file fails. After +this patch, it succeeds. Replace this part of the test with a qemu-io +call, but keep the final 'qemu-img info' to show that the invalid data +file is correctly displayed in the output. + +Fixes: CVE-2024-4467 +Cc: qemu-stable@nongnu.org +Signed-off-by: Kevin Wolf +Reviewed-by: Eric Blake +Reviewed-by: Stefan Hajnoczi +Reviewed-by: Hanna Czenczek +--- + block/qcow2.c | 17 ++++++++++++++++- + tests/qemu-iotests/061 | 6 ++++-- + tests/qemu-iotests/061.out | 8 ++++++-- + 3 files changed, 26 insertions(+), 5 deletions(-) + +diff --git a/block/qcow2.c b/block/qcow2.c +index 4a6b0a3ea9..af1e94f2e2 100644 +--- a/block/qcow2.c ++++ b/block/qcow2.c +@@ -1615,7 +1615,22 @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options, + goto fail; + } + +- if (open_data_file) { ++ if (open_data_file && (flags & BDRV_O_NO_IO)) { ++ /* ++ * Don't open the data file for 'qemu-img info' so that it can be used ++ * to verify that an untrusted qcow2 image doesn't refer to external ++ * files. ++ * ++ * Note: This still makes has_data_file() return true. ++ */ ++ if (s->incompatible_features & QCOW2_INCOMPAT_DATA_FILE) { ++ s->data_file = NULL; ++ } else { ++ s->data_file = bs->file; ++ } ++ qdict_extract_subqdict(options, NULL, "data-file."); ++ qdict_del(options, "data-file"); ++ } else if (open_data_file) { + /* Open external data file */ + s->data_file = bdrv_open_child(NULL, options, "data-file", bs, + &child_of_bds, BDRV_CHILD_DATA, +diff --git a/tests/qemu-iotests/061 b/tests/qemu-iotests/061 +index 9507c223bd..6a5bd47efc 100755 +--- a/tests/qemu-iotests/061 ++++ b/tests/qemu-iotests/061 +@@ -322,12 +322,14 @@ $QEMU_IMG amend -o "data_file=foo" "$TEST_IMG" + echo + _make_test_img -o "compat=1.1,data_file=$TEST_IMG.data" 64M + $QEMU_IMG amend -o "data_file=foo" "$TEST_IMG" +-_img_info --format-specific ++$QEMU_IO -c "read 0 4k" "$TEST_IMG" 2>&1 | _filter_testdir | _filter_imgfmt ++$QEMU_IO -c "open -o data-file.filename=$TEST_IMG.data,file.filename=$TEST_IMG" -c "read 0 4k" | _filter_qemu_io + TEST_IMG="data-file.filename=$TEST_IMG.data,file.filename=$TEST_IMG" _img_info --format-specific --image-opts + + echo + $QEMU_IMG amend -o "data_file=" --image-opts "data-file.filename=$TEST_IMG.data,file.filename=$TEST_IMG" +-_img_info --format-specific ++$QEMU_IO -c "read 0 4k" "$TEST_IMG" 2>&1 | _filter_testdir | _filter_imgfmt ++$QEMU_IO -c "open -o data-file.filename=$TEST_IMG.data,file.filename=$TEST_IMG" -c "read 0 4k" | _filter_qemu_io + TEST_IMG="data-file.filename=$TEST_IMG.data,file.filename=$TEST_IMG" _img_info --format-specific --image-opts + + echo +diff --git a/tests/qemu-iotests/061.out b/tests/qemu-iotests/061.out +index 7ecbd4dea8..99b2307a23 100644 +--- a/tests/qemu-iotests/061.out ++++ b/tests/qemu-iotests/061.out +@@ -545,7 +545,9 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 + qemu-img: data-file can only be set for images that use an external data file + + Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 data_file=TEST_DIR/t.IMGFMT.data +-qemu-img: Could not open 'TEST_DIR/t.IMGFMT': Could not open 'foo': No such file or directory ++qemu-io: can't open device TEST_DIR/t.IMGFMT: Could not open 'foo': No such file or directory ++read 4096/4096 bytes at offset 0 ++4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + image: TEST_DIR/t.IMGFMT + file format: IMGFMT + virtual size: 64 MiB (67108864 bytes) +@@ -560,7 +562,9 @@ Format specific information: + corrupt: false + extended l2: false + +-qemu-img: Could not open 'TEST_DIR/t.IMGFMT': 'data-file' is required for this image ++qemu-io: can't open device TEST_DIR/t.IMGFMT: 'data-file' is required for this image ++read 4096/4096 bytes at offset 0 ++4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + image: TEST_DIR/t.IMGFMT + file format: IMGFMT + virtual size: 64 MiB (67108864 bytes) +-- +2.41.0.windows.1 + diff --git a/qemu.spec b/qemu.spec index 2aae97a5..b17d58af 100644 --- a/qemu.spec +++ b/qemu.spec @@ -3,7 +3,7 @@ Name: qemu Version: 6.2.0 -Release: 95 +Release: 96 Epoch: 10 Summary: QEMU is a generic and open source machine emulator and virtualizer License: GPLv2 and BSD and MIT and CC-BY-SA-4.0 @@ -970,6 +970,18 @@ Patch0955: tests-qtest-ahci-test-add-test-exposing-reset-issue-.patch Patch0956: cvm-bug-fix-for-macro-isolation.patch Patch0957: hw-arm-virt-Disable-DTB-randomness-for-confidential-.patch Patch0958: cvm-bug-fix-for-disable-DTB-randomness-for-confident.patch +Patch0959: hw-virtio-virtio-pci-Support-shadow-device-for-virti.patch +Patch0960: vdpa-fix-vdpa-device-migrate-rollback-wrong-when-sus.patch +Patch0961: target-ppc-Split-off-common-embedded-TLB-init.patch +Patch0962: vhost-user-Skip-unnecessary-duplicated-VHOST_USER_SE.patch +Patch0963: hw-intc-arm_gic-Fix-deactivation-of-SPI-lines.patch +Patch0964: qcow2-Do-not-reopen-data_file-in-invalidate_cache.patch +Patch0965: qcow2-Don-t-open-data_file-with-BDRV_O_NO_IO-CVE-202.patch +Patch0966: iotests-244-Don-t-store-data-file-with-protocol-in-i.patch +Patch0967: iotests-270-Don-t-store-data-file-with-json-prefix-i.patch +Patch0968: block-introduce-bdrv_open_file_child-helper.patch +Patch0969: block-Parse-filenames-only-when-explicitly-requested.patch +Patch0970: vdpa-Fix-bug-where-vdpa-appliance-migration-does-not.patch BuildRequires: flex BuildRequires: gcc @@ -1568,6 +1580,20 @@ getent passwd qemu >/dev/null || \ %endif %changelog +* Thu Jul 11 2024 - 10:6.2.0-96 +- vdpa: Fix bug where vdpa appliance migration does not resume after rollback +- block: Parse filenames only when explicitly requested (CVE-2024-4467) +- block: introduce bdrv_open_file_child() helper +- iotests/270: Don't store data-file with json: prefix in image (CVE-2024-4467) +- iotests/244: Don't store data-file with protocol in image (CVE-2024-4467) +- qcow2: Don't open data_file with BDRV_O_NO_IO (CVE-2024-4467) +- qcow2: Do not reopen data_file in invalidate_cache +- hw/intc/arm_gic: Fix deactivation of SPI lines chery-pick from 7175a562f157d39725ab396e39c1e8e410d206b3 +- vhost-user: Skip unnecessary duplicated VHOST_USER_SET_LOG_BASE requests +- target/ppc: Split off common embedded TLB init cheery-pick from 581eea5d656b73c6532109f4ced4c73fd4e5fd47` +- vdpa: fix vdpa device migrate rollback wrong when suspend device failed 1. +- hw/virtio/virtio-pci:Support shadow device for virtio-net/blk/scsi devices + * Fri Jun 21 2024 - 10:6.2.0-95 - cvm: bug-fix for disable DTB randomness for confidential VMs diff --git a/target-ppc-Split-off-common-embedded-TLB-init.patch b/target-ppc-Split-off-common-embedded-TLB-init.patch new file mode 100644 index 00000000..ecccae5d --- /dev/null +++ b/target-ppc-Split-off-common-embedded-TLB-init.patch @@ -0,0 +1,118 @@ +From 9f45d0ded0694739898e2fbbb6fa08891a7de280 Mon Sep 17 00:00:00 2001 +From: dinglimin +Date: Mon, 10 Jun 2024 15:52:59 +0800 +Subject: [PATCH] target/ppc: Split off common embedded TLB init cheery-pick + from 581eea5d656b73c6532109f4ced4c73fd4e5fd47` + +Several 4xx CPUs and e200 share the same TLB settings enclosed in an +ifdef. Split it off in a common function to reduce code duplication +and the number of ifdefs. + +Reviewed-by: Nicholas Piggin +Signed-off-by: BALATON Zoltan +Signed-off-by: Nicholas Piggin + +Signed-off-by: dinglimin +--- + target/ppc/cpu_init.c | 50 +++++++++++++------------------------------ + 1 file changed, 15 insertions(+), 35 deletions(-) + +diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c +index 986d16a24d..d0dfa1aeaf 100644 +--- a/target/ppc/cpu_init.c ++++ b/target/ppc/cpu_init.c +@@ -3018,7 +3018,15 @@ POWERPC_FAMILY(403GCX)(ObjectClass *oc, void *data) + pcc->flags = POWERPC_FLAG_CE | POWERPC_FLAG_PX | + POWERPC_FLAG_BUS_CLK; + } +- ++static void init_tlbs_emb(CPUPPCState *env) ++{ ++#if !defined(CONFIG_USER_ONLY) ++ env->nb_tlb = 64; ++ env->nb_ways = 1; ++ env->id_tlbs = 0; ++ env->tlb_type = TLB_EMB; ++#endif ++} + static void init_proc_405(CPUPPCState *env) + { + /* Time base */ +@@ -3036,13 +3044,7 @@ static void init_proc_405(CPUPPCState *env) + SPR_NOACCESS, SPR_NOACCESS, + &spr_read_generic, &spr_write_generic, + 0x00000000); +- /* Memory management */ +-#if !defined(CONFIG_USER_ONLY) +- env->nb_tlb = 64; +- env->nb_ways = 1; +- env->id_tlbs = 0; +- env->tlb_type = TLB_EMB; +-#endif ++ init_tlbs_emb(env); + init_excp_4xx_softmmu(env); + env->dcache_line_size = 32; + env->icache_line_size = 32; +@@ -3135,13 +3137,7 @@ static void init_proc_440EP(CPUPPCState *env) + SPR_NOACCESS, SPR_NOACCESS, + &spr_read_generic, &spr_write_generic, + 0x00000000); +- /* Memory management */ +-#if !defined(CONFIG_USER_ONLY) +- env->nb_tlb = 64; +- env->nb_ways = 1; +- env->id_tlbs = 0; +- env->tlb_type = TLB_EMB; +-#endif ++ init_tlbs_emb(env); + init_excp_BookE(env); + env->dcache_line_size = 32; + env->icache_line_size = 32; +@@ -3259,13 +3255,7 @@ static void init_proc_440GP(CPUPPCState *env) + SPR_NOACCESS, SPR_NOACCESS, + &spr_read_generic, &spr_write_generic, + 0x00000000); +- /* Memory management */ +-#if !defined(CONFIG_USER_ONLY) +- env->nb_tlb = 64; +- env->nb_ways = 1; +- env->id_tlbs = 0; +- env->tlb_type = TLB_EMB; +-#endif ++ init_tlbs_emb(env); + init_excp_BookE(env); + env->dcache_line_size = 32; + env->icache_line_size = 32; +@@ -3443,13 +3433,7 @@ static void init_proc_440x5(CPUPPCState *env) + SPR_NOACCESS, SPR_NOACCESS, + &spr_read_generic, &spr_write_generic, + 0x00000000); +- /* Memory management */ +-#if !defined(CONFIG_USER_ONLY) +- env->nb_tlb = 64; +- env->nb_ways = 1; +- env->id_tlbs = 0; +- env->tlb_type = TLB_EMB; +-#endif ++ init_tlbs_emb(env); + init_excp_BookE(env); + env->dcache_line_size = 32; + env->icache_line_size = 32; +@@ -3877,12 +3861,8 @@ static void init_proc_e200(CPUPPCState *env) + SPR_NOACCESS, SPR_NOACCESS, + &spr_read_generic, &spr_write_generic, + 0x00000000); +-#if !defined(CONFIG_USER_ONLY) +- env->nb_tlb = 64; +- env->nb_ways = 1; +- env->id_tlbs = 0; +- env->tlb_type = TLB_EMB; +-#endif ++ ++ init_tlbs_emb(env); + init_excp_e200(env, 0xFFFF0000UL); + env->dcache_line_size = 32; + env->icache_line_size = 32; +-- +2.41.0.windows.1 + diff --git a/vdpa-Fix-bug-where-vdpa-appliance-migration-does-not.patch b/vdpa-Fix-bug-where-vdpa-appliance-migration-does-not.patch new file mode 100644 index 00000000..b08bcaeb --- /dev/null +++ b/vdpa-Fix-bug-where-vdpa-appliance-migration-does-not.patch @@ -0,0 +1,38 @@ +From 2713ad857506ce338472e19706fbbab4ee4ba662 Mon Sep 17 00:00:00 2001 +From: Adttil <2429917001@qq.com> +Date: Mon, 8 Jul 2024 14:45:18 +0800 +Subject: [PATCH] vdpa: Fix bug where vdpa appliance migration does not resume + after rollback + +using vdpa->started to judge device started instead of vdev->vhost_started + +Signed-off-by: Adttil <2429917001@qq.com> +--- + hw/virtio/vdpa-dev-mig.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/hw/virtio/vdpa-dev-mig.c b/hw/virtio/vdpa-dev-mig.c +index 23238c9f19..c080f9d89b 100644 +--- a/hw/virtio/vdpa-dev-mig.c ++++ b/hw/virtio/vdpa-dev-mig.c +@@ -137,7 +137,7 @@ static int vhost_vdpa_device_suspend(VhostVdpaDevice *vdpa) + { + VirtIODevice *vdev = VIRTIO_DEVICE(vdpa); + +- if (!vdev->vhost_started || vdpa->suspended) { ++ if (!vdpa->started || vdpa->suspended) { + return 0; + } + +@@ -152,7 +152,7 @@ static int vhost_vdpa_device_resume(VhostVdpaDevice *vdpa) + MigrationIncomingState *mis = migration_incoming_get_current(); + int ret; + +- if (!vdev->vhost_started || ++ if (!vdpa->started || + (!vdpa->suspended && mis->state != RUN_STATE_RESTORE_VM)) { + return 0; + } +-- +2.41.0.windows.1 + diff --git a/vdpa-fix-vdpa-device-migrate-rollback-wrong-when-sus.patch b/vdpa-fix-vdpa-device-migrate-rollback-wrong-when-sus.patch new file mode 100644 index 00000000..9ebffdfc --- /dev/null +++ b/vdpa-fix-vdpa-device-migrate-rollback-wrong-when-sus.patch @@ -0,0 +1,140 @@ +From 493ef78aebf2aac04e9dbf5d1f21eb0c18763917 Mon Sep 17 00:00:00 2001 +From: jiangdongxu +Date: Sat, 22 Jun 2024 07:02:48 +0000 +Subject: [PATCH] vdpa: fix vdpa device migrate rollback wrong when suspend + device failed 1. set vdpa->suspended before call vhost_dev_suspend to make + sure vdpa device will resume when suspend failed. 2. using + vdpa->vhost_started to judge device started instead of vdev->started 3. using + state == RUN_STATE_FINISH_MIGRATE instead of ms->state == + MIGRATION_STATUS_ACTIVE to judge vm in migration. As migrate_fd_cancel will + change ms->state, which will result in some vdpa devices not being suspended. + +Signed-off-by: jiangdongxu +--- + hw/virtio/vdpa-dev-mig.c | 83 ++++------------------------------------ + 1 file changed, 8 insertions(+), 75 deletions(-) + +diff --git a/hw/virtio/vdpa-dev-mig.c b/hw/virtio/vdpa-dev-mig.c +index 679d37b182..23238c9f19 100644 +--- a/hw/virtio/vdpa-dev-mig.c ++++ b/hw/virtio/vdpa-dev-mig.c +@@ -136,100 +136,33 @@ free: + static int vhost_vdpa_device_suspend(VhostVdpaDevice *vdpa) + { + VirtIODevice *vdev = VIRTIO_DEVICE(vdpa); +- BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev))); +- VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus); +- int ret; + +- if (!vdpa->started || vdpa->suspended) { ++ if (!vdev->vhost_started || vdpa->suspended) { + return 0; + } + +- if (!k->set_guest_notifiers) { +- return -EFAULT; +- } +- +- vdpa->started = false; + vdpa->suspended = true; + +- ret = vhost_dev_suspend(&vdpa->dev, vdev, false); +- if (ret) { +- goto suspend_fail; +- } +- +- ret = k->set_guest_notifiers(qbus->parent, vdpa->dev.nvqs, false); +- if (ret < 0) { +- error_report("vhost guest notifier cleanup failed: %d\n", ret); +- goto set_guest_notifiers_fail; +- } +- +- vhost_dev_disable_notifiers(&vdpa->dev, vdev); +- return ret; +- +-set_guest_notifiers_fail: +- ret = k->set_guest_notifiers(qbus->parent, vdpa->dev.nvqs, true); +- if (ret) { +- error_report("vhost guest notifier restore failed: %d\n", ret); +- } +- +-suspend_fail: +- vdpa->suspended = false; +- vdpa->started = true; +- return ret; ++ return vhost_dev_suspend(&vdpa->dev, vdev, false); + } + + static int vhost_vdpa_device_resume(VhostVdpaDevice *vdpa) + { + VirtIODevice *vdev = VIRTIO_DEVICE(vdpa); +- BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev))); +- VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus); +- int i, ret; ++ MigrationIncomingState *mis = migration_incoming_get_current(); ++ int ret; + +- if (vdpa->started || !vdpa->suspended) { ++ if (!vdev->vhost_started || ++ (!vdpa->suspended && mis->state != RUN_STATE_RESTORE_VM)) { + return 0; + } + +- if (!k->set_guest_notifiers) { +- error_report("binding does not support guest notifiers\n"); +- return -ENOSYS; +- } +- +- ret = vhost_dev_enable_notifiers(&vdpa->dev, vdev); ++ ret = vhost_dev_resume(&vdpa->dev, vdev, false); + if (ret < 0) { +- error_report("Error enabling host notifiers: %d\n", ret); + return ret; + } + +- ret = k->set_guest_notifiers(qbus->parent, vdpa->dev.nvqs, true); +- if (ret < 0) { +- error_report("Error binding guest notifier: %d\n", ret); +- goto err_host_notifiers; +- } +- +- vdpa->dev.acked_features = vdev->guest_features; +- +- ret = vhost_dev_resume(&vdpa->dev, vdev, false); +- if (ret < 0) { +- error_report("Error starting vhost: %d\n", ret); +- goto err_guest_notifiers; +- } +- vdpa->started = true; + vdpa->suspended = false; +- +- /* +- * guest_notifier_mask/pending not used yet, so just unmask +- * everything here. virtio-pci will do the right thing by +- * enabling/disabling irqfd. +- */ +- for (i = 0; i < vdpa->dev.nvqs; i++) { +- vhost_virtqueue_mask(&vdpa->dev, vdev, i, false); +- } +- +- return ret; +- +-err_guest_notifiers: +- k->set_guest_notifiers(qbus->parent, vdpa->dev.nvqs, false); +-err_host_notifiers: +- vhost_dev_disable_notifiers(&vdpa->dev, vdev); + return ret; + } + +@@ -254,7 +187,7 @@ static void vdpa_dev_vmstate_change(void *opaque, bool running, RunState state) + MigrationIncomingState *mis = migration_incoming_get_current(); + + if (!running) { +- if (ms->state == MIGRATION_STATUS_ACTIVE || state == RUN_STATE_PAUSED) { ++ if (state == RUN_STATE_FINISH_MIGRATE || state == RUN_STATE_PAUSED) { + ret = vhost_vdpa_device_suspend(vdpa); + if (ret) { + error_report("suspend vdpa device failed: %d\n", ret); +-- +2.41.0.windows.1 + diff --git a/vhost-user-Skip-unnecessary-duplicated-VHOST_USER_SE.patch b/vhost-user-Skip-unnecessary-duplicated-VHOST_USER_SE.patch new file mode 100644 index 00000000..1b754bfe --- /dev/null +++ b/vhost-user-Skip-unnecessary-duplicated-VHOST_USER_SE.patch @@ -0,0 +1,31 @@ +From 24e57d8013b2d039ed917676b7fb34d3736c9d8d Mon Sep 17 00:00:00 2001 +From: BillXiang <1373760142@qq.com> +Date: Wed, 19 Jun 2024 09:24:05 +0800 +Subject: [PATCH] vhost-user: Skip unnecessary duplicated + VHOST_USER_SET_LOG_BASE requests + +The VHOST_USER_SET_LOG_BASE requests should be categorized into +non-vring specific messages, and should be sent only once. +If send more than once, dpdk will munmap old log_addr which may has been used +and cause segmentation fault. + +Signed-off-by: BillXiang <1373760142@qq.com> +--- + hw/virtio/vhost-user.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c +index 937b3021e9..c97ea2544d 100644 +--- a/hw/virtio/vhost-user.c ++++ b/hw/virtio/vhost-user.c +@@ -456,6 +456,7 @@ static bool vhost_user_one_time_request(VhostUserRequest request) + case VHOST_USER_SET_MEM_TABLE: + case VHOST_USER_GET_QUEUE_NUM: + case VHOST_USER_NET_SET_MTU: ++ case VHOST_USER_SET_LOG_BASE: + return true; + default: + return false; +-- +2.41.0.windows.1 + -- Gitee From 8a522bdd9f1252638e4fc88a113f2f95f41f5db1 Mon Sep 17 00:00:00 2001 From: Jiabo Feng Date: Tue, 13 Aug 2024 16:18:01 +0800 Subject: [PATCH 14/19] QEMU update to version 6.2.0-97: - nbd/server: CVE-2024-7409: Close stray clients at server-stop - main-loop.h: introduce qemu_in_main_thread() - aio-wait.h: introduce AIO_WAIT_WHILE_UNLOCKED - nbd/server: CVE-2024-7409: Drop non-negotiating clients - nbd/server: CVE-2024-7409: Cap default max-connections to 100 - nbd/server: Plumb in new args to nbd_client_add() - nbd: Minor style and typo fixes Signed-off-by: Jiabo Feng (cherry picked from commit 5e30f8e310a15452f86723a0ae459d303cc29470) --- ....h-introduce-AIO_WAIT_WHILE_UNLOCKED.patch | 79 ++++++++ ...loop.h-introduce-qemu_in_main_thread.patch | 118 ++++++++++++ nbd-Minor-style-and-typo-fixes.patch | 49 +++++ ...024-7409-Cap-default-max-connections.patch | 175 ++++++++++++++++++ ...024-7409-Close-stray-clients-at-serv.patch | 163 ++++++++++++++++ ...024-7409-Drop-non-negotiating-client.patch | 122 ++++++++++++ ...-Plumb-in-new-args-to-nbd_client_add.patch | 162 ++++++++++++++++ qemu.spec | 18 +- 8 files changed, 885 insertions(+), 1 deletion(-) create mode 100644 aio-wait.h-introduce-AIO_WAIT_WHILE_UNLOCKED.patch create mode 100644 main-loop.h-introduce-qemu_in_main_thread.patch create mode 100644 nbd-Minor-style-and-typo-fixes.patch create mode 100644 nbd-server-CVE-2024-7409-Cap-default-max-connections.patch create mode 100644 nbd-server-CVE-2024-7409-Close-stray-clients-at-serv.patch create mode 100644 nbd-server-CVE-2024-7409-Drop-non-negotiating-client.patch create mode 100644 nbd-server-Plumb-in-new-args-to-nbd_client_add.patch diff --git a/aio-wait.h-introduce-AIO_WAIT_WHILE_UNLOCKED.patch b/aio-wait.h-introduce-AIO_WAIT_WHILE_UNLOCKED.patch new file mode 100644 index 00000000..a6bddfef --- /dev/null +++ b/aio-wait.h-introduce-AIO_WAIT_WHILE_UNLOCKED.patch @@ -0,0 +1,79 @@ +From 0943a32cdfc513c7a845ecd4dabba06fb1ca46a6 Mon Sep 17 00:00:00 2001 +From: Emanuele Giuseppe Esposito +Date: Mon, 26 Sep 2022 05:31:57 -0400 +Subject: [PATCH 5/7] aio-wait.h: introduce AIO_WAIT_WHILE_UNLOCKED + +Same as AIO_WAIT_WHILE macro, but if we are in the Main loop +do not release and then acquire ctx_ 's aiocontext. + +Once all Aiocontext locks go away, this macro will replace +AIO_WAIT_WHILE. + +Signed-off-by: Emanuele Giuseppe Esposito +Reviewed-by: Stefan Hajnoczi +Reviewed-by: Vladimir Sementsov-Ogievskiy +Message-Id: <20220926093214.506243-5-eesposit@redhat.com> +Reviewed-by: Kevin Wolf +Signed-off-by: Kevin Wolf +--- + include/block/aio-wait.h | 17 +++++++++++++---- + 1 file changed, 13 insertions(+), 4 deletions(-) + +diff --git a/include/block/aio-wait.h b/include/block/aio-wait.h +index b39eefb38d..e4b811433d 100644 +--- a/include/block/aio-wait.h ++++ b/include/block/aio-wait.h +@@ -59,10 +59,13 @@ typedef struct { + extern AioWait global_aio_wait; + + /** +- * AIO_WAIT_WHILE: ++ * AIO_WAIT_WHILE_INTERNAL: + * @ctx: the aio context, or NULL if multiple aio contexts (for which the + * caller does not hold a lock) are involved in the polling condition. + * @cond: wait while this conditional expression is true ++ * @unlock: whether to unlock and then lock again @ctx. This apples ++ * only when waiting for another AioContext from the main loop. ++ * Otherwise it's ignored. + * + * Wait while a condition is true. Use this to implement synchronous + * operations that require event loop activity. +@@ -75,7 +78,7 @@ extern AioWait global_aio_wait; + * wait on conditions between two IOThreads since that could lead to deadlock, + * go via the main loop instead. + */ +-#define AIO_WAIT_WHILE(ctx, cond) ({ \ ++#define AIO_WAIT_WHILE_INTERNAL(ctx, cond, unlock) ({ \ + bool waited_ = false; \ + AioWait *wait_ = &global_aio_wait; \ + AioContext *ctx_ = (ctx); \ +@@ -90,11 +93,11 @@ extern AioWait global_aio_wait; + assert(qemu_get_current_aio_context() == \ + qemu_get_aio_context()); \ + while ((cond)) { \ +- if (ctx_) { \ ++ if (unlock && ctx_) { \ + aio_context_release(ctx_); \ + } \ + aio_poll(qemu_get_aio_context(), true); \ +- if (ctx_) { \ ++ if (unlock && ctx_) { \ + aio_context_acquire(ctx_); \ + } \ + waited_ = true; \ +@@ -103,6 +106,12 @@ extern AioWait global_aio_wait; + qatomic_dec(&wait_->num_waiters); \ + waited_; }) + ++#define AIO_WAIT_WHILE(ctx, cond) \ ++ AIO_WAIT_WHILE_INTERNAL(ctx, cond, true) ++ ++#define AIO_WAIT_WHILE_UNLOCKED(ctx, cond) \ ++ AIO_WAIT_WHILE_INTERNAL(ctx, cond, false) ++ + /** + * aio_wait_kick: + * Wake up the main thread if it is waiting on AIO_WAIT_WHILE(). During +-- +2.45.1.windows.1 + diff --git a/main-loop.h-introduce-qemu_in_main_thread.patch b/main-loop.h-introduce-qemu_in_main_thread.patch new file mode 100644 index 00000000..2296c06b --- /dev/null +++ b/main-loop.h-introduce-qemu_in_main_thread.patch @@ -0,0 +1,118 @@ +From f4b69408785a19f4acd0b16cd3b97aa93da48d47 Mon Sep 17 00:00:00 2001 +From: Emanuele Giuseppe Esposito +Date: Thu, 3 Mar 2022 10:15:46 -0500 +Subject: [PATCH 6/7] main-loop.h: introduce qemu_in_main_thread() + +When invoked from the main loop, this function is the same +as qemu_mutex_iothread_locked, and returns true if the BQL is held. +When invoked from iothreads or tests, it returns true only +if the current AioContext is the Main Loop. + +This essentially just extends qemu_mutex_iothread_locked to work +also in unit tests or other users like storage-daemon, that run +in the Main Loop but end up using the implementation in +stubs/iothread-lock.c. + +Using qemu_mutex_iothread_locked in unit tests defaults to false +because they use the implementation in stubs/iothread-lock, +making all assertions added in next patches fail despite the +AioContext is still the main loop. + +See the comment in the function header for more information. + +Signed-off-by: Emanuele Giuseppe Esposito +Message-Id: <20220303151616.325444-2-eesposit@redhat.com> +Signed-off-by: Kevin Wolf +--- + include/qemu/main-loop.h | 24 ++++++++++++++++++++++++ + softmmu/cpus.c | 5 +++++ + stubs/iothread-lock-block.c | 8 ++++++++ + stubs/meson.build | 3 +++ + 4 files changed, 40 insertions(+) + create mode 100644 stubs/iothread-lock-block.c + +diff --git a/include/qemu/main-loop.h b/include/qemu/main-loop.h +index 85dd5ada9e..a472ebd289 100644 +--- a/include/qemu/main-loop.h ++++ b/include/qemu/main-loop.h +@@ -242,9 +242,33 @@ AioContext *iohandler_get_aio_context(void); + * must always be taken outside other locks. This function helps + * functions take different paths depending on whether the current + * thread is running within the main loop mutex. ++ * ++ * This function should never be used in the block layer, because ++ * unit tests, block layer tools and qemu-storage-daemon do not ++ * have a BQL. ++ * Please instead refer to qemu_in_main_thread(). + */ + bool qemu_mutex_iothread_locked(void); + ++/** ++ * qemu_in_main_thread: return whether it's possible to safely access ++ * the global state of the block layer. ++ * ++ * Global state of the block layer is not accessible from I/O threads ++ * or worker threads; only from threads that "own" the default ++ * AioContext that qemu_get_aio_context() returns. For tests, block ++ * layer tools and qemu-storage-daemon there is a designated thread that ++ * runs the event loop for qemu_get_aio_context(), and that is the ++ * main thread. ++ * ++ * For emulators, however, any thread that holds the BQL can act ++ * as the block layer main thread; this will be any of the actual ++ * main thread, the vCPU threads or the RCU thread. ++ * ++ * For clarity, do not use this function outside the block layer. ++ */ ++bool qemu_in_main_thread(void); ++ + /** + * qemu_mutex_lock_iothread: Lock the main loop mutex. + * +diff --git a/softmmu/cpus.c b/softmmu/cpus.c +index 071085f840..3f61a3c31d 100644 +--- a/softmmu/cpus.c ++++ b/softmmu/cpus.c +@@ -481,6 +481,11 @@ bool qemu_mutex_iothread_locked(void) + return iothread_locked; + } + ++bool qemu_in_main_thread(void) ++{ ++ return qemu_mutex_iothread_locked(); ++} ++ + /* + * The BQL is taken from so many places that it is worth profiling the + * callers directly, instead of funneling them all through a single function. +diff --git a/stubs/iothread-lock-block.c b/stubs/iothread-lock-block.c +new file mode 100644 +index 0000000000..c88ed70462 +--- /dev/null ++++ b/stubs/iothread-lock-block.c +@@ -0,0 +1,8 @@ ++#include "qemu/osdep.h" ++#include "qemu/main-loop.h" ++ ++bool qemu_in_main_thread(void) ++{ ++ return qemu_get_current_aio_context() == qemu_get_aio_context(); ++} ++ +diff --git a/stubs/meson.build b/stubs/meson.build +index 71469c1d50..3aca1d67c1 100644 +--- a/stubs/meson.build ++++ b/stubs/meson.build +@@ -18,6 +18,9 @@ if linux_io_uring.found() + stub_ss.add(files('io_uring.c')) + endif + stub_ss.add(files('iothread-lock.c')) ++if have_block ++ stub_ss.add(files('iothread-lock-block.c')) ++endif + stub_ss.add(files('isa-bus.c')) + stub_ss.add(files('is-daemonized.c')) + if libaio.found() +-- +2.45.1.windows.1 + diff --git a/nbd-Minor-style-and-typo-fixes.patch b/nbd-Minor-style-and-typo-fixes.patch new file mode 100644 index 00000000..9c69c659 --- /dev/null +++ b/nbd-Minor-style-and-typo-fixes.patch @@ -0,0 +1,49 @@ +From 1953dfe58fae8c778b275d786a4166add940353d Mon Sep 17 00:00:00 2001 +From: Eric Blake +Date: Thu, 1 Aug 2024 16:49:20 -0500 +Subject: [PATCH 1/7] nbd: Minor style and typo fixes +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Touch up a comment with the wrong type name, and an over-long line, +both noticed while working on upcoming patches. + +Signed-off-by: Eric Blake +Message-ID: <20240807174943.771624-10-eblake@redhat.com> +Reviewed-by: Daniel P. Berrangé +--- + nbd/server.c | 2 +- + qemu-nbd.c | 3 ++- + 2 files changed, 3 insertions(+), 2 deletions(-) + +diff --git a/nbd/server.c b/nbd/server.c +index 37515ed520..73fd4c46d1 100644 +--- a/nbd/server.c ++++ b/nbd/server.c +@@ -1801,7 +1801,7 @@ static void nbd_export_request_shutdown(BlockExport *blk_exp) + + blk_exp_ref(&exp->common); + /* +- * TODO: Should we expand QMP NbdServerRemoveNode enum to allow a ++ * TODO: Should we expand QMP BlockExportRemoveMode enum to allow a + * close mode that stops advertising the export to new clients but + * still permits existing clients to run to completion? Because of + * that possibility, nbd_export_close() can be called more than +diff --git a/qemu-nbd.c b/qemu-nbd.c +index 15a4bc4018..86dfa0b5d9 100644 +--- a/qemu-nbd.c ++++ b/qemu-nbd.c +@@ -561,7 +561,8 @@ int main(int argc, char **argv) + pthread_t client_thread; + const char *fmt = NULL; + Error *local_err = NULL; +- BlockdevDetectZeroesOptions detect_zeroes = BLOCKDEV_DETECT_ZEROES_OPTIONS_OFF; ++ BlockdevDetectZeroesOptions detect_zeroes = ++ BLOCKDEV_DETECT_ZEROES_OPTIONS_OFF; + QDict *options = NULL; + const char *export_name = NULL; /* defaults to "" later for server mode */ + const char *export_description = NULL; +-- +2.45.1.windows.1 + diff --git a/nbd-server-CVE-2024-7409-Cap-default-max-connections.patch b/nbd-server-CVE-2024-7409-Cap-default-max-connections.patch new file mode 100644 index 00000000..c81f2c27 --- /dev/null +++ b/nbd-server-CVE-2024-7409-Cap-default-max-connections.patch @@ -0,0 +1,175 @@ +From ed53c5fb670478378c72f2d4312160eccf34a6dd Mon Sep 17 00:00:00 2001 +From: Eric Blake +Date: Tue, 6 Aug 2024 13:53:00 -0500 +Subject: [PATCH 3/7] nbd/server: CVE-2024-7409: Cap default max-connections to + 100 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Allowing an unlimited number of clients to any web service is a recipe +for a rudimentary denial of service attack: the client merely needs to +open lots of sockets without closing them, until qemu no longer has +any more fds available to allocate. + +For qemu-nbd, we default to allowing only 1 connection unless more are +explicitly asked for (-e or --shared); this was historically picked as +a nice default (without an explicit -t, a non-persistent qemu-nbd goes +away after a client disconnects, without needing any additional +follow-up commands), and we are not going to change that interface now +(besides, someday we want to point people towards qemu-storage-daemon +instead of qemu-nbd). + +But for qemu proper, and the newer qemu-storage-daemon, the QMP +nbd-server-start command has historically had a default of unlimited +number of connections, in part because unlike qemu-nbd it is +inherently persistent until nbd-server-stop. Allowing multiple client +sockets is particularly useful for clients that can take advantage of +MULTI_CONN (creating parallel sockets to increase throughput), +although known clients that do so (such as libnbd's nbdcopy) typically +use only 8 or 16 connections (the benefits of scaling diminish once +more sockets are competing for kernel attention). Picking a number +large enough for typical use cases, but not unlimited, makes it +slightly harder for a malicious client to perform a denial of service +merely by opening lots of connections withot progressing through the +handshake. + +This change does not eliminate CVE-2024-7409 on its own, but reduces +the chance for fd exhaustion or unlimited memory usage as an attack +surface. On the other hand, by itself, it makes it more obvious that +with a finite limit, we have the problem of an unauthenticated client +holding 100 fds opened as a way to block out a legitimate client from +being able to connect; thus, later patches will further add timeouts +to reject clients that are not making progress. + +This is an INTENTIONAL change in behavior, and will break any client +of nbd-server-start that was not passing an explicit max-connections +parameter, yet expects more than 100 simultaneous connections. We are +not aware of any such client (as stated above, most clients aware of +MULTI_CONN get by just fine on 8 or 16 connections, and probably cope +with later connections failing by relying on the earlier connections; +libvirt has not yet been passing max-connections, but generally +creates NBD servers with the intent for a single client for the sake +of live storage migration; meanwhile, the KubeSAN project anticipates +a large cluster sharing multiple clients [up to 8 per node, and up to +100 nodes in a cluster], but it currently uses qemu-nbd with an +explicit --shared=0 rather than qemu-storage-daemon with +nbd-server-start). + +We considered using a deprecation period (declare that omitting +max-parameters is deprecated, and make it mandatory in 3 releases - +then we don't need to pick an arbitrary default); that has zero risk +of breaking any apps that accidentally depended on more than 100 +connections, and where such breakage might not be noticed under unit +testing but only under the larger loads of production usage. But it +does not close the denial-of-service hole until far into the future, +and requires all apps to change to add the parameter even if 100 was +good enough. It also has a drawback that any app (like libvirt) that +is accidentally relying on an unlimited default should seriously +consider their own CVE now, at which point they are going to change to +pass explicit max-connections sooner than waiting for 3 qemu releases. +Finally, if our changed default breaks an app, that app can always +pass in an explicit max-parameters with a larger value. + +It is also intentional that the HMP interface to nbd-server-start is +not changed to expose max-connections (any client needing to fine-tune +things should be using QMP). + +Suggested-by: Daniel P. Berrangé +Signed-off-by: Eric Blake +Message-ID: <20240807174943.771624-12-eblake@redhat.com> +Reviewed-by: Daniel P. Berrangé +[ericb: Expand commit message to summarize Dan's argument for why we +break corner-case back-compat behavior without a deprecation period] +Signed-off-by: Eric Blake +Signed-off-by: liuxiangdong +--- + block/monitor/block-hmp-cmds.c | 3 ++- + blockdev-nbd.c | 8 ++++++++ + include/block/nbd.h | 7 +++++++ + qapi/block-export.json | 4 ++-- + 4 files changed, 19 insertions(+), 3 deletions(-) + +diff --git a/block/monitor/block-hmp-cmds.c b/block/monitor/block-hmp-cmds.c +index 44f0af3430..bc4bd46b47 100644 +--- a/block/monitor/block-hmp-cmds.c ++++ b/block/monitor/block-hmp-cmds.c +@@ -413,7 +413,8 @@ void hmp_nbd_server_start(Monitor *mon, const QDict *qdict) + goto exit; + } + +- nbd_server_start(addr, NULL, NULL, 0, &local_err); ++ nbd_server_start(addr, NULL, NULL, NBD_DEFAULT_MAX_CONNECTIONS, ++ &local_err); + qapi_free_SocketAddress(addr); + if (local_err != NULL) { + goto exit; +diff --git a/blockdev-nbd.c b/blockdev-nbd.c +index b9e8dc78f3..4bd90bac16 100644 +--- a/blockdev-nbd.c ++++ b/blockdev-nbd.c +@@ -171,6 +171,10 @@ void nbd_server_start(SocketAddress *addr, const char *tls_creds, + + void nbd_server_start_options(NbdServerOptions *arg, Error **errp) + { ++ if (!arg->has_max_connections) { ++ arg->max_connections = NBD_DEFAULT_MAX_CONNECTIONS; ++ } ++ + nbd_server_start(arg->addr, arg->tls_creds, arg->tls_authz, + arg->max_connections, errp); + } +@@ -183,6 +187,10 @@ void qmp_nbd_server_start(SocketAddressLegacy *addr, + { + SocketAddress *addr_flat = socket_address_flatten(addr); + ++ if (!has_max_connections) { ++ max_connections = NBD_DEFAULT_MAX_CONNECTIONS; ++ } ++ + nbd_server_start(addr_flat, tls_creds, tls_authz, max_connections, errp); + qapi_free_SocketAddress(addr_flat); + } +diff --git a/include/block/nbd.h b/include/block/nbd.h +index b71a297249..a31c34a8a6 100644 +--- a/include/block/nbd.h ++++ b/include/block/nbd.h +@@ -33,6 +33,13 @@ extern const BlockExportDriver blk_exp_nbd; + */ + #define NBD_DEFAULT_HANDSHAKE_MAX_SECS 10 + ++/* ++ * NBD_DEFAULT_MAX_CONNECTIONS: Number of client sockets to allow at ++ * once; must be large enough to allow a MULTI_CONN-aware client like ++ * nbdcopy to create its typical number of 8-16 sockets. ++ */ ++#define NBD_DEFAULT_MAX_CONNECTIONS 100 ++ + /* Handshake phase structs - this struct is passed on the wire */ + + struct NBDOption { +diff --git a/qapi/block-export.json b/qapi/block-export.json +index c1b92ce1c1..181d7238fe 100644 +--- a/qapi/block-export.json ++++ b/qapi/block-export.json +@@ -21,7 +21,7 @@ + # recreated on the fly while the NBD server is active. + # If missing, it will default to denying access (since 4.0). + # @max-connections: The maximum number of connections to allow at the same +-# time, 0 for unlimited. (since 5.2; default: 0) ++# time, 0 for unlimited. (since 5.2; default: 100) + # + # Since: 4.2 + ## +@@ -50,7 +50,7 @@ + # recreated on the fly while the NBD server is active. + # If missing, it will default to denying access (since 4.0). + # @max-connections: The maximum number of connections to allow at the same +-# time, 0 for unlimited. (since 5.2; default: 0) ++# time, 0 for unlimited. (since 5.2; default: 100) + # + # Returns: error if the server is already running. + # +-- +2.45.1.windows.1 + diff --git a/nbd-server-CVE-2024-7409-Close-stray-clients-at-serv.patch b/nbd-server-CVE-2024-7409-Close-stray-clients-at-serv.patch new file mode 100644 index 00000000..decbed2b --- /dev/null +++ b/nbd-server-CVE-2024-7409-Close-stray-clients-at-serv.patch @@ -0,0 +1,163 @@ +From 494093a8482a044290275e01d310100e874cc701 Mon Sep 17 00:00:00 2001 +From: Eric Blake +Date: Wed, 7 Aug 2024 12:23:13 -0500 +Subject: [PATCH 7/7] nbd/server: CVE-2024-7409: Close stray clients at + server-stop +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +A malicious client can attempt to connect to an NBD server, and then +intentionally delay progress in the handshake, including if it does +not know the TLS secrets. Although the previous two patches reduce +this behavior by capping the default max-connections parameter and +killing slow clients, they did not eliminate the possibility of a +client waiting to close the socket until after the QMP nbd-server-stop +command is executed, at which point qemu would SEGV when trying to +dereference the NULL nbd_server global which is no longer present. +This amounts to a denial of service attack. Worse, if another NBD +server is started before the malicious client disconnects, I cannot +rule out additional adverse effects when the old client interferes +with the connection count of the new server (although the most likely +is a crash due to an assertion failure when checking +nbd_server->connections > 0). + +For environments without this patch, the CVE can be mitigated by +ensuring (such as via a firewall) that only trusted clients can +connect to an NBD server. Note that using frameworks like libvirt +that ensure that TLS is used and that nbd-server-stop is not executed +while any trusted clients are still connected will only help if there +is also no possibility for an untrusted client to open a connection +but then stall on the NBD handshake. + +Given the previous patches, it would be possible to guarantee that no +clients remain connected by having nbd-server-stop sleep for longer +than the default handshake deadline before finally freeing the global +nbd_server object, but that could make QMP non-responsive for a long +time. So intead, this patch fixes the problem by tracking all client +sockets opened while the server is running, and forcefully closing any +such sockets remaining without a completed handshake at the time of +nbd-server-stop, then waiting until the coroutines servicing those +sockets notice the state change. nbd-server-stop now has a second +AIO_WAIT_WHILE_UNLOCKED (the first is indirectly through the +blk_exp_close_all_type() that disconnects all clients that completed +handshakes), but forced socket shutdown is enough to progress the +coroutines and quickly tear down all clients before the server is +freed, thus finally fixing the CVE. + +This patch relies heavily on the fact that nbd/server.c guarantees +that it only calls nbd_blockdev_client_closed() from the main loop +(see the assertion in nbd_client_put() and the hoops used in +nbd_client_put_nonzero() to achieve that); if we did not have that +guarantee, we would also need a mutex protecting our accesses of the +list of connections to survive re-entrancy from independent iothreads. + +Although I did not actually try to test old builds, it looks like this +problem has existed since at least commit 862172f45c (v2.12.0, 2017) - +even back when that patch started using a QIONetListener to handle +listening on multiple sockets, nbd_server_free() was already unaware +that the nbd_blockdev_client_closed callback can be reached later by a +client thread that has not completed handshakes (and therefore the +client's socket never got added to the list closed in +nbd_export_close_all), despite that patch intentionally tearing down +the QIONetListener to prevent new clients. + +Reported-by: Alexander Ivanov +Fixes: CVE-2024-7409 +CC: qemu-stable@nongnu.org +Signed-off-by: Eric Blake +Message-ID: <20240807174943.771624-14-eblake@redhat.com> +Reviewed-by: Daniel P. Berrangé +--- + blockdev-nbd.c | 35 ++++++++++++++++++++++++++++++++++- + 1 file changed, 34 insertions(+), 1 deletion(-) + +diff --git a/blockdev-nbd.c b/blockdev-nbd.c +index 4bd90bac16..c71ca38d29 100644 +--- a/blockdev-nbd.c ++++ b/blockdev-nbd.c +@@ -21,12 +21,18 @@ + #include "io/channel-socket.h" + #include "io/net-listener.h" + ++typedef struct NBDConn { ++ QIOChannelSocket *cioc; ++ QLIST_ENTRY(NBDConn) next; ++} NBDConn; ++ + typedef struct NBDServerData { + QIONetListener *listener; + QCryptoTLSCreds *tlscreds; + char *tlsauthz; + uint32_t max_connections; + uint32_t connections; ++ QLIST_HEAD(, NBDConn) conns; + } NBDServerData; + + static NBDServerData *nbd_server; +@@ -46,6 +52,14 @@ bool nbd_server_is_running(void) + + static void nbd_blockdev_client_closed(NBDClient *client, bool ignored) + { ++ NBDConn *conn = nbd_client_owner(client); ++ ++ assert(qemu_in_main_thread() && nbd_server); ++ ++ object_unref(OBJECT(conn->cioc)); ++ QLIST_REMOVE(conn, next); ++ g_free(conn); ++ + nbd_client_put(client); + assert(nbd_server->connections > 0); + nbd_server->connections--; +@@ -55,14 +69,20 @@ static void nbd_blockdev_client_closed(NBDClient *client, bool ignored) + static void nbd_accept(QIONetListener *listener, QIOChannelSocket *cioc, + gpointer opaque) + { ++ NBDConn *conn = g_new0(NBDConn, 1); ++ ++ assert(qemu_in_main_thread() && nbd_server); + nbd_server->connections++; ++ object_ref(OBJECT(cioc)); ++ conn->cioc = cioc; ++ QLIST_INSERT_HEAD(&nbd_server->conns, conn, next); + nbd_update_server_watch(nbd_server); + + qio_channel_set_name(QIO_CHANNEL(cioc), "nbd-server"); + /* TODO - expose handshake timeout as QMP option */ + nbd_client_new(cioc, NBD_DEFAULT_HANDSHAKE_MAX_SECS, + nbd_server->tlscreds, nbd_server->tlsauthz, +- nbd_blockdev_client_closed, NULL); ++ nbd_blockdev_client_closed, conn); + } + + static void nbd_update_server_watch(NBDServerData *s) +@@ -76,12 +96,25 @@ static void nbd_update_server_watch(NBDServerData *s) + + static void nbd_server_free(NBDServerData *server) + { ++ NBDConn *conn, *tmp; ++ + if (!server) { + return; + } + ++ /* ++ * Forcefully close the listener socket, and any clients that have ++ * not yet disconnected on their own. ++ */ + qio_net_listener_disconnect(server->listener); + object_unref(OBJECT(server->listener)); ++ QLIST_FOREACH_SAFE(conn, &server->conns, next, tmp) { ++ qio_channel_shutdown(QIO_CHANNEL(conn->cioc), QIO_CHANNEL_SHUTDOWN_BOTH, ++ NULL); ++ } ++ ++ AIO_WAIT_WHILE_UNLOCKED(NULL, server->connections > 0); ++ + if (server->tlscreds) { + object_unref(OBJECT(server->tlscreds)); + } +-- +2.45.1.windows.1 + diff --git a/nbd-server-CVE-2024-7409-Drop-non-negotiating-client.patch b/nbd-server-CVE-2024-7409-Drop-non-negotiating-client.patch new file mode 100644 index 00000000..769b4d5a --- /dev/null +++ b/nbd-server-CVE-2024-7409-Drop-non-negotiating-client.patch @@ -0,0 +1,122 @@ +From 66aa9657f2c64095a18aa90920d53f36f06fea37 Mon Sep 17 00:00:00 2001 +From: Eric Blake +Date: Thu, 8 Aug 2024 16:05:08 -0500 +Subject: [PATCH 4/7] nbd/server: CVE-2024-7409: Drop non-negotiating clients +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +A client that opens a socket but does not negotiate is merely hogging +qemu's resources (an open fd and a small amount of memory); and a +malicious client that can access the port where NBD is listening can +attempt a denial of service attack by intentionally opening and +abandoning lots of unfinished connections. The previous patch put a +default bound on the number of such ongoing connections, but once that +limit is hit, no more clients can connect (including legitimate ones). +The solution is to insist that clients complete handshake within a +reasonable time limit, defaulting to 10 seconds. A client that has +not successfully completed NBD_OPT_GO by then (including the case of +where the client didn't know TLS credentials to even reach the point +of NBD_OPT_GO) is wasting our time and does not deserve to stay +connected. Later patches will allow fine-tuning the limit away from +the default value (including disabling it for doing integration +testing of the handshake process itself). + +Note that this patch in isolation actually makes it more likely to see +qemu SEGV after nbd-server-stop, as any client socket still connected +when the server shuts down will now be closed after 10 seconds rather +than at the client's whims. That will be addressed in the next patch. + +For a demo of this patch in action: +$ qemu-nbd -f raw -r -t -e 10 file & +$ nbdsh --opt-mode -c ' +H = list() +for i in range(20): + print(i) + H.insert(i, nbd.NBD()) + H[i].set_opt_mode(True) + H[i].connect_uri("nbd://localhost") +' +$ kill $! + +where later connections get to start progressing once earlier ones are +forcefully dropped for taking too long, rather than hanging. + +Suggested-by: Daniel P. Berrangé +Signed-off-by: Eric Blake +Message-ID: <20240807174943.771624-13-eblake@redhat.com> +Reviewed-by: Daniel P. Berrangé +[eblake: rebase to changes earlier in series, reduce scope of timer] +Signed-off-by: Eric Blake +Signed-off-by: liuxiangdong +--- + nbd/server.c | 28 +++++++++++++++++++++++++++- + nbd/trace-events | 1 + + 2 files changed, 28 insertions(+), 1 deletion(-) + +diff --git a/nbd/server.c b/nbd/server.c +index fff9e98bac..026e0b5919 100644 +--- a/nbd/server.c ++++ b/nbd/server.c +@@ -2702,22 +2702,48 @@ static void nbd_client_receive_next_request(NBDClient *client) + } + } + ++static void nbd_handshake_timer_cb(void *opaque) ++{ ++ QIOChannel *ioc = opaque; ++ ++ trace_nbd_handshake_timer_cb(); ++ qio_channel_shutdown(ioc, QIO_CHANNEL_SHUTDOWN_BOTH, NULL); ++} ++ + static coroutine_fn void nbd_co_client_start(void *opaque) + { + NBDClient *client = opaque; + Error *local_err = NULL; ++ QEMUTimer *handshake_timer = NULL; + + qemu_co_mutex_init(&client->send_lock); + +- /* TODO - utilize client->handshake_max_secs */ ++ /* ++ * Create a timer to bound the time spent in negotiation. If the ++ * timer expires, it is likely nbd_negotiate will fail because the ++ * socket was shutdown. ++ */ ++ if (client->handshake_max_secs > 0) { ++ handshake_timer = aio_timer_new(qemu_get_aio_context(), ++ QEMU_CLOCK_REALTIME, ++ SCALE_NS, ++ nbd_handshake_timer_cb, ++ client->sioc); ++ timer_mod(handshake_timer, ++ qemu_clock_get_ns(QEMU_CLOCK_REALTIME) + ++ client->handshake_max_secs * NANOSECONDS_PER_SECOND); ++ } ++ + if (nbd_negotiate(client, &local_err)) { + if (local_err) { + error_report_err(local_err); + } ++ timer_free(handshake_timer); + client_close(client, false); + return; + } + ++ timer_free(handshake_timer); + nbd_client_receive_next_request(client); + } + +diff --git a/nbd/trace-events b/nbd/trace-events +index c4919a2dd5..553546f1f2 100644 +--- a/nbd/trace-events ++++ b/nbd/trace-events +@@ -73,3 +73,4 @@ nbd_co_receive_request_decode_type(uint64_t handle, uint16_t type, const char *n + nbd_co_receive_request_payload_received(uint64_t handle, uint32_t len) "Payload received: handle = %" PRIu64 ", len = %" PRIu32 + nbd_co_receive_align_compliance(const char *op, uint64_t from, uint32_t len, uint32_t align) "client sent non-compliant unaligned %s request: from=0x%" PRIx64 ", len=0x%" PRIx32 ", align=0x%" PRIx32 + nbd_trip(void) "Reading request" ++nbd_handshake_timer_cb(void) "client took too long to negotiate" +-- +2.45.1.windows.1 + diff --git a/nbd-server-Plumb-in-new-args-to-nbd_client_add.patch b/nbd-server-Plumb-in-new-args-to-nbd_client_add.patch new file mode 100644 index 00000000..e453d055 --- /dev/null +++ b/nbd-server-Plumb-in-new-args-to-nbd_client_add.patch @@ -0,0 +1,162 @@ +From f529a09058a1a5c9069b9ca506780546b8e7acca Mon Sep 17 00:00:00 2001 +From: Eric Blake +Date: Wed, 7 Aug 2024 08:50:01 -0500 +Subject: [PATCH 2/7] nbd/server: Plumb in new args to nbd_client_add() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Upcoming patches to fix a CVE need to track an opaque pointer passed +in by the owner of a client object, as well as request for a time +limit on how fast negotiation must complete. Prepare for that by +changing the signature of nbd_client_new() and adding an accessor to +get at the opaque pointer, although for now the two servers +(qemu-nbd.c and blockdev-nbd.c) do not change behavior even though +they pass in a new default timeout value. + +Suggested-by: Vladimir Sementsov-Ogievskiy +Signed-off-by: Eric Blake +Message-ID: <20240807174943.771624-11-eblake@redhat.com> +Reviewed-by: Daniel P. Berrangé +[eblake: s/LIMIT/MAX_SECS/ as suggested by Dan] +Signed-off-by: Eric Blake +--- + blockdev-nbd.c | 6 ++++-- + include/block/nbd.h | 11 ++++++++++- + nbd/server.c | 20 +++++++++++++++++--- + qemu-nbd.c | 4 +++- + 4 files changed, 34 insertions(+), 7 deletions(-) + +diff --git a/blockdev-nbd.c b/blockdev-nbd.c +index bdfa7ed3a5..b9e8dc78f3 100644 +--- a/blockdev-nbd.c ++++ b/blockdev-nbd.c +@@ -59,8 +59,10 @@ static void nbd_accept(QIONetListener *listener, QIOChannelSocket *cioc, + nbd_update_server_watch(nbd_server); + + qio_channel_set_name(QIO_CHANNEL(cioc), "nbd-server"); +- nbd_client_new(cioc, nbd_server->tlscreds, nbd_server->tlsauthz, +- nbd_blockdev_client_closed); ++ /* TODO - expose handshake timeout as QMP option */ ++ nbd_client_new(cioc, NBD_DEFAULT_HANDSHAKE_MAX_SECS, ++ nbd_server->tlscreds, nbd_server->tlsauthz, ++ nbd_blockdev_client_closed, NULL); + } + + static void nbd_update_server_watch(NBDServerData *s) +diff --git a/include/block/nbd.h b/include/block/nbd.h +index 78d101b774..b71a297249 100644 +--- a/include/block/nbd.h ++++ b/include/block/nbd.h +@@ -27,6 +27,12 @@ + + extern const BlockExportDriver blk_exp_nbd; + ++/* ++ * NBD_DEFAULT_HANDSHAKE_MAX_SECS: Number of seconds in which client must ++ * succeed at NBD_OPT_GO before being forcefully dropped as too slow. ++ */ ++#define NBD_DEFAULT_HANDSHAKE_MAX_SECS 10 ++ + /* Handshake phase structs - this struct is passed on the wire */ + + struct NBDOption { +@@ -338,9 +344,12 @@ AioContext *nbd_export_aio_context(NBDExport *exp); + NBDExport *nbd_export_find(const char *name); + + void nbd_client_new(QIOChannelSocket *sioc, ++ uint32_t handshake_max_secs, + QCryptoTLSCreds *tlscreds, + const char *tlsauthz, +- void (*close_fn)(NBDClient *, bool)); ++ void (*close_fn)(NBDClient *, bool), ++ void *owner); ++void *nbd_client_owner(NBDClient *client); + void nbd_client_get(NBDClient *client); + void nbd_client_put(NBDClient *client); + +diff --git a/nbd/server.c b/nbd/server.c +index 73fd4c46d1..fff9e98bac 100644 +--- a/nbd/server.c ++++ b/nbd/server.c +@@ -120,10 +120,12 @@ typedef struct NBDExportMetaContexts { + struct NBDClient { + int refcount; + void (*close_fn)(NBDClient *client, bool negotiated); ++ void *owner; + + NBDExport *exp; + QCryptoTLSCreds *tlscreds; + char *tlsauthz; ++ uint32_t handshake_max_secs; + QIOChannelSocket *sioc; /* The underlying data channel */ + QIOChannel *ioc; /* The current I/O channel which may differ (eg TLS) */ + +@@ -2707,6 +2709,7 @@ static coroutine_fn void nbd_co_client_start(void *opaque) + + qemu_co_mutex_init(&client->send_lock); + ++ /* TODO - utilize client->handshake_max_secs */ + if (nbd_negotiate(client, &local_err)) { + if (local_err) { + error_report_err(local_err); +@@ -2719,14 +2722,17 @@ static coroutine_fn void nbd_co_client_start(void *opaque) + } + + /* +- * Create a new client listener using the given channel @sioc. ++ * Create a new client listener using the given channel @sioc and @owner. + * Begin servicing it in a coroutine. When the connection closes, call +- * @close_fn with an indication of whether the client completed negotiation. ++ * @close_fn with an indication of whether the client completed negotiation ++ * within @handshake_max_secs seconds (0 for unbounded). + */ + void nbd_client_new(QIOChannelSocket *sioc, ++ uint32_t handshake_max_secs, + QCryptoTLSCreds *tlscreds, + const char *tlsauthz, +- void (*close_fn)(NBDClient *, bool)) ++ void (*close_fn)(NBDClient *, bool), ++ void *owner) + { + NBDClient *client; + Coroutine *co; +@@ -2738,12 +2744,20 @@ void nbd_client_new(QIOChannelSocket *sioc, + object_ref(OBJECT(client->tlscreds)); + } + client->tlsauthz = g_strdup(tlsauthz); ++ client->handshake_max_secs = handshake_max_secs; + client->sioc = sioc; + object_ref(OBJECT(client->sioc)); + client->ioc = QIO_CHANNEL(sioc); + object_ref(OBJECT(client->ioc)); + client->close_fn = close_fn; ++ client->owner = owner; + + co = qemu_coroutine_create(nbd_co_client_start, client); + qemu_coroutine_enter(co); + } ++ ++void * ++nbd_client_owner(NBDClient *client) ++{ ++ return client->owner; ++} +diff --git a/qemu-nbd.c b/qemu-nbd.c +index 86dfa0b5d9..69fd101cd1 100644 +--- a/qemu-nbd.c ++++ b/qemu-nbd.c +@@ -363,7 +363,9 @@ static void nbd_accept(QIONetListener *listener, QIOChannelSocket *cioc, + + nb_fds++; + nbd_update_server_watch(); +- nbd_client_new(cioc, tlscreds, tlsauthz, nbd_client_closed); ++ /* TODO - expose handshake timeout as command line option */ ++ nbd_client_new(cioc, NBD_DEFAULT_HANDSHAKE_MAX_SECS, ++ tlscreds, tlsauthz, nbd_client_closed, NULL); + } + + static void nbd_update_server_watch(void) +-- +2.45.1.windows.1 + diff --git a/qemu.spec b/qemu.spec index b17d58af..8e7eec29 100644 --- a/qemu.spec +++ b/qemu.spec @@ -3,7 +3,7 @@ Name: qemu Version: 6.2.0 -Release: 96 +Release: 97 Epoch: 10 Summary: QEMU is a generic and open source machine emulator and virtualizer License: GPLv2 and BSD and MIT and CC-BY-SA-4.0 @@ -982,6 +982,13 @@ Patch0967: iotests-270-Don-t-store-data-file-with-json-prefix-i.patch Patch0968: block-introduce-bdrv_open_file_child-helper.patch Patch0969: block-Parse-filenames-only-when-explicitly-requested.patch Patch0970: vdpa-Fix-bug-where-vdpa-appliance-migration-does-not.patch +Patch0971: nbd-Minor-style-and-typo-fixes.patch +Patch0972: nbd-server-Plumb-in-new-args-to-nbd_client_add.patch +Patch0973: nbd-server-CVE-2024-7409-Cap-default-max-connections.patch +Patch0974: nbd-server-CVE-2024-7409-Drop-non-negotiating-client.patch +Patch0975: aio-wait.h-introduce-AIO_WAIT_WHILE_UNLOCKED.patch +Patch0976: main-loop.h-introduce-qemu_in_main_thread.patch +Patch0977: nbd-server-CVE-2024-7409-Close-stray-clients-at-serv.patch BuildRequires: flex BuildRequires: gcc @@ -1580,6 +1587,15 @@ getent passwd qemu >/dev/null || \ %endif %changelog +* Tue Aug 13 2024 - 10:6.2.0-97 +- nbd/server: CVE-2024-7409: Close stray clients at server-stop +- main-loop.h: introduce qemu_in_main_thread() +- aio-wait.h: introduce AIO_WAIT_WHILE_UNLOCKED +- nbd/server: CVE-2024-7409: Drop non-negotiating clients +- nbd/server: CVE-2024-7409: Cap default max-connections to 100 +- nbd/server: Plumb in new args to nbd_client_add() +- nbd: Minor style and typo fixes + * Thu Jul 11 2024 - 10:6.2.0-96 - vdpa: Fix bug where vdpa appliance migration does not resume after rollback - block: Parse filenames only when explicitly requested (CVE-2024-4467) -- Gitee From ae37a72f4c4d93bd46de695d8cc435e4416d5c27 Mon Sep 17 00:00:00 2001 From: Jiabo Feng Date: Wed, 21 Aug 2024 15:14:18 +0800 Subject: [PATCH 15/19] QEMU update to version 6.2.0-98: - pci-host: designware: Limit value range of iATU viewport register - hmat acpi: Fix out of bounds access due to missing use of indirection - migration: Skip only empty block devices - aspeed/hace: Initialize g_autofree pointer - hw/net/vmxnet3: Fix guest-triggerable assert() - qxl: don't assert() if device isn't yet initialized - Avoid unaligned fetch in ladr_match() - linux-user: Fix waitid return of siginfo_t and rusage - hw/net/lan9118: Replace magic '2048' value by MIL_TXFIFO_SIZE definition - stdvga: fix screen blanking - virtio-net: drop too short packets early - ebpf: replace deprecated bpf_program__set_socket_filter - vhsot-user: only read reply of SET_LOG_BASE from vq 0 - cpu: add Tengyun S5000C cpu support - hw/virtio: Fix obtain the buffer id from the last descriptor - hw/core: ensure kernel_end never gets used undefined Signed-off-by: Jiabo Feng (cherry picked from commit 1f9e476e96edb07e34e0133a312f478ddab4b6ff) --- Avoid-unaligned-fetch-in-ladr_match.patch | 36 ++++++++ ...d-hace-Initialize-g_autofree-pointer.patch | 50 ++++++++++ cpu-add-Tengyun-S5000C-cpu-support.patch | 82 +++++++++++++++++ ...recated-bpf_program__set_socket_filt.patch | 32 +++++++ ...t-of-bounds-access-due-to-missing-us.patch | 64 +++++++++++++ ...kernel_end-never-gets-used-undefined.patch | 51 +++++++++++ ...eplace-magic-2048-value-by-MIL_TXFIF.patch | 75 +++++++++++++++ ...vmxnet3-Fix-guest-triggerable-assert.patch | 45 +++++++++ ...tain-the-buffer-id-from-the-last-des.patch | 57 ++++++++++++ ...aitid-return-of-siginfo_t-and-rusage.patch | 60 ++++++++++++ migration-Skip-only-empty-block-devices.patch | 51 +++++++++++ ...are-Limit-value-range-of-iATU-viewpo.patch | 54 +++++++++++ qemu.spec | 36 +++++++- ...sert-if-device-isn-t-yet-initialized.patch | 52 +++++++++++ stdvga-fix-screen-blanking.patch | 47 ++++++++++ ...read-reply-of-SET_LOG_BASE-from-vq-0.patch | 30 ++++++ virtio-net-drop-too-short-packets-early.patch | 91 +++++++++++++++++++ 17 files changed, 912 insertions(+), 1 deletion(-) create mode 100644 Avoid-unaligned-fetch-in-ladr_match.patch create mode 100644 aspeed-hace-Initialize-g_autofree-pointer.patch create mode 100644 cpu-add-Tengyun-S5000C-cpu-support.patch create mode 100644 ebpf-replace-deprecated-bpf_program__set_socket_filt.patch create mode 100644 hmat-acpi-Fix-out-of-bounds-access-due-to-missing-us.patch create mode 100644 hw-core-ensure-kernel_end-never-gets-used-undefined.patch create mode 100644 hw-net-lan9118-Replace-magic-2048-value-by-MIL_TXFIF.patch create mode 100644 hw-net-vmxnet3-Fix-guest-triggerable-assert.patch create mode 100644 hw-virtio-Fix-obtain-the-buffer-id-from-the-last-des.patch create mode 100644 linux-user-Fix-waitid-return-of-siginfo_t-and-rusage.patch create mode 100644 migration-Skip-only-empty-block-devices.patch create mode 100644 pci-host-designware-Limit-value-range-of-iATU-viewpo.patch create mode 100644 qxl-don-t-assert-if-device-isn-t-yet-initialized.patch create mode 100644 stdvga-fix-screen-blanking.patch create mode 100644 vhsot-user-only-read-reply-of-SET_LOG_BASE-from-vq-0.patch create mode 100644 virtio-net-drop-too-short-packets-early.patch diff --git a/Avoid-unaligned-fetch-in-ladr_match.patch b/Avoid-unaligned-fetch-in-ladr_match.patch new file mode 100644 index 00000000..cc29ce6e --- /dev/null +++ b/Avoid-unaligned-fetch-in-ladr_match.patch @@ -0,0 +1,36 @@ +From 7696f21456a2a42279efd3f9fca6df839bdbe441 Mon Sep 17 00:00:00 2001 +From: Nick Briggs +Date: Thu, 1 Feb 2024 10:11:17 -0800 +Subject: [PATCH] Avoid unaligned fetch in ladr_match() + +There is no guarantee that the PCNetState is allocated such that +csr[8] is allocated on an 8-byte boundary. Since not all hosts are +capable of unaligned fetches the 16-bit elements need to be fetched +individually to avoid a potential fault. Closes issue #2143 + +Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2143 +Signed-off-by: Nick Briggs +Reviewed-by: Peter Maydell +Signed-off-by: Jason Wang +(cherry picked from commit 6a5287ce80470bb8df95901d73ee779a64e70c3a) +Signed-off-by: zhujun2 +--- + hw/net/pcnet.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/hw/net/pcnet.c b/hw/net/pcnet.c +index da910a70bf..9c475d5721 100644 +--- a/hw/net/pcnet.c ++++ b/hw/net/pcnet.c +@@ -632,7 +632,7 @@ static inline int ladr_match(PCNetState *s, const uint8_t *buf, int size) + { + struct qemu_ether_header *hdr = (void *)buf; + if ((*(hdr->ether_dhost)&0x01) && +- ((uint64_t *)&s->csr[8])[0] != 0LL) { ++ (s->csr[8] | s->csr[9] | s->csr[10] | s->csr[11]) != 0) { + uint8_t ladr[8] = { + s->csr[8] & 0xff, s->csr[8] >> 8, + s->csr[9] & 0xff, s->csr[9] >> 8, +-- +2.41.0.windows.1 + diff --git a/aspeed-hace-Initialize-g_autofree-pointer.patch b/aspeed-hace-Initialize-g_autofree-pointer.patch new file mode 100644 index 00000000..66e5a6f9 --- /dev/null +++ b/aspeed-hace-Initialize-g_autofree-pointer.patch @@ -0,0 +1,50 @@ +From 4f957cd7c79c7820e6218560efde3de142d1caf1 Mon Sep 17 00:00:00 2001 +From: zhujun2 +Date: Tue, 13 Aug 2024 23:24:29 -0700 +Subject: [PATCH] aspeed/hace: Initialize g_autofree pointer +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +As mentioned in docs/devel/style.rst "Automatic memory deallocation": + +* Variables declared with g_auto* MUST always be initialized, + otherwise the cleanup function will use uninitialized stack memory + +This avoids QEMU to coredump when running the "hash test" command +under Zephyr. + +Cc: Steven Lee +Cc: Joel Stanley +Cc: qemu-stable@nongnu.org +Fixes: c5475b3f9a ("hw: Model ASPEED's Hash and Crypto Engine") +Reviewed-by: Philippe Mathieu-Daudé +Reviewed-by: Alex Bennée +Reviewed-by: Thomas Huth +Reviewed-by: Francisco Iglesias +Message-Id: <20230421131547.2177449-1-clg@kaod.org> +Signed-off-by: Cédric Le Goater +Reviewed-by: Joel Stanley +Signed-off-by: Cédric Le Goater +(cherry picked from commit c8f48b120b31f6bbe33135ef5d478e485c37e3c2) +Signed-off-by: zhujun2 +--- + hw/misc/aspeed_hace.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/hw/misc/aspeed_hace.c b/hw/misc/aspeed_hace.c +index 10f00e65f4..1192322f0a 100644 +--- a/hw/misc/aspeed_hace.c ++++ b/hw/misc/aspeed_hace.c +@@ -97,7 +97,7 @@ static int hash_algo_lookup(uint32_t reg) + static void do_hash_operation(AspeedHACEState *s, int algo, bool sg_mode) + { + struct iovec iov[ASPEED_HACE_MAX_SG]; +- g_autofree uint8_t *digest_buf; ++ g_autofree uint8_t *digest_buf = NULL; + size_t digest_len = 0; + int i; + +-- +2.41.0.windows.1 + diff --git a/cpu-add-Tengyun-S5000C-cpu-support.patch b/cpu-add-Tengyun-S5000C-cpu-support.patch new file mode 100644 index 00000000..f782583a --- /dev/null +++ b/cpu-add-Tengyun-S5000C-cpu-support.patch @@ -0,0 +1,82 @@ +From 38d4158a556f27c9ce7d9229d6a28cf57dd8de26 Mon Sep 17 00:00:00 2001 +From: Jiakun Shuai +Date: Fri, 19 Jul 2024 15:29:13 +0800 +Subject: [PATCH] cpu: add Tengyun S5000C cpu support + +Add the Tengyun-S5000C CPU model. + +Signed-off-by: pengmengguang +Signed-off-by: Jiakun Shuai +--- + hw/arm/virt.c | 1 + + target/arm/cpu64.c | 35 +++++++++++++++++++++++++++++++++++ + 2 files changed, 36 insertions(+) + +diff --git a/hw/arm/virt.c b/hw/arm/virt.c +index dc119732f0..3394d3a6a6 100644 +--- a/hw/arm/virt.c ++++ b/hw/arm/virt.c +@@ -210,6 +210,7 @@ static const char *valid_cpus[] = { + ARM_CPU_TYPE_NAME("Kunpeng-920"), + ARM_CPU_TYPE_NAME("FT-2000+"), + ARM_CPU_TYPE_NAME("Tengyun-S2500"), ++ ARM_CPU_TYPE_NAME("Tengyun-S5000C"), + ARM_CPU_TYPE_NAME("a64fx"), + ARM_CPU_TYPE_NAME("host"), + ARM_CPU_TYPE_NAME("max"), +diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c +index 3ec788fc29..b4522a337f 100644 +--- a/target/arm/cpu64.c ++++ b/target/arm/cpu64.c +@@ -724,6 +724,40 @@ static void aarch64_max_tengyun_s2500_initfn(Object *obj) + } + } + ++static void aarch64_tengyun_s5000c_initfn(Object *obj) ++{ ++ ARMCPU *cpu = ARM_CPU(obj); ++ ++ aarch64_a72_initfn(obj); ++ ++ cpu->midr = 0x700f8620; ++ cpu->ctr = 0x9444c004; ++ cpu->isar.regs[ID_ISAR0] = 0x2101110; ++ cpu->isar.regs[ID_ISAR1] = 0x1311211; ++ cpu->isar.regs[ID_ISAR2] = 0x21232042; ++ cpu->isar.regs[ID_ISAR3] = 0x1112131; ++ cpu->isar.regs[ID_ISAR4] = 0x10142; ++ cpu->isar.regs[ID_ISAR5] = 0x1011121; ++ cpu->isar.regs[ID_MMFR0] = 0x10201105; ++ cpu->isar.regs[ID_MMFR1] = 0x40000000; ++ cpu->isar.regs[ID_MMFR2] = 0x1260000; ++ cpu->isar.regs[ID_MMFR3] = 0x2122211; ++ cpu->isar.regs[ID_MMFR4] = 0x21110; ++ cpu->isar.regs[MVFR0] = 0x10110222; ++ cpu->isar.regs[MVFR1] = 0x13211111; ++ cpu->isar.regs[MVFR2] = 0x43; ++ cpu->isar.regs[ID_DFR0] = 0x4010088; ++ cpu->isar.regs[ID_PFR0] = 0x10131; ++ cpu->isar.regs[ID_PFR1] = 0x10010000; ++ cpu->isar.regs[ID_AA64PFR0] = 0x1100000011111112; ++ cpu->isar.regs[ID_AA64DFR0] = 0x10305408; ++ cpu->isar.regs[ID_AA64ISAR0] = 0x111110212120; ++ cpu->isar.regs[ID_AA64ISAR1] = 0x100001; ++ cpu->isar.regs[ID_AA64MMFR0] = 0x101125; ++ cpu->isar.regs[ID_AA64MMFR1] = 0x10212122; ++ cpu->isar.regs[ID_AA64MMFR2] = 0x1011; ++} ++ + /* -cpu max: if KVM is enabled, like -cpu host (best possible with this host); + * otherwise, a CPU with as many features enabled as our emulation supports. + * The version of '-cpu max' for qemu-system-arm is defined in cpu.c; +@@ -964,6 +998,7 @@ static const ARMCPUInfo aarch64_cpus[] = { + { .name = "Kunpeng-920", .initfn = aarch64_kunpeng_920_initfn}, + { .name = "FT-2000+", .initfn = aarch64_max_ft2000plus_initfn }, + { .name = "Tengyun-S2500", .initfn = aarch64_max_tengyun_s2500_initfn }, ++ { .name = "Tengyun-S5000C", .initfn = aarch64_tengyun_s5000c_initfn }, + { .name = "a64fx", .initfn = aarch64_a64fx_initfn }, + { .name = "max", .initfn = aarch64_max_initfn }, + }; +-- +2.41.0.windows.1 + diff --git a/ebpf-replace-deprecated-bpf_program__set_socket_filt.patch b/ebpf-replace-deprecated-bpf_program__set_socket_filt.patch new file mode 100644 index 00000000..8c1ed611 --- /dev/null +++ b/ebpf-replace-deprecated-bpf_program__set_socket_filt.patch @@ -0,0 +1,32 @@ +From 6824dd870cde75d4ef1e8c74d3d596ff94ce5a26 Mon Sep 17 00:00:00 2001 +From: Haochen Tong +Date: Sat, 28 May 2022 03:06:58 +0800 +Subject: [PATCH] ebpf: replace deprecated bpf_program__set_socket_filter + +bpf_program__set_ functions have been deprecated since libbpf 0.8. +Replace with the equivalent bpf_program__set_type call to avoid a +deprecation warning. + +Signed-off-by: Haochen Tong +Reviewed-by: Zhang Chen +Signed-off-by: Jason Wang +--- + ebpf/ebpf_rss.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/ebpf/ebpf_rss.c b/ebpf/ebpf_rss.c +index 118c68da83..cee658c158 100644 +--- a/ebpf/ebpf_rss.c ++++ b/ebpf/ebpf_rss.c +@@ -49,7 +49,7 @@ bool ebpf_rss_load(struct EBPFRSSContext *ctx) + goto error; + } + +- bpf_program__set_socket_filter(rss_bpf_ctx->progs.tun_rss_steering_prog); ++ bpf_program__set_type(rss_bpf_ctx->progs.tun_rss_steering_prog, BPF_PROG_TYPE_SOCKET_FILTER); + + if (rss_bpf__load(rss_bpf_ctx)) { + trace_ebpf_error("eBPF RSS", "can not load RSS program"); +-- +2.41.0.windows.1 + diff --git a/hmat-acpi-Fix-out-of-bounds-access-due-to-missing-us.patch b/hmat-acpi-Fix-out-of-bounds-access-due-to-missing-us.patch new file mode 100644 index 00000000..b6783f0b --- /dev/null +++ b/hmat-acpi-Fix-out-of-bounds-access-due-to-missing-us.patch @@ -0,0 +1,64 @@ +From a47cccd44f4f97238fc2877bf38fdb5ae72b65a6 Mon Sep 17 00:00:00 2001 +From: zhujun2 +Date: Wed, 14 Aug 2024 19:14:40 -0700 +Subject: [PATCH] hmat acpi: Fix out of bounds access due to missing use of + indirection + +With a numa set up such as + +-numa nodeid=0,cpus=0 \ +-numa nodeid=1,memdev=mem \ +-numa nodeid=2,cpus=1 + +and appropriate hmat_lb entries the initiator list is correctly +computed and writen to HMAT as 0,2 but then the LB data is accessed +using the node id (here 2), landing outside the entry_list array. + +Stash the reverse lookup when writing the initiator list and use +it to get the correct array index index. + +Fixes: 4586a2cb83 ("hmat acpi: Build System Locality Latency and Bandwidth Information Structure(s)") +Signed-off-by: Jonathan Cameron +Message-Id: <20240307160326.31570-3-Jonathan.Cameron@huawei.com> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +(cherry picked from commit 74e2845c5f95b0c139c79233ddb65bb17f2dd679) +Signed-off-by: zhujun2 +--- + hw/acpi/hmat.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/hw/acpi/hmat.c b/hw/acpi/hmat.c +index 6913ebf730..8af753c67b 100644 +--- a/hw/acpi/hmat.c ++++ b/hw/acpi/hmat.c +@@ -77,6 +77,7 @@ static void build_hmat_lb(GArray *table_data, HMAT_LB_Info *hmat_lb, + uint32_t *initiator_list) + { + int i, index; ++ uint32_t initiator_to_index[MAX_NODES] = {}; + HMAT_LB_Data *lb_data; + uint16_t *entry_list; + uint32_t base; +@@ -120,6 +121,8 @@ static void build_hmat_lb(GArray *table_data, HMAT_LB_Info *hmat_lb, + /* Initiator Proximity Domain List */ + for (i = 0; i < num_initiator; i++) { + build_append_int_noprefix(table_data, initiator_list[i], 4); ++ /* Reverse mapping for array possitions */ ++ initiator_to_index[initiator_list[i]] = i; + } + + /* Target Proximity Domain List */ +@@ -131,7 +134,8 @@ static void build_hmat_lb(GArray *table_data, HMAT_LB_Info *hmat_lb, + entry_list = g_malloc0(num_initiator * num_target * sizeof(uint16_t)); + for (i = 0; i < hmat_lb->list->len; i++) { + lb_data = &g_array_index(hmat_lb->list, HMAT_LB_Data, i); +- index = lb_data->initiator * num_target + lb_data->target; ++ index = initiator_to_index[lb_data->initiator] * num_target + ++ lb_data->target; + + entry_list[index] = (uint16_t)(lb_data->data / hmat_lb->base); + } +-- +2.41.0.windows.1 + diff --git a/hw-core-ensure-kernel_end-never-gets-used-undefined.patch b/hw-core-ensure-kernel_end-never-gets-used-undefined.patch new file mode 100644 index 00000000..6d571827 --- /dev/null +++ b/hw-core-ensure-kernel_end-never-gets-used-undefined.patch @@ -0,0 +1,51 @@ +From 26faf838c837c09bf22ef6dc1621adc4e207fc8c Mon Sep 17 00:00:00 2001 +From: guping +Date: Tue, 9 Jul 2024 11:56:12 +0000 +Subject: [PATCH] hw/core: ensure kernel_end never gets used undefined + cherry-pick from f5fcc648083e71cfb9394894903f8ea108ff8831 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Really the problem here is the return values of fit_load_[kernel|fdt]() are a +little all over the place. However we don't want to somehow get +through not having set kernel_end and having it just be random unused +data. + +The compiler complained on an --enable-gcov build: + + In file included from ../../hw/core/loader-fit.c:20: + /home/alex/lsrc/qemu.git/include/qemu/osdep.h: In function ‘load_fit’: + /home/alex/lsrc/qemu.git/include/qemu/osdep.h:486:45: error: ‘kernel_end’ may be used uninitialized [-Werror=maybe-uninitialized] + 486 | #define ROUND_UP(n, d) ROUND_DOWN((n) + (d) - 1, (d)) + | ^ + ../../hw/core/loader-fit.c:270:12: note: ‘kernel_end’ was declared here + 270 | hwaddr kernel_end; + | ^~~~~~~~~~ + +Reviewed-by: default avatarManos Pitsidianakis +Signed-off-by: default avatarAlex Bennée +Reviewed-by: default avatarAleksandar Rikalo +Message-Id: <20240705084047.857176-5-alex.bennee@linaro.org> + +Signed-off-by: guping +--- + hw/core/loader-fit.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/hw/core/loader-fit.c b/hw/core/loader-fit.c +index b7c7b3ba94..4a9a74cf3a 100644 +--- a/hw/core/loader-fit.c ++++ b/hw/core/loader-fit.c +@@ -265,7 +265,7 @@ int load_fit(const struct fit_loader *ldr, const char *filename, void *opaque) + const char *def_cfg_name; + char path[FIT_LOADER_MAX_PATH]; + int itb_size, configs, cfg_off, off; +- hwaddr kernel_end; ++ hwaddr kernel_end = 0; + int ret; + + itb = load_device_tree(filename, &itb_size); +-- +2.41.0.windows.1 + diff --git a/hw-net-lan9118-Replace-magic-2048-value-by-MIL_TXFIF.patch b/hw-net-lan9118-Replace-magic-2048-value-by-MIL_TXFIF.patch new file mode 100644 index 00000000..3bac2e1f --- /dev/null +++ b/hw-net-lan9118-Replace-magic-2048-value-by-MIL_TXFIF.patch @@ -0,0 +1,75 @@ +From c85a85a2c5eb5f26f9c713c010e2ca3408cb8ce4 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Mon, 8 Apr 2024 12:44:22 +0200 +Subject: [PATCH] hw/net/lan9118: Replace magic '2048' value by MIL_TXFIFO_SIZE + definition +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The magic 2048 is explained in the LAN9211 datasheet (DS00002414A) +in chapter 1.4, "10/100 Ethernet MAC": + + The MAC Interface Layer (MIL), within the MAC, contains a + 2K Byte transmit and a 128 Byte receive FIFO which is separate + from the TX and RX FIFOs. [...] + +Note, the use of the constant in lan9118_receive() reveals that +our implementation is using the same buffer for both tx and rx. + +Signed-off-by: Philippe Mathieu-Daudé +Reviewed-by: Peter Maydell +Message-Id: <20240409133801.23503-2-philmd@linaro.org> +(cherry picked from commit a45223467e4e185fff1c76a6483784fa379ded77) +Signed-off-by: zhujun2 +--- + hw/net/lan9118.c | 12 +++++++++--- + 1 file changed, 9 insertions(+), 3 deletions(-) + +diff --git a/hw/net/lan9118.c b/hw/net/lan9118.c +index 942bce9ae6..fa43758105 100644 +--- a/hw/net/lan9118.c ++++ b/hw/net/lan9118.c +@@ -155,6 +155,12 @@ do { fprintf(stderr, "lan9118: error: " fmt , ## __VA_ARGS__);} while (0) + + #define GPT_TIMER_EN 0x20000000 + ++/* ++ * The MAC Interface Layer (MIL), within the MAC, contains a 2K Byte transmit ++ * and a 128 Byte receive FIFO which is separate from the TX and RX FIFOs. ++ */ ++#define MIL_TXFIFO_SIZE 2048 ++ + enum tx_state { + TX_IDLE, + TX_B, +@@ -171,7 +177,7 @@ typedef struct { + int32_t pad; + int32_t fifo_used; + int32_t len; +- uint8_t data[2048]; ++ uint8_t data[MIL_TXFIFO_SIZE]; + } LAN9118Packet; + + static const VMStateDescription vmstate_lan9118_packet = { +@@ -187,7 +193,7 @@ static const VMStateDescription vmstate_lan9118_packet = { + VMSTATE_INT32(pad, LAN9118Packet), + VMSTATE_INT32(fifo_used, LAN9118Packet), + VMSTATE_INT32(len, LAN9118Packet), +- VMSTATE_UINT8_ARRAY(data, LAN9118Packet, 2048), ++ VMSTATE_UINT8_ARRAY(data, LAN9118Packet, MIL_TXFIFO_SIZE), + VMSTATE_END_OF_LIST() + } + }; +@@ -549,7 +555,7 @@ static ssize_t lan9118_receive(NetClientState *nc, const uint8_t *buf, + return -1; + } + +- if (size >= 2048 || size < 14) { ++ if (size >= MIL_TXFIFO_SIZE || size < 14) { + return -1; + } + +-- +2.41.0.windows.1 + diff --git a/hw-net-vmxnet3-Fix-guest-triggerable-assert.patch b/hw-net-vmxnet3-Fix-guest-triggerable-assert.patch new file mode 100644 index 00000000..5207fb4f --- /dev/null +++ b/hw-net-vmxnet3-Fix-guest-triggerable-assert.patch @@ -0,0 +1,45 @@ +From 2c4d30134778dc9219a883243d207f9dff9f0a7e Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Thu, 17 Aug 2023 14:56:00 +0200 +Subject: [PATCH] hw/net/vmxnet3: Fix guest-triggerable assert() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The assert() that checks for valid MTU sizes can be triggered by +the guest (e.g. with the reproducer code from the bug ticket +https://gitlab.com/qemu-project/qemu/-/issues/517 ). Let's avoid +this problem by simply logging the error and refusing to activate +the device instead. + +Fixes: d05dcd94ae ("net: vmxnet3: validate configuration values during activate") +Signed-off-by: Thomas Huth +Cc: qemu-stable@nongnu.org +Reviewed-by: Philippe Mathieu-Daudé +Signed-off-by: Michael Tokarev +[Mjt: change format specifier from %d to %u for uint32_t argument] +(cherry picked from commit 90a0778421acdf4ca903be64c8ed19378183c944) +Signed-off-by: zhujun2 +--- + hw/net/vmxnet3.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/hw/net/vmxnet3.c b/hw/net/vmxnet3.c +index 2a32ab32ea..674b3a6946 100644 +--- a/hw/net/vmxnet3.c ++++ b/hw/net/vmxnet3.c +@@ -1441,7 +1441,10 @@ static void vmxnet3_activate_device(VMXNET3State *s) + vmxnet3_setup_rx_filtering(s); + /* Cache fields from shared memory */ + s->mtu = VMXNET3_READ_DRV_SHARED32(d, s->drv_shmem, devRead.misc.mtu); +- assert(VMXNET3_MIN_MTU <= s->mtu && s->mtu <= VMXNET3_MAX_MTU); ++ if (s->mtu < VMXNET3_MIN_MTU || s->mtu > VMXNET3_MAX_MTU) { ++ qemu_log_mask(LOG_GUEST_ERROR, "vmxnet3: Bad MTU size: %u\n", s->mtu); ++ return; ++ } + VMW_CFPRN("MTU is %u", s->mtu); + + s->max_rx_frags = +-- +2.41.0.windows.1 + diff --git a/hw-virtio-Fix-obtain-the-buffer-id-from-the-last-des.patch b/hw-virtio-Fix-obtain-the-buffer-id-from-the-last-des.patch new file mode 100644 index 00000000..fc35d0d3 --- /dev/null +++ b/hw-virtio-Fix-obtain-the-buffer-id-from-the-last-des.patch @@ -0,0 +1,57 @@ +From 1937c00107f7598d5b0632f2eb6045e5bb46f6db Mon Sep 17 00:00:00 2001 +From: guping +Date: Tue, 9 Jul 2024 12:39:01 +0000 +Subject: [PATCH] hw/virtio: Fix obtain the buffer id from the last descriptor + cherry-pick from 33abfea239592a706e98269b01c0096249612ea4 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The virtio-1.3 specification + writes: +2.8.6 Next Flag: Descriptor Chaining + Buffer ID is included in the last descriptor in the list. + +If the feature (_F_INDIRECT_DESC) has been negotiated, install only +one descriptor in the virtqueue. +Therefor the buffer id should be obtained from the first descriptor. + +In descriptor chaining scenarios, the buffer id should be obtained +from the last descriptor. + +Fixes: 86044b24 + + ("virtio: basic packed virtqueue support") + +Signed-off-by: default avatarWafer +Reviewed-by: Jason Wang's avatarJason Wang +Reviewed-by: default avatarEugenio Pérez +Acked-by: Jason Wang's avatarJason Wang +Message-Id: <20240510072753.26158-2-wafer@jaguarmicro.com> +Reviewed-by: MST's avatarMichael S. Tsirkin +Signed-off-by: MST's avatarMichael S. Tsirkin + +Signed-off-by: guping +--- + hw/virtio/virtio.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c +index 80156bfbd5..913b40e1f8 100644 +--- a/hw/virtio/virtio.c ++++ b/hw/virtio/virtio.c +@@ -1635,6 +1635,11 @@ static void *virtqueue_packed_pop(VirtQueue *vq, size_t sz) + &indirect_desc_cache); + } while (rc == VIRTQUEUE_READ_DESC_MORE); + ++ if (desc_cache != &indirect_desc_cache) { ++ /* Buffer ID is included in the last descriptor in the list. */ ++ id = desc.id; ++ } ++ + /* Now copy what we have collected and mapped */ + elem = virtqueue_alloc_element(sz, out_num, in_num); + for (i = 0; i < out_num; i++) { +-- +2.41.0.windows.1 + diff --git a/linux-user-Fix-waitid-return-of-siginfo_t-and-rusage.patch b/linux-user-Fix-waitid-return-of-siginfo_t-and-rusage.patch new file mode 100644 index 00000000..a98ee1ec --- /dev/null +++ b/linux-user-Fix-waitid-return-of-siginfo_t-and-rusage.patch @@ -0,0 +1,60 @@ +From 828944a7eb5d67f81aa3bc7158860466dc1f1325 Mon Sep 17 00:00:00 2001 +From: Richard Henderson +Date: Fri, 5 Apr 2024 11:58:14 -1000 +Subject: [PATCH] linux-user: Fix waitid return of siginfo_t and rusage +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The copy back to siginfo_t should be conditional only on arg3, +not the specific values that might have been written. +The copy back to rusage was missing entirely. + +Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2262 +Signed-off-by: Richard Henderson +Tested-by: Alex Fan +Reviewed-by: Philippe Mathieu-Daudé +(cherry picked from commit f0907ff4cae743f1a4ef3d0a55a047029eed06ff) +Signed-off-by: zhujun2 +--- + linux-user/syscall.c | 22 ++++++++++++++++------ + 1 file changed, 16 insertions(+), 6 deletions(-) + +diff --git a/linux-user/syscall.c b/linux-user/syscall.c +index a5fe399277..c4951d449f 100644 +--- a/linux-user/syscall.c ++++ b/linux-user/syscall.c +@@ -8460,14 +8460,24 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, + #ifdef TARGET_NR_waitid + case TARGET_NR_waitid: + { ++ struct rusage ru; + siginfo_t info; +- info.si_pid = 0; +- ret = get_errno(safe_waitid(arg1, arg2, &info, arg4, NULL)); +- if (!is_error(ret) && arg3 && info.si_pid != 0) { +- if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_siginfo_t), 0))) ++ ++ ret = get_errno(safe_waitid(arg1, arg2, (arg3 ? &info : NULL), ++ arg4, (arg5 ? &ru : NULL))); ++ if (!is_error(ret)) { ++ if (arg3) { ++ p = lock_user(VERIFY_WRITE, arg3, ++ sizeof(target_siginfo_t), 0); ++ if (!p) { ++ return -TARGET_EFAULT; ++ } ++ host_to_target_siginfo(p, &info); ++ unlock_user(p, arg3, sizeof(target_siginfo_t)); ++ } ++ if (arg5 && host_to_target_rusage(arg5, &ru)) { + return -TARGET_EFAULT; +- host_to_target_siginfo(p, &info); +- unlock_user(p, arg3, sizeof(target_siginfo_t)); ++ } + } + } + return ret; +-- +2.41.0.windows.1 + diff --git a/migration-Skip-only-empty-block-devices.patch b/migration-Skip-only-empty-block-devices.patch new file mode 100644 index 00000000..ef1f81d5 --- /dev/null +++ b/migration-Skip-only-empty-block-devices.patch @@ -0,0 +1,51 @@ +From 3fce4b6eed6f37140ff94ea119dd47caaf8eba10 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= +Date: Tue, 12 Mar 2024 13:04:31 +0100 +Subject: [PATCH] migration: Skip only empty block devices +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The block .save_setup() handler calls a helper routine +init_blk_migration() which builds a list of block devices to take into +account for migration. When one device is found to be empty (sectors +== 0), the loop exits and all the remaining devices are ignored. This +is a regression introduced when bdrv_iterate() was removed. + +Change that by skipping only empty devices. + +Cc: Markus Armbruster +Cc: qemu-stable +Suggested-by: Kevin Wolf +Fixes: fea68bb6e9fa ("block: Eliminate bdrv_iterate(), use bdrv_next()") +Signed-off-by: Cédric Le Goater +Reviewed-by: Stefan Hajnoczi +Reviewed-by: Kevin Wolf +Link: https://lore.kernel.org/r/20240312120431.550054-1-clg@redhat.com +[peterx: fix "Suggested-by:"] +Signed-off-by: Peter Xu +(cherry picked from commit 2e128776dc56f502c2ee41750afe83938f389528) +Signed-off-by: zhujun2 +--- + migration/block.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/migration/block.c b/migration/block.c +index 391f8169fd..4055a6bb60 100644 +--- a/migration/block.c ++++ b/migration/block.c +@@ -415,7 +415,10 @@ static int init_blk_migration(QEMUFile *f) + } + + sectors = bdrv_nb_sectors(bs); +- if (sectors <= 0) { ++ if (sectors == 0) { ++ continue; ++ } ++ if (sectors < 0) { + ret = sectors; + bdrv_next_cleanup(&it); + goto out; +-- +2.41.0.windows.1 + diff --git a/pci-host-designware-Limit-value-range-of-iATU-viewpo.patch b/pci-host-designware-Limit-value-range-of-iATU-viewpo.patch new file mode 100644 index 00000000..3b05c152 --- /dev/null +++ b/pci-host-designware-Limit-value-range-of-iATU-viewpo.patch @@ -0,0 +1,54 @@ +From 13ece9fb57c74aafdb785b80d7a09b2d90c54cfd Mon Sep 17 00:00:00 2001 +From: Guenter Roeck +Date: Sun, 28 Jan 2024 22:00:55 -0800 +Subject: [PATCH] pci-host: designware: Limit value range of iATU viewport + register + +The latest version of qemu (v8.2.0-869-g7a1dc45af5) crashes when booting +the mcimx7d-sabre emulation with Linux v5.11 and later. + +qemu-system-arm: ../system/memory.c:2750: memory_region_set_alias_offset: Assertion `mr->alias' failed. + +Problem is that the Designware PCIe emulation accepts the full value range +for the iATU Viewport Register. However, both hardware and emulation only +support four inbound and four outbound viewports. + +The Linux kernel determines the number of supported viewports by writing +0xff into the viewport register and reading the value back. The expected +value when reading the register is the highest supported viewport index. +Match that code by masking the supported viewport value range when the +register is written. With this change, the Linux kernel reports + +imx6q-pcie 33800000.pcie: iATU: unroll F, 4 ob, 4 ib, align 0K, limit 4G + +as expected and supported. + +Fixes: d64e5eabc4c7 ("pci: Add support for Designware IP block") +Cc: Andrey Smirnov +Cc: Nikita Ostrenkov +Signed-off-by: Guenter Roeck +Message-id: 20240129060055.2616989-1-linux@roeck-us.net +Reviewed-by: Peter Maydell +Signed-off-by: Peter Maydell +(cherry picked from commit 8a73152020337a7fbf34daf0a006d4d89ec1494e) +Signed-off-by: zhujun2 +--- + hw/pci-host/designware.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/hw/pci-host/designware.c b/hw/pci-host/designware.c +index bde3a343a2..c235b9daa3 100644 +--- a/hw/pci-host/designware.c ++++ b/hw/pci-host/designware.c +@@ -340,6 +340,8 @@ static void designware_pcie_root_config_write(PCIDevice *d, uint32_t address, + break; + + case DESIGNWARE_PCIE_ATU_VIEWPORT: ++ val &= DESIGNWARE_PCIE_ATU_REGION_INBOUND | ++ (DESIGNWARE_PCIE_NUM_VIEWPORTS - 1); + root->atu_viewport = val; + break; + +-- +2.41.0.windows.1 + diff --git a/qemu.spec b/qemu.spec index 8e7eec29..409feba2 100644 --- a/qemu.spec +++ b/qemu.spec @@ -3,7 +3,7 @@ Name: qemu Version: 6.2.0 -Release: 97 +Release: 98 Epoch: 10 Summary: QEMU is a generic and open source machine emulator and virtualizer License: GPLv2 and BSD and MIT and CC-BY-SA-4.0 @@ -989,6 +989,22 @@ Patch0974: nbd-server-CVE-2024-7409-Drop-non-negotiating-client.patch Patch0975: aio-wait.h-introduce-AIO_WAIT_WHILE_UNLOCKED.patch Patch0976: main-loop.h-introduce-qemu_in_main_thread.patch Patch0977: nbd-server-CVE-2024-7409-Close-stray-clients-at-serv.patch +Patch0978: hw-core-ensure-kernel_end-never-gets-used-undefined.patch +Patch0979: hw-virtio-Fix-obtain-the-buffer-id-from-the-last-des.patch +Patch0980: cpu-add-Tengyun-S5000C-cpu-support.patch +Patch0981: vhsot-user-only-read-reply-of-SET_LOG_BASE-from-vq-0.patch +Patch0982: ebpf-replace-deprecated-bpf_program__set_socket_filt.patch +Patch0983: virtio-net-drop-too-short-packets-early.patch +Patch0984: stdvga-fix-screen-blanking.patch +Patch0985: hw-net-lan9118-Replace-magic-2048-value-by-MIL_TXFIF.patch +Patch0986: linux-user-Fix-waitid-return-of-siginfo_t-and-rusage.patch +Patch0987: Avoid-unaligned-fetch-in-ladr_match.patch +Patch0988: qxl-don-t-assert-if-device-isn-t-yet-initialized.patch +Patch0989: hw-net-vmxnet3-Fix-guest-triggerable-assert.patch +Patch0990: aspeed-hace-Initialize-g_autofree-pointer.patch +Patch0991: migration-Skip-only-empty-block-devices.patch +Patch0992: hmat-acpi-Fix-out-of-bounds-access-due-to-missing-us.patch +Patch0993: pci-host-designware-Limit-value-range-of-iATU-viewpo.patch BuildRequires: flex BuildRequires: gcc @@ -1587,6 +1603,24 @@ getent passwd qemu >/dev/null || \ %endif %changelog +* Wed Aug 21 2024 - 10:6.2.0-98 +- pci-host: designware: Limit value range of iATU viewport register +- hmat acpi: Fix out of bounds access due to missing use of indirection +- migration: Skip only empty block devices +- aspeed/hace: Initialize g_autofree pointer +- hw/net/vmxnet3: Fix guest-triggerable assert() +- qxl: don't assert() if device isn't yet initialized +- Avoid unaligned fetch in ladr_match() +- linux-user: Fix waitid return of siginfo_t and rusage +- hw/net/lan9118: Replace magic '2048' value by MIL_TXFIFO_SIZE definition +- stdvga: fix screen blanking +- virtio-net: drop too short packets early +- ebpf: replace deprecated bpf_program__set_socket_filter +- vhsot-user: only read reply of SET_LOG_BASE from vq 0 +- cpu: add Tengyun S5000C cpu support +- hw/virtio: Fix obtain the buffer id from the last descriptor +- hw/core: ensure kernel_end never gets used undefined + * Tue Aug 13 2024 - 10:6.2.0-97 - nbd/server: CVE-2024-7409: Close stray clients at server-stop - main-loop.h: introduce qemu_in_main_thread() diff --git a/qxl-don-t-assert-if-device-isn-t-yet-initialized.patch b/qxl-don-t-assert-if-device-isn-t-yet-initialized.patch new file mode 100644 index 00000000..b64b8156 --- /dev/null +++ b/qxl-don-t-assert-if-device-isn-t-yet-initialized.patch @@ -0,0 +1,52 @@ +From 5cb26fdba648f1347f0746cf5c8f619427e4c2b5 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= +Date: Mon, 14 Aug 2023 23:33:30 +0400 +Subject: [PATCH] qxl: don't assert() if device isn't yet initialized +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +If the PCI BAR isn't yet mapped or was unmapped, QXL_IO_SET_MODE will +assert(). Instead, report a guest bug and keep going. + +This can be reproduced with: + +cat << EOF | ./qemu-system-x86_64 -vga qxl -m 2048 -nodefaults -qtest stdio +outl 0xcf8 0x8000101c +outl 0xcfc 0xc000 +outl 0xcf8 0x80001001 +outl 0xcfc 0x01000000 +outl 0xc006 0x00 +EOF + +Fixes: https://gitlab.com/qemu-project/qemu/-/issues/1829 + +Signed-off-by: Marc-André Lureau +Reviewed-by: Thomas Huth +Cc: qemu-stable@nongnu.org +Signed-off-by: Michael Tokarev +(cherry picked from commit 95bef686e490bc3afc3f51f5fc6e20bf260b938c) +Signed-off-by: zhujun2 +--- + hw/display/qxl.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/hw/display/qxl.c b/hw/display/qxl.c +index 0f663b9912..d7673b8169 100644 +--- a/hw/display/qxl.c ++++ b/hw/display/qxl.c +@@ -1601,7 +1601,10 @@ static void qxl_set_mode(PCIQXLDevice *d, unsigned int modenr, int loadvm) + } + + d->guest_slots[0].slot = slot; +- assert(qxl_add_memslot(d, 0, devmem, QXL_SYNC) == 0); ++ if (qxl_add_memslot(d, 0, devmem, QXL_SYNC) != 0) { ++ qxl_set_guest_bug(d, "device isn't initialized yet"); ++ return; ++ } + + d->guest_primary.surface = surface; + qxl_create_guest_primary(d, 0, QXL_SYNC); +-- +2.41.0.windows.1 + diff --git a/stdvga-fix-screen-blanking.patch b/stdvga-fix-screen-blanking.patch new file mode 100644 index 00000000..286cbea2 --- /dev/null +++ b/stdvga-fix-screen-blanking.patch @@ -0,0 +1,47 @@ +From 5e725ce433c562e1e7fbcd1918305846303689fd Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Wed, 5 Jun 2024 15:14:41 +0200 +Subject: [PATCH] stdvga: fix screen blanking +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +In case the display surface uses a shared buffer (i.e. uses vga vram +directly instead of a shadow) go unshare the buffer before clearing it. + +This avoids vga memory corruption, which in turn fixes unblanking not +working properly with X11. + +Cc: qemu-stable@nongnu.org +Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2067 +Signed-off-by: Gerd Hoffmann +Reviewed-by: Marc-André Lureau +Message-ID: <20240605131444.797896-2-kraxel@redhat.com> +Signed-off-by: Philippe Mathieu-Daudé +(cherry picked from commit b1cf266c82cb1211ee2785f1813a6a3f3e693390) +Signed-off-by: zhujun2 +--- + hw/display/vga.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/hw/display/vga.c b/hw/display/vga.c +index 33765148d9..5e5fdf67d7 100644 +--- a/hw/display/vga.c ++++ b/hw/display/vga.c +@@ -1745,6 +1745,13 @@ static void vga_draw_blank(VGACommonState *s, int full_update) + if (s->last_scr_width <= 0 || s->last_scr_height <= 0) + return; + ++ if (is_buffer_shared(surface)) { ++ /* unshare buffer, otherwise the blanking corrupts vga vram */ ++ surface = qemu_create_displaysurface(s->last_scr_width, ++ s->last_scr_height); ++ dpy_gfx_replace_surface(s->con, surface); ++ } ++ + w = s->last_scr_width * surface_bytes_per_pixel(surface); + d = surface_data(surface); + for(i = 0; i < s->last_scr_height; i++) { +-- +2.41.0.windows.1 + diff --git a/vhsot-user-only-read-reply-of-SET_LOG_BASE-from-vq-0.patch b/vhsot-user-only-read-reply-of-SET_LOG_BASE-from-vq-0.patch new file mode 100644 index 00000000..53ce87df --- /dev/null +++ b/vhsot-user-only-read-reply-of-SET_LOG_BASE-from-vq-0.patch @@ -0,0 +1,30 @@ +From 840318752f3d4611f46378395d67add885f422e0 Mon Sep 17 00:00:00 2001 +From: BillXiang <1373760142@qq.com> +Date: Thu, 18 Jul 2024 15:29:07 +0800 +Subject: [PATCH] vhsot-user: only read reply of SET_LOG_BASE from vq 0 + +We have added VHOST_USER_SET_LOG_BASE to vhost_user_one_time_request +in https://gitee.com/openeuler/qemu/pulls/913 +and will not send this message for other vqs. + +Signed-off-by: BillXiang <1373760142@qq.com> +--- + hw/virtio/vhost-user.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c +index c97ea2544d..f10620494b 100644 +--- a/hw/virtio/vhost-user.c ++++ b/hw/virtio/vhost-user.c +@@ -534,7 +534,7 @@ static int vhost_user_set_log_base(struct vhost_dev *dev, uint64_t base, + return ret; + } + +- if (shmfd) { ++ if (shmfd && (dev->vq_index == 0)) { + msg.hdr.size = 0; + ret = vhost_user_read(dev, &msg); + if (ret < 0) { +-- +2.41.0.windows.1 + diff --git a/virtio-net-drop-too-short-packets-early.patch b/virtio-net-drop-too-short-packets-early.patch new file mode 100644 index 00000000..b42b7b7b --- /dev/null +++ b/virtio-net-drop-too-short-packets-early.patch @@ -0,0 +1,91 @@ +From b808292dbbb5e49db4b54123010ed2832d0ac548 Mon Sep 17 00:00:00 2001 +From: zhujun2 +Date: Tue, 13 Aug 2024 00:30:30 -0700 +Subject: [PATCH] virtio-net: drop too short packets early + +Reproducer from https://gitlab.com/qemu-project/qemu/-/issues/1451 +creates small packet (1 segment, len = 10 == n->guest_hdr_len), +then destroys queue. + +"if (n->host_hdr_len != n->guest_hdr_len)" is triggered, if body creates +zero length/zero segment packet as there is nothing after guest header. + +qemu_sendv_packet_async() tries to send it. + +slirp discards it because it is smaller than Ethernet header, +but returns 0 because tx hooks are supposed to return total length of data. + +0 is propagated upwards and is interpreted as "packet has been sent" +which is terrible because queue is being destroyed, nobody is waiting for TX +to complete and assert it triggered. + +Fix is discard such empty packets instead of sending them. + +Length 1 packets will go via different codepath: + +virtqueue_push(q->tx_vq, elem, 0); +virtio_notify(vdev, q->tx_vq); +g_free(elem); + +and aren't problematic. + +Signed-off-by: Alexey Dobriyan +Signed-off-by: Jason Wang +(cherry picked from commit 2c3e4e2de699cd4d9f6c71f30a22d8f125cd6164) +Signed-off-by: zhujun2 +--- + hw/net/virtio-net.c | 18 ++++++++++++------ + 1 file changed, 12 insertions(+), 6 deletions(-) + +diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c +index f3fb9393b3..ab794ee789 100644 +--- a/hw/net/virtio-net.c ++++ b/hw/net/virtio-net.c +@@ -2602,18 +2602,14 @@ static int32_t virtio_net_flush_tx(VirtIONetQueue *q) + out_sg = elem->out_sg; + if (out_num < 1) { + virtio_error(vdev, "virtio-net header not in first element"); +- virtqueue_detach_element(q->tx_vq, elem, 0); +- g_free(elem); +- return -EINVAL; ++ goto detach; + } + + if (n->has_vnet_hdr) { + if (iov_to_buf(out_sg, out_num, 0, &vhdr, n->guest_hdr_len) < + n->guest_hdr_len) { + virtio_error(vdev, "virtio-net header incorrect"); +- virtqueue_detach_element(q->tx_vq, elem, 0); +- g_free(elem); +- return -EINVAL; ++ goto detach; + } + if (n->needs_vnet_hdr_swap) { + virtio_net_hdr_swap(vdev, (void *) &vhdr); +@@ -2644,6 +2640,11 @@ static int32_t virtio_net_flush_tx(VirtIONetQueue *q) + n->guest_hdr_len, -1); + out_num = sg_num; + out_sg = sg; ++ ++ if (out_num < 1) { ++ virtio_error(vdev, "virtio-net nothing to send"); ++ goto detach; ++ } + } + + ret = qemu_sendv_packet_async(qemu_get_subqueue(n->nic, queue_index), +@@ -2664,6 +2665,11 @@ drop: + } + } + return num_packets; ++ ++detach: ++ virtqueue_detach_element(q->tx_vq, elem, 0); ++ g_free(elem); ++ return -EINVAL; + } + + static void virtio_net_handle_tx_timer(VirtIODevice *vdev, VirtQueue *vq) +-- +2.41.0.windows.1 + -- Gitee From ab7fc8ee5b368afeb64cf39fd95fb2087be69662 Mon Sep 17 00:00:00 2001 From: Jiabo Feng Date: Wed, 18 Sep 2024 14:57:25 +0800 Subject: [PATCH 16/19] QEMU update to version 6.2.0-99: - target/i386: Introduce SapphireRapids-v3 to add missing features - qtest/fuzz-lsi53c895a-test: set guest RAM to 2G - hw/net/lan9118: Signal TSFL_INT flag when TX FIFO reaches specified level - target/arm: Fix alignment for VLD4.32 - hw/microblaze: pass random seed to fdt - tests/qtest: npcm7xx-emc-test: Skip checking MAC - tests: mark io-command test as skipped if socat is missing - tests: unit: add NULL-pointer check - tests: test-qga: close socket on failure to connect - vdpa:block device capacity expansion online support vdpa block device update capacity. - virtio-net: Ensure queue index fits with RSS(CVE-2024-6505) - nbd/server: CVE-2024-7409: Avoid use-after-free when closing server - ppc/vof: Fix unaligned FDT property access - vvfat: Fix reading files with non-continuous clusters - vvfat: Fix bug in writing to middle of file - savevm: Fix load_snapshot error path crash - hw/dma/xilinx_axidma: Use semicolon at end of statement, not comma - hw/remote/message.c: Don't directly invoke DeviceClass:reset - crypto/tlscredspsk: Free username on finalize - hw/display/vhost-user-gpu.c: fix vhost_user_gpu_chr_read() - virtio: remove virtio_tswap16s() call in vring_packed_event_read() - char-stdio: Restore blocking mode of stdout on exit - hw/ppc: spapr: Use qemu_vfree() to free spapr->htab - smbios: sanitize type from external type before checking have_fields_bitmap - spapr_pci: fix leak in spapr_phb_vfio_get_loc_code - KVM: use store-release to mark dirty pages as harvested - monitor/hmp: print trace as option in help for log command - tpm_crb: Avoid backend startup just before shutdown under Xen - crypto/block-luks: make range overlap check more readable - spapr: Free stdout path - target/rx: Use target_ulong for address in LI - virtio-pci: Fix the use of an uninitialized irqfd - rtl8139: Fix behaviour for old kernels. - virtio-rng: block max-bytes=0 MIME-Version: 1.0 - hw/audio/es1370: Clean up comment - vhost-user-server: do not set memory fd non-blocking - ui: reject extended clipboard message if not activated - virtio-net: Fix vhost virtqueue notifiers for RSS - hw/misc/applesmc: Fix memory leak in reset() handler Signed-off-by: Jiabo Feng (cherry picked from commit db7a5d9a7239db307c8c1454fab5f8a92fd486b8) --- ...lease-to-mark-dirty-pages-as-harvest.patch | 91 +++++++++++++++++++ ...tore-blocking-mode-of-stdout-on-exit.patch | 54 +++++++++++ ...s-make-range-overlap-check-more-read.patch | 47 ++++++++++ ...lscredspsk-Free-username-on-finalize.patch | 77 ++++++++++++++++ hw-audio-es1370-Clean-up-comment.patch | 44 +++++++++ ...-user-gpu.c-fix-vhost_user_gpu_chr_r.patch | 38 ++++++++ ...idma-Use-semicolon-at-end-of-stateme.patch | 42 +++++++++ hw-microblaze-pass-random-seed-to-fdt.patch | 54 +++++++++++ ...smc-Fix-memory-leak-in-reset-handler.patch | 40 ++++++++ ...ignal-TSFL_INT-flag-when-TX-FIFO-rea.patch | 49 ++++++++++ ...pr-Use-qemu_vfree-to-free-spapr-htab.patch | 44 +++++++++ ...e.c-Don-t-directly-invoke-DeviceClas.patch | 48 ++++++++++ ...t-trace-as-option-in-help-for-log-co.patch | 60 ++++++++++++ ...024-7409-Avoid-use-after-free-when-c.patch | 90 ++++++++++++++++++ ...of-Fix-unaligned-FDT-property-access.patch | 33 +++++++ qemu.spec | 82 ++++++++++++++++- ...-lsi53c895a-test-set-guest-RAM-to-2G.patch | 43 +++++++++ rtl8139-Fix-behaviour-for-old-kernels.patch | 35 +++++++ ...m-Fix-load_snapshot-error-path-crash.patch | 36 ++++++++ ...type-from-external-type-before-check.patch | 51 +++++++++++ spapr-Free-stdout-path.patch | 30 ++++++ ...-leak-in-spapr_phb_vfio_get_loc_code.patch | 35 +++++++ target-arm-Fix-alignment-for-VLD4.32.patch | 50 ++++++++++ ...oduce-SapphireRapids-v3-to-add-missi.patch | 48 ++++++++++ ...x-Use-target_ulong-for-address-in-LI.patch | 35 +++++++ ...mmand-test-as-skipped-if-socat-is-mi.patch | 39 ++++++++ ...t-npcm7xx-emc-test-Skip-checking-MAC.patch | 39 ++++++++ ...a-close-socket-on-failure-to-connect.patch | 32 +++++++ tests-unit-add-NULL-pointer-check.patch | 39 ++++++++ ...ckend-startup-just-before-shutdown-u.patch | 58 ++++++++++++ ...ed-clipboard-message-if-not-activate.patch | 41 +++++++++ ...ock-device-capacity-expansion-online.patch | 50 ++++++++++ ...er-do-not-set-memory-fd-non-blocking.patch | 59 ++++++++++++ ...e-queue-index-fits-with-RSS-CVE-2024.patch | 36 ++++++++ ...ix-vhost-virtqueue-notifiers-for-RSS.patch | 45 +++++++++ ...ix-the-use-of-an-uninitialized-irqfd.patch | 83 +++++++++++++++++ ...rtio_tswap16s-call-in-vring_packed_e.patch | 52 +++++++++++ ...g-block-max-bytes-0-MIME-Version-1.0.patch | 40 ++++++++ ...Fix-bug-in-writing-to-middle-of-file.patch | 42 +++++++++ ...g-files-with-non-continuous-clusters.patch | 50 ++++++++++ 40 files changed, 1960 insertions(+), 1 deletion(-) create mode 100644 KVM-use-store-release-to-mark-dirty-pages-as-harvest.patch create mode 100644 char-stdio-Restore-blocking-mode-of-stdout-on-exit.patch create mode 100644 crypto-block-luks-make-range-overlap-check-more-read.patch create mode 100644 crypto-tlscredspsk-Free-username-on-finalize.patch create mode 100644 hw-audio-es1370-Clean-up-comment.patch create mode 100644 hw-display-vhost-user-gpu.c-fix-vhost_user_gpu_chr_r.patch create mode 100644 hw-dma-xilinx_axidma-Use-semicolon-at-end-of-stateme.patch create mode 100644 hw-microblaze-pass-random-seed-to-fdt.patch create mode 100644 hw-misc-applesmc-Fix-memory-leak-in-reset-handler.patch create mode 100644 hw-net-lan9118-Signal-TSFL_INT-flag-when-TX-FIFO-rea.patch create mode 100644 hw-ppc-spapr-Use-qemu_vfree-to-free-spapr-htab.patch create mode 100644 hw-remote-message.c-Don-t-directly-invoke-DeviceClas.patch create mode 100644 monitor-hmp-print-trace-as-option-in-help-for-log-co.patch create mode 100644 nbd-server-CVE-2024-7409-Avoid-use-after-free-when-c.patch create mode 100644 ppc-vof-Fix-unaligned-FDT-property-access.patch create mode 100644 qtest-fuzz-lsi53c895a-test-set-guest-RAM-to-2G.patch create mode 100644 rtl8139-Fix-behaviour-for-old-kernels.patch create mode 100644 savevm-Fix-load_snapshot-error-path-crash.patch create mode 100644 smbios-sanitize-type-from-external-type-before-check.patch create mode 100644 spapr-Free-stdout-path.patch create mode 100644 spapr_pci-fix-leak-in-spapr_phb_vfio_get_loc_code.patch create mode 100644 target-arm-Fix-alignment-for-VLD4.32.patch create mode 100644 target-i386-Introduce-SapphireRapids-v3-to-add-missi.patch create mode 100644 target-rx-Use-target_ulong-for-address-in-LI.patch create mode 100644 tests-mark-io-command-test-as-skipped-if-socat-is-mi.patch create mode 100644 tests-qtest-npcm7xx-emc-test-Skip-checking-MAC.patch create mode 100644 tests-test-qga-close-socket-on-failure-to-connect.patch create mode 100644 tests-unit-add-NULL-pointer-check.patch create mode 100644 tpm_crb-Avoid-backend-startup-just-before-shutdown-u.patch create mode 100644 ui-reject-extended-clipboard-message-if-not-activate.patch create mode 100644 vdpa-block-device-capacity-expansion-online.patch create mode 100644 vhost-user-server-do-not-set-memory-fd-non-blocking.patch create mode 100644 virtio-net-Ensure-queue-index-fits-with-RSS-CVE-2024.patch create mode 100644 virtio-net-Fix-vhost-virtqueue-notifiers-for-RSS.patch create mode 100644 virtio-pci-Fix-the-use-of-an-uninitialized-irqfd.patch create mode 100644 virtio-remove-virtio_tswap16s-call-in-vring_packed_e.patch create mode 100644 virtio-rng-block-max-bytes-0-MIME-Version-1.0.patch create mode 100644 vvfat-Fix-bug-in-writing-to-middle-of-file.patch create mode 100644 vvfat-Fix-reading-files-with-non-continuous-clusters.patch diff --git a/KVM-use-store-release-to-mark-dirty-pages-as-harvest.patch b/KVM-use-store-release-to-mark-dirty-pages-as-harvest.patch new file mode 100644 index 00000000..f802de4b --- /dev/null +++ b/KVM-use-store-release-to-mark-dirty-pages-as-harvest.patch @@ -0,0 +1,91 @@ +From e9fc6950c9d253ab9243f662d20da3021da3cb03 Mon Sep 17 00:00:00 2001 +From: tangbinzy +Date: Wed, 4 Sep 2024 06:03:35 +0000 +Subject: [PATCH] KVM: use store-release to mark dirty pages as harvested + mainline inclusion commit 52281c6d11ec68b802e8a264780df2c4b981e6bc category: + bugfix +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +--------------------------------------------------------------- + +The following scenario can happen if QEMU sets more RESET flags while +the KVM_RESET_DIRTY_RINGS ioctl is ongoing on another host CPU: + + CPU0 CPU1 CPU2 + ------------------------ ------------------ ------------------------ + fill gfn0 + store-rel flags for gfn0 + fill gfn1 + store-rel flags for gfn1 + load-acq flags for gfn0 + set RESET for gfn0 + load-acq flags for gfn1 + set RESET for gfn1 + do ioctl! -----------> + ioctl(RESET_RINGS) + fill gfn2 + store-rel flags for gfn2 + load-acq flags for gfn2 + set RESET for gfn2 + process gfn0 + process gfn1 + process gfn2 + do ioctl! + etc. + +The three load-acquire in CPU0 synchronize with the three store-release +in CPU2, but CPU0 and CPU1 are only synchronized up to gfn1 and CPU1 +may miss gfn2's fields other than flags. + +The kernel must be able to cope with invalid values of the fields, and +userspace *will* invoke the ioctl once more. However, once the RESET flag +is cleared on gfn2, it is lost forever, therefore in the above scenario +CPU1 must read the correct value of gfn2's fields. + +Therefore RESET must be set with a store-release, that will synchronize +with KVM's load-acquire in CPU1. + +Cc: Gavin Shan +Reviewed-by: Peter Xu +Reviewed-by: Philippe Mathieu-Daudé +Signed-off-by: Paolo Bonzini + +Signed-off-by: tangbinzy +--- + accel/kvm/kvm-all.c | 18 +++++++++++++++++- + 1 file changed, 17 insertions(+), 1 deletion(-) + +diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c +index 381e3c8552..3a09307a26 100644 +--- a/accel/kvm/kvm-all.c ++++ b/accel/kvm/kvm-all.c +@@ -675,7 +675,23 @@ static bool dirty_gfn_is_dirtied(struct kvm_dirty_gfn *gfn) + + static void dirty_gfn_set_collected(struct kvm_dirty_gfn *gfn) + { +- gfn->flags = KVM_DIRTY_GFN_F_RESET; ++ /* ++ * Use a store-release so that the CPU that executes KVM_RESET_DIRTY_RINGS ++ * sees the full content of the ring: ++ * ++ * CPU0 CPU1 CPU2 ++ * ------------------------------------------------------------------------------ ++ * fill gfn0 ++ * store-rel flags for gfn0 ++ * load-acq flags for gfn0 ++ * store-rel RESET for gfn0 ++ * ioctl(RESET_RINGS) ++ * load-acq flags for gfn0 ++ * check if flags have RESET ++ * ++ * The synchronization goes from CPU2 to CPU0 to CPU1. ++ */ ++ qatomic_store_release(&gfn->flags, KVM_DIRTY_GFN_F_RESET); + } + + /* +-- +2.41.0.windows.1 + diff --git a/char-stdio-Restore-blocking-mode-of-stdout-on-exit.patch b/char-stdio-Restore-blocking-mode-of-stdout-on-exit.patch new file mode 100644 index 00000000..6d0abf40 --- /dev/null +++ b/char-stdio-Restore-blocking-mode-of-stdout-on-exit.patch @@ -0,0 +1,54 @@ +From 17744d85df589f40e889639147889c98a50bc671 Mon Sep 17 00:00:00 2001 +From: zhujun2 +Date: Wed, 4 Sep 2024 23:25:17 -0700 +Subject: [PATCH] char-stdio: Restore blocking mode of stdout on exit + +qemu_chr_open_fd() sets stdout into non-blocking mode. Restore the old +fd flags on exit to avoid breaking unsuspecting applications that run on +the same terminal after qemu and don't expect to get EAGAIN. + +While at at, also ensure term_exit is called once (at the moment it's +called both from char_stdio_finalize() and as the atexit() hook. + +Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2423 +Signed-off-by: Maxim Mikityanskiy +Link: https://lore.kernel.org/r/20240703190812.3459514-1-maxtram95@gmail.com +Signed-off-by: Paolo Bonzini +(cherry picked from commit a0124e333e2176640f233e5ea57a2f413985d9b5) +Signed-off-by: zhujun2 +--- + chardev/char-stdio.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/chardev/char-stdio.c b/chardev/char-stdio.c +index 403da308c9..69bedca7f5 100644 +--- a/chardev/char-stdio.c ++++ b/chardev/char-stdio.c +@@ -41,6 +41,7 @@ + /* init terminal so that we can grab keys */ + static struct termios oldtty; + static int old_fd0_flags; ++static int old_fd1_flags; + static bool stdio_in_use; + static bool stdio_allow_signal; + static bool stdio_echo_state; +@@ -50,6 +51,8 @@ static void term_exit(void) + if (stdio_in_use) { + tcsetattr(0, TCSANOW, &oldtty); + fcntl(0, F_SETFL, old_fd0_flags); ++ fcntl(1, F_SETFL, old_fd1_flags); ++ stdio_in_use = false; + } + } + +@@ -102,6 +105,7 @@ static void qemu_chr_open_stdio(Chardev *chr, + + stdio_in_use = true; + old_fd0_flags = fcntl(0, F_GETFL); ++ old_fd1_flags = fcntl(1, F_GETFL); + tcgetattr(0, &oldtty); + qemu_set_nonblock(0); + atexit(term_exit); +-- +2.41.0.windows.1 + diff --git a/crypto-block-luks-make-range-overlap-check-more-read.patch b/crypto-block-luks-make-range-overlap-check-more-read.patch new file mode 100644 index 00000000..80bae5fc --- /dev/null +++ b/crypto-block-luks-make-range-overlap-check-more-read.patch @@ -0,0 +1,47 @@ +From ca6f8348075be1839e87fa826a2719127ec64d41 Mon Sep 17 00:00:00 2001 +From: dinglimin +Date: Mon, 2 Sep 2024 17:40:40 +0800 +Subject: [PATCH] crypto/block-luks: make range overlap check more readable +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +cheery-pick from 7cd9b9d476e729808f3c9b82a12f51a39673d5cb + +use ranges_overlap() instead of open-coding the overlap check to improve the readability of the code. + +Signed-off-by: Yao Xingtao +Reviewed-by: Philippe Mathieu-Daudé +Tested-by: Philippe Mathieu-Daudé +Reviewed-by: Daniel P. Berrangé +Message-ID: <20240722040742.11513-12-yaoxt.fnst@fujitsu.com> +Signed-off-by: Philippe Mathieu-Daudé +Signed-off-by: dinglimin +--- + crypto/block-luks.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/crypto/block-luks.c b/crypto/block-luks.c +index fe8f04ffb2..2648719337 100644 +--- a/crypto/block-luks.c ++++ b/crypto/block-luks.c +@@ -33,6 +33,7 @@ + + #include "qemu/coroutine.h" + #include "qemu/bitmap.h" ++#include "qemu/range.h" + + /* + * Reference for the LUKS format implemented here is +@@ -591,7 +592,7 @@ qcrypto_block_luks_check_header(const QCryptoBlockLUKS *luks, Error **errp) + header_sectors, + slot2->stripes); + +- if (start1 + len1 > start2 && start2 + len2 > start1) { ++ if (ranges_overlap(start1, len1, start2, len2)) { + error_setg(errp, + "Keyslots %zu and %zu are overlapping in the header", + i, j); +-- +2.41.0.windows.1 + diff --git a/crypto-tlscredspsk-Free-username-on-finalize.patch b/crypto-tlscredspsk-Free-username-on-finalize.patch new file mode 100644 index 00000000..84262124 --- /dev/null +++ b/crypto-tlscredspsk-Free-username-on-finalize.patch @@ -0,0 +1,77 @@ +From 58fb7b6216c6b2c8204e1046dd788f18eeb3b45f Mon Sep 17 00:00:00 2001 +From: Peter Maydell +Date: Mon, 19 Aug 2024 15:50:21 +0100 +Subject: [PATCH] crypto/tlscredspsk: Free username on finalize +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +When the creds->username property is set we allocate memory +for it in qcrypto_tls_creds_psk_prop_set_username(), but +we never free this when the QCryptoTLSCredsPSK is destroyed. +Free the memory in finalize. + +This fixes a LeakSanitizer complaint in migration-test: + +$ (cd build/asan; ASAN_OPTIONS="fast_unwind_on_malloc=0" QTEST_QEMU_BINARY=./qemu-system-x86_64 ./tests/qtest/migration-test --tap -k -p /x86_64/migration/precopy/unix/tls/psk) + +================================================================= +==3867512==ERROR: LeakSanitizer: detected memory leaks + +Direct leak of 5 byte(s) in 1 object(s) allocated from: + #0 0x5624e5c99dee in malloc (/mnt/nvmedisk/linaro/qemu-from-laptop/qemu/build/asan/qemu-system-x86_64+0x218edee) (BuildId: a9e623fa1009a9435c0142c037cd7b8c1ad04ce3) + #1 0x7fb199ae9738 in g_malloc debian/build/deb/../../../glib/gmem.c:128:13 + #2 0x7fb199afe583 in g_strdup debian/build/deb/../../../glib/gstrfuncs.c:361:17 + #3 0x5624e82ea919 in qcrypto_tls_creds_psk_prop_set_username /mnt/nvmedisk/linaro/qemu-from-laptop/qemu/build/asan/../../crypto/tlscredspsk.c:255:23 + #4 0x5624e812c6b5 in property_set_str /mnt/nvmedisk/linaro/qemu-from-laptop/qemu/build/asan/../../qom/object.c:2277:5 + #5 0x5624e8125ce5 in object_property_set /mnt/nvmedisk/linaro/qemu-from-laptop/qemu/build/asan/../../qom/object.c:1463:5 + #6 0x5624e8136e7c in object_set_properties_from_qdict /mnt/nvmedisk/linaro/qemu-from-laptop/qemu/build/asan/../../qom/object_interfaces.c:55:14 + #7 0x5624e81372d2 in user_creatable_add_type /mnt/nvmedisk/linaro/qemu-from-laptop/qemu/build/asan/../../qom/object_interfaces.c:112:5 + #8 0x5624e8137964 in user_creatable_add_qapi /mnt/nvmedisk/linaro/qemu-from-laptop/qemu/build/asan/../../qom/object_interfaces.c:157:11 + #9 0x5624e891ba3c in qmp_object_add /mnt/nvmedisk/linaro/qemu-from-laptop/qemu/build/asan/../../qom/qom-qmp-cmds.c:227:5 + #10 0x5624e8af9118 in qmp_marshal_object_add /mnt/nvmedisk/linaro/qemu-from-laptop/qemu/build/asan/qapi/qapi-commands-qom.c:337:5 + #11 0x5624e8bd1d49 in do_qmp_dispatch_bh /mnt/nvmedisk/linaro/qemu-from-laptop/qemu/build/asan/../../qapi/qmp-dispatch.c:128:5 + #12 0x5624e8cb2531 in aio_bh_call /mnt/nvmedisk/linaro/qemu-from-laptop/qemu/build/asan/../../util/async.c:171:5 + #13 0x5624e8cb340c in aio_bh_poll /mnt/nvmedisk/linaro/qemu-from-laptop/qemu/build/asan/../../util/async.c:218:13 + #14 0x5624e8c0be98 in aio_dispatch /mnt/nvmedisk/linaro/qemu-from-laptop/qemu/build/asan/../../util/aio-posix.c:423:5 + #15 0x5624e8cba3ce in aio_ctx_dispatch /mnt/nvmedisk/linaro/qemu-from-laptop/qemu/build/asan/../../util/async.c:360:5 + #16 0x7fb199ae0d3a in g_main_dispatch debian/build/deb/../../../glib/gmain.c:3419:28 + #17 0x7fb199ae0d3a in g_main_context_dispatch debian/build/deb/../../../glib/gmain.c:4137:7 + #18 0x5624e8cbe1d9 in glib_pollfds_poll /mnt/nvmedisk/linaro/qemu-from-laptop/qemu/build/asan/../../util/main-loop.c:287:9 + #19 0x5624e8cbcb13 in os_host_main_loop_wait /mnt/nvmedisk/linaro/qemu-from-laptop/qemu/build/asan/../../util/main-loop.c:310:5 + #20 0x5624e8cbc6dc in main_loop_wait /mnt/nvmedisk/linaro/qemu-from-laptop/qemu/build/asan/../../util/main-loop.c:589:11 + #21 0x5624e6f3f917 in qemu_main_loop /mnt/nvmedisk/linaro/qemu-from-laptop/qemu/build/asan/../../system/runstate.c:801:9 + #22 0x5624e893379c in qemu_default_main /mnt/nvmedisk/linaro/qemu-from-laptop/qemu/build/asan/../../system/main.c:37:14 + #23 0x5624e89337e7 in main /mnt/nvmedisk/linaro/qemu-from-laptop/qemu/build/asan/../../system/main.c:48:12 + #24 0x7fb197972d8f in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16 + #25 0x7fb197972e3f in __libc_start_main csu/../csu/libc-start.c:392:3 + #26 0x5624e5c16fa4 in _start (/mnt/nvmedisk/linaro/qemu-from-laptop/qemu/build/asan/qemu-system-x86_64+0x210bfa4) (BuildId: a9e623fa1009a9435c0142c037cd7b8c1ad04ce3) + +SUMMARY: AddressSanitizer: 5 byte(s) leaked in 1 allocation(s). + +Cc: qemu-stable@nongnu.org +Signed-off-by: Peter Maydell +Reviewed-by: Daniel P. Berrangé +Message-ID: <20240819145021.38524-1-peter.maydell@linaro.org> +Signed-off-by: Philippe Mathieu-Daudé +--- + crypto/tlscredspsk.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/crypto/tlscredspsk.c b/crypto/tlscredspsk.c +index 752f2d92be..9ab62b411d 100644 +--- a/crypto/tlscredspsk.c ++++ b/crypto/tlscredspsk.c +@@ -245,6 +245,7 @@ qcrypto_tls_creds_psk_finalize(Object *obj) + QCryptoTLSCredsPSK *creds = QCRYPTO_TLS_CREDS_PSK(obj); + + qcrypto_tls_creds_psk_unload(creds); ++ g_free(creds->username); + } + + static void +-- +2.41.0.windows.1 + diff --git a/hw-audio-es1370-Clean-up-comment.patch b/hw-audio-es1370-Clean-up-comment.patch new file mode 100644 index 00000000..8c04a0b6 --- /dev/null +++ b/hw-audio-es1370-Clean-up-comment.patch @@ -0,0 +1,44 @@ +From 25a18f3ade8c4c412d21b9147f018fc7c55558d4 Mon Sep 17 00:00:00 2001 +From: zhujun2 +Date: Thu, 15 Aug 2024 23:59:42 -0700 +Subject: [PATCH] hw/audio/es1370: Clean up comment +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Replace a sweary comment with one that's a bit more helpful to +future readers of the code. + +Signed-off-by: Peter Maydell +Reviewed-by: Volker Rümelin +Message-ID: <20231110164318.2197569-1-peter.maydell@linaro.org> +Signed-off-by: Thomas Huth +(cherry picked from commit 4409a6d85522925df580554d476161a570bb1ed9) +Signed-off-by: zhujun2 +--- + hw/audio/es1370.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/hw/audio/es1370.c b/hw/audio/es1370.c +index 6904589814..72de110e0b 100644 +--- a/hw/audio/es1370.c ++++ b/hw/audio/es1370.c +@@ -702,8 +702,13 @@ static void es1370_transfer_audio (ES1370State *s, struct chan *d, int loop_sel, + cnt += (transferred + d->leftover) >> 2; + + if (s->sctl & loop_sel) { +- /* Bah, how stupid is that having a 0 represent true value? +- i just spent few hours on this shit */ ++ /* ++ * loop_sel tells us which bit in the SCTL register to look at ++ * (either P1_LOOP_SEL, P2_LOOP_SEL or R1_LOOP_SEL). The sense ++ * of these bits is 0 for loop mode (set interrupt and keep recording ++ * when the sample count reaches zero) or 1 for stop mode (set ++ * interrupt and stop recording). ++ */ + AUD_log ("es1370: warning", "non looping mode\n"); + } + else { +-- +2.41.0.windows.1 + diff --git a/hw-display-vhost-user-gpu.c-fix-vhost_user_gpu_chr_r.patch b/hw-display-vhost-user-gpu.c-fix-vhost_user_gpu_chr_r.patch new file mode 100644 index 00000000..44c7b2ce --- /dev/null +++ b/hw-display-vhost-user-gpu.c-fix-vhost_user_gpu_chr_r.patch @@ -0,0 +1,38 @@ +From a5e9442e8e386e62c043fa0b5fba469251fa5d4d Mon Sep 17 00:00:00 2001 +From: Haoran Zhang +Date: Thu, 22 Aug 2024 11:07:58 +0800 +Subject: [PATCH] hw/display/vhost-user-gpu.c: fix vhost_user_gpu_chr_read() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +fix vhost_user_gpu_chr_read() where `size` was incorrectly passed to `msg->flags`. + +Fixes: 267f664658 ("hw/display: add vhost-user-vga & gpu-pci") +Signed-off-by: Haoran Zhang +Reviewed-by: Marc-André Lureau +Reviewed-by: Philippe Mathieu-Daudé +Reviewed-by: Michael Tokarev +Signed-off-by: Michael Tokarev +(cherry picked from commit d6192f3f7593536a4285e8ab6c6cf3f34973ce62) +Signed-off-by: zhujun2 +--- + hw/display/vhost-user-gpu.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/hw/display/vhost-user-gpu.c b/hw/display/vhost-user-gpu.c +index 4363e34db1..b2d89cd54e 100644 +--- a/hw/display/vhost-user-gpu.c ++++ b/hw/display/vhost-user-gpu.c +@@ -334,7 +334,7 @@ vhost_user_gpu_chr_read(void *opaque) + } + + msg->request = request; +- msg->flags = size; ++ msg->flags = flags; + msg->size = size; + + if (request == VHOST_USER_GPU_CURSOR_UPDATE || +-- +2.41.0.windows.1 + diff --git a/hw-dma-xilinx_axidma-Use-semicolon-at-end-of-stateme.patch b/hw-dma-xilinx_axidma-Use-semicolon-at-end-of-stateme.patch new file mode 100644 index 00000000..e54ca7a6 --- /dev/null +++ b/hw-dma-xilinx_axidma-Use-semicolon-at-end-of-stateme.patch @@ -0,0 +1,42 @@ +From 1816af81d099d0ab7dc434a42e7218184894e3ef Mon Sep 17 00:00:00 2001 +From: Peter Maydell +Date: Tue, 13 Aug 2024 17:52:45 +0100 +Subject: [PATCH] hw/dma/xilinx_axidma: Use semicolon at end of statement, not + comma +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +In axidma_class_init() we accidentally used a comma at the end of +a statement rather than a semicolon. This has no ill effects, but +it's obviously not intended and it means that Coccinelle scripts +for instance will fail to match on the two statements. Use a +semicolon instead. + +Signed-off-by: Peter Maydell +Reviewed-by: Richard Henderson +Reviewed-by: Thomas Huth +Message-ID: <20240813165250.2717650-6-peter.maydell@linaro.org> +Signed-off-by: Philippe Mathieu-Daudé +--- + hw/dma/xilinx_axidma.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/hw/dma/xilinx_axidma.c b/hw/dma/xilinx_axidma.c +index bc383f53cc..5044fb146d 100644 +--- a/hw/dma/xilinx_axidma.c ++++ b/hw/dma/xilinx_axidma.c +@@ -598,7 +598,7 @@ static void axidma_class_init(ObjectClass *klass, void *data) + { + DeviceClass *dc = DEVICE_CLASS(klass); + +- dc->realize = xilinx_axidma_realize, ++ dc->realize = xilinx_axidma_realize; + dc->reset = xilinx_axidma_reset; + device_class_set_props(dc, axidma_properties); + } +-- +2.41.0.windows.1 + diff --git a/hw-microblaze-pass-random-seed-to-fdt.patch b/hw-microblaze-pass-random-seed-to-fdt.patch new file mode 100644 index 00000000..58f38c3a --- /dev/null +++ b/hw-microblaze-pass-random-seed-to-fdt.patch @@ -0,0 +1,54 @@ +From 74e95f7071c8d8f40b352992b19c967655459b31 Mon Sep 17 00:00:00 2001 +From: tangbinzy +Date: Mon, 9 Sep 2024 08:20:28 +0000 +Subject: [PATCH] hw/microblaze: pass random seed to fdt mainline inclusion + commit b91b6b5a2cd83a096116929dfc8e016091080adc category: bugfix + +--------------------------------------------------------------- + +If the FDT contains /chosen/rng-seed, then the Linux RNG will use it to +initialize early. Set this using the usual guest random number +generation function. This FDT node is part of the DT specification. + +Reviewed-by: Edgar E. Iglesias +Signed-off-by: Jason A. Donenfeld +Signed-off-by: Edgar E. Iglesias + +Signed-off-by: tangbinzy +--- + hw/microblaze/boot.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/hw/microblaze/boot.c b/hw/microblaze/boot.c +index 8821d009f1..26f315aaea 100644 +--- a/hw/microblaze/boot.c ++++ b/hw/microblaze/boot.c +@@ -31,6 +31,7 @@ + #include "qemu/option.h" + #include "qemu/config-file.h" + #include "qemu/error-report.h" ++#include "qemu/guest-random.h" + #include "sysemu/device_tree.h" + #include "sysemu/reset.h" + #include "hw/boards.h" +@@ -76,6 +77,7 @@ static int microblaze_load_dtb(hwaddr addr, + int fdt_size; + void *fdt = NULL; + int r; ++ uint8_t rng_seed[32]; + + if (dtb_filename) { + fdt = load_device_tree(dtb_filename, &fdt_size); +@@ -84,6 +86,9 @@ static int microblaze_load_dtb(hwaddr addr, + return 0; + } + ++ qemu_guest_getrandom_nofail(rng_seed, sizeof(rng_seed)); ++ qemu_fdt_setprop(fdt, "/chosen", "rng-seed", rng_seed, sizeof(rng_seed)); ++ + if (kernel_cmdline) { + r = qemu_fdt_setprop_string(fdt, "/chosen", "bootargs", + kernel_cmdline); +-- +2.41.0.windows.1 + diff --git a/hw-misc-applesmc-Fix-memory-leak-in-reset-handler.patch b/hw-misc-applesmc-Fix-memory-leak-in-reset-handler.patch new file mode 100644 index 00000000..74958e93 --- /dev/null +++ b/hw-misc-applesmc-Fix-memory-leak-in-reset-handler.patch @@ -0,0 +1,40 @@ +From dd51b99923c20a289f4b2c9de0cba5d272fbb493 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Mon, 8 Apr 2024 11:41:59 +0200 +Subject: [PATCH] hw/misc/applesmc: Fix memory leak in reset() handler +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +AppleSMCData is allocated with g_new0() in applesmc_add_key(): +release it with g_free(). + +Leaked since commit 1ddda5cd36 ("AppleSMC device emulation"). + +Cc: qemu-stable@nongnu.org +Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2272 +Reported-by: Zheyu Ma +Signed-off-by: Philippe Mathieu-Daudé +Reviewed-by: Peter Maydell +Message-Id: <20240408095217.57239-3-philmd@linaro.org> +(cherry picked from commit fc09ff2979defdcf8d00c2db94022d5d610e36ba) +Signed-off-by: zhujun2 +--- + hw/misc/applesmc.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/hw/misc/applesmc.c b/hw/misc/applesmc.c +index 1b9acaf1d3..e17229025f 100644 +--- a/hw/misc/applesmc.c ++++ b/hw/misc/applesmc.c +@@ -269,6 +269,7 @@ static void qdev_applesmc_isa_reset(DeviceState *dev) + /* Remove existing entries */ + QLIST_FOREACH_SAFE(d, &s->data_def, node, next) { + QLIST_REMOVE(d, node); ++ g_free(d); + } + s->status = 0x00; + s->status_1e = 0x00; +-- +2.41.0.windows.1 + diff --git a/hw-net-lan9118-Signal-TSFL_INT-flag-when-TX-FIFO-rea.patch b/hw-net-lan9118-Signal-TSFL_INT-flag-when-TX-FIFO-rea.patch new file mode 100644 index 00000000..3cebf928 --- /dev/null +++ b/hw-net-lan9118-Signal-TSFL_INT-flag-when-TX-FIFO-rea.patch @@ -0,0 +1,49 @@ +From 8b72b72180276e4f0af962e60fead6bdbe0e0577 Mon Sep 17 00:00:00 2001 +From: tangbinzy +Date: Tue, 10 Sep 2024 11:42:12 +0000 +Subject: [PATCH] hw/net/lan9118: Signal TSFL_INT flag when TX FIFO reaches + specified level mainline inclusion commit + 895a803ce91704f28c9b49621a4f589273289f1e category: bugfix + +--------------------------------------------------------------- + +The LAN9118 allows the guest to specify a level for both the TX and +RX FIFOs at which an interrupt will be generated. We implement the +RSFL_INT interrupt for the RX FIFO but are missing the handling of +the equivalent TSFL_INT for the TX FIFO. Add the missing test to set +the interrupt if the TX FIFO has exceeded the guest-specified level. + +This flag is required for Micrium lan911x ethernet driver to work. + +Signed-off-by: Lucas Dietrich +[PMM: Tweaked commit message and comment] +Reviewed-by: Peter Maydell +Signed-off-by: Peter Maydell + +Signed-off-by: tangbinzy +--- + hw/net/lan9118.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/hw/net/lan9118.c b/hw/net/lan9118.c +index fa43758105..9897296c21 100644 +--- a/hw/net/lan9118.c ++++ b/hw/net/lan9118.c +@@ -702,6 +702,14 @@ static void do_tx_packet(lan9118_state *s) + n = (s->tx_status_fifo_head + s->tx_status_fifo_used) & 511; + s->tx_status_fifo[n] = status; + s->tx_status_fifo_used++; ++ ++ /* ++ * Generate TSFL interrupt if TX FIFO level exceeds the level ++ * specified in the FIFO_INT TX Status Level field. ++ */ ++ if (s->tx_status_fifo_used > ((s->fifo_int >> 16) & 0xff)) { ++ s->int_sts |= TSFL_INT; ++ } + if (s->tx_status_fifo_used == 512) { + s->int_sts |= TSFF_INT; + /* TODO: Stop transmission. */ +-- +2.41.0.windows.1 + diff --git a/hw-ppc-spapr-Use-qemu_vfree-to-free-spapr-htab.patch b/hw-ppc-spapr-Use-qemu_vfree-to-free-spapr-htab.patch new file mode 100644 index 00000000..fe1d1ef9 --- /dev/null +++ b/hw-ppc-spapr-Use-qemu_vfree-to-free-spapr-htab.patch @@ -0,0 +1,44 @@ +From 814378bd1174b4cb9f98e5ed0cac4f4d700c893d Mon Sep 17 00:00:00 2001 +From: tangbinzy +Date: Wed, 4 Sep 2024 08:25:49 +0000 +Subject: [PATCH] hw/ppc: spapr: Use qemu_vfree() to free spapr->htab mainline + inclusion commit cb5b5ab9a516ce5ecddfc50971bf6f690300fd74 category: bugfix +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +--------------------------------------------------------------- + +spapr->htab is allocated by qemu_memalign(), hence we should use +qemu_vfree() to free it. + +Fixes: c5f54f3e31bf ("pseries: Move hash page table allocation to reset time") +Fixes: b4db54132ffe ("target/ppc: Implement H_REGISTER_PROCESS_TABLE H_CALL"") +Signed-off-by: Xuzhou Cheng +Signed-off-by: Bin Meng +Reviewed-by: Daniel Henrique Barboza +Reviewed-by: Marc-André Lureau +Message-Id: <20220920103159.1865256-28-bmeng.cn@gmail.com> +Signed-off-by: Daniel Henrique Barboza + +Signed-off-by: tangbinzy +--- + hw/ppc/spapr.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c +index d1fbea16e3..6727ea7118 100644 +--- a/hw/ppc/spapr.c ++++ b/hw/ppc/spapr.c +@@ -1482,7 +1482,7 @@ int spapr_hpt_shift_for_ramsize(uint64_t ramsize) + + void spapr_free_hpt(SpaprMachineState *spapr) + { +- g_free(spapr->htab); ++ qemu_vfree(spapr->htab); + spapr->htab = NULL; + spapr->htab_shift = 0; + close_htab_fd(spapr); +-- +2.41.0.windows.1 + diff --git a/hw-remote-message.c-Don-t-directly-invoke-DeviceClas.patch b/hw-remote-message.c-Don-t-directly-invoke-DeviceClas.patch new file mode 100644 index 00000000..2d4d8f6c --- /dev/null +++ b/hw-remote-message.c-Don-t-directly-invoke-DeviceClas.patch @@ -0,0 +1,48 @@ +From ea0169b5de433426e863f162f7a299fc29b9ff8d Mon Sep 17 00:00:00 2001 +From: Peter Maydell +Date: Tue, 13 Aug 2024 17:52:46 +0100 +Subject: [PATCH] hw/remote/message.c: Don't directly invoke DeviceClass:reset +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Directly invoking the DeviceClass::reset method is a bad idea, +because if the device is using three-phase reset then it relies on +transitional reset machinery which is likely to disappear at some +point. + +Reset the device in the standard way, by calling device_cold_reset(). + +Signed-off-by: Peter Maydell +Reviewed-by: Richard Henderson +Reviewed-by: Philippe Mathieu-Daudé +Message-ID: <20240813165250.2717650-7-peter.maydell@linaro.org> +Signed-off-by: Philippe Mathieu-Daudé +--- + hw/remote/message.c | 5 +---- + 1 file changed, 1 insertion(+), 4 deletions(-) + +diff --git a/hw/remote/message.c b/hw/remote/message.c +index 11d729845c..83b91c8762 100644 +--- a/hw/remote/message.c ++++ b/hw/remote/message.c +@@ -216,13 +216,10 @@ fail: + static void process_device_reset_msg(QIOChannel *ioc, PCIDevice *dev, + Error **errp) + { +- DeviceClass *dc = DEVICE_GET_CLASS(dev); + DeviceState *s = DEVICE(dev); + MPQemuMsg ret = { 0 }; + +- if (dc->reset) { +- dc->reset(s); +- } ++ device_cold_reset(s); + + ret.cmd = MPQEMU_CMD_RET; + +-- +2.41.0.windows.1 + diff --git a/monitor-hmp-print-trace-as-option-in-help-for-log-co.patch b/monitor-hmp-print-trace-as-option-in-help-for-log-co.patch new file mode 100644 index 00000000..6414d677 --- /dev/null +++ b/monitor-hmp-print-trace-as-option-in-help-for-log-co.patch @@ -0,0 +1,60 @@ +From 0807b94d2cb88f1253d90f649604f0110b33f9b4 Mon Sep 17 00:00:00 2001 +From: tangbinzy +Date: Tue, 3 Sep 2024 02:12:05 +0000 +Subject: [PATCH] monitor/hmp: print trace as option in help for log command + mainline inclusion commit 3183bb3f441ba5b9da570f7f5f9abdc3313ba311 category: + bugfix + +--------------------------------------------------------------- + +The below is printed when printing help information in qemu-system-x86_64 +command line, and when CONFIG_TRACE_LOG is enabled: + +---------------------------- +$ qemu-system-x86_64 -d help +... ... +trace:PATTERN enable trace events + +Use "-d trace:help" to get a list of trace events. +---------------------------- + +However, the options of "trace:PATTERN" are only printed by +"qemu-system-x86_64 -d help", but missing in hmp "help log" command. + +Fixes: c84ea00dc2 ("log: add "-d trace:PATTERN"") +Cc: Joe Jin +Signed-off-by: Dongli Zhang +Message-Id: <20220831213943.8155-1-dongli.zhang@oracle.com> +Reviewed-by: Markus Armbruster +Signed-off-by: Dr. David Alan Gilbert + +Signed-off-by: tangbinzy +--- + monitor/hmp.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/monitor/hmp.c b/monitor/hmp.c +index b20737e63c..9cbbe52812 100644 +--- a/monitor/hmp.c ++++ b/monitor/hmp.c +@@ -285,10 +285,15 @@ void help_cmd(Monitor *mon, const char *name) + if (!strcmp(name, "log")) { + const QEMULogItem *item; + monitor_printf(mon, "Log items (comma separated):\n"); +- monitor_printf(mon, "%-10s %s\n", "none", "remove all logs"); ++ monitor_printf(mon, "%-15s %s\n", "none", "remove all logs"); + for (item = qemu_log_items; item->mask != 0; item++) { +- monitor_printf(mon, "%-10s %s\n", item->name, item->help); ++ monitor_printf(mon, "%-15s %s\n", item->name, item->help); + } ++#ifdef CONFIG_TRACE_LOG ++ monitor_printf(mon, "trace:PATTERN enable trace events\n"); ++ monitor_printf(mon, "\nUse \"log trace:help\" to get a list of " ++ "trace events.\n\n"); ++#endif + return; + } + +-- +2.41.0.windows.1 + diff --git a/nbd-server-CVE-2024-7409-Avoid-use-after-free-when-c.patch b/nbd-server-CVE-2024-7409-Avoid-use-after-free-when-c.patch new file mode 100644 index 00000000..0d036345 --- /dev/null +++ b/nbd-server-CVE-2024-7409-Avoid-use-after-free-when-c.patch @@ -0,0 +1,90 @@ +From fa58315ae2b81ea8b5b352bf19ff6bc1d3a4c684 Mon Sep 17 00:00:00 2001 +From: Eric Blake +Date: Thu, 22 Aug 2024 09:35:29 -0500 +Subject: [PATCH] nbd/server: CVE-2024-7409: Avoid use-after-free when closing + server + +Commit 3e7ef738 plugged the use-after-free of the global nbd_server +object, but overlooked a use-after-free of nbd_server->listener. +Although this race is harder to hit, notice that our shutdown path +first drops the reference count of nbd_server->listener, then triggers +actions that can result in a pending client reaching the +nbd_blockdev_client_closed() callback, which in turn calls +qio_net_listener_set_client_func on a potentially stale object. + +If we know we don't want any more clients to connect, and have already +told the listener socket to shut down, then we should not be trying to +update the listener socket's associated function. + +Reproducer: + +> #!/usr/bin/python3 +> +> import os +> from threading import Thread +> +> def start_stop(): +> while 1: +> os.system('virsh qemu-monitor-command VM \'{"execute": "nbd-server-start", ++"arguments":{"addr":{"type":"unix","data":{"path":"/tmp/nbd-sock"}}}}\'') +> os.system('virsh qemu-monitor-command VM \'{"execute": "nbd-server-stop"}\'') +> +> def nbd_list(): +> while 1: +> os.system('/path/to/build/qemu-nbd -L -k /tmp/nbd-sock') +> +> def test(): +> sst = Thread(target=start_stop) +> sst.start() +> nlt = Thread(target=nbd_list) +> nlt.start() +> +> sst.join() +> nlt.join() +> +> test() + +Fixes: CVE-2024-7409 +Fixes: 3e7ef738c8 ("nbd/server: CVE-2024-7409: Close stray clients at server-stop") +CC: qemu-stable@nongnu.org +Reported-by: Andrey Drobyshev +Signed-off-by: Eric Blake +Message-ID: <20240822143617.800419-2-eblake@redhat.com> +Reviewed-by: Stefan Hajnoczi +--- + blockdev-nbd.c | 12 ++++++++---- + 1 file changed, 8 insertions(+), 4 deletions(-) + +diff --git a/blockdev-nbd.c b/blockdev-nbd.c +index c71ca38d29..94e9eddc3c 100644 +--- a/blockdev-nbd.c ++++ b/blockdev-nbd.c +@@ -87,10 +87,13 @@ static void nbd_accept(QIONetListener *listener, QIOChannelSocket *cioc, + + static void nbd_update_server_watch(NBDServerData *s) + { +- if (!s->max_connections || s->connections < s->max_connections) { +- qio_net_listener_set_client_func(s->listener, nbd_accept, NULL, NULL); +- } else { +- qio_net_listener_set_client_func(s->listener, NULL, NULL, NULL); ++ if (s->listener) { ++ if (!s->max_connections || s->connections < s->max_connections) { ++ qio_net_listener_set_client_func(s->listener, nbd_accept, NULL, ++ NULL); ++ } else { ++ qio_net_listener_set_client_func(s->listener, NULL, NULL, NULL); ++ } + } + } + +@@ -108,6 +111,7 @@ static void nbd_server_free(NBDServerData *server) + */ + qio_net_listener_disconnect(server->listener); + object_unref(OBJECT(server->listener)); ++ server->listener = NULL; + QLIST_FOREACH_SAFE(conn, &server->conns, next, tmp) { + qio_channel_shutdown(QIO_CHANNEL(conn->cioc), QIO_CHANNEL_SHUTDOWN_BOTH, + NULL); +-- +2.41.0.windows.1 + diff --git a/ppc-vof-Fix-unaligned-FDT-property-access.patch b/ppc-vof-Fix-unaligned-FDT-property-access.patch new file mode 100644 index 00000000..ee6eb267 --- /dev/null +++ b/ppc-vof-Fix-unaligned-FDT-property-access.patch @@ -0,0 +1,33 @@ +From 387b359dd8713cdf5e234bdbc41bc6546934c160 Mon Sep 17 00:00:00 2001 +From: Akihiko Odaki +Date: Mon, 8 Jul 2024 15:55:13 +0900 +Subject: [PATCH] ppc/vof: Fix unaligned FDT property access + +FDT properties are aligned by 4 bytes, not 8 bytes. + +Signed-off-by: Akihiko Odaki +Reviewed-by: Peter Maydell +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Nicholas Piggin +(cherry picked from commit 785c8637f9d2362a8addf4ded853d975955a9d6b) +Signed-off-by: zhujun2 +--- + hw/ppc/vof.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/hw/ppc/vof.c b/hw/ppc/vof.c +index b1aa0ceb8b..cb1ae6fabf 100644 +--- a/hw/ppc/vof.c ++++ b/hw/ppc/vof.c +@@ -648,7 +648,7 @@ static void vof_dt_memory_available(void *fdt, GArray *claimed, uint64_t base) + mem0_reg = fdt_getprop(fdt, offset, "reg", &proplen); + g_assert(mem0_reg && proplen == sizeof(uint32_t) * (ac + sc)); + if (sc == 2) { +- mem0_end = be64_to_cpu(*(uint64_t *)(mem0_reg + sizeof(uint32_t) * ac)); ++ mem0_end = ldq_be_p(mem0_reg + sizeof(uint32_t) * ac); + } else { + mem0_end = be32_to_cpu(*(uint32_t *)(mem0_reg + sizeof(uint32_t) * ac)); + } +-- +2.41.0.windows.1 + diff --git a/qemu.spec b/qemu.spec index 409feba2..fa7c941a 100644 --- a/qemu.spec +++ b/qemu.spec @@ -3,7 +3,7 @@ Name: qemu Version: 6.2.0 -Release: 98 +Release: 99 Epoch: 10 Summary: QEMU is a generic and open source machine emulator and virtualizer License: GPLv2 and BSD and MIT and CC-BY-SA-4.0 @@ -1005,6 +1005,45 @@ Patch0990: aspeed-hace-Initialize-g_autofree-pointer.patch Patch0991: migration-Skip-only-empty-block-devices.patch Patch0992: hmat-acpi-Fix-out-of-bounds-access-due-to-missing-us.patch Patch0993: pci-host-designware-Limit-value-range-of-iATU-viewpo.patch +Patch0994: hw-misc-applesmc-Fix-memory-leak-in-reset-handler.patch +Patch0995: virtio-net-Fix-vhost-virtqueue-notifiers-for-RSS.patch +Patch0996: ui-reject-extended-clipboard-message-if-not-activate.patch +Patch0997: vhost-user-server-do-not-set-memory-fd-non-blocking.patch +Patch0998: hw-audio-es1370-Clean-up-comment.patch +Patch0999: virtio-rng-block-max-bytes-0-MIME-Version-1.0.patch +Patch1000: rtl8139-Fix-behaviour-for-old-kernels.patch +Patch1001: virtio-pci-Fix-the-use-of-an-uninitialized-irqfd.patch +Patch1002: target-rx-Use-target_ulong-for-address-in-LI.patch +Patch1003: spapr-Free-stdout-path.patch +Patch1004: crypto-block-luks-make-range-overlap-check-more-read.patch +Patch1005: tpm_crb-Avoid-backend-startup-just-before-shutdown-u.patch +Patch1006: monitor-hmp-print-trace-as-option-in-help-for-log-co.patch +Patch1007: KVM-use-store-release-to-mark-dirty-pages-as-harvest.patch +Patch1008: spapr_pci-fix-leak-in-spapr_phb_vfio_get_loc_code.patch +Patch1009: smbios-sanitize-type-from-external-type-before-check.patch +Patch1010: hw-ppc-spapr-Use-qemu_vfree-to-free-spapr-htab.patch +Patch1011: char-stdio-Restore-blocking-mode-of-stdout-on-exit.patch +Patch1012: virtio-remove-virtio_tswap16s-call-in-vring_packed_e.patch +Patch1013: hw-display-vhost-user-gpu.c-fix-vhost_user_gpu_chr_r.patch +Patch1014: crypto-tlscredspsk-Free-username-on-finalize.patch +Patch1015: hw-remote-message.c-Don-t-directly-invoke-DeviceClas.patch +Patch1016: hw-dma-xilinx_axidma-Use-semicolon-at-end-of-stateme.patch +Patch1017: savevm-Fix-load_snapshot-error-path-crash.patch +Patch1018: vvfat-Fix-bug-in-writing-to-middle-of-file.patch +Patch1019: vvfat-Fix-reading-files-with-non-continuous-clusters.patch +Patch1020: ppc-vof-Fix-unaligned-FDT-property-access.patch +Patch1021: nbd-server-CVE-2024-7409-Avoid-use-after-free-when-c.patch +Patch1022: virtio-net-Ensure-queue-index-fits-with-RSS-CVE-2024.patch +Patch1023: vdpa-block-device-capacity-expansion-online.patch +Patch1024: tests-test-qga-close-socket-on-failure-to-connect.patch +Patch1025: tests-unit-add-NULL-pointer-check.patch +Patch1026: tests-mark-io-command-test-as-skipped-if-socat-is-mi.patch +Patch1027: tests-qtest-npcm7xx-emc-test-Skip-checking-MAC.patch +Patch1028: hw-microblaze-pass-random-seed-to-fdt.patch +Patch1029: target-arm-Fix-alignment-for-VLD4.32.patch +Patch1030: hw-net-lan9118-Signal-TSFL_INT-flag-when-TX-FIFO-rea.patch +Patch1031: qtest-fuzz-lsi53c895a-test-set-guest-RAM-to-2G.patch +Patch1032: target-i386-Introduce-SapphireRapids-v3-to-add-missi.patch BuildRequires: flex BuildRequires: gcc @@ -1603,6 +1642,47 @@ getent passwd qemu >/dev/null || \ %endif %changelog +* Wed Sep 18 2024 - 10:6.2.0-99 +- target/i386: Introduce SapphireRapids-v3 to add missing features +- qtest/fuzz-lsi53c895a-test: set guest RAM to 2G +- hw/net/lan9118: Signal TSFL_INT flag when TX FIFO reaches specified level +- target/arm: Fix alignment for VLD4.32 +- hw/microblaze: pass random seed to fdt +- tests/qtest: npcm7xx-emc-test: Skip checking MAC +- tests: mark io-command test as skipped if socat is missing +- tests: unit: add NULL-pointer check +- tests: test-qga: close socket on failure to connect +- vdpa:block device capacity expansion online support vdpa block device update capacity. +- virtio-net: Ensure queue index fits with RSS(CVE-2024-6505) +- nbd/server: CVE-2024-7409: Avoid use-after-free when closing server +- ppc/vof: Fix unaligned FDT property access +- vvfat: Fix reading files with non-continuous clusters +- vvfat: Fix bug in writing to middle of file +- savevm: Fix load_snapshot error path crash +- hw/dma/xilinx_axidma: Use semicolon at end of statement, not comma +- hw/remote/message.c: Don't directly invoke DeviceClass:reset +- crypto/tlscredspsk: Free username on finalize +- hw/display/vhost-user-gpu.c: fix vhost_user_gpu_chr_read() +- virtio: remove virtio_tswap16s() call in vring_packed_event_read() +- char-stdio: Restore blocking mode of stdout on exit +- hw/ppc: spapr: Use qemu_vfree() to free spapr->htab +- smbios: sanitize type from external type before checking have_fields_bitmap +- spapr_pci: fix leak in spapr_phb_vfio_get_loc_code +- KVM: use store-release to mark dirty pages as harvested +- monitor/hmp: print trace as option in help for log command +- tpm_crb: Avoid backend startup just before shutdown under Xen +- crypto/block-luks: make range overlap check more readable +- spapr: Free stdout path +- target/rx: Use target_ulong for address in LI +- virtio-pci: Fix the use of an uninitialized irqfd +- rtl8139: Fix behaviour for old kernels. +- virtio-rng: block max-bytes=0 MIME-Version: 1.0 +- hw/audio/es1370: Clean up comment +- vhost-user-server: do not set memory fd non-blocking +- ui: reject extended clipboard message if not activated +- virtio-net: Fix vhost virtqueue notifiers for RSS +- hw/misc/applesmc: Fix memory leak in reset() handler + * Wed Aug 21 2024 - 10:6.2.0-98 - pci-host: designware: Limit value range of iATU viewport register - hmat acpi: Fix out of bounds access due to missing use of indirection diff --git a/qtest-fuzz-lsi53c895a-test-set-guest-RAM-to-2G.patch b/qtest-fuzz-lsi53c895a-test-set-guest-RAM-to-2G.patch new file mode 100644 index 00000000..006e46d7 --- /dev/null +++ b/qtest-fuzz-lsi53c895a-test-set-guest-RAM-to-2G.patch @@ -0,0 +1,43 @@ +From c113a6e7135eb5f3676c59f733dd109a8be95b44 Mon Sep 17 00:00:00 2001 +From: tangbinzy +Date: Tue, 10 Sep 2024 11:48:29 +0000 +Subject: [PATCH] qtest/fuzz-lsi53c895a-test: set guest RAM to 2G mainline + inclusion commit a772ddc1c013c3ff54cd6bc5f1e4a9107093fc01 category: bugfix +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +--------------------------------------------------------------- + +test_lsi_do_msgout_cancel_req does not run on machines with small size +memory. Reduce guest memory from 4G to 2G to alleviate the problem. + +Reported-by: Bin Meng +Signed-off-by: Mauro Matteo Cascella +Message-Id: <20220902133853.834065-1-mcascell@redhat.com> +Reviewed-by: Philippe Mathieu-Daudé +Tested-by: Bin Meng +Reviewed-by: Alexander Bulekov +Signed-off-by: Thomas Huth + +Signed-off-by: tangbinzy +--- + tests/qtest/fuzz-lsi53c895a-test.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tests/qtest/fuzz-lsi53c895a-test.c b/tests/qtest/fuzz-lsi53c895a-test.c +index 9c50958796..bd18e8622e 100644 +--- a/tests/qtest/fuzz-lsi53c895a-test.c ++++ b/tests/qtest/fuzz-lsi53c895a-test.c +@@ -51,7 +51,7 @@ static void test_lsi_do_msgout_cancel_req(void) + return; + } + +- s = qtest_init("-M q35 -m 4G -display none -nodefaults " ++ s = qtest_init("-M q35 -m 2G -display none -nodefaults " + "-device lsi53c895a,id=scsi " + "-device scsi-hd,drive=disk0 " + "-drive file=null-co://,id=disk0,if=none,format=raw"); +-- +2.41.0.windows.1 + diff --git a/rtl8139-Fix-behaviour-for-old-kernels.patch b/rtl8139-Fix-behaviour-for-old-kernels.patch new file mode 100644 index 00000000..a59e96fe --- /dev/null +++ b/rtl8139-Fix-behaviour-for-old-kernels.patch @@ -0,0 +1,35 @@ +From b5bcfc82399f2651e8370fe25e07104327ed5ae4 Mon Sep 17 00:00:00 2001 +From: dinglimin +Date: Mon, 26 Aug 2024 18:27:47 +0800 +Subject: [PATCH] rtl8139: Fix behaviour for old kernels. + +Old linux kernel rtl8139 drivers (ex. debian 2.1) uses outb to set the rx +mode for RxConfig. Unfortunatelly qemu does not support outb for RxConfig. + +Signed-off-by: Hans +Signed-off-by: Jason Wang +Signed-off-by: dinglimin +--- + hw/net/rtl8139.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/hw/net/rtl8139.c b/hw/net/rtl8139.c +index 8af396cf06..7bcc05e2a5 100644 +--- a/hw/net/rtl8139.c ++++ b/hw/net/rtl8139.c +@@ -2746,7 +2746,11 @@ static void rtl8139_io_writeb(void *opaque, uint8_t addr, uint32_t val) + } + + break; +- ++ case RxConfig: ++ DPRINTF("RxConfig write(b) val=0x%02x\n", val); ++ rtl8139_RxConfig_write(s, ++ (rtl8139_RxConfig_read(s) & 0xFFFFFF00) | val); ++ break; + default: + DPRINTF("not implemented write(b) addr=0x%x val=0x%02x\n", addr, + val); +-- +2.41.0.windows.1 + diff --git a/savevm-Fix-load_snapshot-error-path-crash.patch b/savevm-Fix-load_snapshot-error-path-crash.patch new file mode 100644 index 00000000..22033f73 --- /dev/null +++ b/savevm-Fix-load_snapshot-error-path-crash.patch @@ -0,0 +1,36 @@ +From 9c5278b1cb8c4f524f519e4f54332c5333a8e4a2 Mon Sep 17 00:00:00 2001 +From: zhujun2 +Date: Thu, 5 Sep 2024 04:13:36 -0700 +Subject: [PATCH] savevm: Fix load_snapshot error path crash +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +An error path missed setting *errp, which can cause a NULL deref. + +Reviewed-by: Alex Bennée +Signed-off-by: Nicholas Piggin +Message-Id: <20240813050638.446172-11-npiggin@gmail.com> +Signed-off-by: Alex Bennée +Message-Id: <20240813202329.1237572-19-alex.bennee@linaro.org> +(cherry picked from commit 97d2b66dcd8c771065807b4acfd0002dac4385be) +Signed-off-by: zhujun2 +--- + migration/savevm.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/migration/savevm.c b/migration/savevm.c +index d59e976d50..b501504bd5 100644 +--- a/migration/savevm.c ++++ b/migration/savevm.c +@@ -3022,6 +3022,7 @@ bool load_snapshot(const char *name, const char *vmstate, + ret = bdrv_snapshot_find(bs_vm_state, &sn, name); + aio_context_release(aio_context); + if (ret < 0) { ++ error_setg(errp, "Snapshot can not be found"); + return false; + } else if (sn.vm_state_size == 0) { + error_setg(errp, "This is a disk-only snapshot. Revert to it " +-- +2.41.0.windows.1 + diff --git a/smbios-sanitize-type-from-external-type-before-check.patch b/smbios-sanitize-type-from-external-type-before-check.patch new file mode 100644 index 00000000..f9ce5f02 --- /dev/null +++ b/smbios-sanitize-type-from-external-type-before-check.patch @@ -0,0 +1,51 @@ +From 27179c493623b7758aead29955e96a6c52248502 Mon Sep 17 00:00:00 2001 +From: tangbinzy +Date: Wed, 4 Sep 2024 07:56:16 +0000 +Subject: [PATCH] smbios: sanitize type from external type before checking + have_fields_bitmap mainline inclusion commit + 57e3069641d057a9ca90bb603c86477d5b331ecd category: bugfix + +--------------------------------------------------------------- + +test_bit uses header->type as an offset; if the file incorrectly specifies a +type greater than 127, smbios_entry_add will read and write garbage. + +To fix this, just pass the smbios data through, assuming the user knows what +to do. Reported by Coverity as CID 1487255. + +Signed-off-by: Paolo Bonzini + +Signed-off-by: tangbinzy +--- + hw/smbios/smbios.c | 14 ++++++++------ + 1 file changed, 8 insertions(+), 6 deletions(-) + +diff --git a/hw/smbios/smbios.c b/hw/smbios/smbios.c +index f73b9417c8..d506fd4e7e 100644 +--- a/hw/smbios/smbios.c ++++ b/hw/smbios/smbios.c +@@ -1171,13 +1171,15 @@ void smbios_entry_add(QemuOpts *opts, Error **errp) + return; + } + +- if (test_bit(header->type, have_fields_bitmap)) { +- error_setg(errp, +- "can't load type %d struct, fields already specified!", +- header->type); +- return; ++ if (header->type <= SMBIOS_MAX_TYPE) { ++ if (test_bit(header->type, have_fields_bitmap)) { ++ error_setg(errp, ++ "can't load type %d struct, fields already specified!", ++ header->type); ++ return; ++ } ++ set_bit(header->type, have_binfile_bitmap); + } +- set_bit(header->type, have_binfile_bitmap); + + if (header->type == 4) { + smbios_type4_count++; +-- +2.41.0.windows.1 + diff --git a/spapr-Free-stdout-path.patch b/spapr-Free-stdout-path.patch new file mode 100644 index 00000000..aa82540c --- /dev/null +++ b/spapr-Free-stdout-path.patch @@ -0,0 +1,30 @@ +From 3dd770cfc6a59b45c3a960177f36e57612cf8818 Mon Sep 17 00:00:00 2001 +From: dinglimin +Date: Mon, 2 Sep 2024 16:47:04 +0800 +Subject: [PATCH] spapr: Free stdout path + +cheery-pick from 8af863f2bd976b937f7e3d38b2ab1813b2fa1d9d + +This fixes LeakSanitizer warnings. + +Signed-off-by: dinglimin +--- + hw/ppc/spapr_vof.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/hw/ppc/spapr_vof.c b/hw/ppc/spapr_vof.c +index 40ce8fe003..e437cab642 100644 +--- a/hw/ppc/spapr_vof.c ++++ b/hw/ppc/spapr_vof.c +@@ -29,7 +29,7 @@ target_ulong spapr_h_vof_client(PowerPCCPU *cpu, SpaprMachineState *spapr, + + void spapr_vof_client_dt_finalize(SpaprMachineState *spapr, void *fdt) + { +- char *stdout_path = spapr_vio_stdout_path(spapr->vio_bus); ++ g_autofree char *stdout_path = spapr_vio_stdout_path(spapr->vio_bus); + + vof_build_dt(fdt, spapr->vof); + +-- +2.41.0.windows.1 + diff --git a/spapr_pci-fix-leak-in-spapr_phb_vfio_get_loc_code.patch b/spapr_pci-fix-leak-in-spapr_phb_vfio_get_loc_code.patch new file mode 100644 index 00000000..4a0ae637 --- /dev/null +++ b/spapr_pci-fix-leak-in-spapr_phb_vfio_get_loc_code.patch @@ -0,0 +1,35 @@ +From 401dbfbce0b9acbc59f953d80461781afca4b0f7 Mon Sep 17 00:00:00 2001 +From: tangbinzy +Date: Wed, 4 Sep 2024 06:53:37 +0000 +Subject: [PATCH] spapr_pci: fix leak in spapr_phb_vfio_get_loc_code mainline + inclusion commit c4ef328bdc5dac319c8a1bdbe6d4108382b41584 category: bugfix + +--------------------------------------------------------------- + +Overwriting "path" in the second call to g_strdup_printf() causes a memory leak, +even if the variable itself is g_autofree. + +Reported by Coverity as CID 1460454. + +Signed-off-by: Paolo Bonzini + +Signed-off-by: tangbinzy +--- + hw/ppc/spapr_pci.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c +index 3b518f1be9..567bc8481c 100644 +--- a/hw/ppc/spapr_pci.c ++++ b/hw/ppc/spapr_pci.c +@@ -800,6 +800,7 @@ static char *spapr_phb_vfio_get_loc_code(SpaprPhbState *sphb, PCIDevice *pdev) + } + + /* Construct and read from host device tree the loc-code */ ++ g_free(path); + path = g_strdup_printf("/proc/device-tree%s/ibm,loc-code", devspec); + if (!g_file_get_contents(path, &buf, NULL, NULL)) { + return NULL; +-- +2.41.0.windows.1 + diff --git a/target-arm-Fix-alignment-for-VLD4.32.patch b/target-arm-Fix-alignment-for-VLD4.32.patch new file mode 100644 index 00000000..a0ca8c6b --- /dev/null +++ b/target-arm-Fix-alignment-for-VLD4.32.patch @@ -0,0 +1,50 @@ +From 6a071b8797f06850073b3a095a622117e554f302 Mon Sep 17 00:00:00 2001 +From: tangbinzy +Date: Mon, 9 Sep 2024 08:29:05 +0000 +Subject: [PATCH] target/arm: Fix alignment for VLD4.32 mainline inclusion + commit 3a661024cc680104ce2cd21f8f5466dacba6f405 category: bugfix +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +--------------------------------------------------------------- + +When requested, the alignment for VLD4.32 is 8 and not 16. + +See ARM documentation about VLD4 encoding: + ebytes = 1 << UInt(size); + if size == '10' then + alignment = if a == '0' then 1 else 8; + else + alignment = if a == '0' then 1 else 4*ebytes; + +Signed-off-by: Clément Chigot +Reviewed-by: Richard Henderson +Message-id: 20220914105058.2787404-1-chigot@adacore.com +Signed-off-by: Peter Maydell + +Signed-off-by: tangbinzy +--- + target/arm/translate-neon.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/target/arm/translate-neon.c b/target/arm/translate-neon.c +index dd43de558e..761fd6a755 100644 +--- a/target/arm/translate-neon.c ++++ b/target/arm/translate-neon.c +@@ -586,7 +586,11 @@ static bool trans_VLD_all_lanes(DisasContext *s, arg_VLD_all_lanes *a) + case 3: + return false; + case 4: +- align = pow2_align(size + 2); ++ if (size == 2) { ++ align = pow2_align(3); ++ } else { ++ align = pow2_align(size + 2); ++ } + break; + default: + g_assert_not_reached(); +-- +2.41.0.windows.1 + diff --git a/target-i386-Introduce-SapphireRapids-v3-to-add-missi.patch b/target-i386-Introduce-SapphireRapids-v3-to-add-missi.patch new file mode 100644 index 00000000..ef505244 --- /dev/null +++ b/target-i386-Introduce-SapphireRapids-v3-to-add-missi.patch @@ -0,0 +1,48 @@ +From 147ca6c521c4b59a5dd610e3a2bcd9553901ba6a Mon Sep 17 00:00:00 2001 +From: Lei Wang +Date: Wed, 24 Apr 2024 03:29:12 -0400 +Subject: [PATCH] target/i386: Introduce SapphireRapids-v3 to add missing + features + +commit b10b2481738304db13d28252e86c10555121a5b3 upstream. + +Add the missing features(ss, tsc-adjust, cldemote, movdiri, movdir64b) in +the SapphireRapids-v3 CPU model. + +Intel-SIG: commit b10b24817383 target/i386: Introduce SapphireRapids-v3 to add missing features. +6.2-SPR new model support + +Signed-off-by: Lei Wang +Message-ID: <20240424072912.43188-1-lei4.wang@intel.com> +Signed-off-by: Paolo Bonzini +[ Quanxian Wang: amend commit log ] +Signed-off-by: Quanxian Wang +--- + target/i386/cpu.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index 4c8453e0df..4473e0923e 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -3754,6 +3754,17 @@ static const X86CPUDefinition builtin_x86_defs[] = { + { /* end of list */ } + } + }, ++ { ++ .version = 3, ++ .props = (PropValue[]) { ++ { "ss", "on" }, ++ { "tsc-adjust", "on" }, ++ { "cldemote", "on" }, ++ { "movdiri", "on" }, ++ { "movdir64b", "on" }, ++ { /* end of list */ } ++ } ++ }, + { /* end of list */ } + } + }, +-- +2.41.0.windows.1 + diff --git a/target-rx-Use-target_ulong-for-address-in-LI.patch b/target-rx-Use-target_ulong-for-address-in-LI.patch new file mode 100644 index 00000000..d1aa0f0b --- /dev/null +++ b/target-rx-Use-target_ulong-for-address-in-LI.patch @@ -0,0 +1,35 @@ +From 3d5808bb00ec5cf2f2e78aa570a202af2ed3e201 Mon Sep 17 00:00:00 2001 +From: dinglimin +Date: Mon, 2 Sep 2024 14:42:51 +0800 +Subject: [PATCH] target/rx: Use target_ulong for address in LI + +cheery-pick from 83340193b991e7a974f117baa86a04db1fd835a9 + +Using int32_t meant that the address was sign-extended to uint64_t +when passing to translator_ld*, triggering an assert. + +Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2453 +Signed-off-by: Richard Henderson +Tested-by: Thomas Huth +Signed-off-by: dinglimin +--- + target/rx/translate.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/target/rx/translate.c b/target/rx/translate.c +index 5db8f79a82..aacf59d5cb 100644 +--- a/target/rx/translate.c ++++ b/target/rx/translate.c +@@ -82,7 +82,8 @@ static uint32_t decode_load_bytes(DisasContext *ctx, uint32_t insn, + + static uint32_t li(DisasContext *ctx, int sz) + { +- int32_t tmp, addr; ++ target_ulong addr; ++ uint32_t tmp; + CPURXState *env = ctx->env; + addr = ctx->base.pc_next; + +-- +2.41.0.windows.1 + diff --git a/tests-mark-io-command-test-as-skipped-if-socat-is-mi.patch b/tests-mark-io-command-test-as-skipped-if-socat-is-mi.patch new file mode 100644 index 00000000..f42a01f1 --- /dev/null +++ b/tests-mark-io-command-test-as-skipped-if-socat-is-mi.patch @@ -0,0 +1,39 @@ +From 62e1305aa46d91915aa987aca125db7f32845cd9 Mon Sep 17 00:00:00 2001 +From: tangbinzy +Date: Mon, 9 Sep 2024 07:57:18 +0000 +Subject: [PATCH] tests: mark io-command test as skipped if socat is missing + mainline inclusion commit 525207cd77adb181b4ef61d0b7669f52f737e9d0 category: + bugfix +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +--------------------------------------------------------------- + +Signed-off-by: Marc-André Lureau +Reviewed-by: Daniel P. Berrangé +Message-Id: <20220901110414.2892954-1-marcandre.lureau@redhat.com> +Signed-off-by: Thomas Huth + +Signed-off-by: tangbinzy +--- + tests/unit/test-io-channel-command.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/tests/unit/test-io-channel-command.c b/tests/unit/test-io-channel-command.c +index 99056e07c0..aa09c559cd 100644 +--- a/tests/unit/test-io-channel-command.c ++++ b/tests/unit/test-io-channel-command.c +@@ -41,7 +41,8 @@ static void test_io_channel_command_fifo(bool async) + + unlink(TEST_FIFO); + if (access("/bin/socat", X_OK) < 0) { +- return; /* Pretend success if socat is not present */ ++ g_test_skip("socat is missing"); ++ return; + } + if (mkfifo(TEST_FIFO, 0600) < 0) { + abort(); +-- +2.41.0.windows.1 + diff --git a/tests-qtest-npcm7xx-emc-test-Skip-checking-MAC.patch b/tests-qtest-npcm7xx-emc-test-Skip-checking-MAC.patch new file mode 100644 index 00000000..5ff86c91 --- /dev/null +++ b/tests-qtest-npcm7xx-emc-test-Skip-checking-MAC.patch @@ -0,0 +1,39 @@ +From 00edc3a590c95bce8c4fa96dd682edd533280c3e Mon Sep 17 00:00:00 2001 +From: tangbinzy +Date: Mon, 9 Sep 2024 08:15:19 +0000 +Subject: [PATCH] tests/qtest: npcm7xx-emc-test: Skip checking MAC mainline + inclusion commit d1592cbe07fa7b653aa9dde2eb8dafbe1de16885 category: bugfix + +--------------------------------------------------------------- + +The register tests walks all the registers to verify they are initially +0 when appropriate. However, if the MAC address is set in the register +space, this should not be checked against 0. + +Reviewed-by: Hao Wu +Signed-off-by: Patrick Venture +Message-Id: <20220906163138.2831353-1-venture@google.com> +Signed-off-by: Thomas Huth + +Signed-off-by: tangbinzy +--- + tests/qtest/npcm7xx_emc-test.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/tests/qtest/npcm7xx_emc-test.c b/tests/qtest/npcm7xx_emc-test.c +index 9eec71d87c..1bc1d821c5 100644 +--- a/tests/qtest/npcm7xx_emc-test.c ++++ b/tests/qtest/npcm7xx_emc-test.c +@@ -378,7 +378,8 @@ static void test_init(gconstpointer test_data) + + #undef CHECK_REG + +- for (i = 0; i < NUM_CAMML_REGS; ++i) { ++ /* Skip over the MAC address registers, which is BASE+0 */ ++ for (i = 1; i < NUM_CAMML_REGS; ++i) { + g_assert_cmpuint(emc_read(qts, mod, REG_CAMM_BASE + i * 2), ==, + 0); + g_assert_cmpuint(emc_read(qts, mod, REG_CAML_BASE + i * 2), ==, +-- +2.41.0.windows.1 + diff --git a/tests-test-qga-close-socket-on-failure-to-connect.patch b/tests-test-qga-close-socket-on-failure-to-connect.patch new file mode 100644 index 00000000..08809d38 --- /dev/null +++ b/tests-test-qga-close-socket-on-failure-to-connect.patch @@ -0,0 +1,32 @@ +From 18e9e427e2355afab0c17ffaa85d3120837e292c Mon Sep 17 00:00:00 2001 +From: tangbinzy +Date: Mon, 9 Sep 2024 07:41:17 +0000 +Subject: [PATCH] tests: test-qga: close socket on failure to connect mainline + inclusion commit 5dc51100394206b4ca3fdcafb008de8f99fc4676 category: bugfix + +--------------------------------------------------------------- + +Reported by Coverity as CID 1432543. + +Signed-off-by: Paolo Bonzini + +Signed-off-by: tangbinzy +--- + tests/unit/test-qga.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/tests/unit/test-qga.c b/tests/unit/test-qga.c +index 5cb140d1b5..e6564c673b 100644 +--- a/tests/unit/test-qga.c ++++ b/tests/unit/test-qga.c +@@ -32,6 +32,7 @@ static int connect_qga(char *path) + g_usleep(G_USEC_PER_SEC); + } + if (i++ == 10) { ++ close(s); + return -1; + } + } while (ret == -1); +-- +2.41.0.windows.1 + diff --git a/tests-unit-add-NULL-pointer-check.patch b/tests-unit-add-NULL-pointer-check.patch new file mode 100644 index 00000000..6f5973ff --- /dev/null +++ b/tests-unit-add-NULL-pointer-check.patch @@ -0,0 +1,39 @@ +From f2f914e1868a83ffef1580465988557df0257bc6 Mon Sep 17 00:00:00 2001 +From: tangbinzy +Date: Mon, 9 Sep 2024 07:54:12 +0000 +Subject: [PATCH] tests: unit: add NULL-pointer check mainline inclusion commit + b3a58a6ae346f14075af0df7f9903ad389c33dbd category: bugfix + +--------------------------------------------------------------- + +In CID 1432593, Coverity complains that the result of qdict_crumple() +might leak if it is not a dictionary. This is not a practical concern +since the test would fail immediately with a NULL pointer dereference +in qdict_size(). + +However, it is not nice to depend on qdict_size() crashing, so add an +explicit assertion that that the crumpled object was indeed a dictionary. + +Signed-off-by: Paolo Bonzini + +Signed-off-by: tangbinzy +--- + tests/unit/check-block-qdict.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tests/unit/check-block-qdict.c b/tests/unit/check-block-qdict.c +index 5a25825093..751c58e737 100644 +--- a/tests/unit/check-block-qdict.c ++++ b/tests/unit/check-block-qdict.c +@@ -504,7 +504,7 @@ static void qdict_crumple_test_empty(void) + src = qdict_new(); + + dst = qobject_to(QDict, qdict_crumple(src, &error_abort)); +- ++ g_assert(dst); + g_assert_cmpint(qdict_size(dst), ==, 0); + + qobject_unref(src); +-- +2.41.0.windows.1 + diff --git a/tpm_crb-Avoid-backend-startup-just-before-shutdown-u.patch b/tpm_crb-Avoid-backend-startup-just-before-shutdown-u.patch new file mode 100644 index 00000000..fca83907 --- /dev/null +++ b/tpm_crb-Avoid-backend-startup-just-before-shutdown-u.patch @@ -0,0 +1,58 @@ +From 5cafaebb7f31713b826a678e79eef976beb8caf6 Mon Sep 17 00:00:00 2001 +From: tangbinzy +Date: Tue, 3 Sep 2024 01:56:25 +0000 +Subject: [PATCH] tpm_crb: Avoid backend startup just before shutdown under Xen + mainline inclusion commit f0ccce6a95f6ff947040692ef941230918181562 category: + bugfix + +--------------------------------------------------------------- + +When running under Xen and the guest reboots, it boots into a new domain +with a new QEMU process (and a new swtpm process if using the emulator +backend). The existing reset function is triggered just before the old +QEMU process exists which causes QEMU to startup the TPM backend and +then immediately shut it down. This is probably harmless but when using +the emulated backend, it wastes CPU and IO time reloading state, etc. + +Fix this by calling the reset function directly from realize() when +running under Xen. During a reboot, this will be called by the QEMU +process for the new domain. + +Signed-off-by: Ross Lagerwall +Reviewed-by: Stefan Berger +Message-id: 20220826143841.1515326-1-ross.lagerwall@citrix.com +Signed-off-by: Stefan Berger + +Signed-off-by: tangbinzy +--- + hw/tpm/tpm_crb.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/hw/tpm/tpm_crb.c b/hw/tpm/tpm_crb.c +index c05972736a..ed89ab4afe 100644 +--- a/hw/tpm/tpm_crb.c ++++ b/hw/tpm/tpm_crb.c +@@ -25,6 +25,7 @@ + #include "sysemu/tpm_backend.h" + #include "sysemu/tpm_util.h" + #include "sysemu/reset.h" ++#include "sysemu/xen.h" + #include "tpm_prop.h" + #include "tpm_ppi.h" + #include "trace.h" +@@ -307,7 +308,11 @@ static void tpm_crb_realize(DeviceState *dev, Error **errp) + TPM_PPI_ADDR_BASE, OBJECT(s)); + } + +- qemu_register_reset(tpm_crb_reset, dev); ++ if (xen_enabled()) { ++ tpm_crb_reset(dev); ++ } else { ++ qemu_register_reset(tpm_crb_reset, dev); ++ } + } + + static void tpm_crb_class_init(ObjectClass *klass, void *data) +-- +2.41.0.windows.1 + diff --git a/ui-reject-extended-clipboard-message-if-not-activate.patch b/ui-reject-extended-clipboard-message-if-not-activate.patch new file mode 100644 index 00000000..c03b1920 --- /dev/null +++ b/ui-reject-extended-clipboard-message-if-not-activate.patch @@ -0,0 +1,41 @@ +From 5dc2ba3fa793407b1dd6ee1920808a729990abf7 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= +Date: Mon, 15 Jan 2024 09:51:19 +0000 +Subject: [PATCH] ui: reject extended clipboard message if not activated +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The extended clipboard message protocol requires that the client +activate the extension by requesting a psuedo encoding. If this +is not done, then any extended clipboard messages from the client +should be considered invalid and the client dropped. + +Signed-off-by: Daniel P. Berrangé +Reviewed-by: Marc-André Lureau +Message-Id: <20240115095119.654271-1-berrange@redhat.com> +(cherry picked from commit 4cba8388968b70fe20e290221dc421c717051fdd) +Signed-off-by: zhujun2 +--- + ui/vnc.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/ui/vnc.c b/ui/vnc.c +index 3cb24badf6..667db3b990 100644 +--- a/ui/vnc.c ++++ b/ui/vnc.c +@@ -2458,6 +2458,11 @@ static int protocol_client_msg(VncState *vs, uint8_t *data, size_t len) + } + + if (read_s32(data, 4) < 0) { ++ if (!vnc_has_feature(vs, VNC_FEATURE_CLIPBOARD_EXT)) { ++ error_report("vnc: extended clipboard message while disabled"); ++ vnc_client_error(vs); ++ break; ++ } + if (dlen < 4) { + error_report("vnc: malformed payload (header less than 4 bytes)" + " in extended clipboard pseudo-encoding."); +-- +2.41.0.windows.1 + diff --git a/vdpa-block-device-capacity-expansion-online.patch b/vdpa-block-device-capacity-expansion-online.patch new file mode 100644 index 00000000..c8e11c95 --- /dev/null +++ b/vdpa-block-device-capacity-expansion-online.patch @@ -0,0 +1,50 @@ +From cec9c300b0a2ede77fa12f242ee7fd672546940c Mon Sep 17 00:00:00 2001 +From: jiangdongxu +Date: Sat, 7 Sep 2024 07:11:07 +0000 +Subject: [PATCH] vdpa:block device capacity expansion online support vdpa + block device update capacity. + +Signed-off-by: jiangdongxu +--- + hw/virtio/vdpa-dev.c | 17 +++++++++++++++++ + 1 file changed, 17 insertions(+) + +diff --git a/hw/virtio/vdpa-dev.c b/hw/virtio/vdpa-dev.c +index 04d8e96a5d..fa3a4dc8bc 100644 +--- a/hw/virtio/vdpa-dev.c ++++ b/hw/virtio/vdpa-dev.c +@@ -32,6 +32,7 @@ + #include "hw/virtio/vdpa-dev-mig.h" + #include "migration/migration.h" + #include "exec/address-spaces.h" ++#include "standard-headers/linux/virtio_ids.h" + + static void + vhost_vdpa_device_dummy_handle_output(VirtIODevice *vdev, VirtQueue *vq) +@@ -202,7 +203,23 @@ static void + vhost_vdpa_device_get_config(VirtIODevice *vdev, uint8_t *config) + { + VhostVdpaDevice *s = VHOST_VDPA_DEVICE(vdev); ++ uint8_t *new_config; ++ int ret; ++ ++ if (s->vdev_id != VIRTIO_ID_BLOCK) { ++ goto out; ++ } + ++ new_config = g_malloc0(s->config_size); ++ ret = vhost_dev_get_config(&s->dev, new_config, s->config_size, NULL); ++ if (ret < 0) { ++ error_report("vhost-vdpa-device: get config failed(%d)\n", ret); ++ goto free; ++ } ++ memcpy(s->config, new_config, s->config_size); ++free: ++ g_free(new_config); ++out: + memcpy(config, s->config, s->config_size); + } + +-- +2.41.0.windows.1 + diff --git a/vhost-user-server-do-not-set-memory-fd-non-blocking.patch b/vhost-user-server-do-not-set-memory-fd-non-blocking.patch new file mode 100644 index 00000000..f53912b3 --- /dev/null +++ b/vhost-user-server-do-not-set-memory-fd-non-blocking.patch @@ -0,0 +1,59 @@ +From 4b38d60e4a4a1fc4b7191ec94959f304b222b604 Mon Sep 17 00:00:00 2001 +From: zhujun2 +Date: Thu, 15 Aug 2024 20:20:35 -0700 +Subject: [PATCH] vhost-user-server: do not set memory fd non-blocking +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +In vhost-user-server we set all fd received from the other peer +in non-blocking mode. For some of them (e.g. memfd, shm_open, etc.) +it's not really needed, because we don't use these fd with blocking +operations, but only to map memory. + +In addition, in some systems this operation can fail (e.g. in macOS +setting an fd returned by shm_open() non-blocking fails with errno += ENOTTY). + +So, let's avoid setting fd non-blocking for those messages that we +know carry memory fd (e.g. VHOST_USER_ADD_MEM_REG, +VHOST_USER_SET_MEM_TABLE). + +Reviewed-by: Daniel P. Berrangé +Acked-by: Stefan Hajnoczi +Reviewed-by: David Hildenbrand +Signed-off-by: Stefano Garzarella +Message-Id: <20240618100043.144657-6-sgarzare@redhat.com> +Signed-off-by: Michael S. Tsirkin +(cherry picked from commit 4c58843e5d3192c67394b28a3330144ea56eefac) +Signed-off-by: zhujun2 +--- + util/vhost-user-server.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/util/vhost-user-server.c b/util/vhost-user-server.c +index 783d847a6d..eda82447bd 100644 +--- a/util/vhost-user-server.c ++++ b/util/vhost-user-server.c +@@ -64,6 +64,18 @@ static void vmsg_close_fds(VhostUserMsg *vmsg) + static void vmsg_unblock_fds(VhostUserMsg *vmsg) + { + int i; ++ ++ /* ++ * These messages carry fd used to map memory, not to send/receive messages, ++ * so this operation is useless. In addition, in some systems this ++ * operation can fail (e.g. in macOS setting an fd returned by shm_open() ++ * non-blocking fails with errno = ENOTTY) ++ */ ++ if (vmsg->request == VHOST_USER_ADD_MEM_REG || ++ vmsg->request == VHOST_USER_SET_MEM_TABLE) { ++ return; ++ } ++ + for (i = 0; i < vmsg->fd_num; i++) { + qemu_set_nonblock(vmsg->fds[i]); + } +-- +2.41.0.windows.1 + diff --git a/virtio-net-Ensure-queue-index-fits-with-RSS-CVE-2024.patch b/virtio-net-Ensure-queue-index-fits-with-RSS-CVE-2024.patch new file mode 100644 index 00000000..e01933a3 --- /dev/null +++ b/virtio-net-Ensure-queue-index-fits-with-RSS-CVE-2024.patch @@ -0,0 +1,36 @@ +From 8cd5679908e7af9353c8c4e9198aef2fbb3256ec Mon Sep 17 00:00:00 2001 +From: Akihiko Odaki +Date: Mon, 1 Jul 2024 20:58:04 +0900 +Subject: [PATCH] virtio-net: Ensure queue index fits with RSS(CVE-2024-6505) + +Ensure the queue index points to a valid queue when software RSS +enabled. The new calculation matches with the behavior of Linux's TAP +device with the RSS eBPF program. + +Fixes: 4474e37a5b3a ("virtio-net: implement RX RSS processing") +Reported-by: Zhibin Hu +Cc: qemu-stable@nongnu.org +Signed-off-by: Akihiko Odaki +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Jason Wang +--- + hw/net/virtio-net.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c +index f7248fc2e2..cef7fc0aa0 100644 +--- a/hw/net/virtio-net.c ++++ b/hw/net/virtio-net.c +@@ -1818,7 +1818,8 @@ static ssize_t virtio_net_receive_rcu(NetClientState *nc, const uint8_t *buf, + if (!no_rss && n->rss_data.enabled && n->rss_data.enabled_software_rss) { + int index = virtio_net_process_rss(nc, buf, size); + if (index >= 0) { +- NetClientState *nc2 = qemu_get_subqueue(n->nic, index); ++ NetClientState *nc2 = ++ qemu_get_subqueue(n->nic, index % n->curr_queue_pairs); + return virtio_net_receive_rcu(nc2, buf, size, true); + } + } +-- +2.41.0.windows.1 + diff --git a/virtio-net-Fix-vhost-virtqueue-notifiers-for-RSS.patch b/virtio-net-Fix-vhost-virtqueue-notifiers-for-RSS.patch new file mode 100644 index 00000000..03387fd2 --- /dev/null +++ b/virtio-net-Fix-vhost-virtqueue-notifiers-for-RSS.patch @@ -0,0 +1,45 @@ +From 24140cab0cc08a239c6df320c6da59b8ce638055 Mon Sep 17 00:00:00 2001 +From: Akihiko Odaki +Date: Wed, 27 Mar 2024 11:05:09 +0900 +Subject: [PATCH] virtio-net: Fix vhost virtqueue notifiers for RSS + +virtio_net_guest_notifier_pending() and virtio_net_guest_notifier_mask() +checked VIRTIO_NET_F_MQ to know there are multiple queues, but +VIRTIO_NET_F_RSS also enables multiple queues. Refer to n->multiqueue, +which is set to true either of VIRTIO_NET_F_MQ or VIRTIO_NET_F_RSS is +enabled. + +Fixes: 68b0a6395f36 ("virtio-net: align ctrl_vq index for non-mq guest for vhost_vdpa") +Signed-off-by: Akihiko Odaki +Signed-off-by: Jason Wang +(cherry picked from commit 1c188fc8cbffc5f05cc616cab4e1372fb6e6f11f) +Signed-off-by: zhujun2 +--- + hw/net/virtio-net.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c +index f3fb9393b3..f72fe61dda 100644 +--- a/hw/net/virtio-net.c ++++ b/hw/net/virtio-net.c +@@ -3239,7 +3239,7 @@ static bool virtio_net_guest_notifier_pending(VirtIODevice *vdev, int idx) + VirtIONet *n = VIRTIO_NET(vdev); + NetClientState *nc; + assert(n->vhost_started); +- if (!virtio_vdev_has_feature(vdev, VIRTIO_NET_F_MQ) && idx == 2) { ++ if (!n->multiqueue && idx == 2) { + /* Must guard against invalid features and bogus queue index + * from being set by malicious guest, or penetrated through + * buggy migration stream. +@@ -3271,7 +3271,7 @@ static void virtio_net_guest_notifier_mask(VirtIODevice *vdev, int idx, + VirtIONet *n = VIRTIO_NET(vdev); + NetClientState *nc; + assert(n->vhost_started); +- if (!virtio_vdev_has_feature(vdev, VIRTIO_NET_F_MQ) && idx == 2) { ++ if (!n->multiqueue && idx == 2) { + /* Must guard against invalid features and bogus queue index + * from being set by malicious guest, or penetrated through + * buggy migration stream. +-- +2.41.0.windows.1 + diff --git a/virtio-pci-Fix-the-use-of-an-uninitialized-irqfd.patch b/virtio-pci-Fix-the-use-of-an-uninitialized-irqfd.patch new file mode 100644 index 00000000..2acebaa0 --- /dev/null +++ b/virtio-pci-Fix-the-use-of-an-uninitialized-irqfd.patch @@ -0,0 +1,83 @@ +From f57991f3f88e281d3c9bcf7c1d1e2b15651c6262 Mon Sep 17 00:00:00 2001 +From: guping +Date: Mon, 2 Sep 2024 09:29:45 +0000 +Subject: [PATCH] virtio-pci: Fix the use of an uninitialized irqfd chery-pick + from a8e63ff289d137197ad7a701a587cc432872d798 + +The crash was reported in MAC OS and NixOS, here is the link for this bug +#2334 +#2321 + +In this bug, they are using the virtio_input device. The guest notifier was +not supported for this device, The function virtio_pci_set_guest_notifiers() +was not called, and the vector_irqfd was not initialized. + +So the fix is adding the check for vector_irqfd in virtio_pci_get_notifier() + +The function virtio_pci_get_notifier() can be used in various devices. +It could also be called when VIRTIO_CONFIG_S_DRIVER_OK is not set. In this situation, +the vector_irqfd being NULL is acceptable. We can allow the device continue to boot + +If the vector_irqfd still hasn't been initialized after VIRTIO_CONFIG_S_DRIVER_OK +is set, it means that the function set_guest_notifiers was not called before the +driver started. This indicates that the device is not using the notifier. +At this point, we will let the check fail. + +This fix is verified in vyatta,MacOS,NixOS,fedora system. + +The bt tree for this bug is: +Thread 6 "CPU 0/KVM" received signal SIGSEGV, Segmentation fault. +[Switching to Thread 0x7c817be006c0 (LWP 1269146)] +kvm_virtio_pci_vq_vector_use () at ../qemu-9.0.0/hw/virtio/virtio-pci.c:817 +817 if (irqfd->users == 0) { +(gdb) thread apply all bt +... +Thread 6 (Thread 0x7c817be006c0 (LWP 1269146) "CPU 0/KVM"): +0 kvm_virtio_pci_vq_vector_use () at ../qemu-9.0.0/hw/virtio/virtio-pci.c:817 +1 kvm_virtio_pci_vector_use_one () at ../qemu-9.0.0/hw/virtio/virtio-pci.c:893 +2 0x00005983657045e2 in memory_region_write_accessor () at ../qemu-9.0.0/system/memory.c:497 +3 0x0000598365704ba6 in access_with_adjusted_size () at ../qemu-9.0.0/system/memory.c:573 +4 0x0000598365705059 in memory_region_dispatch_write () at ../qemu-9.0.0/system/memory.c:1528 +5 0x00005983659b8e1f in flatview_write_continue_step.isra.0 () at ../qemu-9.0.0/system/physmem.c:2713 +6 0x000059836570ba7d in flatview_write_continue () at ../qemu-9.0.0/system/physmem.c:2743 +7 flatview_write () at ../qemu-9.0.0/system/physmem.c:2774 +8 0x000059836570bb76 in address_space_write () at ../qemu-9.0.0/system/physmem.c:2894 +9 0x0000598365763afe in address_space_rw () at ../qemu-9.0.0/system/physmem.c:2904 +10 kvm_cpu_exec () at ../qemu-9.0.0/accel/kvm/kvm-all.c:2917 +11 0x000059836576656e in kvm_vcpu_thread_fn () at ../qemu-9.0.0/accel/kvm/kvm-accel-ops.c:50 +12 0x0000598365926ca8 in qemu_thread_start () at ../qemu-9.0.0/util/qemu-thread-posix.c:541 +13 0x00007c8185bcd1cf in ??? () at /usr/lib/libc.so.6 +14 0x00007c8185c4e504 in clone () at /usr/lib/libc.so.6 + +Fixes: 2ce6cff9 + + ("virtio-pci: fix use of a released vector") +Cc: qemu-stable@nongnu.org +Signed-off-by: Cindy Lu's avatarCindy Lu +Message-Id: <20240806093715.65105-1-lulu@redhat.com> +Acked-by: Jason Wang's avatarJason Wang +Reviewed-by: MST's avatarMichael S. Tsirkin +Signed-off-by: MST's avatarMichael S. Tsirkin + +Signed-off-by: guping +--- + hw/virtio/virtio-pci.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c +index d675526016..1e4661bebd 100644 +--- a/hw/virtio/virtio-pci.c ++++ b/hw/virtio/virtio-pci.c +@@ -811,6 +811,9 @@ static int virtio_pci_get_notifier(VirtIOPCIProxy *proxy, int queue_no, + VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); + VirtQueue *vq; + ++ if (!proxy->vector_irqfd && vdev->status & VIRTIO_CONFIG_S_DRIVER_OK) ++ return -1; ++ + if (queue_no == VIRTIO_CONFIG_IRQ_IDX) { + *n = virtio_config_get_guest_notifier(vdev); + *vector = vdev->config_vector; +-- +2.41.0.windows.1 + diff --git a/virtio-remove-virtio_tswap16s-call-in-vring_packed_e.patch b/virtio-remove-virtio_tswap16s-call-in-vring_packed_e.patch new file mode 100644 index 00000000..4f789bd1 --- /dev/null +++ b/virtio-remove-virtio_tswap16s-call-in-vring_packed_e.patch @@ -0,0 +1,52 @@ +From f91ab1b5dc0a3b9713472a0f0762b189c33334d0 Mon Sep 17 00:00:00 2001 +From: Stefano Garzarella +Date: Mon, 1 Jul 2024 09:52:08 +0200 +Subject: [PATCH] virtio: remove virtio_tswap16s() call in + vring_packed_event_read() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Commit d152cdd6f6 ("virtio: use virtio accessor to access packed event") +switched using of address_space_read_cached() to virito_lduw_phys_cached() +to access packed descriptor event. + +When we used address_space_read_cached(), we needed to call +virtio_tswap16s() to handle the endianess of the field, but +virito_lduw_phys_cached() already handles it internally, so we no longer +need to call virtio_tswap16s() (as the commit had done for `off_wrap`, +but forgot for `flags`). + +Fixes: d152cdd6f6 ("virtio: use virtio accessor to access packed event") +Cc: jasowang@redhat.com +Cc: qemu-stable@nongnu.org +Reported-by: Xoykie +Link: https://lore.kernel.org/qemu-devel/CAFU8RB_pjr77zMLsM0Unf9xPNxfr_--Tjr49F_eX32ZBc5o2zQ@mail.gmail.com +Signed-off-by: Stefano Garzarella +Message-Id: <20240701075208.19634-1-sgarzare@redhat.com> +Acked-by: Jason Wang +Reviewed-by: Peter Maydell +Reviewed-by: Eugenio Pérez +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +(cherry picked from commit 7aa6492401e95fb296dec7cda81e67d91f6037d7) +Signed-off-by: zhujun2 +--- + hw/virtio/virtio.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c +index 913b40e1f8..9c40d565bb 100644 +--- a/hw/virtio/virtio.c ++++ b/hw/virtio/virtio.c +@@ -251,7 +251,6 @@ static void vring_packed_event_read(VirtIODevice *vdev, + /* Make sure flags is seen before off_wrap */ + smp_rmb(); + e->off_wrap = virtio_lduw_phys_cached(vdev, cache, off_off); +- virtio_tswap16s(vdev, &e->flags); + } + + static void vring_packed_off_wrap_write(VirtIODevice *vdev, +-- +2.41.0.windows.1 + diff --git a/virtio-rng-block-max-bytes-0-MIME-Version-1.0.patch b/virtio-rng-block-max-bytes-0-MIME-Version-1.0.patch new file mode 100644 index 00000000..46842832 --- /dev/null +++ b/virtio-rng-block-max-bytes-0-MIME-Version-1.0.patch @@ -0,0 +1,40 @@ +From 38b34a054490d7dd8a3ed6ee313c1ee501363688 Mon Sep 17 00:00:00 2001 +From: dinglimin +Date: Mon, 26 Aug 2024 15:27:20 +0800 +Subject: [PATCH] virtio-rng: block max-bytes=0 MIME-Version: 1.0 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +cheery-pick from 024d046bf41b5256adec671085bcee767a6da125 + +with max-bytes set to 0, quota is 0 and so device does not work. +block this to avoid user confusion + +Message-Id: <73a89a42d82ec8b47358f25119b87063e4a6ea57.1721818306.git.mst@redhat.com> +Signed-off-by: Michael S. Tsirkin +Reviewed-by: Philippe Mathieu-Daudé +Signed-off-by: dinglimin +--- + hw/virtio/virtio-rng.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/hw/virtio/virtio-rng.c b/hw/virtio/virtio-rng.c +index cc8e9f775d..e0f71ddd0f 100644 +--- a/hw/virtio/virtio-rng.c ++++ b/hw/virtio/virtio-rng.c +@@ -184,8 +184,9 @@ static void virtio_rng_device_realize(DeviceState *dev, Error **errp) + + /* Workaround: Property parsing does not enforce unsigned integers, + * So this is a hack to reject such numbers. */ +- if (vrng->conf.max_bytes > INT64_MAX) { +- error_setg(errp, "'max-bytes' parameter must be non-negative, " ++ if (vrng->conf.max_bytes == 0 || ++ vrng->conf.max_bytes > INT64_MAX) { ++ error_setg(errp, "'max-bytes' parameter must be positive, " + "and less than 2^63"); + return; + } +-- +2.41.0.windows.1 + diff --git a/vvfat-Fix-bug-in-writing-to-middle-of-file.patch b/vvfat-Fix-bug-in-writing-to-middle-of-file.patch new file mode 100644 index 00000000..9ccc412b --- /dev/null +++ b/vvfat-Fix-bug-in-writing-to-middle-of-file.patch @@ -0,0 +1,42 @@ +From f0f408c65fc606cb5a4dfce2f5b051519820d967 Mon Sep 17 00:00:00 2001 +From: Amjad Alsharafi +Date: Sat, 20 Jul 2024 18:13:30 +0800 +Subject: [PATCH] vvfat: Fix bug in writing to middle of file + +Before this commit, the behavior when calling `commit_one_file` for +example with `offset=0x2000` (second cluster), what will happen is that +we won't fetch the next cluster from the fat, and instead use the first +cluster for the read operation. + +This is due to off-by-one error here, where `i=0x2000 !< offset=0x2000`, +thus not fetching the next cluster. + +Signed-off-by: Amjad Alsharafi +Reviewed-by: Kevin Wolf +Tested-by: Kevin Wolf +Message-ID: +Signed-off-by: Kevin Wolf +(cherry picked from commit b881cf00c99e03bc8a3648581f97736ff275b18b) +Signed-off-by: zhujun2 +--- + block/vvfat.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/block/vvfat.c b/block/vvfat.c +index 5dacc6cfac..2d9c4ff6a4 100644 +--- a/block/vvfat.c ++++ b/block/vvfat.c +@@ -2521,8 +2521,9 @@ static int commit_one_file(BDRVVVFATState* s, + return -1; + } + +- for (i = s->cluster_size; i < offset; i += s->cluster_size) ++ for (i = 0; i < offset; i += s->cluster_size) { + c = modified_fat_get(s, c); ++ } + + fd = qemu_open_old(mapping->path, O_RDWR | O_CREAT | O_BINARY, 0666); + if (fd < 0) { +-- +2.41.0.windows.1 + diff --git a/vvfat-Fix-reading-files-with-non-continuous-clusters.patch b/vvfat-Fix-reading-files-with-non-continuous-clusters.patch new file mode 100644 index 00000000..18a3a722 --- /dev/null +++ b/vvfat-Fix-reading-files-with-non-continuous-clusters.patch @@ -0,0 +1,50 @@ +From 9399660f4ef94129f4f8ba9277a316bd6e7151b5 Mon Sep 17 00:00:00 2001 +From: Amjad Alsharafi +Date: Sat, 20 Jul 2024 18:13:33 +0800 +Subject: [PATCH] vvfat: Fix reading files with non-continuous clusters + +When reading with `read_cluster` we get the `mapping` with +`find_mapping_for_cluster` and then we call `open_file` for this +mapping. +The issue appear when its the same file, but a second cluster that is +not immediately after it, imagine clusters `500 -> 503`, this will give +us 2 mappings one has the range `500..501` and another `503..504`, both +point to the same file, but different offsets. + +When we don't open the file since the path is the same, we won't assign +`s->current_mapping` and thus accessing way out of bound of the file. + +From our example above, after `open_file` (that didn't open anything) we +will get the offset into the file with +`s->cluster_size*(cluster_num-s->current_mapping->begin)`, which will +give us `0x2000 * (504-500)`, which is out of bound for this mapping and +will produce some issues. + +Signed-off-by: Amjad Alsharafi +Message-ID: <1f3ea115779abab62ba32c788073cdc99f9ad5dd.1721470238.git.amjadsharafi10@gmail.com> +[kwolf: Simplified the patch based on Amjad's analysis and input] +Signed-off-by: Kevin Wolf +(cherry picked from commit 5eed3db336506b529b927ba221fe0d836e5b8819) +Signed-off-by: zhujun2 +--- + block/vvfat.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/block/vvfat.c b/block/vvfat.c +index 5dacc6cfac..9af817088f 100644 +--- a/block/vvfat.c ++++ b/block/vvfat.c +@@ -1368,8 +1368,9 @@ static int open_file(BDRVVVFATState* s,mapping_t* mapping) + return -1; + vvfat_close_current_file(s); + s->current_fd = fd; +- s->current_mapping = mapping; + } ++ ++ s->current_mapping = mapping; + return 0; + } + +-- +2.41.0.windows.1 + -- Gitee From 05bd14f229ce72e9c5247895b2dd64023b1f9549 Mon Sep 17 00:00:00 2001 From: Jiabo Feng Date: Mon, 14 Oct 2024 20:01:28 +0800 Subject: [PATCH 17/19] QEMU update to version 6.2.0-100: - mac_dbdma: Remove leftover `dma_memory_unmap` calls(CVE-2024-8612) - softmmu: Support concurrent bounce buffers(CVE-2024-8612) - system/physmem: Per-AddressSpace bounce buffering - system/physmem: Propagate AddressSpace to MapClient helpers Signed-off-by: Jiabo Feng (cherry picked from commit e52e8efdaac44ee7550723ea1138e2aa4aa52d0d) --- ...-leftover-dma_memory_unmap-calls-CVE.patch | 71 +++++ qemu.spec | 13 +- ...concurrent-bounce-buffers-CVE-2024-8.patch | 284 ++++++++++++++++++ ...em-Per-AddressSpace-bounce-buffering.patch | 261 ++++++++++++++++ ...ropagate-AddressSpace-to-MapClient-h.patch | 205 +++++++++++++ 5 files changed, 833 insertions(+), 1 deletion(-) create mode 100644 mac_dbdma-Remove-leftover-dma_memory_unmap-calls-CVE.patch create mode 100644 softmmu-Support-concurrent-bounce-buffers-CVE-2024-8.patch create mode 100644 system-physmem-Per-AddressSpace-bounce-buffering.patch create mode 100644 system-physmem-Propagate-AddressSpace-to-MapClient-h.patch diff --git a/mac_dbdma-Remove-leftover-dma_memory_unmap-calls-CVE.patch b/mac_dbdma-Remove-leftover-dma_memory_unmap-calls-CVE.patch new file mode 100644 index 00000000..893216c9 --- /dev/null +++ b/mac_dbdma-Remove-leftover-dma_memory_unmap-calls-CVE.patch @@ -0,0 +1,71 @@ +From da2996d0ea1769719830993991f8d0cedb21ccf1 Mon Sep 17 00:00:00 2001 +From: Mattias Nissler +Date: Mon, 16 Sep 2024 10:57:08 -0700 +Subject: [PATCH] mac_dbdma: Remove leftover `dma_memory_unmap` + calls(CVE-2024-8612) + +cherry-pick from 2d0a071e625d7234e8c5623b7e7bf445e1bef72c + +These were passing a NULL buffer pointer unconditionally, which happens +to behave in a mostly benign way (except for the chance of an excess +memory region unref and a bounce buffer leak). Per the function comment, +this was never meant to be accepted though, and triggers an assertion +with the "softmmu: Support concurrent bounce buffers" change. + +Given that the code in question never sets up any mappings, just remove +the unnecessary dma_memory_unmap calls along with the DBDMA_io struct +fields that are now entirely unused. + +Signed-off-by: Mattias Nissler +Message-Id: <20240916175708.1829059-1-mnissler@rivosinc.com> +Fixes: be1e343995 ("macio: switch over to new byte-aligned DMA helpers") +Reviewed-by: Mark Cave-Ayland +Tested-by: Mark Cave-Ayland +Signed-off-by: Mark Cave-Ayland +--- + hw/ide/macio.c | 6 ------ + include/hw/ppc/mac_dbdma.h | 4 ---- + 2 files changed, 10 deletions(-) + +diff --git a/hw/ide/macio.c b/hw/ide/macio.c +index f08318cf97..f23ce15459 100644 +--- a/hw/ide/macio.c ++++ b/hw/ide/macio.c +@@ -119,9 +119,6 @@ static void pmac_ide_atapi_transfer_cb(void *opaque, int ret) + return; + + done: +- dma_memory_unmap(&address_space_memory, io->dma_mem, io->dma_len, +- io->dir, io->dma_len); +- + if (ret < 0) { + block_acct_failed(blk_get_stats(s->blk), &s->acct); + } else { +@@ -202,9 +199,6 @@ static void pmac_ide_transfer_cb(void *opaque, int ret) + return; + + done: +- dma_memory_unmap(&address_space_memory, io->dma_mem, io->dma_len, +- io->dir, io->dma_len); +- + if (s->dma_cmd == IDE_DMA_READ || s->dma_cmd == IDE_DMA_WRITE) { + if (ret < 0) { + block_acct_failed(blk_get_stats(s->blk), &s->acct); +diff --git a/include/hw/ppc/mac_dbdma.h b/include/hw/ppc/mac_dbdma.h +index 4a3f644516..c774f6bf84 100644 +--- a/include/hw/ppc/mac_dbdma.h ++++ b/include/hw/ppc/mac_dbdma.h +@@ -44,10 +44,6 @@ struct DBDMA_io { + DBDMA_end dma_end; + /* DMA is in progress, don't start another one */ + bool processing; +- /* DMA request */ +- void *dma_mem; +- dma_addr_t dma_len; +- DMADirection dir; + }; + + /* +-- +2.45.1.windows.1 + diff --git a/qemu.spec b/qemu.spec index fa7c941a..417538f3 100644 --- a/qemu.spec +++ b/qemu.spec @@ -3,7 +3,7 @@ Name: qemu Version: 6.2.0 -Release: 99 +Release: 100 Epoch: 10 Summary: QEMU is a generic and open source machine emulator and virtualizer License: GPLv2 and BSD and MIT and CC-BY-SA-4.0 @@ -1044,6 +1044,11 @@ Patch1029: target-arm-Fix-alignment-for-VLD4.32.patch Patch1030: hw-net-lan9118-Signal-TSFL_INT-flag-when-TX-FIFO-rea.patch Patch1031: qtest-fuzz-lsi53c895a-test-set-guest-RAM-to-2G.patch Patch1032: target-i386-Introduce-SapphireRapids-v3-to-add-missi.patch +Patch1033: system-physmem-Propagate-AddressSpace-to-MapClient-h.patch +Patch1034: system-physmem-Per-AddressSpace-bounce-buffering.patch +Patch1035: softmmu-Support-concurrent-bounce-buffers-CVE-2024-8.patch +Patch1036: mac_dbdma-Remove-leftover-dma_memory_unmap-calls-CVE.patch + BuildRequires: flex BuildRequires: gcc @@ -1642,6 +1647,12 @@ getent passwd qemu >/dev/null || \ %endif %changelog +* Mon Oct 14 2024 - 10:6.2.0-100 +- mac_dbdma: Remove leftover `dma_memory_unmap` calls(CVE-2024-8612) +- softmmu: Support concurrent bounce buffers(CVE-2024-8612) +- system/physmem: Per-AddressSpace bounce buffering +- system/physmem: Propagate AddressSpace to MapClient helpers + * Wed Sep 18 2024 - 10:6.2.0-99 - target/i386: Introduce SapphireRapids-v3 to add missing features - qtest/fuzz-lsi53c895a-test: set guest RAM to 2G diff --git a/softmmu-Support-concurrent-bounce-buffers-CVE-2024-8.patch b/softmmu-Support-concurrent-bounce-buffers-CVE-2024-8.patch new file mode 100644 index 00000000..f376f9ba --- /dev/null +++ b/softmmu-Support-concurrent-bounce-buffers-CVE-2024-8.patch @@ -0,0 +1,284 @@ +From 409eea48ae96cce3fea6c42339805be180c86da2 Mon Sep 17 00:00:00 2001 +From: Mattias Nissler +Date: Mon, 19 Aug 2024 06:54:54 -0700 +Subject: [PATCH] softmmu: Support concurrent bounce buffers(CVE-2024-8612) +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +cherry-pick from 637b0aa139565cb82a7b9269e62214f87082635c + +When DMA memory can't be directly accessed, as is the case when +running the device model in a separate process without shareable DMA +file descriptors, bounce buffering is used. + +It is not uncommon for device models to request mapping of several DMA +regions at the same time. Examples include: + * net devices, e.g. when transmitting a packet that is split across + several TX descriptors (observed with igb) + * USB host controllers, when handling a packet with multiple data TRBs + (observed with xhci) + +Previously, qemu only provided a single bounce buffer per AddressSpace +and would fail DMA map requests while the buffer was already in use. In +turn, this would cause DMA failures that ultimately manifest as hardware +errors from the guest perspective. + +This change allocates DMA bounce buffers dynamically instead of +supporting only a single buffer. Thus, multiple DMA mappings work +correctly also when RAM can't be mmap()-ed. + +The total bounce buffer allocation size is limited individually for each +AddressSpace. The default limit is 4096 bytes, matching the previous +maximum buffer size. A new x-max-bounce-buffer-size parameter is +provided to configure the limit for PCI devices. + +Signed-off-by: Mattias Nissler +Reviewed-by: Philippe Mathieu-Daudé +Acked-by: Peter Xu +Link: https://lore.kernel.org/r/20240819135455.2957406-1-mnissler@rivosinc.com +Signed-off-by: Peter Xu +--- + hw/pci/pci.c | 8 +++++ + include/exec/memory.h | 14 +++----- + include/hw/pci/pci.h | 3 ++ + softmmu/memory.c | 5 +-- + softmmu/physmem.c | 77 ++++++++++++++++++++++++++++++------------- + 5 files changed, 74 insertions(+), 33 deletions(-) + +diff --git a/hw/pci/pci.c b/hw/pci/pci.c +index 9ea67dba31..df58028b4c 100644 +--- a/hw/pci/pci.c ++++ b/hw/pci/pci.c +@@ -79,6 +79,8 @@ static Property pci_props[] = { + DEFINE_PROP_STRING("failover_pair_id", PCIDevice, + failover_pair_id), + DEFINE_PROP_UINT32("acpi-index", PCIDevice, acpi_index, 0), ++ DEFINE_PROP_SIZE32("x-max-bounce-buffer-size", PCIDevice, ++ max_bounce_buffer_size, DEFAULT_MAX_BOUNCE_BUFFER_SIZE), + DEFINE_PROP_END_OF_LIST() + }; + +@@ -1108,6 +1110,8 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, + "bus master container", UINT64_MAX); + address_space_init(&pci_dev->bus_master_as, + &pci_dev->bus_master_container_region, pci_dev->name); ++ pci_dev->bus_master_as.max_bounce_buffer_size = ++ pci_dev->max_bounce_buffer_size; + + if (phase_check(PHASE_MACHINE_READY)) { + pci_init_bus_master(pci_dev); +@@ -2696,6 +2700,10 @@ static void pci_device_class_init(ObjectClass *klass, void *data) + k->unrealize = pci_qdev_unrealize; + k->bus_type = TYPE_PCI_BUS; + device_class_set_props(k, pci_props); ++ object_class_property_set_description( ++ klass, "x-max-bounce-buffer-size", ++ "Maximum buffer size allocated for bounce buffers used for mapped " ++ "access to indirect DMA memory"); + } + + static void pci_device_class_base_init(ObjectClass *klass, void *data) +diff --git a/include/exec/memory.h b/include/exec/memory.h +index f6bde44ecf..2444e0f39d 100644 +--- a/include/exec/memory.h ++++ b/include/exec/memory.h +@@ -1040,13 +1040,7 @@ typedef struct AddressSpaceMapClient { + QLIST_ENTRY(AddressSpaceMapClient) link; + } AddressSpaceMapClient; + +-typedef struct { +- MemoryRegion *mr; +- void *buffer; +- hwaddr addr; +- hwaddr len; +- bool in_use; +-} BounceBuffer; ++#define DEFAULT_MAX_BOUNCE_BUFFER_SIZE (4096) + + /** + * struct AddressSpace: describes a mapping of addresses to #MemoryRegion objects +@@ -1065,8 +1059,10 @@ struct AddressSpace { + QTAILQ_HEAD(, MemoryListener) listeners; + QTAILQ_ENTRY(AddressSpace) address_spaces_link; + +- /* Bounce buffer to use for this address space. */ +- BounceBuffer bounce; ++ /* Maximum DMA bounce buffer size used for indirect memory map requests */ ++ size_t max_bounce_buffer_size; ++ /* Total size of bounce buffers currently allocated, atomically accessed */ ++ size_t bounce_buffer_size; + /* List of callbacks to invoke when buffers free up */ + QemuMutex map_client_list_lock; + QLIST_HEAD(, AddressSpaceMapClient) map_client_list; +diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h +index 483d5c7c72..458126a18c 100644 +--- a/include/hw/pci/pci.h ++++ b/include/hw/pci/pci.h +@@ -361,6 +361,9 @@ struct PCIDevice { + /* ID of standby device in net_failover pair */ + char *failover_pair_id; + uint32_t acpi_index; ++ ++ /* Maximum DMA bounce buffer size used for indirect memory map requests */ ++ uint32_t max_bounce_buffer_size; + }; + + void pci_register_bar(PCIDevice *pci_dev, int region_num, +diff --git a/softmmu/memory.c b/softmmu/memory.c +index 3ab6a58902..0bb49da904 100644 +--- a/softmmu/memory.c ++++ b/softmmu/memory.c +@@ -2946,7 +2946,8 @@ void address_space_init(AddressSpace *as, MemoryRegion *root, const char *name) + as->ioeventfds = NULL; + QTAILQ_INIT(&as->listeners); + QTAILQ_INSERT_TAIL(&address_spaces, as, address_spaces_link); +- as->bounce.in_use = false; ++ as->max_bounce_buffer_size = DEFAULT_MAX_BOUNCE_BUFFER_SIZE; ++ as->bounce_buffer_size = 0; + qemu_mutex_init(&as->map_client_list_lock); + QLIST_INIT(&as->map_client_list); + as->name = g_strdup(name ? name : "anonymous"); +@@ -2956,7 +2957,7 @@ void address_space_init(AddressSpace *as, MemoryRegion *root, const char *name) + + static void do_address_space_destroy(AddressSpace *as) + { +- assert(!qatomic_read(&as->bounce.in_use)); ++ assert(qatomic_read(&as->bounce_buffer_size) == 0); + assert(QLIST_EMPTY(&as->map_client_list)); + qemu_mutex_destroy(&as->map_client_list_lock); + +diff --git a/softmmu/physmem.c b/softmmu/physmem.c +index 9905d55c67..45d290cde5 100644 +--- a/softmmu/physmem.c ++++ b/softmmu/physmem.c +@@ -3081,6 +3081,20 @@ void cpu_flush_icache_range(hwaddr start, hwaddr len) + NULL, len, FLUSH_CACHE); + } + ++/* ++ * A magic value stored in the first 8 bytes of the bounce buffer struct. Used ++ * to detect illegal pointers passed to address_space_unmap. ++ */ ++#define BOUNCE_BUFFER_MAGIC 0xb4017ceb4ffe12ed ++ ++typedef struct { ++ uint64_t magic; ++ MemoryRegion *mr; ++ hwaddr addr; ++ size_t len; ++ uint8_t buffer[]; ++} BounceBuffer; ++ + static void + address_space_unregister_map_client_do(AddressSpaceMapClient *client) + { +@@ -3106,7 +3120,7 @@ void address_space_register_map_client(AddressSpace *as, QEMUBH *bh) + qemu_mutex_lock(&as->map_client_list_lock); + client->bh = bh; + QLIST_INSERT_HEAD(&as->map_client_list, client, link); +- if (!qatomic_read(&as->bounce.in_use)) { ++ if (qatomic_read(&as->bounce_buffer_size) < as->max_bounce_buffer_size) { + address_space_notify_map_clients_locked(as); + } + qemu_mutex_unlock(&as->map_client_list_lock); +@@ -3237,28 +3251,40 @@ void *address_space_map(AddressSpace *as, + mr = flatview_translate(fv, addr, &xlat, &l, is_write, attrs); + + if (!memory_access_is_direct(mr, is_write)) { +- if (qatomic_xchg(&as->bounce.in_use, true)) { ++ size_t used = qatomic_read(&as->bounce_buffer_size); ++ for (;;) { ++ hwaddr alloc = MIN(as->max_bounce_buffer_size - used, l); ++ size_t new_size = used + alloc; ++ size_t actual = ++ qatomic_cmpxchg(&as->bounce_buffer_size, used, new_size); ++ if (actual == used) { ++ l = alloc; ++ break; ++ } ++ used = actual; ++ } ++ ++ if (l == 0) { + *plen = 0; + return NULL; + } +- /* Avoid unbounded allocations */ +- l = MIN(l, TARGET_PAGE_SIZE); +- as->bounce.buffer = qemu_memalign(TARGET_PAGE_SIZE, l); +- as->bounce.addr = addr; +- as->bounce.len = l; + ++ BounceBuffer *bounce = g_malloc0(l + sizeof(BounceBuffer)); ++ bounce->magic = BOUNCE_BUFFER_MAGIC; + memory_region_ref(mr); +- as->bounce.mr = mr; ++ bounce->mr = mr; ++ bounce->addr = addr; ++ bounce->len = l; ++ + if (!is_write) { + flatview_read(fv, addr, MEMTXATTRS_UNSPECIFIED, +- as->bounce.buffer, l); ++ bounce->buffer, l); + } + + *plen = l; +- return as->bounce.buffer; ++ return bounce->buffer; + } + +- + memory_region_ref(mr); + *plen = flatview_extend_translation(fv, addr, len, mr, xlat, + l, is_write, attrs); +@@ -3275,12 +3301,11 @@ void *address_space_map(AddressSpace *as, + void address_space_unmap(AddressSpace *as, void *buffer, hwaddr len, + bool is_write, hwaddr access_len) + { +- if (buffer != as->bounce.buffer) { +- MemoryRegion *mr; +- ram_addr_t addr1; ++ MemoryRegion *mr; ++ ram_addr_t addr1; + +- mr = memory_region_from_host(buffer, &addr1); +- assert(mr != NULL); ++ mr = memory_region_from_host(buffer, &addr1); ++ if (mr != NULL) { + if (is_write) { + invalidate_and_set_dirty(mr, addr1, access_len); + } +@@ -3290,14 +3315,22 @@ void address_space_unmap(AddressSpace *as, void *buffer, hwaddr len, + memory_region_unref(mr); + return; + } ++ ++ ++ BounceBuffer *bounce = container_of(buffer, BounceBuffer, buffer); ++ assert(bounce->magic == BOUNCE_BUFFER_MAGIC); ++ + if (is_write) { +- address_space_write(as, as->bounce.addr, MEMTXATTRS_UNSPECIFIED, +- as->bounce.buffer, access_len); ++ address_space_write(as, bounce->addr, MEMTXATTRS_UNSPECIFIED, ++ bounce->buffer, access_len); + } +- qemu_vfree(as->bounce.buffer); +- as->bounce.buffer = NULL; +- memory_region_unref(as->bounce.mr); +- qatomic_mb_set(&as->bounce.in_use, false); ++ ++ qatomic_sub(&as->bounce_buffer_size, bounce->len); ++ bounce->magic = ~BOUNCE_BUFFER_MAGIC; ++ memory_region_unref(bounce->mr); ++ g_free(bounce); ++ /* Write bounce_buffer_size before reading map_client_list. */ ++ smp_mb(); + address_space_notify_map_clients(as); + } + +-- +2.45.1.windows.1 + diff --git a/system-physmem-Per-AddressSpace-bounce-buffering.patch b/system-physmem-Per-AddressSpace-bounce-buffering.patch new file mode 100644 index 00000000..787a144f --- /dev/null +++ b/system-physmem-Per-AddressSpace-bounce-buffering.patch @@ -0,0 +1,261 @@ +From dcab52cf7a81db32d744aae81888a3ed1d3a9efa Mon Sep 17 00:00:00 2001 +From: Mattias Nissler +Date: Thu, 7 Sep 2023 06:04:23 -0700 +Subject: [PATCH] system/physmem: Per-AddressSpace bounce buffering +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +cherry-pick 69e78f1b3484e429274352a464a94fa1d78be339 + +Instead of using a single global bounce buffer, give each AddressSpace +its own bounce buffer. The MapClient callback mechanism moves to +AddressSpace accordingly. + +This is in preparation for generalizing bounce buffer handling further +to allow multiple bounce buffers, with a total allocation limit +configured per AddressSpace. + +Reviewed-by: Peter Xu +Tested-by: Jonathan Cameron +Signed-off-by: Mattias Nissler +Message-ID: <20240507094210.300566-2-mnissler@rivosinc.com> +Reviewed-by: Philippe Mathieu-Daudé +[PMD: Split patch, part 2/2] +Signed-off-by: Philippe Mathieu-Daudé +--- + include/exec/memory.h | 19 +++++++++++ + softmmu/memory.c | 7 ++++ + softmmu/physmem.c | 79 ++++++++++++++++--------------------------- + 3 files changed, 56 insertions(+), 49 deletions(-) + +diff --git a/include/exec/memory.h b/include/exec/memory.h +index 859e3da182..f6bde44ecf 100644 +--- a/include/exec/memory.h ++++ b/include/exec/memory.h +@@ -1035,6 +1035,19 @@ struct MemoryListener { + QTAILQ_ENTRY(MemoryListener) link_as; + }; + ++typedef struct AddressSpaceMapClient { ++ QEMUBH *bh; ++ QLIST_ENTRY(AddressSpaceMapClient) link; ++} AddressSpaceMapClient; ++ ++typedef struct { ++ MemoryRegion *mr; ++ void *buffer; ++ hwaddr addr; ++ hwaddr len; ++ bool in_use; ++} BounceBuffer; ++ + /** + * struct AddressSpace: describes a mapping of addresses to #MemoryRegion objects + */ +@@ -1051,6 +1064,12 @@ struct AddressSpace { + struct MemoryRegionIoeventfd *ioeventfds; + QTAILQ_HEAD(, MemoryListener) listeners; + QTAILQ_ENTRY(AddressSpace) address_spaces_link; ++ ++ /* Bounce buffer to use for this address space. */ ++ BounceBuffer bounce; ++ /* List of callbacks to invoke when buffers free up */ ++ QemuMutex map_client_list_lock; ++ QLIST_HEAD(, AddressSpaceMapClient) map_client_list; + }; + + typedef struct AddressSpaceDispatch AddressSpaceDispatch; +diff --git a/softmmu/memory.c b/softmmu/memory.c +index 0bf37f11aa..3ab6a58902 100644 +--- a/softmmu/memory.c ++++ b/softmmu/memory.c +@@ -2946,6 +2946,9 @@ void address_space_init(AddressSpace *as, MemoryRegion *root, const char *name) + as->ioeventfds = NULL; + QTAILQ_INIT(&as->listeners); + QTAILQ_INSERT_TAIL(&address_spaces, as, address_spaces_link); ++ as->bounce.in_use = false; ++ qemu_mutex_init(&as->map_client_list_lock); ++ QLIST_INIT(&as->map_client_list); + as->name = g_strdup(name ? name : "anonymous"); + address_space_update_topology(as); + address_space_update_ioeventfds(as); +@@ -2953,6 +2956,10 @@ void address_space_init(AddressSpace *as, MemoryRegion *root, const char *name) + + static void do_address_space_destroy(AddressSpace *as) + { ++ assert(!qatomic_read(&as->bounce.in_use)); ++ assert(QLIST_EMPTY(&as->map_client_list)); ++ qemu_mutex_destroy(&as->map_client_list_lock); ++ + assert(QTAILQ_EMPTY(&as->listeners)); + + flatview_unref(as->current_map); +diff --git a/softmmu/physmem.c b/softmmu/physmem.c +index b86d7a0cf4..9905d55c67 100644 +--- a/softmmu/physmem.c ++++ b/softmmu/physmem.c +@@ -3081,26 +3081,8 @@ void cpu_flush_icache_range(hwaddr start, hwaddr len) + NULL, len, FLUSH_CACHE); + } + +-typedef struct { +- MemoryRegion *mr; +- void *buffer; +- hwaddr addr; +- hwaddr len; +- bool in_use; +-} BounceBuffer; +- +-static BounceBuffer bounce; +- +-typedef struct MapClient { +- QEMUBH *bh; +- QLIST_ENTRY(MapClient) link; +-} MapClient; +- +-QemuMutex map_client_list_lock; +-static QLIST_HEAD(, MapClient) map_client_list +- = QLIST_HEAD_INITIALIZER(map_client_list); +- +-static void address_space_unregister_map_client_do(MapClient *client) ++static void ++address_space_unregister_map_client_do(AddressSpaceMapClient *client) + { + QLIST_REMOVE(client, link); + g_free(client); +@@ -3108,10 +3090,10 @@ static void address_space_unregister_map_client_do(MapClient *client) + + static void address_space_notify_map_clients_locked(AddressSpace *as) + { +- MapClient *client; ++ AddressSpaceMapClient *client; + +- while (!QLIST_EMPTY(&map_client_list)) { +- client = QLIST_FIRST(&map_client_list); ++ while (!QLIST_EMPTY(&as->map_client_list)) { ++ client = QLIST_FIRST(&as->map_client_list); + qemu_bh_schedule(client->bh); + address_space_unregister_map_client_do(client); + } +@@ -3119,15 +3101,15 @@ static void address_space_notify_map_clients_locked(AddressSpace *as) + + void address_space_register_map_client(AddressSpace *as, QEMUBH *bh) + { +- MapClient *client = g_malloc(sizeof(*client)); ++ AddressSpaceMapClient *client = g_malloc(sizeof(*client)); + +- qemu_mutex_lock(&map_client_list_lock); ++ qemu_mutex_lock(&as->map_client_list_lock); + client->bh = bh; +- QLIST_INSERT_HEAD(&map_client_list, client, link); +- if (!qatomic_read(&bounce.in_use)) { ++ QLIST_INSERT_HEAD(&as->map_client_list, client, link); ++ if (!qatomic_read(&as->bounce.in_use)) { + address_space_notify_map_clients_locked(as); + } +- qemu_mutex_unlock(&map_client_list_lock); ++ qemu_mutex_unlock(&as->map_client_list_lock); + } + + void cpu_exec_init_all(void) +@@ -3143,28 +3125,27 @@ void cpu_exec_init_all(void) + finalize_target_page_bits(); + io_mem_init(); + memory_map_init(); +- qemu_mutex_init(&map_client_list_lock); + } + + void address_space_unregister_map_client(AddressSpace *as, QEMUBH *bh) + { +- MapClient *client; ++ AddressSpaceMapClient *client; + +- qemu_mutex_lock(&map_client_list_lock); +- QLIST_FOREACH(client, &map_client_list, link) { ++ qemu_mutex_lock(&as->map_client_list_lock); ++ QLIST_FOREACH(client, &as->map_client_list, link) { + if (client->bh == bh) { + address_space_unregister_map_client_do(client); + break; + } + } +- qemu_mutex_unlock(&map_client_list_lock); ++ qemu_mutex_unlock(&as->map_client_list_lock); + } + + static void address_space_notify_map_clients(AddressSpace *as) + { +- qemu_mutex_lock(&map_client_list_lock); ++ qemu_mutex_lock(&as->map_client_list_lock); + address_space_notify_map_clients_locked(as); +- qemu_mutex_unlock(&map_client_list_lock); ++ qemu_mutex_unlock(&as->map_client_list_lock); + } + + static bool flatview_access_valid(FlatView *fv, hwaddr addr, hwaddr len, +@@ -3256,25 +3237,25 @@ void *address_space_map(AddressSpace *as, + mr = flatview_translate(fv, addr, &xlat, &l, is_write, attrs); + + if (!memory_access_is_direct(mr, is_write)) { +- if (qatomic_xchg(&bounce.in_use, true)) { ++ if (qatomic_xchg(&as->bounce.in_use, true)) { + *plen = 0; + return NULL; + } + /* Avoid unbounded allocations */ + l = MIN(l, TARGET_PAGE_SIZE); +- bounce.buffer = qemu_memalign(TARGET_PAGE_SIZE, l); +- bounce.addr = addr; +- bounce.len = l; ++ as->bounce.buffer = qemu_memalign(TARGET_PAGE_SIZE, l); ++ as->bounce.addr = addr; ++ as->bounce.len = l; + + memory_region_ref(mr); +- bounce.mr = mr; ++ as->bounce.mr = mr; + if (!is_write) { + flatview_read(fv, addr, MEMTXATTRS_UNSPECIFIED, +- bounce.buffer, l); ++ as->bounce.buffer, l); + } + + *plen = l; +- return bounce.buffer; ++ return as->bounce.buffer; + } + + +@@ -3294,7 +3275,7 @@ void *address_space_map(AddressSpace *as, + void address_space_unmap(AddressSpace *as, void *buffer, hwaddr len, + bool is_write, hwaddr access_len) + { +- if (buffer != bounce.buffer) { ++ if (buffer != as->bounce.buffer) { + MemoryRegion *mr; + ram_addr_t addr1; + +@@ -3310,13 +3291,13 @@ void address_space_unmap(AddressSpace *as, void *buffer, hwaddr len, + return; + } + if (is_write) { +- address_space_write(as, bounce.addr, MEMTXATTRS_UNSPECIFIED, +- bounce.buffer, access_len); ++ address_space_write(as, as->bounce.addr, MEMTXATTRS_UNSPECIFIED, ++ as->bounce.buffer, access_len); + } +- qemu_vfree(bounce.buffer); +- bounce.buffer = NULL; +- memory_region_unref(bounce.mr); +- qatomic_mb_set(&bounce.in_use, false); ++ qemu_vfree(as->bounce.buffer); ++ as->bounce.buffer = NULL; ++ memory_region_unref(as->bounce.mr); ++ qatomic_mb_set(&as->bounce.in_use, false); + address_space_notify_map_clients(as); + } + +-- +2.45.1.windows.1 + diff --git a/system-physmem-Propagate-AddressSpace-to-MapClient-h.patch b/system-physmem-Propagate-AddressSpace-to-MapClient-h.patch new file mode 100644 index 00000000..7a718771 --- /dev/null +++ b/system-physmem-Propagate-AddressSpace-to-MapClient-h.patch @@ -0,0 +1,205 @@ +From 055bd1a398060bb44aa13a1b732df843f759d5e4 Mon Sep 17 00:00:00 2001 +From: Mattias Nissler +Date: Thu, 7 Sep 2023 06:04:23 -0700 +Subject: [PATCH] system/physmem: Propagate AddressSpace to MapClient helpers +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +cherry-pick from 5c62719710bab66a98f68ebdba333e2240ed6668 + +Propagate AddressSpace handler to following helpers: +- register_map_client() +- unregister_map_client() +- notify_map_clients[_locked]() + +Rename them using 'address_space_' prefix instead of 'cpu_'. + +The AddressSpace argument will be used in the next commit. + +Reviewed-by: Peter Xu +Tested-by: Jonathan Cameron +Signed-off-by: Mattias Nissler +Message-ID: <20240507094210.300566-2-mnissler@rivosinc.com> +[PMD: Split patch, part 1/2] +Signed-off-by: Philippe Mathieu-Daudé +--- + include/exec/cpu-common.h | 2 -- + include/exec/memory.h | 26 ++++++++++++++++++++++++-- + softmmu/dma-helpers.c | 4 ++-- + softmmu/physmem.c | 24 ++++++++++++------------ + 4 files changed, 38 insertions(+), 18 deletions(-) + +diff --git a/include/exec/cpu-common.h b/include/exec/cpu-common.h +index cdee668f20..2a3050f553 100644 +--- a/include/exec/cpu-common.h ++++ b/include/exec/cpu-common.h +@@ -87,8 +87,6 @@ void *cpu_physical_memory_map(hwaddr addr, + bool is_write); + void cpu_physical_memory_unmap(void *buffer, hwaddr len, + bool is_write, hwaddr access_len); +-void cpu_register_map_client(QEMUBH *bh); +-void cpu_unregister_map_client(QEMUBH *bh); + + bool cpu_physical_memory_is_io(hwaddr phys_addr); + +diff --git a/include/exec/memory.h b/include/exec/memory.h +index bbf1468d59..859e3da182 100644 +--- a/include/exec/memory.h ++++ b/include/exec/memory.h +@@ -2772,8 +2772,8 @@ bool address_space_access_valid(AddressSpace *as, hwaddr addr, hwaddr len, + * May return %NULL and set *@plen to zero(0), if resources needed to perform + * the mapping are exhausted. + * Use only for reads OR writes - not for read-modify-write operations. +- * Use cpu_register_map_client() to know when retrying the map operation is +- * likely to succeed. ++ * Use address_space_register_map_client() to know when retrying the map ++ * operation is likely to succeed. + * + * @as: #AddressSpace to be accessed + * @addr: address within that address space +@@ -2798,6 +2798,28 @@ void *address_space_map(AddressSpace *as, hwaddr addr, + void address_space_unmap(AddressSpace *as, void *buffer, hwaddr len, + bool is_write, hwaddr access_len); + ++/* ++ * address_space_register_map_client: Register a callback to invoke when ++ * resources for address_space_map() are available again. ++ * ++ * address_space_map may fail when there are not enough resources available, ++ * such as when bounce buffer memory would exceed the limit. The callback can ++ * be used to retry the address_space_map operation. Note that the callback ++ * gets automatically removed after firing. ++ * ++ * @as: #AddressSpace to be accessed ++ * @bh: callback to invoke when address_space_map() retry is appropriate ++ */ ++void address_space_register_map_client(AddressSpace *as, QEMUBH *bh); ++ ++/* ++ * address_space_unregister_map_client: Unregister a callback that has ++ * previously been registered and not fired yet. ++ * ++ * @as: #AddressSpace to be accessed ++ * @bh: callback to unregister ++ */ ++void address_space_unregister_map_client(AddressSpace *as, QEMUBH *bh); + + /* Internal functions, part of the implementation of address_space_read. */ + MemTxResult address_space_read_full(AddressSpace *as, hwaddr addr, +diff --git a/softmmu/dma-helpers.c b/softmmu/dma-helpers.c +index c2028b6585..3f664156db 100644 +--- a/softmmu/dma-helpers.c ++++ b/softmmu/dma-helpers.c +@@ -165,7 +165,7 @@ static void dma_blk_cb(void *opaque, int ret) + if (dbs->iov.size == 0) { + trace_dma_map_wait(dbs); + dbs->bh = aio_bh_new(dbs->ctx, reschedule_dma, dbs); +- cpu_register_map_client(dbs->bh); ++ address_space_register_map_client(dbs->sg->as, dbs->bh); + return; + } + +@@ -195,7 +195,7 @@ static void dma_aio_cancel(BlockAIOCB *acb) + } + + if (dbs->bh) { +- cpu_unregister_map_client(dbs->bh); ++ address_space_unregister_map_client(dbs->sg->as, dbs->bh); + qemu_bh_delete(dbs->bh); + dbs->bh = NULL; + } +diff --git a/softmmu/physmem.c b/softmmu/physmem.c +index e5c3557d54..b86d7a0cf4 100644 +--- a/softmmu/physmem.c ++++ b/softmmu/physmem.c +@@ -3100,24 +3100,24 @@ QemuMutex map_client_list_lock; + static QLIST_HEAD(, MapClient) map_client_list + = QLIST_HEAD_INITIALIZER(map_client_list); + +-static void cpu_unregister_map_client_do(MapClient *client) ++static void address_space_unregister_map_client_do(MapClient *client) + { + QLIST_REMOVE(client, link); + g_free(client); + } + +-static void cpu_notify_map_clients_locked(void) ++static void address_space_notify_map_clients_locked(AddressSpace *as) + { + MapClient *client; + + while (!QLIST_EMPTY(&map_client_list)) { + client = QLIST_FIRST(&map_client_list); + qemu_bh_schedule(client->bh); +- cpu_unregister_map_client_do(client); ++ address_space_unregister_map_client_do(client); + } + } + +-void cpu_register_map_client(QEMUBH *bh) ++void address_space_register_map_client(AddressSpace *as, QEMUBH *bh) + { + MapClient *client = g_malloc(sizeof(*client)); + +@@ -3125,7 +3125,7 @@ void cpu_register_map_client(QEMUBH *bh) + client->bh = bh; + QLIST_INSERT_HEAD(&map_client_list, client, link); + if (!qatomic_read(&bounce.in_use)) { +- cpu_notify_map_clients_locked(); ++ address_space_notify_map_clients_locked(as); + } + qemu_mutex_unlock(&map_client_list_lock); + } +@@ -3146,24 +3146,24 @@ void cpu_exec_init_all(void) + qemu_mutex_init(&map_client_list_lock); + } + +-void cpu_unregister_map_client(QEMUBH *bh) ++void address_space_unregister_map_client(AddressSpace *as, QEMUBH *bh) + { + MapClient *client; + + qemu_mutex_lock(&map_client_list_lock); + QLIST_FOREACH(client, &map_client_list, link) { + if (client->bh == bh) { +- cpu_unregister_map_client_do(client); ++ address_space_unregister_map_client_do(client); + break; + } + } + qemu_mutex_unlock(&map_client_list_lock); + } + +-static void cpu_notify_map_clients(void) ++static void address_space_notify_map_clients(AddressSpace *as) + { + qemu_mutex_lock(&map_client_list_lock); +- cpu_notify_map_clients_locked(); ++ address_space_notify_map_clients_locked(as); + qemu_mutex_unlock(&map_client_list_lock); + } + +@@ -3231,8 +3231,8 @@ flatview_extend_translation(FlatView *fv, hwaddr addr, + * May map a subset of the requested range, given by and returned in *plen. + * May return NULL if resources needed to perform the mapping are exhausted. + * Use only for reads OR writes - not for read-modify-write operations. +- * Use cpu_register_map_client() to know when retrying the map operation is +- * likely to succeed. ++ * Use address_space_register_map_client() to know when retrying the map ++ * operation is likely to succeed. + */ + void *address_space_map(AddressSpace *as, + hwaddr addr, +@@ -3317,7 +3317,7 @@ void address_space_unmap(AddressSpace *as, void *buffer, hwaddr len, + bounce.buffer = NULL; + memory_region_unref(bounce.mr); + qatomic_mb_set(&bounce.in_use, false); +- cpu_notify_map_clients(); ++ address_space_notify_map_clients(as); + } + + void *cpu_physical_memory_map(hwaddr addr, +-- +2.45.1.windows.1 + -- Gitee From 11aadaf893ad9af947978d9d01e0d1471631a63f Mon Sep 17 00:00:00 2001 From: Jiabo Feng Date: Mon, 21 Oct 2024 10:21:47 +0800 Subject: [PATCH 18/19] QEMU update to version 6.2.0-101: - python/aqmp: use absolute import statement - sysemu: Cleanup qemu_run_machine_init_done_notifiers() - vhost-backend: avoid overflow on memslots_limit - hw/i386/vmmouse: Require 'i8042' property to be set - hw/scsi/megasas: Fails command if SGL buffer overflows - target/i386/kvm: Replace use of __u32 type - hw/avr: Realize AVRCPU qdev object using qdev_realize() - qemu-keymap: Add license in generated files - configure: Symlink binaries using .exe suffix with MinGW - ui: remove break after g_assert_not_reached() - io/channel-websock: Replace strlen(const_str) by sizeof(const_str) - 1 - target/ppc: Add HASHKEYR and HASHPKEYR SPRs - tests: Fix error strings - Hexagon (target/hexagon) remove unused encodings - target/i386: introduce insn_get_addr - target/i386: REPZ and REPNZ are mutually exclusive - target/i386: correctly mask SSE4a bit indices in register operands - bios-tables-test: Make oem-fields tests be consistent - tests/vm: update NetBSD to 9.3 - monitor/hmp-cmds: Avoid displaying bogus size in 'info pci' When BAR aren't mapped, we get: - virtio-mem: don't warn about THP sizes on a kernel without THP Support - Subject: [PATCH] kvm: Use 'unsigned long' for request argument in functions wrapping ioctl() Signed-off-by: Jiabo Feng (cherry picked from commit 2430c96ac522f910c11eb98c2d9f74c2c3336a00) --- ...rget-hexagon-remove-unused-encodings.patch | 70 +++++++ ...m-Use-unsigned-long-for-request-argu.patch | 189 ++++++++++++++++++ ...-Make-oem-fields-tests-be-consistent.patch | 102 ++++++++++ ...k-binaries-using-.exe-suffix-with-Mi.patch | 40 ++++ ...VRCPU-qdev-object-using-qdev_realize.patch | 39 ++++ ...use-Require-i8042-property-to-be-set.patch | 48 +++++ ...Fails-command-if-SGL-buffer-overflow.patch | 40 ++++ ...ck-Replace-strlen-const_str-by-sizeo.patch | 46 +++++ ...-Avoid-displaying-bogus-size-in-info.patch | 97 +++++++++ ...n-aqmp-use-absolute-import-statement.patch | 41 ++++ ...eymap-Add-license-in-generated-files.patch | 34 ++++ qemu.spec | 49 ++++- ...qemu_run_machine_init_done_notifiers.patch | 38 ++++ ...EPZ-and-REPNZ-are-mutually-exclusive.patch | 33 +++ ...ectly-mask-SSE4a-bit-indices-in-regi.patch | 43 ++++ target-i386-introduce-insn_get_addr.patch | 73 +++++++ ...t-i386-kvm-Replace-use-of-__u32-type.patch | 38 ++++ ...-ppc-Add-HASHKEYR-and-HASHPKEYR-SPRs.patch | 89 +++++++++ tests-Fix-error-strings.patch | 49 +++++ tests-vm-update-NetBSD-to-9.3.patch | 33 +++ ...ove-break-after-g_assert_not_reached.patch | 47 +++++ ...end-avoid-overflow-on-memslots_limit.patch | 36 ++++ ...-warn-about-THP-sizes-on-a-kernel-wi.patch | 50 +++++ 23 files changed, 1322 insertions(+), 2 deletions(-) create mode 100644 Hexagon-target-hexagon-remove-unused-encodings.patch create mode 100644 Subject-PATCH-kvm-Use-unsigned-long-for-request-argu.patch create mode 100644 bios-tables-test-Make-oem-fields-tests-be-consistent.patch create mode 100644 configure-Symlink-binaries-using-.exe-suffix-with-Mi.patch create mode 100644 hw-avr-Realize-AVRCPU-qdev-object-using-qdev_realize.patch create mode 100644 hw-i386-vmmouse-Require-i8042-property-to-be-set.patch create mode 100644 hw-scsi-megasas-Fails-command-if-SGL-buffer-overflow.patch create mode 100644 io-channel-websock-Replace-strlen-const_str-by-sizeo.patch create mode 100644 monitor-hmp-cmds-Avoid-displaying-bogus-size-in-info.patch create mode 100644 python-aqmp-use-absolute-import-statement.patch create mode 100644 qemu-keymap-Add-license-in-generated-files.patch create mode 100644 sysemu-Cleanup-qemu_run_machine_init_done_notifiers.patch create mode 100644 target-i386-REPZ-and-REPNZ-are-mutually-exclusive.patch create mode 100644 target-i386-correctly-mask-SSE4a-bit-indices-in-regi.patch create mode 100644 target-i386-introduce-insn_get_addr.patch create mode 100644 target-i386-kvm-Replace-use-of-__u32-type.patch create mode 100644 target-ppc-Add-HASHKEYR-and-HASHPKEYR-SPRs.patch create mode 100644 tests-Fix-error-strings.patch create mode 100644 tests-vm-update-NetBSD-to-9.3.patch create mode 100644 ui-remove-break-after-g_assert_not_reached.patch create mode 100644 vhost-backend-avoid-overflow-on-memslots_limit.patch create mode 100644 virtio-mem-don-t-warn-about-THP-sizes-on-a-kernel-wi.patch diff --git a/Hexagon-target-hexagon-remove-unused-encodings.patch b/Hexagon-target-hexagon-remove-unused-encodings.patch new file mode 100644 index 00000000..2857cc36 --- /dev/null +++ b/Hexagon-target-hexagon-remove-unused-encodings.patch @@ -0,0 +1,70 @@ +From 3be03a8e76551f8065fbe75633f9f0ce5200d8e0 Mon Sep 17 00:00:00 2001 +From: liujing +Date: Wed, 18 Sep 2024 19:02:59 +0800 +Subject: [PATCH] Hexagon (target/hexagon) remove unused encodings +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Remove encodings guarded by ifdef that is not defined + +Signed-off-by: Taylor Simpson +Reviewed-by: Philippe Mathieu-Daudé +Signed-off-by: Liu Jing +--- + target/hexagon/imported/encode_pp.def | 23 ----------------------- + 1 file changed, 23 deletions(-) + +diff --git a/target/hexagon/imported/encode_pp.def b/target/hexagon/imported/encode_pp.def +index 939c6fc55f..d71c04cd30 100644 +--- a/target/hexagon/imported/encode_pp.def ++++ b/target/hexagon/imported/encode_pp.def +@@ -944,13 +944,6 @@ MPY_ENC(F2_dfmpyfix, "1000","ddddd","0","0","1","0","11") + MPY_ENC(F2_dfmin, "1000","ddddd","0","0","1","1","11") + MPY_ENC(F2_dfmax, "1000","ddddd","0","1","0","0","11") + MPY_ENC(F2_dfmpyll, "1000","ddddd","0","1","0","1","11") +-#ifdef ADD_DP_OPS +-MPY_ENC(F2_dfdivcheat, "1000","ddddd","0","0","0","1","00") +- +-MPY_ENC(F2_dffixupn, "1000","ddddd","0","1","0","1","11") +-MPY_ENC(F2_dffixupd, "1000","ddddd","0","1","1","0","11") +-MPY_ENC(F2_dfrecipa, "1000","ddddd","0","1","1","1","ee") +-#endif + + MPY_ENC(M7_dcmpyrw, "1000","ddddd","0","0","0","1","10") + MPY_ENC(M7_dcmpyrwc, "1000","ddddd","0","0","1","1","10") +@@ -1024,15 +1017,6 @@ MPY_ENC(M5_vdmacbsu, "1010","xxxxx","0","1","0","0","01") + + MPY_ENC(F2_dfmpylh, "1010","xxxxx","0","0","0","0","11") + MPY_ENC(F2_dfmpyhh, "1010","xxxxx","0","0","0","1","11") +-#ifdef ADD_DP_OPS +-MPY_ENC(F2_dfmpyhh, "1010","xxxxx","0","0","1","0","11") +-MPY_ENC(F2_dffma, "1010","xxxxx","0","0","0","0","11") +-MPY_ENC(F2_dffms, "1010","xxxxx","0","0","0","1","11") +- +-MPY_ENC(F2_dffma_lib, "1010","xxxxx","0","0","1","0","11") +-MPY_ENC(F2_dffms_lib, "1010","xxxxx","0","0","1","1","11") +-MPY_ENC(F2_dffma_sc, "1010","xxxxx","0","1","1","1","uu") +-#endif + + + MPY_ENC(M7_dcmpyrw_acc, "1010","xxxxx","0","0","0","1","10") +@@ -1547,15 +1531,8 @@ SH2_RR_ENC(F2_conv_df2d, "0000","111","0","0 00","ddddd") + SH2_RR_ENC(F2_conv_df2ud, "0000","111","0","0 01","ddddd") + SH2_RR_ENC(F2_conv_ud2df, "0000","111","0","0 10","ddddd") + SH2_RR_ENC(F2_conv_d2df, "0000","111","0","0 11","ddddd") +-#ifdef ADD_DP_OPS +-SH2_RR_ENC(F2_dffixupr, "0000","111","0","1 00","ddddd") +-SH2_RR_ENC(F2_dfsqrtcheat, "0000","111","0","1 01","ddddd") +-#endif + SH2_RR_ENC(F2_conv_df2d_chop, "0000","111","0","1 10","ddddd") + SH2_RR_ENC(F2_conv_df2ud_chop,"0000","111","0","1 11","ddddd") +-#ifdef ADD_DP_OPS +-SH2_RR_ENC(F2_dfinvsqrta, "0000","111","1","0 ee","ddddd") +-#endif + + + +-- +2.41.0.windows.1 + diff --git a/Subject-PATCH-kvm-Use-unsigned-long-for-request-argu.patch b/Subject-PATCH-kvm-Use-unsigned-long-for-request-argu.patch new file mode 100644 index 00000000..325922c4 --- /dev/null +++ b/Subject-PATCH-kvm-Use-unsigned-long-for-request-argu.patch @@ -0,0 +1,189 @@ +From d3dcd2635b1830648a1aa95d5653aba6fd20bde6 Mon Sep 17 00:00:00 2001 +From: dinglimin +Date: Mon, 16 Sep 2024 16:36:27 +0800 +Subject: [PATCH] Subject: [PATCH] kvm: Use 'unsigned long' for request + argument in functions wrapping ioctl() + +Change the data type of the ioctl _request_ argument from 'int' to +'unsigned long' for the various accel/kvm functions which are +essentially wrappers around the ioctl() syscall. + +The correct type for ioctl()'s 'request' argument is confused: + * POSIX defines the request argument as 'int' + * glibc uses 'unsigned long' in the prototype in sys/ioctl.h + * the glibc info documentation uses 'int' + * the Linux manpage uses 'unsigned long' + * the Linux implementation of the syscall uses 'unsigned int' + +If we wrap ioctl() with another function which uses 'int' as the +type for the request argument, then requests with the 0x8000_0000 +bit set will be sign-extended when the 'int' is cast to +'unsigned long' for the call to ioctl(). + +On x86_64 one such example is the KVM_IRQ_LINE_STATUS request. +Bit requests with the _IOC_READ direction bit set, will have the high +bit set. + +Fortunately the Linux Kernel truncates the upper 32bit of the request +on 64bit machines (because it uses 'unsigned int', and see also Linus +Torvalds' comments in + https://sourceware.org/bugzilla/show_bug.cgi?id=14362 ) +so this doesn't cause active problems for us. However it is more +consistent to follow the glibc ioctl() prototype when we define +functions that are essentially wrappers around ioctl(). + +This resolves a Coverity issue where it points out that in +kvm_get_xsave() we assign a value (KVM_GET_XSAVE or KVM_GET_XSAVE2) +to an 'int' variable which can't hold it without overflow. + +Resolves: Coverity CID 1547759 +Signed-off-by: Johannes Stoelp +Signed-off-by: Peter Maydell +Reviewed-by: Eric Blake +Message-id: 20240815122747.3053871-1-peter.maydell@linaro.org +[PMM: Rebased patch, adjusted commit message, included note about + Coverity fix, updated the type of the local var in kvm_get_xsave, + updated the comment in the KVMState struct definition] +Signed-off-by: Peter Maydell +Signed-off-by: dinglimin +--- + accel/kvm/kvm-all.c | 8 ++++---- + accel/kvm/trace-events | 8 ++++---- + include/sysemu/kvm.h | 8 ++++---- + include/sysemu/kvm_int.h | 17 +++++++++++++---- + target/i386/kvm/kvm.c | 3 ++- + 5 files changed, 27 insertions(+), 17 deletions(-) + +diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c +index 3a09307a26..2eb0666bd7 100644 +--- a/accel/kvm/kvm-all.c ++++ b/accel/kvm/kvm-all.c +@@ -2985,7 +2985,7 @@ int kvm_cpu_exec(CPUState *cpu) + return ret; + } + +-int kvm_ioctl(KVMState *s, int type, ...) ++int kvm_ioctl(KVMState *s, unsigned long type, ...) + { + int ret; + void *arg; +@@ -3003,7 +3003,7 @@ int kvm_ioctl(KVMState *s, int type, ...) + return ret; + } + +-int kvm_vm_ioctl(KVMState *s, int type, ...) ++int kvm_vm_ioctl(KVMState *s, unsigned long type, ...) + { + int ret; + void *arg; +@@ -3021,7 +3021,7 @@ int kvm_vm_ioctl(KVMState *s, int type, ...) + return ret; + } + +-int kvm_vcpu_ioctl(CPUState *cpu, int type, ...) ++int kvm_vcpu_ioctl(CPUState *cpu, unsigned long type, ...) + { + int ret; + void *arg; +@@ -3039,7 +3039,7 @@ int kvm_vcpu_ioctl(CPUState *cpu, int type, ...) + return ret; + } + +-int kvm_device_ioctl(int fd, int type, ...) ++int kvm_device_ioctl(int fd, unsigned long type, ...) + { + int ret; + void *arg; +diff --git a/accel/kvm/trace-events b/accel/kvm/trace-events +index 399aaeb0ec..a1905fe985 100644 +--- a/accel/kvm/trace-events ++++ b/accel/kvm/trace-events +@@ -1,11 +1,11 @@ + # See docs/devel/tracing.rst for syntax documentation. + + # kvm-all.c +-kvm_ioctl(int type, void *arg) "type 0x%x, arg %p" +-kvm_vm_ioctl(int type, void *arg) "type 0x%x, arg %p" +-kvm_vcpu_ioctl(int cpu_index, int type, void *arg) "cpu_index %d, type 0x%x, arg %p" ++kvm_ioctl(unsigned long type, void *arg) "type 0x%lx, arg %p" ++kvm_vm_ioctl(unsigned long type, void *arg) "type 0x%lx, arg %p" ++kvm_vcpu_ioctl(int cpu_index, unsigned long type, void *arg) "cpu_index %d, type 0x%lx, arg %p" + kvm_run_exit(int cpu_index, uint32_t reason) "cpu_index %d, reason %d" +-kvm_device_ioctl(int fd, int type, void *arg) "dev fd %d, type 0x%x, arg %p" ++kvm_device_ioctl(int fd, unsigned long type, void *arg) "dev fd %d, type 0x%lx, arg %p" + kvm_failed_reg_get(uint64_t id, const char *msg) "Warning: Unable to retrieve ONEREG %" PRIu64 " from KVM: %s" + kvm_failed_reg_set(uint64_t id, const char *msg) "Warning: Unable to set ONEREG %" PRIu64 " to KVM: %s" + kvm_init_vcpu(int cpu_index, unsigned long arch_cpu_id) "index: %d id: %lu" +diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h +index 5860228034..5c06cd3d91 100644 +--- a/include/sysemu/kvm.h ++++ b/include/sysemu/kvm.h +@@ -258,11 +258,11 @@ int kvm_on_sigbus(int code, void *addr); + + /* internal API */ + +-int kvm_ioctl(KVMState *s, int type, ...); ++int kvm_ioctl(KVMState *s, unsigned long type, ...); + +-int kvm_vm_ioctl(KVMState *s, int type, ...); ++int kvm_vm_ioctl(KVMState *s, unsigned long type, ...); + +-int kvm_vcpu_ioctl(CPUState *cpu, int type, ...); ++int kvm_vcpu_ioctl(CPUState *cpu, unsigned long type, ...); + + /** + * kvm_device_ioctl - call an ioctl on a kvm device +@@ -271,7 +271,7 @@ int kvm_vcpu_ioctl(CPUState *cpu, int type, ...); + * + * Returns: -errno on error, nonnegative on success + */ +-int kvm_device_ioctl(int fd, int type, ...); ++int kvm_device_ioctl(int fd, unsigned long type, ...); + + /** + * kvm_vm_check_attr - check for existence of a specific vm attribute +diff --git a/include/sysemu/kvm_int.h b/include/sysemu/kvm_int.h +index 3b4adcdc10..b332d79ce5 100644 +--- a/include/sysemu/kvm_int.h ++++ b/include/sysemu/kvm_int.h +@@ -83,10 +83,19 @@ struct KVMState + OnOffAuto kernel_irqchip_split; + bool sync_mmu; + uint64_t manual_dirty_log_protect; +- /* The man page (and posix) say ioctl numbers are signed int, but +- * they're not. Linux, glibc and *BSD all treat ioctl numbers as +- * unsigned, and treating them as signed here can break things */ +- unsigned irq_set_ioctl; ++ /* ++ * Older POSIX says that ioctl numbers are signed int, but in ++ * practice they are not. (Newer POSIX doesn't specify ioctl ++ * at all.) Linux, glibc and *BSD all treat ioctl numbers as ++ * unsigned, and real-world ioctl values like KVM_GET_XSAVE have ++ * bit 31 set, which means that passing them via an 'int' will ++ * result in sign-extension when they get converted back to the ++ * 'unsigned long' which the ioctl() prototype uses. Luckily Linux ++ * always treats the argument as an unsigned 32-bit int, so any ++ * possible sign-extension is deliberately ignored, but for ++ * consistency we keep to the same type that glibc is using. ++ */ ++ unsigned long irq_set_ioctl; + unsigned int sigmask_len; + GHashTable *gsimap; + #ifdef KVM_CAP_IRQ_ROUTING +diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c +index 9f3ddd5da2..15755197f4 100644 +--- a/target/i386/kvm/kvm.c ++++ b/target/i386/kvm/kvm.c +@@ -3360,7 +3360,8 @@ static int kvm_get_xsave(X86CPU *cpu) + { + CPUX86State *env = &cpu->env; + void *xsave = env->xsave_buf; +- int type, ret; ++ unsigned long type; ++ int ret; + + if (!has_xsave) { + return kvm_get_fpu(cpu); +-- +2.41.0.windows.1 + diff --git a/bios-tables-test-Make-oem-fields-tests-be-consistent.patch b/bios-tables-test-Make-oem-fields-tests-be-consistent.patch new file mode 100644 index 00000000..5077108f --- /dev/null +++ b/bios-tables-test-Make-oem-fields-tests-be-consistent.patch @@ -0,0 +1,102 @@ +From 2a9e30e5cd8d838a367175a0c1bad0e79764063f Mon Sep 17 00:00:00 2001 +From: liujing +Date: Wed, 18 Sep 2024 15:09:30 +0800 +Subject: [PATCH] bios-tables-test: Make oem-fields tests be consistent +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Every other test function is named: + + test_acpi__() + +Just make this test the same. Once there, rename "acpi/oem-fields" to +"acpi/piix4/oem-fields" so it is consistent with everything else. + +Signed-off-by: Juan Quintela +Message-Id: <20220902173452.1904-2-quintela@redhat.com> +Reviewed-by: Ani Sinha +Reviewed-by: Philippe Mathieu-Daudé +Signed-off-by: Thomas Huth +Signed-off-by: Liu Jing +--- + tests/qtest/bios-tables-test.c | 16 ++++++++-------- + 1 file changed, 8 insertions(+), 8 deletions(-) + +diff --git a/tests/qtest/bios-tables-test.c b/tests/qtest/bios-tables-test.c +index ff8f13199d..0b89cae577 100644 +--- a/tests/qtest/bios-tables-test.c ++++ b/tests/qtest/bios-tables-test.c +@@ -1501,7 +1501,7 @@ static void test_oem_fields(test_data *data) + } + } + +-static void test_acpi_oem_fields_pc(void) ++static void test_acpi_piix4_oem_fields(void) + { + test_data data; + char *args; +@@ -1521,7 +1521,7 @@ static void test_acpi_oem_fields_pc(void) + g_free(args); + } + +-static void test_acpi_oem_fields_q35(void) ++static void test_acpi_q35_oem_fields(void) + { + test_data data; + char *args; +@@ -1541,7 +1541,7 @@ static void test_acpi_oem_fields_q35(void) + g_free(args); + } + +-static void test_acpi_oem_fields_microvm(void) ++static void test_acpi_microvm_oem_fields(void) + { + test_data data; + char *args; +@@ -1558,7 +1558,7 @@ static void test_acpi_oem_fields_microvm(void) + g_free(args); + } + +-static void test_acpi_oem_fields_virt(void) ++static void test_acpi_virt_oem_fields(void) + { + test_data data = { + .machine = "virt", +@@ -1596,13 +1596,13 @@ int main(int argc, char *argv[]) + if (ret) { + return ret; + } +- qtest_add_func("acpi/q35/oem-fields", test_acpi_oem_fields_q35); ++ qtest_add_func("acpi/q35/oem-fields", test_acpi_q35_oem_fields); + if (tpm_model_is_available("-machine q35", "tpm-tis")) { + qtest_add_func("acpi/q35/tpm2-tis", test_acpi_q35_tcg_tpm2_tis); + qtest_add_func("acpi/q35/tpm12-tis", test_acpi_q35_tcg_tpm12_tis); + } + qtest_add_func("acpi/piix4", test_acpi_piix4_tcg); +- qtest_add_func("acpi/oem-fields", test_acpi_oem_fields_pc); ++ qtest_add_func("acpi/piix4/oem-fields", test_acpi_piix4_oem_fields); + qtest_add_func("acpi/piix4/bridge", test_acpi_piix4_tcg_bridge); + qtest_add_func("acpi/piix4/pci-hotplug/no_root_hotplug", + test_acpi_piix4_no_root_hotplug); +@@ -1642,7 +1642,7 @@ int main(int argc, char *argv[]) + qtest_add_func("acpi/microvm/usb", test_acpi_microvm_usb_tcg); + qtest_add_func("acpi/microvm/rtc", test_acpi_microvm_rtc_tcg); + qtest_add_func("acpi/microvm/ioapic2", test_acpi_microvm_ioapic2_tcg); +- qtest_add_func("acpi/microvm/oem-fields", test_acpi_oem_fields_microvm); ++ qtest_add_func("acpi/microvm/oem-fields", test_acpi_microvm_oem_fields); + if (has_tcg) { + qtest_add_func("acpi/q35/ivrs", test_acpi_q35_tcg_ivrs); + if (strcmp(arch, "x86_64") == 0) { +@@ -1660,7 +1660,7 @@ int main(int argc, char *argv[]) + qtest_add_func("acpi/virt/numamem", test_acpi_virt_tcg_numamem); + qtest_add_func("acpi/virt/memhp", test_acpi_virt_tcg_memhp); + qtest_add_func("acpi/virt/pxb", test_acpi_virt_tcg_pxb); +- qtest_add_func("acpi/virt/oem-fields", test_acpi_oem_fields_virt); ++ qtest_add_func("acpi/virt/oem-fields", test_acpi_virt_oem_fields); + } + } + ret = g_test_run(); +-- +2.41.0.windows.1 + diff --git a/configure-Symlink-binaries-using-.exe-suffix-with-Mi.patch b/configure-Symlink-binaries-using-.exe-suffix-with-Mi.patch new file mode 100644 index 00000000..ec1fc52b --- /dev/null +++ b/configure-Symlink-binaries-using-.exe-suffix-with-Mi.patch @@ -0,0 +1,40 @@ +From c66c944a2caf4a457d542c843e5215bd7d673887 Mon Sep 17 00:00:00 2001 +From: Luo Yifan +Date: Thu, 26 Sep 2024 10:28:30 +0800 +Subject: [PATCH] configure: Symlink binaries using .exe suffix with MinGW +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +cherry picked from commit 57a93f16e8dad554720edcc5ed1fe613d68bf230 + +When using the MinGW toolchain, we use the .exe suffix for the +executable name. We also need to use it for the symlinks in the +build directory. + +Signed-off-by: Philippe Mathieu-Daudé +Reviewed-by: Stefan Weil +Acked-by: Paolo Bonzini +Message-Id: <20211109144504.1541206-1-philmd@redhat.com> +Signed-off-by: Laurent Vivier +Signed-off-by: Luo Yifan +--- + configure | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/configure b/configure +index 991fe67886..7d508b2e72 100755 +--- a/configure ++++ b/configure +@@ -3685,7 +3685,7 @@ fi + + for target in $target_list; do + target_dir="$target" +- target_name=$(echo $target | cut -d '-' -f 1) ++ target_name=$(echo $target | cut -d '-' -f 1)$EXESUF + mkdir -p "$target_dir" + case $target in + *-user) symlink "../qemu-$target_name" "$target_dir/qemu-$target_name" ;; +-- +2.41.0.windows.1 + diff --git a/hw-avr-Realize-AVRCPU-qdev-object-using-qdev_realize.patch b/hw-avr-Realize-AVRCPU-qdev-object-using-qdev_realize.patch new file mode 100644 index 00000000..65641d37 --- /dev/null +++ b/hw-avr-Realize-AVRCPU-qdev-object-using-qdev_realize.patch @@ -0,0 +1,39 @@ +From 21d4f71e7ad312a86b83cfa7dc9eb5bf6ef240ee Mon Sep 17 00:00:00 2001 +From: Luo Yifan +Date: Thu, 26 Sep 2024 10:48:54 +0800 +Subject: [PATCH] hw/avr: Realize AVRCPU qdev object using qdev_realize() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +cherry picked from commit 74fb2f4f4c47c966ab54687392e6561b4de4bb8a + +TYPE_AVR_CPU inherits TYPE_CPU, which itself inherits TYPE_DEVICE. +TYPE_DEVICE instances are realized using qdev_realize(), we don't +need to access QOM internal values. + +Signed-off-by: Philippe Mathieu-Daudé +Reviewed-by: Michael Rolnik +Message-Id: <20211205224109.322152-1-f4bug@amsat.org> +Signed-off-by: Laurent Vivier +Signed-off-by: Luo Yifan +--- + hw/avr/atmega.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/hw/avr/atmega.c b/hw/avr/atmega.c +index 0608e2d475..a34803e642 100644 +--- a/hw/avr/atmega.c ++++ b/hw/avr/atmega.c +@@ -233,7 +233,7 @@ static void atmega_realize(DeviceState *dev, Error **errp) + + /* CPU */ + object_initialize_child(OBJECT(dev), "cpu", &s->cpu, mc->cpu_type); +- object_property_set_bool(OBJECT(&s->cpu), "realized", true, &error_abort); ++ qdev_realize(DEVICE(&s->cpu), NULL, &error_abort); + cpudev = DEVICE(&s->cpu); + + /* SRAM */ +-- +2.41.0.windows.1 + diff --git a/hw-i386-vmmouse-Require-i8042-property-to-be-set.patch b/hw-i386-vmmouse-Require-i8042-property-to-be-set.patch new file mode 100644 index 00000000..3e779ae8 --- /dev/null +++ b/hw-i386-vmmouse-Require-i8042-property-to-be-set.patch @@ -0,0 +1,48 @@ +From 12756f09bddf7e31b9bf846bd5301ddbdcadfedf Mon Sep 17 00:00:00 2001 +From: Luo Yifan +Date: Thu, 26 Sep 2024 11:15:58 +0800 +Subject: [PATCH] hw/i386/vmmouse: Require 'i8042' property to be set +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +cherry picked from commit 5a3a2eb3b1096a52580c1b8c3eb0739714e7d941 + +If the 'i8042' property is not set, mouse events handled by +vmmouse_mouse_event() end calling i8042_isa_mouse_fake_event() +with a NULL argument, resulting in ps2_mouse_fake_event() being +called with invalid PS2MouseState pointer. Fix by requiring +the 'i8042' property to be always set: + + $ qemu-system-x86_64 -device vmmouse + qemu-system-x86_64: -device vmmouse: 'i8042' link is not set + +Fixes: 91c9e09147b ("vmmouse: convert to qdev") +Reported-by: Calvin Buckley +Resolves: https://gitlab.com/qemu-project/qemu/-/issues/752 +Signed-off-by: Philippe Mathieu-Daudé +Message-Id: <20211201223253.36080-1-f4bug@amsat.org> +Signed-off-by: Paolo Bonzini +Signed-off-by: Luo Yifan +--- + hw/i386/vmmouse.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/hw/i386/vmmouse.c b/hw/i386/vmmouse.c +index 3d66368286..a56c185f15 100644 +--- a/hw/i386/vmmouse.c ++++ b/hw/i386/vmmouse.c +@@ -286,6 +286,10 @@ static void vmmouse_realizefn(DeviceState *dev, Error **errp) + + DPRINTF("vmmouse_init\n"); + ++ if (!s->i8042) { ++ error_setg(errp, "'i8042' link is not set"); ++ return; ++ } + if (!object_resolve_path_type("", TYPE_VMPORT, NULL)) { + error_setg(errp, "vmmouse needs a machine with vmport"); + return; +-- +2.41.0.windows.1 + diff --git a/hw-scsi-megasas-Fails-command-if-SGL-buffer-overflow.patch b/hw-scsi-megasas-Fails-command-if-SGL-buffer-overflow.patch new file mode 100644 index 00000000..2d0bd85f --- /dev/null +++ b/hw-scsi-megasas-Fails-command-if-SGL-buffer-overflow.patch @@ -0,0 +1,40 @@ +From 4524c893498ef2c8d2fa5da69ccefe167011ed3d Mon Sep 17 00:00:00 2001 +From: Luo Yifan +Date: Thu, 26 Sep 2024 10:52:25 +0800 +Subject: [PATCH] hw/scsi/megasas: Fails command if SGL buffer overflows +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +cherry picked from commit 97a2b074d150918a7a3a4065b946a52d4d0be8a3 + +If we detect an overflow on the SGL buffer, do not +keep processing the command: discard it. TARGET_FAILURE +sense code will be returned (MFI_STAT_SCSI_DONE_WITH_ERROR). + +Reported-by: Alexander Bulekov +Resolves: https://gitlab.com/qemu-project/qemu/-/issues/521 +Signed-off-by: Philippe Mathieu-Daudé +Reviewed-by: Darren Kenny +Message-Id: <20211119201141.532377-2-philmd@redhat.com> +Signed-off-by: Paolo Bonzini +Signed-off-by: Luo Yifan +--- + hw/scsi/megasas.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/hw/scsi/megasas.c b/hw/scsi/megasas.c +index 946050bf83..dc9bbdb740 100644 +--- a/hw/scsi/megasas.c ++++ b/hw/scsi/megasas.c +@@ -310,6 +310,7 @@ static int megasas_map_sgl(MegasasState *s, MegasasCmd *cmd, union mfi_sgl *sgl) + } + if (cmd->iov_size > iov_size) { + trace_megasas_iovec_overflow(cmd->index, iov_size, cmd->iov_size); ++ goto unmap; + } else if (cmd->iov_size < iov_size) { + trace_megasas_iovec_underflow(cmd->index, iov_size, cmd->iov_size); + } +-- +2.41.0.windows.1 + diff --git a/io-channel-websock-Replace-strlen-const_str-by-sizeo.patch b/io-channel-websock-Replace-strlen-const_str-by-sizeo.patch new file mode 100644 index 00000000..3fb964fe --- /dev/null +++ b/io-channel-websock-Replace-strlen-const_str-by-sizeo.patch @@ -0,0 +1,46 @@ +From f9d4fad347970ddff4252312a71565a3f0be5305 Mon Sep 17 00:00:00 2001 +From: tangbinzy +Date: Thu, 19 Sep 2024 10:00:08 +0000 +Subject: [PATCH] io/channel-websock: Replace strlen(const_str) by + sizeof(const_str) - 1 mainline inclusion commit + 5e689840a10e01dc2ab87defc5347337db8103da category: bugfix +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +--------------------------------------------------------------- + +he combined_key[... QIO_CHANNEL_WEBSOCK_GUID_LEN ...] array in +qio_channel_websock_handshake_send_res_ok() expands to a call +to strlen(QIO_CHANNEL_WEBSOCK_GUID), and the compiler doesn't +realize the string is const, so consider combined_key[] being +a variable-length array. + +To remove the variable-length array, we provide it a hint to +the compiler by using sizeof() - 1 instead of strlen(). + +Signed-off-by: Philippe Mathieu-Daudé +Reviewed-by: Daniel P. Berrangé +Signed-off-by: Peter Maydell + +Signed-off-by: tangbinzy +--- + io/channel-websock.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/io/channel-websock.c b/io/channel-websock.c +index 70889bb54d..d9fc27a003 100644 +--- a/io/channel-websock.c ++++ b/io/channel-websock.c +@@ -32,7 +32,7 @@ + + #define QIO_CHANNEL_WEBSOCK_CLIENT_KEY_LEN 24 + #define QIO_CHANNEL_WEBSOCK_GUID "258EAFA5-E914-47DA-95CA-C5AB0DC85B11" +-#define QIO_CHANNEL_WEBSOCK_GUID_LEN strlen(QIO_CHANNEL_WEBSOCK_GUID) ++#define QIO_CHANNEL_WEBSOCK_GUID_LEN (sizeof(QIO_CHANNEL_WEBSOCK_GUID) - 1) + + #define QIO_CHANNEL_WEBSOCK_HEADER_PROTOCOL "sec-websocket-protocol" + #define QIO_CHANNEL_WEBSOCK_HEADER_VERSION "sec-websocket-version" +-- +2.41.0.windows.1 + diff --git a/monitor-hmp-cmds-Avoid-displaying-bogus-size-in-info.patch b/monitor-hmp-cmds-Avoid-displaying-bogus-size-in-info.patch new file mode 100644 index 00000000..d15370bb --- /dev/null +++ b/monitor-hmp-cmds-Avoid-displaying-bogus-size-in-info.patch @@ -0,0 +1,97 @@ +From 0ccf41541a2c2a65196327fc5466af611aa9f929 Mon Sep 17 00:00:00 2001 +From: dinglimin +Date: Mon, 16 Sep 2024 17:07:55 +0800 +Subject: [PATCH] monitor/hmp-cmds: Avoid displaying bogus size in 'info pci' + When BAR aren't mapped, we get: +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + + (qemu) info pci + Bus 0, device 0, function 0: + Host bridge: PCI device dead:beef + ... + BAR4: 32 bit memory at 0xffffffffffffffff [0x00000ffe]. + BAR5: I/O at 0xffffffffffffffff [0x0ffe]. + +Check the BAR is mapped comparing its address to PCI_BAR_UNMAPPED +which is what the PCI layer uses for unmapped BARs. +See pci_bar_address and pci_update_mappings implementations and +in "hw/pci/pci.h": + + typedef struct PCIIORegion { + pcibus_t addr; /* current PCI mapping address. -1 means not mapped */ + #define PCI_BAR_UNMAPPED (~(pcibus_t)0) + ... + +This improves the logging, not displaying bogus sizes: + + (qemu) info pci + Bus 0, device 0, function 0: + Host bridge: PCI device dead:beef + ... + BAR4: 32 bit memory (not mapped) + BAR5: I/O (not mapped) + +Remove trailing dot which is not used in other commands format. + +Signed-off-by: Philippe Mathieu-Daudé +Message-Id: <20240801131449.51328-1-philmd@linaro.org> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Signed-off-by: dinglimin +--- + monitor/hmp-cmds.c | 30 +++++++++++++++++++++--------- + 1 file changed, 21 insertions(+), 9 deletions(-) + +diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c +index c139e8087e..4abd4a8aa0 100644 +--- a/monitor/hmp-cmds.c ++++ b/monitor/hmp-cmds.c +@@ -60,6 +60,8 @@ + #include + #endif + ++#include "hw/pci/pci.h" ++ + bool hmp_handle_error(Monitor *mon, Error *err) + { + if (err) { +@@ -781,15 +783,25 @@ static void hmp_info_pci_device(Monitor *mon, const PciDeviceInfo *dev) + monitor_printf(mon, " BAR%" PRId64 ": ", region->value->bar); + + if (!strcmp(region->value->type, "io")) { +- monitor_printf(mon, "I/O at 0x%04" PRIx64 +- " [0x%04" PRIx64 "].\n", +- addr, addr + size - 1); +- } else { +- monitor_printf(mon, "%d bit%s memory at 0x%08" PRIx64 +- " [0x%08" PRIx64 "].\n", +- region->value->mem_type_64 ? 64 : 32, +- region->value->prefetch ? " prefetchable" : "", +- addr, addr + size - 1); ++ if (addr != PCI_BAR_UNMAPPED) { ++ monitor_printf(mon, "I/O at 0x%04" PRIx64 ++ " [0x%04" PRIx64 "]\n", ++ addr, addr + size - 1); ++ } else { ++ monitor_printf(mon, "I/O (not mapped)\n"); ++ } ++ } else { ++ if (addr != PCI_BAR_UNMAPPED) { ++ monitor_printf(mon, "%d bit%s memory at 0x%08" PRIx64 ++ " [0x%08" PRIx64 "]\n", ++ region->value->mem_type_64 ? 64 : 32, ++ region->value->prefetch ? " prefetchable" : "", ++ addr, addr + size - 1); ++ } else { ++ monitor_printf(mon, "%d bit%s memory (not mapped)\n", ++ region->value->mem_type_64 ? 64 : 32, ++ region->value->prefetch ? " prefetchable" : ""); ++ } + } + } + +-- +2.41.0.windows.1 + diff --git a/python-aqmp-use-absolute-import-statement.patch b/python-aqmp-use-absolute-import-statement.patch new file mode 100644 index 00000000..cfff60ac --- /dev/null +++ b/python-aqmp-use-absolute-import-statement.patch @@ -0,0 +1,41 @@ +From 81ab64fe4c328b3981290afe4860f9bcd8f8750c Mon Sep 17 00:00:00 2001 +From: Luo Yifan +Date: Thu, 26 Sep 2024 16:07:19 +0800 +Subject: [PATCH] python/aqmp: use absolute import statement + +cherry picked from commit f75b20e4f16663af4c65657821c5727b1d1c2493 + +pylint's dependency astroid appears to have bugs in 2.9.1 and 2.9.2 (Dec +31 and Jan 3) that appear to erroneously expect the qemu namespace to +have an __init__.py file. astroid 2.9.3 (Jan 9) avoids that problem, but +appears to not understand a relative import within a namespace package. + +Update the relative import - it was worth changing anyway, because these +packages will eventually be packaged and distributed separately. + +Signed-off-by: John Snow +Reviewed-by: Beraldo Leal +Message-id: 20220110191349.1841027-2-jsnow@redhat.com +Signed-off-by: John Snow +Signed-off-by: Luo Yifan +--- + python/qemu/aqmp/aqmp_tui.py | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/python/qemu/aqmp/aqmp_tui.py b/python/qemu/aqmp/aqmp_tui.py +index a2929f771c..f1e926dd75 100644 +--- a/python/qemu/aqmp/aqmp_tui.py ++++ b/python/qemu/aqmp/aqmp_tui.py +@@ -35,7 +35,8 @@ + import urwid + import urwid_readline + +-from ..qmp import QEMUMonitorProtocol, QMPBadPortError ++from qemu.qmp import QEMUMonitorProtocol, QMPBadPortError ++ + from .error import ProtocolError + from .message import DeserializationError, Message, UnexpectedTypeError + from .protocol import ConnectError, Runstate +-- +2.41.0.windows.1 + diff --git a/qemu-keymap-Add-license-in-generated-files.patch b/qemu-keymap-Add-license-in-generated-files.patch new file mode 100644 index 00000000..bdbd34c2 --- /dev/null +++ b/qemu-keymap-Add-license-in-generated-files.patch @@ -0,0 +1,34 @@ +From db089183c5aff11b3dae7d3893477c8abbb8d863 Mon Sep 17 00:00:00 2001 +From: Luo Yifan +Date: Thu, 26 Sep 2024 10:44:55 +0800 +Subject: [PATCH] qemu-keymap: Add license in generated files +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +cherry picked from commit 4455922f7bb8fef2f5aa0a4d3901041bcc4b659d + +Signed-off-by: Philippe Mathieu-Daudé +Reviewed-by: Warner Losh +Message-Id: <20211117174533.1900570-1-philmd@redhat.com> +Signed-off-by: Laurent Vivier +Signed-off-by: Luo Yifan +--- + qemu-keymap.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/qemu-keymap.c b/qemu-keymap.c +index 536e8f2385..4095b654a6 100644 +--- a/qemu-keymap.c ++++ b/qemu-keymap.c +@@ -187,6 +187,7 @@ int main(int argc, char *argv[]) + } + + fprintf(outfile, ++ "# SPDX-License-Identifier: GPL-2.0-or-later\n" + "#\n" + "# generated by qemu-keymap\n" + "# model : %s\n" +-- +2.41.0.windows.1 + diff --git a/qemu.spec b/qemu.spec index 417538f3..07c8cda9 100644 --- a/qemu.spec +++ b/qemu.spec @@ -3,7 +3,7 @@ Name: qemu Version: 6.2.0 -Release: 100 +Release: 101 Epoch: 10 Summary: QEMU is a generic and open source machine emulator and virtualizer License: GPLv2 and BSD and MIT and CC-BY-SA-4.0 @@ -1048,7 +1048,28 @@ Patch1033: system-physmem-Propagate-AddressSpace-to-MapClient-h.patch Patch1034: system-physmem-Per-AddressSpace-bounce-buffering.patch Patch1035: softmmu-Support-concurrent-bounce-buffers-CVE-2024-8.patch Patch1036: mac_dbdma-Remove-leftover-dma_memory_unmap-calls-CVE.patch - +Patch1037: Subject-PATCH-kvm-Use-unsigned-long-for-request-argu.patch +Patch1038: virtio-mem-don-t-warn-about-THP-sizes-on-a-kernel-wi.patch +Patch1039: monitor-hmp-cmds-Avoid-displaying-bogus-size-in-info.patch +Patch1040: tests-vm-update-NetBSD-to-9.3.patch +Patch1041: bios-tables-test-Make-oem-fields-tests-be-consistent.patch +Patch1042: target-i386-correctly-mask-SSE4a-bit-indices-in-regi.patch +Patch1043: target-i386-REPZ-and-REPNZ-are-mutually-exclusive.patch +Patch1044: target-i386-introduce-insn_get_addr.patch +Patch1045: Hexagon-target-hexagon-remove-unused-encodings.patch +Patch1046: tests-Fix-error-strings.patch +Patch1047: target-ppc-Add-HASHKEYR-and-HASHPKEYR-SPRs.patch +Patch1048: io-channel-websock-Replace-strlen-const_str-by-sizeo.patch +Patch1049: ui-remove-break-after-g_assert_not_reached.patch +Patch1050: configure-Symlink-binaries-using-.exe-suffix-with-Mi.patch +Patch1051: qemu-keymap-Add-license-in-generated-files.patch +Patch1052: hw-avr-Realize-AVRCPU-qdev-object-using-qdev_realize.patch +Patch1053: target-i386-kvm-Replace-use-of-__u32-type.patch +Patch1054: hw-scsi-megasas-Fails-command-if-SGL-buffer-overflow.patch +Patch1055: hw-i386-vmmouse-Require-i8042-property-to-be-set.patch +Patch1056: vhost-backend-avoid-overflow-on-memslots_limit.patch +Patch1057: sysemu-Cleanup-qemu_run_machine_init_done_notifiers.patch +Patch1058: python-aqmp-use-absolute-import-statement.patch BuildRequires: flex BuildRequires: gcc @@ -1647,6 +1668,30 @@ getent passwd qemu >/dev/null || \ %endif %changelog +* Mon Oct 21 2024 - 10:6.2.0-101 +- python/aqmp: use absolute import statement +- sysemu: Cleanup qemu_run_machine_init_done_notifiers() +- vhost-backend: avoid overflow on memslots_limit +- hw/i386/vmmouse: Require 'i8042' property to be set +- hw/scsi/megasas: Fails command if SGL buffer overflows +- target/i386/kvm: Replace use of __u32 type +- hw/avr: Realize AVRCPU qdev object using qdev_realize() +- qemu-keymap: Add license in generated files +- configure: Symlink binaries using .exe suffix with MinGW +- ui: remove break after g_assert_not_reached() +- io/channel-websock: Replace strlen(const_str) by sizeof(const_str) - 1 +- target/ppc: Add HASHKEYR and HASHPKEYR SPRs +- tests: Fix error strings +- Hexagon (target/hexagon) remove unused encodings +- target/i386: introduce insn_get_addr +- target/i386: REPZ and REPNZ are mutually exclusive +- target/i386: correctly mask SSE4a bit indices in register operands +- bios-tables-test: Make oem-fields tests be consistent +- tests/vm: update NetBSD to 9.3 +- monitor/hmp-cmds: Avoid displaying bogus size in 'info pci' When BAR aren't mapped, we get: +- virtio-mem: don't warn about THP sizes on a kernel without THP Support +- Subject: [PATCH] kvm: Use 'unsigned long' for request argument in functions wrapping ioctl() + * Mon Oct 14 2024 - 10:6.2.0-100 - mac_dbdma: Remove leftover `dma_memory_unmap` calls(CVE-2024-8612) - softmmu: Support concurrent bounce buffers(CVE-2024-8612) diff --git a/sysemu-Cleanup-qemu_run_machine_init_done_notifiers.patch b/sysemu-Cleanup-qemu_run_machine_init_done_notifiers.patch new file mode 100644 index 00000000..c949936d --- /dev/null +++ b/sysemu-Cleanup-qemu_run_machine_init_done_notifiers.patch @@ -0,0 +1,38 @@ +From f9cd46b75aa937498b956cb32aef9232bef86cc9 Mon Sep 17 00:00:00 2001 +From: Luo Yifan +Date: Thu, 26 Sep 2024 14:12:57 +0800 +Subject: [PATCH] sysemu: Cleanup qemu_run_machine_init_done_notifiers() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +cherry picked from commit 9de225a1c27500c2d80a916d1c2a41d8e2a5f6e8 + +Remove qemu_run_machine_init_done_notifiers() since no implementation +and user. + +Fixes: f66dc8737c9 ("vl: move all generic initialization out of vl.c") +Signed-off-by: Xiaoyao Li +Reviewed-by: Philippe Mathieu-Daudé +Message-Id: <20220104024136.1433545-1-xiaoyao.li@intel.com> +Signed-off-by: Richard Henderson +Signed-off-by: Luo Yifan +--- + include/sysemu/sysemu.h | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h +index 8fae667172..b9421e03ff 100644 +--- a/include/sysemu/sysemu.h ++++ b/include/sysemu/sysemu.h +@@ -16,7 +16,6 @@ extern bool qemu_uuid_set; + void qemu_add_exit_notifier(Notifier *notify); + void qemu_remove_exit_notifier(Notifier *notify); + +-void qemu_run_machine_init_done_notifiers(void); + void qemu_add_machine_init_done_notifier(Notifier *notify); + void qemu_remove_machine_init_done_notifier(Notifier *notify); + +-- +2.41.0.windows.1 + diff --git a/target-i386-REPZ-and-REPNZ-are-mutually-exclusive.patch b/target-i386-REPZ-and-REPNZ-are-mutually-exclusive.patch new file mode 100644 index 00000000..28598516 --- /dev/null +++ b/target-i386-REPZ-and-REPNZ-are-mutually-exclusive.patch @@ -0,0 +1,33 @@ +From 216483f975d268d1bba93e5a44c06b080f515a97 Mon Sep 17 00:00:00 2001 +From: liujing +Date: Wed, 18 Sep 2024 16:58:59 +0800 +Subject: [PATCH] target/i386: REPZ and REPNZ are mutually exclusive + +The later prefix wins if both are present, make it show in s->prefix too. + +Reviewed-by: Richard Henderson +Signed-off-by: Paolo Bonzini +Signed-off-by: Liu Jing +--- + target/i386/tcg/translate.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c +index 82f77b52fb..0b035df68e 100644 +--- a/target/i386/tcg/translate.c ++++ b/target/i386/tcg/translate.c +@@ -4587,9 +4587,11 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) + switch (b) { + case 0xf3: + prefixes |= PREFIX_REPZ; ++ prefixes &= ~PREFIX_REPNZ; + goto next_byte; + case 0xf2: + prefixes |= PREFIX_REPNZ; ++ prefixes &= ~PREFIX_REPZ; + goto next_byte; + case 0xf0: + prefixes |= PREFIX_LOCK; +-- +2.41.0.windows.1 + diff --git a/target-i386-correctly-mask-SSE4a-bit-indices-in-regi.patch b/target-i386-correctly-mask-SSE4a-bit-indices-in-regi.patch new file mode 100644 index 00000000..b85eb7c6 --- /dev/null +++ b/target-i386-correctly-mask-SSE4a-bit-indices-in-regi.patch @@ -0,0 +1,43 @@ +From 4d18374e62d3206d564d9a6a7154e7eb4b48ecb2 Mon Sep 17 00:00:00 2001 +From: liujing +Date: Wed, 18 Sep 2024 16:44:18 +0800 +Subject: [PATCH] target/i386: correctly mask SSE4a bit indices in register + operands + +SSE4a instructions EXTRQ and INSERTQ have two bit index operands, that can be +immediates or taken from an XMM register. In both cases, the fields are +6-bit wide and the top two bits in the byte are ignored. translate.c is +doing that correctly for the immediate case, but not for the XMM case, so +fix it. + +Signed-off-by: Paolo Bonzini +Signed-off-by: Liu Jing +--- + target/i386/ops_sse.h | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/target/i386/ops_sse.h b/target/i386/ops_sse.h +index 6f1fc174b3..898b7e4292 100644 +--- a/target/i386/ops_sse.h ++++ b/target/i386/ops_sse.h +@@ -899,7 +899,7 @@ static inline uint64_t helper_extrq(uint64_t src, int shift, int len) + + void helper_extrq_r(CPUX86State *env, ZMMReg *d, ZMMReg *s) + { +- d->ZMM_Q(0) = helper_extrq(d->ZMM_Q(0), s->ZMM_B(1), s->ZMM_B(0)); ++ d->ZMM_Q(0) = helper_extrq(d->ZMM_Q(0), s->ZMM_B(1) & 63, s->ZMM_B(0) & 63); + } + + void helper_extrq_i(CPUX86State *env, ZMMReg *d, int index, int length) +@@ -921,7 +921,7 @@ static inline uint64_t helper_insertq(uint64_t src, int shift, int len) + + void helper_insertq_r(CPUX86State *env, ZMMReg *d, ZMMReg *s) + { +- d->ZMM_Q(0) = helper_insertq(s->ZMM_Q(0), s->ZMM_B(9), s->ZMM_B(8)); ++ d->ZMM_Q(0) = helper_insertq(s->ZMM_Q(0), s->ZMM_B(9) & 63, s->ZMM_B(8) & 63); + } + + void helper_insertq_i(CPUX86State *env, ZMMReg *d, int index, int length) +-- +2.41.0.windows.1 + diff --git a/target-i386-introduce-insn_get_addr.patch b/target-i386-introduce-insn_get_addr.patch new file mode 100644 index 00000000..5d1aec7b --- /dev/null +++ b/target-i386-introduce-insn_get_addr.patch @@ -0,0 +1,73 @@ +From 45e03e38593db8583788a53f08735199f203a370 Mon Sep 17 00:00:00 2001 +From: liujing +Date: Wed, 18 Sep 2024 17:54:50 +0800 +Subject: [PATCH] target/i386: introduce insn_get_addr + +The "O" operand type in the Intel SDM needs to load an 8- to 64-bit +unsigned value, while insn_get is limited to 32 bits. Extract the code +out of disas_insn and into a separate function. + +Reviewed-by: Richard Henderson +Signed-off-by: Paolo Bonzini +Signed-off-by: Liu Jing +--- + target/i386/tcg/translate.c | 36 ++++++++++++++++++++++++++---------- + 1 file changed, 26 insertions(+), 10 deletions(-) + +diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c +index 82f77b52fb..44cea102eb 100644 +--- a/target/i386/tcg/translate.c ++++ b/target/i386/tcg/translate.c +@@ -2282,6 +2282,31 @@ static void gen_ldst_modrm(CPUX86State *env, DisasContext *s, int modrm, + } + } + ++static target_ulong insn_get_addr(CPUX86State *env, DisasContext *s, MemOp ot) ++{ ++ target_ulong ret; ++ ++ switch (ot) { ++ case MO_8: ++ ret = x86_ldub_code(env, s); ++ break; ++ case MO_16: ++ ret = x86_lduw_code(env, s); ++ break; ++ case MO_32: ++ ret = x86_ldl_code(env, s); ++ break; ++#ifdef TARGET_X86_64 ++ case MO_64: ++ ret = x86_ldq_code(env, s); ++ break; ++#endif ++ default: ++ g_assert_not_reached(); ++ } ++ return ret; ++} ++ + static inline uint32_t insn_get(CPUX86State *env, DisasContext *s, MemOp ot) + { + uint32_t ret; +@@ -5703,16 +5728,7 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) + target_ulong offset_addr; + + ot = mo_b_d(b, dflag); +- switch (s->aflag) { +-#ifdef TARGET_X86_64 +- case MO_64: +- offset_addr = x86_ldq_code(env, s); +- break; +-#endif +- default: +- offset_addr = insn_get(env, s, s->aflag); +- break; +- } ++ offset_addr = insn_get_addr(env, s, s->aflag); + tcg_gen_movi_tl(s->A0, offset_addr); + gen_add_A0_ds_seg(s); + if ((b & 2) == 0) { +-- +2.41.0.windows.1 + diff --git a/target-i386-kvm-Replace-use-of-__u32-type.patch b/target-i386-kvm-Replace-use-of-__u32-type.patch new file mode 100644 index 00000000..2a964007 --- /dev/null +++ b/target-i386-kvm-Replace-use-of-__u32-type.patch @@ -0,0 +1,38 @@ +From 91ffc3ebae439ac3de19a5f494e9319101e6d532 Mon Sep 17 00:00:00 2001 +From: Luo Yifan +Date: Thu, 26 Sep 2024 10:40:33 +0800 +Subject: [PATCH] target/i386/kvm: Replace use of __u32 type +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +cherry picked from commit dc7d6cafce8a7d36d2ebc03be3b6162e0eb98c22 + +QEMU coding style mandates to not use Linux kernel internal +types for scalars types. Replace __u32 by uint32_t. + +Signed-off-by: Philippe Mathieu-Daudé +Reviewed-by: Richard Henderson +Message-Id: <20211116193955.2793171-1-philmd@redhat.com> +Signed-off-by: Laurent Vivier +Signed-off-by: Luo Yifan +--- + target/i386/kvm/kvm.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c +index 15755197f4..1c019f2f98 100644 +--- a/target/i386/kvm/kvm.c ++++ b/target/i386/kvm/kvm.c +@@ -1452,7 +1452,7 @@ static int hyperv_fill_cpuids(CPUState *cs, + c->edx = cpu->hyperv_limits[2]; + + if (hyperv_feat_enabled(cpu, HYPERV_FEAT_EVMCS)) { +- __u32 function; ++ uint32_t function; + + /* Create zeroed 0x40000006..0x40000009 leaves */ + for (function = HV_CPUID_IMPLEMENT_LIMITS + 1; +-- +2.41.0.windows.1 + diff --git a/target-ppc-Add-HASHKEYR-and-HASHPKEYR-SPRs.patch b/target-ppc-Add-HASHKEYR-and-HASHPKEYR-SPRs.patch new file mode 100644 index 00000000..50910441 --- /dev/null +++ b/target-ppc-Add-HASHKEYR-and-HASHPKEYR-SPRs.patch @@ -0,0 +1,89 @@ +From c7a2780e7e3ff001d3651c20767011d1f5bfbfd5 Mon Sep 17 00:00:00 2001 +From: liujing +Date: Thu, 19 Sep 2024 10:14:22 +0800 +Subject: [PATCH] target/ppc: Add HASHKEYR and HASHPKEYR SPRs +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Add the Special Purpose Registers HASHKEYR and HASHPKEYR, which were +introduced by the Power ISA 3.1B. They are used by the new instructions +hashchk(p) and hashst(p). + +The ISA states that the Operating System should generate the value for +these registers when creating a process, so it's its responsability to +do so. We initialize it with 0 for qemu-softmmu, and set a random 64 +bits value for linux-user. + +Signed-off-by: Víctor Colombo +Reviewed-by: Lucas Mateus Castro +Message-Id: <20220715205439.161110-2-victor.colombo@eldorado.org.br> +Signed-off-by: Daniel Henrique Barboza +Signed-off-by: Liu Jing +--- + target/ppc/cpu.h | 2 ++ + target/ppc/cpu_init.c | 28 ++++++++++++++++++++++++++++ + 2 files changed, 30 insertions(+) + +diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h +index 8b214b2cc1..1281323c02 100644 +--- a/target/ppc/cpu.h ++++ b/target/ppc/cpu.h +@@ -1623,6 +1623,8 @@ typedef PowerPCCPU ArchCPU; + #define SPR_BOOKE_GIVOR14 (0x1BD) + #define SPR_TIR (0x1BE) + #define SPR_PTCR (0x1D0) ++#define SPR_HASHKEYR (0x1D4) ++#define SPR_HASHPKEYR (0x1D5) + #define SPR_BOOKE_SPEFSCR (0x200) + #define SPR_Exxx_BBEAR (0x201) + #define SPR_Exxx_BBTAR (0x202) +diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c +index a220d0dc51..211759508f 100644 +--- a/target/ppc/cpu_init.c ++++ b/target/ppc/cpu_init.c +@@ -2098,6 +2098,33 @@ static void register_8xx_sprs(CPUPPCState *env) + 0x00000000); + } + ++static void register_power10_hash_sprs(CPUPPCState *env) ++{ ++ /* ++ * it's the OS responsability to generate a random value for the registers ++ * in each process' context. So, initialize it with 0 here. ++ */ ++ uint64_t hashkeyr_initial_value = 0, hashpkeyr_initial_value = 0; ++#if defined(CONFIG_USER_ONLY) ++ /* in linux-user, setup the hash register with a random value */ ++ GRand *rand = g_rand_new(); ++ hashkeyr_initial_value = ++ ((uint64_t)g_rand_int(rand) << 32) | (uint64_t)g_rand_int(rand); ++ hashpkeyr_initial_value = ++ ((uint64_t)g_rand_int(rand) << 32) | (uint64_t)g_rand_int(rand); ++ g_rand_free(rand); ++#endif ++ spr_register(env, SPR_HASHKEYR, "HASHKEYR", ++ SPR_NOACCESS, SPR_NOACCESS, ++ &spr_read_generic, &spr_write_generic, ++ hashkeyr_initial_value); ++ spr_register_hv(env, SPR_HASHPKEYR, "HASHPKEYR", ++ SPR_NOACCESS, SPR_NOACCESS, ++ SPR_NOACCESS, SPR_NOACCESS, ++ &spr_read_generic, &spr_write_generic, ++ hashpkeyr_initial_value); ++} ++ + /* + * AMR => SPR 29 (Power 2.04) + * CTRL => SPR 136 (Power 2.04) +@@ -8107,6 +8134,7 @@ static void init_proc_POWER10(CPUPPCState *env) + register_power8_book4_sprs(env); + register_power8_rpr_sprs(env); + register_power9_mmu_sprs(env); ++ register_power10_hash_sprs(env); + + /* FIXME: Filter fields properly based on privilege level */ + spr_register_kvm_hv(env, SPR_PSSCR, "PSSCR", NULL, NULL, NULL, NULL, +-- +2.41.0.windows.1 + diff --git a/tests-Fix-error-strings.patch b/tests-Fix-error-strings.patch new file mode 100644 index 00000000..25c50d96 --- /dev/null +++ b/tests-Fix-error-strings.patch @@ -0,0 +1,49 @@ +From deb4c3c20a63d0b61ba291a8edb237c2d065a04e Mon Sep 17 00:00:00 2001 +From: liujing +Date: Wed, 18 Sep 2024 19:24:00 +0800 +Subject: [PATCH] tests: Fix error strings +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +They were copy-pasted from e1000e and never changed. + +Signed-off-by: Juan Quintela +Message-Id: <20220902165126.1482-7-quintela@redhat.com> +Reviewed-by: Philippe Mathieu-Daudé +Signed-off-by: Thomas Huth +Signed-off-by: Liu Jing +--- + tests/qtest/e1000-test.c | 2 +- + tests/qtest/es1370-test.c | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/tests/qtest/e1000-test.c b/tests/qtest/e1000-test.c +index ea286d1793..1bd25d584b 100644 +--- a/tests/qtest/e1000-test.c ++++ b/tests/qtest/e1000-test.c +@@ -35,7 +35,7 @@ static void *e1000_get_driver(void *obj, const char *interface) + return &e1000->dev; + } + +- fprintf(stderr, "%s not present in e1000e\n", interface); ++ fprintf(stderr, "%s not present in e1000\n", interface); + g_assert_not_reached(); + } + +diff --git a/tests/qtest/es1370-test.c b/tests/qtest/es1370-test.c +index 2fd7fd2d3d..861656d572 100644 +--- a/tests/qtest/es1370-test.c ++++ b/tests/qtest/es1370-test.c +@@ -28,7 +28,7 @@ static void *es1370_get_driver(void *obj, const char *interface) + return &es1370->dev; + } + +- fprintf(stderr, "%s not present in e1000e\n", interface); ++ fprintf(stderr, "%s not present in es1370\n", interface); + g_assert_not_reached(); + } + +-- +2.41.0.windows.1 + diff --git a/tests-vm-update-NetBSD-to-9.3.patch b/tests-vm-update-NetBSD-to-9.3.patch new file mode 100644 index 00000000..13750443 --- /dev/null +++ b/tests-vm-update-NetBSD-to-9.3.patch @@ -0,0 +1,33 @@ +From 20df6de2677d05cd6efafb94b97ddf6eb4671aa3 Mon Sep 17 00:00:00 2001 +From: liujing +Date: Wed, 18 Sep 2024 14:29:26 +0800 +Subject: [PATCH] tests/vm: update NetBSD to 9.3 + +Update NetBSD to 9.3 + +Signed-off-by: Brad Smith +Message-Id: +Signed-off-by: Thomas Huth +Signed-off-by: Liu Jing +--- + tests/vm/netbsd | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/tests/vm/netbsd b/tests/vm/netbsd +index 4cc58df130..df4769c63d 100755 +--- a/tests/vm/netbsd ++++ b/tests/vm/netbsd +@@ -22,8 +22,8 @@ class NetBSDVM(basevm.BaseVM): + name = "netbsd" + arch = "x86_64" + +- link = "https://cdn.netbsd.org/pub/NetBSD/NetBSD-9.2/images/NetBSD-9.2-amd64.iso" +- csum = "5ee0ea101f73386b9b424f5d1041e371db3c42fdd6f4e4518dc79c4a08f31d43091ebe93425c9f0dcaaed2b51131836fe6774f33f89030b58d64709b35fda72f" ++ link = "https://cdn.netbsd.org/pub/NetBSD/NetBSD-9.3/images/NetBSD-9.3-amd64.iso" ++ csum = "2bfce544f762a579f61478e7106c436fc48731ff25cf6f79b392ba5752e6f5ec130364286f7471716290a5f033637cf56aacee7fedb91095face59adf36300c3" + size = "20G" + pkgs = [ + # tools +-- +2.41.0.windows.1 + diff --git a/ui-remove-break-after-g_assert_not_reached.patch b/ui-remove-break-after-g_assert_not_reached.patch new file mode 100644 index 00000000..81ec279b --- /dev/null +++ b/ui-remove-break-after-g_assert_not_reached.patch @@ -0,0 +1,47 @@ +From 9949490829e5f4d0a0f3700025501e8cb5afc4d4 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?=E5=BC=A0=E6=A5=9A=E5=90=9B?= + +Date: Tue, 24 Sep 2024 18:07:34 +0800 +Subject: [PATCH] ui: remove break after g_assert_not_reached() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Use of assert(false) can trip spurious control flow warnings from +some versions of GCC (i.e. using -fsanitize=thread with gcc-12): + + error: control reaches end of non-void function [-Werror=return-type] + default: + g_assert_not_reached(); + break; + | ^^^^^ + +Solve that by removing the unreachable 'break' statement, unifying +the code base on g_assert_not_reached() instead. + +Signed-off-by: Pierrick Bouvier +Reviewed-by: Richard Henderson +Reviewed-by: Philippe Mathieu-Daudé +Message-ID: <20240910221606.1817478-37-pierrick.bouvier@linaro.org> +[PMD: Add description suggested by Eric Blake] +Signed-off-by: Philippe Mathieu-Daudé +Signed-off-by: zhangchujun +--- + ui/qemu-pixman.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/ui/qemu-pixman.c b/ui/qemu-pixman.c +index 3ab7e2e958..67a88bf8dd 100644 +--- a/ui/qemu-pixman.c ++++ b/ui/qemu-pixman.c +@@ -48,7 +48,6 @@ PixelFormat qemu_pixelformat_from_pixman(pixman_format_code_t format) + break; + default: + g_assert_not_reached(); +- break; + } + + pf.amax = (1 << pf.abits) - 1; +-- +2.41.0.windows.1 + diff --git a/vhost-backend-avoid-overflow-on-memslots_limit.patch b/vhost-backend-avoid-overflow-on-memslots_limit.patch new file mode 100644 index 00000000..4ae12a04 --- /dev/null +++ b/vhost-backend-avoid-overflow-on-memslots_limit.patch @@ -0,0 +1,36 @@ +From dae2e53c30574daff59c7ddf651b730a750a3623 Mon Sep 17 00:00:00 2001 +From: Luo Yifan +Date: Thu, 26 Sep 2024 11:23:32 +0800 +Subject: [PATCH] vhost-backend: avoid overflow on memslots_limit + +cherry picked from commit 6dcae534e82520aa2280009de4b78a19059e8bbb + +Fix the (hypothetical) potential problem when the value parsed out of +the vhost module parameter in sysfs overflows the return value from +vhost_kernel_memslots_limit. + +Signed-off-by: Roman Kagan +Message-Id: <20211111153354.18807-6-rvkagan@yandex-team.ru> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Signed-off-by: Luo Yifan +--- + hw/virtio/vhost-backend.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/hw/virtio/vhost-backend.c b/hw/virtio/vhost-backend.c +index 2acfb750fd..5787775c91 100644 +--- a/hw/virtio/vhost-backend.c ++++ b/hw/virtio/vhost-backend.c +@@ -60,7 +60,7 @@ static int vhost_kernel_memslots_limit(struct vhost_dev *dev) + if (g_file_get_contents("/sys/module/vhost/parameters/max_mem_regions", + &s, NULL, NULL)) { + uint64_t val = g_ascii_strtoull(s, NULL, 10); +- if (!((val == G_MAXUINT64 || !val) && errno)) { ++ if (val < INT_MAX && val > 0) { + g_free(s); + return val; + } +-- +2.41.0.windows.1 + diff --git a/virtio-mem-don-t-warn-about-THP-sizes-on-a-kernel-wi.patch b/virtio-mem-don-t-warn-about-THP-sizes-on-a-kernel-wi.patch new file mode 100644 index 00000000..b61550e6 --- /dev/null +++ b/virtio-mem-don-t-warn-about-THP-sizes-on-a-kernel-wi.patch @@ -0,0 +1,50 @@ +From 2fc1b97a5acd19c52d8af4bfd8bcf4824db48fb9 Mon Sep 17 00:00:00 2001 +From: dinglimin +Date: Mon, 16 Sep 2024 16:53:58 +0800 +Subject: [PATCH] virtio-mem: don't warn about THP sizes on a kernel without + THP support cheery-pick from 95b717a8154b955de2782305f305b63f357b0576 If the + config directory in sysfs does not exist at all, we are dealing with a system + that does not support THPs. Simply use 1 MiB block size then, instead of + warning "Could not detect THP size, falling back to ..." and falling back to + the default THP size. + +Cc: "Michael S. Tsirkin" +Cc: Gavin Shan +Cc: Juraj Marcin +Signed-off-by: David Hildenbrand +Message-Id: <20240910163433.2100295-1-david@redhat.com> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Signed-off-by: dinglimin +--- + hw/virtio/virtio-mem.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/hw/virtio/virtio-mem.c b/hw/virtio/virtio-mem.c +index 49749349e0..452f60266a 100644 +--- a/hw/virtio/virtio-mem.c ++++ b/hw/virtio/virtio-mem.c +@@ -61,6 +61,7 @@ + static uint32_t thp_size; + + #define HPAGE_PMD_SIZE_PATH "/sys/kernel/mm/transparent_hugepage/hpage_pmd_size" ++#define HPAGE_PATH "/sys/kernel/mm/transparent_hugepage/" + static uint32_t virtio_mem_thp_size(void) + { + gchar *content = NULL; +@@ -71,6 +72,12 @@ static uint32_t virtio_mem_thp_size(void) + return thp_size; + } + ++ /* No THP -> no restrictions. */ ++ if (!g_file_test(HPAGE_PATH, G_FILE_TEST_EXISTS)) { ++ thp_size = VIRTIO_MEM_MIN_BLOCK_SIZE; ++ return thp_size; ++ } ++ + /* + * Try to probe the actual THP size, fallback to (sane but eventually + * incorrect) default sizes. +-- +2.41.0.windows.1 + -- Gitee From 1b70589acf9a25e62cd1a14092202fed3b7026d6 Mon Sep 17 00:00:00 2001 From: cheliequan Date: Thu, 14 Nov 2024 10:06:01 +0800 Subject: [PATCH 19/19] Introduce-the-SM4-cipher-algorithms-OSCCA-GB-T-32907 Signed-off-by: cheliequan --- ...4-cipher-algorithms-OSCCA-GB-T-32907.patch | 341 ++++++++++++++++++ qemu.spec | 5 +- 2 files changed, 345 insertions(+), 1 deletion(-) create mode 100644 Introduce-the-SM4-cipher-algorithms-OSCCA-GB-T-32907.patch diff --git a/Introduce-the-SM4-cipher-algorithms-OSCCA-GB-T-32907.patch b/Introduce-the-SM4-cipher-algorithms-OSCCA-GB-T-32907.patch new file mode 100644 index 00000000..3cf77143 --- /dev/null +++ b/Introduce-the-SM4-cipher-algorithms-OSCCA-GB-T-32907.patch @@ -0,0 +1,341 @@ +From b8752afb94b20ec6ea0892260a689cfedbf6f1a5 Mon Sep 17 00:00:00 2001 +From: gaochuanji +Date: Thu, 19 Sep 2024 10:56:42 +0800 +Subject: [PATCH] Introduce the SM4 cipher algorithms (OSCCA GB/T 32907-2016). +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +SM4 (GBT.32907-2016) is a cryptographic standard issued by the +Organization of State Commercial Administration of China (OSCCA) +as an authorized cryptographic algorithms for the use within China. + +Detect the SM4 cipher algorithms and enable the feature silently +if it is available. + +Signed-off-by: Hyman Huang +Reviewed-by: Philippe Mathieu-Daudé +Reviewed-by: Daniel P. Berrangé +Signed-off-by: Daniel P. Berrangé +Signed-off-by: cheliequan +--- + crypto/block-luks.c | 11 ++++++++ + crypto/cipher-gcrypt.c.inc | 8 ++++++ + crypto/cipher-nettle.c.inc | 49 +++++++++++++++++++++++++++++++++ + crypto/cipher.c | 6 ++++ + meson.build | 49 +++++++++++++++++++++++++++++++++ + qapi/crypto.json | 5 +++- + tests/unit/test-crypto-cipher.c | 13 +++++++++ + 7 files changed, 140 insertions(+), 1 deletion(-) + +diff --git a/crypto/block-luks.c b/crypto/block-luks.c +index fe8f04ffb2..0626092739 100644 +--- a/crypto/block-luks.c ++++ b/crypto/block-luks.c +@@ -126,12 +126,23 @@ qcrypto_block_luks_cipher_size_map_twofish[] = { + { 0, 0 }, + }; + ++#ifdef CONFIG_CRYPTO_SM4 ++static const QCryptoBlockLUKSCipherSizeMap ++qcrypto_block_luks_cipher_size_map_sm4[] = { ++ { 16, QCRYPTO_CIPHER_ALG_SM4}, ++ { 0, 0 }, ++}; ++#endif ++ + static const QCryptoBlockLUKSCipherNameMap + qcrypto_block_luks_cipher_name_map[] = { + { "aes", qcrypto_block_luks_cipher_size_map_aes }, + { "cast5", qcrypto_block_luks_cipher_size_map_cast5 }, + { "serpent", qcrypto_block_luks_cipher_size_map_serpent }, + { "twofish", qcrypto_block_luks_cipher_size_map_twofish }, ++#ifdef CONFIG_CRYPTO_SM4 ++ { "sm4", qcrypto_block_luks_cipher_size_map_sm4}, ++#endif + }; + + +diff --git a/crypto/cipher-gcrypt.c.inc b/crypto/cipher-gcrypt.c.inc +index a6a0117717..1377cbaf14 100644 +--- a/crypto/cipher-gcrypt.c.inc ++++ b/crypto/cipher-gcrypt.c.inc +@@ -35,6 +35,9 @@ bool qcrypto_cipher_supports(QCryptoCipherAlgorithm alg, + case QCRYPTO_CIPHER_ALG_SERPENT_256: + case QCRYPTO_CIPHER_ALG_TWOFISH_128: + case QCRYPTO_CIPHER_ALG_TWOFISH_256: ++#ifdef CONFIG_CRYPTO_SM4 ++ case QCRYPTO_CIPHER_ALG_SM4: ++#endif + break; + default: + return false; +@@ -219,6 +222,11 @@ static QCryptoCipher *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg, + case QCRYPTO_CIPHER_ALG_TWOFISH_256: + gcryalg = GCRY_CIPHER_TWOFISH; + break; ++#ifdef CONFIG_CRYPTO_SM4 ++ case QCRYPTO_CIPHER_ALG_SM4: ++ gcryalg = GCRY_CIPHER_SM4; ++ break; ++#endif + default: + error_setg(errp, "Unsupported cipher algorithm %s", + QCryptoCipherAlgorithm_str(alg)); +diff --git a/crypto/cipher-nettle.c.inc b/crypto/cipher-nettle.c.inc +index 24cc61f87b..42b39e18a2 100644 +--- a/crypto/cipher-nettle.c.inc ++++ b/crypto/cipher-nettle.c.inc +@@ -33,6 +33,9 @@ + #ifndef CONFIG_QEMU_PRIVATE_XTS + #include + #endif ++#ifdef CONFIG_CRYPTO_SM4 ++#include ++#endif + + static inline bool qcrypto_length_check(size_t len, size_t blocksize, + Error **errp) +@@ -426,6 +429,30 @@ DEFINE_ECB_CBC_CTR_XTS(qcrypto_nettle_twofish, + QCryptoNettleTwofish, TWOFISH_BLOCK_SIZE, + twofish_encrypt_native, twofish_decrypt_native) + ++#ifdef CONFIG_CRYPTO_SM4 ++typedef struct QCryptoNettleSm4 { ++ QCryptoCipher base; ++ struct sm4_ctx key[2]; ++} QCryptoNettleSm4; ++ ++static void sm4_encrypt_native(void *ctx, size_t length, ++ uint8_t *dst, const uint8_t *src) ++{ ++ struct sm4_ctx *keys = ctx; ++ sm4_crypt(&keys[0], length, dst, src); ++} ++ ++static void sm4_decrypt_native(void *ctx, size_t length, ++ uint8_t *dst, const uint8_t *src) ++{ ++ struct sm4_ctx *keys = ctx; ++ sm4_crypt(&keys[1], length, dst, src); ++} ++ ++DEFINE_ECB(qcrypto_nettle_sm4, ++ QCryptoNettleSm4, SM4_BLOCK_SIZE, ++ sm4_encrypt_native, sm4_decrypt_native) ++#endif + + bool qcrypto_cipher_supports(QCryptoCipherAlgorithm alg, + QCryptoCipherMode mode) +@@ -443,6 +470,9 @@ bool qcrypto_cipher_supports(QCryptoCipherAlgorithm alg, + case QCRYPTO_CIPHER_ALG_TWOFISH_128: + case QCRYPTO_CIPHER_ALG_TWOFISH_192: + case QCRYPTO_CIPHER_ALG_TWOFISH_256: ++#ifdef CONFIG_CRYPTO_SM4 ++ case QCRYPTO_CIPHER_ALG_SM4: ++#endif + break; + default: + return false; +@@ -701,6 +731,25 @@ static QCryptoCipher *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg, + + return &ctx->base; + } ++#ifdef CONFIG_CRYPTO_SM4 ++ case QCRYPTO_CIPHER_ALG_SM4: ++ { ++ QCryptoNettleSm4 *ctx = g_new0(QCryptoNettleSm4, 1); ++ ++ switch (mode) { ++ case QCRYPTO_CIPHER_MODE_ECB: ++ ctx->base.driver = &qcrypto_nettle_sm4_driver_ecb; ++ break; ++ default: ++ goto bad_cipher_mode; ++ } ++ ++ sm4_set_encrypt_key(&ctx->key[0], key); ++ sm4_set_decrypt_key(&ctx->key[1], key); ++ ++ return &ctx->base; ++ } ++#endif + + default: + error_setg(errp, "Unsupported cipher algorithm %s", +diff --git a/crypto/cipher.c b/crypto/cipher.c +index 74b09a5b26..5f512768ea 100644 +--- a/crypto/cipher.c ++++ b/crypto/cipher.c +@@ -38,6 +38,9 @@ static const size_t alg_key_len[QCRYPTO_CIPHER_ALG__MAX] = { + [QCRYPTO_CIPHER_ALG_TWOFISH_128] = 16, + [QCRYPTO_CIPHER_ALG_TWOFISH_192] = 24, + [QCRYPTO_CIPHER_ALG_TWOFISH_256] = 32, ++#ifdef CONFIG_CRYPTO_SM4 ++ [QCRYPTO_CIPHER_ALG_SM4] = 16, ++#endif + }; + + static const size_t alg_block_len[QCRYPTO_CIPHER_ALG__MAX] = { +@@ -53,6 +56,9 @@ static const size_t alg_block_len[QCRYPTO_CIPHER_ALG__MAX] = { + [QCRYPTO_CIPHER_ALG_TWOFISH_128] = 16, + [QCRYPTO_CIPHER_ALG_TWOFISH_192] = 16, + [QCRYPTO_CIPHER_ALG_TWOFISH_256] = 16, ++#ifdef CONFIG_CRYPTO_SM4 ++ [QCRYPTO_CIPHER_ALG_SM4] = 16, ++#endif + }; + + static const bool mode_need_iv[QCRYPTO_CIPHER_MODE__MAX] = { +diff --git a/meson.build b/meson.build +index 45bc69bf0c..1a225b51f3 100644 +--- a/meson.build ++++ b/meson.build +@@ -1010,6 +1010,7 @@ endif + # gcrypt over nettle for performance reasons. + gcrypt = not_found + nettle = not_found ++crypto_sm4 = not_found + xts = 'none' + + if get_option('nettle').enabled() and get_option('gcrypt').enabled() +@@ -1035,6 +1036,17 @@ if not gnutls_crypto.found() + gcrypt, + cc.find_library('gpg-error', required: true, kwargs: static_kwargs)]) + endif ++ crypto_sm4 = gcrypt ++ # SM4 ALG is available in libgcrypt >= 1.9 ++ if gcrypt.found() and not cc.links(''' ++ #include ++ int main(void) { ++ gcry_cipher_hd_t handler; ++ gcry_cipher_open(&handler, GCRY_CIPHER_SM4, GCRY_CIPHER_MODE_ECB, 0); ++ return 0; ++ }''', dependencies: gcrypt) ++ crypto_sm4 = not_found ++ endif + endif + if (not get_option('nettle').auto() or have_system) and not gcrypt.found() + nettle = dependency('nettle', version: '>=3.4', +@@ -1044,6 +1056,18 @@ if not gnutls_crypto.found() + if nettle.found() and not cc.has_header('nettle/xts.h', dependencies: nettle) + xts = 'private' + endif ++ crypto_sm4 = nettle ++ # SM4 ALG is available in nettle >= 3.9 ++ if nettle.found() and not cc.links(''' ++ #include ++ int main(void) { ++ struct sm4_ctx ctx; ++ unsigned char key[16] = {0}; ++ sm4_set_encrypt_key(&ctx, key); ++ return 0; ++ }''', dependencies: nettle) ++ crypto_sm4 = not_found ++ endif + endif + endif + +@@ -1411,6 +1435,17 @@ if get_option('virtfs').enabled() + elif not have_system + error('virtio-9p (virtfs) needs system emulation support') + endif ++ crypto_sm4 = gcrypt ++ # SM4 ALG is available in libgcrypt >= 1.9 ++ if gcrypt.found() and not cc.links(''' ++ #include ++ int main(void) { ++ gcry_cipher_hd_t handler; ++ gcry_cipher_open(&handler, GCRY_CIPHER_SM4, GCRY_CIPHER_MODE_ECB, 0); ++ return 0; ++ }''', dependencies: gcrypt) ++ crypto_sm4 = not_found ++ endif + endif + elif get_option('virtfs').disabled() + have_virtfs = false +@@ -1487,6 +1522,7 @@ config_host_data.set('CONFIG_GNUTLS', gnutls.found()) + config_host_data.set('CONFIG_GNUTLS_CRYPTO', gnutls_crypto.found()) + config_host_data.set('CONFIG_GCRYPT', gcrypt.found()) + config_host_data.set('CONFIG_NETTLE', nettle.found()) ++config_host_data.set('CONFIG_CRYPTO_SM4', crypto_sm4.found()) + config_host_data.set('CONFIG_QEMU_PRIVATE_XTS', xts == 'private') + config_host_data.set('CONFIG_MALLOC_TRIM', has_malloc_trim) + config_host_data.set('CONFIG_STATX', has_statx) +@@ -2093,6 +2129,18 @@ if capstone_opt in ['enabled', 'auto', 'system'] + if capstone_opt == 'system' + error('system capstone requested, it does not appear to work') + endif ++ crypto_sm4 = nettle ++ # SM4 ALG is available in nettle >= 3.9 ++ if nettle.found() and not cc.links(''' ++ #include ++ int main(void) { ++ struct sm4_ctx ctx; ++ unsigned char key[16] = {0}; ++ sm4_set_encrypt_key(&ctx, key); ++ return 0; ++ }''', dependencies: nettle) ++ crypto_sm4 = not_found ++ endif + endif + + if capstone.found() +@@ -3432,6 +3480,7 @@ summary_info += {'nettle': nettle} + if nettle.found() + summary_info += {' XTS': xts != 'private'} + endif ++summary_info += {'SM4 ALG support': crypto_sm4} + summary_info += {'crypto afalg': config_host.has_key('CONFIG_AF_ALG')} + summary_info += {'rng-none': config_host.has_key('CONFIG_RNG_NONE')} + summary_info += {'Linux keyring': config_host.has_key('CONFIG_SECRET_KEYRING')} +diff --git a/qapi/crypto.json b/qapi/crypto.json +index 1ec54c15ca..60e706ae09 100644 +--- a/qapi/crypto.json ++++ b/qapi/crypto.json +@@ -75,6 +75,8 @@ + # @twofish-128: Twofish with 128 bit / 16 byte keys + # @twofish-192: Twofish with 192 bit / 24 byte keys + # @twofish-256: Twofish with 256 bit / 32 byte keys ++# @sm4: SM4 with 128 bit / 16 byte keys (since 9.0) ++# + # Since: 2.6 + ## + { 'enum': 'QCryptoCipherAlgorithm', +@@ -83,7 +85,8 @@ + 'des', '3des', + 'cast5-128', + 'serpent-128', 'serpent-192', 'serpent-256', +- 'twofish-128', 'twofish-192', 'twofish-256']} ++ 'twofish-128', 'twofish-192', 'twofish-256', ++ 'sm4']} + + + ## +diff --git a/tests/unit/test-crypto-cipher.c b/tests/unit/test-crypto-cipher.c +index d9d9d078ff..11ab1a54fc 100644 +--- a/tests/unit/test-crypto-cipher.c ++++ b/tests/unit/test-crypto-cipher.c +@@ -382,6 +382,19 @@ static QCryptoCipherTestData test_data[] = { + .plaintext = "90afe91bb288544f2c32dc239b2635e6", + .ciphertext = "6cb4561c40bf0a9705931cb6d408e7fa", + }, ++#ifdef CONFIG_CRYPTO_SM4 ++ { ++ /* SM4, GB/T 32907-2016, Appendix A.1 */ ++ .path = "/crypto/cipher/sm4", ++ .alg = QCRYPTO_CIPHER_ALG_SM4, ++ .mode = QCRYPTO_CIPHER_MODE_ECB, ++ .key = "0123456789abcdeffedcba9876543210", ++ .plaintext = ++ "0123456789abcdeffedcba9876543210", ++ .ciphertext = ++ "681edf34d206965e86b3e94f536e4246", ++ }, ++#endif + { + /* #1 32 byte key, 32 byte PTX */ + .path = "/crypto/cipher/aes-xts-128-1", +-- +2.33.0 + diff --git a/qemu.spec b/qemu.spec index 07c8cda9..6989adf6 100644 --- a/qemu.spec +++ b/qemu.spec @@ -3,7 +3,7 @@ Name: qemu Version: 6.2.0 -Release: 101 +Release: 102 Epoch: 10 Summary: QEMU is a generic and open source machine emulator and virtualizer License: GPLv2 and BSD and MIT and CC-BY-SA-4.0 @@ -1070,6 +1070,7 @@ Patch1055: hw-i386-vmmouse-Require-i8042-property-to-be-set.patch Patch1056: vhost-backend-avoid-overflow-on-memslots_limit.patch Patch1057: sysemu-Cleanup-qemu_run_machine_init_done_notifiers.patch Patch1058: python-aqmp-use-absolute-import-statement.patch +Patch1059: Introduce-the-SM4-cipher-algorithms-OSCCA-GB-T-32907.patch BuildRequires: flex BuildRequires: gcc @@ -1668,6 +1669,8 @@ getent passwd qemu >/dev/null || \ %endif %changelog +* Wed Nov 13 2024 - 10:6.2.0-102 +- crypto: Introduce-the-SM4-cipher-algorithms-OSCCA-GB-T-32907 * Mon Oct 21 2024 - 10:6.2.0-101 - python/aqmp: use absolute import statement - sysemu: Cleanup qemu_run_machine_init_done_notifiers() -- Gitee