pci, vhost, virtio, iommu: features, fixes, cleanups
Subsystems (3)
Resolved a bunch of conflicts.
If you see anything wrong here, pls holler.
The following changes since commit f5a2438405d4ae8b62de7c9b39fac0b2155ee544:
Merge tag 'pull-qapi-2026-05-21' of https://repo.or.cz/qemu/armbru into staging (2026-05-21 09:00:22 -0400)
are available in the Git repository at:
https://git.kernel.org/pub/scm/virt/kvm/mst/qemu.git tags/for_upstream
for you to fetch changes up to 31dbba011d0f3a21432d0629fae0b4885f2eed25:
hw/scsi/vhost-scsi: fix build with older kernel headers (2026-06-03 08:36:42 -0400)
----------------------------------------------------------------
pci, vhost, virtio, iommu: features, fixes, cleanups
intel_iommu:
PASID support for passthrough
some properties renamed
virtio-rtc:
new device
acpi:
watchdog (x86 q35)
COM irqs are now shared
vhost-user:
vhost-user passes GPA not HVA now
vhost SHMEM_MAP/UNMAP support
vhost-vdpa:
svq IN_ORDER supportamd_iommu:
IOMMU XT interrupt support
command buffer fixes
cxl:
PPR support
performant path for non-interleaved cases
vhost-scsi:
build fix for older kernel headers
fixes, cleanups all over the place
----------------------------------------------------------------
Aditya Gupta (2):
ppc/pnv_phb3: Error out on invalid config access hw/pci: Replace assert with bounds check and return
Albert Esteve (7):
vhost-user: Add VirtIO Shared Memory map request vhost_user.rst: Align VhostUserMsg excerpt members vhost_user.rst: Add SHMEM_MAP/_UNMAP to spec
vhost_user: Add frontend get_shmem_config command vhost_user.rst: Add GET_SHMEM_CONFIG message
qmp: add shmem feature map
vhost-user-device: Add shared memory BAR
Alejandro Jimenez (3):
amd_iommu: Update command buffer head ptr in MMIO region after wraparound
amd_iommu: Follow root pointer before page walk and use 1-based levels
amd_iommu: Reject non-decreasing NextLevel in fetch_pte()
Alexandr Moshkov (1):
vhost-user.rst: fix typo
Alexey Gerasimenko (1):
q35: Fix incorrect values for PCIEXBAR masks
Alireza Sanaee via qemu development (2):
hw/cxl: Allow cxl_cfmws_find_device() to filter on whether interleaved paths are accepted hw/cxl: Add a performant (and correct) path for the non interleaved cases
Costas Argyris (1):
tests/qtest: Add amd-iommu command buffer head wrap test
Eugenio Pérez (8):
net/vhost-vdpa: enable vqs before DRIVER_OK if no cvq
virtio: Allow to fill a whole virtqueue in order
vhost: move svq next desc array to descs state struct
vhost: factor out the descriptor next fetching
vhost: factor out the get of last used desc in SVQ
vhost: factor out the detach buf logic in SVQ
vhost: add in_order feature to shadow virtqueue
vhost: accept in order feature flag
Igor Mammedov (6):
acpi: add API to build WDAT instructions
x86: q35: add 'wdat' property
x86: q35: generate WDAT ACPI table
tests: acpi: x86/q35: whitelist new WDAT table
tests: acpi: x86/q35: add WDAT table test case
tests: acpi: x86/q35: update expected WDAT blob
Jonathan Cameron (1):
MAINTAINERS: Update CXL maintainers entry including adding linux-cxl list
Jorge E. Moreira (1):
vhost-user.rst: Explicitly allow front-end to write to kick FDs
Junjie Cao (2):
intel_iommu: fix guest-triggerable abort on oversized MMIO access tests/qtest: add 8-byte MMIO access sweep for intel-iommu
Kuan-Wei Chiu (3):
vhost-user: Fix stale error logs and return values in teardown paths
standard-headers: Add virtio_rtc.h from Linux 7.0-rc1
virtio-rtc: Add basic virtio-rtc support
Mark Cave-Ayland (4):
hw/acpi/aml-build.c: add aml_irq() representing the 3-byte IRQ descriptor tests/acpi: allow DSDT acpi table changes hw/char/serial-isa.c: declare IRQ as shared in ACPI IRQ descriptor
tests: data: update x86 ACPI tables
Max Makarov (2):
vhost-user-blk-server: do not advertise VIRTIO_BLK_F_SIZE_MAX with size_max=0
vhost-user-blk: do not force VIRTIO_BLK_F_SIZE_MAX
Paolo Bonzini (1):
amd_iommu: restrict command buffer head/tail ranges to ring size
Quan Sun (1):
hw/scsi/vhost-scsi: fix build with older kernel headers
Sairaj Kodilkar (3):
amd_iommu: Use switch case to determine mmio register name
amd_iommu: Turn on XT support only when guest has enabled it
amd_iommu: Generate XT interrupts when xt support is enabled
Shiju Jose (3):
hw/cxl: Fix handling of component ID to not assume it is a string
hw/cxl: Add fixes in Post Package Repair (PPR)
hw/cxl/events: Fix handling of component ID in event records generation to not assume it is a string
Stefano Garzarella (2):
libvhost-user: fix buffer overflow in virtqueue_read_indirect_desc()
libvduse: fix buffer overflow in vduse_queue_read_indirect_desc()
Thomas Huth (1):
hw/i386/pc: Add a proper owner for the ioport memory regions
Vladimir Sementsov-Ogievskiy (32):
vhost-user: rework enabling vrings
vhost: drop backend_features field
vhost-user: introduce vhost_user_has_protocol_feature() helper
vhost: move protocol_features to vhost_user
vhost-user-gpu: drop code duplication
vhost: make vhost_dev.features private
virtio: move common part of _set_guest_notifier to generic code
virtio: drop *_set_guest_notifier_fd_handler() helpers
vhost-user: keep QIOChannelSocket for backend channel
vhost: vhost_virtqueue_start(): fix failure path
vhost: make vhost_memory_unmap() null-safe
vhost: simplify calls to vhost_memory_unmap()
vhost: move vrings mapping to the top of vhost_virtqueue_start()
vhost: vhost_virtqueue_start(): drop extra local variables
vhost: final refactoring of vhost vrings map/unmap
vhost: simplify vhost_dev_init() error-path
vhost: move busyloop timeout initialization to vhost_virtqueue_init()
vhost: vhost_dev_init(): simplify features initialization hw/virtio/virtio-bus: refactor virtio_bus_set_host_notifier()
vhost-user: make trace events more readable
vhost-user-blk: add some useful trace-points
vhost: add some useful trace-points
vhost: move IOTLB functions from vhost-backend.c to vhost.c
vhost: use consistent naming for backend handlers
vhost: rename vhost-backend.c to vhost-kernel.c
vhost: replace .vhost_vq_get_addr() with .vhost_phys_vring_addr()
vhost: simplify vhost_memory_map() and vhost_memory_unmap()
qapi: remove user addresses from x-query-virtio-vhost-queue-status
vhost: stop reusing vq->desc (and friends) to store physical address
vhost: rename vring pointer fields to reflect user addresses
vhost: add .vhost_phys_iotlb_msg() handler
vhost-user: add VHOST_USER_PROTOCOL_F_GPA_ADDRESSES
Zhenzhong Duan (19):
intel_iommu: Remove 'x-' prefix from 'x-scalable-mode' and 'x-flts' properties
intel_iommu: Change 'flts' property naming to 'fsts'
vfio/iommufd: Extend attach/detach_hwpt callback implementations with pasid
iommufd: Extend attach/detach_hwpt callbacks to support pasid
vfio/iommufd: Create nesting parent hwpt with IOMMU_HWPT_ALLOC_PASID flag
intel_iommu: Create the nested hwpt with IOMMU_HWPT_ALLOC_PASID flag
intel_iommu: Rename pasid property to "pasid-bits" and define it as type uint8
intel_iommu: make vtd_dev_get_pe_from_pasid() more generic
intel_iommu: Export some functions
intel_iommu: Fix PASID validity check in fault reporting
intel_iommu: Use IOMMU_NO_PASID and delete PASID_0
intel_iommu: Refactor PASID processing to use IOMMU_NO_PASID internally
intel_iommu_accel: Handle PASID entry addition for pc_inv_dsc request
intel_iommu_accel: Handle PASID entry removal for pc_inv_dsc request
intel_iommu_accel: Bypass PASID entry addition for just deleted entry
intel_iommu_accel: Handle PASID entry removal for system reset
intel_iommu_accel: Switch to VTDAccelPASIDCacheEntry for PASID bind/unbind and PIOTLB invalidation
intel_iommu_accel: Add pasid bits size check
intel_iommu: Expose flag VIOMMU_FLAG_PASID_SUPPORTED and VIOMMU_FLAG_WANT_PASID_ATTACH
MAINTAINERS | 12 +-
backends/cryptodev-vhost.c | 9 +-
backends/iommufd.c | 23 +-
backends/vhost-user.c | 8 +-
block/export/vhost-user-blk-server.c | 2 +-
docs/devel/vfio-iommufd.rst | 10 +-
docs/interop/vhost-user.rst | 135 +++++-
hw/acpi/aml-build-stub.c | 6 +
hw/acpi/aml-build.c | 41 ++
hw/acpi/meson.build | 3 +-
hw/acpi/wdat-ich9-stub.c | 15 +
hw/acpi/wdat-ich9.c | 90 ++++
hw/arm/smmuv3-accel.c | 12 +-
hw/block/trace-events | 10 +
hw/block/vhost-user-blk.c | 36 +-
hw/char/serial-isa.c | 3 +-
hw/cxl/cxl-component-utils.c | 6 +
hw/cxl/cxl-host.c | 234 ++++++++-
hw/cxl/cxl-mailbox-utils.c | 6 +-
hw/display/vhost-user-gpu.c | 11 +-
hw/i386/acpi-build.c | 12 +
hw/i386/amd_iommu.c | 288 +++++++----
hw/i386/amd_iommu.h | 36 +-
hw/i386/intel_iommu.c | 352 +++++++-------
hw/i386/intel_iommu_accel.c | 401 ++++++++++++---
hw/i386/intel_iommu_accel.h | 20 +-
hw/i386/intel_iommu_internal.h | 44 +-
hw/i386/pc.c | 6 +-
hw/i386/pc_q35.c | 18 +
hw/i386/trace-events | 1 +
hw/mem/cxl_type3.c | 17 +-
hw/net/vhost_net.c | 35 +-
hw/pci-host/pnv_phb3.c | 10 +
hw/pci-host/q35.c | 6 +-
hw/pci/pci_host.c | 14 +-
hw/s390x/virtio-ccw.c | 35 +-
hw/scsi/vhost-scsi-common.c | 2 +-
hw/scsi/vhost-scsi.c | 2 +-
hw/scsi/vhost-user-scsi.c | 1 -
hw/vfio/device.c | 11 +
hw/vfio/iommufd.c | 68 ++-
hw/vfio/trace-events | 4 +-
hw/virtio/Kconfig | 5 +
hw/virtio/meson.build | 5 +-
hw/virtio/trace-events | 16 +-
hw/virtio/vdpa-dev.c | 3 +-
hw/virtio/{vhost-backend.c => vhost-kernel.c} | 90 +---
hw/virtio/vhost-shadow-virtqueue.c | 215 ++++++--
hw/virtio/vhost-shadow-virtqueue.h | 38 +-
hw/virtio/vhost-user-base.c | 63 ++-
hw/virtio/vhost-user-fs.c | 9 +-
hw/virtio/vhost-user-scmi.c | 9 +-
hw/virtio/vhost-user-stub.c | 6 +
hw/virtio/vhost-user-test-device-pci.c | 42 +-
hw/virtio/vhost-user.c | 566 ++++++++++++++++++----
hw/virtio/vhost-vdpa.c | 19 +-
hw/virtio/vhost-vsock-common.c | 9 +-
hw/virtio/vhost.c | 384 +++++++++------
hw/virtio/virtio-bus.c | 18 +-
hw/virtio/virtio-hmp-cmds.c | 5 -
hw/virtio/virtio-mmio.c | 41 +-
hw/virtio/virtio-pci.c | 34 +-
hw/virtio/virtio-qmp.c | 18 +-
hw/virtio/virtio-rtc-pci.c | 65 +++
hw/virtio/virtio-rtc.c | 190 ++++++++
hw/virtio/virtio.c | 251 +++++++++-
include/hw/acpi/aml-build.h | 2 +
include/hw/acpi/wdat-ich9.h | 15 +
include/hw/acpi/wdat.h | 118 +++++
include/hw/core/iommu.h | 14 +
include/hw/cxl/cxl.h | 1 +
include/hw/cxl/cxl_device.h | 4 +
include/hw/i386/intel_iommu.h | 4 +-
include/hw/i386/pc.h | 1 +
include/hw/pci-host/q35.h | 4 +-
include/hw/vfio/vfio-device.h | 1 +
include/hw/virtio/vhost-backend.h | 47 +-
include/hw/virtio/vhost-user.h | 6 +
include/hw/virtio/vhost.h | 71 ++-
include/hw/virtio/virtio-pci.h | 3 -
include/hw/virtio/virtio-rtc.h | 22 +
include/hw/virtio/virtio.h | 151 +++++-
include/standard-headers/linux/virtio_rtc.h | 237 +++++++++
include/system/iommufd.h | 18 +-
include/system/memory.h | 4 +-
net/vhost-vdpa.c | 37 +-
qapi/virtio.json | 18 -
subprojects/libvduse/libvduse.c | 7 +-
subprojects/libvhost-user/libvhost-user.c | 77 ++-
subprojects/libvhost-user/libvhost-user.h | 56 +++
system/memory.c | 14 +
tests/data/acpi/x86/microvm/DSDT | Bin 365 -> 366 bytes
tests/data/acpi/x86/microvm/DSDT.ioapic2 | Bin 365 -> 366 bytes
tests/data/acpi/x86/microvm/DSDT.pcie | Bin 2985 -> 2986 bytes
tests/data/acpi/x86/microvm/DSDT.rtc | Bin 404 -> 405 bytes
tests/data/acpi/x86/microvm/DSDT.usb | Bin 414 -> 415 bytes
tests/data/acpi/x86/pc/DSDT | Bin 8598 -> 8599 bytes
tests/data/acpi/x86/pc/DSDT.acpierst | Bin 8509 -> 8510 bytes
tests/data/acpi/x86/pc/DSDT.acpihmat | Bin 9923 -> 9924 bytes
tests/data/acpi/x86/pc/DSDT.bridge | Bin 15469 -> 15470 bytes
tests/data/acpi/x86/pc/DSDT.cphp | Bin 9062 -> 9063 bytes
tests/data/acpi/x86/pc/DSDT.dimmpxm | Bin 10252 -> 10253 bytes
tests/data/acpi/x86/pc/DSDT.hpbridge | Bin 8549 -> 8550 bytes
tests/data/acpi/x86/pc/DSDT.hpbrroot | Bin 5087 -> 5088 bytes
tests/data/acpi/x86/pc/DSDT.ipmikcs | Bin 8670 -> 8671 bytes
tests/data/acpi/x86/pc/DSDT.memhp | Bin 9957 -> 9958 bytes
tests/data/acpi/x86/pc/DSDT.nohpet | Bin 8456 -> 8457 bytes
tests/data/acpi/x86/pc/DSDT.numamem | Bin 8604 -> 8605 bytes
tests/data/acpi/x86/pc/DSDT.roothp | Bin 12391 -> 12392 bytes
tests/data/acpi/x86/q35/DSDT | Bin 8427 -> 8428 bytes
tests/data/acpi/x86/q35/DSDT.acpierst | Bin 8444 -> 8445 bytes
tests/data/acpi/x86/q35/DSDT.acpihmat | Bin 9752 -> 9753 bytes
tests/data/acpi/x86/q35/DSDT.acpihmat-generic-x | Bin 12637 -> 12638 bytes
tests/data/acpi/x86/q35/DSDT.acpihmat-noinitiator | Bin 8706 -> 8707 bytes
tests/data/acpi/x86/q35/DSDT.applesmc | Bin 8473 -> 8474 bytes
tests/data/acpi/x86/q35/DSDT.bridge | Bin 12040 -> 12041 bytes
tests/data/acpi/x86/q35/DSDT.core-count | Bin 12985 -> 12986 bytes
tests/data/acpi/x86/q35/DSDT.core-count2 | Bin 33842 -> 33843 bytes
tests/data/acpi/x86/q35/DSDT.cphp | Bin 8891 -> 8892 bytes
tests/data/acpi/x86/q35/DSDT.cxl | Bin 13218 -> 13219 bytes
tests/data/acpi/x86/q35/DSDT.dimmpxm | Bin 10081 -> 10082 bytes
tests/data/acpi/x86/q35/DSDT.ipmibt | Bin 8502 -> 8503 bytes
tests/data/acpi/x86/q35/DSDT.ipmismbus | Bin 8515 -> 8516 bytes
tests/data/acpi/x86/q35/DSDT.ivrs | Bin 8444 -> 8445 bytes
tests/data/acpi/x86/q35/DSDT.memhp | Bin 9786 -> 9787 bytes
tests/data/acpi/x86/q35/DSDT.mmio64 | Bin 9557 -> 9558 bytes
tests/data/acpi/x86/q35/DSDT.multi-bridge | Bin 13280 -> 13281 bytes
tests/data/acpi/x86/q35/DSDT.noacpihp | Bin 8289 -> 8290 bytes
tests/data/acpi/x86/q35/DSDT.nohpet | Bin 8285 -> 8286 bytes
tests/data/acpi/x86/q35/DSDT.numamem | Bin 8433 -> 8434 bytes
tests/data/acpi/x86/q35/DSDT.pvpanic-isa | Bin 8528 -> 8529 bytes
tests/data/acpi/x86/q35/DSDT.thread-count | Bin 12985 -> 12986 bytes
tests/data/acpi/x86/q35/DSDT.thread-count2 | Bin 33842 -> 33843 bytes
tests/data/acpi/x86/q35/DSDT.tis.tpm12 | Bin 9033 -> 9034 bytes
tests/data/acpi/x86/q35/DSDT.tis.tpm2 | Bin 9059 -> 9060 bytes
tests/data/acpi/x86/q35/DSDT.type4-count | Bin 18661 -> 18662 bytes
tests/data/acpi/x86/q35/DSDT.viot | Bin 14684 -> 14685 bytes
tests/data/acpi/x86/q35/DSDT.xapic | Bin 35790 -> 35791 bytes
tests/data/acpi/x86/q35/WDAT.wdat | Bin 0 -> 308 bytes
tests/qtest/amd-iommu-test.c | 76 +++
tests/qtest/bios-tables-test.c | 13 +
tests/qtest/intel-iommu-test.c | 32 +-
tests/qtest/iommu-intel-test.c | 4 +-
tests/qtest/meson.build | 1 +
144 files changed, 4056 insertions(+), 1158 deletions(-)
create mode 100644 hw/acpi/wdat-ich9-stub.c
create mode 100644 hw/acpi/wdat-ich9.c
rename hw/virtio/{vhost-backend.c => vhost-kernel.c} (83%)
create mode 100644 hw/virtio/vhost-user-stub.c
create mode 100644 hw/virtio/virtio-rtc-pci.c
create mode 100644 hw/virtio/virtio-rtc.c
create mode 100644 include/hw/acpi/wdat-ich9.h
create mode 100644 include/hw/acpi/wdat.h
create mode 100644 include/hw/virtio/virtio-rtc.h
create mode 100644 include/standard-headers/linux/virtio_rtc.h
create mode 100644 tests/data/acpi/x86/q35/WDAT.wdat
create mode 100644 tests/qtest/amd-iommu-test.c[PULL 003/106] tests/qtest: Add amd-iommu command buffer head wrap test
From: Costas Argyris <[email protected]>
Add a qtest for AMD IOMMU command buffer head pointer wraparound. The test programs a command buffer, fills it with COMPLETION_WAIT commands, advances the tail to consume all but the final entry, then wraps the tail to zero to force the final command to advance CmdHeadPtr past the end of the buffer. The guest-visible CmdHeadPtr register must then wrap back to zero.
This covers the case fixed by an earlier CmdHeadPtr wraparound patch.
The Linux kernel AMD IOMMU driver is not affected by this bug because it uses COMPLETION_WAIT with a memory store doorbell to detect command progress.
Message-Id: <[email protected]>
--- MAINTAINERS | 1 + tests/qtest/amd-iommu-test.c | 76 ++++++++++++++++++++++++++++++++++++ tests/qtest/meson.build | 1 + 3 files changed, 78 insertions(+) create mode 100644 tests/qtest/amd-iommu-test.c
MAINTAINERS +1 -0
@@ -4053,6 +4053,7 @@ M: Alejandro Jimenez <[email protected]> R: Sairaj Kodilkar <[email protected]> S: Supported F: hw/i386/amd_iommu* +F: tests/qtest/amd-iommu-test.c OpenSBI Firmware L: [email protected]
tests/qtest/amd-iommu-test.c new file +76 -0
76 lines not on this page · raw message
tests/qtest/meson.build +1 -0
@@ -95,6 +95,7 @@ qtests_i386 = \ (config_all_devices.has_key('CONFIG_SB16') ? ['fuzz-sb16-test'] : []) + \ (config_all_devices.has_key('CONFIG_SDHCI_PCI') ? ['fuzz-sdcard-test'] : []) + \ (config_all_devices.has_key('CONFIG_ESP_PCI') ? ['am53c974-test'] : []) + \ + (config_all_devices.has_key('CONFIG_AMD_IOMMU') ? ['amd-iommu-test'] : []) + \ (config_all_devices.has_key('CONFIG_VTD') ? ['intel-iommu-test'] : []) + \ (config_all_devices.has_key('CONFIG_VTD') and config_all_devices.has_key('CONFIG_IOMMU_TESTDEV') ? ['iommu-intel-test'] : []) + \
Signature · 1 line
MST
[PULL 004/106] intel_iommu: Remove 'x-' prefix from 'x-scalable-mode' and 'x-flts' properties
In reply to Michael S. TsirkinFrom: Zhenzhong Duan <[email protected]>
We had 'x-scalable-mode' for more than 5 years and 'x-flts' for more than 1 year, it's fine to remove 'x-' now.
This is a prerequisite to enable intel_iommu's scalable mode and first stage translation support in libvirt.
Message-Id: <[email protected]>
--- docs/devel/vfio-iommufd.rst | 10 +++++----- hw/i386/intel_iommu.c | 8 ++++---- hw/i386/intel_iommu_accel.c | 4 ++-- tests/qtest/intel-iommu-test.c | 2 +- tests/qtest/iommu-intel-test.c | 4 ++-- 5 files changed, 14 insertions(+), 14 deletions(-)
docs/devel/vfio-iommufd.rst +5 -5
@@ -153,22 +153,22 @@ RAM discarding for mdev. ``vfio-ap`` and ``vfio-ccw`` devices don't have same issue as their backend devices are always mdev and RAM discarding is force enabled. -Usage with intel_iommu featuring x-flts=on +Usage with intel_iommu featuring flts=on ------------------------------------------ Only IOMMUFD backed VFIO device is supported when intel_iommu is configured -with x-flts=on, for legacy container backed VFIO device, below error shows: +with flts=on, for legacy container backed VFIO device, below error shows: .. code-block:: none - qemu-system-x86_64: -device vfio-pci,host=0000:02:00.0: vfio 0000:02:00.0: Failed to set vIOMMU: Need IOMMUFD backend when x-flts=on + qemu-system-x86_64: -device vfio-pci,host=0000:02:00.0: vfio 0000:02:00.0: Failed to set vIOMMU: Need IOMMUFD backend when flts=on VFIO device under PCI bridge is unsupported, use PCIE bridge if necessary, otherwise below error shows: .. code-block:: none - qemu-system-x86_64: -device vfio-pci,host=0000:02:00.0,bus=bridge1,iommufd=iommufd0: vfio 0000:02:00.0: Failed to set vIOMMU: Host device downstream to a PCI bridge is unsupported when x-flts=on + qemu-system-x86_64: -device vfio-pci,host=0000:02:00.0,bus=bridge1,iommufd=iommufd0: vfio 0000:02:00.0: Failed to set vIOMMU: Host device downstream to a PCI bridge is unsupported when flts=on If host IOMMU has ERRATA_772415_SPR17, running guest with "intel_iommu=on,sm_off" is unsupported, kexec or reboot guest from "intel_iommu=on,sm_on" to
@@ -177,4 +177,4 @@ below if it's not needed by guest: .. code-block:: bash - -device intel-iommu,x-scalable-mode=off + -device intel-iommu,scalable-mode=off
hw/i386/intel_iommu.c +4 -4
@@ -4200,8 +4200,8 @@ static const Property vtd_properties[] = {DEFINE_PROP_UINT8 ("aw-bits" , IntelIOMMUState, aw_bits,VTD_HOST_ADDRESS_WIDTH ),DEFINE_PROP_BOOL ("caching-mode" , IntelIOMMUState, caching_mode, FALSE), -DEFINE_PROP_BOOL ("x-scalable-mode" , IntelIOMMUState, scalable_mode, FALSE), -DEFINE_PROP_BOOL ("x-flts" , IntelIOMMUState, fsts, FALSE), +DEFINE_PROP_BOOL ("scalable-mode" , IntelIOMMUState, scalable_mode, FALSE), +DEFINE_PROP_BOOL ("flts" , IntelIOMMUState, fsts, FALSE),DEFINE_PROP_BOOL ("snoop-control" , IntelIOMMUState, snoop_control, false),DEFINE_PROP_BOOL ("x-pasid-mode" , IntelIOMMUState, pasid, false), DEFINE_PROP_BOOL("svm", IntelIOMMUState, svm, false),
@@ -5563,7 +5563,7 @@ static bool vtd_decide_config(IntelIOMMUState *s, Error **errp) }if (!s->scalable_mode && s->fsts) { -error_setg (errp,"x-flts is only available in scalable mode" ); +error_setg (errp,"flts is only available in scalable mode" );return false; }
@@ -5576,7 +5576,7 @@ static bool vtd_decide_config(IntelIOMMUState *s, Error **errp) }if (s->fsts && s->aw_bits !=VTD_HOST_AW_48BIT ) { -error_setg (errp,"Scalable mode(x-flts=on): supported value for " +error_setg (errp,"Scalable mode(flts=on): supported value for " "aw-bits is: %d" ,VTD_HOST_AW_48BIT );return false; }
hw/i386/intel_iommu_accel.c +2 -2
@@ -26,7 +26,7 @@ bool vtd_check_hiod_accel(IntelIOMMUState *s, VTDHostIOMMUDevice *vtd_hiod,PCIDevice *pdev = bus->devices[vtd_hiod->devfn];if (!object_dynamic_cast (OBJECT (hiod),TYPE_HOST_IOMMU_DEVICE_IOMMUFD )) { -error_setg (errp,"Need IOMMUFD backend when x-flts=on" ); +error_setg (errp,"Need IOMMUFD backend when flts=on" );return false; }
@@ -44,7 +44,7 @@ bool vtd_check_hiod_accel(IntelIOMMUState *s, VTDHostIOMMUDevice *vtd_hiod,if (pci_device_get_iommu_bus_devfn (pdev, &bus,NULL ,NULL )) {error_setg (errp,"Host device downstream to a PCI bridge is " -"unsupported when x-flts=on" ); +"unsupported when flts=on" );return false; }
tests/qtest/intel-iommu-test.c +1 -1
@@ -29,7 +29,7 @@ static void test_intel_iommu_stage_1(void)uint64_t cap, ecap, tmp;QTestState *s; - s =qtest_init ("-M q35 -device intel-iommu,x-scalable-mode=on,x-flts=on" ); + s =qtest_init ("-M q35 -device intel-iommu,scalable-mode=on,flts=on" ); cap =vtd_reg_readq (s,DMAR_CAP_REG );g_assert ((cap &CAP_STAGE_1_FIXED1 ) ==CAP_STAGE_1_FIXED1 );
tests/qtest/iommu-intel-test.c +2 -2
@@ -54,10 +54,10 @@ static const char *qvtd_iommu_args(QVTDTransMode mode) {switch (mode) {case QVTD_TM_SCALABLE_FLT : -return "-device intel-iommu,x-scalable-mode=on,x-flts=on " ; +return "-device intel-iommu,scalable-mode=on,flts=on " ;case QVTD_TM_SCALABLE_PT :case QVTD_TM_SCALABLE_SLT : -return "-device intel-iommu,x-scalable-mode=on " ; +return "-device intel-iommu,scalable-mode=on " ;default :return "-device intel-iommu " ; }
Signature · 1 line
MST
[PULL 014/106] intel_iommu: Use IOMMU_NO_PASID and delete PASID_0
In reply to Michael S. TsirkinFrom: Zhenzhong Duan <[email protected]>
In previous patch we introduced a global macro IOMMU_NO_PASID(0) for the RID attachment, this makes the local macro PASID_0 redundant. Delete it and use IOMMU_NO_PASID instead.
No functional changes intended.
Message-Id: <[email protected]>
--- hw/i386/intel_iommu.c | 22 +++++++++++----------- hw/i386/intel_iommu_accel.c | 2 +- hw/i386/intel_iommu_internal.h | 1 - 3 files changed, 12 insertions(+), 13 deletions(-)
hw/i386/intel_iommu.c +11 -11
@@ -941,7 +941,7 @@ static int vtd_ce_get_pasid_entry(IntelIOMMUState *s, VTDContextEntry *ce,dma_addr_t pasid_dir_base;if (pasid ==PCI_NO_PASID ) { - pasid =PASID_0 ; + pasid =IOMMU_NO_PASID ; } pasid_dir_base =VTD_CE_GET_PASID_DIR_TABLE (ce);return vtd_get_pe_from_pasid_table (s, pasid_dir_base, pasid, pe);
@@ -958,7 +958,7 @@ static int vtd_ce_get_pasid_fpd(IntelIOMMUState *s,VTDPASIDEntry pe;if (pasid ==PCI_NO_PASID ) { - pasid =PASID_0 ; + pasid =IOMMU_NO_PASID ; } pasid_dir_base =VTD_CE_GET_PASID_DIR_TABLE (ce);
@@ -1501,9 +1501,9 @@ static int vtd_ce_pasid_0_check(IntelIOMMUState *s, VTDContextEntry *ce)/* * Make sure in Scalable Mode, a present context entry -* has valid pasid entry setting at PASID_0. +* has valid pasid entry setting at IOMMU_NO_PASID. */ -return vtd_ce_get_pasid_entry (s, ce, &pe,PASID_0 ); +return vtd_ce_get_pasid_entry (s, ce, &pe,IOMMU_NO_PASID ); }/* Map a device to its corresponding domain (context-entry) */
@@ -1564,7 +1564,7 @@ int vtd_dev_to_context_entry(IntelIOMMUState *s, uint8_t bus_num, } }else {/* -* Check if the programming of pasid setting of PASID_0 +* Check if the programming of pasid setting of IOMMU_NO_PASID * is valid, and thus avoids to check pasid entry fetching * result in future helper function calling. */
@@ -2123,7 +2123,7 @@ static bool vtd_do_iommu_translate(VTDAddressSpace *vtd_as, PCIBus *bus,vtd_iommu_lock (s);if (pasid ==PCI_NO_PASID && s->root_scalable) { - pasid =PASID_0 ; + pasid =IOMMU_NO_PASID ; }/* Try to fetch pte from IOTLB */
@@ -2488,7 +2488,7 @@ static void vtd_iotlb_domain_invalidate(IntelIOMMUState *s, uint16_t domain_id) }/* -* There is no pasid field in iotlb invalidation descriptor, so PCI_NO_PASID +* There is no pasid field in iotlb invalidation descriptor, so IOMMU_NO_PASID * is passed as parameter. Piotlb invalidation supports pasid, pasid in its * descriptor is passed which should not be PCI_NO_PASID. */
@@ -2509,10 +2509,10 @@ static void vtd_iotlb_page_invalidate_notify(IntelIOMMUState *s,* In legacy mode, vtd_as->pasid == pasid is always true. * In scalable mode, for vtd address space backing a PCI * device without pasid, needs to compare pasid with -* PASID_0 of this device. +* IOMMU_NO_PASID of this device. */ if (!(vtd_as->pasid == pasid || - (vtd_as->pasid ==PCI_NO_PASID && pasid ==PASID_0 ))) { + (vtd_as->pasid ==PCI_NO_PASID && pasid ==IOMMU_NO_PASID ))) {continue ; }
@@ -2564,7 +2564,7 @@ static void vtd_iotlb_page_invalidate(IntelIOMMUState *s, uint16_t domain_id,vtd_iommu_lock (s);g_hash_table_foreach_remove (s->iotlb, vtd_hash_remove_by_page, &info);vtd_iommu_unlock (s); -vtd_iotlb_page_invalidate_notify (s, domain_id, addr, am,PCI_NO_PASID ); +vtd_iotlb_page_invalidate_notify (s, domain_id, addr, am,IOMMU_NO_PASID ); }/* Flush IOTLB
@@ -3023,7 +3023,7 @@ static void vtd_piotlb_pasid_invalidate(IntelIOMMUState *s,if (!vtd_dev_to_context_entry (s,pci_bus_num (vtd_as->bus), vtd_as->devfn, &ce) && domain_id ==vtd_get_domain_id (s, &ce, vtd_as->pasid)) { -if ((vtd_as->pasid !=PCI_NO_PASID || pasid !=PASID_0 ) && +if ((vtd_as->pasid !=PCI_NO_PASID || pasid !=IOMMU_NO_PASID ) && vtd_as->pasid != pasid) {continue ; }
hw/i386/intel_iommu_accel.c +1 -1
@@ -217,7 +217,7 @@ static void vtd_flush_host_piotlb_locked(gpointer key, gpointer value, did =VTD_SM_PASID_ENTRY_DID (&pc_entry->pasid_entry); -if (piotlb_info->domain_id == did && piotlb_info->pasid ==PASID_0 ) { +if (piotlb_info->domain_id == did && piotlb_info->pasid ==IOMMU_NO_PASID ) {HostIOMMUDeviceIOMMUFD *hiodi =HOST_IOMMU_DEVICE_IOMMUFD (vtd_hiod->hiod);uint32_t entry_num =1 ;/* Only implement one request for simplicity */
hw/i386/intel_iommu_internal.h +0 -1
@@ -615,7 +615,6 @@ typedef struct VTDRootEntry VTDRootEntry;#define VTD_CTX_ENTRY_LEGACY_SIZE 16#define VTD_CTX_ENTRY_SCALABLE_SIZE 32 -#define PASID_0 0#define VTD_SM_CONTEXT_ENTRY_RSVD_VAL0 (aw) (0x1e0ULL | ~VTD_HAW_MASK(aw))#define VTD_SM_CONTEXT_ENTRY_RSVD_VAL1 0xffffffffffe00000ULL#define VTD_SM_CONTEXT_ENTRY_PRE 0x10ULL
Signature · 1 line
MST
[PULL 011/106] intel_iommu: make vtd_dev_get_pe_from_pasid() more generic
In reply to Michael S. TsirkinFrom: Zhenzhong Duan <[email protected]>
Refactor vtd_dev_get_pe_from_pasid() to take individual parameters (IntelIOMMUState, PCIBus, devfn, pasid) instead of VTDAddressSpace.
This makes the function more reusable and prepares it for export to be used in the acceleration path. Remove inline qualifier as the function will be exported in a subsequent patch.
No functional changes intended.
Message-Id: <[email protected]>
--- hw/i386/intel_iommu.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-)
hw/i386/intel_iommu.c +7 -7
@@ -3113,10 +3113,10 @@ static bool vtd_process_piotlb_desc(IntelIOMMUState *s,return true; } -static inline int vtd_dev_get_pe_from_pasid (VTDAddressSpace *vtd_as, -VTDPASIDEntry *pe) +static int vtd_dev_get_pe_from_pasid (IntelIOMMUState *s,PCIBus *bus, +uint8_t devfn,uint32_t pasid, +VTDPASIDEntry *pe) { -IntelIOMMUState *s = vtd_as->iommu_state;VTDContextEntry ce;int ret;
@@ -3124,13 +3124,12 @@ static inline int vtd_dev_get_pe_from_pasid(VTDAddressSpace *vtd_as,return -VTD_FR_RTADDR_INV_TTM ; } - ret =vtd_dev_to_context_entry (s,pci_bus_num (vtd_as->bus), vtd_as->devfn, - &ce); + ret =vtd_dev_to_context_entry (s,pci_bus_num (bus), devfn, &ce);if (ret) {return ret; } -return vtd_ce_get_pasid_entry (s, &ce, pe, vtd_as->pasid); +return vtd_ce_get_pasid_entry (s, &ce, pe, pasid); }static int vtd_pasid_entry_compare (VTDPASIDEntry *p1,VTDPASIDEntry *p2)
@@ -3151,7 +3150,8 @@ static void vtd_pasid_cache_sync_locked(gpointer key, gpointer value,const char *err_prefix ="Attaching to HWPT failed: " ;Error *local_err =NULL ; -if (vtd_dev_get_pe_from_pasid (vtd_as, &pe)) { +if (vtd_dev_get_pe_from_pasid (vtd_as->iommu_state, vtd_as->bus, + vtd_as->devfn, vtd_as->pasid, &pe)) {if (!pc_entry->valid) {return ; }
Signature · 1 line
MST
[PULL 015/106] intel_iommu: Refactor PASID processing to use IOMMU_NO_PASID internally
In reply to Michael S. TsirkinFrom: Zhenzhong Duan <[email protected]>
The PCI subsystem uses PCI_NO_PASID for requests-without-PASID, but VT-d emulation uses IOMMU_NO_PASID internally (ecap.RPS==0). This leads to conversion and checking code between PCI_NO_PASID and IOMMU_NO_PASID throughout the implementation.
Refactor to use IOMMU PASID consistently within Intel IOMMU by storing IOMMU PASID value in vtd_as->pasid. After this change, PCI_NO_PASID is only used at three boundary points:
1. PCI_NO_PASID -> IOMMU_NO_PASID: Convert PCI PASID to IOMMU PASID in vtd_find_add_as() and cache in vtd_as->pasid.
2. IOMMU_NO_PASID -> PCI_NO_PASID: Convert when notifying UNMAP events via memory_region_notify_iommu() and returning IOMMUTLBEntry in vtd_iommu_translate().
This eliminates conversion/checks in PASID table lookups, simplifies invalidation logic with consistent PASID values, and improves code readability. The PCI subsystem interface remains unchanged to maintain compatibility with other IOMMU implementations that may not use PASID 0 for requests-without-PASID.
Message-Id: <[email protected]>
--- hw/i386/intel_iommu.c | 166 +++++++++++++++++------------------- hw/i386/intel_iommu_accel.c | 2 +- include/system/memory.h | 2 +- 3 files changed, 81 insertions(+), 89 deletions(-)
hw/i386/intel_iommu.c +79 -87
@@ -938,12 +938,8 @@ static int vtd_get_pe_from_pasid_table(IntelIOMMUState *s,static int vtd_ce_get_pasid_entry (IntelIOMMUState *s,VTDContextEntry *ce,VTDPASIDEntry *pe,uint32_t pasid) { -dma_addr_t pasid_dir_base; +dma_addr_t pasid_dir_base =VTD_CE_GET_PASID_DIR_TABLE (ce); -if (pasid ==PCI_NO_PASID ) { - pasid =IOMMU_NO_PASID ; - } - pasid_dir_base =VTD_CE_GET_PASID_DIR_TABLE (ce);return vtd_get_pe_from_pasid_table (s, pasid_dir_base, pasid, pe); }
@@ -953,15 +949,10 @@ static int vtd_ce_get_pasid_fpd(IntelIOMMUState *s, uint32_t pasid) {int ret; -dma_addr_t pasid_dir_base; +dma_addr_t pasid_dir_base =VTD_CE_GET_PASID_DIR_TABLE (ce);VTDPASIDDirEntry pdire;VTDPASIDEntry pe; -if (pasid ==PCI_NO_PASID ) { - pasid =IOMMU_NO_PASID ; - } - pasid_dir_base =VTD_CE_GET_PASID_DIR_TABLE (ce); -/* * No present bit check since fpd is meaningful even * if the present bit is clear.
@@ -1750,7 +1741,7 @@ static bool vtd_switch_address_space(VTDAddressSpace *as)* * Need to disable ir for as with PASID. */ -if (as->pasid !=PCI_NO_PASID ) { +if (as->pasid !=IOMMU_NO_PASID ) {memory_region_set_enabled (&as->iommu_ir, false); }else {memory_region_set_enabled (&as->iommu_ir, true);
@@ -1780,7 +1771,7 @@ static bool vtd_switch_address_space(VTDAddressSpace *as)* We enable per as memory region (iommu_ir_fault) for catching * the translation for interrupt range through PASID + PT. */ -if (pt && as->pasid !=PCI_NO_PASID ) { +if (pt && as->pasid !=IOMMU_NO_PASID ) {memory_region_set_enabled (&as->iommu_ir_fault, true); }else {memory_region_set_enabled (&as->iommu_ir_fault, false);
@@ -1892,7 +1883,7 @@ static VTDAddressSpace *vtd_get_as_by_sid_and_pasid(IntelIOMMUState *s,VTDAddressSpace *vtd_get_as_by_sid (IntelIOMMUState *s,uint16_t sid) { -return vtd_get_as_by_sid_and_pasid (s, sid,PCI_NO_PASID ); +return vtd_get_as_by_sid_and_pasid (s, sid,IOMMU_NO_PASID ); }static void vtd_pt_enable_fast_path (IntelIOMMUState *s,uint16_t source_id)
@@ -2109,7 +2100,7 @@ static bool vtd_do_iommu_translate(VTDAddressSpace *vtd_as, PCIBus *bus,bool is_fpd_set = false;bool reads = true;bool writes = true; -bool is_pasid = pasid !=PCI_NO_PASID ; +bool is_pasid = pasid !=IOMMU_NO_PASID ;uint8_t access_flags, pgtt;VTDIOTLBEntry *iotlb_entry;uint64_t xlat, size;
@@ -2122,10 +2113,6 @@ static bool vtd_do_iommu_translate(VTDAddressSpace *vtd_as, PCIBus *bus,vtd_iommu_lock (s); -if (pasid ==PCI_NO_PASID && s->root_scalable) { - pasid =IOMMU_NO_PASID ; - } -/* Try to fetch pte from IOTLB */ iotlb_entry =vtd_lookup_iotlb (s, source_id, pasid, addr);if (iotlb_entry) {
@@ -2490,7 +2477,7 @@ static void vtd_iotlb_domain_invalidate(IntelIOMMUState *s, uint16_t domain_id)/* * There is no pasid field in iotlb invalidation descriptor, so IOMMU_NO_PASID * is passed as parameter. Piotlb invalidation supports pasid, pasid in its -* descriptor is passed which should not be PCI_NO_PASID. +* descriptor is passed. */ static void vtd_iotlb_page_invalidate_notify(IntelIOMMUState *s, uint16_t domain_id, hwaddr addr,
@@ -2504,48 +2491,41 @@ static void vtd_iotlb_page_invalidate_notify(IntelIOMMUState *s, QLIST_FOREACH(vtd_as, &(s->vtd_as_with_notifiers), next) { ret =vtd_dev_to_context_entry (s,pci_bus_num (vtd_as->bus), vtd_as->devfn, &ce); -if (!ret && domain_id ==vtd_get_domain_id (s, &ce, vtd_as->pasid)) { -/* -* In legacy mode, vtd_as->pasid == pasid is always true. -* In scalable mode, for vtd address space backing a PCI -* device without pasid, needs to compare pasid with -* IOMMU_NO_PASID of this device. -*/ -if (!(vtd_as->pasid == pasid || - (vtd_as->pasid ==PCI_NO_PASID && pasid ==IOMMU_NO_PASID ))) { -continue ; - } +if (ret || vtd_as->pasid != pasid || + domain_id !=vtd_get_domain_id (s, &ce, pasid)) { +continue ; + } -if (vtd_as_has_map_notifier (vtd_as)) { -/* -* When first stage translation is off, as long as we have MAP -* notifications registered in any of our IOMMU notifiers, -* we need to sync the shadow page table. Otherwise VFIO -* device attaches to nested page table instead of shadow -* page table, so no need to sync. -*/ -if (!s->fsts || !s->root_scalable) { -vtd_sync_shadow_page_table_range (vtd_as, &ce, addr, size); - } - }else { -/* -* For UNMAP-only notifiers, we don't need to walk the -* page tables. We just deliver the PSI down to -* invalidate caches. -*/ -const IOMMUTLBEvent event = { - .type =IOMMU_NOTIFIER_UNMAP , - .entry = { - .target_as = &address_space_memory, - .iova = addr, - .translated_addr =0 , - .addr_mask = size -1 , - .perm =IOMMU_NONE , - .pasid = vtd_as->pasid, - }, - }; -memory_region_notify_iommu (&vtd_as->iommu,0 , event); +if (vtd_as_has_map_notifier (vtd_as)) { +/* +* When first stage translation is off, as long as we have MAP +* notifications registered in any of our IOMMU notifiers, +* we need to sync the shadow page table. Otherwise VFIO +* device attaches to nested page table instead of shadow +* page table, so no need to sync. +*/ +if (!s->fsts || !s->root_scalable) { +vtd_sync_shadow_page_table_range (vtd_as, &ce, addr, size); } + }else { +/* +* For UNMAP-only notifiers, we don't need to walk the +* page tables. We just deliver the PSI down to +* invalidate caches. +*/ +const IOMMUTLBEvent event = { + .type =IOMMU_NOTIFIER_UNMAP , + .entry = { + .target_as = &address_space_memory, + .iova = addr, + .translated_addr =0 , + .addr_mask = size -1 , + .perm =IOMMU_NONE , +/* Other sub-systems use PCI pasid */ + .pasid = pasid ==IOMMU_NO_PASID ?PCI_NO_PASID : pasid, + }, + }; +memory_region_notify_iommu (&vtd_as->iommu,0 , event); } } }
@@ -3008,6 +2988,7 @@ static void vtd_piotlb_pasid_invalidate(IntelIOMMUState *s,VTDIOTLBPageInvInfo info;VTDAddressSpace *vtd_as;VTDContextEntry ce; +int ret; info.domain_id = domain_id; info.pasid = pasid;
@@ -3020,17 +3001,15 @@ static void vtd_piotlb_pasid_invalidate(IntelIOMMUState *s,vtd_iommu_unlock (s); QLIST_FOREACH(vtd_as, &s->vtd_as_with_notifiers, next) { -if (!vtd_dev_to_context_entry (s,pci_bus_num (vtd_as->bus), - vtd_as->devfn, &ce) && - domain_id ==vtd_get_domain_id (s, &ce, vtd_as->pasid)) { -if ((vtd_as->pasid !=PCI_NO_PASID || pasid !=IOMMU_NO_PASID ) && - vtd_as->pasid != pasid) { -continue ; - } + ret =vtd_dev_to_context_entry (s,pci_bus_num (vtd_as->bus), + vtd_as->devfn, &ce); +if (ret || vtd_as->pasid != pasid || + domain_id !=vtd_get_domain_id (s, &ce, pasid)) { +continue ; + } -if (!s->fsts || !vtd_as_has_map_notifier (vtd_as)) { -vtd_address_space_sync (vtd_as); - } +if (!s->fsts || !vtd_as_has_map_notifier (vtd_as)) { +vtd_address_space_sync (vtd_as); } } }
@@ -3239,7 +3218,7 @@ static bool vtd_process_pasid_desc(IntelIOMMUState *s,/* PASID selective implies a DID selective */ trace_vtd_inv_desc_pasid_cache_psi (did, pasid); pc_info.did = did; - pc_info.pasid = pasid ?:PCI_NO_PASID ; + pc_info.pasid = pasid;break ;case VTD_INV_DESC_PASIDC_G_GLOBAL :
@@ -3291,6 +3270,7 @@ static void do_invalidate_device_tlb(VTDAddressSpace *vtd_dev_as,* ... */ +uint32_t pasid = vtd_dev_as->pasid;IOMMUTLBEvent event;uint64_t sz;
@@ -3307,7 +3287,8 @@ static void do_invalidate_device_tlb(VTDAddressSpace *vtd_dev_as, event.entry.iova = addr; event.entry.perm =IOMMU_NONE ; event.entry.translated_addr =0 ; - event.entry.pasid = vtd_dev_as->pasid; +/* Other sub-systems use PCI pasid */ + event.entry.pasid = pasid ==IOMMU_NO_PASID ?PCI_NO_PASID : pasid;memory_region_notify_iommu (&vtd_dev_as->iommu,0 , event); }
@@ -3335,7 +3316,7 @@ static bool vtd_process_device_piotlb_desc(IntelIOMMUState *s, sid =VTD_INV_DESC_PASID_DEVICE_IOTLB_SID (inv_desc->lo);if (global) { QLIST_FOREACH(vtd_dev_as, &s->vtd_as_with_notifiers, next) { -if ((vtd_dev_as->pasid !=PCI_NO_PASID ) && +if ((vtd_dev_as->pasid !=IOMMU_NO_PASID ) && (PCI_BUILD_BDF (pci_bus_num (vtd_dev_as->bus), vtd_dev_as->devfn) == sid)) {do_invalidate_device_tlb (vtd_dev_as, size, addr);
@@ -3983,13 +3964,12 @@ static void vtd_mem_write(void *opaque, hwaddr addr, }static void vtd_prepare_identity_entry (hwaddr addr,IOMMUAccessFlags perm, -uint32_t pasid,IOMMUTLBEntry *iotlb) +IOMMUTLBEntry *iotlb) { iotlb->iova = addr &VTD_PAGE_MASK_4K ; iotlb->translated_addr = addr &VTD_PAGE_MASK_4K ; iotlb->addr_mask = ~VTD_PAGE_MASK_4K ; iotlb->perm = perm; - iotlb->pasid = pasid; }static inline void vtd_prepare_error_entry (IOMMUTLBEntry *entry)
@@ -4001,6 +3981,10 @@ static inline void vtd_prepare_error_entry(IOMMUTLBEntry *entry) entry->pasid =PCI_NO_PASID ; } +/* +* This function returns translation result to other sub-system such as PCI, +* so iommu pasid is converted to PCI pasid and returned in IOMMUTLBEntry. +*/ static IOMMUTLBEntry vtd_iommu_translate (IOMMUMemoryRegion *iommu,hwaddr addr,IOMMUAccessFlags flag,int iommu_idx) {
@@ -4009,7 +3993,7 @@ static IOMMUTLBEntry vtd_iommu_translate(IOMMUMemoryRegion *iommu, hwaddr addr,IOMMUTLBEntry iotlb = {/* We'll fill in the rest later. */ .target_as = &address_space_memory, - .pasid = vtd_as->pasid, + .pasid = vtd_as->pasid ==IOMMU_NO_PASID ?PCI_NO_PASID : vtd_as->pasid, };bool success;bool is_write = flag &IOMMU_WO ;
@@ -4017,9 +4001,8 @@ static IOMMUTLBEntry vtd_iommu_translate(IOMMUMemoryRegion *iommu, hwaddr addr,if (likely (s->dmar_enabled)) {/* Only support translated requests in scalable mode */ if (iommu_idx ==VTD_IDX_TRANSLATED && s->root_scalable) { -if (vtd_as->pasid ==PCI_NO_PASID ) { -vtd_prepare_identity_entry (addr,IOMMU_RW ,PCI_NO_PASID , - &iotlb); +if (vtd_as->pasid ==IOMMU_NO_PASID ) { +vtd_prepare_identity_entry (addr,IOMMU_RW , &iotlb); success = true; }else {vtd_prepare_error_entry (&iotlb);
@@ -4034,7 +4017,7 @@ static IOMMUTLBEntry vtd_iommu_translate(IOMMUMemoryRegion *iommu, hwaddr addr, } }else {/* DMAR disabled, passthrough, use 4k-page*/ -vtd_prepare_identity_entry (addr,IOMMU_RW , vtd_as->pasid, &iotlb); +vtd_prepare_identity_entry (addr,IOMMU_RW , &iotlb); success = true; }
@@ -4460,7 +4443,7 @@ static void vtd_report_sid_ir_illegal_access(IntelIOMMUState *s, uint16_t sid, }vtd_report_fault (s,VTD_FR_SM_INTERRUPT_ADDR , is_fpd_set, sid, addr, - is_write, pasid !=PCI_NO_PASID , pasid); + is_write, pasid !=IOMMU_NO_PASID , pasid); } static void vtd_report_ir_illegal_access(VTDAddressSpace *vtd_as,
@@ -4488,7 +4471,6 @@ static MemTxResult vtd_mem_ir_write(void *opaque, hwaddr addr,int ret =0 ;MSIMessage from = {}, to = {};uint16_t sid =X86_IOMMU_SID_INVALID ; -uint32_t pasid; from.address = (uint64_t ) addr +VTD_INTERRUPT_ADDR_FIRST ; from.data = (uint32_t ) value;
@@ -4496,11 +4478,11 @@ static MemTxResult vtd_mem_ir_write(void *opaque, hwaddr addr,if (!attrs.unspecified) {/* We have explicit Source ID */ sid = attrs.requester_id; - pasid = attrs.pid !=0 ? attrs.pid :PCI_NO_PASID ;if (attrs.address_type ==PCI_AT_TRANSLATED && sid !=X86_IOMMU_SID_INVALID ) { -vtd_report_sid_ir_illegal_access (s, sid, pasid, from.address, true); +vtd_report_sid_ir_illegal_access (s, sid, attrs.pid, from.address, + true);return MEMTX_ERROR ; } }
@@ -4562,9 +4544,19 @@ static const MemoryRegionOps vtd_mem_ir_fault_ops = { }, }; +/* +* This function is called by many PCIIOMMUOps callbacks to get +* VTDAddressSpace or create one if non-exist. Those callbacks are +* used by PCI sub-system and are passed in a PCI pasid value. +* +* VTD honors iommu pasid, so the first thing is to convert PCI +* pasid to iommu pasid. +*/ VTDAddressSpace *vtd_find_add_as (IntelIOMMUState *s,PCIBus *bus,int devfn,unsigned int pasid) { + pasid = pasid ==PCI_NO_PASID ?IOMMU_NO_PASID : pasid; +/* * We can't simply use sid here since the bus number might not be * initialized by the guest.
@@ -4606,7 +4598,7 @@ VTDAddressSpace *vtd_find_add_as(IntelIOMMUState *s, PCIBus *bus, new_key->devfn = devfn; new_key->pasid = pasid; -if (pasid ==PCI_NO_PASID ) { +if (pasid ==IOMMU_NO_PASID ) {snprintf (name,sizeof (name),"vtd-%02x.%x" ,PCI_SLOT (devfn),PCI_FUNC (devfn)); }else {
@@ -5290,7 +5282,7 @@ error_get_fpd_and_report:vtd_ce_get_pasid_fpd (s, &ce, &is_fpd_set, vtd_as->pasid); error_report:vtd_report_fault (s, -ret, is_fpd_set, sid, addr, is_write, - vtd_as->pasid !=PCI_NO_PASID , vtd_as->pasid); + vtd_as->pasid !=IOMMU_NO_PASID , vtd_as->pasid);return false; }
@@ -5381,7 +5373,7 @@ static int vtd_pri_request_page(PCIBus *bus, void *opaque, int devfn,*/ /* We do not support PRI without PASID */ -if (vtd_as->pasid ==PCI_NO_PASID ) { +if (vtd_as->pasid ==IOMMU_NO_PASID ) {return -EPERM ; }if (exec_req && !is_read) {
hw/i386/intel_iommu_accel.c +1 -1
@@ -207,7 +207,7 @@ static void vtd_flush_host_piotlb_locked(gpointer key, gpointer value,return ; } -assert (vtd_as->pasid ==PCI_NO_PASID ); +assert (vtd_as->pasid ==IOMMU_NO_PASID );/* Nothing to do if there is no first stage HWPT attached */ if (!pc_entry->valid ||
include/system/memory.h +1 -1
@@ -150,7 +150,7 @@ struct IOMMUTLBEntry {hwaddr translated_addr;hwaddr addr_mask;/* 0xfff = 4k translation */ IOMMUAccessFlags perm; -uint32_t pasid; +uint32_t pasid;/* PCI pasid */ };/*
Signature · 1 line
MST
[PULL 005/106] intel_iommu: Change 'flts' property naming to 'fsts'
In reply to Michael S. TsirkinFrom: Zhenzhong Duan <[email protected]>
Previous patch Removed 'x-' prefix from 'x-flts' property. Opportunistically, this patch does s/flts/fsts for property name in order to better align with newer spec since revision 3.4 which changed terminology from "First-level" to "First-stage".
Message-Id: <[email protected]>
--- docs/devel/vfio-iommufd.rst | 8 ++++---- hw/i386/intel_iommu.c | 10 +++++----- hw/i386/intel_iommu_accel.c | 6 +++--- tests/qtest/intel-iommu-test.c | 2 +- tests/qtest/iommu-intel-test.c | 2 +- 5 files changed, 14 insertions(+), 14 deletions(-)
docs/devel/vfio-iommufd.rst +4 -4
@@ -153,22 +153,22 @@ RAM discarding for mdev. ``vfio-ap`` and ``vfio-ccw`` devices don't have same issue as their backend devices are always mdev and RAM discarding is force enabled. -Usage with intel_iommu featuring flts=on +Usage with intel_iommu featuring fsts=on ------------------------------------------ Only IOMMUFD backed VFIO device is supported when intel_iommu is configured -with flts=on, for legacy container backed VFIO device, below error shows: +with fsts=on, for legacy container backed VFIO device, below error shows: .. code-block:: none - qemu-system-x86_64: -device vfio-pci,host=0000:02:00.0: vfio 0000:02:00.0: Failed to set vIOMMU: Need IOMMUFD backend when flts=on + qemu-system-x86_64: -device vfio-pci,host=0000:02:00.0: vfio 0000:02:00.0: Failed to set vIOMMU: Need IOMMUFD backend when fsts=on VFIO device under PCI bridge is unsupported, use PCIE bridge if necessary, otherwise below error shows: .. code-block:: none - qemu-system-x86_64: -device vfio-pci,host=0000:02:00.0,bus=bridge1,iommufd=iommufd0: vfio 0000:02:00.0: Failed to set vIOMMU: Host device downstream to a PCI bridge is unsupported when flts=on + qemu-system-x86_64: -device vfio-pci,host=0000:02:00.0,bus=bridge1,iommufd=iommufd0: vfio 0000:02:00.0: Failed to set vIOMMU: Host device downstream to a PCI bridge is unsupported when fsts=on If host IOMMU has ERRATA_772415_SPR17, running guest with "intel_iommu=on,sm_off" is unsupported, kexec or reboot guest from "intel_iommu=on,sm_on" to
hw/i386/intel_iommu.c +5 -5
@@ -4201,7 +4201,7 @@ static const Property vtd_properties[] = { VTD_HOST_ADDRESS_WIDTH),DEFINE_PROP_BOOL ("caching-mode" , IntelIOMMUState, caching_mode, FALSE),DEFINE_PROP_BOOL ("scalable-mode" , IntelIOMMUState, scalable_mode, FALSE), -DEFINE_PROP_BOOL ("flts" , IntelIOMMUState, fsts, FALSE), +DEFINE_PROP_BOOL ("fsts" , IntelIOMMUState, fsts, FALSE),DEFINE_PROP_BOOL ("snoop-control" , IntelIOMMUState, snoop_control, false),DEFINE_PROP_BOOL ("x-pasid-mode" , IntelIOMMUState, pasid, false), DEFINE_PROP_BOOL("svm", IntelIOMMUState, svm, false),
@@ -5563,20 +5563,20 @@ static bool vtd_decide_config(IntelIOMMUState *s, Error **errp) }if (!s->scalable_mode && s->fsts) { -error_setg (errp,"flts is only available in scalable mode" ); +error_setg (errp,"fsts is only available in scalable mode" );return false; }if (!s->fsts && s->aw_bits !=VTD_HOST_AW_39BIT && s->aw_bits !=VTD_HOST_AW_48BIT ) {error_setg (errp,"%s: supported values for aw-bits are: %d, %d" , - s->scalable_mode ?"Scalable mode(flts=off)" :"Legacy mode" , + s->scalable_mode ?"Scalable mode(fsts=off)" :"Legacy mode" ,VTD_HOST_AW_39BIT ,VTD_HOST_AW_48BIT );return false; }if (s->fsts && s->aw_bits !=VTD_HOST_AW_48BIT ) { -error_setg (errp,"Scalable mode(flts=on): supported value for " +error_setg (errp,"Scalable mode(fsts=on): supported value for " "aw-bits is: %d" ,VTD_HOST_AW_48BIT );return false; }
@@ -5593,7 +5593,7 @@ static bool vtd_decide_config(IntelIOMMUState *s, Error **errp) }if (!s->fsts) { -error_setg (errp,"Need to set flts for svm" ); +error_setg (errp,"Need to set fsts for svm" );return false; }
hw/i386/intel_iommu_accel.c +3 -3
@@ -26,7 +26,7 @@ bool vtd_check_hiod_accel(IntelIOMMUState *s, VTDHostIOMMUDevice *vtd_hiod,PCIDevice *pdev = bus->devices[vtd_hiod->devfn];if (!object_dynamic_cast (OBJECT (hiod),TYPE_HOST_IOMMU_DEVICE_IOMMUFD )) { -error_setg (errp,"Need IOMMUFD backend when flts=on" ); +error_setg (errp,"Need IOMMUFD backend when fsts=on" );return false; }
@@ -44,7 +44,7 @@ bool vtd_check_hiod_accel(IntelIOMMUState *s, VTDHostIOMMUDevice *vtd_hiod,if (pci_device_get_iommu_bus_devfn (pdev, &bus,NULL ,NULL )) {error_setg (errp,"Host device downstream to a PCI bridge is " -"unsupported when flts=on" ); +"unsupported when fsts=on" );return false; }
@@ -105,7 +105,7 @@ static bool vtd_device_attach_iommufd(VTDHostIOMMUDevice *vtd_hiod,bool ret;/* -* We can get here only if flts=on, the supported PGTT is FST or PT. +* We can get here only if fsts=on, the supported PGTT is FST or PT. * Catch invalid PGTT when processing invalidation request to avoid * attaching to wrong hwpt. */
tests/qtest/intel-iommu-test.c +1 -1
@@ -29,7 +29,7 @@ static void test_intel_iommu_stage_1(void)uint64_t cap, ecap, tmp;QTestState *s; - s =qtest_init ("-M q35 -device intel-iommu,scalable-mode=on,flts=on" ); + s =qtest_init ("-M q35 -device intel-iommu,scalable-mode=on,fsts=on" ); cap =vtd_reg_readq (s,DMAR_CAP_REG );g_assert ((cap &CAP_STAGE_1_FIXED1 ) ==CAP_STAGE_1_FIXED1 );
tests/qtest/iommu-intel-test.c +1 -1
@@ -54,7 +54,7 @@ static const char *qvtd_iommu_args(QVTDTransMode mode) {switch (mode) {case QVTD_TM_SCALABLE_FLT : -return "-device intel-iommu,scalable-mode=on,flts=on " ; +return "-device intel-iommu,scalable-mode=on,fsts=on " ;case QVTD_TM_SCALABLE_PT :case QVTD_TM_SCALABLE_SLT :return "-device intel-iommu,scalable-mode=on " ;
Signature · 1 line
MST
[PULL 034/106] virtio: drop *_set_guest_notifier_fd_handler() helpers
In reply to Michael S. TsirkinFrom: Vladimir Sementsov-Ogievskiy <[email protected]>
Now they don't make code more readable. Let's better put the whole logic into virtio_queue_set_guest_notifier().
Message-Id: <[email protected]>
--- hw/virtio/virtio.c | 75 +++++++++++----------------------------------- 1 file changed, 17 insertions(+), 58 deletions(-)
hw/virtio/virtio.c +17 -58
@@ -3836,73 +3836,32 @@ static void virtio_config_guest_notifier_read(EventNotifier *n) } } -static void virtio_queue_set_guest_notifier_fd_handler (VirtQueue *vq, -bool assign, -bool with_irqfd) -{ -if (assign && !with_irqfd) { -event_notifier_set_handler (&vq->guest_notifier, - virtio_queue_guest_notifier_read); - }else { -event_notifier_set_handler (&vq->guest_notifier,NULL ); - } -if (!assign) { -/* Test and clear notifier before closing it, -* in case poll callback didn't have time to run. */ -virtio_queue_guest_notifier_read (&vq->guest_notifier); - } -} - -static 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); - } -} - -static void virtio_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); - } -} -int virtio_set_guest_notifier (VirtIODevice *vdev,int n,bool assign,bool with_irqfd) { -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); - } +bool is_config = n ==VIRTIO_CONFIG_IRQ_IDX ; +VirtQueue *vq = is_config ?NULL :virtio_get_queue (vdev, n); +EventNotifier *notifier = is_config ? +virtio_config_get_guest_notifier (vdev) : +virtio_queue_get_guest_notifier (vq); +EventNotifierHandler *read_fn = is_config ? + virtio_config_guest_notifier_read : + virtio_queue_guest_notifier_read;if (assign) {int r =event_notifier_init (notifier,0 );if (r <0 ) {return r; } -virtio_set_guest_notifier_fd_handler (vdev, vq, n, true, with_irqfd); - }else { -virtio_set_guest_notifier_fd_handler (vdev, vq, n, false, with_irqfd); + } + +event_notifier_set_handler (notifier, + (assign && !with_irqfd) ? read_fn :NULL ); + +if (!assign) { +/* Test and clear notifier before closing it,*/ +/* in case poll callback didn't have time to run. */ +read_fn (notifier);event_notifier_cleanup (notifier); }
Signature · 1 line
MST
[PULL 033/106] virtio: move common part of _set_guest_notifier to generic code
In reply to Michael S. TsirkinFrom: Vladimir Sementsov-Ogievskiy <[email protected]>
virtio-pci, virtio-mmio and virtio-ccw handle config notifier equally but with different code (mmio adds a separate function, when pci use common function). Let's chose the more compact way (pci) and reuse it for mmio.
Message-Id: <[email protected]>
--- hw/s390x/virtio-ccw.c | 35 ++++++++++++------------- hw/virtio/virtio-mmio.c | 41 +++++------------------------ hw/virtio/virtio-pci.c | 34 +++--------------------- hw/virtio/virtio.c | 47 +++++++++++++++++++++++++++++++--- include/hw/virtio/virtio-pci.h | 3 --- include/hw/virtio/virtio.h | 15 ++++++++--- 6 files changed, 82 insertions(+), 93 deletions(-)
hw/s390x/virtio-ccw.c +17 -18
@@ -1025,20 +1025,27 @@ static int virtio_ccw_set_guest_notifier(VirtioCcwDevice *dev, int n,VirtQueue *vq =virtio_get_queue (vdev, n);EventNotifier *notifier =virtio_queue_get_guest_notifier (vq);VirtioDeviceClass *k =VIRTIO_DEVICE_GET_CLASS (vdev); +int r; + +if (!assign) { +if (k->guest_notifier_mask && vdev->use_guest_notifier_mask) { + k->guest_notifier_mask (vdev, n, true); + } +if (with_irqfd) { +virtio_ccw_remove_irqfd (dev, n); + } + } + + r =virtio_set_guest_notifier (vdev, n, assign, with_irqfd); +if (r <0 ) { +return r; + }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);if (with_irqfd) { r =virtio_ccw_add_irqfd (dev, n);if (r) { -virtio_queue_set_guest_notifier_fd_handler (vq, false, - with_irqfd); -event_notifier_cleanup (notifier); +virtio_set_guest_notifier (vdev, n, false, with_irqfd);return r; } }
@@ -1054,16 +1061,8 @@ static int virtio_ccw_set_guest_notifier(VirtioCcwDevice *dev, int n, k->guest_notifier_pending(vdev, n)) {event_notifier_set (notifier); } - }else { -if (k->guest_notifier_mask && vdev->use_guest_notifier_mask) { - k->guest_notifier_mask (vdev, n, true); - } -if (with_irqfd) { -virtio_ccw_remove_irqfd (dev, n); - } -virtio_queue_set_guest_notifier_fd_handler (vq, false, with_irqfd); -event_notifier_cleanup (notifier); } +return 0 ; }
hw/virtio/virtio-mmio.c +6 -35
61 lines not on this page · raw message
hw/virtio/virtio-pci.c +4 -30
@@ -1208,43 +1208,17 @@ static void virtio_pci_vector_poll(PCIDevice *dev, } } -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,bool with_irqfd) {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 ; +int r; -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_pci_set_guest_notifier_fd_handler (vdev, vq, n, true, with_irqfd); - }else { -virtio_pci_set_guest_notifier_fd_handler (vdev, vq, n, false, - with_irqfd); -event_notifier_cleanup (notifier); + r =virtio_set_guest_notifier (vdev, n, assign, with_irqfd); +if (r <0 ) { +return r; } if (!msix_enabled(&proxy->pci_dev) &&
hw/virtio/virtio.c +44 -3
65 lines not on this page · raw message
include/hw/virtio/virtio-pci.h +0 -3
@@ -250,9 +250,6 @@ 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);int virtio_pci_add_shm_cap (VirtIOPCIProxy *proxy,uint8_t bar,uint64_t offset,uint64_t length,uint8_t id);
include/hw/virtio/virtio.h +11 -4
@@ -420,8 +420,6 @@ void virtio_queue_update_used_idx(VirtIODevice *vdev, int n);VirtQueue *virtio_get_queue (VirtIODevice *vdev,int n);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);int virtio_device_start_ioeventfd (VirtIODevice *vdev);int virtio_device_grab_ioeventfd (VirtIODevice *vdev);void virtio_device_release_ioeventfd (VirtIODevice *vdev);
@@ -435,8 +433,17 @@ void virtio_queue_aio_detach_host_notifier(VirtQueue *vq, AioContext *ctx);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); + +/** +* virtio_set_guest_notifier - set/unset queue or config guest notifier +* +* @vdev: the VirtIO device +* @n: queue number, or VIRTIO_CONFIG_IRQ_IDX to set config notifer +* @assign: true to set notifier, false to unset +* @with_irqfd: irqfd enabled +*/ +int virtio_set_guest_notifier (VirtIODevice *vdev,int n,bool assign, +bool with_irqfd);static inline void virtio_add_feature (uint64_t *features,unsigned int fbit) {
Signature · 1 line
MST
[PULL 025/106] hw/char/serial-isa.c: declare IRQ as shared in ACPI IRQ descriptor
In reply to Michael S. TsirkinFrom: Mark Cave-Ayland <[email protected]>
From Windows 8.1 onwards ISA serial IRQs cannot be shared when ACPI Revision 3.0 is used in the FACP table. The reason for this is that if a 2-byte IRQ Descriptor is used then the interrupt is considered to be high true, edge sensitive, non-shareable. Since legacy serial ports COM1/3 and COM2/4 share an IRQ then if more than 2 serial ports are added, Windows indicates a conflict in Device Manager and these combinations cannot be used together.
Change the 2-byte IRQ Descriptor in the _CRS resource to a 3-byte IRQ Descriptor indicating that the ISA serial IRQ is low true, level sensitive and shareable. This enables all 4 legacy serial ports to be used in Windows without conflict.
Note that it was agreed during the list discussion that this change does not require a compatibility property since it is not part of the default machine configuration and was already broken.
Message-Id: <[email protected]>
--- hw/char/serial-isa.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
hw/char/serial-isa.c +2 -1
@@ -92,7 +92,8 @@ static void serial_isa_build_aml(AcpiDevAmlIf *adev, Aml *scope) crs =aml_resource_template ();aml_append (crs,aml_io (AML_DECODE16 , isa->iobase, isa->iobase,0x00 ,0x08 )); -aml_append (crs,aml_irq_no_flags (isa->isairq)); +aml_append (crs,aml_irq (isa->isairq,AML_LEVEL ,AML_ACTIVE_LOW , +AML_SHARED )); dev =aml_device ("COM%d" , isa->index +1 );aml_append (dev,aml_name_decl ("_HID" ,aml_eisaid ("PNP0501" )));
Signature · 1 line
MST
[PULL 019/106] intel_iommu_accel: Handle PASID entry removal for system reset
In reply to Michael S. TsirkinFrom: Zhenzhong Duan <[email protected]>
When system level reset, DMA translation is turned off, all PASID entries become stale and should be deleted.
vtd_hiod list is never accessed without BQL, so no need to guard with iommu lock.
Message-Id: <[email protected]>
--- hw/i386/intel_iommu.c | 2 ++ hw/i386/intel_iommu_accel.c | 13 +++++++++++++ hw/i386/intel_iommu_accel.h | 5 +++++ 3 files changed, 20 insertions(+)
hw/i386/intel_iommu.c +2 -0
@@ -391,6 +391,8 @@ static void vtd_reset_caches(IntelIOMMUState *s)vtd_reset_context_cache_locked (s);vtd_pasid_cache_reset_locked (s);vtd_iommu_unlock (s); + +vtd_accel_pasid_cache_reset (s); }static uint64_t vtd_get_iotlb_gfn (hwaddr addr,uint32_t level)
hw/i386/intel_iommu_accel.c +13 -0
@@ -486,6 +486,19 @@ void vtd_accel_pasid_cache_sync(IntelIOMMUState *s, VTDPASIDCacheInfo *pc_info) } } +/* Fake a global pasid cache invalidation to remove all pasid cache entries */ +void vtd_accel_pasid_cache_reset (IntelIOMMUState *s) +{ +VTDPASIDCacheInfo pc_info = { .type =VTD_INV_DESC_PASIDC_G_GLOBAL }; +VTDHostIOMMUDevice *vtd_hiod; +GHashTableIter hiod_it; + +g_hash_table_iter_init (&hiod_it, s->vtd_host_iommu_dev); +while (g_hash_table_iter_next (&hiod_it,NULL , (void **)&vtd_hiod)) { +vtd_accel_pasid_cache_invalidate (vtd_hiod, &pc_info); + } +} +static uint64_t vtd_get_host_iommu_quirks (uint32_t type,void *caps,uint32_t size) {
hw/i386/intel_iommu_accel.h +5 -0
@@ -28,6 +28,7 @@ void vtd_flush_host_piotlb_all_locked(IntelIOMMUState *s, uint16_t domain_id, uint32_t pasid, hwaddr addr, uint64_t npages, bool ih);void vtd_accel_pasid_cache_sync (IntelIOMMUState *s,VTDPASIDCacheInfo *pc_info); +void vtd_accel_pasid_cache_reset (IntelIOMMUState *s);void vtd_iommu_ops_update_accel (PCIIOMMUOps *ops);#else static inline bool vtd_check_hiod_accel(IntelIOMMUState *s,
@@ -62,6 +63,10 @@ static inline void vtd_accel_pasid_cache_sync(IntelIOMMUState *s, { } +static inline void vtd_accel_pasid_cache_reset (IntelIOMMUState *s) +{ +} +static inline void vtd_iommu_ops_update_accel (PCIIOMMUOps *ops) { }
Signature · 1 line
MST
[PULL 017/106] intel_iommu_accel: Handle PASID entry removal for pc_inv_dsc request
In reply to Michael S. TsirkinFrom: Zhenzhong Duan <[email protected]>
When guest deletes PASID entries, QEMU will capture the pasid cache invalidation request, walk through pasid_cache_list in each passthrough device to find stale VTDAccelPASIDCacheEntry and delete them.
Message-Id: <[email protected]>
--- hw/i386/intel_iommu_accel.c | 61 +++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+)
hw/i386/intel_iommu_accel.c +61 -0
@@ -280,6 +280,59 @@ static void vtd_accel_fill_pc(VTDHostIOMMUDevice *vtd_hiod, uint32_t pasid,QLIST_INSERT_HEAD (&vtd_hiod->pasid_cache_list, vtd_pce, next); } +static void vtd_accel_delete_pc (VTDAccelPASIDCacheEntry *vtd_pce) +{ +QLIST_REMOVE (vtd_pce, next); +g_free (vtd_pce); +} + +static void +vtd_accel_pasid_cache_invalidate_one (VTDAccelPASIDCacheEntry *vtd_pce, +VTDPASIDCacheInfo *pc_info) +{ +VTDHostIOMMUDevice *vtd_hiod = vtd_pce->vtd_hiod; +VTDPASIDEntry pe; +uint16_t did; + +/* +* VTD_INV_DESC_PASIDC_G_DSI and VTD_INV_DESC_PASIDC_G_PASID_SI require +* DID check. If DID doesn't match the value in cache or memory, then +* it's not a pasid entry we want to invalidate. +*/ +switch (pc_info->type) { +case VTD_INV_DESC_PASIDC_G_PASID_SI : +if (pc_info->pasid != vtd_pce->pasid) { +return ; + } +/* Fall through */ +case VTD_INV_DESC_PASIDC_G_DSI : + did =VTD_SM_PASID_ENTRY_DID (&vtd_pce->pasid_entry); +if (pc_info->did != did) { +return ; + } + } + +if (vtd_dev_get_pe_from_pasid (vtd_hiod->iommu_state, vtd_hiod->bus, + vtd_hiod->devfn, vtd_pce->pasid, &pe)) { +/* +* No valid pasid entry in guest memory. e.g. pasid entry was modified +* to be either all-zero or non-present. Either case means existing +* pasid cache should be invalidated. +*/ +vtd_accel_delete_pc (vtd_pce); + } +} + +static void vtd_accel_pasid_cache_invalidate (VTDHostIOMMUDevice *vtd_hiod, +VTDPASIDCacheInfo *pc_info) +{ +VTDAccelPASIDCacheEntry *vtd_pce, *next; + + QLIST_FOREACH_SAFE(vtd_pce, &vtd_hiod->pasid_cache_list, next, next) { +vtd_accel_pasid_cache_invalidate_one (vtd_pce, pc_info); + } +} +/* * This function walks over PASID range within [start, end) in a single * PASID table for entries matching @info type/did, then create
@@ -411,6 +464,14 @@ void vtd_accel_pasid_cache_sync(IntelIOMMUState *s, VTDPASIDCacheInfo *pc_info) TYPE_HOST_IOMMU_DEVICE_IOMMUFD)) {continue ; } + +/* +* The replay path inevitably needs to iterate through existing +* PASID cache entries. Since cached PASID entries that are marked +* for removal don't need to be iterated, we intentionally handle +* removals before additions to optimize the replay process. +*/ +vtd_accel_pasid_cache_invalidate (vtd_hiod, pc_info);vtd_accel_replay_pasid_bind_for_dev (vtd_hiod, start, end, pc_info); } }
Signature · 1 line
MST
[PULL 036/106] vhost: vhost_virtqueue_start(): fix failure path
In reply to Michael S. TsirkinFrom: Vladimir Sementsov-Ogievskiy <[email protected]>
We miss call to unmap in cases when vhost_memory_map() returns lenght less than requested (still we consider such cases as an error). Let's fix it in vhost_memory_map().
Message-Id: <[email protected]>
--- hw/virtio/vhost.c | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-)
hw/virtio/vhost.c +18 -9
@@ -454,11 +454,20 @@ static inline void vhost_dev_log_resize(struct vhost_dev *dev, uint64_t size) }static void *vhost_memory_map (struct vhost_dev *dev,hwaddr addr, -hwaddr *plen,bool is_write) +hwaddr len,bool is_write) {if (!vhost_dev_has_iommu (dev)) { -return address_space_map (dev->vdev->dma_as, addr, plen, is_write, -MEMTXATTRS_UNSPECIFIED ); +hwaddr mapped_len = len; +void *res =address_space_map (dev->vdev->dma_as, addr, &mapped_len, + is_write,MEMTXATTRS_UNSPECIFIED ); +if (!res) { +return NULL ; + } +if (len != mapped_len) { +address_space_unmap (dev->vdev->dma_as, res, mapped_len,0 ,0 ); +return NULL ; + } +return res; }else {return (void *)(uintptr_t )addr; }
@@ -1312,22 +1321,22 @@ int vhost_virtqueue_start(struct vhost_dev *dev, } l = vq->desc_size; - vq->desc =vhost_memory_map (dev, vq->desc_phys, &l, false); -if (!vq->desc || l != vq->desc_size) { + vq->desc =vhost_memory_map (dev, vq->desc_phys, l, false); +if (!vq->desc) { r = -ENOMEM ; goto fail_alloc_desc; } l = vq->avail_size; - vq->avail =vhost_memory_map (dev, vq->avail_phys, &l, false); -if (!vq->avail || l != vq->avail_size) { + vq->avail =vhost_memory_map (dev, vq->avail_phys, l, false); +if (!vq->avail) { r = -ENOMEM ; goto fail_alloc_avail; } l = vq->used_size; - vq->used =vhost_memory_map (dev, vq->used_phys, &l, true); -if (!vq->used || l != vq->used_size) { + vq->used =vhost_memory_map (dev, vq->used_phys, l, true); +if (!vq->used) { r = -ENOMEM ; goto fail_alloc_used; }
Signature · 1 line
MST
[PULL 028/106] vhost: drop backend_features field
In reply to Michael S. TsirkinFrom: Vladimir Sementsov-Ogievskiy <[email protected]>
This field is mostly unused and sometimes confusing. We even have a TODO-like comment to drop it, the comment is removed in this commit.
The field is used to held VHOST_USER_F_PROTOCOL_FEATURES for vhost-user and/or VHOST_NET_F_VIRTIO_NET_HDR for vhost-net (which may be vhost-user-net). But we can simply recalculate these two flags in place from hdev->features, and from net-client for VHOST_NET_F_VIRTIO_NET_HDR.
Note: removing field from x-query-virtio-status result is incompatible change. We can do it because the command is unstable.
Message-Id: <[email protected]>
--- hw/block/vhost-user-blk.c | 1 - hw/net/vhost_net.c | 26 ++++++++++++++------------ hw/scsi/vhost-scsi.c | 1 - hw/scsi/vhost-user-scsi.c | 1 - hw/virtio/vdpa-dev.c | 1 - hw/virtio/vhost-user.c | 17 ++++++++--------- hw/virtio/virtio-hmp-cmds.c | 2 -- hw/virtio/virtio-qmp.c | 4 ---- include/hw/virtio/vhost.h | 7 ------- qapi/virtio.json | 3 --- 10 files changed, 22 insertions(+), 41 deletions(-)
hw/block/vhost-user-blk.c +0 -1
@@ -348,7 +348,6 @@ static int vhost_user_blk_connect(DeviceState *dev, Error **errp) s->dev.nvqs = s->num_queues; s->dev.vqs = s->vhost_vqs; s->dev.vq_index =0 ; - s->dev.backend_features =0 ;vhost_dev_set_config_notifier (&s->dev, &blk_ops);
hw/net/vhost_net.c +14 -12
@@ -52,8 +52,14 @@ int vhost_net_set_config(struct vhost_net *net, const uint8_t *data,void vhost_net_ack_features_ex (struct vhost_net *net,const uint64_t *features) { -virtio_features_copy (net->dev.acked_features_ex, - net->dev.backend_features_ex); +virtio_features_clear (net->dev.acked_features_ex); +if (net->backend ==-1 ) { + net->dev.acked_features = + net->dev.features & (1ULL <<VHOST_USER_F_PROTOCOL_FEATURES ); + }else if (!qemu_has_vnet_hdr (net->nc)) { + net->dev.acked_features =1ULL <<VHOST_NET_F_VIRTIO_NET_HDR ; + } +vhost_ack_features_ex (&net->dev, net->feature_bits, features); }
@@ -258,12 +264,9 @@ struct vhost_net *vhost_net_init(VhostNetOptions *options)if (r <0 ) { goto fail; } - net->dev.backend_features =qemu_has_vnet_hdr (options->net_backend) - ?0 : (1ULL <<VHOST_NET_F_VIRTIO_NET_HDR ); net->backend = r; net->dev.protocol_features =0 ; }else { -virtio_features_clear (net->dev.backend_features_ex); net->dev.protocol_features =0 ; net->backend =-1 ;
@@ -284,13 +287,12 @@ struct vhost_net *vhost_net_init(VhostNetOptions *options) net->dev.features &= ~(1ULL <<VIRTIO_NET_F_MRG_RXBUF ); } -if (virtio_features_andnot (missing_features, - net->dev.backend_features_ex, - net->dev.features_ex)) { -fprintf (stderr,"vhost lacks feature mask 0x" VIRTIO_FEATURES_FMT -" for backend\n" ,VIRTIO_FEATURES_PR (missing_features)); - goto fail; - } +if (!qemu_has_vnet_hdr (options->net_backend) && + (~net->dev.features & (1ULL <<VHOST_NET_F_VIRTIO_NET_HDR ))) { +fprintf (stderr,"vhost lacks feature mask 0x%llx for backend\n" , + ~net->dev.features & (1ULL <<VHOST_NET_F_VIRTIO_NET_HDR )); + goto fail; + } }/* Set sane init value. Override when guest acks. */
hw/scsi/vhost-scsi.c +0 -1
@@ -275,7 +275,6 @@ static void vhost_scsi_realize(DeviceState *dev, Error **errp) vqs = g_new0(struct vhost_virtqueue, vsc->dev.nvqs); vsc->dev.vqs = vqs; vsc->dev.vq_index =0 ; - vsc->dev.backend_features =0 ; ret =vhost_dev_init (&vsc->dev, (void *)(uintptr_t )vhostfd,VHOST_BACKEND_TYPE_KERNEL ,0 , errp);
hw/scsi/vhost-user-scsi.c +0 -1
@@ -159,7 +159,6 @@ static int vhost_user_scsi_connect(DeviceState *dev, Error **errp) vsc->dev.nvqs =VIRTIO_SCSI_VQ_NUM_FIXED + vs->conf.num_queues; vsc->dev.vqs = s->vhost_vqs; vsc->dev.vq_index =0 ; - vsc->dev.backend_features =0 ; ret =vhost_dev_init (&vsc->dev, &s->vhost_user,VHOST_BACKEND_TYPE_USER ,0 , errp);
hw/virtio/vdpa-dev.c +0 -1
@@ -104,7 +104,6 @@ static void vhost_vdpa_device_realize(DeviceState *dev, Error **errp) v->dev.vqs = vqs; v->dev.vq_index =0 ; v->dev.vq_index_end = v->dev.nvqs; - v->dev.backend_features =0 ; v->started = false; ret =vhost_vdpa_get_iova_range (v->vhostfd, &iova_range);
hw/virtio/vhost-user.c +8 -9
@@ -1465,14 +1465,15 @@ static int vhost_user_set_features(struct vhost_dev *dev,int ret;/* -* We need to include any extra backend only feature bits that -* might be needed by our device. Currently this includes the -* VHOST_USER_F_PROTOCOL_FEATURES bit for enabling protocol -* features. +* Don't lose VHOST_USER_F_PROTOCOL_FEATURES, which is vhost-user +* specific. */ - ret =vhost_user_set_u64 (dev,VHOST_USER_SET_FEATURES , - features | dev->backend_features, - log_enabled); +if (virtio_has_feature (dev->features,VHOST_USER_F_PROTOCOL_FEATURES )) { + features |=1ULL <<VHOST_USER_F_PROTOCOL_FEATURES ; + } + + ret =vhost_user_set_u64 (dev,VHOST_USER_SET_FEATURES , features, + log_enabled);if (virtio_has_feature (dev->protocol_features,VHOST_USER_PROTOCOL_F_STATUS )) {
@@ -2192,8 +2193,6 @@ static int vhost_user_backend_init(struct vhost_dev *dev, void *opaque, (dev->config_ops && dev->config_ops->vhost_dev_config_notifier);uint64_t protocol_features; - dev->backend_features |=1ULL <<VHOST_USER_F_PROTOCOL_FEATURES ; - err =vhost_user_get_u64 (dev,VHOST_USER_GET_PROTOCOL_FEATURES , &protocol_features);if (err <0 ) {
hw/virtio/virtio-hmp-cmds.c +0 -2
@@ -176,8 +176,6 @@ void hmp_virtio_status(Monitor *mon, const QDict *qdict)hmp_virtio_dump_features (mon, s->vhost_dev->features);monitor_printf (mon," Acked features:\n" );hmp_virtio_dump_features (mon, s->vhost_dev->acked_features); -monitor_printf (mon," Backend features:\n" ); -hmp_virtio_dump_features (mon, s->vhost_dev->backend_features);monitor_printf (mon," Protocol features:\n" );hmp_virtio_dump_protocols (mon, s->vhost_dev->protocol_features); }
hw/virtio/virtio-qmp.c +0 -4
@@ -710,8 +710,6 @@ VirtioStatus *qmp_x_query_virtio_status(const char *path, Error **errp) vdev->guest_features_ex); status->host_features =qmp_decode_features (vdev->device_id, vdev->host_features_ex); - status->backend_features =qmp_decode_features (vdev->device_id, - vdev->backend_features_ex);switch (vdev->device_endian) {case VIRTIO_DEVICE_ENDIAN_LITTLE :
@@ -752,8 +750,6 @@ VirtioStatus *qmp_x_query_virtio_status(const char *path, Error **errp)qmp_decode_features (vdev->device_id, hdev->features_ex); status->vhost_dev->acked_features =qmp_decode_features (vdev->device_id, hdev->acked_features_ex); - status->vhost_dev->backend_features = -qmp_decode_features (vdev->device_id, hdev->backend_features_ex); status->vhost_dev->protocol_features =qmp_decode_protocols (hdev->protocol_features);
include/hw/virtio/vhost.h +0 -7
@@ -100,16 +100,9 @@ struct vhost_dev {* * @features: available features provided by the backend * @acked_features: final negotiated features with front-end driver -* -* @backend_features: this is used in a couple of places to either -* store VHOST_USER_F_PROTOCOL_FEATURES to apply to -* VHOST_USER_SET_FEATURES or VHOST_NET_F_VIRTIO_NET_HDR. Its -* future use should be discouraged and the variable retired as -* its easy to confuse with the VirtIO backend_features. */ VIRTIO_DECLARE_FEATURES (features);VIRTIO_DECLARE_FEATURES (acked_features); -VIRTIO_DECLARE_FEATURES (backend_features);/** * @protocol_features: is the vhost-user only feature set by
qapi/virtio.json +0 -3
@@ -85,8 +85,6 @@ # # @acked-features: vhost_dev acked_features # -# @backend-features: vhost_dev backend_features -# # @protocol-features: vhost_dev protocol_features # # @max-queues: vhost_dev max_queues
@@ -106,7 +104,6 @@ 'vq-index': 'int', 'features': 'VirtioDeviceFeatures', 'acked-features': 'VirtioDeviceFeatures', - 'backend-features': 'VirtioDeviceFeatures', 'protocol-features': 'VhostDeviceProtocols', 'max-queues': 'uint64', 'backend-cap': 'uint64',
Signature · 1 line
MST
[PULL 049/106] vhost: move IOTLB functions from vhost-backend.c to vhost.c
In reply to Michael S. TsirkinFrom: Vladimir Sementsov-Ogievskiy <[email protected]>
Move and rename vhost_backend_update_device_iotlb(), vhost_backend_invalidate_device_iotlb(), and vhost_backend_handle_iotlb_msg() from vhost-backend.c to vhost.c. vhost-backend.c is actually about vhost-kernel backend. But these functions are shared with vhost-user, so let's move them into generic place. Moreover, two of three functions becomes static as they are used only in vhost.c.
Based-on: <[email protected]>
Message-Id: <[email protected]>
--- hw/virtio/vhost-backend.c | 82 +---------------------------- hw/virtio/vhost-user.c | 2 +- hw/virtio/vhost.c | 85 +++++++++++++++++++++++++++++-- include/hw/virtio/vhost-backend.h | 11 ---- include/hw/virtio/vhost.h | 2 + 5 files changed, 86 insertions(+), 96 deletions(-)
hw/virtio/vhost-backend.c +2 -80
@@ -298,7 +298,7 @@ static void vhost_kernel_iotlb_read(void *opaque)break ; } -vhost_backend_handle_iotlb_msg (dev, &msg.iotlb); +vhost_handle_iotlb_msg (dev, &msg.iotlb); } }else {struct vhost_msg msg;
@@ -313,7 +313,7 @@ static void vhost_kernel_iotlb_read(void *opaque)break ; } -vhost_backend_handle_iotlb_msg (dev, &msg.iotlb); +vhost_handle_iotlb_msg (dev, &msg.iotlb); } } }
@@ -392,81 +392,3 @@ const VhostOps kernel_ops = { .vhost_send_device_iotlb_msg = vhost_kernel_send_device_iotlb_msg, };#endif - -int vhost_backend_update_device_iotlb (struct vhost_dev *dev, -uint64_t iova,uint64_t uaddr, -uint64_t len, -IOMMUAccessFlags perm) -{ -struct vhost_iotlb_msg imsg; - - imsg.iova = iova; - imsg.uaddr = uaddr; - imsg.size = len; - imsg.type =VHOST_IOTLB_UPDATE ; - -switch (perm) { -case IOMMU_RO : - imsg.perm =VHOST_ACCESS_RO ; -break ; -case IOMMU_WO : - imsg.perm =VHOST_ACCESS_WO ; -break ; -case IOMMU_RW : - imsg.perm =VHOST_ACCESS_RW ; -break ; -default : -return -EINVAL ; - } - -if (dev->vhost_ops && dev->vhost_ops->vhost_send_device_iotlb_msg) -return dev->vhost_ops->vhost_send_device_iotlb_msg (dev, &imsg); - -return -ENODEV ; -} - -int vhost_backend_invalidate_device_iotlb (struct vhost_dev *dev, -uint64_t iova,uint64_t len) -{ -struct vhost_iotlb_msg imsg; - - imsg.iova = iova; - imsg.size = len; - imsg.type =VHOST_IOTLB_INVALIDATE ; - -if (dev->vhost_ops && dev->vhost_ops->vhost_send_device_iotlb_msg) -return dev->vhost_ops->vhost_send_device_iotlb_msg (dev, &imsg); - -return -ENODEV ; -} - -int vhost_backend_handle_iotlb_msg (struct vhost_dev *dev, -struct vhost_iotlb_msg *imsg) -{ -int ret =0 ; - -if (unlikely (!dev->vdev)) { -error_report ("Unexpected IOTLB message when virtio device is stopped" ); -return -EINVAL ; - } - -switch (imsg->type) { -case VHOST_IOTLB_MISS : - ret =vhost_device_iotlb_miss (dev, imsg->iova, - imsg->perm !=VHOST_ACCESS_RO ); -break ; -case VHOST_IOTLB_ACCESS_FAIL : -/* FIXME: report device iotlb error */ -error_report ("Access failure IOTLB message type not supported" ); - ret = -ENOTSUP ; -break ; -case VHOST_IOTLB_UPDATE : -case VHOST_IOTLB_INVALIDATE : -default : -error_report ("Unexpected IOTLB message type" ); - ret = -EINVAL ; -break ; - } - -return ret; -}
hw/virtio/vhost-user.c +1 -1
@@ -1901,7 +1901,7 @@ static gboolean backend_read(QIOChannel *ioc, GIOCondition condition,switch (hdr.request) {case VHOST_USER_BACKEND_IOTLB_MSG : - ret =vhost_backend_handle_iotlb_msg (dev, &payload.iotlb); + ret =vhost_handle_iotlb_msg (dev, &payload.iotlb);break ;case VHOST_USER_BACKEND_CONFIG_CHANGE_MSG : ret =vhost_user_backend_handle_config_change (dev);
hw/virtio/vhost.c +81 -4
103 lines not on this page · raw message
include/hw/virtio/vhost-backend.h +0 -11
@@ -222,17 +222,6 @@ typedef struct VhostOps {vhost_check_device_state_op vhost_check_device_state; } VhostOps; -int vhost_backend_update_device_iotlb (struct vhost_dev *dev, -uint64_t iova,uint64_t uaddr, -uint64_t len, -IOMMUAccessFlags perm); - -int vhost_backend_invalidate_device_iotlb (struct vhost_dev *dev, -uint64_t iova,uint64_t len); - -int vhost_backend_handle_iotlb_msg (struct vhost_dev *dev, -struct vhost_iotlb_msg *imsg); -int vhost_user_gpu_set_socket (struct vhost_dev *dev,int fd); int vhost_user_get_shared_object(struct vhost_dev *dev, unsigned char *uuid,
include/hw/virtio/vhost.h +2 -0
@@ -403,6 +403,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 vhost_dev_has_iommu (struct vhost_dev *dev); +int vhost_handle_iotlb_msg (struct vhost_dev *dev,struct vhost_iotlb_msg *imsg); +static inline bool vhost_dev_has_feature (struct vhost_dev *dev,uint64_t feature)
Signature · 1 line
MST
[PULL 013/106] intel_iommu: Fix PASID validity check in fault reporting
In reply to Michael S. TsirkinFrom: Zhenzhong Duan <[email protected]>
The current code incorrectly uses "pasid != PCI_NO_PASID" to determine if PASID should be reported in fault records. However, this check happens after the code converts PCI_NO_PASID to PASID_0 in scalable mode.
This means that for requests that originally had PCI_NO_PASID, the check "pasid != PCI_NO_PASID" will incorrectly return true (since pasid is now PASID_0), causing fault records to incorrectly indicate PASID validity. According to the VT-d specification, the PASID field in fault records is only valid for Requests-with-PASID:
"When Set, indicates the faulted request has a PASID TLP Prefix."
Fix this by capturing the original PASID state before the PCI_NO_PASID to PASID_0 conversion, ensuring fault records correctly reflect whether the original request had a PASID.
Message-Id: <[email protected]>
--- hw/i386/intel_iommu.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
hw/i386/intel_iommu.c +2 -1
@@ -2109,6 +2109,7 @@ static bool vtd_do_iommu_translate(VTDAddressSpace *vtd_as, PCIBus *bus,bool is_fpd_set = false;bool reads = true;bool writes = true; +bool is_pasid = pasid !=PCI_NO_PASID ;uint8_t access_flags, pgtt;VTDIOTLBEntry *iotlb_entry;uint64_t xlat, size;
@@ -2235,7 +2236,7 @@ static bool vtd_do_iommu_translate(VTDAddressSpace *vtd_as, PCIBus *bus,if (ret_fr) {if (!vtd_is_recoverable_fault (-ret_fr, iommu_idx)) {vtd_report_fault (s, -ret_fr, is_fpd_set, source_id, - addr, is_write, pasid !=PCI_NO_PASID , pasid); + addr, is_write, is_pasid, pasid); } goto error; }
Signature · 1 line
MST
[PULL 051/106] vhost: rename vhost-backend.c to vhost-kernel.c
In reply to Michael S. TsirkinFrom: Vladimir Sementsov-Ogievskiy <[email protected]>
This file is totally about vhost-kernel implementation, not generic code. Let's finally give it corresponding name.
Message-Id: <[email protected]>
---
hw/virtio/meson.build | 2 +-
hw/virtio/{vhost-backend.c => vhost-kernel.c} | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
rename hw/virtio/{vhost-backend.c => vhost-kernel.c} (99%)hw/virtio/meson.build +1 -1
@@ -14,7 +14,7 @@ system_virtio_ss.add(files('virtio-qmp.c')) if have_vhost system_virtio_ss.add(files('vhost.c')) - system_virtio_ss.add(files('vhost-backend.c', 'vhost-iova-tree.c')) + system_virtio_ss.add(files('vhost-kernel.c', 'vhost-iova-tree.c')) if have_vhost_user system_virtio_ss.add(files('vhost-user.c')) system_virtio_ss.add(files('vhost-user-base.c'))
hw/virtio/vhost-kernel.c renamed from hw/virtio/vhost-backend.c +1 -1
@@ -1,5 +1,5 @@/* -* vhost-backend +* vhost-kernel * * Copyright (c) 2013 Virtual Open Systems Sarl. *
Signature · 1 line
MST
[PULL 022/106] intel_iommu: Expose flag VIOMMU_FLAG_PASID_SUPPORTED and VIOMMU_FLAG_WANT_PASID_ATTACH
In reply to Michael S. TsirkinFrom: Zhenzhong Duan <[email protected]>
VFIO device will check flag VIOMMU_FLAG_PASID_SUPPORTED and expose PASID capability, also check VIOMMU_FLAG_WANT_PASID_ATTACH to enable pasid attachment, without those guest could not enable PASID of this device even if vIOMMU's pasid is configured.
We don't expose the two flags when fist stage translation is not configured as we don't support shadow page table on a PASID.
This is the final knob to enable PASID.
Message-Id: <[email protected]>
--- hw/i386/intel_iommu.c | 5 +++++ 1 file changed, 5 insertions(+)
hw/i386/intel_iommu.c +5 -0
@@ -4788,6 +4788,11 @@ static uint64_t vtd_get_viommu_flags(void *opaque)if (s->fsts) { flags =VIOMMU_FLAG_WANT_NESTING_PARENT |VIOMMU_FLAG_WANT_NESTING_DIRTY_TRACKING ; + +if (s->pasid) { + flags |=VIOMMU_FLAG_PASID_SUPPORTED | +VIOMMU_FLAG_WANT_PASID_ATTACH ; + } }return flags;
Signature · 1 line
MST
[PULL 052/106] vhost: replace .vhost_vq_get_addr() with .vhost_phys_vring_addr()
In reply to Michael S. TsirkinFrom: Vladimir Sementsov-Ogievskiy <[email protected]>
Make a simper handler to consolidate the logic in one place. That helps further changes.
Based-on: <[email protected]>
Message-Id: <[email protected]>
--- hw/virtio/vhost-vdpa.c | 13 +++---------- hw/virtio/vhost.c | 12 ++++++------ include/hw/virtio/vhost-backend.h | 6 ++---- 3 files changed, 11 insertions(+), 20 deletions(-)
hw/virtio/vhost-vdpa.c +3 -10
@@ -1571,16 +1571,9 @@ static int vhost_vdpa_set_owner(struct vhost_dev *dev)return 0 ; } -static int vhost_vdpa_vq_get_addr (struct vhost_dev *dev, -struct vhost_vring_addr *addr,struct vhost_virtqueue *vq) +static bool vhost_vdpa_phys_vring_addr (struct vhost_dev *dev) { -assert (dev->vhost_ops->backend_type ==VHOST_BACKEND_TYPE_VDPA ); - addr->desc_user_addr = (uint64_t )(unsigned long )vq->desc_phys; - addr->avail_user_addr = (uint64_t )(unsigned long )vq->avail_phys; - addr->used_user_addr = (uint64_t )(unsigned long )vq->used_phys; -trace_vhost_vdpa_vq_get_addr (dev, vq, addr->desc_user_addr, - addr->avail_user_addr, addr->used_user_addr); -return 0 ; +return true; }static bool vhost_vdpa_force_iommu (struct vhost_dev *dev)
@@ -1617,7 +1610,7 @@ const VhostOps vdpa_ops = { .vhost_send_device_iotlb_msg = NULL, .vhost_dev_start = vhost_vdpa_dev_start, .vhost_get_device_id = vhost_vdpa_get_device_id, - .vhost_vq_get_addr = vhost_vdpa_vq_get_addr, + .vhost_phys_vring_addr = vhost_vdpa_phys_vring_addr, .vhost_force_iommu = vhost_vdpa_force_iommu, .vhost_set_config_call = vhost_vdpa_set_config_call, .vhost_reset_status = vhost_vdpa_reset_status,
hw/virtio/vhost.c +6 -6
@@ -1093,16 +1093,16 @@ static int vhost_virtqueue_set_addr(struct vhost_dev *dev,struct vhost_virtqueue *vq, unsigned idx, bool enable_log) { + bool phys = dev->vhost_ops->vhost_phys_vring_addr && + dev->vhost_ops->vhost_phys_vring_addr (dev);struct vhost_vring_addr addr;int r;memset (&addr,0 ,sizeof (struct vhost_vring_addr )); -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 (r,"vhost_vq_get_addr failed" ); -return r; - } +if (phys) { + addr.desc_user_addr = (uint64_t )(unsigned long )vq->desc_phys; + addr.avail_user_addr = (uint64_t )(unsigned long )vq->avail_phys; + addr.used_user_addr = (uint64_t )(unsigned long )vq->used_phys; }else { addr.desc_user_addr = (uint64_t )(unsigned long )vq->desc; addr.avail_user_addr = (uint64_t )(unsigned long )vq->avail;
include/hw/virtio/vhost-backend.h +2 -4
@@ -141,9 +141,7 @@ typedef int (*vhost_set_inflight_fd_op)(struct vhost_dev *dev,typedef int (*vhost_dev_start_op )(struct vhost_dev *dev,bool started); -typedef int (*vhost_vq_get_addr_op )(struct vhost_dev *dev, -struct vhost_vring_addr *addr, -struct vhost_virtqueue *vq); +typedef bool (*vhost_phys_vring_addr_op )(struct vhost_dev *dev);typedef int (*vhost_get_device_id_op )(struct vhost_dev *dev,uint32_t *dev_id);
@@ -211,7 +209,7 @@ typedef struct VhostOps {vhost_get_inflight_fd_op vhost_get_inflight_fd;vhost_set_inflight_fd_op vhost_set_inflight_fd;vhost_dev_start_op vhost_dev_start; -vhost_vq_get_addr_op vhost_vq_get_addr; +vhost_phys_vring_addr_op vhost_phys_vring_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;
Signature · 1 line
MST
[PULL 029/106] vhost-user: introduce vhost_user_has_protocol_feature() helper
In reply to Michael S. TsirkinFrom: Vladimir Sementsov-Ogievskiy <[email protected]>
Make all protocol feature checks in the same way.
Message-Id: <[email protected]>
--- hw/virtio/vhost-user.c | 120 +++++++++++++++++++++-------------------- 1 file changed, 62 insertions(+), 58 deletions(-)
hw/virtio/vhost-user.c +62 -58
@@ -267,6 +267,12 @@ struct scrub_regions {int fd_idx; }; +static bool vhost_user_has_protocol_feature (struct vhost_dev *dev, +uint64_t feature) +{ +return virtio_has_feature (dev->protocol_features, feature); +} +static int vhost_user_read_header (struct vhost_dev *dev,VhostUserMsg *msg) {struct vhost_user *u = dev->opaque;
@@ -430,8 +436,8 @@ static int vhost_user_set_log_base(struct vhost_dev *dev, uint64_t base, {int fds[VHOST_USER_MAX_RAM_SLOTS ];size_t fd_num =0 ; -bool shmfd =virtio_has_feature (dev->protocol_features, -VHOST_USER_PROTOCOL_F_LOG_SHMFD ); +bool shmfd = +vhost_user_has_protocol_feature (dev,VHOST_USER_PROTOCOL_F_LOG_SHMFD );int ret;VhostUserMsg msg = { .hdr.request =VHOST_USER_SET_LOG_BASE ,
@@ -1001,11 +1007,11 @@ static int vhost_user_set_mem_table(struct vhost_dev *dev,int fds[VHOST_MEMORY_BASELINE_NREGIONS ];size_t fd_num =0 ;bool do_postcopy = u->postcopy_listen && u->postcopy_fd.handler; -bool reply_supported =virtio_has_feature (dev->protocol_features, -VHOST_USER_PROTOCOL_F_REPLY_ACK ); +bool reply_supported = +vhost_user_has_protocol_feature (dev,VHOST_USER_PROTOCOL_F_REPLY_ACK );bool config_mem_slots = -virtio_has_feature (dev->protocol_features, -VHOST_USER_PROTOCOL_F_CONFIGURE_MEM_SLOTS ); +vhost_user_has_protocol_feature ( + dev,VHOST_USER_PROTOCOL_F_CONFIGURE_MEM_SLOTS );int ret;if (do_postcopy) {
@@ -1053,8 +1059,9 @@ static int vhost_user_set_mem_table(struct vhost_dev *dev,static int vhost_user_set_vring_endian (struct vhost_dev *dev,struct vhost_vring_state *ring) { -bool cross_endian =virtio_has_feature (dev->protocol_features, -VHOST_USER_PROTOCOL_F_CROSS_ENDIAN ); +bool cross_endian = +vhost_user_has_protocol_feature ( + dev,VHOST_USER_PROTOCOL_F_CROSS_ENDIAN );VhostUserMsg msg = { .hdr.request =VHOST_USER_SET_VRING_ENDIAN , .hdr.flags =VHOST_USER_VERSION ,
@@ -1124,8 +1131,9 @@ static int vhost_user_write_sync(struct vhost_dev *dev, VhostUserMsg *msg,int ret;if (wait_for_reply) { -bool reply_supported =virtio_has_feature (dev->protocol_features, -VHOST_USER_PROTOCOL_F_REPLY_ACK ); +bool reply_supported = +vhost_user_has_protocol_feature ( + dev,VHOST_USER_PROTOCOL_F_REPLY_ACK );if (reply_supported) { msg->hdr.flags |=VHOST_USER_NEED_REPLY_MASK ; }
@@ -1475,8 +1483,7 @@ static int vhost_user_set_features(struct vhost_dev *dev, ret =vhost_user_set_u64 (dev,VHOST_USER_SET_FEATURES , features, log_enabled); -if (virtio_has_feature (dev->protocol_features, -VHOST_USER_PROTOCOL_F_STATUS )) { +if (vhost_user_has_protocol_feature (dev,VHOST_USER_PROTOCOL_F_STATUS )) {if (!ret) {return vhost_user_add_status (dev,VIRTIO_CONFIG_S_FEATURES_OK ); }
@@ -1530,8 +1537,8 @@ static int vhost_user_reset_device(struct vhost_dev *dev)* Historically, reset was not implemented so only reset devices * that are expecting it. */ -if (!virtio_has_feature (dev->protocol_features, -VHOST_USER_PROTOCOL_F_RESET_DEVICE )) { +if (!vhost_user_has_protocol_feature ( + dev,VHOST_USER_PROTOCOL_F_RESET_DEVICE )) {return -ENOSYS ; }
@@ -1588,8 +1595,8 @@ static int vhost_user_backend_handle_vring_host_notifier(struct vhost_dev *dev,void *addr;char *name; -if (!virtio_has_feature (dev->protocol_features, -VHOST_USER_PROTOCOL_F_HOST_NOTIFIER ) || +if (!vhost_user_has_protocol_feature ( + dev,VHOST_USER_PROTOCOL_F_HOST_NOTIFIER ) || vdev ==NULL || queue_idx >=virtio_get_num_queues (vdev)) {return -EINVAL ; }
@@ -1887,13 +1894,13 @@ static int vhost_setup_backend_channel(struct vhost_dev *dev) };struct vhost_user *u = dev->opaque;int sv[2 ], ret =0 ; -bool reply_supported =virtio_has_feature (dev->protocol_features, -VHOST_USER_PROTOCOL_F_REPLY_ACK ); +bool reply_supported = +vhost_user_has_protocol_feature (dev,VHOST_USER_PROTOCOL_F_REPLY_ACK );Error *local_err =NULL ;QIOChannel *ioc; -if (!virtio_has_feature (dev->protocol_features, -VHOST_USER_PROTOCOL_F_BACKEND_REQ )) { +if (!vhost_user_has_protocol_feature ( + dev,VHOST_USER_PROTOCOL_F_BACKEND_REQ )) {return 0 ; }
@@ -2141,8 +2148,8 @@ static int vhost_user_postcopy_notifier(NotifierWithReturn *notifier,switch (pnd->reason) {case POSTCOPY_NOTIFY_PROBE : -if (!virtio_has_feature (dev->protocol_features, -VHOST_USER_PROTOCOL_F_PAGEFAULT )) { +if (!vhost_user_has_protocol_feature ( + dev,VHOST_USER_PROTOCOL_F_PAGEFAULT )) {/* TODO: Get the device name into this error somehow */ error_setg (errp,"vhost-user backend not capable of postcopy" );
@@ -2240,7 +2247,7 @@ static int vhost_user_backend_init(struct vhost_dev *dev, void *opaque, }/* query the max queues we support if backend supports Multiple Queue */ -if (dev->protocol_features & (1ULL <<VHOST_USER_PROTOCOL_F_MQ )) { +if (vhost_user_has_protocol_feature (dev,VHOST_USER_PROTOCOL_F_MQ )) { err =vhost_user_get_u64 (dev,VHOST_USER_GET_QUEUE_NUM , &dev->max_queues);if (err <0 ) {
@@ -2258,18 +2265,18 @@ static int vhost_user_backend_init(struct vhost_dev *dev, void *opaque, }if (virtio_has_feature (features,VIRTIO_F_IOMMU_PLATFORM ) && - !(virtio_has_feature (dev->protocol_features, -VHOST_USER_PROTOCOL_F_BACKEND_REQ ) && -virtio_has_feature (dev->protocol_features, -VHOST_USER_PROTOCOL_F_REPLY_ACK ))) { + !(vhost_user_has_protocol_feature ( + dev,VHOST_USER_PROTOCOL_F_BACKEND_REQ ) && +vhost_user_has_protocol_feature ( + dev,VHOST_USER_PROTOCOL_F_REPLY_ACK ))) {error_setg (errp,"IOMMU support requires reply-ack and " "backend-req protocol features." );return -EINVAL ; }/* get max memory regions if backend supports configurable RAM slots */ -if (!virtio_has_feature (dev->protocol_features, -VHOST_USER_PROTOCOL_F_CONFIGURE_MEM_SLOTS )) { +if (!vhost_user_has_protocol_feature ( + dev,VHOST_USER_PROTOCOL_F_CONFIGURE_MEM_SLOTS )) { u->user->memory_slots =VHOST_MEMORY_BASELINE_NREGIONS ; }else { err =vhost_user_get_max_memslots (dev, &ram_slots);
@@ -2293,8 +2300,8 @@ static int vhost_user_backend_init(struct vhost_dev *dev, void *opaque, }if (dev->migration_blocker ==NULL && - !virtio_has_feature (dev->protocol_features, -VHOST_USER_PROTOCOL_F_LOG_SHMFD )) { + !vhost_user_has_protocol_feature ( + dev,VHOST_USER_PROTOCOL_F_LOG_SHMFD )) {error_setg (&dev->migration_blocker,"Migration disabled: vhost-user backend lacks " "VHOST_USER_PROTOCOL_F_LOG_SHMFD feature." );
@@ -2363,8 +2370,8 @@ static bool vhost_user_requires_shm_log(struct vhost_dev *dev) {assert (dev->vhost_ops->backend_type ==VHOST_BACKEND_TYPE_USER ); -return virtio_has_feature (dev->protocol_features, -VHOST_USER_PROTOCOL_F_LOG_SHMFD ); +return vhost_user_has_protocol_feature ( + dev,VHOST_USER_PROTOCOL_F_LOG_SHMFD ); }static int vhost_user_migration_done (struct vhost_dev *dev,char * mac_addr)
@@ -2379,8 +2386,7 @@ static int vhost_user_migration_done(struct vhost_dev *dev, char* mac_addr) }/* if backend supports VHOST_USER_PROTOCOL_F_RARP ask it to send the RARP */ -if (virtio_has_feature (dev->protocol_features, -VHOST_USER_PROTOCOL_F_RARP )) { +if (vhost_user_has_protocol_feature (dev,VHOST_USER_PROTOCOL_F_RARP )) { msg.hdr.request =VHOST_USER_SEND_RARP ; msg.hdr.flags =VHOST_USER_VERSION ;memcpy ((char *)&msg.payload.u64, mac_addr,6 );
@@ -2394,11 +2400,11 @@ static int vhost_user_migration_done(struct vhost_dev *dev, char* mac_addr)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 ); +bool reply_supported = +vhost_user_has_protocol_feature (dev,VHOST_USER_PROTOCOL_F_REPLY_ACK );int ret; -if (!(dev->protocol_features & (1ULL <<VHOST_USER_PROTOCOL_F_NET_MTU ))) { +if (!vhost_user_has_protocol_feature (dev,VHOST_USER_PROTOCOL_F_NET_MTU )) {return 0 ; }
@@ -2458,8 +2464,7 @@ static int vhost_user_get_config(struct vhost_dev *dev, uint8_t *config, .hdr.size = VHOST_USER_CONFIG_HDR_SIZE + config_len, }; -if (!virtio_has_feature (dev->protocol_features, -VHOST_USER_PROTOCOL_F_CONFIG )) { +if (!vhost_user_has_protocol_feature (dev,VHOST_USER_PROTOCOL_F_CONFIG )) {error_setg (errp,"VHOST_USER_PROTOCOL_F_CONFIG not supported" );return -EINVAL ; }
@@ -2502,8 +2507,8 @@ static int vhost_user_set_config(struct vhost_dev *dev, const uint8_t *data, {int ret;uint8_t *p; -bool reply_supported =virtio_has_feature (dev->protocol_features, -VHOST_USER_PROTOCOL_F_REPLY_ACK ); +bool reply_supported = +vhost_user_has_protocol_feature (dev,VHOST_USER_PROTOCOL_F_REPLY_ACK );VhostUserMsg msg = { .hdr.request =VHOST_USER_SET_CONFIG ,
@@ -2511,8 +2516,7 @@ static int vhost_user_set_config(struct vhost_dev *dev, const uint8_t *data, .hdr.size = VHOST_USER_CONFIG_HDR_SIZE + size, }; -if (!virtio_has_feature (dev->protocol_features, -VHOST_USER_PROTOCOL_F_CONFIG )) { +if (!vhost_user_has_protocol_feature (dev,VHOST_USER_PROTOCOL_F_CONFIG )) {return -ENOTSUP ; }
@@ -2547,8 +2551,9 @@ static int vhost_user_crypto_create_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 ); +bool crypto_session = +vhost_user_has_protocol_feature ( + dev,VHOST_USER_PROTOCOL_F_CRYPTO_SESSION );CryptoDevBackendSessionInfo *backend_info = session_info;VhostUserMsg msg = { .hdr.request =VHOST_USER_CREATE_CRYPTO_SESSION ,
@@ -2649,8 +2654,9 @@ 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 ); +bool crypto_session = +vhost_user_has_protocol_feature ( + dev,VHOST_USER_PROTOCOL_F_CRYPTO_SESSION ); VhostUserMsg msg = { .hdr.request = VHOST_USER_CLOSE_CRYPTO_SESSION, .hdr.flags = VHOST_USER_VERSION,
@@ -2695,8 +2701,8 @@ static int vhost_user_get_inflight_fd(struct vhost_dev *dev, .hdr.size = sizeof(msg.payload.inflight), }; -if (!virtio_has_feature (dev->protocol_features, -VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD )) { +if (!vhost_user_has_protocol_feature ( + dev,VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD )) {return 0 ; }
@@ -2763,8 +2769,8 @@ static int vhost_user_set_inflight_fd(struct vhost_dev *dev, .hdr.size = sizeof(msg.payload.inflight), }; -if (!virtio_has_feature (dev->protocol_features, -VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD )) { +if (!vhost_user_has_protocol_feature ( + dev,VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD )) {return 0 ; }
@@ -2863,8 +2869,7 @@ void vhost_user_async_close(DeviceState *d,static int vhost_user_dev_start (struct vhost_dev *dev,bool started) { -if (!virtio_has_feature (dev->protocol_features, -VHOST_USER_PROTOCOL_F_STATUS )) { +if (!vhost_user_has_protocol_feature (dev,VHOST_USER_PROTOCOL_F_STATUS )) {return 0 ; }
@@ -2889,16 +2894,15 @@ static void vhost_user_reset_status(struct vhost_dev *dev)return ; } -if (virtio_has_feature (dev->protocol_features, -VHOST_USER_PROTOCOL_F_STATUS )) { +if (vhost_user_has_protocol_feature (dev,VHOST_USER_PROTOCOL_F_STATUS )) {vhost_user_set_status (dev,0 ); } }static bool vhost_user_supports_device_state (struct vhost_dev *dev) { -return virtio_has_feature (dev->protocol_features, -VHOST_USER_PROTOCOL_F_DEVICE_STATE ); +return vhost_user_has_protocol_feature ( + dev,VHOST_USER_PROTOCOL_F_DEVICE_STATE ); } static int vhost_user_set_device_state_fd(struct vhost_dev *dev,
Signature · 1 line
MST
[PULL 069/106] vhost-user: Fix stale error logs and return values in teardown paths
In reply to Michael S. TsirkinFrom: Kuan-Wei Chiu <[email protected]>
Commit bc85aae42045 ("vhost-user: return failure if backend crash when live migration") refactored the set_guest_notifiers error handling but introduced two regressions across multiple vhost devices.
By moving the function call directly into the if condition, the subsequent error_report prints the stale ret variable instead of the actual error code. Additionally, the refactoring hardcoded a return value of -1 rather than propagating the true error status to the caller.
Fix these issues by storing the set_guest_notifiers result in a local err variable.
Message-Id: <[email protected]>
--- backends/vhost-user.c | 8 ++++---- hw/block/vhost-user-blk.c | 9 +++++---- hw/scsi/vhost-scsi-common.c | 2 +- hw/virtio/vhost-user-base.c | 9 +++++---- hw/virtio/vhost-user-fs.c | 9 +++++---- hw/virtio/vhost-user-scmi.c | 9 +++++---- hw/virtio/vhost-vsock-common.c | 9 +++++---- 7 files changed, 30 insertions(+), 25 deletions(-)
backends/vhost-user.c +4 -4
@@ -102,7 +102,7 @@ vhost_user_backend_stop(VhostUserBackend *b) {BusState *qbus =BUS (qdev_get_parent_bus (DEVICE (b->vdev)));VirtioBusClass *k =VIRTIO_BUS_GET_CLASS (qbus); -int ret; +int ret, err;if (!b->started) {return 0 ;
@@ -111,9 +111,9 @@ vhost_user_backend_stop(VhostUserBackend *b) ret =vhost_dev_stop (&b->dev, b->vdev, true);if (k->set_guest_notifiers && - k->set_guest_notifiers (qbus->parent, b->dev.nvqs, false) <0 ) { -error_report ("vhost guest notifier cleanup failed: %d" , ret); -return -1 ; + (err = k->set_guest_notifiers (qbus->parent, b->dev.nvqs, false)) <0 ) { +error_report ("vhost guest notifier cleanup failed: %d" , err); +return err; }vhost_dev_disable_notifiers (&b->dev, b->vdev);
hw/block/vhost-user-blk.c +5 -4
@@ -214,7 +214,7 @@ static int vhost_user_blk_stop(VirtIODevice *vdev)VHostUserBlk *s =VHOST_USER_BLK (vdev);BusState *qbus =BUS (qdev_get_parent_bus (DEVICE (vdev)));VirtioBusClass *k =VIRTIO_BUS_GET_CLASS (qbus); -int ret; +int ret, err;bool force_stop = false;trace_vhost_user_blk_stop_in (vdev);
@@ -234,9 +234,10 @@ static int vhost_user_blk_stop(VirtIODevice *vdev) ret = force_stop ?vhost_dev_force_stop (&s->dev, vdev, true) :vhost_dev_stop (&s->dev, vdev, true); -if (k->set_guest_notifiers (qbus->parent, s->dev.nvqs, false) <0 ) { -error_report ("vhost guest notifier cleanup failed: %d" , ret); -return -1 ; + err = k->set_guest_notifiers (qbus->parent, s->dev.nvqs, false); +if (err <0 ) { +error_report ("vhost guest notifier cleanup failed: %d" , err); +return err; }vhost_dev_disable_notifiers (&s->dev, vdev);
hw/scsi/vhost-scsi-common.c +1 -1
@@ -113,7 +113,7 @@ int vhost_scsi_common_stop(VHostSCSICommon *vsc)if (k->set_guest_notifiers) {int r = k->set_guest_notifiers (qbus->parent, vsc->dev.nvqs, false);if (r <0 ) { -error_report ("vhost guest notifier cleanup failed: %d" , ret); +error_report ("vhost guest notifier cleanup failed: %d" , r);return r; } }
hw/virtio/vhost-user-base.c +5 -4
@@ -71,7 +71,7 @@ static int vub_stop(VirtIODevice *vdev)VHostUserBase *vub =VHOST_USER_BASE (vdev);BusState *qbus =BUS (qdev_get_parent_bus (DEVICE (vdev)));VirtioBusClass *k =VIRTIO_BUS_GET_CLASS (qbus); -int ret; +int ret, err;if (!k->set_guest_notifiers) {return 0 ;
@@ -79,9 +79,10 @@ static int vub_stop(VirtIODevice *vdev) ret =vhost_dev_stop (&vub->vhost_dev, vdev, true); -if (k->set_guest_notifiers (qbus->parent, vub->vhost_dev.nvqs, false) <0 ) { -error_report ("vhost guest notifier cleanup failed: %d" , ret); -return -1 ; + err = k->set_guest_notifiers (qbus->parent, vub->vhost_dev.nvqs, false); +if (err <0 ) { +error_report ("vhost guest notifier cleanup failed: %d" , err); +return err; }vhost_dev_disable_notifiers (&vub->vhost_dev, vdev);
hw/virtio/vhost-user-fs.c +5 -4
@@ -105,7 +105,7 @@ static int vuf_stop(VirtIODevice *vdev)VHostUserFS *fs =VHOST_USER_FS (vdev);BusState *qbus =BUS (qdev_get_parent_bus (DEVICE (vdev)));VirtioBusClass *k =VIRTIO_BUS_GET_CLASS (qbus); -int ret; +int ret, err;if (!k->set_guest_notifiers) {return 0 ;
@@ -113,9 +113,10 @@ static int vuf_stop(VirtIODevice *vdev) ret =vhost_dev_stop (&fs->vhost_dev, vdev, true); -if (k->set_guest_notifiers (qbus->parent, fs->vhost_dev.nvqs, false) <0 ) { -error_report ("vhost guest notifier cleanup failed: %d" , ret); -return -1 ; + err = k->set_guest_notifiers (qbus->parent, fs->vhost_dev.nvqs, false); +if (err <0 ) { +error_report ("vhost guest notifier cleanup failed: %d" , err); +return err; }vhost_dev_disable_notifiers (&fs->vhost_dev, vdev);
hw/virtio/vhost-user-scmi.c +5 -4
@@ -89,7 +89,7 @@ static int vu_scmi_stop(VirtIODevice *vdev)BusState *qbus =BUS (qdev_get_parent_bus (DEVICE (vdev)));VirtioBusClass *k =VIRTIO_BUS_GET_CLASS (qbus);struct vhost_dev *vhost_dev = &scmi->vhost_dev; -int ret; +int ret, err;/* vhost_dev_is_started() check in the callers is not fully reliable. */ if (!scmi->started_vu) {
@@ -103,9 +103,10 @@ static int vu_scmi_stop(VirtIODevice *vdev) ret =vhost_dev_stop (vhost_dev, vdev, true); -if (k->set_guest_notifiers (qbus->parent, vhost_dev->nvqs, false) <0 ) { -error_report ("vhost guest notifier cleanup failed: %d" , ret); -return -1 ; + err = k->set_guest_notifiers (qbus->parent, vhost_dev->nvqs, false); +if (err <0 ) { +error_report ("vhost guest notifier cleanup failed: %d" , err); +return err; }vhost_dev_disable_notifiers (vhost_dev, vdev);return ret;
hw/virtio/vhost-vsock-common.c +5 -4
@@ -100,7 +100,7 @@ int vhost_vsock_common_stop(VirtIODevice *vdev)VHostVSockCommon *vvc =VHOST_VSOCK_COMMON (vdev);BusState *qbus =BUS (qdev_get_parent_bus (DEVICE (vdev)));VirtioBusClass *k =VIRTIO_BUS_GET_CLASS (qbus); -int ret; +int ret, err;if (!k->set_guest_notifiers) {return 0 ;
@@ -108,9 +108,10 @@ int vhost_vsock_common_stop(VirtIODevice *vdev) ret =vhost_dev_stop (&vvc->vhost_dev, vdev, true); -if (k->set_guest_notifiers (qbus->parent, vvc->vhost_dev.nvqs, false) <0 ) { -error_report ("vhost guest notifier cleanup failed: %d" , ret); -return -1 ; + err = k->set_guest_notifiers (qbus->parent, vvc->vhost_dev.nvqs, false); +if (err <0 ) { +error_report ("vhost guest notifier cleanup failed: %d" , err); +return err; }vhost_dev_disable_notifiers (&vvc->vhost_dev, vdev);
Signature · 1 line
MST
[PULL 006/106] vfio/iommufd: Extend attach/detach_hwpt callback implementations with pasid
In reply to Michael S. TsirkinFrom: Zhenzhong Duan <[email protected]>
For attachment with pasid, pasid together with flag VFIO_DEVICE_ATTACH_PASID should be passed in.
Define IOMMU_NO_PASID to represent device attachment without pasid same as in kernel.
The implementation is similar for detachment.
Message-Id: <[email protected]>
--- hw/vfio/iommufd.c | 44 +++++++++++++++++++++++++---------------- hw/vfio/trace-events | 4 ++-- include/hw/core/iommu.h | 3 +++ 3 files changed, 32 insertions(+), 19 deletions(-)
hw/vfio/iommufd.c +27 -17
@@ -20,6 +20,7 @@#include "trace.h" #include "qapi/error.h" #include "system/iommufd.h" +#include "hw/core/iommu.h" #include "hw/core/qdev.h" #include "hw/vfio/vfio-cpr.h" #include "system/reset.h"
@@ -305,43 +306,48 @@ out:return ret; } -static int iommufd_cdev_attach_ioas_hwpt (VFIODevice *vbasedev,uint32_t id, -Error **errp) +static int iommufd_cdev_pasid_attach_ioas_hwpt (VFIODevice *vbasedev, +uint32_t pasid,uint32_t id, +Error **errp) {int iommufd = vbasedev->iommufd->fd;struct vfio_device_attach_iommufd_pt attach_data = { .argsz =sizeof (attach_data), - .flags =0 , + .flags = pasid ==IOMMU_NO_PASID ?0 :VFIO_DEVICE_ATTACH_PASID , + .pasid = pasid, .pt_id = id, };/* Attach device to an IOAS or hwpt within iommufd */ if (ioctl (vbasedev->fd,VFIO_DEVICE_ATTACH_IOMMUFD_PT , &attach_data)) {error_setg_errno (errp, errno, -"[iommufd=%d] error attach %s (%d) to id=%d" , - iommufd, vbasedev->name, vbasedev->fd, id); +"[iommufd=%d] error attach %s (%d) pasid %d to id=%d" , + iommufd, vbasedev->name, vbasedev->fd, pasid, id);return -errno; } -trace_iommufd_cdev_attach_ioas_hwpt (iommufd, vbasedev->name, - vbasedev->fd, id); +trace_iommufd_cdev_pasid_attach_ioas_hwpt (iommufd, vbasedev->name, + vbasedev->fd, pasid, id);return 0 ; } -static bool iommufd_cdev_detach_ioas_hwpt (VFIODevice *vbasedev,Error **errp) +static bool iommufd_cdev_pasid_detach_ioas_hwpt (VFIODevice *vbasedev, +uint32_t pasid,Error **errp) {int iommufd = vbasedev->iommufd->fd;struct vfio_device_detach_iommufd_pt detach_data = { .argsz =sizeof (detach_data), - .flags =0 , + .flags = pasid ==IOMMU_NO_PASID ?0 :VFIO_DEVICE_DETACH_PASID , + .pasid = pasid, };if (ioctl (vbasedev->fd,VFIO_DEVICE_DETACH_IOMMUFD_PT , &detach_data)) { -error_setg_errno (errp, errno,"detach %s failed" , vbasedev->name); +error_setg_errno (errp, errno,"detach %s pasid %d failed" , + vbasedev->name, pasid);return false; } -trace_iommufd_cdev_detach_ioas_hwpt (iommufd, vbasedev->name); +trace_iommufd_cdev_pasid_detach_ioas_hwpt (iommufd, vbasedev->name, pasid);return true; }
@@ -363,7 +369,8 @@ static bool iommufd_cdev_autodomains_get(VFIODevice *vbasedev,/* Try to find a domain */ QLIST_FOREACH(hwpt, &container->hwpt_list, next) {if (!cpr_is_incoming ()) { - ret =iommufd_cdev_attach_ioas_hwpt (vbasedev, hwpt->hwpt_id, errp); + ret =iommufd_cdev_pasid_attach_ioas_hwpt (vbasedev,IOMMU_NO_PASID , + hwpt->hwpt_id, errp); }else if (vbasedev->cpr.hwpt_id == hwpt->hwpt_id) { ret =0 ; }else {
@@ -442,7 +449,8 @@ static bool iommufd_cdev_autodomains_get(VFIODevice *vbasedev,return false; } - ret =iommufd_cdev_attach_ioas_hwpt (vbasedev, hwpt_id, errp); + ret =iommufd_cdev_pasid_attach_ioas_hwpt (vbasedev,IOMMU_NO_PASID , hwpt_id, + errp);if (ret) {iommufd_backend_free_id (container->be, hwpt_id);return false;
@@ -495,7 +503,8 @@ static bool iommufd_cdev_attach_container(VFIODevice *vbasedev,/* If CPR, we are already attached to ioas_id. */ return cpr_is_incoming () || - !iommufd_cdev_attach_ioas_hwpt (vbasedev, container->ioas_id, errp); + !iommufd_cdev_pasid_attach_ioas_hwpt (vbasedev,IOMMU_NO_PASID , + container->ioas_id, errp); } static void iommufd_cdev_detach_container(VFIODevice *vbasedev,
@@ -503,7 +512,7 @@ static void iommufd_cdev_detach_container(VFIODevice *vbasedev, {Error *err =NULL ; -if (!iommufd_cdev_detach_ioas_hwpt (vbasedev, &err)) { +if (!iommufd_cdev_pasid_detach_ioas_hwpt (vbasedev,IOMMU_NO_PASID , &err)) {error_report_err (err); }
@@ -929,7 +938,8 @@ host_iommu_device_iommufd_vfio_attach_hwpt(HostIOMMUDeviceIOMMUFD *hiodi, {VFIODevice *vbasedev =HOST_IOMMU_DEVICE (hiodi)->agent; -return !iommufd_cdev_attach_ioas_hwpt (vbasedev, hwpt_id, errp); +return !iommufd_cdev_pasid_attach_ioas_hwpt (vbasedev,IOMMU_NO_PASID , + hwpt_id, errp); } static bool
@@ -938,7 +948,7 @@ host_iommu_device_iommufd_vfio_detach_hwpt(HostIOMMUDeviceIOMMUFD *hiodi, {VFIODevice *vbasedev =HOST_IOMMU_DEVICE (hiodi)->agent; -return iommufd_cdev_detach_ioas_hwpt (vbasedev, errp); +return iommufd_cdev_pasid_detach_ioas_hwpt (vbasedev,IOMMU_NO_PASID , errp); } static bool hiod_iommufd_vfio_realize(HostIOMMUDevice *hiod, void *opaque,
hw/vfio/trace-events +2 -2
@@ -183,8 +183,8 @@ vfio_vmstate_change_prepare(const char *name, int running, const char *reason, c iommufd_cdev_connect_and_bind(int iommufd, const char *name, int devfd, int devid) " [iommufd=%d] Successfully bound device %s (fd=%d): output devid=%d" iommufd_cdev_getfd(const char *dev, int devfd) " %s (fd=%d)" -iommufd_cdev_attach_ioas_hwpt(int iommufd, const char *name, int devfd, int id) " [iommufd=%d] Successfully attached device %s (%d) to id=%d" -iommufd_cdev_detach_ioas_hwpt(int iommufd, const char *name) " [iommufd=%d] Successfully detached %s" +iommufd_cdev_pasid_attach_ioas_hwpt(int iommufd, const char *name, int devfd, uint32_t pasid, int id) " [iommufd=%d] Successfully attached device %s (%d) pasid %u to id=%d" +iommufd_cdev_pasid_detach_ioas_hwpt(int iommufd, const char *name, uint32_t pasid) " [iommufd=%d] Successfully detached %s pasid %u" iommufd_cdev_fail_attach_existing_container(const char *msg) " %s" iommufd_cdev_alloc_ioas(int iommufd, int ioas_id) " [iommufd=%d] new IOMMUFD container with ioasid=%d" iommufd_cdev_device_info(char *name, int devfd, int num_irqs, int num_regions, int flags) " %s (%d) num_irqs=%d num_regions=%d flags=%d"
include/hw/core/iommu.h +3 -0
@@ -30,4 +30,7 @@ enum host_iommu_quirks { HOST_IOMMU_QUIRK_NESTING_PARENT_BYPASS_RO = BIT_ULL(0), }; +/* ABI constant: IOMMU_NO_PASID must always be 0 (keep in sync with kernel) */ +#define IOMMU_NO_PASID 0 +#endif /* HW_IOMMU_H */
Signature · 1 line
MST
[PULL 002/106] amd_iommu: Update command buffer head ptr in MMIO region after wraparound
In reply to Michael S. TsirkinFrom: Alejandro Jimenez <[email protected]>
When processing a command, amdvi_cmdbuf_run() increments cmdbuf_head and writes it to the emulated MMIO register space before checking whether it has reached the end of the command buffer.
If the incremented value reaches the end of the buffer and the tail pointer is zero, the loop exits and the COMMAND_HEAD offset still contains an unwrapped value. There are no errors in command processing since internal cmdbuf_head state is always correctly updated, but the spec defines the CmdHeadPtr field in MMIO Offset 2000h Command Buffer Head Pointer Register as RW i.e. guest-visible, so it should be kept consistent.
Wrap cmdbuf_head before updating COMMAND_HEAD so the MMIO-visible register always matches the internal command buffer head pointer position.
Message-Id: <[email protected]>
--- hw/i386/amd_iommu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
hw/i386/amd_iommu.c +1 -1
@@ -1475,12 +1475,12 @@ static void amdvi_cmdbuf_run(AMDVIState *s)trace_amdvi_command_exec (s->cmdbuf_head, s->cmdbuf_tail, s->cmdbuf);amdvi_cmdbuf_exec (s); s->cmdbuf_head +=AMDVI_COMMAND_SIZE ; -amdvi_writeq_raw (s,AMDVI_MMIO_COMMAND_HEAD , s->cmdbuf_head);/* wrap head pointer */ if (s->cmdbuf_head >= s->cmdbuf_len *AMDVI_COMMAND_SIZE ) { s->cmdbuf_head =0 ; } +amdvi_writeq_raw (s,AMDVI_MMIO_COMMAND_HEAD , s->cmdbuf_head); } }
Signature · 1 line
MST
[PULL 055/106] vhost: stop reusing vq->desc (and friends) to store physical address
In reply to Michael S. TsirkinFrom: Vladimir Sementsov-Ogievskiy <[email protected]>
Remove the hack of storing physical addresses in vq->desc/avail/used pointers when IOMMU is present. Instead, handle this case directly in vhost_virtqueue_set_addr() by checking for IOMMU presence.
Based-on: <[email protected]>
Message-Id: <[email protected]>
--- hw/virtio/vhost.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-)
hw/virtio/vhost.c +1 -4
@@ -518,9 +518,6 @@ static int vhost_vrings_map(struct vhost_dev *dev, }if (vhost_dev_has_iommu (dev)) { - vq->desc = (void *)(uintptr_t )vq->desc_phys; - vq->avail = (void *)(uintptr_t )vq->avail_phys; - vq->used = (void *)(uintptr_t )vq->used_phys;return 1 ; }
@@ -1104,7 +1101,7 @@ static int vhost_virtqueue_set_addr(struct vhost_dev *dev,int r;memset (&addr,0 ,sizeof (struct vhost_vring_addr )); -if (phys) { +if (phys ||vhost_dev_has_iommu (dev)) { addr.desc_user_addr = (uint64_t )(unsigned long )vq->desc_phys; addr.avail_user_addr = (uint64_t )(unsigned long )vq->avail_phys; addr.used_user_addr = (uint64_t )(unsigned long )vq->used_phys;
Signature · 1 line
MST
[PULL 018/106] intel_iommu_accel: Bypass PASID entry addition for just deleted entry
In reply to Michael S. TsirkinFrom: Zhenzhong Duan <[email protected]>
For VTD_INV_DESC_PASIDC_G_PASID_SI typed pc_inv_dsc invalidation, if an pasid entry is just removed, it can never be a new entry to add. So calling vtd_replay_pasid_bind_for_dev() is unnecessary.
Introduce a new field accel_pce_deleted in VTDPASIDCacheInfo to mark this case and to do the bypassing.
Message-Id: <[email protected]>
--- hw/i386/intel_iommu_accel.c | 16 +++++++++++++--- hw/i386/intel_iommu_internal.h | 1 + 2 files changed, 14 insertions(+), 3 deletions(-)
hw/i386/intel_iommu_accel.c +13 -3
@@ -280,10 +280,15 @@ static void vtd_accel_fill_pc(VTDHostIOMMUDevice *vtd_hiod, uint32_t pasid,QLIST_INSERT_HEAD (&vtd_hiod->pasid_cache_list, vtd_pce, next); } -static void vtd_accel_delete_pc (VTDAccelPASIDCacheEntry *vtd_pce) +static void vtd_accel_delete_pc (VTDAccelPASIDCacheEntry *vtd_pce, +VTDPASIDCacheInfo *pc_info) {QLIST_REMOVE (vtd_pce, next);g_free (vtd_pce); + +if (pc_info->type ==VTD_INV_DESC_PASIDC_G_PASID_SI ) { + pc_info->accel_pce_deleted = true; + } } static void
@@ -319,7 +324,7 @@ vtd_accel_pasid_cache_invalidate_one(VTDAccelPASIDCacheEntry *vtd_pce,* to be either all-zero or non-present. Either case means existing * pasid cache should be invalidated. */ -vtd_accel_delete_pc (vtd_pce); +vtd_accel_delete_pc (vtd_pce, pc_info); } }
@@ -472,7 +477,12 @@ void vtd_accel_pasid_cache_sync(IntelIOMMUState *s, VTDPASIDCacheInfo *pc_info)* removals before additions to optimize the replay process. */ vtd_accel_pasid_cache_invalidate (vtd_hiod, pc_info); -vtd_accel_replay_pasid_bind_for_dev (vtd_hiod, start, end, pc_info); + +if (pc_info->accel_pce_deleted) { + pc_info->accel_pce_deleted = false; + }else { +vtd_accel_replay_pasid_bind_for_dev (vtd_hiod, start, end, pc_info); + } } }
hw/i386/intel_iommu_internal.h +1 -0
@@ -630,6 +630,7 @@ typedef struct VTDPASIDCacheInfo {uint8_t type;uint16_t did;uint32_t pasid; +bool accel_pce_deleted; } VTDPASIDCacheInfo; typedef struct VTDPIOTLBInvInfo {
Signature · 1 line
MST
[PULL 099/106] hw/cxl: Fix handling of component ID to not assume it is a string
In reply to Michael S. TsirkinFrom: Shiju Jose <[email protected]>
Add following fixes,
1. Coverity reports a warning (CID 1645325) for use of strncpy() in handling of component ID. In cxl_create_mem_sparing_event_records(), fix handling of component ID to not assume it is a string by replacing strncpy with memcpy to solve this warning and copy the entire component ID data, which is 16 bytes.
2. In cxl_maintenance_insert(),
- replace strncpy with memcpy to copy full data because component ID, which is 16 bytes data.
- remove memset which is not required.
Message-Id: <[email protected]>
--- hw/cxl/cxl-mailbox-utils.c | 4 ++-- hw/mem/cxl_type3.c | 4 +--- 2 files changed, 3 insertions(+), 5 deletions(-)
hw/cxl/cxl-mailbox-utils.c +2 -2
@@ -1994,8 +1994,8 @@ static void cxl_create_mem_sparing_event_records(CXLType3Dev *ct3d,stw_le_p (&event_rec.column, ent->column); event_rec.sub_channel = ent->sub_channel;if (ent->validity_flags &CXL_MSER_VALID_COMP_ID ) { -strncpy ((char *)event_rec.component_id, (char *)ent->component_id, -sizeof (event_rec.component_id)); +memcpy (event_rec.component_id, ent->component_id, +sizeof (event_rec.component_id)); } }else if (sparing_pi) { event_rec.flags =CXL_MSER_FLAGS_QUERY_RESOURCES ;
hw/mem/cxl_type3.c +1 -3
@@ -1767,7 +1767,6 @@ static void cxl_maintenance_insert(CXLType3Dev *ct3d, uint64_t dpa, } } m =g_new0 (CXLMaintenance,1 ); -memset (m,0 ,sizeof (*m)); m->dpa = dpa; m->validity_flags =0 ;
@@ -1804,8 +1803,7 @@ static void cxl_maintenance_insert(CXLType3Dev *ct3d, uint64_t dpa, m->validity_flags |=CXL_MSER_VALID_SUB_CHANNEL ; }if (component_id) { -strncpy ((char *)m->component_id, component_id, -sizeof (m->component_id) -1 ); +memcpy (m->component_id, component_id,sizeof (m->component_id)); m->validity_flags |=CXL_MSER_VALID_COMP_ID ;if (has_comp_id_pldm && is_comp_id_pldm) { m->validity_flags |=CXL_MSER_VALID_COMP_ID_FORMAT ;
Signature · 1 line
MST
[PULL 100/106] hw/cxl: Add fixes in Post Package Repair (PPR)
In reply to Michael S. TsirkinFrom: Shiju Jose <[email protected]>
Add following fixes to the commit: hw/cxl: Add support for Maintenance command and Post Package Repair (PPR).
In cxl_perform_ppr(), remove and free the maintenance entry from QLIST if match is found and PPR operation is performed.
Message-Id: <[email protected]>
--- hw/cxl/cxl-mailbox-utils.c | 2 ++ 1 file changed, 2 insertions(+)
hw/cxl/cxl-mailbox-utils.c +2 -0
@@ -2068,6 +2068,8 @@ static void cxl_perform_ppr(CXLType3Dev *ct3d, uint64_t dpa)CXL_MEMDEV_MAINT_SUBCLASS_CACHELINE_SPARING , ent, NULL); } +QLIST_REMOVE (ent, node); +g_free (ent);break ; } }
Signature · 1 line
MST
[PULL 101/106] hw/cxl/events: Fix handling of component ID in event records generation to not assume it is a string
In reply to Michael S. TsirkinFrom: Shiju Jose <[email protected]>
Fix handling of component ID in event records generation to not assume it is a string. Component ID in CXL events is 16 bytes data, but event record generation copy 15 bytes only from the qmp "component-id" field using strncpy. Replace strncpy with memcpy and copy the entire component ID data.
Message-Id: <[email protected]>
--- hw/mem/cxl_type3.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-)
hw/mem/cxl_type3.c +3 -6
@@ -1895,8 +1895,7 @@ void qmp_cxl_inject_general_media_event(const char *path, CxlEventLog log, }if (component_id) { -strncpy ((char *)gem.component_id, component_id, -sizeof (gem.component_id) -1 ); +memcpy (gem.component_id, component_id,sizeof (gem.component_id)); valid_flags |=CXL_GMER_VALID_COMPONENT ;if (has_comp_id_pldm && is_comp_id_pldm) { valid_flags |=CXL_GMER_VALID_COMPONENT_ID_FORMAT ;
@@ -2066,8 +2065,7 @@ void qmp_cxl_inject_dram_event(const char *path, CxlEventLog log, }if (component_id) { -strncpy ((char *)dram.component_id, component_id, -sizeof (dram.component_id) -1 ); +memcpy (dram.component_id, component_id,sizeof (dram.component_id)); valid_flags |=CXL_DRAM_VALID_COMPONENT ;if (has_comp_id_pldm && is_comp_id_pldm) { valid_flags |=CXL_DRAM_VALID_COMPONENT_ID_FORMAT ;
@@ -2185,8 +2183,7 @@ void qmp_cxl_inject_memory_module_event(const char *path, CxlEventLog log, corrected_persist_error_count);if (component_id) { -strncpy ((char *)module.component_id, component_id, -sizeof (module.component_id) -1 ); +memcpy (module.component_id, component_id,sizeof (module.component_id)); valid_flags |=CXL_MMER_VALID_COMPONENT ;if (has_comp_id_pldm && is_comp_id_pldm) { valid_flags |=CXL_MMER_VALID_COMPONENT_ID_FORMAT ;
Signature · 1 line
MST
[PULL 102/106] hw/cxl: Allow cxl_cfmws_find_device() to filter on whether interleaved paths are accepted
In reply to Michael S. TsirkinFrom: Alireza Sanaee via qemu development <[email protected]>
Extend cxl_cfmws_find_device() with a parameter that filters on whether the address lies in an interleaved range. For now all callers accept interleave configurations so no functional changes.
Message-Id: <[email protected]>
--- hw/cxl/cxl-host.c | 33 ++++++++++++++++++++++++++------- 1 file changed, 26 insertions(+), 7 deletions(-)
hw/cxl/cxl-host.c +26 -7
@@ -104,7 +104,7 @@ void cxl_fmws_link_targets(Error **errp) }static bool cxl_hdm_find_target (uint32_t *cache_mem,hwaddr addr, -uint8_t *target) +uint8_t *target,bool *interleaved) {int hdm_inc =R_CXL_HDM_DECODER1_BASE_LO -R_CXL_HDM_DECODER0_BASE_LO ;unsigned int hdm_count;
@@ -138,6 +138,11 @@ static bool cxl_hdm_find_target(uint32_t *cache_mem, hwaddr addr, found = true; ig_enc =FIELD_EX32 (ctrl,CXL_HDM_DECODER0_CTRL ,IG ); iw_enc =FIELD_EX32 (ctrl,CXL_HDM_DECODER0_CTRL ,IW ); + +if (interleaved) { + *interleaved = iw_enc !=0 ; + } + target_idx = (addr /cxl_decode_ig (ig_enc)) % (1 << iw_enc);if (target_idx <4 ) {
@@ -157,7 +162,8 @@ static bool cxl_hdm_find_target(uint32_t *cache_mem, hwaddr addr,return found; } -static PCIDevice *cxl_cfmws_find_device (CXLFixedWindow *fw,hwaddr addr) +static PCIDevice *cxl_cfmws_find_device (CXLFixedWindow *fw,hwaddr addr, +bool allow_interleave) {CXLComponentState *hb_cstate, *usp_cstate;PCIHostState *hb;
@@ -165,9 +171,13 @@ static PCIDevice *cxl_cfmws_find_device(CXLFixedWindow *fw, hwaddr addr)int rb_index;uint32_t *cache_mem;uint8_t target; -bool target_found; +bool target_found, interleaved;PCIDevice *rp, *d; +if ((fw->num_targets >1 ) && !allow_interleave) { +return NULL ; + } + rb_index = (addr /cxl_decode_ig (fw->enc_int_gran)) % fw->num_targets; hb =PCI_HOST_BRIDGE (fw->target_hbs[rb_index]->cxl_host_bridge);if (!hb || !hb->bus || !pci_bus_is_cxl (hb->bus)) {
@@ -187,11 +197,16 @@ static PCIDevice *cxl_cfmws_find_device(CXLFixedWindow *fw, hwaddr addr) cache_mem = hb_cstate->crb.cache_mem_registers; - target_found =cxl_hdm_find_target (cache_mem, addr, &target); + target_found =cxl_hdm_find_target (cache_mem, addr, &target, + &interleaved);if (!target_found) {return NULL ; } +if (interleaved && !allow_interleave) { +return NULL ; + } + rp =pcie_find_port_by_pn (hb->bus, target);if (!rp) {return NULL ;
@@ -223,11 +238,15 @@ static PCIDevice *cxl_cfmws_find_device(CXLFixedWindow *fw, hwaddr addr) cache_mem = usp_cstate->crb.cache_mem_registers; - target_found =cxl_hdm_find_target (cache_mem, addr, &target); + target_found =cxl_hdm_find_target (cache_mem, addr, &target, &interleaved);if (!target_found) {return NULL ; } +if (interleaved && !allow_interleave) { +return NULL ; + } + d =pcie_find_port_by_pn (&PCI_BRIDGE (d)->sec_bus, target);if (!d) {return NULL ;
@@ -251,7 +270,7 @@ static MemTxResult cxl_read_cfmws(void *opaque, hwaddr addr, uint64_t *data,CXLFixedWindow *fw = opaque;PCIDevice *d; - d =cxl_cfmws_find_device (fw, addr + fw->base); + d =cxl_cfmws_find_device (fw, addr + fw->base, true);if (d ==NULL ) { *data =0 ;/* Reads to invalid address return poison */
@@ -268,7 +287,7 @@ static MemTxResult cxl_write_cfmws(void *opaque, hwaddr addr,CXLFixedWindow *fw = opaque;PCIDevice *d; - d =cxl_cfmws_find_device (fw, addr + fw->base); + d =cxl_cfmws_find_device (fw, addr + fw->base, true);if (d ==NULL ) {/* Writes to invalid address are silent */ return MEMTX_OK ;
Signature · 1 line
MST
[PULL 008/106] vfio/iommufd: Create nesting parent hwpt with IOMMU_HWPT_ALLOC_PASID flag
In reply to Michael S. TsirkinFrom: Zhenzhong Duan <[email protected]>
When both device and vIOMMU have PASID enabled, then guest may setup pasid usages such as SVM.
VFIO needs to be aware of potential pasid usage and should attach the non-pasid part of pasid-capable device to hwpt flagged with IOMMU_HWPT_ALLOC_PASID.
ARM SMMU doesn't support IOMMU_HWPT_ALLOC_PASID, only VTD need it. So we can't check the existing vIOMMU flag VIOMMU_FLAG_PASID_SUPPORTED to determine if set flag IOMMU_HWPT_ALLOC_PASID. Instead, introduce a new flag VIOMMU_FLAG_WANT_PASID_ATTACH which will only be exposed by VTD.
Opportunistically add documentation for VIOMMU_FLAG_PASID_SUPPORTED and explain the difference with VIOMMU_FLAG_WANT_PASID_ATTACH.
Message-Id: <[email protected]>
--- hw/vfio/device.c | 11 +++++++++++ hw/vfio/iommufd.c | 8 +++++++- include/hw/core/iommu.h | 11 +++++++++++ include/hw/vfio/vfio-device.h | 1 + 4 files changed, 30 insertions(+), 1 deletion(-)
hw/vfio/device.c +11 -0
@@ -543,6 +543,17 @@ bool vfio_device_get_viommu_flags_want_nesting(VFIODevice *vbasedev)return false; } +bool vfio_device_get_viommu_flags_want_pasid_attach (VFIODevice *vbasedev) +{ +VFIOPCIDevice *vdev =vfio_pci_from_vfio_device (vbasedev); + +if (vdev) { +return !!(pci_device_get_viommu_flags (PCI_DEVICE (vdev)) & +VIOMMU_FLAG_WANT_PASID_ATTACH ); + } +return false; +} +bool vfio_device_get_host_iommu_quirk_bypass_ro (VFIODevice *vbasedev,uint32_t type,void *caps,uint32_t size)
hw/vfio/iommufd.c +7 -1
@@ -364,6 +364,7 @@ static bool iommufd_cdev_autodomains_get(VFIODevice *vbasedev,VendorCaps caps;VFIOIOASHwpt *hwpt;uint32_t hwpt_id; +uint8_t max_pasid_log2 =0 ;int ret;/* Try to find a domain */
@@ -409,7 +410,7 @@ static bool iommufd_cdev_autodomains_get(VFIODevice *vbasedev,*/ if (!iommufd_backend_get_device_info (vbasedev->iommufd, vbasedev->devid, &type, &caps,sizeof (caps), &hw_caps, -NULL , errp)) { + &max_pasid_log2, errp)) {return false; }
@@ -437,6 +438,11 @@ static bool iommufd_cdev_autodomains_get(VFIODevice *vbasedev, } } +if (max_pasid_log2 && +vfio_device_get_viommu_flags_want_pasid_attach (vbasedev)) { + flags |=IOMMU_HWPT_ALLOC_PASID ; + } +if (cpr_is_incoming ()) { hwpt_id = vbasedev->cpr.hwpt_id; goto skip_alloc;
include/hw/core/iommu.h +11 -0
@@ -20,9 +20,20 @@enum viommu_flags {/* vIOMMU needs nesting parent HWPT to create nested HWPT */ VIOMMU_FLAG_WANT_NESTING_PARENT =BIT_ULL (0 ), +/* +* vIOMMU supports PASID capability, VFIO checks this flag and synthesize +* a PASID capability. +*/ VIOMMU_FLAG_PASID_SUPPORTED =BIT_ULL (1 ),/* vIOMMU needs dirty tracking on the nesting parent HWPT for nested use */ VIOMMU_FLAG_WANT_NESTING_DIRTY_TRACKING =BIT_ULL (2 ), +/* +* vIOMMU requests other sub-system like VFIO to create a HWPT that can be +* used with PASID attachment. VIOMMU_FLAG_PASID_SUPPORTED can't be used +* for this purpose as PASID attachment is needed by VTD IOMMU but not ARM +* SMMU. +*/ +VIOMMU_FLAG_WANT_PASID_ATTACH =BIT_ULL (3 ), };/* Host IOMMU quirks. Extracted from host IOMMU capabilities */
include/hw/vfio/vfio-device.h +1 -0
@@ -282,6 +282,7 @@ void vfio_device_unprepare(VFIODevice *vbasedev);bool vfio_device_get_viommu_flags_want_nesting (VFIODevice *vbasedev);bool vfio_device_get_viommu_flags_want_nesting_dirty (VFIODevice *vbasedev); +bool vfio_device_get_viommu_flags_want_pasid_attach (VFIODevice *vbasedev);bool vfio_device_get_host_iommu_quirk_bypass_ro (VFIODevice *vbasedev,uint32_t type,void *caps,uint32_t size);
Signature · 1 line
MST
[PULL 043/106] vhost: move busyloop timeout initialization to vhost_virtqueue_init()
In reply to Michael S. TsirkinFrom: Vladimir Sementsov-Ogievskiy <[email protected]>
Let's all per-virtqueue initializations be in one place.
Message-Id: <[email protected]>
--- hw/virtio/vhost.c | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-)
hw/virtio/vhost.c +12 -13
@@ -1496,7 +1496,8 @@ static void vhost_virtqueue_error_notifier(EventNotifier *n) }static int vhost_virtqueue_init (struct vhost_dev *dev, -struct vhost_virtqueue *vq,int n) +struct vhost_virtqueue *vq,int n, +bool busyloop_timeout) {int vhost_vq_index = dev->vhost_ops->vhost_get_vq_index (dev, n);struct vhost_vring_file file = {
@@ -1533,6 +1534,14 @@ static int vhost_virtqueue_init(struct vhost_dev *dev, vhost_virtqueue_error_notifier); } +if (busyloop_timeout) { + r =vhost_virtqueue_set_busyloop_timeout (dev, n, busyloop_timeout); +if (r <0 ) { +VHOST_OPS_DEBUG (r,"Failed to set busyloop timeout" ); + goto fail_err; + } + } +return 0 ; fail_err:
@@ -1611,24 +1620,14 @@ int vhost_dev_init(struct vhost_dev *hdev, void *opaque, }for (i =0 ; i < hdev->nvqs; ++i, ++n_initialized_vqs) { - r =vhost_virtqueue_init (hdev, hdev->vqs + i, hdev->vq_index + i); + r =vhost_virtqueue_init (hdev, hdev->vqs + i, hdev->vq_index + i, + busyloop_timeout);if (r <0 ) {error_setg_errno (errp, -r,"Failed to initialize virtqueue %d" , i); goto fail; } } -if (busyloop_timeout) { -for (i =0 ; i < hdev->nvqs; ++i) { - r =vhost_virtqueue_set_busyloop_timeout (hdev, hdev->vq_index + i, - busyloop_timeout); -if (r <0 ) { -error_setg_errno (errp, -r,"Failed to set busyloop timeout" ); - goto fail; - } - } - } -virtio_features_copy (hdev->_features_ex, features); hdev->memory_listener = (MemoryListener ) {
Signature · 1 line
MST
[PULL 103/106] hw/cxl: Add a performant (and correct) path for the non interleaved cases
In reply to Michael S. TsirkinFrom: Alireza Sanaee via qemu development <[email protected]>
The CXL address to device decoding logic is complex because of the need to correctly decode fine grained interleave. The current implementation prevents use with KVM where executed instructions may reside in that memory and gives very slow performance even in TCG.
In many real cases non interleaved memory configurations are useful and for those we can use a more conventional memory region alias allowing similar performance to other memory in the system.
Whether this fast path is applicable can be established once the full set of HDM decoders has been committed (in whatever order the guest decides to commit them). As such a check is performed on each commit/uncommit of HDM decoder to establish if the alias should be added or removed.
Message-Id: <[email protected]>
--- hw/cxl/cxl-component-utils.c | 6 ++ hw/cxl/cxl-host.c | 201 +++++++++++++++++++++++++++++++++++ hw/mem/cxl_type3.c | 4 + include/hw/cxl/cxl.h | 1 + include/hw/cxl/cxl_device.h | 4 + 5 files changed, 216 insertions(+)
hw/cxl/cxl-component-utils.c +6 -0
@@ -143,6 +143,12 @@ static void dumb_hdm_handler(CXLComponentState *cxl_cstate, hwaddr offset, value =FIELD_DP32 (value,CXL_HDM_DECODER0_CTRL ,COMMITTED ,0 ); }stl_le_p ((uint8_t *)cache_mem + offset, value); + +if (should_commit) { +cfmws_update_non_interleaved (true); + }else if (should_uncommit) { +cfmws_update_non_interleaved (false); + } } static void bi_handler(CXLComponentState *cxl_cstate, hwaddr offset,
hw/cxl/cxl-host.c +201 -0
207 lines not on this page · raw message
hw/mem/cxl_type3.c +4 -0
@@ -427,6 +427,8 @@ static void hdm_decoder_commit(CXLType3Dev *ct3d, int which) ctrl =FIELD_DP32 (ctrl,CXL_HDM_DECODER0_CTRL ,COMMITTED ,1 );stl_le_p (cache_mem +R_CXL_HDM_DECODER0_CTRL + which * hdm_inc, ctrl); + +cfmws_update_non_interleaved (true); }static void hdm_decoder_uncommit (CXLType3Dev *ct3d,int which)
@@ -442,6 +444,8 @@ static void hdm_decoder_uncommit(CXLType3Dev *ct3d, int which) ctrl =FIELD_DP32 (ctrl,CXL_HDM_DECODER0_CTRL ,COMMITTED ,0 );stl_le_p (cache_mem +R_CXL_HDM_DECODER0_CTRL + which * hdm_inc, ctrl); + +cfmws_update_non_interleaved (false); }static int ct3d_qmp_uncor_err_to_cxl (CxlUncorErrorType qmp_err)
include/hw/cxl/cxl.h +1 -0
@@ -71,4 +71,5 @@ CXLComponentState *cxl_usp_to_cstate(CXLUpstreamPort *usp);typedef struct CXLDownstreamPort CXLDownstreamPort ; DECLARE_INSTANCE_CHECKER(CXLDownstreamPort, CXL_DSP, TYPE_CXL_DSP) +void cfmws_update_non_interleaved (bool commit);#endif
include/hw/cxl/cxl_device.h +4 -0
@@ -685,6 +685,8 @@ typedef struct CXLSetFeatureInfo {size_t data_size; } CXLSetFeatureInfo; +typedef struct CXLFixedWindow CXLFixedWindow ; +struct CXLSanitizeInfo ; typedef struct CXLAlertConfig {
@@ -712,6 +714,8 @@ struct CXLType3Dev {uint64_t sn;/* State */ +MemoryRegion direct_mr[CXL_HDM_DECODER_COUNT ]; +CXLFixedWindow *direct_mr_fw[CXL_HDM_DECODER_COUNT ];AddressSpace hostvmem_as;AddressSpace hostpmem_as;CXLComponentState cxl_cstate;
Signature · 1 line
MST
[PULL 062/106] vhost-user.rst: Explicitly allow front-end to write to kick FDs
In reply to Michael S. TsirkinFrom: "Jorge E. Moreira" <[email protected]>
Migration of back-end state happens while the device is suspended (i.e all vrings are stopped). To resume normal operation on the destination, the vrings need to be started again with a kick (either a write on the FD or the VHOST_USER_VRING_KICK in-band message if negotiated). While these notifications are typically sent by the driver, it has no reason to send them in the destination if it already sent them in the source as the driver is unaware that a migration took place. Therefore it should be the responsibility of the vhost-user front-end to ensure these vrings are started. This is particularly necessary for queues where data only flows from device to driver, such as those used by the vsock and input devices.
This behavior is already used by some qemu vhost-user front-ends (e.g vhost-user-blk) and by front-ends implemented on other VMMs(e.g CrosVm). Adding it to the vhost-user documentation makes it explicit that this strategy is permitted and suggest it to vhost-user front-end authors. Explicitly documenting it is necessary because vring kicks appear designed to originate in the driver, so having some originate in the front-end can be counterintuitive and cause developers to waste time looking for other alternatives or face pushback during code review.
Message-Id: <[email protected]>
--- docs/interop/vhost-user.rst | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
docs/interop/vhost-user.rst +4 -1
@@ -668,7 +668,10 @@ destination, following the usual protocol for establishing a connection to a vhost-user back-end: This includes, for example, setting up memory mappings and kick and call FDs as necessary, negotiating protocol features, or setting the initial vring base indices (to the same value -as on the source side, so that operation can resume). +as on the source side, so that operation can resume). The vhost-user front-end +may also write to the kick FDs of vrings containing unused buffers or send +``VHOST_USER_VRING_KICK`` if negotiated to start those vrings in the destination +since the driver likely already kicked them in the source and won't do it again. Both on the source and on the destination side, after the respective front-end has seen all data transferred (when the transfer FD has been
Signature · 1 line
MST
[PULL 021/106] intel_iommu_accel: Add pasid bits size check
In reply to Michael S. TsirkinFrom: Zhenzhong Duan <[email protected]>
If pasid bits size is bigger than host side, host could fail to emulate all bindings in guest. Add a check to fail device plug early.
Message-Id: <[email protected]>
--- hw/i386/intel_iommu_accel.c | 8 ++++++++ hw/i386/intel_iommu_internal.h | 1 + 2 files changed, 9 insertions(+)
hw/i386/intel_iommu_accel.c +8 -0
@@ -22,6 +22,7 @@ bool vtd_check_hiod_accel(IntelIOMMUState *s, VTDHostIOMMUDevice *vtd_hiod,HostIOMMUDevice *hiod = vtd_hiod->hiod;struct HostIOMMUDeviceCaps *caps = &hiod->caps;struct iommu_hw_info_vtd *vtd = &caps->vendor_caps.vtd; +uint8_t hpasid =VTD_ECAP_GET_PSS (vtd->ecap_reg) +1 ;PCIBus *bus = vtd_hiod->bus;PCIDevice *pdev = bus->devices[vtd_hiod->devfn];
@@ -42,6 +43,13 @@ bool vtd_check_hiod_accel(IntelIOMMUState *s, VTDHostIOMMUDevice *vtd_hiod,return false; } +/* Only do the check when host device support PASIDs */ +if (caps->max_pasid_log2 && s->pasid > hpasid) { +error_setg (errp,"PASID bits size %d > host IOMMU PASID bits size %d" , + s->pasid, hpasid); +return false; + } +if (pci_device_get_iommu_bus_devfn (pdev, &bus,NULL ,NULL )) {error_setg (errp,"Host device downstream to a PCI bridge is " "unsupported when fsts=on" );
hw/i386/intel_iommu_internal.h +1 -0
@@ -196,6 +196,7 @@#define VTD_ECAP_SRS (1ULL << 31)#define VTD_ECAP_NWFS (1ULL << 33)#define VTD_ECAP_SET_PSS (x, v) ((x)->ecap = deposit64((x)->ecap, 35, 5, v)) +#define VTD_ECAP_GET_PSS (ecap) extract64(ecap, 35, 5)#define VTD_ECAP_PASID (1ULL << 40)#define VTD_ECAP_PDS (1ULL << 42)#define VTD_ECAP_SMTS (1ULL << 43)
Signature · 1 line
MST
[PULL 058/106] vhost-user: add VHOST_USER_PROTOCOL_F_GPA_ADDRESSES
In reply to Michael S. TsirkinFrom: Vladimir Sementsov-Ogievskiy <[email protected]>
Unlike the kernel, vhost-user backend knows nothing about QEMU's userspace addresses. We can pass GPA instead and nothing changes. Generally, vhost-user servers need these addresses only to calculate offsets inside memory regions. Still, some servers (QEMU's internal is one example) may do checks for passed addresses to be "userspace addresses", for example check for non-zero. That's why we need additional negotiation for the feature.
The benefit: this opens the doors for further implementation of local migration (live-update) with passing open vhost-related FDs through UNIX domain socket. This way the connection with backend is kept live and untouched.
Without this change, we would have to communicate with backend to inform it about UVA address changes, but it's better to simply use more stable GPA numbers, which don't change after migration.
Additionally, the current implementation exposes QEMU's process address space by passing UVA, which breaks ASLR. New protocol feature avoids that.
Note, that we do nothing with backend messages and replies. Frontends have to work with backends userspace addresses anyway, because they come from userfaultfd.
Based-on: <[email protected]>
Message-Id: <[email protected]>
--- docs/interop/vhost-user.rst | 21 +++++++++++++++++---- hw/virtio/vhost-user.c | 22 +++++++++++++++++----- include/hw/virtio/vhost-user.h | 1 + 3 files changed, 35 insertions(+), 9 deletions(-)
docs/interop/vhost-user.rst +17 -4
@@ -164,8 +164,16 @@ A vring address description :log: a 64-bit guest address for logging -Note that a ring address is an IOVA if ``VIRTIO_F_IOMMU_PLATFORM`` has -been negotiated. Otherwise it is a user address. +.. Note:: + When ``VIRTIO_F_IOMMU_PLATFORM`` is negotiated, ring addresses are IOVAs. + + Otherwise, when ``VHOST_USER_PROTOCOL_F_GPA_ADDRESSES`` is negotiated, the + ring addresses are guest physical addresses for frontend messages. That + does not apply to backend replies. + + Finally, when neither ``VIRTIO_F_IOMMU_PLATFORM`` nor + ``VHOST_USER_PROTOCOL_F_GPA_ADDRESSES`` features are negotiated, ring + addresses are user virtual addresses. .. _memory_region_description:
@@ -180,7 +188,9 @@ Memory region description :size: a 64-bit size -:user address: a 64-bit user address +:user address: a 64-bit user address. When ``VHOST_USER_PROTOCOL_F_GPA_ADDRESSES`` + is negotiated, this field contain guest physical address instead and must + duplicate ``guest address`` field. :mmap offset: a 64-bit offset where region starts in the mapped memory
@@ -252,7 +262,9 @@ An IOTLB message :size: a 64-bit size -:user address: a 64-bit user address +:user address: a 64-bit user address. When ``VHOST_USER_PROTOCOL_F_GPA_ADDRESSES`` + is negotiated, this field contain guest physical address instead, except for + ``VHOST_USER_BACKEND_IOTLB_MSG``, where it's user address anyway. :permissions flags: an 8-bit value: - 0: No access
@@ -1063,6 +1075,7 @@ Protocol features #define VHOST_USER_PROTOCOL_F_SHARED_OBJECT 18 #define VHOST_USER_PROTOCOL_F_DEVICE_STATE 19 #define VHOST_USER_PROTOCOL_F_GET_VRING_BASE_INFLIGHT 20 + #define VHOST_USER_PROTOCOL_F_GPA_ADDRESSES 21 Front-end message types -----------------------
hw/virtio/vhost-user.c +17 -5
@@ -563,12 +563,22 @@ static MemoryRegion *vhost_user_get_mr_data(uint64_t addr, ram_addr_t *offset,return mr; } -static void vhost_user_fill_msg_region (VhostUserMemoryRegion *dst, +static bool vhost_user_gpa_addresses (struct vhost_dev *dev) +{ +return vhost_user_has_protocol_feature ( + dev,VHOST_USER_PROTOCOL_F_GPA_ADDRESSES ); +} + +static void vhost_user_fill_msg_region (struct vhost_dev *dev, +VhostUserMemoryRegion *dst,struct vhost_memory_region *src,uint64_t mmap_offset) { +bool use_phys =vhost_user_gpa_addresses (dev); +assert (src !=NULL && dst !=NULL ); - dst->userspace_addr = src->userspace_addr; + + dst->userspace_addr = use_phys ? src->guest_phys_addr : src->userspace_addr; dst->memory_size = src->memory_size; dst->guest_phys_addr = src->guest_phys_addr; dst->mmap_offset = mmap_offset;
@@ -606,7 +616,7 @@ static int vhost_user_fill_set_mem_table_msg(struct vhost_user *u,error_report ("Failed preparing vhost-user memory table msg" );return -ENOBUFS ; } -vhost_user_fill_msg_region (®ion_buffer, reg, offset); +vhost_user_fill_msg_region (dev, ®ion_buffer, reg, offset); msg->payload.memory.regions[*fd_num] = region_buffer; fds[(*fd_num)++] = fd; }else if (track_ramblocks) {
@@ -752,7 +762,7 @@ static int send_remove_regions(struct vhost_dev *dev,if (fd >0 ) { msg->hdr.request =VHOST_USER_REM_MEM_REG ; -vhost_user_fill_msg_region (®ion_buffer, shadow_reg,0 ); +vhost_user_fill_msg_region (dev, ®ion_buffer, shadow_reg,0 ); msg->payload.mem_reg.region = region_buffer; ret =vhost_user_write (dev, msg,NULL ,0 );
@@ -813,7 +823,7 @@ static int send_add_regions(struct vhost_dev *dev, u->region_rb[reg_idx] = mr->ram_block; } msg->hdr.request =VHOST_USER_ADD_MEM_REG ; -vhost_user_fill_msg_region (®ion_buffer, reg, offset); +vhost_user_fill_msg_region (dev, ®ion_buffer, reg, offset); msg->payload.mem_reg.region = region_buffer; ret =vhost_user_write (dev, msg, &fd,1 );
@@ -3151,4 +3161,6 @@ const VhostOps user_ops = { .vhost_supports_device_state = vhost_user_supports_device_state, .vhost_set_device_state_fd = vhost_user_set_device_state_fd, .vhost_check_device_state = vhost_user_check_device_state, + .vhost_phys_vring_addr = vhost_user_gpa_addresses, + .vhost_phys_iotlb_msg = vhost_user_gpa_addresses, };
include/hw/virtio/vhost-user.h +1 -0
@@ -34,6 +34,7 @@ enum VhostUserProtocolFeature {VHOST_USER_PROTOCOL_F_SHARED_OBJECT =18 ,VHOST_USER_PROTOCOL_F_DEVICE_STATE =19 ,VHOST_USER_PROTOCOL_F_GET_VRING_BASE_INFLIGHT =20 , +VHOST_USER_PROTOCOL_F_GPA_ADDRESSES =21 , VHOST_USER_PROTOCOL_F_MAX };
Signature · 1 line
MST
[PULL 065/106] vhost-user-blk-server: do not advertise VIRTIO_BLK_F_SIZE_MAX with size_max=0
In reply to Michael S. TsirkinFrom: Max Makarov <[email protected]>
The QSD vhost-user-blk backend advertises VIRTIO_BLK_F_SIZE_MAX but sets size_max=0 in config, creating a contradictory state. The feature bit tells the guest that size_max is valid, but the value is zero.
Windows viostor trusts the feature bit, reads size_max=0, and uses it in scatter-gather calculations producing zero-length segments that hang I/O. The disk appears empty (no GPT, no partitions), causing INACCESSIBLE_BOOT_DEVICE BSOD. Linux tolerates this because blk_validate_limits() silently corrects max_segment_size=0 to BLK_MAX_SEGMENT_SIZE (65536).
This affects any VMM using QSD as a vhost-user-blk backend (QEMU, Cloud Hypervisor, etc.), since both pass through SIZE_MAX from the backend to the guest via feature intersection.
Remove VIRTIO_BLK_F_SIZE_MAX from the backend feature bits. The size_max config field remains zero but is now ignored by guests since the feature is not negotiated.
Message-Id: <[email protected]>
--- block/export/vhost-user-blk-server.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
block/export/vhost-user-blk-server.c +1 -1
@@ -119,7 +119,7 @@ static uint64_t vu_blk_get_features(VuDev *dev)uint64_t features;VuServer *server =container_of (dev, VuServer, vu_dev);VuBlkExport *vexp =container_of (server, VuBlkExport, vu_server); - features =1ull <<VIRTIO_BLK_F_SIZE_MAX | + features =1ull <<VIRTIO_BLK_F_SEG_MAX |1ull <<VIRTIO_BLK_F_TOPOLOGY | 1ull << VIRTIO_BLK_F_BLK_SIZE |
Signature · 1 line
MST
[PULL 030/106] vhost: move protocol_features to vhost_user
In reply to Michael S. TsirkinFrom: Vladimir Sementsov-Ogievskiy <[email protected]>
As comment says: it's only for vhost-user. So, let's move it to corresponding vhost backend realization.
Message-Id: <[email protected]>
--- backends/cryptodev-vhost.c | 1 - hw/block/vhost-user-blk.c | 6 ++---- hw/net/vhost_net.c | 2 -- hw/virtio/meson.build | 1 + hw/virtio/vhost-user-stub.c | 6 ++++++ hw/virtio/vhost-user.c | 36 +++++++++++++++++++++++++++------- hw/virtio/virtio-qmp.c | 6 ++++-- include/hw/virtio/vhost-user.h | 4 ++++ include/hw/virtio/vhost.h | 8 -------- 9 files changed, 46 insertions(+), 24 deletions(-) create mode 100644 hw/virtio/vhost-user-stub.c
backends/cryptodev-vhost.c +0 -1
@@ -60,7 +60,6 @@ cryptodev_vhost_init( crypto->cc = options->cc; - crypto->dev.protocol_features =0 ; crypto->backend =-1 ;/* vhost-user needs vq_index to initiate a specific queue pair */
hw/block/vhost-user-blk.c +2 -4
@@ -572,10 +572,8 @@ static bool vhost_user_blk_inflight_needed(void *opaque) {struct VHostUserBlk *s = opaque; -bool inflight_migration =virtio_has_feature (s->dev.protocol_features, -VHOST_USER_PROTOCOL_F_GET_VRING_BASE_INFLIGHT ); - -return inflight_migration; +return vhost_user_has_protocol_feature ( + &s->dev,VHOST_USER_PROTOCOL_F_GET_VRING_BASE_INFLIGHT ); }static const VMStateDescription vmstate_vhost_user_blk_inflight = {
hw/net/vhost_net.c +0 -2
@@ -265,9 +265,7 @@ struct vhost_net *vhost_net_init(VhostNetOptions *options) goto fail; } net->backend = r; - net->dev.protocol_features =0 ; }else { - net->dev.protocol_features =0 ; net->backend =-1 ;/* vhost-user needs vq_index to initiate a specific queue pair */
hw/virtio/meson.build +1 -0
@@ -94,6 +94,7 @@ system_virtio_ss.add_all(when: 'CONFIG_VIRTIO_PCI', if_true: virtio_pci_ss) system_ss.add_all(when: 'CONFIG_VIRTIO', if_true: system_virtio_ss) stub_ss.add(files('vhost-stub.c')) +stub_ss.add(files('vhost-user-stub.c')) stub_ss.add(files('virtio-stub.c')) stub_ss.add(files('virtio-md-stubs.c'))
hw/virtio/vhost-user-stub.c new file +6 -0
@@ -0,0 +1,6 @@ +#include "qemu/osdep.h" +#include "hw/virtio/vhost-user.h" + +void vhost_user_qmp_status (struct vhost_dev *dev,VirtioStatus *status) +{ +}
hw/virtio/vhost-user.c +29 -7
@@ -11,6 +11,7 @@#include "qemu/osdep.h" #include "qapi/error.h" #include "hw/virtio/virtio-dmabuf.h" +#include "hw/virtio/virtio-qmp.h" #include "hw/virtio/vhost.h" #include "hw/virtio/virtio-crypto.h" #include "hw/virtio/vhost-user.h"
@@ -259,6 +260,14 @@ struct vhost_user {/* Our current regions */ int num_shadow_regions;struct vhost_memory_region shadow_regions[VHOST_USER_MAX_RAM_SLOTS ]; + +/** +* @protocol_features: the vhost-user protocol feature set by +* VHOST_USER_SET_PROTOCOL_FEATURES. Protocol features are only +* negotiated if VHOST_USER_F_PROTOCOL_FEATURES has been offered +* by the backend (see @features). +*/ +uint64_t protocol_features; };struct scrub_regions {
@@ -267,10 +276,13 @@ struct scrub_regions {int fd_idx; }; -static bool vhost_user_has_protocol_feature (struct vhost_dev *dev, -uint64_t feature) +bool vhost_user_has_protocol_feature (struct vhost_dev *dev,uint64_t feature) { -return virtio_has_feature (dev->protocol_features, feature); +struct vhost_user *u = dev->opaque; + +assert (dev->vhost_ops->backend_type ==VHOST_BACKEND_TYPE_USER ); + +return virtio_has_feature (u->protocol_features, feature); }static int vhost_user_read_header (struct vhost_dev *dev,VhostUserMsg *msg)
@@ -1338,8 +1350,8 @@ static int vhost_set_vring_file(struct vhost_dev *dev,int ret;int fds[VHOST_USER_MAX_RAM_SLOTS ];size_t fd_num =0 ; -bool reply_supported =virtio_has_feature (dev->protocol_features, -VHOST_USER_PROTOCOL_F_REPLY_ACK ); +bool reply_supported = +vhost_user_has_protocol_feature (dev,VHOST_USER_PROTOCOL_F_REPLY_ACK );VhostUserMsg msg = { .hdr.request = request, .hdr.flags =VHOST_USER_VERSION ,
@@ -2239,8 +2251,8 @@ static int vhost_user_backend_init(struct vhost_dev *dev, void *opaque, }/* final set of protocol features */ - dev->protocol_features = protocol_features; - err =vhost_user_set_protocol_features (dev, dev->protocol_features); + u->protocol_features = protocol_features; + err =vhost_user_set_protocol_features (dev, u->protocol_features);if (err <0 ) {error_setg_errno (errp,EPROTO ,"vhost_backend_init failed" );return -EPROTO ;
@@ -3033,6 +3045,16 @@ static int vhost_user_check_device_state(struct vhost_dev *dev, Error **errp)return 0 ; } +void vhost_user_qmp_status (struct vhost_dev *dev,VirtioStatus *status) +{ +struct vhost_user *u = dev->opaque; + +assert (dev->vhost_ops->backend_type ==VHOST_BACKEND_TYPE_USER ); + + status->vhost_dev->protocol_features = +qmp_decode_protocols (u->protocol_features); +} +const VhostOps user_ops = { .backend_type =VHOST_BACKEND_TYPE_USER , .vhost_backend_init = vhost_user_backend_init,
hw/virtio/virtio-qmp.c +4 -2
@@ -751,12 +751,14 @@ VirtioStatus *qmp_x_query_virtio_status(const char *path, Error **errp) status->vhost_dev->acked_features =qmp_decode_features (vdev->device_id, hdev->acked_features_ex); - status->vhost_dev->protocol_features = -qmp_decode_protocols (hdev->protocol_features); status->vhost_dev->max_queues = hdev->max_queues; status->vhost_dev->backend_cap = hdev->backend_cap; status->vhost_dev->log_enabled = hdev->log_enabled; status->vhost_dev->log_size = hdev->log_size; + +if (hdev->vhost_ops->backend_type ==VHOST_BACKEND_TYPE_USER ) { +vhost_user_qmp_status (hdev, status); + } }return status;
include/hw/virtio/vhost-user.h +4 -0
@@ -10,6 +10,7 @@#include "chardev/char-fe.h" #include "hw/virtio/virtio.h" +#include "qapi/qapi-types-virtio.h" enum VhostUserProtocolFeature {VHOST_USER_PROTOCOL_F_MQ =0 ,
@@ -113,4 +114,7 @@ void vhost_user_async_close(DeviceState *d, CharFrontend *chardev, struct vhost_dev *vhost, vu_async_close_fn cb); +void vhost_user_qmp_status (struct vhost_dev *dev,VirtioStatus *status); +bool vhost_user_has_protocol_feature (struct vhost_dev *dev,uint64_t feature); +#endif
include/hw/virtio/vhost.h +0 -8
@@ -104,14 +104,6 @@ struct vhost_dev {VIRTIO_DECLARE_FEATURES (features);VIRTIO_DECLARE_FEATURES (acked_features); -/** -* @protocol_features: is the vhost-user only feature set by -* VHOST_USER_SET_PROTOCOL_FEATURES. Protocol features are only -* negotiated if VHOST_USER_F_PROTOCOL_FEATURES has been offered -* by the backend (see @features). -*/ -uint64_t protocol_features; -uint64_t max_queues;uint64_t backend_cap;/* @started: is the vhost device started? */
Signature · 1 line
MST
[PULL 097/106] vhost-user-device: Add shared memory BAR
In reply to Michael S. TsirkinFrom: Albert Esteve <[email protected]>
Add shared memory BAR support to vhost-user-device-pci to enable direct file mapping for VIRTIO Shared Memory Regions.
The implementation creates a consolidated shared memory BAR that contains all VIRTIO Shared Memory Regions as subregions. Each region is configured with its proper shmid, size, and offset within the BAR. The number and size of regions are retrieved via VHOST_USER_GET_SHMEM_CONFIG message sent by vhost-user-base during realization after virtio_init().
Specifically, it uses BAR 4 to avoid conflicts, as it is currently unused.
The shared memory BAR is only created when the backend supports VHOST_USER_PROTOCOL_F_SHMEM and has configured shared memory regions. This maintains backward compatibility with backends that do not support shared memory functionality.
Message-Id: <[email protected]>
--- hw/virtio/vhost-user-base.c | 46 ++++++++++++++++++++++++-- hw/virtio/vhost-user-test-device-pci.c | 42 +++++++++++++++++++++-- 2 files changed, 83 insertions(+), 5 deletions(-)
hw/virtio/vhost-user-base.c +43 -3
@@ -16,6 +16,7 @@#include "hw/virtio/virtio-bus.h" #include "hw/virtio/vhost-user-base.h" #include "qemu/error-report.h" +#include "migration/blocker.h" static void vub_start (VirtIODevice *vdev) {
@@ -281,7 +282,8 @@ static void vub_device_realize(DeviceState *dev, Error **errp) {VirtIODevice *vdev =VIRTIO_DEVICE (dev);VHostUserBase *vub =VHOST_USER_BASE (dev); -int ret; +uint64_t memory_sizes[VIRTIO_MAX_SHMEM_REGIONS ]; +int i, ret, nregions, regions_processed =0 ;if (!vub->chardev.chr) {error_setg (errp,"vhost-user-base: missing chardev" );
@@ -324,7 +326,7 @@ static void vub_device_realize(DeviceState *dev, Error **errp)/* Allocate queues */ vub->vqs =g_ptr_array_sized_new (vub->num_vqs); -for (int i =0 ; i < vub->num_vqs; i++) { +for (i =0 ; i < vub->num_vqs; i++) {g_ptr_array_add (vub->vqs,virtio_add_queue (vdev, vub->vq_size, vub_handle_output));
@@ -338,11 +340,49 @@ static void vub_device_realize(DeviceState *dev, Error **errp) VHOST_BACKEND_TYPE_USER, 0, errp);if (ret <0 ) { -do_vhost_user_cleanup (vdev, vub); + goto err; + } + + ret = vub->vhost_dev.vhost_ops->vhost_get_shmem_config (&vub->vhost_dev, + &nregions, + memory_sizes, + errp); + +if (ret <0 ) { + goto err; + } + +for (i =0 ; i <VIRTIO_MAX_SHMEM_REGIONS && regions_processed < nregions; i++) { +if (memory_sizes[i]) { + regions_processed++; +if (vub->vhost_dev.migration_blocker ==NULL ) { +error_setg (&vub->vhost_dev.migration_blocker, +"Migration disabled: devices with VIRTIO Shared Memory " +"Regions do not support migration yet." ); + ret =migrate_add_blocker_normal ( + &vub->vhost_dev.migration_blocker, + errp); + +if (ret <0 ) { + goto err; + } + } + +if (memory_sizes[i] %qemu_real_host_page_size () !=0 ) { +error_setg (errp,"Shared memory %d size must be a multiple of " +"the host page size" , i); + goto err; + } + +virtio_new_shmem_region (vdev, i, memory_sizes[i]); + } }qemu_chr_fe_set_handlers (&vub->chardev,NULL ,NULL , vub_event,NULL , dev,NULL , true); +return ; +err: +do_vhost_user_cleanup (vdev, vub); }static void vub_device_unrealize (DeviceState *dev)
hw/virtio/vhost-user-test-device-pci.c +40 -2
60 lines not on this page · raw message
Signature · 1 line
MST
[PULL 020/106] intel_iommu_accel: Switch to VTDAccelPASIDCacheEntry for PASID bind/unbind and PIOTLB invalidation
In reply to Michael S. TsirkinFrom: Zhenzhong Duan <[email protected]>
This patch switches from VTDAddressSpace to VTDAccelPASIDCacheEntry for handling PASID bind/unbind operations and PIOTLB invalidations in passthrough scenarios. VTDAccelPASIDCacheEntry was introduced to cache PASID entries for passthrough devices and is now ready to propagate PASID bind/unbind operations and PIOTLB invalidations to the host.
Unlike the previous approach, VTDAccelPASIDCacheEntry supports both IOMMU_NO_PASID (rid_pasid) and other valid PASIDs, so this switch drops IOMMU_NO_PASID limitations that existed in the prior PASID bind/unbind and PIOTLB invalidation path. For IOMMU_NO_PASID of passthrough devices, VTDAddressSpace continues to handle shadow page modifications to the host, but no longer manages PASID bind/unbind operations or PIOTLB invalidations for passthrough scenarios.
Message-Id: <[email protected]>
--- hw/i386/intel_iommu.c | 17 +---- hw/i386/intel_iommu_accel.c | 131 +++++++++++++++++----------------- hw/i386/intel_iommu_accel.h | 2 +- include/hw/i386/intel_iommu.h | 2 - 4 files changed, 68 insertions(+), 84 deletions(-)
hw/i386/intel_iommu.c +1 -16
@@ -86,8 +86,6 @@ static void vtd_pasid_cache_reset_locked(IntelIOMMUState *s)VTDPASIDCacheEntry *pc_entry = &vtd_as->pasid_cache_entry;if (pc_entry->valid) { pc_entry->valid = false; -/* It's fatal to get failure during reset */ -vtd_propagate_guest_pasid (vtd_as, &error_fatal); } } }
@@ -3104,8 +3102,6 @@ static void vtd_pasid_cache_sync_locked(gpointer key, gpointer value,VTDPASIDEntry pe;IOMMUNotifier *n;uint16_t did; -const char *err_prefix ="Attaching to HWPT failed: " ; -Error *local_err =NULL ;if (vtd_dev_get_pe_from_pasid (vtd_as->iommu_state, vtd_as->bus, vtd_as->devfn, vtd_as->pasid, &pe)) {
@@ -3127,9 +3123,6 @@ static void vtd_pasid_cache_sync_locked(gpointer key, gpointer value,vtd_address_space_unmap (vtd_as, n); }vtd_switch_address_space (vtd_as); - - err_prefix ="Detaching from HWPT failed: " ; - goto do_bind_unbind; }/*
@@ -3157,20 +3150,12 @@ static void vtd_pasid_cache_sync_locked(gpointer key, gpointer value,if (!pc_entry->valid) { pc_entry->pasid_entry = pe; pc_entry->valid = true; - }else if (vtd_pasid_entry_compare (&pe, &pc_entry->pasid_entry)) { - err_prefix ="Replacing HWPT attachment failed: " ; - }else { + }else if (!vtd_pasid_entry_compare (&pe, &pc_entry->pasid_entry)) {return ; }vtd_switch_address_space (vtd_as);vtd_address_space_sync (vtd_as); - -do_bind_unbind: -/* TODO: Fault event injection into guest, report error to QEMU for now */ -if (!vtd_propagate_guest_pasid (vtd_as, &local_err)) { -error_reportf_err (local_err,"%s" , err_prefix); - } }static void vtd_pasid_cache_sync (IntelIOMMUState *s,VTDPASIDCacheInfo *pc_info)
hw/i386/intel_iommu_accel.c +66 -65
226 lines not on this page · raw message
hw/i386/intel_iommu_accel.h +1 -1
@@ -16,6 +16,7 @@ typedef struct VTDAccelPASIDCacheEntry {VTDHostIOMMUDevice *vtd_hiod;VTDPASIDEntry pasid_entry;uint32_t pasid; +uint32_t fs_hwpt_id;QLIST_ENTRY (VTDAccelPASIDCacheEntry) next; } VTDAccelPASIDCacheEntry;
@@ -23,7 +24,6 @@ typedef struct VTDAccelPASIDCacheEntry {bool vtd_check_hiod_accel (IntelIOMMUState *s,VTDHostIOMMUDevice *vtd_hiod,Error **errp);VTDHostIOMMUDevice *vtd_find_hiod_iommufd (VTDAddressSpace *as); -bool vtd_propagate_guest_pasid (VTDAddressSpace *vtd_as,Error **errp);void vtd_flush_host_piotlb_all_locked (IntelIOMMUState *s,uint16_t domain_id,uint32_t pasid,hwaddr addr,uint64_t npages,bool ih);
include/hw/i386/intel_iommu.h +0 -2
@@ -154,8 +154,6 @@ struct VTDAddressSpace {* with the guest IOMMU pgtables for a device. */ IOVATree *iova_tree; - -uint32_t fs_hwpt_id; };struct VTDIOTLBEntry {
Signature · 1 line
MST
[PULL 071/106] net/vhost-vdpa: enable vqs before DRIVER_OK if no cvq
In reply to Michael S. TsirkinFrom: Eugenio Pérez <[email protected]>
VDUSE do not forward the enable message to the userland device at the moment, leaving the dataplane disabled. As there is no functional difference if the device have no CVQ, enable them before DRIVER_OK in that case.
For devices with a control vq, keep the enabling of the dataplane after CVQ so QEMU can restore the device configuration.
Message-Id: <[email protected]>
--- net/vhost-vdpa.c | 30 ++++++++++-------------------- 1 file changed, 10 insertions(+), 20 deletions(-)
net/vhost-vdpa.c +10 -20
@@ -396,6 +396,7 @@ static int vhost_vdpa_net_data_start(NetClientState *nc) {VhostVDPAState *s =DO_UPCAST (VhostVDPAState, nc, nc);struct vhost_vdpa *v = &s->vhost_vdpa; +bool has_cvq = v->dev->vq_index_end %2 ;assert (nc->info->type ==NET_CLIENT_DRIVER_VHOST_VDPA );
@@ -405,6 +406,15 @@ static int vhost_vdpa_net_data_start(NetClientState *nc) v->shadow_vqs_enabled = false; } +if (!has_cvq) { +for (int i =0 ; i < v->dev->nvqs; ++i) { +int ret =vhost_vdpa_set_vring_ready (v, i + v->dev->vq_index); +if (ret <0 ) { +return ret; + } + } + } +if (v->index ==0 ) { v->shared->shadow_data = v->shadow_vqs_enabled;vhost_vdpa_net_data_start_first (s);
@@ -414,25 +424,6 @@ static int vhost_vdpa_net_data_start(NetClientState *nc)return 0 ; } -static int vhost_vdpa_net_data_load (NetClientState *nc) -{ -VhostVDPAState *s =DO_UPCAST (VhostVDPAState, nc, nc); -struct vhost_vdpa *v = &s->vhost_vdpa; -bool has_cvq = v->dev->vq_index_end %2 ; - -if (has_cvq) { -return 0 ; - } - -for (int i =0 ; i < v->dev->nvqs; ++i) { -int ret =vhost_vdpa_set_vring_ready (v, i + v->dev->vq_index); -if (ret <0 ) { -return ret; - } - } -return 0 ; -} -static void vhost_vdpa_net_client_stop (NetClientState *nc) {VhostVDPAState *s =DO_UPCAST (VhostVDPAState, nc, nc);
@@ -449,7 +440,6 @@ static NetClientInfo net_vhost_vdpa_info = { .size = sizeof(VhostVDPAState), .receive = vhost_vdpa_receive, .start = vhost_vdpa_net_data_start, - .load = vhost_vdpa_net_data_load, .stop = vhost_vdpa_net_client_stop, .cleanup = vhost_vdpa_cleanup, .has_vnet_hdr = vhost_vdpa_has_vnet_hdr,
Signature · 1 line
MST
[PULL 098/106] vhost-user.rst: fix typo
In reply to Michael S. TsirkinFrom: Alexandr Moshkov <[email protected]>
Message-Id: <[email protected]>
--- docs/interop/vhost-user.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
docs/interop/vhost-user.rst +1 -1
@@ -1329,7 +1329,7 @@ Front-end message types How to suspend an in-flight request depends on the implementation of the back-end but it typically can be done by aborting or cancelling the underlying I/O request. The ``VHOST_USER_PROTOCOL_F_GET_VRING_BASE_INFLIGHT`` - protocol feature must only be neogotiated if + protocol feature must only be negotiated if ``VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD`` is also negotiated. ``VHOST_USER_SET_VRING_KICK``
Signature · 1 line
MST
[PULL 016/106] intel_iommu_accel: Handle PASID entry addition for pc_inv_dsc request
In reply to Michael S. TsirkinFrom: Zhenzhong Duan <[email protected]>
Structure VTDAddressSpace includes some elements suitable for emulated device and passthrough device without PASID, e.g., address space, different memory regions, etc, it is also protected by vtd iommu lock, all these are useless and become a burden for passthrough device with PASID.
When there are lots of PASIDs used in one device, the AS and MRs are all registered to memory core and impact the whole system performance.
So instead of using VTDAddressSpace to cache pasid entry for each pasid of a passthrough device, we define a light weight structure VTDAccelPASIDCacheEntry with only necessary elements for each pasid. We will use this struct as a parameter to conduct binding/unbinding to nested hwpt and to record the current bound nested hwpt. It's also designed to support IOMMU_NO_PASID.
VTDAccelPASIDCacheEntry is designed to only be used in intel_iommu_accel.c, similarly VTDPASIDCacheEntry should only be used in hw/i386/intel_iommu.c
When guest creates new PASID entries, QEMU will capture the pc_inv_dsc (pasid cache invalidation) request, walk through each pasid in each passthrough device for valid pasid entries, create a new VTDAccelPASIDCacheEntry if not existing yet.
IOMMU_NO_PASID of passthrough device still need to register MRs in case guest does not operate in scalable mode. So for IOMMU_NO_PASID, we have both VTDPASIDCacheEntry and VTDAccelPASIDCacheEntry.
Message-Id: <[email protected]>
--- hw/i386/intel_iommu.c | 3 + hw/i386/intel_iommu_accel.c | 156 +++++++++++++++++++++++++++++++++ hw/i386/intel_iommu_accel.h | 13 +++ hw/i386/intel_iommu_internal.h | 8 ++ 4 files changed, 180 insertions(+)
hw/i386/intel_iommu.c +3 -0
@@ -3181,6 +3181,8 @@ static void vtd_pasid_cache_sync(IntelIOMMUState *s, VTDPASIDCacheInfo *pc_info)g_hash_table_foreach (s->vtd_address_spaces, vtd_pasid_cache_sync_locked, pc_info);vtd_iommu_unlock (s); + +vtd_accel_pasid_cache_sync (s, pc_info); }static void vtd_replay_pasid_bindings_all (IntelIOMMUState *s)
@@ -4751,6 +4753,7 @@ static bool vtd_dev_set_iommu_device(PCIBus *bus, void *opaque, int devfn, vtd_hiod->devfn = (uint8_t )devfn; vtd_hiod->iommu_state = s; vtd_hiod->hiod = hiod; +QLIST_INIT (&vtd_hiod->pasid_cache_list);if (!vtd_check_hiod (s, vtd_hiod, errp)) {g_free (vtd_hiod);
hw/i386/intel_iommu_accel.c +156 -0
162 lines not on this page · raw message
hw/i386/intel_iommu_accel.h +13 -0
@@ -12,6 +12,13 @@#define HW_I386_INTEL_IOMMU_ACCEL_H #include CONFIG_DEVICES +typedef struct VTDAccelPASIDCacheEntry { +VTDHostIOMMUDevice *vtd_hiod; +VTDPASIDEntry pasid_entry; +uint32_t pasid; +QLIST_ENTRY (VTDAccelPASIDCacheEntry) next; +}VTDAccelPASIDCacheEntry ; +#ifdef CONFIG_VTD_ACCEL bool vtd_check_hiod_accel (IntelIOMMUState *s,VTDHostIOMMUDevice *vtd_hiod,Error **errp);
@@ -20,6 +27,7 @@ bool vtd_propagate_guest_pasid(VTDAddressSpace *vtd_as, Error **errp);void vtd_flush_host_piotlb_all_locked (IntelIOMMUState *s,uint16_t domain_id,uint32_t pasid,hwaddr addr,uint64_t npages,bool ih); +void vtd_accel_pasid_cache_sync (IntelIOMMUState *s,VTDPASIDCacheInfo *pc_info);void vtd_iommu_ops_update_accel (PCIIOMMUOps *ops);#else static inline bool vtd_check_hiod_accel(IntelIOMMUState *s,
@@ -49,6 +57,11 @@ static inline void vtd_flush_host_piotlb_all_locked(IntelIOMMUState *s, { } +static inline void vtd_accel_pasid_cache_sync (IntelIOMMUState *s, +VTDPASIDCacheInfo *pc_info) +{ +} +static inline void vtd_iommu_ops_update_accel (PCIIOMMUOps *ops) { }
hw/i386/intel_iommu_internal.h +8 -0
@@ -615,6 +615,7 @@ typedef struct VTDRootEntry VTDRootEntry;#define VTD_CTX_ENTRY_LEGACY_SIZE 16#define VTD_CTX_ENTRY_SCALABLE_SIZE 32 +#define VTD_SM_CONTEXT_ENTRY_PDTS (x) extract64((x)->val[0], 9, 3)#define VTD_SM_CONTEXT_ENTRY_RSVD_VAL0 (aw) (0x1e0ULL | ~VTD_HAW_MASK(aw))#define VTD_SM_CONTEXT_ENTRY_RSVD_VAL1 0xffffffffffe00000ULL#define VTD_SM_CONTEXT_ENTRY_PRE 0x10ULL
@@ -645,6 +646,7 @@ typedef struct VTDPIOTLBInvInfo {#define VTD_PASID_DIR_BITS_MASK (0x3fffULL)#define VTD_PASID_DIR_INDEX (pasid) (((pasid) >> 6) & VTD_PASID_DIR_BITS_MASK)#define VTD_PASID_DIR_FPD (1ULL << 1)/* Fault Processing Disable */ +#define VTD_PASID_TABLE_ENTRY_NUM (1ULL << 6)#define VTD_PASID_TABLE_BITS_MASK (0x3fULL)#define VTD_PASID_TABLE_INDEX (pasid) ((pasid) & VTD_PASID_TABLE_BITS_MASK)#define VTD_PASID_ENTRY_FPD (1ULL << 1)/* Fault Processing Disable */
@@ -710,6 +712,7 @@ typedef struct VTDHostIOMMUDevice {PCIBus *bus;uint8_t devfn;HostIOMMUDevice *hiod; + QLIST_HEAD(, VTDAccelPASIDCacheEntry) pasid_cache_list; } VTDHostIOMMUDevice;/*
@@ -767,6 +770,11 @@ static inline int vtd_pasid_entry_compare(VTDPASIDEntry *p1, VTDPASIDEntry *p2)return memcmp (p1, p2,sizeof (*p1)); } +static inline uint32_t vtd_sm_ce_get_pdt_entry_num (VTDContextEntry *ce) +{ +return 1U << (VTD_SM_CONTEXT_ENTRY_PDTS (ce) +7 ); +} +int vtd_get_pdire_from_pdir_table (dma_addr_t pasid_dir_base,uint32_t pasid,VTDPASIDDirEntry *pdire); int vtd_get_pe_in_pasid_leaf_table(IntelIOMMUState *s, uint32_t pasid,
Signature · 1 line
MST
Re: [PULL 016/106] intel_iommu_accel: Handle PASID entry addition for pc_inv_dsc request
Hi,
Quoted 36 lines · Michael S. Tsirkin
From: Zhenzhong Duan <[email protected]>
Structure VTDAddressSpace includes some elements suitable for emulated device and passthrough device without PASID, e.g., address space, different memory regions, etc, it is also protected by vtd iommu lock, all these are useless and become a burden for passthrough device with PASID.
When there are lots of PASIDs used in one device, the AS and MRs are all registered to memory core and impact the whole system performance.
So instead of using VTDAddressSpace to cache pasid entry for each pasid of a passthrough device, we define a light weight structure VTDAccelPASIDCacheEntry with only necessary elements for each pasid. We will use this struct as a parameter to conduct binding/unbinding to nested hwpt and to record the current bound nested hwpt. It's also designed to support
IOMMU_NO_PASID.VTDAccelPASIDCacheEntry is designed to only be used in
intel_iommu_accel.c, similarly VTDPASIDCacheEntry should only be used inhw/i386/intel_iommu.cWhen guest creates new PASID entries, QEMU will capture the
pc_inv_dsc(pasid cache invalidation) request, walk through each pasid in each passthrough device for valid pasid entries, create a new VTDAccelPASIDCacheEntry if not existing yet.
IOMMU_NO_PASIDof passthrough device still need to register MRs in case guest does not operate in scalable mode. So forIOMMU_NO_PASID, we have both VTDPASIDCacheEntry and VTDAccelPASIDCacheEntry.Co-developed-by Yi Liu <[email protected]>Signed-off-by Yi Liu <[email protected]>Signed-off-by Zhenzhong Duan <[email protected]>Tested-by Xudong Hao <[email protected]>Reviewed-by Michael S. Tsirkin <[email protected]>Signed-off-by Michael S. Tsirkin <[email protected]>
Quoted 7 lines
Message-Id: <[email protected]>
--- hw/i386/intel_iommu.c | 3 + hw/i386/intel_iommu_accel.c | 156 +++++++++++++++++++++++++++++++++ hw/i386/intel_iommu_accel.h | 13 +++ hw/i386/intel_iommu_internal.h | 8 ++ 4 files changed, 180 insertions(+)
Michael, please setup scripts/git.orderfile ;)
Quoted 5 lines
hw/i386/intel_iommu_accel.h +0
-0
hw/i386/intel_iommu_accel.h line 20
Quoted 9 lines
hw/i386/intel_iommu_accel.h +6
-0@@ -12,6 +12,13 @@#define HW_I386_INTEL_IOMMU_ACCEL_H #include CONFIG_DEVICES +typedef struct VTDAccelPASIDCacheEntry { +VTDHostIOMMUDevice *vtd_hiod; +VTDPASIDEntry pasid_entry; +uint32_t pasid; +QLIST_ENTRY (VTDAccelPASIDCacheEntry) next; +}VTDAccelPASIDCacheEntry ;
Zhenzhong, this structure should be declared ...
hw/i386/intel_iommu_accel.h line 22
Quoted 1 line
hw/i386/intel_iommu_accel.h +0
-0#ifdef CONFIG_VTD_ACCEL
... after this guard.
Quoted 22 lines
hw/i386/intel_iommu_accel.h +6
-0bool vtd_check_hiod_accel (IntelIOMMUState *s,VTDHostIOMMUDevice *vtd_hiod,Error **errp);@@ -20,6 +27,7 @@ bool vtd_propagate_guest_pasid(VTDAddressSpace *vtd_as, Error **errp);void vtd_flush_host_piotlb_all_locked (IntelIOMMUState *s,uint16_t domain_id,uint32_t pasid,hwaddr addr,uint64_t npages,bool ih); +void vtd_accel_pasid_cache_sync (IntelIOMMUState *s,VTDPASIDCacheInfo *pc_info);void vtd_iommu_ops_update_accel (PCIIOMMUOps *ops);#else static inline bool vtd_check_hiod_accel(IntelIOMMUState *s,@@ -49,6 +57,11 @@ static inline void vtd_flush_host_piotlb_all_locked(IntelIOMMUState *s, { } +static inline void vtd_accel_pasid_cache_sync (IntelIOMMUState *s, +VTDPASIDCacheInfo *pc_info) +{ +} +static inline void vtd_iommu_ops_update_accel (PCIIOMMUOps *ops) { }
RE: [PULL 016/106] intel_iommu_accel: Handle PASID entry addition for pc_inv_dsc request
Hi Philippe,
Quoted 9 lines
hw/i386/intel_iommu_accel.h line 20
Quoted 6 lines
hw/i386/intel_iommu_accel.h +6
-0+typedef struct VTDAccelPASIDCacheEntry { +VTDHostIOMMUDevice *vtd_hiod; +VTDPASIDEntry pasid_entry; +uint32_t pasid; +QLIST_ENTRY (VTDAccelPASIDCacheEntry) next; +}VTDAccelPASIDCacheEntry ;Zhenzhong, this structure should be declared ...
Quoted 3 lines
Quoted 1 line
#ifdef CONFIG_VTD_ACCEL... after this guard.
Indeed. It doesn’t impact build process, build pass with or without fix. I can send a fix together with PRQ v3 series if you will not send it.
Just curious, how do you catch this?:)
Thanks
Zhenzhong
Re: [PULL 016/106] intel_iommu_accel: Handle PASID entry addition for pc_inv_dsc request
Quoted 11 lines · Zhenzhong
Hi Philippe,
Quoted 9 lines
hw/i386/intel_iommu_accel.h line 20
Quoted 6 lines
hw/i386/intel_iommu_accel.h +6
-0+typedef struct VTDAccelPASIDCacheEntry { +VTDHostIOMMUDevice *vtd_hiod; +VTDPASIDEntry pasid_entry; +uint32_t pasid; +QLIST_ENTRY (VTDAccelPASIDCacheEntry) next; +}VTDAccelPASIDCacheEntry ;Zhenzhong, this structure should be declared ...
Quoted 5 lines
Quoted 3 lines
Quoted 1 line
#ifdef CONFIG_VTD_ACCEL... after this guard.
Indeed. It doesn’t impact build process, build pass with or without fix.
I didn't complain about build failure in the main repository ;)
Quoted 3 lines
I can send a fix together with PRQ v3 series if you will not send it.
Just curious, how do you catch this?:)
Rebasing this patch:
https://lore.kernel.org/qemu-devel/[email protected]/
[PULL 027/106] vhost-user: rework enabling vrings
In reply to Michael S. TsirkinFrom: Vladimir Sementsov-Ogievskiy <[email protected]>
We call the handler almost the same way in three places:
- cryptodev-vhost.c
- vhost_net.c
- vhost.c
The only difference, is that in vhost.c we don't try to call the handler for old vhost-user (when VHOST_USER_F_PROTOCOL_FEATURES is not supported).
cryptodev-vhost and vhost_net code will just fail in this case. Probably they were developed only for newer vhost-user. Anyway, it doesn't seem correct to rely on this error path, if these devices want to check, that they don't communicate to old vhost-user protocol, they should do that earlier.
Let's create the common helper, to call .vhost_set_vring_enable and use in all three places. For vhost-user let's just always skip enable/disable if it's unsupported.
Message-Id: <[email protected]>
--- backends/cryptodev-vhost.c | 8 +------- hw/net/vhost_net.c | 7 +------ hw/virtio/vhost-user.c | 7 ++++++- hw/virtio/vhost.c | 21 --------------------- include/hw/virtio/vhost.h | 9 +++++++++ 5 files changed, 17 insertions(+), 35 deletions(-)
backends/cryptodev-vhost.c +1 -7
@@ -152,7 +152,6 @@ vhost_set_vring_enable(CryptoDevBackendClient *cc, {CryptoDevBackendVhost *crypto =cryptodev_get_vhost (cc, b, queue); -const VhostOps *vhost_ops; cc->vring_enable = enable;
@@ -160,12 +159,7 @@ vhost_set_vring_enable(CryptoDevBackendClient *cc,return 0 ; } - vhost_ops = crypto->dev.vhost_ops; -if (vhost_ops->vhost_set_vring_enable) { -return vhost_ops->vhost_set_vring_enable (&crypto->dev, enable); - } - -return 0 ; +return vhost_dev_set_vring_enable (&crypto->dev, enable); }int cryptodev_vhost_start (VirtIODevice *dev,int total_queues)
hw/net/vhost_net.c +1 -6
@@ -587,7 +587,6 @@ VHostNetState *get_vhost_net(NetClientState *nc)int vhost_net_set_vring_enable (NetClientState *nc,int enable) {VHostNetState *net =get_vhost_net (nc); -const VhostOps *vhost_ops = net->dev.vhost_ops;/* * vhost-vdpa network devices need to enable dataplane virtqueues after
@@ -601,11 +600,7 @@ int vhost_net_set_vring_enable(NetClientState *nc, int enable) nc->vring_enable = enable; -if (vhost_ops && vhost_ops->vhost_set_vring_enable) { -return vhost_ops->vhost_set_vring_enable (&net->dev, enable); - } - -return 0 ; +return vhost_dev_set_vring_enable (&net->dev, enable); }int vhost_net_set_mtu (struct vhost_net *net,uint16_t mtu)
hw/virtio/vhost-user.c +6 -1
@@ -1230,7 +1230,12 @@ 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 -EINVAL ; +/* +* For vhost-user devices, if VHOST_USER_F_PROTOCOL_FEATURES has not +* been negotiated, the rings start directly in the enabled state, +* and can't be disabled. +*/ +return 0 ; }for (i =0 ; i < dev->nvqs; ++i) {
hw/virtio/vhost.c +0 -21
@@ -2078,27 +2078,6 @@ 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. *
include/hw/virtio/vhost.h +9 -0
@@ -215,6 +215,15 @@ static inline bool vhost_dev_is_started(struct vhost_dev *hdev)return hdev->started; } +static inline int vhost_dev_set_vring_enable (struct vhost_dev *hdev,int enable) +{ +if (!hdev->vhost_ops->vhost_set_vring_enable) { +return 0 ; + } + +return hdev->vhost_ops->vhost_set_vring_enable (hdev, enable); +} +/** * vhost_dev_start() - start the vhost device * @hdev: common vhost_dev structure
Signature · 1 line
MST
[PULL 060/106] libvduse: fix buffer overflow in vduse_queue_read_indirect_desc()
In reply to Michael S. TsirkinFrom: Stefano Garzarella <[email protected]>
vduse_queue_read_indirect_desc() copies an indirect descriptor table into a buffer in chunks when the table crosses a memory region boundary. The destination is a struct vring_desc pointer but is advanced by a byte count, so each increment moves the pointer by read_len elements instead of read_len bytes, writing beyond the buffer.
Use a char pointer for the destination so that the arithmetic advances correctly.
While at it, change the source from a struct vring_desc pointer to a void pointer: when the table is split across regions, iova_to_va() can return a pointer into the middle of a descriptor, so casting it to a struct vring_desc pointer is wrong. The pointer is only used as a memcpy() source, so a void pointer is fine.
Message-Id: <[email protected]>
--- subprojects/libvduse/libvduse.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
subprojects/libvduse/libvduse.c +4 -3
@@ -465,8 +465,9 @@ static int vduse_queue_read_indirect_desc(VduseDev *dev, struct vring_desc *desc, uint64_t addr, size_t len) { -struct vring_desc *ori_desc; +char *dst_desc = (char *)desc;uint64_t read_len; +void *ori_desc;if (len > (VIRTQUEUE_MAX_SIZE *sizeof (struct vring_desc ))) {return -1 ;
@@ -483,10 +484,10 @@ vduse_queue_read_indirect_desc(VduseDev *dev, struct vring_desc *desc,return -1 ; } -memcpy (desc, ori_desc, read_len); +memcpy (dst_desc, ori_desc, read_len); len -= read_len; addr += read_len; - desc += read_len; + dst_desc += read_len; }return 0 ;
Signature · 1 line
MST
[PULL 068/106] hw/pci: Replace assert with bounds check and return
In reply to Michael S. TsirkinFrom: Aditya Gupta <[email protected]>
As reported in https://gitlab.com/qemu-project/qemu/-/work_items/3334,
callers of 'pci_host_config_{read,write}_common' can pass length as 8, causing an assert failure
The original issue with pnv_phb3 triggering the assert was fixed in a previous commit
Instead of asserting on invalid length, check if the length is valid (<=4), otherwise return (with the failure error code in read)
Message-Id: <[email protected]>
--- hw/pci/pci_host.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-)
hw/pci/pci_host.c +12 -2
@@ -81,7 +81,12 @@ void pci_host_config_write_common(PCIDevice *pci_dev, uint32_t addr,return ; } -assert (len <=4 ); +if (len >4 ) { +PCI_DPRINTF ("%s: invalid length access: addr " HWADDR_FMT_plx" \ +len %d val %" PRIx32"\n" , __func__, addr, len, val); +return ; + } +/* non-zero functions are only exposed when function 0 is present, * allowing direct removal of unexposed functions. */
@@ -106,7 +111,12 @@ uint32_t pci_host_config_read_common(PCIDevice *pci_dev, uint32_t addr,return ~0x0 ; } -assert (len <=4 ); +if (len >4 ) { +PCI_DPRINTF ("%s: invalid length access: addr " HWADDR_FMT_plx" \ +len %d val %" PRIx32"\n" , __func__, addr, len, val); +return ~0x0 ; + } +/* non-zero functions are only exposed when function 0 is present, * allowing direct removal of unexposed functions. */
Signature · 1 line
MST
[PULL 057/106] vhost: add .vhost_phys_iotlb_msg() handler
In reply to Michael S. TsirkinFrom: Vladimir Sementsov-Ogievskiy <[email protected]>
Allow backends to chose, which addr to put into vhost_iotlb_msg:
user or physical. To be used in further commit.
Based-on: <[email protected]>
Message-Id: <[email protected]>
--- hw/virtio/vhost.c | 11 ++++++++--- include/hw/virtio/vhost-backend.h | 3 +++ 2 files changed, 11 insertions(+), 3 deletions(-)
hw/virtio/vhost.c +8 -3
@@ -920,14 +920,18 @@ static void vhost_region_addnop(MemoryListener *listener, }static int vhost_update_device_iotlb (struct vhost_dev *dev, -uint64_t iova,uint64_t uaddr, +uint64_t iova, +uint64_t paddr, +uint64_t uaddr,uint64_t len,IOMMUAccessFlags perm) { +bool phys = dev->vhost_ops->vhost_phys_iotlb_msg && + dev->vhost_ops->vhost_phys_iotlb_msg (dev);struct vhost_iotlb_msg imsg; imsg.iova = iova; - imsg.uaddr = uaddr; + imsg.uaddr = phys ? paddr : uaddr; imsg.size = len; imsg.type =VHOST_IOTLB_UPDATE ;
@@ -1385,7 +1389,8 @@ int vhost_device_iotlb_miss(struct vhost_dev *dev, uint64_t iova, int write) len =MIN (iotlb.addr_mask +1 , len); iova = iova & ~iotlb.addr_mask; - ret =vhost_update_device_iotlb (dev, iova, uaddr, len, iotlb.perm); + ret =vhost_update_device_iotlb (dev, iova, iotlb.translated_addr, uaddr, + len, iotlb.perm);if (ret) {trace_vhost_iotlb_miss (dev,4 );error_report ("Fail to update device iotlb" );
include/hw/virtio/vhost-backend.h +3 -0
@@ -143,6 +143,8 @@ typedef int (*vhost_dev_start_op)(struct vhost_dev *dev, bool started);typedef bool (*vhost_phys_vring_addr_op )(struct vhost_dev *dev); +typedef bool (*vhost_phys_iotlb_msg_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);
@@ -210,6 +212,7 @@ typedef struct VhostOps {vhost_set_inflight_fd_op vhost_set_inflight_fd;vhost_dev_start_op vhost_dev_start;vhost_phys_vring_addr_op vhost_phys_vring_addr; +vhost_phys_iotlb_msg_op vhost_phys_iotlb_msg;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;
Signature · 1 line
MST
[PULL 072/106] virtio: Allow to fill a whole virtqueue in order
In reply to Michael S. TsirkinFrom: Eugenio Pérez <[email protected]>
As the while steps < max_steps is already one less than the vq size, the right maximum max_steps variable is queue length, not the maximum possible remainder of % vq->vring.num.
Message-Id: <[email protected]>
--- hw/virtio/virtio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
hw/virtio/virtio.c +1 -1
@@ -986,7 +986,7 @@ static void virtqueue_ordered_fill(VirtQueue *vq, const VirtQueueElement *elem,* We shouldn't need to increase 'i' by more than or equal to * the distance between used_idx and last_avail_idx (max_steps). */ - max_steps = (vq->last_avail_idx - vq->used_idx) % vq->vring.num; + max_steps =MIN (vq->last_avail_idx - vq->used_idx, vq->vring.num);/* Search for element in vq->used_elems */ while (steps < max_steps) {
Signature · 1 line
MST
[PULL 054/106] qapi: remove user addresses from x-query-virtio-vhost-queue-status
In reply to Michael S. TsirkinFrom: Vladimir Sementsov-Ogievskiy <[email protected]>
Semantics of these (actually, internal) fields is not simple, they may contain either virtual or physical addresses. We are going to change this to simplify the logic. Keeping this logic only for unstable info command seems too much. Changing semantics of info fields doesn't seem to make real sense too. So, let's just drop them. We can dot it, as command is experimental.
Based-on: <[email protected]>
Message-Id: <[email protected]>
--- hw/virtio/virtio-hmp-cmds.c | 3 --- hw/virtio/virtio-qmp.c | 3 --- qapi/virtio.json | 15 --------------- 3 files changed, 21 deletions(-)
hw/virtio/virtio-hmp-cmds.c +0 -3
@@ -203,15 +203,12 @@ void hmp_vhost_queue_status(Monitor *mon, const QDict *qdict)monitor_printf (mon," call: %" PRId64"\n" , s->call);monitor_printf (mon," VRing:\n" );monitor_printf (mon," num: %" PRId64"\n" , s->num); -monitor_printf (mon," desc: 0x%016" PRIx64"\n" , s->desc);monitor_printf (mon," desc_phys: 0x%016" PRIx64"\n" , s->desc_phys);monitor_printf (mon," desc_size: %" PRId32"\n" , s->desc_size); -monitor_printf (mon," avail: 0x%016" PRIx64"\n" , s->avail);monitor_printf (mon," avail_phys: 0x%016" PRIx64"\n" , s->avail_phys);monitor_printf (mon," avail_size: %" PRId32"\n" , s->avail_size); -monitor_printf (mon," used: 0x%016" PRIx64"\n" , s->used);monitor_printf (mon," used_phys: 0x%016" PRIx64"\n" , s->used_phys);monitor_printf (mon," used_size: %" PRId32"\n" , s->used_size);
hw/virtio/virtio-qmp.c +0 -3
@@ -794,9 +794,6 @@ VirtVhostQueueStatus *qmp_x_query_virtio_vhost_queue_status(const char *path, status->name =g_strdup (vdev->name); status->kick = hdev->vqs[queue].kick; status->call = hdev->vqs[queue].call; - status->desc = (uintptr_t )hdev->vqs[queue].desc; - status->avail = (uintptr_t )hdev->vqs[queue].avail; - status->used = (uintptr_t )hdev->vqs[queue].used; status->num = hdev->vqs[queue].num; status->desc_phys = hdev->vqs[queue].desc_phys; status->desc_size = hdev->vqs[queue].desc_size;
qapi/virtio.json +0 -15
@@ -650,12 +650,6 @@ # # @call: vhost_virtqueue call # -# @desc: vhost_virtqueue desc -# -# @avail: vhost_virtqueue avail -# -# @used: vhost_virtqueue used -# # @num: vhost_virtqueue num # # @desc-phys: vhost_virtqueue desc_phys (descriptor area physical
@@ -678,9 +672,6 @@ 'data': { 'name': 'str', 'kick': 'int', 'call': 'int', - 'desc': 'uint64', - 'avail': 'uint64', - 'used': 'uint64', 'num': 'int', 'desc-phys': 'uint64', 'desc-size': 'uint32',
@@ -720,12 +711,9 @@ # "avail-size": 2054, # "desc-size": 16384, # "used-size": 8198, -# "desc": 140141447430144, # "num": 1024, # "call": 0, -# "avail": 140141447446528, # "desc-phys": 5216108544, -# "used": 140141447448640, # "kick": 0 # } # }
@@ -744,12 +732,9 @@ # "avail-size": 262, # "desc-size": 2048, # "used-size": 1030, -# "desc": 140141413580800, # "num": 128, # "call": 0, -# "avail": 140141413582848, # "desc-phys": 5182259200, -# "used": 140141413583168, # "kick": 0 # } # }
Signature · 1 line
MST
[PULL 001/106] amd_iommu: restrict command buffer head/tail ranges to ring size
In reply to Michael S. TsirkinFrom: Paolo Bonzini <[email protected]>
The AMD IOMMU command buffer is a ring buffer of cmdbuf_len (a power of two) entries. Each entry is 16 bytes and the head pointer cycles through the set:
[0, 16, 32, ..., (cmdbuf_len - 1) * AMDVI_COMMAND_SIZE]
The tail pointer is written by the guest through the COMMAND_TAIL MMIO register (offset 0x2008); the while loop in amdvi_cmdbuf_run() only terminates when head == tail. If tail is set to a value higher than cmdbuf_len * 16, head will cycle through all the elements of the ring buffer indefinitely, without ever matching tail. Fix this by further masking tail (and head, for consistency) against the size of the ring buffer.
Message-Id: <[email protected]>
--- hw/i386/amd_iommu.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
hw/i386/amd_iommu.c +4 -2
@@ -1578,7 +1578,8 @@ static inline void amdvi_handle_devtab_write(AMDVIState *s)static inline void amdvi_handle_cmdhead_write (AMDVIState *s) { s->cmdbuf_head =amdvi_readq (s,AMDVI_MMIO_COMMAND_HEAD ) - &AMDVI_MMIO_CMDBUF_HEAD_MASK ; + &AMDVI_MMIO_CMDBUF_HEAD_MASK + & (s->cmdbuf_len *AMDVI_COMMAND_SIZE -1 );amdvi_cmdbuf_run (s); }
@@ -1594,7 +1595,8 @@ static inline void amdvi_handle_cmdbase_write(AMDVIState *s)static inline void amdvi_handle_cmdtail_write (AMDVIState *s) { s->cmdbuf_tail =amdvi_readq (s,AMDVI_MMIO_COMMAND_TAIL ) - &AMDVI_MMIO_CMDBUF_TAIL_MASK ; + &AMDVI_MMIO_CMDBUF_TAIL_MASK + & (s->cmdbuf_len *AMDVI_COMMAND_SIZE -1 );amdvi_cmdbuf_run (s); }
Signature · 1 line
MST
[PULL 081/106] amd_iommu: Generate XT interrupts when xt support is enabled
In reply to Michael S. TsirkinFrom: Sairaj Kodilkar <[email protected]>
When MMIO 0x18[IntCapXTEn]=1, interrupts originating from the IOMMU itself are sent based on the programming in XT IOMMU Interrupt Control Registers in MMIO 0x170-0x180 instead of the programming in the IOMMU's MSI capability registers. The guest programs these registers with appropriate vector and destination ID instead of writing to PCI MSI capability.
Current AMD vIOMMU is capable of generating interrupts only through PCI MSI capability and does not care about xt mode. Because of this AMD vIOMMU cannot generate event log interrupts when the guest has enabled xt mode.
Introduce a new flag "intcapxten" which is set when guest writes control register [IntCapXTEn] (bit 51) and use vector and destination field in the XT MMIO register (0x170) to support XT mode.
Message-Id: <[email protected]>
--- hw/i386/amd_iommu.c | 47 ++++++++++++++++++++++++++++++++++++++------ hw/i386/amd_iommu.h | 17 ++++++++++++++++ hw/i386/trace-events | 1 + 3 files changed, 59 insertions(+), 6 deletions(-)
hw/i386/amd_iommu.c +41 -6
@@ -192,18 +192,38 @@ static void amdvi_assign_andq(AMDVIState *s, hwaddr addr, uint64_t val)amdvi_writeq_raw (s, addr,amdvi_readq (s, addr) & val); } +static void amdvi_build_xt_msi_msg (AMDVIState *s,MSIMessage *msg) +{ +union mmio_xt_intr xt_reg; +struct X86IOMMUIrq irq; + + xt_reg.val =amdvi_readq (s,AMDVI_MMIO_XT_GEN_INTR ); + + irq.vector = xt_reg.vector; + irq.delivery_mode = xt_reg.delivery_mode; + irq.dest_mode = xt_reg.destination_mode; + irq.dest = (xt_reg.destination_hi <<24 ) | xt_reg.destination_lo; + irq.trigger_mode =0 ; + irq.redir_hint =0 ; + +x86_iommu_irq_to_msi_message (&irq, msg); +} +static void amdvi_generate_msi_interrupt (AMDVIState *s) {MSIMessage msg = {}; -MemTxAttrs attrs = { - .requester_id =pci_requester_id (&s->pci->dev) - }; -if (msi_enabled (&s->pci->dev)) { +if (s->intcapxten) { +trace_amdvi_generate_msi_interrupt ("XT GEN" ); +amdvi_build_xt_msi_msg (s, &msg); + }else if (msi_enabled (&s->pci->dev)) { +trace_amdvi_generate_msi_interrupt ("MSI" ); msg =msi_get_message (&s->pci->dev,0 ); -address_space_stl_le (&address_space_memory, msg.address, msg.data, - attrs,NULL ); + }else { +trace_amdvi_generate_msi_interrupt ("NO MSI" ); +return ; } +apic_get_class (NULL )->send_msi (&msg); }static uint32_t get_next_eventlog_entry (AMDVIState *s)
@@ -1538,6 +1558,7 @@ const char *amdvi_mmio_get_name(hwaddr addr)MMIO_REG_TO_STRING (AMDVI_MMIO_PPR_BASE );MMIO_REG_TO_STRING (AMDVI_MMIO_PPR_HEAD );MMIO_REG_TO_STRING (AMDVI_MMIO_PPR_TAIL ); +MMIO_REG_TO_STRING (AMDVI_MMIO_XT_GEN_INTR );#undef MMIO_REG_TO_STRINGdefault :return "UNHANDLED" ;
@@ -1581,6 +1602,15 @@ static void amdvi_handle_control_write(AMDVIState *s) s->ga_enabled = !!(control &AMDVI_MMIO_CONTROL_GAEN ); s->xten = !!(control &AMDVI_MMIO_CONTROL_XTEN ) && s->xtsup && s->ga_enabled; +/* +* IntCapXTEn controls whether IOMMU-originated interrupts are sent based +* on the information in XT IOMMU Interrupt Control Registers rather than +* the IOMMU’s MSI capability registers. Therefore it requires IOMMU +* x2APIC support capabilities (i.e. XTSup=1), but it is independent of +* whether a driver chooses to enable x2APIC mode for interrupt remapping +* (i.e. XTEn=1). +*/ + s->intcapxten = !!(control &AMDVI_MMIO_CONTROL_INTCAPXTEN ) && s->xtsup;/* update the flags depending on the control register */ if (s->cmdbuf_enabled) {
@@ -1790,6 +1820,9 @@ static void amdvi_mmio_write(void *opaque, hwaddr addr, uint64_t val,case AMDVI_MMIO_STATUS :amdvi_mmio_reg_write (s, size, val, addr);break ; +case AMDVI_MMIO_XT_GEN_INTR : +amdvi_mmio_reg_write (s, size, val, addr); +break ; } }
@@ -2440,6 +2473,7 @@ static void amdvi_init(AMDVIState *s) s->enabled = false; s->cmdbuf_enabled = false; s->xten = false; + s->intcapxten = false;/* reset MMIO */ memset (s->mmior,0 ,AMDVI_MMIO_SIZE );
@@ -2510,6 +2544,7 @@ static const VMStateDescription vmstate_xt = { .minimum_version_id = 1, .fields = (VMStateField []) {VMSTATE_BOOL (xten, AMDVIState), +VMSTATE_BOOL (intcapxten, AMDVIState),VMSTATE_END_OF_LIST () } };
hw/i386/amd_iommu.h +17 -0
@@ -53,6 +53,7 @@#define AMDVI_MMIO_EXCL_BASE 0x0020#define AMDVI_MMIO_EXCL_LIMIT 0x0028#define AMDVI_MMIO_EXT_FEATURES 0x0030 +#define AMDVI_MMIO_XT_GEN_INTR 0x0170#define AMDVI_MMIO_COMMAND_HEAD 0x2000#define AMDVI_MMIO_COMMAND_TAIL 0x2008#define AMDVI_MMIO_EVENT_HEAD 0x2010
@@ -103,6 +104,7 @@#define AMDVI_MMIO_CONTROL_CMDBUFLEN (1ULL << 12)#define AMDVI_MMIO_CONTROL_GAEN (1ULL << 17)#define AMDVI_MMIO_CONTROL_XTEN (1ULL << 50) +#define AMDVI_MMIO_CONTROL_INTCAPXTEN (1ULL << 51)/* MMIO status register bits */ #define AMDVI_MMIO_STATUS_CMDBUF_RUN (1 << 4)
@@ -338,6 +340,20 @@ struct irte_ga {union irte_ga_hi hi; }; +union mmio_xt_intr { +uint64_t val; +struct { +uint64_t rsvd_1:2 , + destination_mode:1 , + rsvd_2:5 , + destination_lo:24 , + vector:8 , + delivery_mode:1 , + rsvd_3:15 , + destination_hi:8 ; + }; +}; +#define TYPE_AMD_IOMMU_DEVICE "amd-iommu"OBJECT_DECLARE_SIMPLE_TYPE (AMDVIState,AMD_IOMMU_DEVICE )
@@ -416,6 +432,7 @@ struct AMDVIState {bool ga_enabled;bool xtsup;/* xtsup=on command line */ bool xten;/* guest controlled, x2apic mode enabled */ +bool intcapxten;/* guest controlled, IOMMU x2apic interrupts enabled */ /* DMA address translation */ bool dma_remap;
hw/i386/trace-events +1 -0
@@ -118,6 +118,7 @@ amdvi_ir_intctl(uint8_t val) "int_ctl 0x%"PRIx8 amdvi_ir_target_abort(const char *str) "%s" amdvi_ir_delivery_mode(const char *str) "%s" amdvi_ir_irte_ga_val(uint64_t hi, uint64_t lo) "hi 0x%"PRIx64" lo 0x%"PRIx64 +amdvi_generate_msi_interrupt(const char *str) "Mode: %s" # vmport.c vmport_register(unsigned char command, void *func, void *opaque) "command: 0x%02x func: %p opaque: %p"
Signature · 1 line
MST
A message that is not in the archive (sent off-list or not yet received): CAFEAcA8sZSNr5N8ri6SCok2aWLED9+OGvy0qA7A83SuwXg9xKA@mail.gmail.com
Re: [PULL 081/106] amd_iommu: Generate XT interrupts when xt support is enabled
Quoted 90 lines · Peter Maydell
Quoted 9 lines · Michael S. Tsirkin
From: Sairaj Kodilkar <[email protected]>
When MMIO 0x18[IntCapXTEn]=1, interrupts originating from the IOMMU itself are sent based on the programming in XT IOMMU Interrupt Control Registers in MMIO 0x170-0x180 instead of the programming in the IOMMU's MSI capability registers. The guest programs these registers with appropriate vector and destination ID instead of writing to PCI MSI capability.
Quoted 8 lines
Current AMD vIOMMU is capable of generating interrupts only through PCI MSI capability and does not care about xt mode. Because of this AMD vIOMMU cannot generate event log interrupts when the guest has enabled xt mode.
Introduce a new flag "intcapxten" which is set when guest writes control register [IntCapXTEn] (bit 51) and use vector and destination field in the XT MMIO register (
0x170) to support XT mode.Hi; Coverity points out a use of an uninitialized struct field here (CID 1660056):
hw/i386/amd_iommu.c static void amdvi_assign_andq(AMDVIState *s, hwaddr addr, uint64_t val) · line 198
Quoted 4 lines
hw/i386/amd_iommu.c +4
-0+static void amdvi_build_xt_msi_msg (AMDVIState *s,MSIMessage *msg) +{ +union mmio_xt_intr xt_reg; +struct X86IOMMUIrq irq;Here we declare irq, without a struct initializer...
hw/i386/amd_iommu.c static void amdvi_assign_andq(AMDVIState *s, hwaddr addr, uint64_t val) · line 207
Quoted 9 lines
hw/i386/amd_iommu.c +9
-0+ + xt_reg.val =amdvi_readq (s,AMDVI_MMIO_XT_GEN_INTR ); + + irq.vector = xt_reg.vector; + irq.delivery_mode = xt_reg.delivery_mode; + irq.dest_mode = xt_reg.destination_mode; + irq.dest = (xt_reg.destination_hi <<24 ) | xt_reg.destination_lo; + irq.trigger_mode =0 ; + irq.redir_hint =0 ;...and here we fill in some but not all of its fields...
Review
Quoted 2 lines
(quoted diff) +2
-0+ + x86_iommu_irq_to_msi_message(&irq, msg);...and here we call a function which (among other things) does this:
msg.__not_used = irq->msi_addr_last_bits;which will read the uninitialized
msi_addr_last_bitsfield.Bonus extra bug report:
hw/i386/amd_iommu.h +13
-0+union mmio_xt_intr { +uint64_t val; +struct { +uint64_t rsvd_1:2 , + destination_mode:1 , + rsvd_2:5 , + destination_lo:24 , + vector:8 , + delivery_mode:1 , + rsvd_3:15 , + destination_hi:8 ; + }; +};Please don't use bitfields like this -- this is not portable to big endian hosts. Use the
extract64()function instead, or the FIELD macros.I suggest something like (untested):
(at top level in a source file or header; the numbers are start-bit and length, check these as I may have made typos)
FIELD(XT_GEN_INTR, DEST_MODE, 2, 1)FIELD(XT_GEN_INTR, DEST_LO, 24, 8)FIELD(XT_GEN_INTR, VECTOR, 32, 8)FIELD(XT_GEN_INTR, DELIVERY_MODE, 33, 1)FIELD(XT_GEN_INTR, DEST_HI, 49, 8)and then in the function you can do:
uint64_t xtreg = amdvi_readq(s, AMDVI_MMIO_XT_GEN_INTR); X86IOMMUIrq irq = { .vector = FIELD_EX64(xtreg, XT_GEN_INTR, VECTOR), .delivery_mode = FIELD_EX64(xtreg, XT_GEN_INTR, DELIVERY_MODE), .dest_mode = FIELD_EX64(xtreg, XT_GEN_INTR, DEST_MODE), .dest = (FIELD_X64(xtreg, XT_GEN_INTR, DEST_HI) << 24) |
FIELD_EX64(xtreg, XT_GEN_INTR, DEST_LO),
};
Quoted 7 lines
which gives you a struct initializer and you can rely on the whole struct being initialized.
Quoted 1 line
+}
thanks
-- PMM
Indeed. Alejandro should we revert or fix up?
Signature · 1 line
MST
Re: [PULL 081/106] amd_iommu: Generate XT interrupts when xt support is enabled
Quoted 94 lines · Michael S. Tsirkin
Quoted 93 lines · Peter Maydell
Quoted 9 lines · Michael S. Tsirkin
From: Sairaj Kodilkar <[email protected]>
When MMIO 0x18[IntCapXTEn]=1, interrupts originating from the IOMMU itself are sent based on the programming in XT IOMMU Interrupt Control Registers in MMIO 0x170-0x180 instead of the programming in the IOMMU's MSI capability registers. The guest programs these registers with appropriate vector and destination ID instead of writing to PCI MSI capability.
Quoted 8 lines
Current AMD vIOMMU is capable of generating interrupts only through PCI MSI capability and does not care about xt mode. Because of this AMD vIOMMU cannot generate event log interrupts when the guest has enabled xt mode.
Introduce a new flag "intcapxten" which is set when guest writes control register [IntCapXTEn] (bit 51) and use vector and destination field in the XT MMIO register (
0x170) to support XT mode.Hi; Coverity points out a use of an uninitialized struct field here (CID 1660056):
hw/i386/amd_iommu.c static void amdvi_assign_andq(AMDVIState *s, hwaddr addr, uint64_t val) · line 198
Quoted 4 lines
hw/i386/amd_iommu.c +4
-0+static void amdvi_build_xt_msi_msg (AMDVIState *s,MSIMessage *msg) +{ +union mmio_xt_intr xt_reg; +struct X86IOMMUIrq irq;Here we declare irq, without a struct initializer...
hw/i386/amd_iommu.c static void amdvi_assign_andq(AMDVIState *s, hwaddr addr, uint64_t val) · line 207
Quoted 9 lines
hw/i386/amd_iommu.c +9
-0+ + xt_reg.val =amdvi_readq (s,AMDVI_MMIO_XT_GEN_INTR ); + + irq.vector = xt_reg.vector; + irq.delivery_mode = xt_reg.delivery_mode; + irq.dest_mode = xt_reg.destination_mode; + irq.dest = (xt_reg.destination_hi <<24 ) | xt_reg.destination_lo; + irq.trigger_mode =0 ; + irq.redir_hint =0 ;...and here we fill in some but not all of its fields...
Review
Quoted 2 lines
(quoted diff) +2
-0+ + x86_iommu_irq_to_msi_message(&irq, msg);...and here we call a function which (among other things) does this:
msg.__not_used = irq->msi_addr_last_bits;which will read the uninitialized
msi_addr_last_bitsfield.Bonus extra bug report:
hw/i386/amd_iommu.h +13
-0+union mmio_xt_intr { +uint64_t val; +struct { +uint64_t rsvd_1:2 , + destination_mode:1 , + rsvd_2:5 , + destination_lo:24 , + vector:8 , + delivery_mode:1 , + rsvd_3:15 , + destination_hi:8 ; + }; +};Please don't use bitfields like this -- this is not portable to big endian hosts. Use the
extract64()function instead, or the FIELD macros.I suggest something like (untested):
(at top level in a source file or header; the numbers are start-bit and length, check these as I may have made typos)
FIELD(XT_GEN_INTR, DEST_MODE, 2, 1)FIELD(XT_GEN_INTR, DEST_LO, 24, 8)FIELD(XT_GEN_INTR, VECTOR, 32, 8)FIELD(XT_GEN_INTR, DELIVERY_MODE, 33, 1)FIELD(XT_GEN_INTR, DEST_HI, 49, 8)and then in the function you can do:
uint64_t xtreg = amdvi_readq(s, AMDVI_MMIO_XT_GEN_INTR); X86IOMMUIrq irq = { .vector = FIELD_EX64(xtreg, XT_GEN_INTR, VECTOR), .delivery_mode = FIELD_EX64(xtreg, XT_GEN_INTR, DELIVERY_MODE), .dest_mode = FIELD_EX64(xtreg, XT_GEN_INTR, DEST_MODE), .dest = (FIELD_X64(xtreg, XT_GEN_INTR, DEST_HI) << 24) |
FIELD_EX64(xtreg, XT_GEN_INTR, DEST_LO),
};which gives you a struct initializer and you can rely on the whole struct being initialized.
Quoted 7 lines
Quoted 4 lines
Quoted 1 line
+}
thanks
-- PMMIndeed. Alejandro should we revert or fix up?
I think the uninitialized struct issue can be quickly fixed using a designated initializer, so that would directly address CID 1660056.
For the bitfield portability in big endian host problem, the changes are a bit more involved since there are existing definitions using the same pattern (dating back to 2018 when IR support was introduced). So to do it right it involves more changes than just the code touched by the current patch. It should be relatively straightforward though, so I will work on it and will send a patch extended Peter's suggestion to all the cases. If run into issues/time constraints, then by EOW I'll send a simple fix with the designated initialized approach to fix the coverity report, while I continue on the "bonus" case.
Does that work?
Alejandro
[PULL 046/106] vhost-user: make trace events more readable
In reply to Michael S. TsirkinFrom: Vladimir Sementsov-Ogievskiy <[email protected]>
Message-Id: <[email protected]>
--- hw/virtio/trace-events | 4 +-- hw/virtio/vhost-user.c | 63 ++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 63 insertions(+), 4 deletions(-)
hw/virtio/trace-events +2 -2
@@ -25,8 +25,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_user_read(uint32_t req, const char *req_name, uint32_t flags) "req:%d (%s) flags:0x%"PRIx32"" +vhost_user_write(uint32_t req, const char *req_name, uint32_t flags) "req:%d (%s) flags:0x%"PRIx32"" vhost_user_create_notifier(int idx, void *n) "idx:%d n:%p" # vhost-vdpa.c
hw/virtio/vhost-user.c +61 -2
81 lines not on this page · raw message
Signature · 1 line
MST
[PULL 037/106] vhost: make vhost_memory_unmap() null-safe
In reply to Michael S. TsirkinFrom: Vladimir Sementsov-Ogievskiy <[email protected]>
This helps to simplify failure paths of vhost_virtqueue_start() a lot. We also need to zero-out pointers on unmap, to not try to unmap invalid pointers.
Message-Id: <[email protected]>
--- hw/virtio/vhost.c | 41 +++++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 20 deletions(-)
hw/virtio/vhost.c +21 -20
@@ -473,14 +473,20 @@ static void *vhost_memory_map(struct vhost_dev *dev, hwaddr addr, } } -static void vhost_memory_unmap (struct vhost_dev *dev,void *buffer, +static void vhost_memory_unmap (struct vhost_dev *dev,void **buffer,hwaddr len,int is_write,hwaddr access_len) { +if (!*buffer) { +return ; + } +if (!vhost_dev_has_iommu (dev)) { -address_space_unmap (dev->vdev->dma_as, buffer, len, is_write, +address_space_unmap (dev->vdev->dma_as, *buffer, len, is_write, access_len); } + + *buffer =NULL ; } static int vhost_verify_ring_part_mapping(void *ring_hva,
@@ -1324,33 +1330,33 @@ int vhost_virtqueue_start(struct vhost_dev *dev, vq->desc =vhost_memory_map (dev, vq->desc_phys, l, false);if (!vq->desc) { r = -ENOMEM ; - goto fail_alloc_desc; + goto fail; } l = vq->avail_size; vq->avail =vhost_memory_map (dev, vq->avail_phys, l, false);if (!vq->avail) { r = -ENOMEM ; - goto fail_alloc_avail; + goto fail; } l = vq->used_size; vq->used =vhost_memory_map (dev, vq->used_phys, l, true);if (!vq->used) { r = -ENOMEM ; - goto fail_alloc_used; + goto fail; } r =vhost_virtqueue_set_addr (dev, vq, vhost_vq_index, dev->log_enabled);if (r <0 ) { - goto fail_alloc; + goto fail; } 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 (r,"vhost_set_vring_kick failed" ); - goto fail_kick; + goto fail; }/* Clear and discard previous events if any. */
@@ -1370,24 +1376,19 @@ int vhost_virtqueue_start(struct vhost_dev *dev, file.fd =-1 ; r = dev->vhost_ops->vhost_set_vring_call (dev, &file);if (r) { - goto fail_vector; + goto fail; } }return 0 ; -fail_vector: -fail_kick: -fail_alloc: -vhost_memory_unmap (dev, vq->used,virtio_queue_get_used_size (vdev, idx), +fail: +vhost_memory_unmap (dev, &vq->used,virtio_queue_get_used_size (vdev, idx),0 ,0 ); -fail_alloc_used: -vhost_memory_unmap (dev, vq->avail,virtio_queue_get_avail_size (vdev, idx), +vhost_memory_unmap (dev, &vq->avail,virtio_queue_get_avail_size (vdev, idx),0 ,0 ); -fail_alloc_avail: -vhost_memory_unmap (dev, vq->desc,virtio_queue_get_desc_size (vdev, idx), +vhost_memory_unmap (dev, &vq->desc,virtio_queue_get_desc_size (vdev, idx),0 ,0 ); -fail_alloc_desc:return r; }
@@ -1434,11 +1435,11 @@ static int do_vhost_virtqueue_stop(struct vhost_dev *dev, vhost_vq_index); } -vhost_memory_unmap (dev, vq->used,virtio_queue_get_used_size (vdev, idx), +vhost_memory_unmap (dev, &vq->used,virtio_queue_get_used_size (vdev, idx),1 ,virtio_queue_get_used_size (vdev, idx)); -vhost_memory_unmap (dev, vq->avail,virtio_queue_get_avail_size (vdev, idx), +vhost_memory_unmap (dev, &vq->avail,virtio_queue_get_avail_size (vdev, idx),0 ,virtio_queue_get_avail_size (vdev, idx)); -vhost_memory_unmap (dev, vq->desc,virtio_queue_get_desc_size (vdev, idx), +vhost_memory_unmap (dev, &vq->desc,virtio_queue_get_desc_size (vdev, idx),0 ,virtio_queue_get_desc_size (vdev, idx));return r; }
Signature · 1 line
MST
[PULL 082/106] standard-headers: Add virtio_rtc.h from Linux 7.0-rc1
In reply to Michael S. TsirkinFrom: Kuan-Wei Chiu <[email protected]>
Add virtio_rtc.h from the upstream Linux kernel using scripts/update-linux-headers.sh.
Source:
- Linux commit 6de23f81a5e08be8fbf5e8d7e9febc72a5b5f27f (v7.0-rc1)
- Author: Linus Torvalds <[email protected]>
- Date: Sun Feb 22 13:18:59 2026 -0800
Message-Id: <[email protected]>
--- include/standard-headers/linux/virtio_rtc.h | 237 ++++++++++++++++++++ 1 file changed, 237 insertions(+) create mode 100644 include/standard-headers/linux/virtio_rtc.h
include/standard-headers/linux/virtio_rtc.h new file +237 -0
@@ -0,0 +1,237 @@ +/* SPDX-License-Identifier: ((GPL-2.0+ WITH Linux-syscall-note) OR BSD-3-Clause) */ +/* +* Copyright (C) 2022-2024 OpenSynergy GmbH +* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved. +*/ + +#ifndef _LINUX_VIRTIO_RTC_H +#define _LINUX_VIRTIO_RTC_H + +#include "standard-headers/linux/types.h" + +/* alarm feature */ +#define VIRTIO_RTC_F_ALARM 0 + +/* read request message types */ + +#define VIRTIO_RTC_REQ_READ 0x0001 +#define VIRTIO_RTC_REQ_READ_CROSS 0x0002 + +/* control request message types */ + +#define VIRTIO_RTC_REQ_CFG 0x1000 +#define VIRTIO_RTC_REQ_CLOCK_CAP 0x1001 +#define VIRTIO_RTC_REQ_CROSS_CAP 0x1002 +#define VIRTIO_RTC_REQ_READ_ALARM 0x1003 +#define VIRTIO_RTC_REQ_SET_ALARM 0x1004 +#define VIRTIO_RTC_REQ_SET_ALARM_ENABLED 0x1005 + +/* alarmq message types */ + +#define VIRTIO_RTC_NOTIF_ALARM 0x2000 + +/* Message headers */ + +/** common request header */ +struct virtio_rtc_req_head { +uint16_t msg_type; +uint8_t reserved[6 ]; +}; + +/** common response header */ +struct virtio_rtc_resp_head { +#define VIRTIO_RTC_S_OK 0 +#define VIRTIO_RTC_S_EOPNOTSUPP 2 +#define VIRTIO_RTC_S_ENODEV 3 +#define VIRTIO_RTC_S_EINVAL 4 +#define VIRTIO_RTC_S_EIO 5 +uint8_t status; +uint8_t reserved[7 ]; +}; + +/** common notification header */ +struct virtio_rtc_notif_head { +uint16_t msg_type; +uint8_t reserved[6 ]; +}; + +/* read requests */ + +/* VIRTIO_RTC_REQ_READ message */ + +struct virtio_rtc_req_read { +struct virtio_rtc_req_head head; +uint16_t clock_id; +uint8_t reserved[6 ]; +}; + +struct virtio_rtc_resp_read { +struct virtio_rtc_resp_head head; +uint64_t clock_reading; +}; + +/* VIRTIO_RTC_REQ_READ_CROSS message */ + +struct virtio_rtc_req_read_cross { +struct virtio_rtc_req_head head; +uint16_t clock_id; +/* Arm Generic Timer Counter-timer Virtual Count Register (CNTVCT_EL0) */ +#define VIRTIO_RTC_COUNTER_ARM_VCT 0 +/* x86 Time-Stamp Counter */ +#define VIRTIO_RTC_COUNTER_X86_TSC 1 +/* Invalid */ +#define VIRTIO_RTC_COUNTER_INVALID 0xFF +uint8_t hw_counter; +uint8_t reserved[5 ]; +}; + +struct virtio_rtc_resp_read_cross { +struct virtio_rtc_resp_head head; +uint64_t clock_reading; +uint64_t counter_cycles; +}; + +/* control requests */ + +/* VIRTIO_RTC_REQ_CFG message */ + +struct virtio_rtc_req_cfg { +struct virtio_rtc_req_head head; +/* no request params */ +}; + +struct virtio_rtc_resp_cfg { +struct virtio_rtc_resp_head head; +/** # of clocks -> clock ids < num_clocks are valid */ +uint16_t num_clocks; +uint8_t reserved[6 ]; +}; + +/* VIRTIO_RTC_REQ_CLOCK_CAP message */ + +struct virtio_rtc_req_clock_cap { +struct virtio_rtc_req_head head; +uint16_t clock_id; +uint8_t reserved[6 ]; +}; + +struct virtio_rtc_resp_clock_cap { +struct virtio_rtc_resp_head head; +#define VIRTIO_RTC_CLOCK_UTC 0 +#define VIRTIO_RTC_CLOCK_TAI 1 +#define VIRTIO_RTC_CLOCK_MONOTONIC 2 +#define VIRTIO_RTC_CLOCK_UTC_SMEARED 3 +#define VIRTIO_RTC_CLOCK_UTC_MAYBE_SMEARED 4 +uint8_t type; +#define VIRTIO_RTC_SMEAR_UNSPECIFIED 0 +#define VIRTIO_RTC_SMEAR_NOON_LINEAR 1 +#define VIRTIO_RTC_SMEAR_UTC_SLS 2 +uint8_t leap_second_smearing; +#define VIRTIO_RTC_FLAG_ALARM_CAP (1 << 0) +uint8_t flags; +uint8_t reserved[5 ]; +}; + +/* VIRTIO_RTC_REQ_CROSS_CAP message */ + +struct virtio_rtc_req_cross_cap { +struct virtio_rtc_req_head head; +uint16_t clock_id; +uint8_t hw_counter; +uint8_t reserved[5 ]; +}; + +struct virtio_rtc_resp_cross_cap { +struct virtio_rtc_resp_head head; +#define VIRTIO_RTC_FLAG_CROSS_CAP (1 << 0) +uint8_t flags; +uint8_t reserved[7 ]; +}; + +/* VIRTIO_RTC_REQ_READ_ALARM message */ + +struct virtio_rtc_req_read_alarm { +struct virtio_rtc_req_head head; +uint16_t clock_id; +uint8_t reserved[6 ]; +}; + +struct virtio_rtc_resp_read_alarm { +struct virtio_rtc_resp_head head; +uint64_t alarm_time; +#define VIRTIO_RTC_FLAG_ALARM_ENABLED (1 << 0) +uint8_t flags; +uint8_t reserved[7 ]; +}; + +/* VIRTIO_RTC_REQ_SET_ALARM message */ + +struct virtio_rtc_req_set_alarm { +struct virtio_rtc_req_head head; +uint64_t alarm_time; +uint16_t clock_id; +/* flag VIRTIO_RTC_FLAG_ALARM_ENABLED */ +uint8_t flags; +uint8_t reserved[5 ]; +}; + +struct virtio_rtc_resp_set_alarm { +struct virtio_rtc_resp_head head; +/* no response params */ +}; + +/* VIRTIO_RTC_REQ_SET_ALARM_ENABLED message */ + +struct virtio_rtc_req_set_alarm_enabled { +struct virtio_rtc_req_head head; +uint16_t clock_id; +/* flag VIRTIO_RTC_ALARM_ENABLED */ +uint8_t flags; +uint8_t reserved[5 ]; +}; + +struct virtio_rtc_resp_set_alarm_enabled { +struct virtio_rtc_resp_head head; +/* no response params */ +}; + +/** Union of request types for requestq */ +union virtio_rtc_req_requestq { +struct virtio_rtc_req_read read; +struct virtio_rtc_req_read_cross read_cross; +struct virtio_rtc_req_cfg cfg; +struct virtio_rtc_req_clock_cap clock_cap; +struct virtio_rtc_req_cross_cap cross_cap; +struct virtio_rtc_req_read_alarm read_alarm; +struct virtio_rtc_req_set_alarm set_alarm; +struct virtio_rtc_req_set_alarm_enabled set_alarm_enabled; +}; + +/** Union of response types for requestq */ +union virtio_rtc_resp_requestq { +struct virtio_rtc_resp_read read; +struct virtio_rtc_resp_read_cross read_cross; +struct virtio_rtc_resp_cfg cfg; +struct virtio_rtc_resp_clock_cap clock_cap; +struct virtio_rtc_resp_cross_cap cross_cap; +struct virtio_rtc_resp_read_alarm read_alarm; +struct virtio_rtc_resp_set_alarm set_alarm; +struct virtio_rtc_resp_set_alarm_enabled set_alarm_enabled; +}; + +/* alarmq notifications */ + +/* VIRTIO_RTC_NOTIF_ALARM notification */ + +struct virtio_rtc_notif_alarm { +struct virtio_rtc_notif_head head; +uint16_t clock_id; +uint8_t reserved[6 ]; +}; + +/** Union of notification types for alarmq */ +union virtio_rtc_notif_alarmq { +struct virtio_rtc_notif_alarm alarm; +}; + +#endif /* _LINUX_VIRTIO_RTC_H */
Signature · 1 line
MST
[PULL 070/106] q35: Fix incorrect values for PCIEXBAR masks
In reply to Michael S. TsirkinFrom: Alexey Gerasimenko <[email protected]>
There are two small issues in PCIEXBAR address mask handling:
- wrong bit positions for address mask bits (see PCIEXBAR description in Q35 datasheet)
- incorrect usage of 64ADR_MASK
Due to this, attempting to write a valid PCIEXBAR address may cause it to shift to another address, causing memory layout corruption where emulated MMIO regions may overlap real (passed through) MMIO ranges. Fix this by providing correct values.
Message-Id: <[email protected]>
--- hw/pci-host/q35.c | 6 +++--- include/hw/pci-host/q35.h | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-)
hw/pci-host/q35.c +3 -3
@@ -306,12 +306,12 @@ static void mch_update_pciexbar(MCHPCIState *mch)break ;case MCH_HOST_BRIDGE_PCIEXBAR_LENGTH_128M : length =128 *1024 *1024 ; - addr_mask |=MCH_HOST_BRIDGE_PCIEXBAR_128ADMSK | -MCH_HOST_BRIDGE_PCIEXBAR_64ADMSK ; + addr_mask |=MCH_HOST_BRIDGE_PCIEXBAR_128ADMSK ;break ;case MCH_HOST_BRIDGE_PCIEXBAR_LENGTH_64M : length =64 *1024 *1024 ; - addr_mask |=MCH_HOST_BRIDGE_PCIEXBAR_64ADMSK ; + addr_mask |=MCH_HOST_BRIDGE_PCIEXBAR_64ADMSK | +MCH_HOST_BRIDGE_PCIEXBAR_128ADMSK ;break ;case MCH_HOST_BRIDGE_PCIEXBAR_LENGTH_RVD :qemu_log_mask (LOG_GUEST_ERROR ,"Q35: Reserved PCIEXBAR LENGTH\n" );
include/hw/pci-host/q35.h +2 -2
@@ -100,8 +100,8 @@ struct Q35PCIHost {#define MCH_HOST_BRIDGE_PCIEXBAR_DEFAULT 0xb0000000#define MCH_HOST_BRIDGE_PCIEXBAR_MAX (0x10000000)/* 256M */ #define MCH_HOST_BRIDGE_PCIEXBAR_ADMSK Q35_MASK(64, 35, 28) -#define MCH_HOST_BRIDGE_PCIEXBAR_128ADMSK ((uint64_t)(1 << 26)) -#define MCH_HOST_BRIDGE_PCIEXBAR_64ADMSK ((uint64_t)(1 << 25)) +#define MCH_HOST_BRIDGE_PCIEXBAR_128ADMSK ((uint64_t)(1 << 27)) +#define MCH_HOST_BRIDGE_PCIEXBAR_64ADMSK ((uint64_t)(1 << 26))#define MCH_HOST_BRIDGE_PCIEXBAR_LENGTH_MASK ((uint64_t)(0x3 << 1))#define MCH_HOST_BRIDGE_PCIEXBAR_LENGTH_256M ((uint64_t)(0x0 << 1))#define MCH_HOST_BRIDGE_PCIEXBAR_LENGTH_128M ((uint64_t)(0x1 << 1))
Signature · 1 line
MST
[PULL 084/106] hw/i386/pc: Add a proper owner for the ioport memory regions
In reply to Michael S. TsirkinFrom: Thomas Huth <[email protected]>
Without a proper owner, the memory regions show up in /machine/unattached in the QOM tree, which is something that should be avoided.
Message-Id: <[email protected]>
--- hw/i386/pc.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
hw/i386/pc.c +4 -2
@@ -1051,10 +1051,12 @@ void pc_basic_device_init(struct PCMachineState *pcms,MemoryRegion *ioportF0_io =g_new (MemoryRegion,1 );X86MachineState *x86ms =X86_MACHINE (pcms); -memory_region_init_io (ioport80_io,NULL , &ioport80_io_ops,NULL ,"ioport80" ,1 ); +memory_region_init_io (ioport80_io,OBJECT (pcms), &ioport80_io_ops,NULL , +"ioport80" ,1 );memory_region_add_subregion (isa_bus->address_space_io,0x80 , ioport80_io); -memory_region_init_io (ioportF0_io,NULL , &ioportF0_io_ops,NULL ,"ioportF0" ,1 ); +memory_region_init_io (ioportF0_io,OBJECT (pcms), &ioportF0_io_ops,NULL , +"ioportF0" ,1 );memory_region_add_subregion (isa_bus->address_space_io,0xf0 , ioportF0_io);/*
Signature · 1 line
MST
[PULL 095/106] vhost_user.rst: Add GET_SHMEM_CONFIG message
In reply to Michael S. TsirkinFrom: Albert Esteve <[email protected]>
Add GET_SHMEM_CONFIG vhost-user frontend
message to the spec documentation.
Message-Id: <[email protected]>
--- docs/interop/vhost-user.rst | 39 +++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+)
docs/interop/vhost-user.rst +39 -0
@@ -384,6 +384,22 @@ MMAP request - 0: Pages are mapped read-only - 1: Pages are mapped read-write +VIRTIO Shared Memory Region configuration +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ++-------------+---------+------------+----+--------------+ +| num regions | padding | mem size 0 | .. | mem size 255 | ++-------------+---------+------------+----+--------------+ + +:num regions: a 32-bit number of regions + +:padding: 32-bit + +:mem size: an array of 256 64-bit fields representing the size of each + VIRTIO Shared Memory Region. ``num regions`` specifies the + number of valid regions (non-zero size). The array index + corresponds to the shared memory ID (shmid). + C structure -----------
@@ -410,6 +426,7 @@ In QEMU the vhost-user message is implemented with the following struct: VhostUserShared object; VhostUserTransferDeviceState transfer_state; VhostUserMMap mmap; + VhostUserShMemConfig shmem; }; } QEMU_PACKED VhostUserMsg;
@@ -1794,6 +1811,28 @@ Front-end message types Using this function requires prior negotiation of the ``VHOST_USER_PROTOCOL_F_DEVICE_STATE`` feature. +``VHOST_USER_GET_SHMEM_CONFIG`` + :id: 44 + :equivalent ioctl: N/A + :request payload: N/A + :reply payload: ``struct VhostUserShMemConfig`` + + When the ``VHOST_USER_PROTOCOL_F_SHMEM`` protocol feature has been + successfully negotiated, this message can be submitted by the front-end + to gather the VIRTIO Shared Memory Region configuration. The back-end will + respond with the number of VIRTIO Shared Memory Regions it requires, and + each shared memory region size in an array. The shared memory IDs are + represented by the array index. The information returned shall comply + with the following rules: + + * The shared information will remain valid and unchanged for the entire + lifetime of the connection. + + * The Shared Memory Region size must be a multiple of the page size + supported by mmap(2). + + * The size may be 0 if the region is unused. + Back-end message types ----------------------
Signature · 1 line
MST
[PULL 086/106] x86: q35: add 'wdat' property
In reply to Michael S. TsirkinFrom: Igor Mammedov <[email protected]>
Used for enabling WDAT based watchdog for builtin iTCO watchdog. Usage:
-M q35,wdat={on|off}By default it is disabled.
Message-Id: <[email protected]>
--- hw/i386/pc_q35.c | 18 ++++++++++++++++++ include/hw/i386/pc.h | 1 + 2 files changed, 19 insertions(+)
hw/i386/pc_q35.c +18 -0
@@ -331,6 +331,18 @@ static void pc_q35_init(MachineState *machine) } } +static bool pc_q35_machine_get_wdat (Object *o,Error **errp) +{ +PCMachineState *pcms =PC_MACHINE (o); +return pcms->wdat_enabled; +} + +static void pc_q35_machine_set_wdat (Object *o,bool value,Error **errp) +{ +PCMachineState *pcms =PC_MACHINE (o); + pcms->wdat_enabled = value; +} +#define DEFINE_Q35_MACHINE (major, minor) \ DEFINE_PC_VER_MACHINE(pc_q35, "pc-q35", pc_q35_init, false, NULL, major, minor);
@@ -343,6 +355,7 @@ static void pc_q35_init(MachineState *machine)static void pc_q35_machine_options (MachineClass *m) {PCMachineClass *pcmc =PC_MACHINE_CLASS (m); +ObjectClass *oc =OBJECT_CLASS (m); pcmc->pci_root_uid =0 ; pcmc->default_cpu_version =1 ;
@@ -361,6 +374,11 @@ static void pc_q35_machine_options(MachineClass *m)machine_class_allow_dynamic_sysbus_dev (m,TYPE_RAMFB_DEVICE );machine_class_allow_dynamic_sysbus_dev (m,TYPE_VMBUS_BRIDGE );machine_class_allow_dynamic_sysbus_dev (m,TYPE_UEFI_VARS_X64 ); +object_class_property_add_bool (oc,"wdat" , + pc_q35_machine_get_wdat, pc_q35_machine_set_wdat); +object_class_property_set_description (oc,"wdat" , +"Enable WDAT watchdog support. Default: off" ); +compat_props_add (m->compat_props, pc_q35_compat_defaults, pc_q35_compat_defaults_len); }
include/hw/i386/pc.h +1 -0
@@ -45,6 +45,7 @@ typedef struct PCMachineState {const char *south_bridge;bool acpi_build_enabled; +bool wdat_enabled;bool smbus_enabled;bool sata_enabled;bool hpet_enabled;
Signature · 1 line
MST
[PULL 061/106] MAINTAINERS: Update CXL maintainers entry including adding linux-cxl list
In reply to Michael S. TsirkinFrom: Jonathan Cameron <[email protected]>
The CXL maintainers entry needs an update.
For a while convention has been to +CC [email protected] to get better coverage for CXL aspects so formalize that with an L entry.
Drop Fan as he has not been at Samsung for a while now. Switch my email address over to my kernel.org one.
Message-Id: <[email protected]>
--- MAINTAINERS | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
MAINTAINERS +2 -2
@@ -3203,8 +3203,8 @@ F: tests/qtest/migration/cpr* F: docs/devel/migration/CPR.rst Compute Express Link -M: Jonathan Cameron <[email protected]> -R: Fan Ni <[email protected]> +M: Jonathan Cameron <[email protected]> +L: [email protected] S: Supported F: hw/cxl/ F: hw/mem/cxl_type3.c
Signature · 1 line
MST
[PULL 088/106] tests: acpi: x86/q35: whitelist new WDAT table
In reply to Michael S. TsirkinFrom: Igor Mammedov <[email protected]>
Message-Id: <[email protected]>
--- tests/data/acpi/x86/q35/WDAT.wdat | 0 tests/qtest/bios-tables-test-allowed-diff.h | 1 + 2 files changed, 1 insertion(+) create mode 100644 tests/data/acpi/x86/q35/WDAT.wdat
tests/data/acpi/x86/q35/WDAT.wdat new file +0 -0
tests/qtest/bios-tables-test-allowed-diff.h +1 -0
@@ -1 +1,2 @@/* List of comma-separated changed AML files to ignore */ +"tests/data/acpi/x86/q35/WDAT.wdat",
Signature · 1 line
MST
[PULL 040/106] vhost: vhost_virtqueue_start(): drop extra local variables
In reply to Michael S. TsirkinFrom: Vladimir Sementsov-Ogievskiy <[email protected]>
One letter named variables doesn't really help to read the code, and they simply duplicate structure fields.
Message-Id: <[email protected]>
--- hw/virtio/vhost.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-)
hw/virtio/vhost.c +3 -10
@@ -1277,7 +1277,6 @@ int vhost_virtqueue_start(struct vhost_dev *dev,BusState *qbus =BUS (qdev_get_parent_bus (DEVICE (vdev)));VirtioBusState *vbus =VIRTIO_BUS (qbus);VirtioBusClass *k =VIRTIO_BUS_GET_CLASS (vbus); -hwaddr l;int r;int vhost_vq_index = dev->vhost_ops->vhost_get_vq_index (dev, idx);struct vhost_vring_file file = {
@@ -1302,23 +1301,17 @@ int vhost_virtqueue_start(struct vhost_dev *dev,/* Queue might not be ready for start */ return 0 ; } - - l = vq->desc_size; - vq->desc =vhost_memory_map (dev, vq->desc_phys, l, false); + vq->desc =vhost_memory_map (dev, vq->desc_phys, vq->desc_size, false);if (!vq->desc) { r = -ENOMEM ; goto fail; } - - l = vq->avail_size; - vq->avail =vhost_memory_map (dev, vq->avail_phys, l, false); + vq->avail =vhost_memory_map (dev, vq->avail_phys, vq->avail_size, false);if (!vq->avail) { r = -ENOMEM ; goto fail; } - - l = vq->used_size; - vq->used =vhost_memory_map (dev, vq->used_phys, l, true); + vq->used =vhost_memory_map (dev, vq->used_phys, vq->used_size, true);if (!vq->used) { r = -ENOMEM ; goto fail;
Signature · 1 line
MST
[PULL 050/106] vhost: use consistent naming for backend handlers
In reply to Michael S. TsirkinFrom: Vladimir Sementsov-Ogievskiy <[email protected]>
Most of handlers start from simply .vhost_, except for these four, starting from .vhost_backend_. Let's rename them to be consistent.
Based-on: <[email protected]>
Message-Id: <[email protected]>
--- hw/virtio/vhost-backend.c | 6 +++--- hw/virtio/vhost-user.c | 8 ++++---- hw/virtio/vhost-vdpa.c | 6 +++--- hw/virtio/vhost.c | 14 +++++++------- include/hw/virtio/vhost-backend.h | 17 ++++++++--------- 5 files changed, 25 insertions(+), 26 deletions(-)
hw/virtio/vhost-backend.c +3 -3
@@ -358,9 +358,9 @@ static void vhost_kernel_set_iotlb_callback(struct vhost_dev *dev,const VhostOps kernel_ops = { .backend_type =VHOST_BACKEND_TYPE_KERNEL , - .vhost_backend_init = vhost_kernel_init, - .vhost_backend_cleanup = vhost_kernel_cleanup, - .vhost_backend_memslots_limit = vhost_kernel_memslots_limit, + .vhost_init = vhost_kernel_init, + .vhost_cleanup = vhost_kernel_cleanup, + .vhost_memslots_limit = vhost_kernel_memslots_limit, .vhost_net_set_backend = vhost_kernel_net_set_backend, .vhost_scsi_set_endpoint = vhost_kernel_scsi_set_endpoint, .vhost_scsi_clear_endpoint = vhost_kernel_scsi_clear_endpoint,
hw/virtio/vhost-user.c +4 -4
@@ -3115,10 +3115,10 @@ void vhost_user_qmp_status(struct vhost_dev *dev, VirtioStatus *status)const VhostOps user_ops = { .backend_type =VHOST_BACKEND_TYPE_USER , - .vhost_backend_init = vhost_user_backend_init, - .vhost_backend_cleanup = vhost_user_backend_cleanup, - .vhost_backend_memslots_limit = vhost_user_memslots_limit, - .vhost_backend_no_private_memslots = vhost_user_no_private_memslots, + .vhost_init = vhost_user_backend_init, + .vhost_cleanup = vhost_user_backend_cleanup, + .vhost_memslots_limit = vhost_user_memslots_limit, + .vhost_no_private_memslots = vhost_user_no_private_memslots, .vhost_set_log_base = vhost_user_set_log_base, .vhost_set_mem_table = vhost_user_set_mem_table, .vhost_set_vring_addr = vhost_user_set_vring_addr,
hw/virtio/vhost-vdpa.c +3 -3
@@ -1590,8 +1590,8 @@ static bool vhost_vdpa_force_iommu(struct vhost_dev *dev)const VhostOps vdpa_ops = { .backend_type =VHOST_BACKEND_TYPE_VDPA , - .vhost_backend_init = vhost_vdpa_init, - .vhost_backend_cleanup = vhost_vdpa_cleanup, + .vhost_init = vhost_vdpa_init, + .vhost_cleanup = vhost_vdpa_cleanup, .vhost_set_log_base = vhost_vdpa_set_log_base, .vhost_set_vring_addr = vhost_vdpa_set_vring_addr, .vhost_set_vring_num = vhost_vdpa_set_vring_num,
@@ -1602,7 +1602,7 @@ const VhostOps vdpa_ops = { .vhost_get_features = vhost_vdpa_get_features, .vhost_set_owner = vhost_vdpa_set_owner, .vhost_set_vring_endian = NULL, - .vhost_backend_memslots_limit = vhost_vdpa_memslots_limit, + .vhost_memslots_limit = vhost_vdpa_memslots_limit, .vhost_set_mem_table = vhost_vdpa_set_mem_table, .vhost_set_features = vhost_vdpa_set_features, .vhost_reset_device = vhost_vdpa_reset_device,
hw/virtio/vhost.c +7 -7
@@ -58,7 +58,7 @@ unsigned int vhost_get_max_memslots(void)struct vhost_dev *hdev; QLIST_FOREACH(hdev, &vhost_devices, entry) { - max =MIN (max, hdev->vhost_ops->vhost_backend_memslots_limit (hdev)); + max =MIN (max, hdev->vhost_ops->vhost_memslots_limit (hdev)); }return max; }
@@ -69,7 +69,7 @@ unsigned int vhost_get_free_memslots(void)struct vhost_dev *hdev; QLIST_FOREACH(hdev, &vhost_devices, entry) { -unsigned int r = hdev->vhost_ops->vhost_backend_memslots_limit (hdev); +unsigned int r = hdev->vhost_ops->vhost_memslots_limit (hdev);unsigned int cur_free = r - hdev->mem->nregions;if (unlikely (r < hdev->mem->nregions)) {
@@ -664,8 +664,8 @@ static bool vhost_section(struct vhost_dev *dev, MemoryRegionSection *section)*/ if ((memory_region_get_fd (section->mr) <0 || !qemu_ram_is_shared (section->mr->ram_block)) && - dev->vhost_ops->vhost_backend_no_private_memslots && - dev->vhost_ops->vhost_backend_no_private_memslots (dev)) { + dev->vhost_ops->vhost_no_private_memslots && + dev->vhost_ops->vhost_no_private_memslots (dev)) {trace_vhost_reject_section (mr->name,2 );return false; }
@@ -1674,7 +1674,7 @@ int vhost_dev_init(struct vhost_dev *hdev, void *opaque, r =vhost_set_backend_type (hdev, backend_type);assert (r >=0 ); - r = hdev->vhost_ops->vhost_backend_init (hdev, opaque, errp); + r = hdev->vhost_ops->vhost_init (hdev, opaque, errp);if (r <0 ) { goto fail; }
@@ -1691,7 +1691,7 @@ int vhost_dev_init(struct vhost_dev *hdev, void *opaque, goto fail; } - limit = hdev->vhost_ops->vhost_backend_memslots_limit (hdev); + limit = hdev->vhost_ops->vhost_memslots_limit (hdev);if (limit <MEMORY_DEVICES_SAFE_MAX_MEMSLOTS &&memory_devices_memslot_auto_decision_active ()) { error_setg(errp, "some memory device (like virtio-mem)"
@@ -1809,7 +1809,7 @@ void vhost_dev_cleanup(struct vhost_dev *hdev)g_free (hdev->mem);g_free (hdev->mem_sections);if (hdev->vhost_ops) { - hdev->vhost_ops->vhost_backend_cleanup (hdev); + hdev->vhost_ops->vhost_cleanup (hdev); }assert (!hdev->log);
include/hw/virtio/vhost-backend.h +8 -9
@@ -51,10 +51,9 @@ struct vhost_scsi_target;struct vhost_iotlb_msg ;struct vhost_virtqueue ; -typedef int (*vhost_backend_init )(struct vhost_dev *dev,void *opaque, -Error **errp); -typedef int (*vhost_backend_cleanup )(struct vhost_dev *dev); -typedef int (*vhost_backend_memslots_limit )(struct vhost_dev *dev); +typedef int (*vhost_init )(struct vhost_dev *dev,void *opaque,Error **errp); +typedef int (*vhost_cleanup )(struct vhost_dev *dev); +typedef int (*vhost_memslots_limit )(struct vhost_dev *dev);typedef int (*vhost_net_set_backend_op )(struct vhost_dev *dev,struct vhost_vring_file *file);
@@ -131,7 +130,7 @@ typedef int (*vhost_crypto_create_session_op)(struct vhost_dev *dev,typedef int (*vhost_crypto_close_session_op )(struct vhost_dev *dev,uint64_t session_id); -typedef bool (*vhost_backend_no_private_memslots_op )(struct vhost_dev *dev); +typedef bool (*vhost_no_private_memslots_op )(struct vhost_dev *dev); typedef int (*vhost_get_inflight_fd_op)(struct vhost_dev *dev, uint16_t queue_size,
@@ -166,10 +165,10 @@ typedef int (*vhost_check_device_state_op)(struct vhost_dev *dev, Error **errp); typedef struct VhostOps { VhostBackendType backend_type; - vhost_backend_init vhost_backend_init; - vhost_backend_cleanup vhost_backend_cleanup; - vhost_backend_memslots_limit vhost_backend_memslots_limit; - vhost_backend_no_private_memslots_op vhost_backend_no_private_memslots; + vhost_init vhost_init; + vhost_cleanup vhost_cleanup; + vhost_memslots_limit vhost_memslots_limit; + vhost_no_private_memslots_op vhost_no_private_memslots; vhost_net_set_backend_op vhost_net_set_backend; vhost_net_set_mtu_op vhost_net_set_mtu; vhost_scsi_set_endpoint_op vhost_scsi_set_endpoint;
Signature · 1 line
MST
[PULL 085/106] acpi: add API to build WDAT instructions
In reply to Michael S. TsirkinFrom: Igor Mammedov <[email protected]>
Add definitions for WDAT[1] actions/instructions and build_append_wdat_ins() API to build table entries.
1)
"Hardware Watchdog Timers Design Specification"
https://uefi.org/acpi 'Watchdog Action Table (WDAT)'
Message-Id: <[email protected]>
--- hw/acpi/aml-build.c | 14 +++++ include/hw/acpi/wdat.h | 118 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 132 insertions(+) create mode 100644 include/hw/acpi/wdat.h
hw/acpi/aml-build.c +14 -0
@@ -35,6 +35,7 @@#include "hw/acpi/acpi_aml_interface.h" #include "qemu/cutils.h" #include "hw/core/cpu.h" +#include "hw/acpi/wdat.h" static GArray *build_alloc_array (void ) {
@@ -2872,3 +2873,16 @@ void qbus_build_aml(BusState *bus, Aml *scope)call_dev_aml_func (DEVICE (kid->child), scope); } } + +void build_append_wdat_ins (GArray *table_data, +WDATAction action,uint8_t flags, +struct AcpiGenericAddress as, +uint32_t val,uint32_t mask) +{ +build_append_int_noprefix (table_data, action,1 );/* Watchdog Action */ +build_append_int_noprefix (table_data, flags,1 );/* Instruction Flags */ +build_append_int_noprefix (table_data,0 ,2 );/* Reserved */ +build_append_gas_from_struct (table_data, &as);/* Register Region */ +build_append_int_noprefix (table_data, val,4 );/* Value */ +build_append_int_noprefix (table_data, mask,4 );/* Mask */ +}
include/hw/acpi/wdat.h new file +118 -0
118 lines not on this page · raw message
Signature · 1 line
MST
[PULL 090/106] tests: acpi: x86/q35: update expected WDAT blob
In reply to Michael S. TsirkinFrom: Igor Mammedov <[email protected]>
replace blank table with a new one:
+[000h 0000 4] Signature : "WDAT" [Watchdog Action Table] +[004h 0004 4] Table Length : 00000134 +[008h 0008 1] Revision : 01 +[009h 0009 1] Checksum : 31 +[00Ah 0010 6] Oem ID : "BOCHS " +[010h 0016 8] Oem Table ID : "BXPC " +[018h 0024 4] Oem Revision : 00000001 +[01Ch 0028 4] Asl Compiler ID : "BXPC" +[020h 0032 4] Asl Compiler Revision : 00000001 + +[024h 0036 4] Header Length : 00000020 +[028h 0040 2] PCI Segment : 00FF +[02Ah 0042 1] PCI Bus : FF +[02Bh 0043 1] PCI Device : FF +[02Ch 0044 1] PCI Function : FF +[02Dh 0045 3] Reserved : 000000 +[030h 0048 4] Timer Period : 00000258 +[034h 0052 4] Max Count : 000003FF +[038h 0056 4] Min Count : 00000004 +[03Ch 0060 1] Flags (decoded below) : 81 + Enabled : 1 + Stopped When Asleep : 1 +[03Dh 0061 3] Reserved : 000000 +[040h 0064 4] Watchdog Entry Count : 0000000A + +[044h 0068 1] Watchdog Action : 01 +[045h 0069 1] Instruction : 02 +[046h 0070 2] Reserved : 0000 + +[048h 0072 12] Register Region : [Generic Address Structure] +[048h 0072 1] Space ID : 01 [SystemIO] +[049h 0073 1] Bit Width : 10 +[04Ah 0074 1] Bit Offset : 00 +[04Bh 0075 1] Encoded Access Width : 02 [Word Access:16] +[04Ch 0076 8] Address : 0000000000000660 + +[054h 0084 4] Value : 00000001 +[058h 0088 4] Register Mask : 000001FF + +[05Ch 0092 1] Watchdog Action : 08 +[05Dh 0093 1] Instruction : 00 +[05Eh 0094 2] Reserved : 0000 + +[060h 0096 12] Register Region : [Generic Address Structure] +[060h 0096 1] Space ID : 01 [SystemIO] +[061h 0097 1] Bit Width : 10 +[062h 0098 1] Bit Offset : 00 +[063h 0099 1] Encoded Access Width : 02 [Word Access:16] +[064h 0100 8] Address : 0000000000000668 + +[06Ch 0108 4] Value : 00000000 +[070h 0112 4] Register Mask : 00000800 + +[074h 0116 1] Watchdog Action : 09 +[075h 0117 1] Instruction : 82 +[076h 0118 2] Reserved : 0000 + +[078h 0120 12] Register Region : [Generic Address Structure] +[078h 0120 1] Space ID : 01 [SystemIO] +[079h 0121 1] Bit Width : 10 +[07Ah 0122 1] Bit Offset : 00 +[07Bh 0123 1] Encoded Access Width : 02 [Word Access:16] +[07Ch 0124 8] Address : 0000000000000668 + +[084h 0132 4] Value : 00000000 +[088h 0136 4] Register Mask : 00000800 + +[08Ch 0140 1] Watchdog Action : 0A +[08Dh 0141 1] Instruction : 00 +[08Eh 0142 2] Reserved : 0000 + +[090h 0144 12] Register Region : [Generic Address Structure] +[090h 0144 1] Space ID : 01 [SystemIO] +[091h 0145 1] Bit Width : 10 +[092h 0146 1] Bit Offset : 00 +[093h 0147 1] Encoded Access Width : 02 [Word Access:16] +[094h 0148 8] Address : 0000000000000668 + +[09Ch 0156 4] Value : 00000800 +[0A0h 0160 4] Register Mask : 00000800 + +[0A4h 0164 1] Watchdog Action : 0B +[0A5h 0165 1] Instruction : 82 +[0A6h 0166 2] Reserved : 0000 + +[0A8h 0168 12] Register Region : [Generic Address Structure] +[0A8h 0168 1] Space ID : 01 [SystemIO] +[0A9h 0169 1] Bit Width : 10 +[0AAh 0170 1] Bit Offset : 00 +[0ABh 0171 1] Encoded Access Width : 02 [Word Access:16] +[0ACh 0172 8] Address : 0000000000000668 + +[0B4h 0180 4] Value : 00000800 +[0B8h 0184 4] Register Mask : 00000800 + +[0BCh 0188 1] Watchdog Action : 06 +[0BDh 0189 1] Instruction : 03 +[0BEh 0190 2] Reserved : 0000 + +[0C0h 0192 12] Register Region : [Generic Address Structure] +[0C0h 0192 1] Space ID : 01 [SystemIO] +[0C1h 0193 1] Bit Width : 10 +[0C2h 0194 1] Bit Offset : 00 +[0C3h 0195 1] Encoded Access Width : 02 [Word Access:16] +[0C4h 0196 8] Address : 0000000000000672 + +[0CCh 0204 4] Value : 00000000 +[0D0h 0208 4] Register Mask : 000003FF + +[0D4h 0212 1] Watchdog Action : 05 +[0D5h 0213 1] Instruction : 01 +[0D6h 0214 2] Reserved : 0000 + +[0D8h 0216 12] Register Region : [Generic Address Structure] +[0D8h 0216 1] Space ID : 01 [SystemIO] +[0D9h 0217 1] Bit Width : 10 +[0DAh 0218 1] Bit Offset : 00 +[0DBh 0219 1] Encoded Access Width : 02 [Word Access:16] +[0DCh 0220 8] Address : 0000000000000672 + +[0E4h 0228 4] Value : 00000000 +[0E8h 0232 4] Register Mask : 000003FF + +[0ECh 0236 1] Watchdog Action : 20 +[0EDh 0237 1] Instruction : 00 +[0EEh 0238 2] Reserved : 0000 + +[0F0h 0240 12] Register Region : [Generic Address Structure] +[0F0h 0240 1] Space ID : 01 [SystemIO] +[0F1h 0241 1] Bit Width : 10 +[0F2h 0242 1] Bit Offset : 00 +[0F3h 0243 1] Encoded Access Width : 02 [Word Access:16] +[0F4h 0244 8] Address : 0000000000000666 + +[0FCh 0252 4] Value : 00000002 +[100h 0256 4] Register Mask : 00000002 + +[104h 0260 1] Watchdog Action : 21 +[105h 0261 1] Instruction : 82 +[106h 0262 2] Reserved : 0000 + +[108h 0264 12] Register Region : [Generic Address Structure] +[108h 0264 1] Space ID : 01 [SystemIO] +[109h 0265 1] Bit Width : 10 +[10Ah 0266 1] Bit Offset : 00 +[10Bh 0267 1] Encoded Access Width : 02 [Word Access:16] +[10Ch 0268 8] Address : 0000000000000666 + +[114h 0276 4] Value : 00000002 +[118h 0280 4] Register Mask : 00000002 + +[11Ch 0284 1] Watchdog Action : 21 +[11Dh 0285 1] Instruction : 82 +[11Eh 0286 2] Reserved : 0000 + +[120h 0288 12] Register Region : [Generic Address Structure] +[120h 0288 1] Space ID : 01 [SystemIO] +[121h 0289 1] Bit Width : 10 +[122h 0290 1] Bit Offset : 00 +[123h 0291 1] Encoded Access Width : 02 [Word Access:16] +[124h 0292 8] Address : 0000000000000666
+
+[12Ch 0300 4] Value : 00000004
+[130h 0304 4] Register Mask : 00000004
Message-Id: <[email protected]>
--- tests/data/acpi/x86/q35/WDAT.wdat | Bin 0 -> 308 bytes tests/qtest/bios-tables-test-allowed-diff.h | 1 - 2 files changed, 1 deletion(-)
tests/data/acpi/x86/q35/WDAT.wdat binary +0 -0
tests/qtest/bios-tables-test-allowed-diff.h +0 -1
@@ -1,2 +1 @@/* List of comma-separated changed AML files to ignore */ -"tests/data/acpi/x86/q35/WDAT.wdat",
Signature · 1 line
MST
[PULL 042/106] vhost: simplify vhost_dev_init() error-path
In reply to Michael S. TsirkinFrom: Vladimir Sementsov-Ogievskiy <[email protected]>
No reason to rollback setting up busyloop timeout on failure. We don't do such rollback for other things we setup in backend. Also, look at vhost_net_init() in hw/net/vhost_net.c: we may fail after successfully called vhost_dev_init(), and in this case we'll just call vhost_dev_cleanup(), which doesn't rollback busyloop timeout.
So, let's keep it simple.
Message-Id: <[email protected]>
--- hw/virtio/vhost.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-)
hw/virtio/vhost.c +3 -9
@@ -1624,7 +1624,7 @@ int vhost_dev_init(struct vhost_dev *hdev, void *opaque, busyloop_timeout);if (r <0 ) {error_setg_errno (errp, -r,"Failed to set busyloop timeout" ); - goto fail_busyloop; + goto fail; } } }
@@ -1664,7 +1664,7 @@ int vhost_dev_init(struct vhost_dev *hdev, void *opaque,if (hdev->migration_blocker !=NULL ) { r =migrate_add_blocker_normal (&hdev->migration_blocker, errp);if (r <0 ) { - goto fail_busyloop; + goto fail; } }
@@ -1696,17 +1696,11 @@ int vhost_dev_init(struct vhost_dev *hdev, void *opaque," than current number of used (%d) and reserved (%d)" " memory slots for memory devices.", limit, used, reserved); r = -EINVAL ; - goto fail_busyloop; + goto fail; }return 0 ; -fail_busyloop: -if (busyloop_timeout) { -while (--i >=0 ) { -vhost_virtqueue_set_busyloop_timeout (hdev, hdev->vq_index + i,0 ); - } - } fail: hdev->nvqs = n_initialized_vqs;vhost_dev_cleanup (hdev);
Signature · 1 line
MST
[PULL 009/106] intel_iommu: Create the nested hwpt with IOMMU_HWPT_ALLOC_PASID flag
In reply to Michael S. TsirkinFrom: Zhenzhong Duan <[email protected]>
When pasid is enabled, any hwpt attached to non-PASID or PASID should be IOMMU_HWPT_ALLOC_PASID flagged, or else attachment fails.
Change vtd_destroy_old_fs_hwpt() to pass in 'VTDHostIOMMUDevice *' for naming consistency.
Message-Id: <[email protected]>
--- hw/i386/intel_iommu_accel.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-)
hw/i386/intel_iommu_accel.c +12 -7
@@ -69,11 +69,13 @@ VTDHostIOMMUDevice *vtd_find_hiod_iommufd(VTDAddressSpace *as)return NULL ; } -static bool vtd_create_fs_hwpt (HostIOMMUDeviceIOMMUFD *hiodi, +static bool vtd_create_fs_hwpt (VTDHostIOMMUDevice *vtd_hiod,VTDPASIDEntry *pe,uint32_t *fs_hwpt_id,Error **errp) { +HostIOMMUDeviceIOMMUFD *hiodi =HOST_IOMMU_DEVICE_IOMMUFD (vtd_hiod->hiod);struct iommu_hwpt_vtd_s1 vtd = {}; +uint32_t flags = vtd_hiod->iommu_state->pasid ?IOMMU_HWPT_ALLOC_PASID :0 ; vtd.flags = (VTD_SM_PASID_ENTRY_SRE (pe) ?IOMMU_VTD_S1_SRE :0 ) | (VTD_SM_PASID_ENTRY_WPE(pe) ? IOMMU_VTD_S1_WPE : 0) |
@@ -82,13 +84,16 @@ static bool vtd_create_fs_hwpt(HostIOMMUDeviceIOMMUFD *hiodi, vtd.pgtbl_addr = (uint64_t )vtd_pe_get_fspt_base (pe);return iommufd_backend_alloc_hwpt (hiodi->iommufd, hiodi->devid, - hiodi->hwpt_id,0 ,IOMMU_HWPT_DATA_VTD_S1 , -sizeof (vtd), &vtd, fs_hwpt_id, errp); + hiodi->hwpt_id, flags, +IOMMU_HWPT_DATA_VTD_S1 ,sizeof (vtd), &vtd, + fs_hwpt_id, errp); } -static void vtd_destroy_old_fs_hwpt (HostIOMMUDeviceIOMMUFD *hiodi, +static void vtd_destroy_old_fs_hwpt (VTDHostIOMMUDevice *vtd_hiod,VTDAddressSpace *vtd_as) { +HostIOMMUDeviceIOMMUFD *hiodi =HOST_IOMMU_DEVICE_IOMMUFD (vtd_hiod->hiod); +if (!vtd_as->fs_hwpt_id) {return ; }
@@ -116,7 +121,7 @@ static bool vtd_device_attach_iommufd(VTDHostIOMMUDevice *vtd_hiod, }if (vtd_pe_pgtt_is_fst (pe)) { -if (!vtd_create_fs_hwpt (hiodi, pe, &hwpt_id, errp)) { +if (!vtd_create_fs_hwpt (vtd_hiod, pe, &hwpt_id, errp)) {return false; } }
@@ -126,7 +131,7 @@ static bool vtd_device_attach_iommufd(VTDHostIOMMUDevice *vtd_hiod,trace_vtd_device_attach_hwpt (hiodi->devid,IOMMU_NO_PASID , hwpt_id, ret);if (ret) {/* Destroy old fs_hwpt if it's a replacement */ -vtd_destroy_old_fs_hwpt (hiodi, vtd_as); +vtd_destroy_old_fs_hwpt (vtd_hiod, vtd_as);if (vtd_pe_pgtt_is_fst (pe)) { vtd_as->fs_hwpt_id = hwpt_id; }
@@ -161,7 +166,7 @@ static bool vtd_device_detach_iommufd(VTDHostIOMMUDevice *vtd_hiod, }if (ret) { -vtd_destroy_old_fs_hwpt (hiodi, vtd_as); +vtd_destroy_old_fs_hwpt (vtd_hiod, vtd_as); }return ret;
Signature · 1 line
MST
[PULL 089/106] tests: acpi: x86/q35: add WDAT table test case
In reply to Michael S. TsirkinFrom: Igor Mammedov <[email protected]>
Message-Id: <[email protected]>
--- tests/qtest/bios-tables-test.c | 13 +++++++++++++ 1 file changed, 13 insertions(+)
tests/qtest/bios-tables-test.c +13 -0
@@ -2534,6 +2534,18 @@ static void test_acpi_isapc_smbios_legacy(void)free_test_data (&data); } +static void test_acpi_q35_wdat (void ) +{ +test_data data = { + .machine =MACHINE_Q35 , + .arch ="x86" , + .variant =".wdat" , + }; + +test_acpi_one ("-machine wdat=on" , &data); +free_test_data (&data); +} +static void test_oem_fields (test_data *data) {int i;
@@ -2828,6 +2840,7 @@ int main(int argc, char *argv[])qtest_add_func ("acpi/q35/cxl" , test_acpi_q35_cxl);#endif qtest_add_func ("acpi/q35/slic" , test_acpi_q35_slic); +qtest_add_func ("acpi/q35/wdat" , test_acpi_q35_wdat); }if (qtest_has_machine ("microvm" )) {qtest_add_func ("acpi/microvm" , test_acpi_microvm_tcg);
Signature · 1 line
MST
[PULL 012/106] intel_iommu: Export some functions
In reply to Michael S. TsirkinFrom: Zhenzhong Duan <[email protected]>
Export some functions for accel code usages. Inline functions and MACROs are moved to internal header files. Then accel code in following patches could access them.
Message-Id: <[email protected]>
--- hw/i386/intel_iommu.c | 43 +++++++--------------------------- hw/i386/intel_iommu_internal.h | 31 ++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 34 deletions(-)
hw/i386/intel_iommu.c +9 -34
@@ -42,12 +42,6 @@#include "migration/vmstate.h" #include "trace.h" -/* context entry operations */ -#define VTD_CE_GET_PASID_DIR_TABLE (ce) \ - ((ce)->val[0] & VTD_PASID_DIR_BASE_ADDR_MASK) -#define VTD_CE_GET_PRE (ce) \ - ((ce)->val[0] & VTD_SM_CONTEXT_ENTRY_PRE) -/* * Paging mode for first-stage translation (VTD spec Figure 9-6) * 00: 4-level paging, 01: 5-level paging
@@ -831,18 +825,12 @@ static inline bool vtd_pe_type_check(IntelIOMMUState *s, VTDPASIDEntry *pe) } } -static inline bool vtd_pdire_present (VTDPASIDDirEntry *pdire) -{ -return pdire->val &1 ; -} -/** * Caller of this function should check present bit if wants * to use pdir entry for further usage except for fpd bit check. */ -static int vtd_get_pdire_from_pdir_table (dma_addr_t pasid_dir_base, -uint32_t pasid, -VTDPASIDDirEntry *pdire) +int vtd_get_pdire_from_pdir_table (dma_addr_t pasid_dir_base,uint32_t pasid, +VTDPASIDDirEntry *pdire) {uint32_t index;dma_addr_t addr, entry_size;
@@ -860,15 +848,8 @@ static int vtd_get_pdire_from_pdir_table(dma_addr_t pasid_dir_base,return 0 ; } -static inline bool vtd_pe_present (VTDPASIDEntry *pe) -{ -return pe->val[0 ] &VTD_PASID_ENTRY_P ; -} - -static int vtd_get_pe_in_pasid_leaf_table (IntelIOMMUState *s, -uint32_t pasid, -dma_addr_t addr, -VTDPASIDEntry *pe) +int vtd_get_pe_in_pasid_leaf_table (IntelIOMMUState *s,uint32_t pasid, +dma_addr_t addr,VTDPASIDEntry *pe) {uint8_t pgtt;uint32_t index;
@@ -1526,8 +1507,8 @@ static int vtd_ce_pasid_0_check(IntelIOMMUState *s, VTDContextEntry *ce) }/* Map a device to its corresponding domain (context-entry) */ -static int vtd_dev_to_context_entry (IntelIOMMUState *s,uint8_t bus_num, -uint8_t devfn,VTDContextEntry *ce) +int vtd_dev_to_context_entry (IntelIOMMUState *s,uint8_t bus_num, +uint8_t devfn,VTDContextEntry *ce) {VTDRootEntry re;int ret_fr;
@@ -1909,7 +1890,7 @@ static VTDAddressSpace *vtd_get_as_by_sid_and_pasid(IntelIOMMUState *s, vtd_find_as_by_sid_and_pasid, &key); } -static VTDAddressSpace *vtd_get_as_by_sid (IntelIOMMUState *s,uint16_t sid) +VTDAddressSpace *vtd_get_as_by_sid (IntelIOMMUState *s,uint16_t sid) {return vtd_get_as_by_sid_and_pasid (s, sid,PCI_NO_PASID ); }
@@ -3113,9 +3094,8 @@ static bool vtd_process_piotlb_desc(IntelIOMMUState *s,return true; } -static int vtd_dev_get_pe_from_pasid (IntelIOMMUState *s,PCIBus *bus, -uint8_t devfn,uint32_t pasid, -VTDPASIDEntry *pe) +int vtd_dev_get_pe_from_pasid (IntelIOMMUState *s,PCIBus *bus,uint8_t devfn, +uint32_t pasid,VTDPASIDEntry *pe) {VTDContextEntry ce;int ret;
@@ -3132,11 +3112,6 @@ static int vtd_dev_get_pe_from_pasid(IntelIOMMUState *s, PCIBus *bus,return vtd_ce_get_pasid_entry (s, &ce, pe, pasid); } -static int vtd_pasid_entry_compare (VTDPASIDEntry *p1,VTDPASIDEntry *p2) -{ -return memcmp (p1, p2,sizeof (*p1)); -} -/* Update or invalidate pasid cache based on the pasid entry in guest memory. */ static void vtd_pasid_cache_sync_locked (gpointer key,gpointer value,gpointer user_data)
hw/i386/intel_iommu_internal.h +31 -0
@@ -620,6 +620,12 @@ typedef struct VTDRootEntry VTDRootEntry;#define VTD_SM_CONTEXT_ENTRY_RSVD_VAL1 0xffffffffffe00000ULL#define VTD_SM_CONTEXT_ENTRY_PRE 0x10ULL +/* context entry operations */ +#define VTD_CE_GET_PASID_DIR_TABLE (ce) \ + ((ce)->val[0] & VTD_PASID_DIR_BASE_ADDR_MASK) +#define VTD_CE_GET_PRE (ce) \ + ((ce)->val[0] & VTD_SM_CONTEXT_ENTRY_PRE) + typedef struct VTDPASIDCacheInfo { uint8_t type; uint16_t did;
@@ -746,4 +752,29 @@ static inline bool vtd_pe_pgtt_is_fst(VTDPASIDEntry *pe) {return (VTD_SM_PASID_ENTRY_PGTT (pe) ==VTD_SM_PASID_ENTRY_FST ); } + +static inline bool vtd_pdire_present (VTDPASIDDirEntry *pdire) +{ +return pdire->val &1 ; +} + +static inline bool vtd_pe_present (VTDPASIDEntry *pe) +{ +return pe->val[0 ] &VTD_PASID_ENTRY_P ; +} + +static inline int vtd_pasid_entry_compare (VTDPASIDEntry *p1,VTDPASIDEntry *p2) +{ +return memcmp (p1, p2,sizeof (*p1)); +} + +int vtd_get_pdire_from_pdir_table (dma_addr_t pasid_dir_base,uint32_t pasid, +VTDPASIDDirEntry *pdire); +int vtd_get_pe_in_pasid_leaf_table (IntelIOMMUState *s,uint32_t pasid, +dma_addr_t addr,VTDPASIDEntry *pe); +int vtd_dev_to_context_entry (IntelIOMMUState *s,uint8_t bus_num, +uint8_t devfn,VTDContextEntry *ce); +VTDAddressSpace *vtd_get_as_by_sid (IntelIOMMUState *s,uint16_t sid); +int vtd_dev_get_pe_from_pasid (IntelIOMMUState *s,PCIBus *bus,uint8_t devfn, +uint32_t pasid,VTDPASIDEntry *pe);#endif
Signature · 1 line
MST
[PULL 047/106] vhost-user-blk: add some useful trace-points
In reply to Michael S. TsirkinFrom: Vladimir Sementsov-Ogievskiy <[email protected]>
Message-Id: <[email protected]>
--- hw/block/trace-events | 10 ++++++++++ hw/block/vhost-user-blk.c | 19 +++++++++++++++++++ 2 files changed, 29 insertions(+)
hw/block/trace-events +10 -0
@@ -58,6 +58,16 @@ virtio_blk_handle_zone_mgmt(void *vdev, void *req, uint8_t op, int64_t sector, i virtio_blk_handle_zone_reset_all(void *vdev, void *req, int64_t sector, int64_t len) "vdev %p req %p sector 0x%" PRIx64 " cap 0x%" PRIx64 "" virtio_blk_handle_zone_append(void *vdev, void *req, int64_t sector) "vdev %p req %p, append sector 0x%" PRIx64 "" +# vhost-user-blk.c +vhost_user_blk_start_in(void *vdev) "vdev %p" +vhost_user_blk_start_out(void *vdev) "vdev %p" +vhost_user_blk_stop_in(void *vdev) "vdev %p" +vhost_user_blk_stop_out(void *vdev) "vdev %p" +vhost_user_blk_connect_in(void *vdev) "vdev %p" +vhost_user_blk_connect_out(void *vdev) "vdev %p" +vhost_user_blk_device_realize_in(void *vdev) "vdev %p" +vhost_user_blk_device_realize_out(void *vdev) "vdev %p" + # hd-geometry.c hd_geometry_lchs_guess(void *blk, int cyls, int heads, int secs) "blk %p LCHS %d %d %d" hd_geometry_guess(void *blk, uint32_t cyls, uint32_t heads, uint32_t secs, int trans) "blk %p CHS %u %u %u trans %d"
hw/block/vhost-user-blk.c +19 -0
@@ -31,6 +31,7 @@#include "hw/virtio/virtio-access.h" #include "system/system.h" #include "system/runstate.h" +#include "trace.h" static const int user_feature_bits[] = {VIRTIO_BLK_F_SIZE_MAX ,
@@ -137,6 +138,8 @@ static int vhost_user_blk_start(VirtIODevice *vdev, Error **errp)VirtioBusClass *k =VIRTIO_BUS_GET_CLASS (qbus);int i, ret; +trace_vhost_user_blk_start_in (vdev); +if (!k->set_guest_notifiers) {error_setg (errp,"binding does not support guest notifiers" );return -ENOSYS ;
@@ -192,6 +195,8 @@ static int vhost_user_blk_start(VirtIODevice *vdev, Error **errp) } s->started_vu = true; +trace_vhost_user_blk_start_out (vdev); +return ret; err_guest_notifiers:
@@ -212,6 +217,8 @@ static int vhost_user_blk_stop(VirtIODevice *vdev)int ret;bool force_stop = false; +trace_vhost_user_blk_stop_in (vdev); +if (!s->started_vu) {return 0 ; }
@@ -233,6 +240,9 @@ static int vhost_user_blk_stop(VirtIODevice *vdev) }vhost_dev_disable_notifiers (&s->dev, vdev); + +trace_vhost_user_blk_stop_out (vdev); +return ret; }
@@ -340,6 +350,8 @@ static int vhost_user_blk_connect(DeviceState *dev, Error **errp)VHostUserBlk *s =VHOST_USER_BLK (vdev);int ret =0 ; +trace_vhost_user_blk_connect_in (vdev); +if (s->connected) {return 0 ; }
@@ -366,6 +378,8 @@ static int vhost_user_blk_connect(DeviceState *dev, Error **errp) ret =vhost_user_blk_start (vdev, errp); } +trace_vhost_user_blk_connect_out (vdev); +return ret; }
@@ -456,6 +470,8 @@ static void vhost_user_blk_device_realize(DeviceState *dev, Error **errp)int retries;int i, ret; +trace_vhost_user_blk_device_realize_in (vdev); +if (!s->chardev.chr) {error_setg (errp,"chardev is mandatory" );return ;
@@ -515,6 +531,9 @@ static void vhost_user_blk_device_realize(DeviceState *dev, Error **errp)qemu_chr_fe_set_handlers (&s->chardev,NULL ,NULL , vhost_user_blk_event,NULL , (void *)dev,NULL , true); + +trace_vhost_user_blk_device_realize_out (vdev); +return ; virtio_err:
Signature · 1 line
MST
[PULL 038/106] vhost: simplify calls to vhost_memory_unmap()
In reply to Michael S. TsirkinFrom: Vladimir Sementsov-Ogievskiy <[email protected]>
No reason to calculate memory size again, as we have corresponding variable for each vring.
Message-Id: <[email protected]>
--- hw/virtio/vhost.c | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-)
hw/virtio/vhost.c +6 -12
@@ -1383,12 +1383,9 @@ int vhost_virtqueue_start(struct vhost_dev *dev,return 0 ; fail: -vhost_memory_unmap (dev, &vq->used,virtio_queue_get_used_size (vdev, idx), -0 ,0 ); -vhost_memory_unmap (dev, &vq->avail,virtio_queue_get_avail_size (vdev, idx), -0 ,0 ); -vhost_memory_unmap (dev, &vq->desc,virtio_queue_get_desc_size (vdev, idx), -0 ,0 ); +vhost_memory_unmap (dev, &vq->used, vq->used_size,0 ,0 ); +vhost_memory_unmap (dev, &vq->avail, vq->avail_size,0 ,0 ); +vhost_memory_unmap (dev, &vq->desc, vq->desc_size,0 ,0 );return r; }
@@ -1435,12 +1432,9 @@ static int do_vhost_virtqueue_stop(struct vhost_dev *dev, vhost_vq_index); } -vhost_memory_unmap (dev, &vq->used,virtio_queue_get_used_size (vdev, idx), -1 ,virtio_queue_get_used_size (vdev, idx)); -vhost_memory_unmap (dev, &vq->avail,virtio_queue_get_avail_size (vdev, idx), -0 ,virtio_queue_get_avail_size (vdev, idx)); -vhost_memory_unmap (dev, &vq->desc,virtio_queue_get_desc_size (vdev, idx), -0 ,virtio_queue_get_desc_size (vdev, idx)); +vhost_memory_unmap (dev, &vq->used, vq->used_size,1 , vq->used_size); +vhost_memory_unmap (dev, &vq->avail, vq->avail_size,0 , vq->avail_size); +vhost_memory_unmap (dev, &vq->desc, vq->desc_size,0 , vq->desc_size);return r; }
Signature · 1 line
MST
[PULL 064/106] amd_iommu: Reject non-decreasing NextLevel in fetch_pte()
In reply to Michael S. TsirkinFrom: Alejandro Jimenez <[email protected]>
The AMD-Vi specification requires that the NextLevel field for a page table entry must not be greater or equal to the current page table entry level. Enforce this to avoid infinite page walk loops on corrupted or buggy guest page tables.
The initial implementation of fetch_pte() did not implement this check, but was not vulnerable since the page walk code explicitly decremented the level instead of retrieving it from the page table entry.
Message-Id: <[email protected]>
--- hw/i386/amd_iommu.c | 4 ++++ 1 file changed, 4 insertions(+)
hw/i386/amd_iommu.c +4 -0
@@ -771,6 +771,10 @@ static uint64_t fetch_pte(AMDVIAddressSpace *as, hwaddr address, uint64_t dte,break ; } +/* Next level must always be less than current level */ +if (pt_level <= next_pt_level) { +return -AMDVI_FR_PT_ENTRY_INV ; + } pt_level = next_pt_level;/*
Signature · 1 line
MST
[PULL 026/106] tests: data: update x86 ACPI tables
In reply to Michael S. TsirkinFrom: Mark Cave-Ayland <[email protected]>
Update the x86 ACPI tables to reflect the IRQ descriptor changes for ISA serial ports:
Device (COM1)
{
Name (_HID, EisaId ("PNP0501") /* 16550A-compatible COM Serial Port */) // _HID: Hardware ID
Name (_UID, One) // _UID: Unique ID
Name (_STA, 0x0F) // _STA: Status
Name (_CRS, ResourceTemplate () // _CRS: Current Resource Settings
{
IO (Decode16,
0x03F8, // Range Minimum
0x03F8, // Range Maximum
0x00, // Alignment
0x08, // Length
)
- IRQNoFlags ()
+ IRQ (Level, ActiveLow, Shared, )
{4}
})
}Message-Id: <[email protected]>
--- tests/data/acpi/x86/microvm/DSDT | Bin 365 -> 366 bytes tests/data/acpi/x86/microvm/DSDT.ioapic2 | Bin 365 -> 366 bytes tests/data/acpi/x86/microvm/DSDT.pcie | Bin 2985 -> 2986 bytes tests/data/acpi/x86/microvm/DSDT.rtc | Bin 404 -> 405 bytes tests/data/acpi/x86/microvm/DSDT.usb | Bin 414 -> 415 bytes tests/data/acpi/x86/pc/DSDT | Bin 8598 -> 8599 bytes tests/data/acpi/x86/pc/DSDT.acpierst | Bin 8509 -> 8510 bytes tests/data/acpi/x86/pc/DSDT.acpihmat | Bin 9923 -> 9924 bytes tests/data/acpi/x86/pc/DSDT.bridge | Bin 15469 -> 15470 bytes tests/data/acpi/x86/pc/DSDT.cphp | Bin 9062 -> 9063 bytes tests/data/acpi/x86/pc/DSDT.dimmpxm | Bin 10252 -> 10253 bytes tests/data/acpi/x86/pc/DSDT.hpbridge | Bin 8549 -> 8550 bytes tests/data/acpi/x86/pc/DSDT.hpbrroot | Bin 5087 -> 5088 bytes tests/data/acpi/x86/pc/DSDT.ipmikcs | Bin 8670 -> 8671 bytes tests/data/acpi/x86/pc/DSDT.memhp | Bin 9957 -> 9958 bytes tests/data/acpi/x86/pc/DSDT.nohpet | Bin 8456 -> 8457 bytes tests/data/acpi/x86/pc/DSDT.numamem | Bin 8604 -> 8605 bytes tests/data/acpi/x86/pc/DSDT.roothp | Bin 12391 -> 12392 bytes tests/data/acpi/x86/q35/DSDT | Bin 8427 -> 8428 bytes tests/data/acpi/x86/q35/DSDT.acpierst | Bin 8444 -> 8445 bytes tests/data/acpi/x86/q35/DSDT.acpihmat | Bin 9752 -> 9753 bytes .../data/acpi/x86/q35/DSDT.acpihmat-generic-x | Bin 12637 -> 12638 bytes .../acpi/x86/q35/DSDT.acpihmat-noinitiator | Bin 8706 -> 8707 bytes tests/data/acpi/x86/q35/DSDT.applesmc | Bin 8473 -> 8474 bytes tests/data/acpi/x86/q35/DSDT.bridge | Bin 12040 -> 12041 bytes tests/data/acpi/x86/q35/DSDT.core-count | Bin 12985 -> 12986 bytes tests/data/acpi/x86/q35/DSDT.core-count2 | Bin 33842 -> 33843 bytes tests/data/acpi/x86/q35/DSDT.cphp | Bin 8891 -> 8892 bytes tests/data/acpi/x86/q35/DSDT.cxl | Bin 13218 -> 13219 bytes tests/data/acpi/x86/q35/DSDT.dimmpxm | Bin 10081 -> 10082 bytes tests/data/acpi/x86/q35/DSDT.ipmibt | Bin 8502 -> 8503 bytes tests/data/acpi/x86/q35/DSDT.ipmismbus | Bin 8515 -> 8516 bytes tests/data/acpi/x86/q35/DSDT.ivrs | Bin 8444 -> 8445 bytes tests/data/acpi/x86/q35/DSDT.memhp | Bin 9786 -> 9787 bytes tests/data/acpi/x86/q35/DSDT.mmio64 | Bin 9557 -> 9558 bytes tests/data/acpi/x86/q35/DSDT.multi-bridge | Bin 13280 -> 13281 bytes tests/data/acpi/x86/q35/DSDT.noacpihp | Bin 8289 -> 8290 bytes tests/data/acpi/x86/q35/DSDT.nohpet | Bin 8285 -> 8286 bytes tests/data/acpi/x86/q35/DSDT.numamem | Bin 8433 -> 8434 bytes tests/data/acpi/x86/q35/DSDT.pvpanic-isa | Bin 8528 -> 8529 bytes tests/data/acpi/x86/q35/DSDT.thread-count | Bin 12985 -> 12986 bytes tests/data/acpi/x86/q35/DSDT.thread-count2 | Bin 33842 -> 33843 bytes tests/data/acpi/x86/q35/DSDT.tis.tpm12 | Bin 9033 -> 9034 bytes tests/data/acpi/x86/q35/DSDT.tis.tpm2 | Bin 9059 -> 9060 bytes tests/data/acpi/x86/q35/DSDT.type4-count | Bin 18661 -> 18662 bytes tests/data/acpi/x86/q35/DSDT.viot | Bin 14684 -> 14685 bytes tests/data/acpi/x86/q35/DSDT.xapic | Bin 35790 -> 35791 bytes tests/qtest/bios-tables-test-allowed-diff.h | 47 ------------------ 48 files changed, 47 deletions(-)
tests/data/acpi/x86/microvm/DSDT binary +0 -0
tests/data/acpi/x86/microvm/DSDT.ioapic2 binary +0 -0
tests/data/acpi/x86/microvm/DSDT.pcie binary +0 -0
tests/data/acpi/x86/microvm/DSDT.rtc binary +0 -0
tests/data/acpi/x86/microvm/DSDT.usb binary +0 -0
tests/data/acpi/x86/pc/DSDT binary +0 -0
tests/data/acpi/x86/pc/DSDT.acpierst binary +0 -0
tests/data/acpi/x86/pc/DSDT.acpihmat binary +0 -0
tests/data/acpi/x86/pc/DSDT.bridge binary +0 -0
tests/data/acpi/x86/pc/DSDT.cphp binary +0 -0
tests/data/acpi/x86/pc/DSDT.dimmpxm binary +0 -0
tests/data/acpi/x86/pc/DSDT.hpbridge binary +0 -0
tests/data/acpi/x86/pc/DSDT.hpbrroot binary +0 -0
tests/data/acpi/x86/pc/DSDT.ipmikcs binary +0 -0
tests/data/acpi/x86/pc/DSDT.memhp binary +0 -0
tests/data/acpi/x86/pc/DSDT.nohpet binary +0 -0
tests/data/acpi/x86/pc/DSDT.numamem binary +0 -0
tests/data/acpi/x86/pc/DSDT.roothp binary +0 -0
tests/data/acpi/x86/q35/DSDT binary +0 -0
tests/data/acpi/x86/q35/DSDT.acpierst binary +0 -0
tests/data/acpi/x86/q35/DSDT.acpihmat binary +0 -0
tests/data/acpi/x86/q35/DSDT.acpihmat-generic-x binary +0 -0
tests/data/acpi/x86/q35/DSDT.acpihmat-noinitiator binary +0 -0
tests/data/acpi/x86/q35/DSDT.applesmc binary +0 -0
tests/data/acpi/x86/q35/DSDT.bridge binary +0 -0
tests/data/acpi/x86/q35/DSDT.core-count binary +0 -0
tests/data/acpi/x86/q35/DSDT.core-count2 binary +0 -0
tests/data/acpi/x86/q35/DSDT.cphp binary +0 -0
tests/data/acpi/x86/q35/DSDT.cxl binary +0 -0
tests/data/acpi/x86/q35/DSDT.dimmpxm binary +0 -0
tests/data/acpi/x86/q35/DSDT.ipmibt binary +0 -0
tests/data/acpi/x86/q35/DSDT.ipmismbus binary +0 -0
tests/data/acpi/x86/q35/DSDT.ivrs binary +0 -0
tests/data/acpi/x86/q35/DSDT.memhp binary +0 -0
tests/data/acpi/x86/q35/DSDT.mmio64 binary +0 -0
tests/data/acpi/x86/q35/DSDT.multi-bridge binary +0 -0
tests/data/acpi/x86/q35/DSDT.noacpihp binary +0 -0
tests/data/acpi/x86/q35/DSDT.nohpet binary +0 -0
tests/data/acpi/x86/q35/DSDT.numamem binary +0 -0
tests/data/acpi/x86/q35/DSDT.pvpanic-isa binary +0 -0
tests/data/acpi/x86/q35/DSDT.thread-count binary +0 -0
tests/data/acpi/x86/q35/DSDT.thread-count2 binary +0 -0
tests/data/acpi/x86/q35/DSDT.tis.tpm12 binary +0 -0
tests/data/acpi/x86/q35/DSDT.tis.tpm2 binary +0 -0
tests/data/acpi/x86/q35/DSDT.type4-count binary +0 -0
tests/data/acpi/x86/q35/DSDT.viot binary +0 -0
tests/data/acpi/x86/q35/DSDT.xapic binary +0 -0
tests/qtest/bios-tables-test-allowed-diff.h +0 -47
48 lines not on this page · raw message
Signature · 1 line
MST
[PULL 007/106] iommufd: Extend attach/detach_hwpt callbacks to support pasid
In reply to Michael S. TsirkinFrom: Zhenzhong Duan <[email protected]>
Same for the two wrappers and their call sites.
Message-Id: <[email protected]>
--- backends/iommufd.c | 23 ++++++++++++----------- hw/arm/smmuv3-accel.c | 12 ++++++++---- hw/i386/intel_iommu_accel.c | 19 ++++++++++--------- hw/vfio/iommufd.c | 22 +++++++++++----------- include/system/iommufd.h | 18 ++++++++++++------ 5 files changed, 53 insertions(+), 41 deletions(-)
backends/iommufd.c +12 -11
@@ -539,23 +539,24 @@ bool iommufd_backend_alloc_veventq(IOMMUFDBackend *be, uint32_t viommu_id, }bool host_iommu_device_iommufd_attach_hwpt (HostIOMMUDeviceIOMMUFD *hiodi, -uint32_t hwpt_id,Error **errp) -{ -HostIOMMUDeviceIOMMUFDClass *hiodic = -HOST_IOMMU_DEVICE_IOMMUFD_GET_CLASS (hiodi); - -g_assert (hiodic->attach_hwpt); -return hiodic->attach_hwpt (hiodi, hwpt_id, errp); -} - -bool host_iommu_device_iommufd_detach_hwpt (HostIOMMUDeviceIOMMUFD *hiodi, +uint32_t pasid,uint32_t hwpt_id,Error **errp) {HostIOMMUDeviceIOMMUFDClass *hiodic =HOST_IOMMU_DEVICE_IOMMUFD_GET_CLASS (hiodi); +g_assert (hiodic->attach_hwpt); +return hiodic->attach_hwpt (hiodi, pasid, hwpt_id, errp); +} + +bool host_iommu_device_iommufd_detach_hwpt (HostIOMMUDeviceIOMMUFD *hiodi, +uint32_t pasid,Error **errp) +{ +HostIOMMUDeviceIOMMUFDClass *hiodic = +HOST_IOMMU_DEVICE_IOMMUFD_GET_CLASS (hiodi); +g_assert (hiodic->detach_hwpt); -return hiodic->detach_hwpt (hiodi, errp); +return hiodic->detach_hwpt (hiodi, pasid, errp); }static int hiod_iommufd_get_cap (HostIOMMUDevice *hiod,int cap,Error **errp)
hw/arm/smmuv3-accel.c +8 -4
@@ -300,7 +300,8 @@ bool smmuv3_accel_install_ste(SMMUv3State *s, SMMUDevice *sdev, int sid,return false; } -if (!host_iommu_device_iommufd_attach_hwpt (hiodi, hwpt_id, errp)) { +if (!host_iommu_device_iommufd_attach_hwpt (hiodi,IOMMU_NO_PASID , hwpt_id, + errp)) {if (s1_hwpt) {iommufd_backend_free_id (hiodi->iommufd, s1_hwpt->hwpt_id);g_free (s1_hwpt);
@@ -575,7 +576,8 @@ smmuv3_accel_alloc_viommu(SMMUv3State *s, HostIOMMUDeviceIOMMUFD *hiodi,/* Attach a HWPT based on SMMUv3 GBPA.ABORT value */ hwpt_id =smmuv3_accel_gbpa_hwpt (s, accel); -if (!host_iommu_device_iommufd_attach_hwpt (hiodi, hwpt_id, errp)) { +if (!host_iommu_device_iommufd_attach_hwpt (hiodi,IOMMU_NO_PASID , hwpt_id, + errp)) { goto free_veventq; }return true;
@@ -665,7 +667,8 @@ static void smmuv3_accel_unset_iommu_device(PCIBus *bus, void *opaque, hiodi = accel_dev->hiodi; accel = accel_dev->s_accel;/* Re-attach the default s2 hwpt id */ -if (!host_iommu_device_iommufd_attach_hwpt (hiodi, hiodi->hwpt_id,NULL )) { +if (!host_iommu_device_iommufd_attach_hwpt (hiodi,IOMMU_NO_PASID , + hiodi->hwpt_id,NULL )) {error_report ("Unable to attach the default HW pagetable: hiodi devid " "0x%x" , hiodi->devid); }
@@ -879,7 +882,8 @@ bool smmuv3_accel_attach_gbpa_hwpt(SMMUv3State *s, Error **errp) hwpt_id =smmuv3_accel_gbpa_hwpt (s, accel); QLIST_FOREACH(accel_dev, &accel->device_list, next) { -if (!host_iommu_device_iommufd_attach_hwpt (accel_dev->hiodi, hwpt_id, +if (!host_iommu_device_iommufd_attach_hwpt (accel_dev->hiodi, +IOMMU_NO_PASID , hwpt_id, &local_err)) { error_append_hint(&local_err, "Failed to attach GBPA hwpt %u for " "hiodi devid %u", hwpt_id,
hw/i386/intel_iommu_accel.c +10 -9
@@ -121,8 +121,9 @@ static bool vtd_device_attach_iommufd(VTDHostIOMMUDevice *vtd_hiod, } } - ret =host_iommu_device_iommufd_attach_hwpt (hiodi, hwpt_id, errp); -trace_vtd_device_attach_hwpt (hiodi->devid, vtd_as->pasid, hwpt_id, ret); + ret =host_iommu_device_iommufd_attach_hwpt (hiodi,IOMMU_NO_PASID , hwpt_id, + errp); +trace_vtd_device_attach_hwpt (hiodi->devid,IOMMU_NO_PASID , hwpt_id, ret);if (ret) {/* Destroy old fs_hwpt if it's a replacement */ vtd_destroy_old_fs_hwpt (hiodi, vtd_as);
@@ -141,22 +142,22 @@ static bool vtd_device_detach_iommufd(VTDHostIOMMUDevice *vtd_hiod, {HostIOMMUDeviceIOMMUFD *hiodi =HOST_IOMMU_DEVICE_IOMMUFD (vtd_hiod->hiod);IntelIOMMUState *s = vtd_as->iommu_state; -uint32_t pasid = vtd_as->pasid;bool ret;if (s->dmar_enabled && s->root_scalable) { - ret =host_iommu_device_iommufd_detach_hwpt (hiodi, errp); -trace_vtd_device_detach_hwpt (hiodi->devid, pasid, ret); + ret =host_iommu_device_iommufd_detach_hwpt (hiodi,IOMMU_NO_PASID , + errp); +trace_vtd_device_detach_hwpt (hiodi->devid,IOMMU_NO_PASID , ret); }else {/* * If DMAR remapping is disabled or guest switches to legacy mode, * we fallback to the default HWPT which contains shadow page table. * So guest DMA could still work. */ - ret =host_iommu_device_iommufd_attach_hwpt (hiodi, hiodi->hwpt_id, - errp); -trace_vtd_device_reattach_def_hwpt (hiodi->devid, pasid, hiodi->hwpt_id, - ret); + ret =host_iommu_device_iommufd_attach_hwpt (hiodi,IOMMU_NO_PASID , + hiodi->hwpt_id, errp); +trace_vtd_device_reattach_def_hwpt (hiodi->devid,IOMMU_NO_PASID , + hiodi->hwpt_id, ret); }if (ret) {
hw/vfio/iommufd.c +11 -11
@@ -934,21 +934,21 @@ static void vfio_iommu_iommufd_class_init(ObjectClass *klass, const void *data)static bool host_iommu_device_iommufd_vfio_attach_hwpt (HostIOMMUDeviceIOMMUFD *hiodi, -uint32_t hwpt_id,Error **errp) -{ -VFIODevice *vbasedev =HOST_IOMMU_DEVICE (hiodi)->agent; - -return !iommufd_cdev_pasid_attach_ioas_hwpt (vbasedev,IOMMU_NO_PASID , - hwpt_id, errp); -} - -static bool -host_iommu_device_iommufd_vfio_detach_hwpt (HostIOMMUDeviceIOMMUFD *hiodi, +uint32_t pasid,uint32_t hwpt_id,Error **errp) {VFIODevice *vbasedev =HOST_IOMMU_DEVICE (hiodi)->agent; -return iommufd_cdev_pasid_detach_ioas_hwpt (vbasedev,IOMMU_NO_PASID , errp); +return !iommufd_cdev_pasid_attach_ioas_hwpt (vbasedev, pasid, hwpt_id, errp); +} + +static bool +host_iommu_device_iommufd_vfio_detach_hwpt (HostIOMMUDeviceIOMMUFD *hiodi, +uint32_t pasid,Error **errp) +{ +VFIODevice *vbasedev =HOST_IOMMU_DEVICE (hiodi)->agent; + +return iommufd_cdev_pasid_detach_ioas_hwpt (vbasedev, pasid, errp); } static bool hiod_iommufd_vfio_realize(HostIOMMUDevice *hiod, void *opaque,
include/system/iommufd.h +12 -6
@@ -138,14 +138,16 @@ struct HostIOMMUDeviceIOMMUFDClass {* * @hiodi: host IOMMU device backed by IOMMUFD backend. * +* @pasid: target pasid of the device to be attached. +* * @hwpt_id: ID of IOMMUFD hardware page table. * * @errp: pass an Error out when attachment fails. * * Returns: true on success, false on failure. */ -bool (*attach_hwpt)(HostIOMMUDeviceIOMMUFD *hiodi,uint32_t hwpt_id, -Error **errp); +bool (*attach_hwpt)(HostIOMMUDeviceIOMMUFD *hiodi,uint32_t pasid, +uint32_t hwpt_id,Error **errp);/** * @detach_hwpt: detach host IOMMU device from IOMMUFD hardware page table. * VFIO and VDPA device can have different implementation.
@@ -154,15 +156,19 @@ struct HostIOMMUDeviceIOMMUFDClass {* * @hiodi: host IOMMU device backed by IOMMUFD backend. * -* @errp: pass an Error out when attachment fails. +* @pasid: target pasid of the device to be detached. +* +* @errp: pass an Error out when detachment fails. * * Returns: true on success, false on failure. */ - bool (*detach_hwpt)(HostIOMMUDeviceIOMMUFD *hiodi, Error **errp); +bool (*detach_hwpt)(HostIOMMUDeviceIOMMUFD *hiodi,uint32_t pasid, + Error **errp); };bool host_iommu_device_iommufd_attach_hwpt (HostIOMMUDeviceIOMMUFD *hiodi, -uint32_t hwpt_id,Error **errp); -bool host_iommu_device_iommufd_detach_hwpt (HostIOMMUDeviceIOMMUFD *hiodi, +uint32_t pasid,uint32_t hwpt_id,Error **errp); +bool host_iommu_device_iommufd_detach_hwpt (HostIOMMUDeviceIOMMUFD *hiodi, +uint32_t pasid,Error **errp);#endif
Signature · 1 line
MST
[PULL 024/106] tests/acpi: allow DSDT acpi table changes
In reply to Michael S. TsirkinFrom: Mark Cave-Ayland <[email protected]>
Message-Id: <[email protected]>
--- tests/qtest/bios-tables-test-allowed-diff.h | 47 +++++++++++++++++++++ 1 file changed, 47 insertions(+)
tests/qtest/bios-tables-test-allowed-diff.h +47 -0
@@ -1 +1,48 @@/* List of comma-separated changed AML files to ignore */ +"tests/data/acpi/x86/pc/DSDT" , +"tests/data/acpi/x86/pc/DSDT.bridge" , +"tests/data/acpi/x86/pc/DSDT.ipmikcs" , +"tests/data/acpi/x86/pc/DSDT.cphp" , +"tests/data/acpi/x86/pc/DSDT.numamem" , +"tests/data/acpi/x86/pc/DSDT.nohpet" , +"tests/data/acpi/x86/pc/DSDT.memhp" , +"tests/data/acpi/x86/pc/DSDT.dimmpxm" , +"tests/data/acpi/x86/pc/DSDT.acpihmat" , +"tests/data/acpi/x86/pc/DSDT.acpierst" , +"tests/data/acpi/x86/pc/DSDT.roothp" , +"tests/data/acpi/x86/pc/DSDT.hpbridge" , +"tests/data/acpi/x86/pc/DSDT.hpbrroot" , +"tests/data/acpi/x86/q35/DSDT" , +"tests/data/acpi/x86/q35/DSDT.tis.tpm2" , +"tests/data/acpi/x86/q35/DSDT.tis.tpm12" , +"tests/data/acpi/x86/q35/DSDT.bridge" , +"tests/data/acpi/x86/q35/DSDT.noacpihp" , +"tests/data/acpi/x86/q35/DSDT.multi-bridge" , +"tests/data/acpi/x86/q35/DSDT.ipmibt" , +"tests/data/acpi/x86/q35/DSDT.cphp" , +"tests/data/acpi/x86/q35/DSDT.numamem" , +"tests/data/acpi/x86/q35/DSDT.nohpet" , +"tests/data/acpi/x86/q35/DSDT.acpihmat-noinitiator" , +"tests/data/acpi/x86/q35/DSDT.acpihmat-generic-x" , +"tests/data/acpi/x86/q35/DSDT.memhp" , +"tests/data/acpi/x86/q35/DSDT.dimmpxm" , +"tests/data/acpi/x86/q35/DSDT.acpihmat" , +"tests/data/acpi/x86/q35/DSDT.mmio64" , +"tests/data/acpi/x86/q35/DSDT.acpierst" , +"tests/data/acpi/x86/q35/DSDT.applesmc" , +"tests/data/acpi/x86/q35/DSDT.pvpanic-isa" , +"tests/data/acpi/x86/q35/DSDT.ivrs" , +"tests/data/acpi/x86/q35/DSDT.type4-count" , +"tests/data/acpi/x86/q35/DSDT.core-count" , +"tests/data/acpi/x86/q35/DSDT.core-count2" , +"tests/data/acpi/x86/q35/DSDT.thread-count" , +"tests/data/acpi/x86/q35/DSDT.thread-count2" , +"tests/data/acpi/x86/q35/DSDT.viot" , +"tests/data/acpi/x86/q35/DSDT.cxl" , +"tests/data/acpi/x86/q35/DSDT.ipmismbus" , +"tests/data/acpi/x86/q35/DSDT.xapic" , +"tests/data/acpi/x86/microvm/DSDT" , +"tests/data/acpi/x86/microvm/DSDT.usb" , +"tests/data/acpi/x86/microvm/DSDT.rtc" , +"tests/data/acpi/x86/microvm/DSDT.ioapic2" , +"tests/data/acpi/x86/microvm/DSDT.pcie",
Signature · 1 line
MST
[PULL 048/106] vhost: add some useful trace-points
In reply to Michael S. TsirkinFrom: Vladimir Sementsov-Ogievskiy <[email protected]>
Message-Id: <[email protected]>
--- hw/virtio/trace-events | 12 ++++++++++-- hw/virtio/vhost.c | 20 ++++++++++++++++++-- 2 files changed, 28 insertions(+), 4 deletions(-)
hw/virtio/trace-events +10 -2
@@ -9,8 +9,16 @@ 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, bool vrings) "%p:%s vrings:%d" -vhost_dev_stop(void *dev, const char *name, bool vrings) "%p:%s vrings:%d" +vhost_dev_start_in(void *dev, const char *name, bool vrings) "%p:%s vrings:%d" +vhost_dev_start_out(void *dev, const char *name) "%p:%s" +vhost_dev_stop_in(void *dev, const char *name, bool vrings) "%p:%s vrings:%d" +vhost_dev_stop_out(void *dev, const char *name) "%p:%s" +vhost_virtqueue_start_in(void *dev, const char *name, int idx) "%p:%s %d" +vhost_virtqueue_start_out(void *dev, const char *name, int idx) "%p:%s %d" +vhost_virtqueue_stop_in(void *dev, const char *name, int idx) "%p:%s %d" +vhost_virtqueue_stop_out(void *dev, const char *name, int idx) "%p:%s %d" +vhost_dev_init_in(void *dev) "%p" +vhost_dev_init_out(void *dev) "%p" # vhost-user.c
hw/virtio/vhost.c +18 -2
@@ -1337,6 +1337,8 @@ int vhost_virtqueue_start(struct vhost_dev *dev, };struct VirtQueue *vvq =virtio_get_queue (vdev, idx); +trace_vhost_virtqueue_start_in (dev, vdev->name, idx); + r =vhost_vrings_map (dev, vdev, vq, idx);if (r <=0 ) {return r;
@@ -1397,6 +1399,8 @@ int vhost_virtqueue_start(struct vhost_dev *dev, } } +trace_vhost_virtqueue_start_out (dev, vdev->name, idx); +return 0 ; fail:
@@ -1415,6 +1419,8 @@ static int do_vhost_virtqueue_stop(struct vhost_dev *dev, };int r =0 ; +trace_vhost_virtqueue_stop_in (dev, vdev->name, idx); +if (virtio_queue_get_desc_addr (vdev, idx) ==0 ) {/* Don't stop the virtqueue which might have not been started */ return 0 ;
@@ -1448,6 +1454,8 @@ static int do_vhost_virtqueue_stop(struct vhost_dev *dev, }vhost_vrings_unmap (dev, vq, true); + +trace_vhost_virtqueue_stop_out (dev, vdev->name, idx);return r; }
@@ -1581,6 +1589,8 @@ int vhost_dev_init(struct vhost_dev *hdev, void *opaque,unsigned int used, reserved, limit;int i, r, n_initialized_vqs =0 ; +trace_vhost_dev_init_in (hdev); + hdev->vdev =NULL ; hdev->migration_blocker =NULL ;
@@ -1694,6 +1704,8 @@ int vhost_dev_init(struct vhost_dev *hdev, void *opaque, goto fail; } +trace_vhost_dev_init_out (hdev); +return 0 ; fail:
@@ -2098,7 +2110,7 @@ int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev, bool vrings)/* should only be called after backend is connected */ assert (hdev->vhost_ops); -trace_vhost_dev_start (hdev, vdev->name, vrings); +trace_vhost_dev_start_in (hdev, vdev->name, vrings); vdev->vhost_started = true; hdev->started = true;
@@ -2183,6 +2195,8 @@ int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev, bool vrings) } }vhost_start_config_intr (hdev); + +trace_vhost_dev_start_out (hdev, vdev->name);return 0 ; fail_iotlb: if (vhost_dev_has_iommu(hdev) &&
@@ -2232,7 +2246,7 @@ static int do_vhost_dev_stop(struct vhost_dev *hdev, VirtIODevice *vdev,event_notifier_cleanup ( &hdev->vqs[VHOST_QUEUE_NUM_CONFIG_INR ].masked_config_notifier); -trace_vhost_dev_stop (hdev, vdev->name, vrings); +trace_vhost_dev_stop_in (hdev, vdev->name, vrings);if (hdev->vhost_ops->vhost_dev_start) { hdev->vhost_ops->vhost_dev_start (hdev, false);
@@ -2262,6 +2276,8 @@ static int do_vhost_dev_stop(struct vhost_dev *hdev, VirtIODevice *vdev, hdev->started = false; vdev->vhost_started = false; hdev->vdev =NULL ; + +trace_vhost_dev_stop_out (hdev, vdev->name);return rc; }
Signature · 1 line
MST
[PULL 087/106] x86: q35: generate WDAT ACPI table
In reply to Michael S. TsirkinFrom: Igor Mammedov <[email protected]>
It will generate WDAT table [1] customized for TCO watchdog. This allows Windows guests (Windows Server 2008/Vista+) to use TCO watchdog using built-in generic driver, which alleviates need to install vendor specific drivers.
Given that enabling it might change guest behaviour (both Windows/Linux) the feature is disabled by default.
Users that need it can enable the feature with
following CLI option.
-machine wdat=on
1)
"Hardware Watchdog Timers Design Specification"
https://uefi.org/acpi 'Watchdog Action Table (WDAT)'
Message-Id: <[email protected]>
--- hw/acpi/meson.build | 3 +- hw/acpi/wdat-ich9-stub.c | 15 +++++++ hw/acpi/wdat-ich9.c | 90 +++++++++++++++++++++++++++++++++++++ hw/i386/acpi-build.c | 12 +++++ include/hw/acpi/wdat-ich9.h | 15 +++++++ 5 files changed, 134 insertions(+), 1 deletion(-) create mode 100644 hw/acpi/wdat-ich9-stub.c create mode 100644 hw/acpi/wdat-ich9.c create mode 100644 include/hw/acpi/wdat-ich9.h
hw/acpi/meson.build +2 -1
@@ -25,7 +25,8 @@ acpi_ss.add(when: 'CONFIG_ACPI_PCI_BRIDGE', if_true: files('pci-bridge.c')) acpi_ss.add(when: 'CONFIG_ACPI_PCIHP', if_true: files('pcihp.c')) stub_ss.add(files('acpi-pci-hotplug-stub.c')) acpi_ss.add(when: 'CONFIG_ACPI_VIOT', if_true: files('viot.c')) -acpi_ss.add(when: 'CONFIG_ACPI_ICH9', if_true: files('ich9.c', 'ich9_tco.c', 'ich9_timer.c')) +acpi_ss.add(when: 'CONFIG_ACPI_ICH9', if_true: files('ich9.c', 'ich9_tco.c', 'ich9_timer.c', 'wdat-ich9.c')) +stub_ss.add(files('wdat-ich9-stub.c')) acpi_ss.add(when: 'CONFIG_ACPI_ERST', if_true: files('erst.c')) acpi_ss.add(when: 'CONFIG_IPMI', if_true: files('ipmi.c')) stub_ss.add(files('ipmi-stub.c'))
hw/acpi/wdat-ich9-stub.c new file +15 -0
@@ -0,0 +1,15 @@ +/* +* Copyright Red Hat, Inc. 2026 +* Author(s): Igor Mammedov <[email protected]> +* +* SPDX-License-Identifier: GPL-2.0-or-later +*/ + +#include "qemu/osdep.h" +#include "hw/acpi/wdat-ich9.h" + +void build_ich9_wdat (GArray *table_data,BIOSLinker *linker,const char *oem_id, +const char *oem_table_id,uint64_t tco_base) +{ +g_assert_not_reached (); +}
hw/acpi/wdat-ich9.c new file +90 -0
90 lines not on this page · raw message
hw/i386/acpi-build.c +12 -0
@@ -78,6 +78,7 @@#include "hw/acpi/hmat.h" #include "hw/acpi/viot.h" +#include "hw/acpi/wdat-ich9.h" #include CONFIG_DEVICES
@@ -110,6 +111,7 @@ typedef struct AcpiPmInfo {uint16_t cpu_hp_io_base;uint16_t pcihp_io_base;uint16_t pcihp_io_len; +uint64_t tco_io_base; } AcpiPmInfo; typedef struct AcpiMiscInfo {
@@ -204,6 +206,7 @@ static void acpi_get_pm_info(MachineState *machine, AcpiPmInfo *pm) pm->pcihp_io_len =0 ; pm->smi_on_cpuhp = false; pm->smi_on_cpu_unplug = false; + pm->tco_io_base =0 ;assert (obj);init_common_fadt_data (machine, obj, &pm->fadt);
@@ -225,6 +228,8 @@ static void acpi_get_pm_info(MachineState *machine, AcpiPmInfo *pm) !!(smi_features &BIT_ULL (ICH9_LPC_SMI_F_CPU_HOTPLUG_BIT )); pm->smi_on_cpu_unplug = !!(smi_features &BIT_ULL (ICH9_LPC_SMI_F_CPU_HOT_UNPLUG_BIT )); + pm->tco_io_base =object_property_get_uint (obj,ACPI_PM_PROP_PM_IO_BASE , +NULL ) +ICH9_PMIO_TCO_RLD ; } pm->pcihp_io_base =object_property_get_uint (obj,ACPI_PCIHP_IO_BASE_PROP ,NULL );
@@ -2078,6 +2083,13 @@ void acpi_build(AcpiBuildTables *tables, MachineState *machine)acpi_add_table (table_offsets, tables_blob);build_waet (tables_blob, tables->linker, x86ms->oem_id, x86ms->oem_table_id); +if (pcms->wdat_enabled == true) { +g_assert (pm.tco_io_base); +acpi_add_table (table_offsets, tables_blob); +build_ich9_wdat (tables_blob, tables->linker, x86ms->oem_id, + x86ms->oem_table_id, pm.tco_io_base); + } +/* Add tables supplied by user (if any) */ for (u =acpi_table_first (); u; u =acpi_table_next (u)) {unsigned len =acpi_table_len (u);
include/hw/acpi/wdat-ich9.h new file +15 -0
@@ -0,0 +1,15 @@ +/* +* Copyright Red Hat, Inc. 2026 +* Author(s): Igor Mammedov <[email protected]> +* +* SPDX-License-Identifier: GPL-2.0-or-later +*/ +#ifndef QEMU_HW_ACPI_WDAT_ICH9_H +#define QEMU_HW_ACPI_WDAT_ICH9_H + +#include "hw/acpi/aml-build.h" + +void build_ich9_wdat (GArray *table_data,BIOSLinker *linker,const char *oem_id, +const char *oem_table_id,uint64_t tco_base); + +#endif /* QEMU_HW_ACPI_WDAT_ICH9_H */
Signature · 1 line
MST
[PULL 077/106] vhost: add in_order feature to shadow virtqueue
In reply to Michael S. TsirkinFrom: Eugenio Pérez <[email protected]>
Some vdpa devices benefit from the in order feature. Add support to SVQ so QEMU can migrate these.
Message-Id: <[email protected]>
--- hw/virtio/vhost-shadow-virtqueue.c | 137 +++++++++++++++++++++++++++-- hw/virtio/vhost-shadow-virtqueue.h | 36 ++++++-- 2 files changed, 160 insertions(+), 13 deletions(-)
hw/virtio/vhost-shadow-virtqueue.c +130 -7
@@ -12,11 +12,14 @@#include "qemu/error-report.h" #include "qapi/error.h" +#include "qemu/iov.h" #include "qemu/main-loop.h" #include "qemu/log.h" #include "qemu/memalign.h" #include "linux-headers/linux/vhost.h" +#define VIRTIO_RING_NOT_IN_BATCH UINT16_MAX +/** * Validate the transport device features that both guests can use with the SVQ * and SVQs can use with the device.
@@ -150,7 +153,33 @@ static bool vhost_svq_translate_addr(const VhostShadowVirtqueue *svq,static uint16_t vhost_svq_next_desc (const VhostShadowVirtqueue *svq,uint16_t id) { -return svq->desc_state[id].next; +if (virtio_vdev_has_feature (svq->vdev,VIRTIO_F_IN_ORDER )) { +return (id == svq->vring.num) ?0 : ++id; + }else { +return svq->desc_state[id].next; + } +} + +/** +* Updates the SVQ free_head member after adding them to the SVQ avail ring. +* The new free_head is the next descriptor that SVQ will make available by +* forwarding a new guest descriptor. +* +* @svq Shadow Virtqueue +* @num Number of descriptors added +* @id ID of the last descriptor added to the SVQ avail ring. +*/ +static void vhost_svq_update_free_head (VhostShadowVirtqueue *svq, +size_t num,uint16_t id) +{ +if (virtio_vdev_has_feature (svq->vdev,VIRTIO_F_IN_ORDER )) { + svq->free_head += num; +if (svq->free_head >= svq->vring.num) { + svq->free_head -= svq->vring.num; + } + }else { + svq->free_head =vhost_svq_next_desc (svq, id); + } }/**
@@ -202,7 +231,7 @@ static bool vhost_svq_vring_write_descs(VhostShadowVirtqueue *svq, hwaddr *sg, i = next; } - svq->free_head =vhost_svq_next_desc (svq, last); +vhost_svq_update_free_head (svq, num, last);return true; }
@@ -306,6 +335,9 @@ int vhost_svq_add(VhostShadowVirtqueue *svq, const struct iovec *out_sg, svq->num_free -= ndescs; svq->desc_state[qemu_head].elem = elem; svq->desc_state[qemu_head].ndescs = ndescs; +if (virtio_vdev_has_feature (svq->vdev,VIRTIO_F_IN_ORDER )) { + svq->desc_state[qemu_head].in_bytes =iov_size (in_sg, in_num); + }vhost_svq_kick (svq);return 0 ; }
@@ -401,6 +433,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 (virtio_vdev_has_feature (svq->vdev,VIRTIO_F_IN_ORDER ) && + svq->batch_last.id !=VIRTIO_RING_NOT_IN_BATCH ) { +return true; + } +if (svq->last_used_idx != svq->shadow_used_idx) {return true; }
@@ -463,6 +501,47 @@ static uint16_t vhost_svq_get_last_used_split(VhostShadowVirtqueue *svq,return le32_to_cpu (used->ring[last_used].id); } +/* +* Gets the next buffer id and moves forward the used idx, so the next time +* SVQ calls this function will get the next one. IN_ORDER version +* +* @svq: Shadow VirtQueue +* @len: Consumed length by the device. +* +* Return the next descriptor consumed by the device. +*/ +static int32_t vhost_svq_get_last_used_split_in_order ( +VhostShadowVirtqueue *svq, +uint32_t *len) +{ +unsigned num = svq->vring.num; +const vring_used_t *used = svq->vring.used; +uint16_t last_used = svq->last_used & (num -1 ); +uint16_t last_used_idx = svq->last_used_idx & (num -1 ); + +if (svq->batch_last.id ==VIRTIO_RING_NOT_IN_BATCH ) { + svq->batch_last.id =le32_to_cpu (used->ring[last_used_idx].id); + svq->batch_last.len =le32_to_cpu (used->ring[last_used_idx].len); + } + +if (unlikely (last_used >= num)) { +qemu_log_mask (LOG_GUEST_ERROR ,"Device %s says index %u is used" , + svq->vdev->name, last_used); +return -1 ; + } + +if (svq->batch_last.id == last_used) { + svq->batch_last.id =VIRTIO_RING_NOT_IN_BATCH ; + *len = svq->batch_last.len; + }else { + *len = svq->desc_state[last_used].in_bytes; + } + + svq->last_used += svq->desc_state[last_used].ndescs; + svq->last_used_idx++; +return last_used; +} +static uint16_t vhost_svq_last_desc_of_chain (const VhostShadowVirtqueue *svq,uint16_t num,uint16_t i) {
@@ -474,8 +553,8 @@ static uint16_t vhost_svq_last_desc_of_chain(const VhostShadowVirtqueue *svq, }G_GNUC_WARN_UNUSED_RESULT -static VirtQueueElement *vhost_svq_detach_buf(VhostShadowVirtqueue *svq, -uint16_t id) +static VirtQueueElement *vhost_svq_detach_buf_split(VhostShadowVirtqueue *svq, +uint16_t id) {uint16_t num = svq->desc_state[id].ndescs;uint16_t last_used_chain =vhost_svq_last_desc_of_chain (svq, num, id);
@@ -486,6 +565,33 @@ static VirtQueueElement *vhost_svq_detach_buf(VhostShadowVirtqueue *svq,return g_steal_pointer (&svq->desc_state[id].elem); } +G_GNUC_WARN_UNUSED_RESULT +static VirtQueueElement *vhost_svq_detach_buf_split_in_order( +VhostShadowVirtqueue *svq, +uint16_t id) +{ +return g_steal_pointer (&svq->desc_state[id].elem); +} + +/* +* Return the descriptor id (and the chain of ids) to the free list +* +* @svq: Shadow Virtqueue +* @id: Id of the buffer to return. +* +* Return the element associated to the buffer if any. +*/ +G_GNUC_WARN_UNUSED_RESULT +static VirtQueueElement *vhost_svq_detach_buf(VhostShadowVirtqueue *svq, +uint16_t id) +{ +if (virtio_vdev_has_feature (svq->vdev,VIRTIO_F_IN_ORDER )) { +return vhost_svq_detach_buf_split_in_order (svq, id); + }else { +return vhost_svq_detach_buf_split (svq, id); + } +} +G_GNUC_WARN_UNUSED_RESULT static VirtQueueElement *vhost_svq_get_buf(VhostShadowVirtqueue *svq, uint32_t *len)
@@ -498,7 +604,18 @@ static VirtQueueElement *vhost_svq_get_buf(VhostShadowVirtqueue *svq,/* Only get used array entries after they have been exposed by dev */ smp_rmb (); - last_used =vhost_svq_get_last_used_split (svq, len); + +if (virtio_vdev_has_feature (svq->vdev,VIRTIO_F_IN_ORDER )) { +int32_t r; + r =vhost_svq_get_last_used_split_in_order (svq, len); +if (r <0 ) { +return NULL ; + } + + last_used = r; + }else { + last_used =vhost_svq_get_last_used_split (svq, len); + }if (unlikely (last_used >= svq->vring.num)) { qemu_log_mask(LOG_GUEST_ERROR, "Device %s says index %u is used",
@@ -726,6 +843,8 @@ void vhost_svq_start(VhostShadowVirtqueue *svq, VirtIODevice *vdev, svq->next_guest_avail_elem =NULL ; svq->shadow_avail_idx =0 ; svq->shadow_used_idx =0 ; +memset (&svq->batch_last,0 ,sizeof (svq->batch_last)); + svq->last_used =0 ; svq->last_used_idx =0 ; svq->vdev = vdev; svq->vq = vq;
@@ -742,8 +861,12 @@ void vhost_svq_start(VhostShadowVirtqueue *svq, VirtIODevice *vdev,PROT_READ |PROT_WRITE ,MAP_SHARED |MAP_ANONYMOUS , -1, 0); svq->desc_state =g_new0 (SVQDescState, svq->vring.num); -for (unsigned i =0 ; i < svq->vring.num -1 ; i++) { - svq->desc_state[i].next = i +1 ; +if (virtio_vdev_has_feature (svq->vdev,VIRTIO_F_IN_ORDER )) { + svq->batch_last.id =VIRTIO_RING_NOT_IN_BATCH ; + }else { +for (unsigned i =0 ; i < svq->vring.num -1 ; i++) { + svq->desc_state[i].next = i +1 ; + } } }
hw/virtio/vhost-shadow-virtqueue.h +30 -6
@@ -24,11 +24,19 @@ typedef struct SVQDescState {*/ unsigned int ndescs; -/* -* Backup next field for each descriptor so we can recover securely, not -* needing to trust the device access. -*/ -uint16_t next; +union { +/* +* Total length of the available buffer that is writable by the device. +* Only used in packed vq. +*/ +uint32_t in_bytes; + +/* +* Backup next field for each descriptor so we can recover securely, not +* needing to trust the device access. Only used in split vq. +*/ +uint16_t next; + }; } SVQDescState;typedef struct VhostShadowVirtqueue VhostShadowVirtqueue ;
@@ -99,9 +107,25 @@ typedef struct VhostShadowVirtqueue {/* Next head to expose to the device */ uint16_t shadow_avail_idx; -/* Next free descriptor */ +/* +* Next free descriptor. +* +* Without IN_ORDER free_head is used as a linked list head, and +* desc_next[id] is the next element. +* With IN_ORDER free_head is the next available buffer index. +*/ uint16_t free_head; +/* +* Last used element of the processing batch of used descriptors if +* IN_ORDER. +* If SVQ is not processing a batch of descriptors id is set to UINT_MAX. +*/ +vring_used_elem_t batch_last; + +/* Last used id if IN_ORDER and split vq */ +uint16_t last_used; +/* Last seen used idx */ uint16_t shadow_used_idx;
Signature · 1 line
MST
[PULL 031/106] vhost-user-gpu: drop code duplication
In reply to Michael S. TsirkinFrom: Vladimir Sementsov-Ogievskiy <[email protected]>
Obviously, this duplicated fragment doesn't make any sense.
Message-Id: <[email protected]>
--- hw/display/vhost-user-gpu.c | 4 ---- 1 file changed, 4 deletions(-)
hw/display/vhost-user-gpu.c +0 -4
@@ -644,10 +644,6 @@ vhost_user_gpu_device_realize(DeviceState *qdev, Error **errp) VIRTIO_GPU_F_RESOURCE_UUID)) { g->parent_obj.conf.flags |=1 <<VIRTIO_GPU_FLAG_RESOURCE_UUID_ENABLED ; } -if (virtio_has_feature (g->vhost->dev.features, -VIRTIO_GPU_F_RESOURCE_UUID )) { - g->parent_obj.conf.flags |=1 <<VIRTIO_GPU_FLAG_RESOURCE_UUID_ENABLED ; - }if (!virtio_gpu_base_device_realize (qdev,NULL ,NULL , errp)) {return ;
Signature · 1 line
MST
[PULL 035/106] vhost-user: keep QIOChannelSocket for backend channel
In reply to Michael S. TsirkinFrom: Vladimir Sementsov-Ogievskiy <[email protected]>
Keep QIOChannelSocket pointer instead of more generic QIOChannel. No real difference for now, but it would be simpler to migrate socket fd in further commit.
Message-Id: <[email protected]>
--- hw/virtio/vhost-user.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-)
hw/virtio/vhost-user.c +10 -11
@@ -239,7 +239,7 @@ struct vhost_user {struct vhost_dev *dev;/* Shared between vhost devs of the same virtio device */ VhostUserState *user; -QIOChannel *backend_ioc; +QIOChannelSocket *backend_sioc;GSource *backend_src;NotifierWithReturn postcopy_notifier;struct PostCopyFD postcopy_fd;
@@ -1796,8 +1796,8 @@ static void close_backend_channel(struct vhost_user *u)g_source_destroy (u->backend_src);g_source_unref (u->backend_src); u->backend_src =NULL ; -object_unref (OBJECT (u->backend_ioc)); - u->backend_ioc =NULL ; +object_unref (OBJECT (u->backend_sioc)); + u->backend_sioc =NULL ; } static gboolean backend_read(QIOChannel *ioc, GIOCondition condition,
@@ -1909,7 +1909,6 @@ static int vhost_setup_backend_channel(struct vhost_dev *dev)bool reply_supported =vhost_user_has_protocol_feature (dev,VHOST_USER_PROTOCOL_F_REPLY_ACK );Error *local_err =NULL ; -QIOChannel *ioc;if (!vhost_user_has_protocol_feature ( dev,VHOST_USER_PROTOCOL_F_BACKEND_REQ )) {
@@ -1922,15 +1921,15 @@ static int vhost_setup_backend_channel(struct vhost_dev *dev)return -saved_errno; } - ioc =QIO_CHANNEL (qio_channel_socket_new_fd (sv[0 ], &local_err)); -if (!ioc) { + u->backend_sioc =qio_channel_socket_new_fd (sv[0 ], &local_err); +if (!u->backend_sioc) {error_report_err (local_err);return -ECONNREFUSED ; } - u->backend_ioc = ioc; - u->backend_src =qio_channel_add_watch_source (u->backend_ioc, -G_IO_IN |G_IO_HUP , - backend_read, dev,NULL ,NULL ); + u->backend_src =qio_channel_add_watch_source (QIO_CHANNEL (u->backend_sioc), +G_IO_IN |G_IO_HUP , + backend_read, dev, +NULL ,NULL );if (reply_supported) { msg.hdr.flags |=VHOST_USER_NEED_REPLY_MASK ;
@@ -2350,7 +2349,7 @@ static int vhost_user_backend_cleanup(struct vhost_dev *dev)close (u->postcopy_fd.fd); u->postcopy_fd.handler =NULL ; } -if (u->backend_ioc) { +if (u->backend_sioc) {close_backend_channel (u); }g_free (u->region_rb);
Signature · 1 line
MST
[PULL 083/106] virtio-rtc: Add basic virtio-rtc support
In reply to Michael S. TsirkinFrom: Kuan-Wei Chiu <[email protected]>
Introduce the core device and PCI bindings for the virtio-rtc device (VIRTIO_ID_CLOCK).
This implementation provides a read-only clock that returns the host's time (QEMU_CLOCK_HOST) to the guest. It handles fundamental control requests, reporting a single supported clock of type VIRTIO_RTC_CLOCK_UTC, and responds to standard read requests.
- Virtio RTC Spec:
https://github.com/oasis-tcs/virtio-spec/tree/master/device-types/rtc
- Linux Virtio RTC driver:
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/virtio/virtio_rtc_driver.c?h=v7.0-rc1
Message-Id: <[email protected]>
--- MAINTAINERS | 7 ++ hw/virtio/Kconfig | 5 + hw/virtio/meson.build | 2 + hw/virtio/virtio-rtc-pci.c | 65 +++++++++++ hw/virtio/virtio-rtc.c | 190 +++++++++++++++++++++++++++++++++ include/hw/virtio/virtio-rtc.h | 22 ++++ 6 files changed, 291 insertions(+) create mode 100644 hw/virtio/virtio-rtc-pci.c create mode 100644 hw/virtio/virtio-rtc.c create mode 100644 include/hw/virtio/virtio-rtc.h
MAINTAINERS +7 -0
@@ -2527,6 +2527,13 @@ F: include/system/rng*.h F: backends/rng*.c F: tests/qtest/virtio-rng-test.c +virtio-rtc +M: Kuan-Wei Chiu <[email protected]> +S: Maintained +F: hw/virtio/virtio-rtc.c +F: hw/virtio/virtio-rtc-pci.c +F: include/hw/virtio/virtio-rtc.h + virtio-nsm M: Alexander Graf <[email protected]> M: Dorjoy Chowdhury <[email protected]>
hw/virtio/Kconfig +5 -0
@@ -76,6 +76,11 @@ config VIRTIO_MEM depends on VIRTIO_MEM_SUPPORTED select VIRTIO_MD +config VIRTIO_RTC + bool + default y + depends on VIRTIO + config VHOST_VSOCK_COMMON bool depends on VIRTIO
hw/virtio/meson.build +2 -0
@@ -54,6 +54,7 @@ if have_vhost endif system_virtio_ss.add(when: 'CONFIG_VHOST_USER_VSOCK', if_true: files('vhost-user-vsock.c')) system_virtio_ss.add(when: 'CONFIG_VIRTIO_RNG', if_true: files('virtio-rng.c')) +system_virtio_ss.add(when: 'CONFIG_VIRTIO_RTC', if_true: files('virtio-rtc.c')) system_virtio_ss.add(when: 'CONFIG_VIRTIO_BALLOON', if_true: files('virtio-balloon.c')) system_virtio_ss.add(when: 'CONFIG_VHOST_USER_FS', if_true: files('vhost-user-fs.c'))
@@ -77,6 +78,7 @@ virtio_pci_ss.add(when: 'CONFIG_VIRTIO_CRYPTO', if_true: files('virtio-crypto-pc virtio_pci_ss.add(when: 'CONFIG_VIRTIO_INPUT_HOST', if_true: files('virtio-input-host-pci.c')) virtio_pci_ss.add(when: 'CONFIG_VIRTIO_INPUT', if_true: files('virtio-input-pci.c')) virtio_pci_ss.add(when: 'CONFIG_VIRTIO_RNG', if_true: files('virtio-rng-pci.c')) +virtio_pci_ss.add(when: 'CONFIG_VIRTIO_RTC', if_true: files('virtio-rtc-pci.c')) virtio_pci_ss.add(when: 'CONFIG_VIRTIO_NSM', if_true: [files('virtio-nsm-pci.c', 'cbor-helpers.c'), libcbor]) virtio_pci_ss.add(when: 'CONFIG_VIRTIO_BALLOON', if_true: files('virtio-balloon-pci.c')) virtio_pci_ss.add(when: 'CONFIG_VIRTIO_9P', if_true: files('virtio-9p-pci.c'))
hw/virtio/virtio-rtc-pci.c new file +65 -0
65 lines not on this page · raw message
hw/virtio/virtio-rtc.c new file +190 -0
190 lines not on this page · raw message
include/hw/virtio/virtio-rtc.h new file +22 -0
@@ -0,0 +1,22 @@ +/* +* Virtio RTC device +* +* Copyright (c) 2026 Kuan-Wei Chiu <[email protected]> +* SPDX-License-Identifier: GPL-2.0-or-later +*/ + +#ifndef QEMU_VIRTIO_RTC_H +#define QEMU_VIRTIO_RTC_H + +#include "hw/virtio/virtio.h" +#include "qom/object.h" + +#define TYPE_VIRTIO_RTC "virtio-rtc-device" +OBJECT_DECLARE_SIMPLE_TYPE(VirtIORtc, VIRTIO_RTC) + +struct VirtIORtc { +VirtIODevice parent_obj; +VirtQueue *vq; +}; + +#endif
Signature · 1 line
MST
[PULL 074/106] vhost: factor out the descriptor next fetching
In reply to Michael S. TsirkinFrom: Eugenio Pérez <[email protected]>
The next field will not be used if IN_ORDER is enabled.
Message-Id: <[email protected]>
--- hw/virtio/vhost-shadow-virtqueue.c | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-)
hw/virtio/vhost-shadow-virtqueue.c +20 -4
@@ -139,6 +139,20 @@ static bool vhost_svq_translate_addr(const VhostShadowVirtqueue *svq,return true; } +/** +* Get the next descriptor in the chain in SVQ vring from a descriptor id +* +* @svq Shadow Virtqueue +* @id ID of the descriptor +* +* Return the id of the next descriptor. +*/ +static uint16_t vhost_svq_next_desc (const VhostShadowVirtqueue *svq, +uint16_t id) +{ +return svq->desc_state[id].next; +} +/** * Write descriptors to SVQ vring *
@@ -173,9 +187,11 @@ static bool vhost_svq_vring_write_descs(VhostShadowVirtqueue *svq, hwaddr *sg, }for (n =0 ; n < num; n++) { +uint16_t next =vhost_svq_next_desc (svq, i); +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_state[i].next); + descs[i].next =cpu_to_le16 (next); }else { descs[i].flags = flags; }
@@ -183,10 +199,10 @@ static bool vhost_svq_vring_write_descs(VhostShadowVirtqueue *svq, hwaddr *sg, descs[i].len =cpu_to_le32 (iovec[n].iov_len); last = i; - i = svq->desc_state[i].next; + i = next; } - svq->free_head = svq->desc_state[last].next; + svq->free_head =vhost_svq_next_desc (svq, last);return true; }
@@ -432,7 +448,7 @@ 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 = svq->desc_state[i].next; + i =vhost_svq_next_desc (svq, i); }return i;
Signature · 1 line
MST
[PULL 094/106] vhost_user: Add frontend get_shmem_config command
In reply to Michael S. TsirkinFrom: Albert Esteve <[email protected]>
The frontend can use this command to retrieve VirtIO Shared Memory Regions configuration from the backend. The response contains the number of shared memory regions, their size, and shmid.
This is useful when the frontend is unaware of specific backend type and configuration,
for example, in the vhost-user-device case.
Message-Id: <[email protected]>
--- include/hw/virtio/vhost-backend.h | 10 ++++++++++ include/hw/virtio/vhost-user.h | 1 + include/hw/virtio/virtio.h | 2 ++ subprojects/libvhost-user/libvhost-user.h | 4 +++- 4 files changed, 16 insertions(+), 1 deletion(-)
include/hw/virtio/vhost-backend.h +10 -0
@@ -162,6 +162,15 @@ typedef int (*vhost_set_device_state_fd_op)(struct vhost_dev *dev,int *reply_fd, Error **errp);typedef int (*vhost_check_device_state_op )(struct vhost_dev *dev,Error **errp); +/* +* Max regions is VIRTIO_MAX_SHMEM_REGIONS, so that is the maximum +* number of memory_sizes that will be accepted. +*/ +typedef int (*vhost_get_shmem_config_op )(struct vhost_dev *dev, +int *nregions, +uint64_t *memory_sizes, +Error **errp); + typedef struct VhostOps { VhostBackendType backend_type;
@@ -220,6 +229,7 @@ typedef struct VhostOps {vhost_supports_device_state_op vhost_supports_device_state;vhost_set_device_state_fd_op vhost_set_device_state_fd;vhost_check_device_state_op vhost_check_device_state; +vhost_get_shmem_config_op vhost_get_shmem_config; } VhostOps;int vhost_user_gpu_set_socket (struct vhost_dev *dev,int fd);
include/hw/virtio/vhost-user.h +1 -0
@@ -35,6 +35,7 @@ enum VhostUserProtocolFeature {VHOST_USER_PROTOCOL_F_DEVICE_STATE =19 ,VHOST_USER_PROTOCOL_F_GET_VRING_BASE_INFLIGHT =20 ,VHOST_USER_PROTOCOL_F_GPA_ADDRESSES =21 , +VHOST_USER_PROTOCOL_F_SHMEM =22 , VHOST_USER_PROTOCOL_F_MAX };
include/hw/virtio/virtio.h +2 -0
@@ -82,6 +82,8 @@ typedef struct VirtQueueElement#define VIRTIO_NO_VECTOR 0xffff +#define VIRTIO_MAX_SHMEM_REGIONS 256 +/* special index value used internally for config irqs */ #define VIRTIO_CONFIG_IRQ_IDX -1
subprojects/libvhost-user/libvhost-user.h +3 -1
@@ -70,7 +70,9 @@ enum VhostUserProtocolFeature {/* Feature 17 reserved for VHOST_USER_PROTOCOL_F_XEN_MMAP. */ VHOST_USER_PROTOCOL_F_SHARED_OBJECT =18 ,/* Feature 19 is reserved for VHOST_USER_PROTOCOL_F_DEVICE_STATE */ -VHOST_USER_PROTOCOL_F_SHMEM =20 , +/* Feature 20 is reserved for VHOST_USER_PROTOCOL_F_GET_VRING_BASE_INFLIGHT */ +/* Feature 21 is reserved for VHOST_USER_PROTOCOL_F_GPA_ADDRESSES */ +VHOST_USER_PROTOCOL_F_SHMEM =22 , VHOST_USER_PROTOCOL_F_MAX };
Signature · 1 line
MST
[PULL 066/106] vhost-user-blk: do not force VIRTIO_BLK_F_SIZE_MAX
In reply to Michael S. TsirkinFrom: Max Makarov <[email protected]>
vhost_user_blk_get_features() unconditionally advertises VIRTIO_BLK_F_SIZE_MAX regardless of what the backend reports in its config. The built-in QSD vhost-user-blk backend sets size_max=0, creating a contradictory state where the feature bit tells the guest that size_max is valid but the value is zero.
The in-process virtio-blk device does not advertise VIRTIO_BLK_F_SIZE_MAX (it also sets size_max=0 in config), so guests never see this contradiction with native virtio-blk.
Linux tolerates size_max=0 because blk_validate_limits() silently corrects max_segment_size=0 to BLK_MAX_SEGMENT_SIZE (65536). Windows viostor, however, trusts the feature bit and uses the raw size_max=0 in its scatter-gather calculations, producing zero-length segments that hang I/O. The disk appears empty to Windows (no GPT, no partitions), causing INACCESSIBLE_BOOT_DEVICE.
Stop force-adding VIRTIO_BLK_F_SIZE_MAX in the frontend. The feature remains in user_feature_bits[], so backends that properly advertise it with a valid config value will still work.
Message-Id: <[email protected]>
--- hw/block/vhost-user-blk.c | 1 - 1 file changed, 1 deletion(-)
hw/block/vhost-user-blk.c +0 -1
@@ -283,7 +283,6 @@ static uint64_t vhost_user_blk_get_features(VirtIODevice *vdev,VHostUserBlk *s =VHOST_USER_BLK (vdev);/* Turn on pre-defined features */ -virtio_add_feature (&features,VIRTIO_BLK_F_SIZE_MAX );virtio_add_feature (&features,VIRTIO_BLK_F_SEG_MAX );virtio_add_feature (&features,VIRTIO_BLK_F_GEOMETRY );virtio_add_feature (&features,VIRTIO_BLK_F_TOPOLOGY );
Signature · 1 line
MST
[PULL 093/106] vhost_user.rst: Add SHMEM_MAP/_UNMAP to spec
In reply to Michael S. TsirkinFrom: Albert Esteve <[email protected]>
Add SHMEM_MAP/_UNMAP request to the vhost-user
spec documentation.
Message-Id: <[email protected]>
--- docs/interop/vhost-user.rst | 64 +++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+)
docs/interop/vhost-user.rst +64 -0
@@ -362,6 +362,28 @@ Device state transfer parameters In the future, additional phases might be added e.g. to allow iterative migration while the device is running. +MMAP request +^^^^^^^^^^^^ + ++-------+---------+-----------+------------+-----+-------+ +| shmid | padding | fd_offset | shm_offset | len | flags | ++-------+---------+-----------+------------+-----+-------+ + +:shmid: a 8-bit shared memory region identifier + +:fd_offset: a 64-bit offset of this area from the start + of the supplied file descriptor + +:shm_offset: a 64-bit offset from the start of the + pointed shared memory region + +:len: a 64-bit size of the memory to map + +:flags: a 64-bit value: + + - 0: Pages are mapped read-only + - 1: Pages are mapped read-write + C structure -----------
@@ -387,6 +409,7 @@ In QEMU the vhost-user message is implemented with the following struct: VhostUserInflight inflight; VhostUserShared object; VhostUserTransferDeviceState transfer_state; + VhostUserMMap mmap; }; } QEMU_PACKED VhostUserMsg;
@@ -1083,6 +1106,7 @@ Protocol features #define VHOST_USER_PROTOCOL_F_DEVICE_STATE 19 #define VHOST_USER_PROTOCOL_F_GET_VRING_BASE_INFLIGHT 20 #define VHOST_USER_PROTOCOL_F_GPA_ADDRESSES 21 + #define VHOST_USER_PROTOCOL_F_SHMEM_MAP 22 Front-end message types -----------------------
@@ -1904,6 +1928,46 @@ is sent by the front-end. when the operation is successful, or non-zero otherwise. Note that if the operation fails, no fd is sent to the backend. +``VHOST_USER_BACKEND_SHMEM_MAP`` + :id: 9 + :equivalent ioctl: N/A + :request payload: fd and ``struct VhostUserMMap`` + :reply payload: N/A + + When the ``VHOST_USER_PROTOCOL_F_SHMEM`` protocol feature has been + successfully negotiated, this message can be submitted by the backends to + advertise a new mapping to be made in a given VIRTIO Shared Memory Region. + Upon receiving the message, the front-end will mmap the given fd into the + VIRTIO Shared Memory Region with the requested ``shmid``. + + If ``VHOST_USER_PROTOCOL_F_REPLY_ACK`` is negotiated, and + back-end set the ``VHOST_USER_NEED_REPLY`` flag, the front-end + must respond with zero when operation is successfully completed, + or non-zero otherwise. + + Mapping over an already existing map is not allowed and requests shall fail. + Therefore, the memory range in the request must correspond with a valid, + free region of the VIRTIO Shared Memory Region. Also, note that mappings + consume resources and that the request can fail when there are no resources + available. Lastly, mappings are automatically unmapped by the front-end + across device reset operation. + +``VHOST_USER_BACKEND_SHMEM_UNMAP`` + :id: 10 + :equivalent ioctl: N/A + :request payload: ``struct VhostUserMMap`` + :reply payload: N/A + + When the ``VHOST_USER_PROTOCOL_F_SHMEM`` protocol feature has been + successfully negotiated, this message can be submitted by the backends so + that the front-end un-mmaps a given range (``shm_offset``, ``len``) in the + VIRTIO Shared Memory Region with the requested ``shmid``. Note that the + given range shall correspond to the entirety of a valid mapped region. + + If ``VHOST_USER_PROTOCOL_F_REPLY_ACK`` is negotiated, and the back-end + sets the ``VHOST_USER_NEED_REPLY`` flag, the front-end must respond with + zero when operation is successfully completed, or non-zero otherwise. + .. _reply_ack: VHOST_USER_PROTOCOL_F_REPLY_ACK
Signature · 1 line
MST
[PULL 075/106] vhost: factor out the get of last used desc in SVQ
In reply to Michael S. TsirkinFrom: Eugenio Pérez <[email protected]>
This code path is modified to handle in order devices. Abstract here so we can generalize on the caller.
Message-Id: <[email protected]>
--- hw/virtio/vhost-shadow-virtqueue.c | 45 +++++++++++++++++++----------- 1 file changed, 29 insertions(+), 16 deletions(-)
hw/virtio/vhost-shadow-virtqueue.c +29 -16
@@ -444,6 +444,25 @@ static void vhost_svq_disable_notification(VhostShadowVirtqueue *svq) } } +/* +* Gets the next buffer id and moves forward the used idx, so the next time +* SVQ calls this function will get the next one. +* +* @svq: Shadow VirtQueue +* @len: Consumed length by the device. +* +* Return the next descriptor consumed by the device. +*/ +static uint16_t vhost_svq_get_last_used_split (VhostShadowVirtqueue *svq, +uint32_t *len) +{ +const vring_used_t *used = svq->vring.used; +uint16_t last_used = svq->last_used_idx++ & (svq->vring.num -1 ); + + *len =le32_to_cpu (used->ring[last_used].len); +return le32_to_cpu (used->ring[last_used].id); +} +static uint16_t vhost_svq_last_desc_of_chain (const VhostShadowVirtqueue *svq,uint16_t num,uint16_t i) {
@@ -458,8 +477,6 @@ G_GNUC_WARN_UNUSED_RESULTstatic 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, last_used_chain, num;if (!vhost_svq_more_used (svq)) {
@@ -468,33 +485,29 @@ static VirtQueueElement *vhost_svq_get_buf(VhostShadowVirtqueue *svq,/* 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); + last_used =vhost_svq_get_last_used_split (svq, len); - svq->last_used_idx++; -if (unlikely (used_elem.id >= svq->vring.num)) { +if (unlikely (last_used >= svq->vring.num)) {qemu_log_mask (LOG_GUEST_ERROR ,"Device %s says index %u is used" , - svq->vdev->name, used_elem.id); + svq->vdev->name, last_used);return NULL ; } -if (unlikely (!svq->desc_state[used_elem.id].ndescs)) { +if (unlikely (!svq->desc_state[last_used].ndescs)) {qemu_log_mask (LOG_GUEST_ERROR ,"Device %s says index %u is used, but it was not available" , - svq->vdev->name, used_elem.id); + svq->vdev->name, last_used);return NULL ; } - num = svq->desc_state[used_elem.id].ndescs; - svq->desc_state[used_elem.id].ndescs =0 ; - last_used_chain =vhost_svq_last_desc_of_chain (svq, num, used_elem.id); + num = svq->desc_state[last_used].ndescs; + svq->desc_state[last_used].ndescs =0 ; + last_used_chain =vhost_svq_last_desc_of_chain (svq, num, last_used); svq->desc_state[last_used_chain].next = svq->free_head; - svq->free_head = used_elem.id; + svq->free_head = last_used; svq->num_free += num; - *len = used_elem.len; -return g_steal_pointer (&svq->desc_state[used_elem.id].elem); +return g_steal_pointer (&svq->desc_state[last_used].elem); }/**
Signature · 1 line
MST
[PULL 079/106] amd_iommu: Use switch case to determine mmio register name
In reply to Michael S. TsirkinFrom: Sairaj Kodilkar <[email protected]>
This makes it easier to add new MMIO registers for tracing and removes the unnecessary complexity introduced by amdvi_mmio_(low/high) array.
Message-Id: <[email protected]>
--- hw/i386/amd_iommu.c | 74 ++++++++++++++++----------------------------- hw/i386/amd_iommu.h | 4 --- 2 files changed, 26 insertions(+), 52 deletions(-)
hw/i386/amd_iommu.c +26 -48
@@ -35,29 +35,6 @@#include "kvm/kvm_i386.h" #include "qemu/iova-tree.h" -/* used AMD-Vi MMIO registers */ -const char *amdvi_mmio_low[] = { -"AMDVI_MMIO_DEVTAB_BASE" , -"AMDVI_MMIO_CMDBUF_BASE" , -"AMDVI_MMIO_EVTLOG_BASE" , -"AMDVI_MMIO_CONTROL" , -"AMDVI_MMIO_EXCL_BASE" , -"AMDVI_MMIO_EXCL_LIMIT" , -"AMDVI_MMIO_EXT_FEATURES" , -"AMDVI_MMIO_PPR_BASE" , -"UNHANDLED" -}; -const char *amdvi_mmio_high[] = { -"AMDVI_MMIO_COMMAND_HEAD" , -"AMDVI_MMIO_COMMAND_TAIL" , -"AMDVI_MMIO_EVTLOG_HEAD" , -"AMDVI_MMIO_EVTLOG_TAIL" , -"AMDVI_MMIO_STATUS" , -"AMDVI_MMIO_PPR_HEAD" , -"AMDVI_MMIO_PPR_TAIL" , -"UNHANDLED" -}; -struct AMDVIAddressSpace {PCIBus *bus;/* PCIBus (for bus number) */ uint8_t devfn;/* device function */
@@ -1540,31 +1517,31 @@ static void amdvi_cmdbuf_run(AMDVIState *s) } } -static inline uint8_t amdvi_mmio_get_index (hwaddr addr) +static inline +const char *amdvi_mmio_get_name (hwaddr addr) { -uint8_t index = (addr & ~0x2000 ) /8 ; - -if ((addr &0x2000 )) { -/* high table */ - index = index >=AMDVI_MMIO_REGS_HIGH ?AMDVI_MMIO_REGS_HIGH : index; - }else { - index = index >=AMDVI_MMIO_REGS_LOW ?AMDVI_MMIO_REGS_LOW : index; +/* Return MMIO names as string literals */ +switch (addr) { +#define MMIO_REG_TO_STRING (mmio_reg) case mmio_reg: return #mmio_reg +MMIO_REG_TO_STRING (AMDVI_MMIO_DEVICE_TABLE ); +MMIO_REG_TO_STRING (AMDVI_MMIO_COMMAND_BASE ); +MMIO_REG_TO_STRING (AMDVI_MMIO_EVENT_BASE ); +MMIO_REG_TO_STRING (AMDVI_MMIO_CONTROL ); +MMIO_REG_TO_STRING (AMDVI_MMIO_EXCL_BASE ); +MMIO_REG_TO_STRING (AMDVI_MMIO_EXCL_LIMIT ); +MMIO_REG_TO_STRING (AMDVI_MMIO_EXT_FEATURES ); +MMIO_REG_TO_STRING (AMDVI_MMIO_COMMAND_HEAD ); +MMIO_REG_TO_STRING (AMDVI_MMIO_COMMAND_TAIL ); +MMIO_REG_TO_STRING (AMDVI_MMIO_EVENT_HEAD ); +MMIO_REG_TO_STRING (AMDVI_MMIO_EVENT_TAIL ); +MMIO_REG_TO_STRING (AMDVI_MMIO_STATUS ); +MMIO_REG_TO_STRING (AMDVI_MMIO_PPR_BASE ); +MMIO_REG_TO_STRING (AMDVI_MMIO_PPR_HEAD ); +MMIO_REG_TO_STRING (AMDVI_MMIO_PPR_TAIL ); +#undef MMIO_REG_TO_STRING +default : +return "UNHANDLED" ; } - -return index; -} - -static void amdvi_mmio_trace_read (hwaddr addr,unsigned size) -{ -uint8_t index =amdvi_mmio_get_index (addr); -trace_amdvi_mmio_read (amdvi_mmio_low[index], addr, size, addr & ~0x07 ); -} - -static void amdvi_mmio_trace_write (hwaddr addr,unsigned size,uint64_t val) -{ -uint8_t index =amdvi_mmio_get_index (addr); -trace_amdvi_mmio_write (amdvi_mmio_low[index], addr, size, val, - addr & ~0x07 ); }static uint64_t amdvi_mmio_read (void *opaque,hwaddr addr,unsigned size)
@@ -1584,7 +1561,7 @@ static uint64_t amdvi_mmio_read(void *opaque, hwaddr addr, unsigned size) }else if (size ==8 ) { val =amdvi_readq (s, addr); } -amdvi_mmio_trace_read (addr, size); +trace_amdvi_mmio_read (amdvi_mmio_get_name (addr), addr, size, addr & ~0x07 );return val; }
@@ -1742,7 +1719,8 @@ static void amdvi_mmio_write(void *opaque, hwaddr addr, uint64_t val,return ; } -amdvi_mmio_trace_write (addr, size, val); +trace_amdvi_mmio_write (amdvi_mmio_get_name (addr), addr, size, val, offset); +switch (addr & ~0x07 ) {case AMDVI_MMIO_CONTROL :amdvi_mmio_reg_write (s, size, val, addr);
hw/i386/amd_iommu.h +0 -4
@@ -45,10 +45,6 @@#define AMDVI_CAPAB_FLAG_IOTLBSUP (1 << 24)#define AMDVI_CAPAB_INIT_TYPE (3 << 16) -/* No. of used MMIO registers */ -#define AMDVI_MMIO_REGS_HIGH 7 -#define AMDVI_MMIO_REGS_LOW 8 -/* MMIO registers */ #define AMDVI_MMIO_DEVICE_TABLE 0x0000#define AMDVI_MMIO_COMMAND_BASE 0x0008
Signature · 1 line
MST
[PULL 032/106] vhost: make vhost_dev.features private
In reply to Michael S. TsirkinFrom: Vladimir Sementsov-Ogievskiy <[email protected]>
It's hard to control where and how do we use this field. Let's cover all usages by getters/setters, and keep direct access to the field only in vhost.c. It will help to control migration of this field in further commits.
Message-Id: <[email protected]>
--- hw/display/vhost-user-gpu.c | 7 +++---- hw/net/vhost_net.c | 18 ++++++++--------- hw/virtio/vdpa-dev.c | 2 +- hw/virtio/vhost-user-base.c | 8 ++++++-- hw/virtio/vhost-user.c | 4 ++-- hw/virtio/vhost.c | 6 +++--- hw/virtio/virtio-qmp.c | 2 +- include/hw/virtio/vhost.h | 39 +++++++++++++++++++++++++++++++++++-- net/vhost-vdpa.c | 7 +++---- 9 files changed, 65 insertions(+), 28 deletions(-)
hw/display/vhost-user-gpu.c +3 -4
@@ -631,17 +631,16 @@ vhost_user_gpu_device_realize(DeviceState *qdev, Error **errp)/* existing backend may send DMABUF, so let's add that requirement */ g->parent_obj.conf.flags |=1 <<VIRTIO_GPU_FLAG_DMABUF_ENABLED ; -if (virtio_has_feature (g->vhost->dev.features,VIRTIO_GPU_F_VIRGL )) { +if (vhost_dev_has_feature (&g->vhost->dev,VIRTIO_GPU_F_VIRGL )) { g->parent_obj.conf.flags |=1 <<VIRTIO_GPU_FLAG_VIRGL_ENABLED ; } -if (virtio_has_feature (g->vhost->dev.features,VIRTIO_GPU_F_EDID )) { +if (vhost_dev_has_feature (&g->vhost->dev,VIRTIO_GPU_F_EDID )) { g->parent_obj.conf.flags |=1 <<VIRTIO_GPU_FLAG_EDID_ENABLED ; }else {error_report ("EDID requested but the backend doesn't support it." ); g->parent_obj.conf.flags &= ~(1 <<VIRTIO_GPU_FLAG_EDID_ENABLED ); } -if (virtio_has_feature (g->vhost->dev.features, -VIRTIO_GPU_F_RESOURCE_UUID )) { +if (vhost_dev_has_feature (&g->vhost->dev,VIRTIO_GPU_F_RESOURCE_UUID )) { g->parent_obj.conf.flags |=1 <<VIRTIO_GPU_FLAG_RESOURCE_UUID_ENABLED ; }
hw/net/vhost_net.c +9 -9
@@ -54,8 +54,8 @@ void vhost_net_ack_features_ex(struct vhost_net *net, const uint64_t *features) {virtio_features_clear (net->dev.acked_features_ex);if (net->backend ==-1 ) { - net->dev.acked_features = - net->dev.features & (1ULL <<VHOST_USER_F_PROTOCOL_FEATURES ); + net->dev.acked_features = (vhost_dev_features (&net->dev) & + (1ULL <<VHOST_USER_F_PROTOCOL_FEATURES )); }else if (!qemu_has_vnet_hdr (net->nc)) { net->dev.acked_features =1ULL <<VHOST_NET_F_VIRTIO_NET_HDR ; }
@@ -282,15 +282,15 @@ struct vhost_net *vhost_net_init(VhostNetOptions *options)if (backend_kernel) {if (!qemu_has_vnet_hdr_len (options->net_backend,sizeof (struct virtio_net_hdr_mrg_rxbuf ))) { - net->dev.features &= ~(1ULL <<VIRTIO_NET_F_MRG_RXBUF ); +vhost_dev_clear_feature (&net->dev,VIRTIO_NET_F_MRG_RXBUF ); }if (!qemu_has_vnet_hdr (options->net_backend) && - (~net->dev.features & (1ULL <<VHOST_NET_F_VIRTIO_NET_HDR ))) { -fprintf (stderr,"vhost lacks feature mask 0x%llx for backend\n" , - ~net->dev.features & (1ULL <<VHOST_NET_F_VIRTIO_NET_HDR )); - goto fail; - } + !vhost_dev_has_feature (&net->dev,VHOST_NET_F_VIRTIO_NET_HDR )) { +fprintf (stderr,"vhost lacks VHOST_NET_F_VIRTIO_NET_HDR " +"feature for backend\n" ); + goto fail; + } }/* Set sane init value. Override when guest acks. */
@@ -298,7 +298,7 @@ struct vhost_net *vhost_net_init(VhostNetOptions *options)virtio_features_from_u64 (features, options->get_acked_features (net->nc));if (virtio_features_andnot (missing_features, features, - net->dev.features_ex)) { +vhost_dev_features_ex (&net->dev))) {fprintf (stderr,"vhost lacks feature mask 0x" VIRTIO_FEATURES_FMT " for backend\n" ,VIRTIO_FEATURES_PR (missing_features)); goto fail;
hw/virtio/vdpa-dev.c +1 -1
@@ -224,7 +224,7 @@ static uint64_t vhost_vdpa_device_get_features(VirtIODevice *vdev, Error **errp) {VhostVdpaDevice *s =VHOST_VDPA_DEVICE (vdev); -uint64_t backend_features = s->dev.features; +uint64_t backend_features =vhost_dev_features (&s->dev);if (!virtio_has_feature (features,VIRTIO_F_IOMMU_PLATFORM )) {virtio_clear_feature (&backend_features,VIRTIO_F_IOMMU_PLATFORM );
hw/virtio/vhost-user-base.c +6 -2
@@ -118,9 +118,13 @@ static uint64_t vub_get_features(VirtIODevice *vdev, uint64_t requested_features, Error **errp) { VHostUserBase *vub = VHOST_USER_BASE(vdev); +uint64_t backend_features =vhost_dev_features (&vub->vhost_dev); +/* This should be set when the vhost connection initialises */ -g_assert (vub->vhost_dev.features); -return vub->vhost_dev.features & ~(1ULL <<VHOST_USER_F_PROTOCOL_FEATURES ); +g_assert (backend_features); +virtio_clear_feature (&backend_features,VHOST_USER_F_PROTOCOL_FEATURES ); + +return backend_features; }/*
hw/virtio/vhost-user.c +2 -2
@@ -1249,7 +1249,7 @@ 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 )) { +if (!vhost_dev_has_feature (dev,VHOST_USER_F_PROTOCOL_FEATURES )) {/* * For vhost-user devices, if VHOST_USER_F_PROTOCOL_FEATURES has not * been negotiated, the rings start directly in the enabled state,
@@ -1488,7 +1488,7 @@ static int vhost_user_set_features(struct vhost_dev *dev,* Don't lose VHOST_USER_F_PROTOCOL_FEATURES, which is vhost-user * specific. */ -if (virtio_has_feature (dev->features,VHOST_USER_F_PROTOCOL_FEATURES )) { +if (vhost_dev_has_feature (dev,VHOST_USER_F_PROTOCOL_FEATURES )) { features |=1ULL <<VHOST_USER_F_PROTOCOL_FEATURES ; }
hw/virtio/vhost.c +3 -3
@@ -1612,7 +1612,7 @@ int vhost_dev_init(struct vhost_dev *hdev, void *opaque, } } -virtio_features_copy (hdev->features_ex, features); +virtio_features_copy (hdev->_features_ex, features); hdev->memory_listener = (MemoryListener ) { .name ="vhost" ,
@@ -1635,7 +1635,7 @@ int vhost_dev_init(struct vhost_dev *hdev, void *opaque, };if (hdev->migration_blocker ==NULL ) { -if (!virtio_has_feature_ex (hdev->features_ex,VHOST_F_LOG_ALL )) { +if (!vhost_dev_has_feature_ex (hdev,VHOST_F_LOG_ALL )) {error_setg (&hdev->migration_blocker,"Migration disabled: vhost lacks VHOST_F_LOG_ALL feature." ); }else if (vhost_dev_log_is_shared (hdev) && !qemu_memfd_alloc_check ()) {
@@ -1909,7 +1909,7 @@ void vhost_get_features_ex(struct vhost_dev *hdev,const int *bit = feature_bits;while (*bit !=VHOST_INVALID_FEATURE_BIT ) { -if (!virtio_has_feature_ex (hdev->features_ex, *bit)) { +if (!vhost_dev_has_feature_ex (hdev, *bit)) {virtio_clear_feature_ex (features, *bit); } bit++;
hw/virtio/virtio-qmp.c +1 -1
@@ -747,7 +747,7 @@ VirtioStatus *qmp_x_query_virtio_status(const char *path, Error **errp) status->vhost_dev->nvqs = hdev->nvqs; status->vhost_dev->vq_index = hdev->vq_index; status->vhost_dev->features = -qmp_decode_features (vdev->device_id, hdev->features_ex); +qmp_decode_features (vdev->device_id,vhost_dev_features_ex (hdev)); status->vhost_dev->acked_features =qmp_decode_features (vdev->device_id, hdev->acked_features_ex);
include/hw/virtio/vhost.h +37 -2
@@ -98,10 +98,11 @@ struct vhost_dev {* offered by a backend which may be a subset of the total * features eventually offered to the guest. * -* @features: available features provided by the backend +* @_features: available features provided by the backend, private, +* direct access only in vhost.h/vhost.c * @acked_features: final negotiated features with front-end driver */ -VIRTIO_DECLARE_FEATURES (features); +VIRTIO_DECLARE_FEATURES (_features);VIRTIO_DECLARE_FEATURES (acked_features);uint64_t max_queues;
@@ -403,6 +404,40 @@ int vhost_dev_get_inflight(struct vhost_dev *dev, uint16_t queue_size, struct vhost_inflight *inflight);bool vhost_dev_has_iommu (struct vhost_dev *dev); +static inline bool vhost_dev_has_feature (struct vhost_dev *dev, +uint64_t feature) +{ +return virtio_has_feature (dev->_features, feature); +} + +static inline bool vhost_dev_has_feature_ex (struct vhost_dev *dev, +uint64_t feature) +{ +return virtio_has_feature_ex (dev->_features_ex, feature); +} + +static inline uint64_t vhost_dev_features (struct vhost_dev *dev) +{ +return dev->_features; +} + +static inline const uint64_t *vhost_dev_features_ex (struct vhost_dev *dev) +{ +return dev->_features_ex; +} + +static inline void vhost_dev_clear_feature (struct vhost_dev *dev, +uint64_t feature) +{ +virtio_clear_feature (&dev->_features, feature); +} + +static inline void vhost_dev_clear_feature_ex (struct vhost_dev *dev, +uint64_t feature) +{ +virtio_clear_feature_ex (dev->_features_ex, feature); +} +#ifdef CONFIG_VHOST int vhost_reset_device (struct vhost_dev *hdev);#else
net/vhost-vdpa.c +3 -4
@@ -257,15 +257,14 @@ static bool vhost_vdpa_get_vnet_hash_supported_types(NetClientState *nc, {assert (nc->info->type ==NET_CLIENT_DRIVER_VHOST_VDPA );VhostVDPAState *s =DO_UPCAST (VhostVDPAState, nc, nc); -uint64_t features = s->vhost_vdpa.dev->features;int fd = s->vhost_vdpa.shared->device_fd;struct {struct vhost_vdpa_config hdr;uint32_t supported_hash_types; } config; -if (!virtio_has_feature (features,VIRTIO_NET_F_HASH_REPORT ) && - !virtio_has_feature (features,VIRTIO_NET_F_RSS )) { +if (!vhost_dev_has_feature (s->vhost_vdpa.dev,VIRTIO_NET_F_HASH_REPORT ) && + !vhost_dev_has_feature (s->vhost_vdpa.dev,VIRTIO_NET_F_RSS )) {return false; }
@@ -586,7 +585,7 @@ static int vhost_vdpa_net_cvq_start(NetClientState *nc)* 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. */ -if (!vhost_vdpa_net_valid_svq_features (v->dev->features,NULL )) { +if (!vhost_vdpa_net_valid_svq_features (vhost_dev_features (v->dev),NULL )) {return 0 ; }
Signature · 1 line
MST
[PULL 053/106] vhost: simplify vhost_memory_map() and vhost_memory_unmap()
In reply to Michael S. TsirkinFrom: Vladimir Sementsov-Ogievskiy <[email protected]>
Make these functions simple wrappers around address_space_map() and address_space_unmap(). Move IOMMU handling logic one layer up to the callers.
Based-on: <[email protected]>
Message-Id: <[email protected]>
--- hw/virtio/vhost.c | 43 ++++++++++++++++++++++++------------------- 1 file changed, 24 insertions(+), 19 deletions(-)
hw/virtio/vhost.c +24 -19
@@ -456,21 +456,17 @@ static inline void vhost_dev_log_resize(struct vhost_dev *dev, uint64_t size)static void *vhost_memory_map (struct vhost_dev *dev,hwaddr addr,hwaddr len,bool is_write) { -if (!vhost_dev_has_iommu (dev)) { -hwaddr mapped_len = len; -void *res =address_space_map (dev->vdev->dma_as, addr, &mapped_len, - is_write,MEMTXATTRS_UNSPECIFIED ); -if (!res) { -return NULL ; - } -if (len != mapped_len) { -address_space_unmap (dev->vdev->dma_as, res, mapped_len,0 ,0 ); -return NULL ; - } -return res; - }else { -return (void *)(uintptr_t )addr; +hwaddr mapped_len = len; +void *res =address_space_map (dev->vdev->dma_as, addr, &mapped_len, + is_write,MEMTXATTRS_UNSPECIFIED ); +if (!res) { +return NULL ; } +if (len != mapped_len) { +address_space_unmap (dev->vdev->dma_as, res, mapped_len,0 ,0 ); +return NULL ; + } +return res; } static void vhost_memory_unmap(struct vhost_dev *dev, void **buffer,
@@ -481,17 +477,18 @@ static void vhost_memory_unmap(struct vhost_dev *dev, void **buffer,return ; } -if (!vhost_dev_has_iommu (dev)) { -address_space_unmap (dev->vdev->dma_as, *buffer, len, is_write, - access_len); - } - +address_space_unmap (dev->vdev->dma_as, *buffer, len, is_write, + access_len); *buffer =NULL ; }static void vhost_vrings_unmap (struct vhost_dev *dev,struct vhost_virtqueue *vq,bool touched) { +if (vhost_dev_has_iommu (dev)) { +return ; + } +vhost_memory_unmap (dev, &vq->used, vq->used_size, touched, touched ? vq->used_size :0 ); vhost_memory_unmap(dev, &vq->avail, vq->avail_size, 0,
@@ -519,6 +516,14 @@ static int vhost_vrings_map(struct vhost_dev *dev,/* Queue might not be ready for start */ return 0 ; } + +if (vhost_dev_has_iommu (dev)) { + vq->desc = (void *)(uintptr_t )vq->desc_phys; + vq->avail = (void *)(uintptr_t )vq->avail_phys; + vq->used = (void *)(uintptr_t )vq->used_phys; +return 1 ; + } + vq->desc =vhost_memory_map (dev, vq->desc_phys, vq->desc_size, false);if (!vq->desc) { goto fail;
Signature · 1 line
MST
[PULL 076/106] vhost: factor out the detach buf logic in SVQ
In reply to Michael S. TsirkinFrom: Eugenio Pérez <[email protected]>
This code path is modified to handle in order devices. Abstract here so we can generalize on the caller.
Message-Id: <[email protected]>
--- hw/virtio/vhost-shadow-virtqueue.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-)
hw/virtio/vhost-shadow-virtqueue.c +16 -8
@@ -473,11 +473,24 @@ static uint16_t vhost_svq_last_desc_of_chain(const VhostShadowVirtqueue *svq,return i; } +G_GNUC_WARN_UNUSED_RESULT +static VirtQueueElement *vhost_svq_detach_buf(VhostShadowVirtqueue *svq, +uint16_t id) +{ +uint16_t num = svq->desc_state[id].ndescs; +uint16_t last_used_chain =vhost_svq_last_desc_of_chain (svq, num, id); + + svq->desc_state[last_used_chain].next = svq->free_head; + svq->free_head = id; + +return g_steal_pointer (&svq->desc_state[id].elem); +} +G_GNUC_WARN_UNUSED_RESULT static VirtQueueElement *vhost_svq_get_buf(VhostShadowVirtqueue *svq,uint32_t *len) { -uint16_t last_used, last_used_chain, num; +uint16_t last_used;if (!vhost_svq_more_used (svq)) {return NULL ;
@@ -500,14 +513,9 @@ static VirtQueueElement *vhost_svq_get_buf(VhostShadowVirtqueue *svq,return NULL ; } - num = svq->desc_state[last_used].ndescs; + svq->num_free += svq->desc_state[last_used].ndescs; svq->desc_state[last_used].ndescs =0 ; - last_used_chain =vhost_svq_last_desc_of_chain (svq, num, last_used); - svq->desc_state[last_used_chain].next = svq->free_head; - svq->free_head = last_used; - svq->num_free += num; - -return g_steal_pointer (&svq->desc_state[last_used].elem); +return vhost_svq_detach_buf (svq, last_used); }/**
Signature · 1 line
MST
[PULL 104/106] intel_iommu: fix guest-triggerable abort on oversized MMIO access
In reply to Michael S. TsirkinFrom: Junjie Cao <[email protected]>
An 8-byte guest access to a 32-bit-only VT-d register hit assert(size == 4) and aborted QEMU. Remove all 25 asserts.
All 3 read-side and 18 of 22 write-side asserts are at non-8-aligned offsets (unreachable, rejected by memory_region_access_valid()) -- simply deleted.
The remaining 4, all writes at 8-aligned offsets, are
reachable: FECTL 0x38, IECTL 0xa0, IEADDR 0xa8, PECTL 0xe0. Truncating the high half via vtd_set_long() matches prior behavior; log under -d guest_errors since the VT-d spec is silent on oversized accesses to 32-bit registers, and add a comment so future maintainers don't delete the check as "harmless". min_access_size stays 4, so all size-based branches on 64-bit register pairs are preserved.
Found by generic-fuzz (24 distinct crash seeds, all fixed).
Message-Id: <[email protected]>
--- hw/i386/intel_iommu.c | 74 ++++++++++++++++++++++++++++--------------- 1 file changed, 49 insertions(+), 25 deletions(-)
hw/i386/intel_iommu.c +49 -25
@@ -21,6 +21,7 @@#include "qemu/osdep.h" #include "qemu/error-report.h" +#include "qemu/log.h" #include "qemu/main-loop.h" #include "qapi/error.h" #include "hw/core/sysbus.h"
@@ -3659,7 +3660,6 @@ static uint64_t vtd_mem_read(void *opaque, hwaddr addr, unsigned size)break ;case DMAR_RTADDR_REG_HI : -assert (size ==4 ); val =vtd_get_quad_raw (s,DMAR_RTADDR_REG ) >>32 ;break ;
@@ -3674,12 +3674,10 @@ static uint64_t vtd_mem_read(void *opaque, hwaddr addr, unsigned size)break ;case DMAR_IQA_REG_HI : -assert (size ==4 ); val = s->iq >>32 ;break ;case DMAR_PEUADDR_REG : -assert (size ==4 ); val =vtd_get_long_raw (s,DMAR_PEUADDR_REG );break ;
@@ -3725,7 +3723,6 @@ static void vtd_mem_write(void *opaque, hwaddr addr,break ;case DMAR_CCMD_REG_HI : -assert (size ==4 );vtd_set_long (s, addr, val);vtd_handle_ccmd_write (s);break ;
@@ -3741,13 +3738,11 @@ static void vtd_mem_write(void *opaque, hwaddr addr,break ;case DMAR_IOTLB_REG_HI : -assert (size ==4 );vtd_set_long (s, addr, val);vtd_handle_iotlb_write (s);break ;case DMAR_PEUADDR_REG : -assert (size ==4 );vtd_set_long (s, addr, val);break ;
@@ -3761,27 +3756,35 @@ static void vtd_mem_write(void *opaque, hwaddr addr,break ;case DMAR_IVA_REG_HI : -assert (size ==4 );vtd_set_long (s, addr, val);break ;/* Fault Status Register, 32-bit */ case DMAR_FSTS_REG : -assert (size ==4 );vtd_set_long (s, addr, val);vtd_handle_fsts_write (s);break ;/* Fault Event Control Register, 32-bit */ case DMAR_FECTL_REG : -assert (size ==4 ); +/* +* 32-bit register at an 8-byte-aligned offset: a well-formed +* 8-byte guest access reaches this handler. vtd_set_long() +* takes uint32_t and truncates the high half -- undefined per +* the VT-d spec but harmless here. Flag it under +* -d guest_errors so the guest-side bug surfaces. +*/ +if (size !=4 ) { +qemu_log_mask (LOG_GUEST_ERROR , +"%s: invalid %u-byte access to 32-bit reg " +"addr=0x%" PRIx64"\n" , __func__, size, addr); + }vtd_set_long (s, addr, val);vtd_handle_fectl_write (s);break ;/* Fault Event Data Register, 32-bit */ case DMAR_FEDATA_REG : -assert (size ==4 );vtd_set_long (s, addr, val);break ;
@@ -3800,13 +3803,11 @@ static void vtd_mem_write(void *opaque, hwaddr addr,/* Fault Event Upper Address Register, 32-bit */ case DMAR_FEUADDR_REG : -assert (size ==4 );vtd_set_long (s, addr, val);break ;/* Protected Memory Enable Register, 32-bit */ case DMAR_PMEN_REG : -assert (size ==4 );vtd_set_long (s, addr, val);break ;
@@ -3820,7 +3821,6 @@ static void vtd_mem_write(void *opaque, hwaddr addr,break ;case DMAR_RTADDR_REG_HI : -assert (size ==4 );vtd_set_long (s, addr, val);break ;
@@ -3835,7 +3835,6 @@ static void vtd_mem_write(void *opaque, hwaddr addr,break ;case DMAR_IQT_REG_HI : -assert (size ==4 );vtd_set_long (s, addr, val);/* 19:63 of IQT_REG is RsvdZ, do nothing here */ break ;
@@ -3851,39 +3850,57 @@ static void vtd_mem_write(void *opaque, hwaddr addr,break ;case DMAR_IQA_REG_HI : -assert (size ==4 );vtd_set_long (s, addr, val);break ;/* Invalidation Completion Status Register, 32-bit */ case DMAR_ICS_REG : -assert (size ==4 );vtd_set_long (s, addr, val);vtd_handle_ics_write (s);break ;/* Invalidation Event Control Register, 32-bit */ case DMAR_IECTL_REG : -assert (size ==4 ); +/* +* 32-bit register at an 8-byte-aligned offset: a well-formed +* 8-byte guest access reaches this handler. vtd_set_long() +* takes uint32_t and truncates the high half -- undefined per +* the VT-d spec but harmless here. Flag it under +* -d guest_errors so the guest-side bug surfaces. +*/ +if (size !=4 ) { +qemu_log_mask (LOG_GUEST_ERROR , +"%s: invalid %u-byte access to 32-bit reg " +"addr=0x%" PRIx64"\n" , __func__, size, addr); + }vtd_set_long (s, addr, val);vtd_handle_iectl_write (s);break ;/* Invalidation Event Data Register, 32-bit */ case DMAR_IEDATA_REG : -assert (size ==4 );vtd_set_long (s, addr, val);break ;/* Invalidation Event Address Register, 32-bit */ case DMAR_IEADDR_REG : -assert (size ==4 ); +/* +* 32-bit register at an 8-byte-aligned offset: a well-formed +* 8-byte guest access reaches this handler. vtd_set_long() +* takes uint32_t and truncates the high half -- undefined per +* the VT-d spec but harmless here. Flag it under +* -d guest_errors so the guest-side bug surfaces. +*/ +if (size !=4 ) { +qemu_log_mask (LOG_GUEST_ERROR , +"%s: invalid %u-byte access to 32-bit reg " +"addr=0x%" PRIx64"\n" , __func__, size, addr); + }vtd_set_long (s, addr, val);break ;/* Invalidation Event Upper Address Register, 32-bit */ case DMAR_IEUADDR_REG : -assert (size ==4 );vtd_set_long (s, addr, val);break ;
@@ -3897,7 +3914,6 @@ static void vtd_mem_write(void *opaque, hwaddr addr,break ;case DMAR_FRCD_REG_0_1 : -assert (size ==4 );vtd_set_long (s, addr, val);break ;
@@ -3912,7 +3928,6 @@ static void vtd_mem_write(void *opaque, hwaddr addr,break ;case DMAR_FRCD_REG_0_3 : -assert (size ==4 );vtd_set_long (s, addr, val);/* May clear bit 127 (Fault), update PPF */ vtd_update_fsts_ppf (s);
@@ -3927,18 +3942,27 @@ static void vtd_mem_write(void *opaque, hwaddr addr,break ;case DMAR_IRTA_REG_HI : -assert (size ==4 );vtd_set_long (s, addr, val);break ;case DMAR_PRS_REG : -assert (size ==4 );vtd_set_long (s, addr, val);vtd_handle_prs_write (s);break ;case DMAR_PECTL_REG : -assert (size ==4 ); +/* +* 32-bit register at an 8-byte-aligned offset: a well-formed +* 8-byte guest access reaches this handler. vtd_set_long() +* takes uint32_t and truncates the high half -- undefined per +* the VT-d spec but harmless here. Flag it under +* -d guest_errors so the guest-side bug surfaces. +*/ +if (size !=4 ) { +qemu_log_mask (LOG_GUEST_ERROR , +"%s: invalid %u-byte access to 32-bit reg " +"addr=0x%" PRIx64"\n" , __func__, size, addr); + }vtd_set_long (s, addr, val);vtd_handle_pectl_write (s);break ;
Signature · 1 line
MST
[PULL 059/106] libvhost-user: fix buffer overflow in virtqueue_read_indirect_desc()
In reply to Michael S. TsirkinFrom: Stefano Garzarella <[email protected]>
virtqueue_read_indirect_desc() copies an indirect descriptor table into a buffer in chunks when the table crosses a memory region boundary. The destination is a struct vring_desc pointer but is advanced by a byte count, so each increment moves the pointer by read_len elements instead of read_len bytes, writing beyond the buffer.
Use a char pointer for the destination so that the arithmetic advances correctly.
While at it, change the source from a struct vring_desc pointer to a void pointer: when the table is split across regions, vu_gpa_to_va() can return a pointer into the middle of a descriptor, so casting it to a struct vring_desc pointer is wrong. The pointer is only used as a memcpy() source, so a void pointer is fine.
Message-Id: <[email protected]>
--- subprojects/libvhost-user/libvhost-user.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
subprojects/libvhost-user/libvhost-user.c +4 -3
@@ -2391,8 +2391,9 @@ static int virtqueue_read_indirect_desc(VuDev *dev, struct vring_desc *desc, uint64_t addr, size_t len) { -struct vring_desc *ori_desc; +char *dst_desc = (char *)desc;uint64_t read_len; +void *ori_desc;if (len > (VIRTQUEUE_MAX_SIZE *sizeof (struct vring_desc ))) {return -1 ;
@@ -2409,10 +2410,10 @@ virtqueue_read_indirect_desc(VuDev *dev, struct vring_desc *desc,return -1 ; } -memcpy (desc, ori_desc, read_len); +memcpy (dst_desc, ori_desc, read_len); len -= read_len; addr += read_len; - desc += read_len; + dst_desc += read_len; }return 0 ;
Signature · 1 line
MST
[PULL 073/106] vhost: move svq next desc array to descs state struct
In reply to Michael S. TsirkinFrom: Eugenio Pérez <[email protected]>
It's the right place for it as it is part of the descriptor state. We save the memory management of the array, and make the code changes of the next patches easier.
Message-Id: <[email protected]>
--- hw/virtio/vhost-shadow-virtqueue.c | 14 ++++++-------- hw/virtio/vhost-shadow-virtqueue.h | 12 ++++++------ 2 files changed, 12 insertions(+), 14 deletions(-)
hw/virtio/vhost-shadow-virtqueue.c +6 -8
@@ -175,7 +175,7 @@ static bool vhost_svq_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]); + descs[i].next =cpu_to_le16 (svq->desc_state[i].next); }else { descs[i].flags = flags; }
@@ -183,10 +183,10 @@ static bool vhost_svq_vring_write_descs(VhostShadowVirtqueue *svq, hwaddr *sg, descs[i].len =cpu_to_le32 (iovec[n].iov_len); last = i; - i = svq->desc_next[i]; + i = svq->desc_state[i].next; } - svq->free_head = svq->desc_next[last]; + svq->free_head = svq->desc_state[last].next;return true; }
@@ -432,7 +432,7 @@ 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 = svq->desc_next[i]; + i = svq->desc_state[i].next; }return i;
@@ -473,7 +473,7 @@ static VirtQueueElement *vhost_svq_get_buf(VhostShadowVirtqueue *svq, num = svq->desc_state[used_elem.id].ndescs; svq->desc_state[used_elem.id].ndescs =0 ; last_used_chain =vhost_svq_last_desc_of_chain (svq, num, used_elem.id); - svq->desc_next[last_used_chain] = svq->free_head; + svq->desc_state[last_used_chain].next = svq->free_head; svq->free_head = used_elem.id; svq->num_free += num;
@@ -705,9 +705,8 @@ void vhost_svq_start(VhostShadowVirtqueue *svq, VirtIODevice *vdev,PROT_READ |PROT_WRITE ,MAP_SHARED |MAP_ANONYMOUS , -1, 0); 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] = i +1 ; + svq->desc_state[i].next = i +1 ; } }
@@ -744,7 +743,6 @@ void vhost_svq_stop(VhostShadowVirtqueue *svq)virtqueue_unpop (svq->vq, next_avail_elem,0 ); } svq->vq =NULL ; -g_free (svq->desc_next);g_free (svq->desc_state);munmap (svq->vring.desc,vhost_svq_driver_area_size (svq));munmap (svq->vring.used,vhost_svq_device_area_size (svq));
hw/virtio/vhost-shadow-virtqueue.h +6 -6
@@ -23,6 +23,12 @@ typedef struct SVQDescState {* guest's */ unsigned int ndescs; + +/* +* Backup next field for each descriptor so we can recover securely, not +* needing to trust the device access. +*/ +uint16_t next; } SVQDescState;typedef struct VhostShadowVirtqueue VhostShadowVirtqueue ;
@@ -84,12 +90,6 @@ 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; -/* Caller callbacks */ const VhostShadowVirtqueueOps *ops;
Signature · 1 line
MST
[PULL 106/106] hw/scsi/vhost-scsi: fix build with older kernel headers
In reply to Michael S. TsirkinFrom: Quan Sun <[email protected]>
On build hosts with kernel headers older than 6.0, the system's <linux/vhost_types.h> does not define struct vhost_vring_worker or struct vhost_worker_state, causing compilation of vhost-scsi.c to fail:
error: storage size of 'vq_worker' isn't known
Fix by including standard-headers/linux/vhost_types.h before the system's <linux/vhost.h>, matching the existing pattern used in hw/virtio/vhost-backend.c. QEMU's bundled header provides the struct definitions, and its include guard prevents redefinition when the system header pulls in its own vhost_types.h.
Message-Id: <[email protected]>
--- hw/scsi/vhost-scsi.c | 1 + 1 file changed, 1 insertion(+)
hw/scsi/vhost-scsi.c +1 -0
@@ -15,6 +15,7 @@*/ #include "qemu/osdep.h" +#include "standard-headers/linux/vhost_types.h" #include <linux/vhost.h> #include <sys/ioctl.h> #include "qapi/error.h"
Signature · 1 line
MST
[PULL 010/106] intel_iommu: Rename pasid property to "pasid-bits" and define it as type uint8
In reply to Michael S. TsirkinFrom: Zhenzhong Duan <[email protected]>
'x-pasid-mode' is a bool property, we need an extra 'pss' property to represent PASID size supported. Because there is no any device in QEMU supporting pasid capability yet, no guest could use the pasid feature until now, 'x-pasid-mode' takes no effect.
So instead of an extra 'pss' property we can use a single property of uint8 type and named 'pasid-bits' to represent if pasid is supported and the PASID bits size. A value of N > 0 means pasid is supported and N - 1 is the value in PSS field in ECAP register.
PASID bits size should also be no more than 20 bits according to PCI spec.
Message-Id: <[email protected]>
--- hw/i386/intel_iommu.c | 11 +++++++++-- hw/i386/intel_iommu_internal.h | 2 +- include/hw/i386/intel_iommu.h | 2 +- 3 files changed, 11 insertions(+), 4 deletions(-)
hw/i386/intel_iommu.c +9 -2
@@ -4203,7 +4203,7 @@ static const Property vtd_properties[] = {DEFINE_PROP_BOOL ("scalable-mode" , IntelIOMMUState, scalable_mode, FALSE),DEFINE_PROP_BOOL ("fsts" , IntelIOMMUState, fsts, FALSE),DEFINE_PROP_BOOL ("snoop-control" , IntelIOMMUState, snoop_control, false), -DEFINE_PROP_BOOL ("x-pasid-mode" , IntelIOMMUState, pasid, false), +DEFINE_PROP_UINT8 ("pasid-bits" , IntelIOMMUState, pasid,0 ),DEFINE_PROP_BOOL ("svm" , IntelIOMMUState, svm, false),DEFINE_PROP_BOOL ("stale-tm" , IntelIOMMUState, stale_tm, false), DEFINE_PROP_BOOL("fs1gp", IntelIOMMUState, fs1gp, true),
@@ -5045,7 +5045,8 @@ static void vtd_cap_init(IntelIOMMUState *s) }if (s->pasid) { - s->ecap |=VTD_ECAP_PASID |VTD_ECAP_PSS ; +VTD_ECAP_SET_PSS (s, s->pasid -1 ); + s->ecap |=VTD_ECAP_PASID ; } }
@@ -5586,6 +5587,12 @@ static bool vtd_decide_config(IntelIOMMUState *s, Error **errp)return false; } +if (s->pasid >PCI_EXT_CAP_PASID_MAX_WIDTH ) { +error_setg (errp,"PASID width %d exceeds Max PASID Width %d allowed " +"in PCI spec" , s->pasid,PCI_EXT_CAP_PASID_MAX_WIDTH ); +return false; + } +if (s->svm) {if (!x86_iommu->dt_supported) {error_setg (errp,"Need to set device IOTLB for svm" );
hw/i386/intel_iommu_internal.h +1 -1
@@ -195,7 +195,7 @@#define VTD_ECAP_MHMV (15ULL << 20)#define VTD_ECAP_SRS (1ULL << 31)#define VTD_ECAP_NWFS (1ULL << 33) -#define VTD_ECAP_PSS (7ULL << 35)/* limit: MemTxAttrs::pid */ +#define VTD_ECAP_SET_PSS (x, v) ((x)->ecap = deposit64((x)->ecap, 35, 5, v))#define VTD_ECAP_PASID (1ULL << 40)#define VTD_ECAP_PDS (1ULL << 42)#define VTD_ECAP_SMTS (1ULL << 43)
include/hw/i386/intel_iommu.h +1 -1
@@ -314,7 +314,7 @@ struct IntelIOMMUState {bool intr_eime;/* Extended interrupt mode enabled */ OnOffAuto intr_eim;/* Toggle for EIM cabability */ uint8_t aw_bits;/* Host/IOVA address width (in bits) */ -bool pasid;/* Whether to support PASID */ +uint8_t pasid;/* PASID supported in bits, 0 if not */ bool fs1gp;/* First Stage 1-GByte Page Support */ /* Transient Mapping, Reserved(0) since VTD spec revision 3.2 */
Signature · 1 line
MST
[PULL 091/106] vhost-user: Add VirtIO Shared Memory map request
In reply to Michael S. TsirkinFrom: Albert Esteve <[email protected]>
Add SHMEM_MAP/UNMAP requests to vhost-user for dynamic management of VIRTIO Shared Memory mappings.
This implementation introduces VirtioSharedMemoryMapping as a unified QOM object that manages both the mapping metadata and MemoryRegion lifecycle. This object provides reference-counted lifecycle management with automatic cleanup of file descriptors and memory regions through QOM finalization.
This request allows backends to dynamically map file descriptors into a VIRTIO Shared Memory Region identified by their shmid. Maps are created using memory_region_init_ram_from_fd() with configurable read/write permissions, and the resulting MemoryRegions are added as subregions to the shmem container region. The mapped memory is then advertised to the guest VIRTIO drivers as a base address plus offset for reading and writting according to the requested mmap flags.
The backend can unmap memory ranges within a given VIRTIO Shared Memory Region to free resources. Upon receiving this message, the frontend removes the MemoryRegion as a subregion and automatically unreferences the VirtioSharedMemoryMapping object, triggering cleanup if no other references exist.
Error handling has been improved to ensure consistent behavior across handlers that manage their own vhost_user_send_resp() calls. Since these handlers clear the VHOST_USER_NEED_REPLY_MASK flag, explicit error checking ensures proper connection closure on failures, maintaining the expected error flow.
Note the memory region commit for these operations needs to be delayed until after we reply to the backend to avoid deadlocks. Otherwise, the MemoryListener would send a VHOST_USER_SET_MEM_TABLE message before the reply.
Message-Id: <[email protected]>
--- hw/virtio/vhost-user.c | 274 ++++++++++++++++++++++ hw/virtio/virtio.c | 201 ++++++++++++++++ include/hw/virtio/virtio.h | 134 +++++++++++ include/system/memory.h | 2 +- subprojects/libvhost-user/libvhost-user.c | 70 ++++++ subprojects/libvhost-user/libvhost-user.h | 54 +++++ system/memory.c | 14 ++ 7 files changed, 748 insertions(+), 1 deletion(-)
hw/virtio/vhost-user.c +274 -0
@@ -100,6 +100,7 @@ typedef enum VhostUserRequest {VHOST_USER_GET_SHARED_OBJECT =41 ,VHOST_USER_SET_DEVICE_STATE_FD =42 ,VHOST_USER_CHECK_DEVICE_STATE =43 , +VHOST_USER_GET_SHMEM_CONFIG =44 , VHOST_USER_MAX } VhostUserRequest;
@@ -111,6 +112,8 @@ typedef enum VhostUserBackendRequest {VHOST_USER_BACKEND_SHARED_OBJECT_ADD =6 ,VHOST_USER_BACKEND_SHARED_OBJECT_REMOVE =7 ,VHOST_USER_BACKEND_SHARED_OBJECT_LOOKUP =8 , +VHOST_USER_BACKEND_SHMEM_MAP =9 , +VHOST_USER_BACKEND_SHMEM_UNMAP =10 , VHOST_USER_BACKEND_MAX } VhostUserBackendRequest;
@@ -189,6 +192,12 @@ typedef struct VhostUserMemRegMsg {VhostUserMemoryRegion region; } VhostUserMemRegMsg; +typedef struct VhostUserShMemConfig { +uint32_t nregions; +uint32_t padding; +uint64_t memory_sizes[VIRTIO_MAX_SHMEM_REGIONS ]; +}VhostUserShMemConfig ; + typedef struct VhostUserLog { uint64_t mmap_size; uint64_t mmap_offset;
@@ -245,6 +254,23 @@ typedef struct VhostUserShared {unsigned char uuid[16 ]; } VhostUserShared; +/* For the flags field of VhostUserMMap */ +#define VHOST_USER_FLAG_MAP_RW (1u << 0) + +typedef struct { +/* VIRTIO Shared Memory Region ID */ +uint8_t shmid; +uint8_t padding[7 ]; +/* File offset */ +uint64_t fd_offset; +/* Offset within the VIRTIO Shared Memory Region */ +uint64_t shm_offset; +/* Size of the mapping */ +uint64_t len; +/* Flags for the mmap operation, from VHOST_USER_FLAG_MAP_* */ +uint64_t flags; +}VhostUserMMap ; + typedef struct { VhostUserRequest request;
@@ -277,6 +303,8 @@ typedef union {VhostUserInflight inflight;VhostUserShared object;VhostUserTransferDeviceState transfer_state; +VhostUserMMap mmap; +VhostUserShMemConfig shmem; } VhostUserPayload; typedef struct VhostUserMsg {
@@ -1860,6 +1888,196 @@ vhost_user_backend_handle_shared_object_lookup(struct vhost_user *u,return 0 ; } +/** +* vhost_user_backend_handle_shmem_map() - Handle SHMEM_MAP backend request +* @dev: vhost device +* @ioc: QIOChannel for communication +* @hdr: vhost-user message header +* @payload: message payload containing mapping details +* @fd: file descriptor for the shared memory region +* +* Handles VHOST_USER_BACKEND_SHMEM_MAP requests from the backend. Creates +* a VhostUserShmemObject to manage the shared memory mapping and adds it +* to the appropriate VirtIO shared memory region. The VhostUserShmemObject +* serves as an intermediate parent for the MemoryRegion, ensuring proper +* lifecycle management with reference counting. +* +* Returns: 0 on success, negative errno on failure +*/ +static int +vhost_user_backend_handle_shmem_map (struct vhost_dev *dev, +QIOChannel *ioc, +VhostUserHeader *hdr, +VhostUserPayload *payload, +int fd) +{ +VirtioSharedMemory *shmem; +VhostUserMMap *vu_mmap = &payload->mmap; +VirtioSharedMemoryMapping *existing; +Error *local_err =NULL ; +int ret =0 ; + +if (fd <0 ) { +error_report ("Bad fd for map" ); + ret = -EBADF ; + goto send_reply; + } + +if (QSIMPLEQ_EMPTY (&dev->vdev->shmem_list)) { +error_report ("Device has no VIRTIO Shared Memory Regions. " +"Requested ID: %d" , vu_mmap->shmid); + ret = -EFAULT ; + goto send_reply; + } + + shmem =virtio_find_shmem_region (dev->vdev, vu_mmap->shmid); +if (!shmem) { +error_report ("VIRTIO Shared Memory Region at " +"ID %d not found or uninitialized" , vu_mmap->shmid); + ret = -EFAULT ; + goto send_reply; + } + +if ((vu_mmap->shm_offset + vu_mmap->len) < vu_mmap->len || + (vu_mmap->shm_offset + vu_mmap->len) >memory_region_size (&shmem->mr)) { +error_report ("Bad offset/len for mmap %" PRIx64"+%" PRIx64, + vu_mmap->shm_offset, vu_mmap->len); + ret = -EFAULT ; + goto send_reply; + } + + QTAILQ_FOREACH(existing, &shmem->mmaps, link) { +if (ranges_overlap (existing->offset, existing->len, + vu_mmap->shm_offset, vu_mmap->len)) { +error_report ("VIRTIO Shared Memory mapping overlap" ); + ret = -EFAULT ; + goto send_reply; + } + } + +memory_region_transaction_begin (); + +/* Create VirtioSharedMemoryMapping object */ +VirtioSharedMemoryMapping *mapping =virtio_shared_memory_mapping_new ( + vu_mmap->shmid, fd, vu_mmap->fd_offset, vu_mmap->shm_offset, + vu_mmap->len, vu_mmap->flags &VHOST_USER_FLAG_MAP_RW ); + +if (!mapping) { + ret = -EFAULT ; + goto send_reply_commit; + } + +/* Add the mapping to the shared memory region */ +if (virtio_add_shmem_map (shmem, mapping) !=0 ) { +error_report ("Failed to add shared memory mapping" ); +object_unref (OBJECT (mapping)); + ret = -EFAULT ; + goto send_reply_commit; + } + +send_reply_commit: +/* Send reply and commit after transaction started */ +if (hdr->flags &VHOST_USER_NEED_REPLY_MASK ) { + payload->u64 = !!ret; + hdr->size =sizeof (payload->u64); +if (!vhost_user_send_resp (ioc, hdr, payload, &local_err)) { +error_report_err (local_err); +memory_region_transaction_commit (); +return -EFAULT ; + } + } +memory_region_transaction_commit (); +return 0 ; + +send_reply: +if (hdr->flags &VHOST_USER_NEED_REPLY_MASK ) { + payload->u64 = !!ret; + hdr->size =sizeof (payload->u64); +if (!vhost_user_send_resp (ioc, hdr, payload, &local_err)) { +error_report_err (local_err); +return -EFAULT ; + } + } +return 0 ; +} + +/** +* vhost_user_backend_handle_shmem_unmap() - Handle SHMEM_UNMAP backend request +* @dev: vhost device +* @ioc: QIOChannel for communication +* @hdr: vhost-user message header +* @payload: message payload containing unmapping details +* +* Handles VHOST_USER_BACKEND_SHMEM_UNMAP requests from the backend. Removes +* the specified memory mapping from the VirtIO shared memory region. This +* automatically unreferences the associated VhostUserShmemObject, which may +* trigger its finalization and cleanup (munmap, close fd) if no other +* references exist. +* +* Returns: 0 on success, negative errno on failure +*/ +static int +vhost_user_backend_handle_shmem_unmap (struct vhost_dev *dev, +QIOChannel *ioc, +VhostUserHeader *hdr, +VhostUserPayload *payload) +{ +VirtioSharedMemory *shmem =NULL ; +VirtioSharedMemoryMapping *mmap =NULL ; +VhostUserMMap *vu_mmap = &payload->mmap; +Error *local_err =NULL ; +int ret =0 ; + +if (QSIMPLEQ_EMPTY (&dev->vdev->shmem_list)) { +error_report ("Device has no VIRTIO Shared Memory Regions. " +"Requested ID: %d" , vu_mmap->shmid); + ret = -EFAULT ; + goto send_reply; + } + + shmem =virtio_find_shmem_region (dev->vdev, vu_mmap->shmid); +if (!shmem) { +error_report ("VIRTIO Shared Memory Region at " +"ID %d not found or uninitialized" , vu_mmap->shmid); + ret = -EFAULT ; + goto send_reply; + } + +if ((vu_mmap->shm_offset + vu_mmap->len) < vu_mmap->len || + (vu_mmap->shm_offset + vu_mmap->len) >memory_region_size (&shmem->mr)) { +error_report ("Bad offset/len for unmmap %" PRIx64"+%" PRIx64, + vu_mmap->shm_offset, vu_mmap->len); + ret = -EFAULT ; + goto send_reply; + } + + mmap =virtio_find_shmem_map (shmem, vu_mmap->shm_offset, vu_mmap->len); +if (!mmap) { +error_report ("Shared memory mapping not found at offset %" PRIx64 +" with length %" PRIx64, + vu_mmap->shm_offset, vu_mmap->len); + ret = -EFAULT ; + goto send_reply; + } + +send_reply: +if (hdr->flags &VHOST_USER_NEED_REPLY_MASK ) { + payload->u64 = !!ret; + hdr->size =sizeof (payload->u64); +if (!vhost_user_send_resp (ioc, hdr, payload, &local_err)) { +error_report_err (local_err); +return -EFAULT ; + } + } + +if (!ret && shmem && mmap) { +/* Free the MemoryRegion only after reply */ +virtio_del_shmem_map (shmem, vu_mmap->shm_offset, vu_mmap->len); + } + +return 0 ; +} +static void close_backend_channel (struct vhost_user *u) {g_source_destroy (u->backend_src);
@@ -1933,6 +2151,21 @@ static gboolean backend_read(QIOChannel *ioc, GIOCondition condition, ret =vhost_user_backend_handle_shared_object_lookup (dev->opaque, &payload.object);break ; +case VHOST_USER_BACKEND_SHMEM_MAP : +/* Handler manages its own response, check error and close connection */ + reply_ack = false; +if (vhost_user_backend_handle_shmem_map (dev, ioc, &hdr, &payload, + fd ? fd[0 ] :-1 ) <0 ) { + goto err; + } +break ; +case VHOST_USER_BACKEND_SHMEM_UNMAP : +/* Handler manages its own response, check error and close connection */ + reply_ack = false; +if (vhost_user_backend_handle_shmem_unmap (dev, ioc, &hdr, &payload) <0 ) { + goto err; + } +break ;default :error_report ("Received unexpected msg type: %d." , hdr.request); ret = -EINVAL ;
@@ -3123,6 +3356,46 @@ void vhost_user_qmp_status(struct vhost_dev *dev, VirtioStatus *status)qmp_decode_protocols (u->protocol_features); } +static int vhost_user_get_shmem_config (struct vhost_dev *dev, +int *nregions, +uint64_t *memory_sizes, +Error **errp) +{ +int ret; +VhostUserMsg msg = { + .hdr.request =VHOST_USER_GET_SHMEM_CONFIG , + .hdr.flags =VHOST_USER_VERSION , + }; + +if (!vhost_user_has_protocol_feature (dev, +VHOST_USER_PROTOCOL_F_SHMEM )) { + *nregions =0 ; +return 0 ; + } + + ret =vhost_user_write (dev, &msg,NULL ,0 ); +if (ret <0 ) { +return ret; + } + + ret =vhost_user_read (dev, &msg); +if (ret <0 ) { +return ret; + } + +if (msg.payload.shmem.nregions >VIRTIO_MAX_SHMEM_REGIONS ) { +error_setg (errp,"Received too many shared memory regions: %d" , + msg.payload.shmem.nregions); +return -EINVAL ; + } + + *nregions = msg.payload.shmem.nregions; +memcpy (memory_sizes, + &msg.payload.shmem.memory_sizes, +sizeof (uint64_t ) *VIRTIO_MAX_SHMEM_REGIONS ); +return 0 ; +} +const VhostOps user_ops = { .backend_type =VHOST_BACKEND_TYPE_USER , .vhost_init = vhost_user_backend_init,
@@ -3163,4 +3436,5 @@ const VhostOps user_ops = { .vhost_check_device_state = vhost_user_check_device_state, .vhost_phys_vring_addr = vhost_user_gpa_addresses, .vhost_phys_iotlb_msg = vhost_user_gpa_addresses, + .vhost_get_shmem_config = vhost_user_get_shmem_config, };
hw/virtio/virtio.c +201 -0
245 lines not on this page · raw message
include/hw/virtio/virtio.h +134 -0
152 lines not on this page · raw message
include/system/memory.h +1 -1
@@ -1456,6 +1456,7 @@ bool memory_region_init_ram_from_file(MemoryRegion *mr,const char *path, ram_addr_t offset, Error **errp); +#endif /** * memory_region_init_ram_from_fd: Initialize RAM memory region with a
@@ -1485,7 +1486,6 @@ bool memory_region_init_ram_from_fd(MemoryRegion *mr,int fd, ram_addr_t offset, Error **errp); -#endif /** * memory_region_init_ram_ptr: Initialize RAM memory region from a
subprojects/libvhost-user/libvhost-user.c +70 -0
76 lines not on this page · raw message
subprojects/libvhost-user/libvhost-user.h +54 -0
84 lines not on this page · raw message
system/memory.c +14 -0
@@ -1652,6 +1652,20 @@ bool memory_region_init_ram_from_fd(MemoryRegion *mr, Object *owner, false, errp);return memory_region_set_ram_block (mr, rb); } +#else +bool memory_region_init_ram_from_fd (MemoryRegion *mr, +Object *owner, +const char *name, +uint64_t size, +uint32_t ram_flags, +int fd, +ram_addr_t offset, +Error **errp) +{ +error_setg (errp, +"memory_region_init_ram_from_fd is not supported on this platform" ); +return false; +}#endif static void memory_region_set_ram_ptr(MemoryRegion *mr, uint64_t size,
Signature · 1 line
MST