From: "Cédric Le Goater" <clg@redhat.com>
To: qemu-devel@nongnu.org
Cc: "Nathan Chen" <nathanc@nvidia.com>,
"Shameer Kolothum" <skolothumtho@nvidia.com>,
"Cédric Le Goater" <clg@redhat.com>
Subject: [PULL 23/27] vfio/pci: Add ats property
Date: Tue, 7 Jul 2026 08:29:16 +0200 [thread overview]
Message-ID: <20260707062920.317302-24-clg@redhat.com> (raw)
In-Reply-To: <20260707062920.317302-1-clg@redhat.com>
From: Nathan Chen <nathanc@nvidia.com>
Add an "ats" OnOffAuto property to vfio-pci. When the device has an ATS
extended capability in config space but we should not expose it (ats=off,
or ats=auto and kernel reports IOMMU_HW_CAP_PCI_ATS_NOT_SUPPORTED), mask
the capability so the guest does not see it.
If ATS is explicitly requested but not supported by the kernel, fail
device realize.
This aligns with the kernel's per-device effective ATS reporting and allows
vfio-pci to mask ATS when the host kernel reports ATS as unsupported.
Emit a warning when ats=on is requested but the physical device does not
advertise ATS, since ATS cannot be exposed to the guest in this case.
Emit a warning when ats=auto, ats cap is present on the physical device,
but kernel reports ATS as unsupported.
Suggested-by: Shameer Kolothum <skolothumtho@nvidia.com>
Signed-off-by: Nathan Chen <nathanc@nvidia.com>
Reviewed-by: Shameer Kolothum <skolothumtho@nvidia.com>
Reviewed-by: Cédric Le Goater <clg@redhat.com>
Link: https://lore.kernel.org/qemu-devel/20260623204943.989903-3-nathanc@nvidia.com
Signed-off-by: Cédric Le Goater <clg@redhat.com>
---
hw/vfio/pci.h | 1 +
hw/vfio/pci.c | 88 ++++++++++++++++++++++++++++++++++++++++++++++++---
2 files changed, 85 insertions(+), 4 deletions(-)
diff --git a/hw/vfio/pci.h b/hw/vfio/pci.h
index cf56711587058b8cf5197945755fff2456168c00..fe52e9df6e67707c9899d418b0261afeedf4aab2 100644
--- a/hw/vfio/pci.h
+++ b/hw/vfio/pci.h
@@ -188,6 +188,7 @@ struct VFIOPCIDevice {
bool clear_parent_atomics_on_exit;
bool skip_vsc_check;
uint16_t vpasid_cap_offset;
+ OnOffAuto ats;
VFIODisplay *dpy;
Notifier irqchip_change_notifier;
VFIOPCICPR cpr;
diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c
index 6b04c6f94f9ade765e236d457e4828ac6199680a..c7f163399f8fbcc4ff70819a0d67879eb26980f9 100644
--- a/hw/vfio/pci.c
+++ b/hw/vfio/pci.c
@@ -2548,10 +2548,53 @@ static bool vfio_pci_synthesize_pasid_cap(VFIOPCIDevice *vdev, Error **errp)
return true;
}
-static void vfio_add_ext_cap(VFIOPCIDevice *vdev)
+/*
+ * Determine whether ATS capability should be advertised for @vdev, based on
+ * whether it was enabled on the command line and whether it is supported
+ * according to the kernel.
+ *
+ * Store whether ATS capability should be advertised in @ats_needed.
+ *
+ * Returns false only when ats=on is explicitly requested but the kernel
+ * reports it is not supported. Returns true in all other cases.
+ */
+static bool vfio_pci_ats_requested_and_supported(VFIOPCIDevice *vdev,
+ bool *ats_needed, Error **errp)
+{
+ HostIOMMUDevice *hiod = vdev->vbasedev.hiod;
+ HostIOMMUDeviceClass *hiodc;
+ bool ats_supported;
+ *ats_needed = false;
+
+ if (vdev->ats == ON_OFF_AUTO_OFF) {
+ return true;
+ }
+
+ *ats_needed = true;
+ if (!hiod) {
+ return true;
+ }
+ hiodc = HOST_IOMMU_DEVICE_GET_CLASS(hiod);
+ if (!hiodc || !hiodc->support_ats) {
+ return true;
+ }
+
+ ats_supported = hiodc->support_ats(hiod);
+ if (vdev->ats == ON_OFF_AUTO_ON && !ats_supported) {
+ error_setg(errp, "vfio-pci: ATS requested but not supported by kernel");
+ *ats_needed = false;
+ return false;
+ }
+
+ *ats_needed = ats_supported;
+ return true;
+}
+
+static void vfio_add_ext_cap(VFIOPCIDevice *vdev, bool ats_needed)
{
PCIDevice *pdev = PCI_DEVICE(vdev);
bool pasid_cap_added = false;
+ bool ats_cap_present = false;
Error *err = NULL;
uint32_t header;
uint16_t cap_id, next, size;
@@ -2637,7 +2680,19 @@ static void vfio_add_ext_cap(VFIOPCIDevice *vdev)
*/
case PCI_EXT_CAP_ID_PASID:
pasid_cap_added = true;
- /* fallthrough */
+ pcie_add_capability(pdev, cap_id, cap_ver, next, size);
+ break;
+ case PCI_EXT_CAP_ID_ATS:
+ ats_cap_present = true;
+ /*
+ * If ATS is requested and supported according to the kernel, add
+ * the ATS capability. If not supported according to the kernel or
+ * disabled on the qemu command line, omit the ATS cap.
+ */
+ if (ats_needed) {
+ pcie_add_capability(pdev, cap_id, cap_ver, next, size);
+ }
+ break;
default:
pcie_add_capability(pdev, cap_id, cap_ver, next, size);
}
@@ -2648,6 +2703,16 @@ static void vfio_add_ext_cap(VFIOPCIDevice *vdev)
error_report_err(err);
}
+ if (vdev->ats == ON_OFF_AUTO_ON && !ats_cap_present) {
+ warn_report("vfio-pci: ats=on requested, but host device has no "
+ "ATS extended capability");
+ }
+
+ if (vdev->ats == ON_OFF_AUTO_AUTO && ats_cap_present && !ats_needed) {
+ warn_report("vfio-pci: host kernel reports ATS unsupported; "
+ "ATS capability will be masked");
+ }
+
/* Cleanup chain head ID if necessary */
if (pci_get_word(pdev->config + PCI_CONFIG_SPACE_SIZE) == 0xFFFF) {
pci_set_word(pdev->config + PCI_CONFIG_SPACE_SIZE, 0);
@@ -2659,6 +2724,7 @@ static void vfio_add_ext_cap(VFIOPCIDevice *vdev)
bool vfio_pci_add_capabilities(VFIOPCIDevice *vdev, Error **errp)
{
PCIDevice *pdev = PCI_DEVICE(vdev);
+ bool ats_needed = false;
if (!(pdev->config[PCI_STATUS] & PCI_STATUS_CAP_LIST) ||
!pdev->config[PCI_CAPABILITY_LIST]) {
@@ -2669,7 +2735,11 @@ bool vfio_pci_add_capabilities(VFIOPCIDevice *vdev, Error **errp)
return false;
}
- vfio_add_ext_cap(vdev);
+ if (!vfio_pci_ats_requested_and_supported(vdev, &ats_needed, errp)) {
+ return false;
+ }
+
+ vfio_add_ext_cap(vdev, ats_needed);
return true;
}
@@ -3819,6 +3889,7 @@ static const Property vfio_pci_properties[] = {
DEFINE_PROP_BOOL("skip-vsc-check", VFIOPCIDevice, skip_vsc_check, true),
DEFINE_PROP_UINT16("x-vpasid-cap-offset", VFIOPCIDevice,
vpasid_cap_offset, 0),
+ DEFINE_PROP_ON_OFF_AUTO("ats", VFIOPCIDevice, ats, ON_OFF_AUTO_AUTO),
};
static void vfio_pci_set_fd(Object *obj, const char *str, Error **errp)
@@ -3970,13 +4041,22 @@ static void vfio_pci_class_init(ObjectClass *klass, const void *data)
"destination when doing live "
"migration of device state via "
"multifd channels");
- object_class_property_set_description(klass, /* 11.0 */
+ object_class_property_set_description(klass, /* 11.0 */
"x-vpasid-cap-offset",
"PCIe extended configuration space offset at which to place a "
"synthetic PASID extended capability when PASID is enabled via "
"a vIOMMU. A value of 0 (default) places the capability at the "
"end of the extended configuration space. The offset must be "
"4-byte aligned and within the PCIe extended configuration space");
+ object_class_property_set_description(klass, /* 11.1 */
+ "ats",
+ "Control guest visibility of the ATS PCIe extended capability. "
+ "Valid values are on, off, and auto (default). "
+ "'off' always masks ATS. "
+ "'on' requires ATS support for the device and fails realize if the "
+ "host kernel reports ATS as unavailable for this device. "
+ "'auto' masks ATS only when the host kernel reports "
+ "ATS as unavailable");
}
static const TypeInfo vfio_pci_info = {
--
2.54.0
next prev parent reply other threads:[~2026-07-07 6:31 UTC|newest]
Thread overview: 29+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-07 6:28 [PULL 00/27] vfio queue Cédric Le Goater
2026-07-07 6:28 ` [PULL 01/27] vfio/pci: Initialize rom_read_failed in vfio_pci_load_rom() Cédric Le Goater
2026-07-07 6:28 ` [PULL 02/27] vfio/pci: Fix information leak in vfio_rom_read() Cédric Le Goater
2026-07-07 6:28 ` [PULL 03/27] docs: Update vfio-user spec to describe DMA access mode bits Cédric Le Goater
2026-07-07 6:28 ` [PULL 04/27] vfio-user: validate VERSION replies Cédric Le Goater
2026-07-07 6:28 ` [PULL 05/27] vfio/iommufd: Merge .dma_map_file() into .dma_map() Cédric Le Goater
2026-07-07 6:28 ` [PULL 06/27] migration: Propagate errors in migration_completion_precopy() Cédric Le Goater
2026-07-07 6:29 ` [PULL 07/27] migration/ram: Use migration_bitmap_sync_precopy() for postcopy discard Cédric Le Goater
2026-07-07 6:29 ` [PULL 08/27] migration: Run final save_query_pending at switchover Cédric Le Goater
2026-07-07 6:29 ` [PULL 09/27] migration: Log the approver in qemu_loadvm_approve_switchover() Cédric Le Goater
2026-07-07 6:29 ` [PULL 10/27] migration: Replace switchover_ack_needed SaveVMHandler Cédric Le Goater
2026-07-07 6:29 ` [PULL 11/27] migration: Rename switchover-ack code to legacy Cédric Le Goater
2026-07-07 6:29 ` [PULL 12/27] migration: Make switchover-ack re-usable Cédric Le Goater
2026-07-07 6:29 ` [PULL 13/27] migration: Fail migration if switchover-ack is requested after switchover decision Cédric Le Goater
2026-07-07 6:29 ` [PULL 14/27] vfio/migration: Extract VFIO_MIG_FLAG_DEV_INIT_DATA_SENT sending to helper Cédric Le Goater
2026-07-07 6:29 ` [PULL 15/27] vfio/migration: Add Error ** parameter to vfio_migration_init() Cédric Le Goater
2026-07-07 6:29 ` [PULL 16/27] vfio/migration: Add new switchover-ack mechanism Cédric Le Goater
2026-07-07 6:29 ` [PULL 17/27] vfio/migration: Implement VFIO_PRECOPY_INFO_REINIT feature Cédric Le Goater
2026-07-07 6:29 ` [PULL 18/27] vfio/migration: Check VFIO_PRECOPY_INFO_REINIT during switchover Cédric Le Goater
2026-07-07 6:29 ` [PULL 19/27] migration: Enable new switchover-ack Cédric Le Goater
2026-07-07 6:29 ` [PULL 20/27] migration: Refactor migration_completion_precopy() to return bool Cédric Le Goater
2026-07-07 6:29 ` [PULL 21/27] migration: Fix "switchover" used as a verb in comments and docs Cédric Le Goater
2026-07-07 6:29 ` [PULL 22/27] iommufd: Introduce handler for device ATS support Cédric Le Goater
2026-07-07 6:29 ` Cédric Le Goater [this message]
2026-07-07 6:29 ` [PULL 24/27] vfio/pci: Propagate errors in vfio_pci_load_rom() using Error API Cédric Le Goater
2026-07-07 6:29 ` [PULL 25/27] vfio/listener: Fix translated_addr for non-identity-mapped RAM sections Cédric Le Goater
2026-07-07 6:29 ` [PULL 26/27] backends/iommufd: Fix dev_id and type order in viommu trace Cédric Le Goater
2026-07-07 6:29 ` [PULL 27/27] vfio/pci: Reject invalid MSI-X Table and PBA BIR values Cédric Le Goater
2026-07-08 5:53 ` [PULL 00/27] vfio queue Stefan Hajnoczi
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260707062920.317302-24-clg@redhat.com \
--to=clg@redhat.com \
--cc=nathanc@nvidia.com \
--cc=qemu-devel@nongnu.org \
--cc=skolothumtho@nvidia.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.