From: Eric Auger <eric.auger@redhat.com>
To: eric.auger.pro@gmail.com, eric.auger@redhat.com,
qemu-devel@nongnu.org, qemu-arm@nongnu.org, mst@redhat.com,
jean-philippe@linaro.org, peter.maydell@linaro.org,
clg@redhat.com, yanghliu@redhat.com, zhenzhong.duan@intel.com,
alex.williamson@redhat.com
Subject: [PATCH v2 5/7] virtio-iommu : Retrieve page size mask on virtio_iommu_set_iommu_device()
Date: Mon, 1 Jul 2024 10:48:57 +0200 [thread overview]
Message-ID: <20240701084957.1567641-6-eric.auger@redhat.com> (raw)
In-Reply-To: <20240701084957.1567641-1-eric.auger@redhat.com>
Retrieve the Host IOMMU Device page size mask when this latter is set.
This allows to get the information much sooner than when relying on
IOMMU MR set_page_size_mask() call, whcih happens when the IOMMU MR
gets enabled. We introduce check_page_size_mask() helper whose code
is inherited from current virtio_iommu_set_page_size_mask()
implementation. This callback will be removed in a subsequent patch.
Signed-off-by: Eric Auger <eric.auger@redhat.com>
---
v1 -> v2:
- do not update the mask if the granule is frozen (Zhenzhong)
---
hw/virtio/virtio-iommu.c | 57 ++++++++++++++++++++++++++++++++++++++--
hw/virtio/trace-events | 1 +
2 files changed, 56 insertions(+), 2 deletions(-)
diff --git a/hw/virtio/virtio-iommu.c b/hw/virtio/virtio-iommu.c
index b8f75d2b1a..7d5db554af 100644
--- a/hw/virtio/virtio-iommu.c
+++ b/hw/virtio/virtio-iommu.c
@@ -598,9 +598,39 @@ out:
return ret;
}
+static bool check_page_size_mask(VirtIOIOMMU *viommu, uint64_t new_mask,
+ Error **errp)
+{
+ uint64_t cur_mask = viommu->config.page_size_mask;
+
+ if ((cur_mask & new_mask) == 0) {
+ error_setg(errp, "virtio-iommu reports a page size mask 0x%"PRIx64
+ " incompatible with currently supported mask 0x%"PRIx64,
+ new_mask, cur_mask);
+ return false;
+ }
+ /*
+ * Once the granule is frozen we can't change the mask anymore. If by
+ * chance the hotplugged device supports the same granule, we can still
+ * accept it.
+ */
+ if (viommu->granule_frozen) {
+ int cur_granule = ctz64(cur_mask);
+
+ if (!(BIT_ULL(cur_granule) & new_mask)) {
+ error_setg(errp,
+ "virtio-iommu does not support frozen granule 0x%llx",
+ BIT_ULL(cur_granule));
+ return false;
+ }
+ }
+ return true;
+}
+
static bool virtio_iommu_set_iommu_device(PCIBus *bus, void *opaque, int devfn,
HostIOMMUDevice *hiod, Error **errp)
{
+ ERRP_GUARD();
VirtIOIOMMU *viommu = opaque;
HostIOMMUDeviceClass *hiodc = HOST_IOMMU_DEVICE_GET_CLASS(hiod);
struct hiod_key *new_key;
@@ -623,8 +653,28 @@ static bool virtio_iommu_set_iommu_device(PCIBus *bus, void *opaque, int devfn,
hiod->aliased_devfn,
host_iova_ranges, errp);
if (ret) {
- g_list_free_full(host_iova_ranges, g_free);
- return false;
+ goto error;
+ }
+ }
+ if (hiodc->get_page_size_mask) {
+ uint64_t new_mask = hiodc->get_page_size_mask(hiod);
+
+ if (check_page_size_mask(viommu, new_mask, errp)) {
+ /*
+ * The default mask depends on the "granule" property. For example,
+ * with 4k granule, it is -(4 * KiB). When an assigned device has
+ * page size restrictions due to the hardware IOMMU configuration,
+ * apply this restriction to the mask.
+ */
+ trace_virtio_iommu_update_page_size_mask(hiod->name,
+ viommu->config.page_size_mask,
+ new_mask);
+ if (!viommu->granule_frozen) {
+ viommu->config.page_size_mask &= new_mask;
+ }
+ } else {
+ error_prepend(errp, "%s: ", hiod->name);
+ goto error;
}
}
@@ -637,6 +687,9 @@ static bool virtio_iommu_set_iommu_device(PCIBus *bus, void *opaque, int devfn,
g_list_free_full(host_iova_ranges, g_free);
return true;
+error:
+ g_list_free_full(host_iova_ranges, g_free);
+ return false;
}
static void
diff --git a/hw/virtio/trace-events b/hw/virtio/trace-events
index 3cf84e04a7..599d855ff6 100644
--- a/hw/virtio/trace-events
+++ b/hw/virtio/trace-events
@@ -132,6 +132,7 @@ virtio_iommu_notify_map(const char *name, uint64_t virt_start, uint64_t virt_end
virtio_iommu_notify_unmap(const char *name, uint64_t virt_start, uint64_t virt_end) "mr=%s virt_start=0x%"PRIx64" virt_end=0x%"PRIx64
virtio_iommu_remap(const char *name, uint64_t virt_start, uint64_t virt_end, uint64_t phys_start) "mr=%s virt_start=0x%"PRIx64" virt_end=0x%"PRIx64" phys_start=0x%"PRIx64
virtio_iommu_set_page_size_mask(const char *name, uint64_t old, uint64_t new) "mr=%s old_mask=0x%"PRIx64" new_mask=0x%"PRIx64
+virtio_iommu_update_page_size_mask(const char *name, uint64_t old, uint64_t new) "host iommu device=%s old_mask=0x%"PRIx64" new_mask=0x%"PRIx64
virtio_iommu_notify_flag_add(const char *name) "add notifier to mr %s"
virtio_iommu_notify_flag_del(const char *name) "del notifier from mr %s"
virtio_iommu_switch_address_space(uint8_t bus, uint8_t slot, uint8_t fn, bool on) "Device %02x:%02x.%x switching address space (iommu enabled=%d)"
--
2.41.0
next prev parent reply other threads:[~2024-07-01 8:51 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-07-01 8:48 [PATCH v2 0/7] VIRTIO-IOMMU/HostIOMMUDevice: Fixes and page size mask rework Eric Auger
2024-07-01 8:48 ` [PATCH v2 1/7] virtio-iommu: Fix error handling in virtio_iommu_set_host_iova_ranges() Eric Auger
2024-07-01 8:48 ` [PATCH v2 2/7] vfio-container-base: Introduce vfio_container_get_iova_ranges() helper Eric Auger
2024-07-01 8:48 ` [PATCH v2 3/7] HostIOMMUDevice : remove Error handle from get_iova_ranges callback Eric Auger
2024-07-01 8:48 ` [PATCH v2 4/7] HostIOMMUDevice: Introduce get_page_size_mask() callback Eric Auger
2024-07-01 8:48 ` Eric Auger [this message]
2024-07-01 9:45 ` [PATCH v2 5/7] virtio-iommu : Retrieve page size mask on virtio_iommu_set_iommu_device() Duan, Zhenzhong
2024-07-01 8:48 ` [PATCH v2 6/7] memory: remove IOMMU MR iommu_set_page_size_mask() callback Eric Auger
2024-07-01 8:48 ` [PATCH v2 7/7] virtio-iommu: Revert transient enablement of IOMMU MR in bypass mode Eric Auger
2024-07-01 21:14 ` [PATCH v2 0/7] VIRTIO-IOMMU/HostIOMMUDevice: Fixes and page size mask rework Michael S. Tsirkin
2024-07-01 21:14 ` Cédric Le Goater
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=20240701084957.1567641-6-eric.auger@redhat.com \
--to=eric.auger@redhat.com \
--cc=alex.williamson@redhat.com \
--cc=clg@redhat.com \
--cc=eric.auger.pro@gmail.com \
--cc=jean-philippe@linaro.org \
--cc=mst@redhat.com \
--cc=peter.maydell@linaro.org \
--cc=qemu-arm@nongnu.org \
--cc=qemu-devel@nongnu.org \
--cc=yanghliu@redhat.com \
--cc=zhenzhong.duan@intel.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.