iommu: Add max_pasids field in struct iommu_device
authorLu Baolu <baolu.lu@linux.intel.com>
Mon, 31 Oct 2022 00:59:05 +0000 (08:59 +0800)
committerJoerg Roedel <jroedel@suse.de>
Thu, 3 Nov 2022 14:47:43 +0000 (15:47 +0100)
Use this field to keep the number of supported PASIDs that an IOMMU
hardware is able to support. This is a generic attribute of an IOMMU
and lifting it into the per-IOMMU device structure makes it possible
to allocate a PASID for device without calls into the IOMMU drivers.
Any iommu driver that supports PASID related features should set this
field before enabling them on the devices.

In the Intel IOMMU driver, intel_iommu_sm is moved to CONFIG_INTEL_IOMMU
enclave so that the pasid_supported() helper could be used in dmar.c
without compilation errors.

Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com>
Reviewed-by: Jean-Philippe Brucker <jean-philippe@linaro.org>
Reviewed-by: Kevin Tian <kevin.tian@intel.com>
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Reviewed-by: Yi Liu <yi.l.liu@intel.com>
Tested-by: Zhangfei Gao <zhangfei.gao@linaro.org>
Tested-by: Tony Zhu <tony.zhu@intel.com>
Link: https://lore.kernel.org/r/20221031005917.45690-2-baolu.lu@linux.intel.com
Signed-off-by: Joerg Roedel <jroedel@suse.de>
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
drivers/iommu/intel/dmar.c
drivers/iommu/intel/iommu.h
include/linux/iommu.h

index 6d5df91..21cb13d 100644 (file)
@@ -3543,6 +3543,7 @@ static int arm_smmu_device_hw_probe(struct arm_smmu_device *smmu)
        /* SID/SSID sizes */
        smmu->ssid_bits = FIELD_GET(IDR1_SSIDSIZE, reg);
        smmu->sid_bits = FIELD_GET(IDR1_SIDSIZE, reg);
+       smmu->iommu.max_pasids = 1UL << smmu->ssid_bits;
 
        /*
         * If the SMMU supports fewer bits than would fill a single L2 stream
index 5a8f780..3528058 100644 (file)
@@ -1105,6 +1105,13 @@ static int alloc_iommu(struct dmar_drhd_unit *drhd)
        raw_spin_lock_init(&iommu->register_lock);
 
        /*
+        * A value of N in PSS field of eCap register indicates hardware
+        * supports PASID field of N+1 bits.
+        */
+       if (pasid_supported(iommu))
+               iommu->iommu.max_pasids = 2UL << ecap_pss(iommu->ecap);
+
+       /*
         * This is only for hotplug; at boot time intel_iommu_enabled won't
         * be set yet. When intel_iommu_init() runs, it registers the units
         * present at boot time, then sets intel_iommu_enabled.
index 92023df..cce0598 100644 (file)
@@ -480,8 +480,6 @@ enum {
 #define VTD_FLAG_IRQ_REMAP_PRE_ENABLED (1 << 1)
 #define VTD_FLAG_SVM_CAPABLE           (1 << 2)
 
-extern int intel_iommu_sm;
-
 #define sm_supported(iommu)    (intel_iommu_sm && ecap_smts((iommu)->ecap))
 #define pasid_supported(iommu) (sm_supported(iommu) &&                 \
                                 ecap_pasid((iommu)->ecap))
@@ -795,6 +793,7 @@ struct context_entry *iommu_context_addr(struct intel_iommu *iommu, u8 bus,
 extern const struct iommu_ops intel_iommu_ops;
 
 #ifdef CONFIG_INTEL_IOMMU
+extern int intel_iommu_sm;
 extern int iommu_calculate_agaw(struct intel_iommu *iommu);
 extern int iommu_calculate_max_sagaw(struct intel_iommu *iommu);
 extern int dmar_disabled;
@@ -810,6 +809,7 @@ static inline int iommu_calculate_max_sagaw(struct intel_iommu *iommu)
 }
 #define dmar_disabled  (1)
 #define intel_iommu_enabled (0)
+#define intel_iommu_sm (0)
 #endif
 
 static inline const char *decode_prq_descriptor(char *str, size_t size,
index 3c9da1f..e3af4f4 100644 (file)
@@ -322,12 +322,14 @@ struct iommu_domain_ops {
  * @list: Used by the iommu-core to keep a list of registered iommus
  * @ops: iommu-ops for talking to this iommu
  * @dev: struct device for sysfs handling
+ * @max_pasids: number of supported PASIDs
  */
 struct iommu_device {
        struct list_head list;
        const struct iommu_ops *ops;
        struct fwnode_handle *fwnode;
        struct device *dev;
+       u32 max_pasids;
 };
 
 /**