180 lines
5.5 KiB
Diff
180 lines
5.5 KiB
Diff
|
|
From a2735cd15160a62065a0a0b39af405c7b0f3fae8 Mon Sep 17 00:00:00 2001
|
||
|
|
From: Nicolin Chen <nicolinc@nvidia.com>
|
||
|
|
Date: Wed, 22 Jun 2022 14:41:27 -0700
|
||
|
|
Subject: [PATCH] hw/arm/smmu-common: Add iommufd helpers
|
||
|
|
|
||
|
|
Add a set of helper functions for IOMMUFD and new "struct SMMUS1Hwpt"
|
||
|
|
to store the nested hwpt information.
|
||
|
|
|
||
|
|
Signed-off-by: Nicolin Chen <nicolinc@nvidia.com>
|
||
|
|
---
|
||
|
|
hw/arm/smmu-common.c | 108 +++++++++++++++++++++++++++++++++++
|
||
|
|
include/hw/arm/smmu-common.h | 20 +++++++
|
||
|
|
2 files changed, 128 insertions(+)
|
||
|
|
|
||
|
|
diff --git a/hw/arm/smmu-common.c b/hw/arm/smmu-common.c
|
||
|
|
index 038ae857d8..a79eb34277 100644
|
||
|
|
--- a/hw/arm/smmu-common.c
|
||
|
|
+++ b/hw/arm/smmu-common.c
|
||
|
|
@@ -838,6 +838,114 @@ IOMMUMemoryRegion *smmu_iommu_mr(SMMUState *s, uint32_t sid)
|
||
|
|
return NULL;
|
||
|
|
}
|
||
|
|
|
||
|
|
+/* IOMMUFD helpers */
|
||
|
|
+int smmu_dev_get_info(SMMUDevice *sdev, uint32_t *data_type,
|
||
|
|
+ uint32_t data_len, void *data)
|
||
|
|
+{
|
||
|
|
+ uint64_t caps;
|
||
|
|
+
|
||
|
|
+ if (!sdev || !sdev->idev) {
|
||
|
|
+ return -ENOENT;
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+ return !iommufd_backend_get_device_info(sdev->idev->iommufd,
|
||
|
|
+ sdev->idev->devid, data_type, data,
|
||
|
|
+ data_len, &caps, NULL);
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
+void smmu_dev_uninstall_nested_ste(SMMUDevice *sdev, bool abort)
|
||
|
|
+{
|
||
|
|
+ HostIOMMUDeviceIOMMUFD *idev = sdev->idev;
|
||
|
|
+ SMMUS1Hwpt *s1_hwpt = sdev->s1_hwpt;
|
||
|
|
+ uint32_t hwpt_id;
|
||
|
|
+
|
||
|
|
+ if (!s1_hwpt || !sdev->viommu) {
|
||
|
|
+ return;
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+ if (abort) {
|
||
|
|
+ hwpt_id = sdev->viommu->abort_hwpt_id;
|
||
|
|
+ } else {
|
||
|
|
+ hwpt_id = sdev->viommu->bypass_hwpt_id;
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+ if (!host_iommu_device_iommufd_attach_hwpt(idev, hwpt_id, NULL)) {
|
||
|
|
+ return;
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+ iommufd_backend_free_id(idev->iommufd, s1_hwpt->hwpt_id);
|
||
|
|
+ sdev->s1_hwpt = NULL;
|
||
|
|
+ g_free(s1_hwpt);
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
+int smmu_dev_install_nested_ste(SMMUDevice *sdev, uint32_t data_type,
|
||
|
|
+ uint32_t data_len, void *data)
|
||
|
|
+{
|
||
|
|
+ SMMUViommu *viommu = sdev->viommu;
|
||
|
|
+ SMMUS1Hwpt *s1_hwpt = sdev->s1_hwpt;
|
||
|
|
+ HostIOMMUDeviceIOMMUFD *idev = sdev->idev;
|
||
|
|
+
|
||
|
|
+ if (!idev || !viommu) {
|
||
|
|
+ return -ENOENT;
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+ if (s1_hwpt) {
|
||
|
|
+ smmu_dev_uninstall_nested_ste(sdev, false);
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+ s1_hwpt = g_new0(SMMUS1Hwpt, 1);
|
||
|
|
+ if (!s1_hwpt) {
|
||
|
|
+ return -ENOMEM;
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+ s1_hwpt->smmu = sdev->smmu;
|
||
|
|
+ s1_hwpt->viommu = viommu;
|
||
|
|
+ s1_hwpt->iommufd = idev->iommufd;
|
||
|
|
+
|
||
|
|
+ if (!iommufd_backend_alloc_hwpt(idev->iommufd, idev->devid,
|
||
|
|
+ viommu->core->viommu_id, 0, data_type,
|
||
|
|
+ data_len, data, &s1_hwpt->hwpt_id, NULL)) {
|
||
|
|
+ goto free;
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+ if (!host_iommu_device_iommufd_attach_hwpt(idev, s1_hwpt->hwpt_id, NULL)) {
|
||
|
|
+ goto free_hwpt;
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+ sdev->s1_hwpt = s1_hwpt;
|
||
|
|
+
|
||
|
|
+ return 0;
|
||
|
|
+free_hwpt:
|
||
|
|
+ iommufd_backend_free_id(idev->iommufd, s1_hwpt->hwpt_id);
|
||
|
|
+free:
|
||
|
|
+ sdev->s1_hwpt = NULL;
|
||
|
|
+ g_free(s1_hwpt);
|
||
|
|
+
|
||
|
|
+ return -EINVAL;
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
+int smmu_hwpt_invalidate_cache(SMMUS1Hwpt *s1_hwpt, uint32_t type, uint32_t len,
|
||
|
|
+ uint32_t *num, void *reqs)
|
||
|
|
+{
|
||
|
|
+ if (!s1_hwpt) {
|
||
|
|
+ return -ENOENT;
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+ return iommufd_backend_invalidate_cache(s1_hwpt->iommufd, s1_hwpt->hwpt_id,
|
||
|
|
+ type, len, num, reqs);
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
+int smmu_viommu_invalidate_cache(IOMMUFDViommu *viommu, uint32_t type,
|
||
|
|
+ uint32_t len, uint32_t *num, void *reqs)
|
||
|
|
+{
|
||
|
|
+ if (!viommu) {
|
||
|
|
+ return -ENOENT;
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+ return iommufd_viommu_invalidate_cache(viommu->iommufd, viommu->viommu_id,
|
||
|
|
+ type, len, num, reqs);
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
/* Unmap all notifiers attached to @mr */
|
||
|
|
static void smmu_inv_notifiers_mr(IOMMUMemoryRegion *mr)
|
||
|
|
{
|
||
|
|
diff --git a/include/hw/arm/smmu-common.h b/include/hw/arm/smmu-common.h
|
||
|
|
index 3bfb68cef6..66dc7206ea 100644
|
||
|
|
--- a/include/hw/arm/smmu-common.h
|
||
|
|
+++ b/include/hw/arm/smmu-common.h
|
||
|
|
@@ -125,6 +125,15 @@ typedef struct SMMUViommu {
|
||
|
|
QLIST_ENTRY(SMMUViommu) next;
|
||
|
|
} SMMUViommu;
|
||
|
|
|
||
|
|
+typedef struct SMMUS1Hwpt {
|
||
|
|
+ void *smmu;
|
||
|
|
+ IOMMUFDBackend *iommufd;
|
||
|
|
+ SMMUViommu *viommu;
|
||
|
|
+ uint32_t hwpt_id;
|
||
|
|
+ QLIST_HEAD(, SMMUDevice) device_list;
|
||
|
|
+ QLIST_ENTRY(SMMUViommu) next;
|
||
|
|
+} SMMUS1Hwpt;
|
||
|
|
+
|
||
|
|
typedef struct SMMUDevice {
|
||
|
|
void *smmu;
|
||
|
|
PCIBus *bus;
|
||
|
|
@@ -132,6 +141,7 @@ typedef struct SMMUDevice {
|
||
|
|
IOMMUMemoryRegion iommu;
|
||
|
|
HostIOMMUDeviceIOMMUFD *idev;
|
||
|
|
SMMUViommu *viommu;
|
||
|
|
+ SMMUS1Hwpt *s1_hwpt;
|
||
|
|
AddressSpace as;
|
||
|
|
uint32_t cfg_cache_hits;
|
||
|
|
uint32_t cfg_cache_misses;
|
||
|
|
@@ -225,4 +235,14 @@ void smmu_iotlb_inv_iova(SMMUState *s, int asid, int vmid, dma_addr_t iova,
|
||
|
|
/* Unmap the range of all the notifiers registered to any IOMMU mr */
|
||
|
|
void smmu_inv_notifiers_all(SMMUState *s);
|
||
|
|
|
||
|
|
+/* IOMMUFD helpers */
|
||
|
|
+int smmu_dev_get_info(SMMUDevice *sdev, uint32_t *data_type,
|
||
|
|
+ uint32_t data_len, void *data);
|
||
|
|
+void smmu_dev_uninstall_nested_ste(SMMUDevice *sdev, bool abort);
|
||
|
|
+int smmu_dev_install_nested_ste(SMMUDevice *sdev, uint32_t data_type,
|
||
|
|
+ uint32_t data_len, void *data);
|
||
|
|
+int smmu_hwpt_invalidate_cache(SMMUS1Hwpt *s1_hwpt, uint32_t type, uint32_t len,
|
||
|
|
+ uint32_t *num, void *reqs);
|
||
|
|
+int smmu_viommu_invalidate_cache(IOMMUFDViommu *viommu, uint32_t type,
|
||
|
|
+ uint32_t len, uint32_t *num, void *reqs);
|
||
|
|
#endif /* HW_ARM_SMMU_COMMON_H */
|
||
|
|
--
|
||
|
|
2.41.0.windows.1
|
||
|
|
|