]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/commitdiff
iommu/vt-d: Global PASID name space
authorLu Baolu <baolu.lu@linux.intel.com>
Sat, 14 Jul 2018 07:46:54 +0000 (15:46 +0800)
committerJoerg Roedel <jroedel@suse.de>
Fri, 20 Jul 2018 12:44:23 +0000 (14:44 +0200)
This adds the system wide PASID name space for the PASID
allocation. Currently we are using per IOMMU PASID name
spaces which are not suitable for some use cases. For an
example, one application (associated with a PASID) might
talk to two physical devices simultaneously while the two
devices could reside behind two different IOMMU units.

Cc: Ashok Raj <ashok.raj@intel.com>
Cc: Jacob Pan <jacob.jun.pan@linux.intel.com>
Cc: Kevin Tian <kevin.tian@intel.com>
Cc: Liu Yi L <yi.l.liu@intel.com>
Suggested-by: Ashok Raj <ashok.raj@intel.com>
Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com>
Reviewed-by: Kevin Tian <kevin.tian@intel.com>
Reviewed-by: Liu Yi L <yi.l.liu@intel.com>
Reviewed-by: Peter Xu <peterx@redhat.com>
Signed-off-by: Joerg Roedel <jroedel@suse.de>
drivers/iommu/Makefile
drivers/iommu/intel-iommu.c
drivers/iommu/intel-pasid.c [new file with mode: 0644]
drivers/iommu/intel-pasid.h [new file with mode: 0644]

index 1fb695854809b0ff261dec43f51d72f90ff7e178..0a190b4b2ada8608c0b7beedb83a3cb5c77f6905 100644 (file)
@@ -14,7 +14,7 @@ obj-$(CONFIG_AMD_IOMMU_V2) += amd_iommu_v2.o
 obj-$(CONFIG_ARM_SMMU) += arm-smmu.o
 obj-$(CONFIG_ARM_SMMU_V3) += arm-smmu-v3.o
 obj-$(CONFIG_DMAR_TABLE) += dmar.o
-obj-$(CONFIG_INTEL_IOMMU) += intel-iommu.o
+obj-$(CONFIG_INTEL_IOMMU) += intel-iommu.o intel-pasid.o
 obj-$(CONFIG_INTEL_IOMMU_SVM) += intel-svm.o
 obj-$(CONFIG_IPMMU_VMSA) += ipmmu-vmsa.o
 obj-$(CONFIG_IRQ_REMAP) += intel_irq_remapping.o irq_remapping.o
index 497ef94c5a8c1e9ad3a0dc9b8296c5daa46445e2..fa15ed036ddcaacb508a518ae180625e9eaaf0c0 100644 (file)
@@ -53,6 +53,7 @@
 #include <asm/iommu.h>
 
 #include "irq_remapping.h"
+#include "intel-pasid.h"
 
 #define ROOT_SIZE              VTD_PAGE_SIZE
 #define CONTEXT_SIZE           VTD_PAGE_SIZE
@@ -3293,6 +3294,18 @@ static int __init init_dmars(void)
        }
 
        for_each_active_iommu(iommu, drhd) {
+               /*
+                * Find the max pasid size of all IOMMU's in the system.
+                * We need to ensure the system pasid table is no bigger
+                * than the smallest supported.
+                */
+               if (pasid_enabled(iommu)) {
+                       u32 temp = 2 << ecap_pss(iommu->ecap);
+
+                       intel_pasid_max_id = min_t(u32, temp,
+                                                  intel_pasid_max_id);
+               }
+
                g_iommus[iommu->seq_id] = iommu;
 
                intel_iommu_init_qi(iommu);
diff --git a/drivers/iommu/intel-pasid.c b/drivers/iommu/intel-pasid.c
new file mode 100644 (file)
index 0000000..e918fe0
--- /dev/null
@@ -0,0 +1,60 @@
+// SPDX-License-Identifier: GPL-2.0
+/**
+ * intel-pasid.c - PASID idr, table and entry manipulation
+ *
+ * Copyright (C) 2018 Intel Corporation
+ *
+ * Author: Lu Baolu <baolu.lu@linux.intel.com>
+ */
+
+#define pr_fmt(fmt)    "DMAR: " fmt
+
+#include <linux/dmar.h>
+#include <linux/intel-iommu.h>
+#include <linux/iommu.h>
+#include <linux/memory.h>
+#include <linux/spinlock.h>
+
+#include "intel-pasid.h"
+
+/*
+ * Intel IOMMU system wide PASID name space:
+ */
+static DEFINE_SPINLOCK(pasid_lock);
+u32 intel_pasid_max_id = PASID_MAX;
+static DEFINE_IDR(pasid_idr);
+
+int intel_pasid_alloc_id(void *ptr, int start, int end, gfp_t gfp)
+{
+       int ret, min, max;
+
+       min = max_t(int, start, PASID_MIN);
+       max = min_t(int, end, intel_pasid_max_id);
+
+       WARN_ON(in_interrupt());
+       idr_preload(gfp);
+       spin_lock(&pasid_lock);
+       ret = idr_alloc(&pasid_idr, ptr, min, max, GFP_ATOMIC);
+       spin_unlock(&pasid_lock);
+       idr_preload_end();
+
+       return ret;
+}
+
+void intel_pasid_free_id(int pasid)
+{
+       spin_lock(&pasid_lock);
+       idr_remove(&pasid_idr, pasid);
+       spin_unlock(&pasid_lock);
+}
+
+void *intel_pasid_lookup_id(int pasid)
+{
+       void *p;
+
+       spin_lock(&pasid_lock);
+       p = idr_find(&pasid_idr, pasid);
+       spin_unlock(&pasid_lock);
+
+       return p;
+}
diff --git a/drivers/iommu/intel-pasid.h b/drivers/iommu/intel-pasid.h
new file mode 100644 (file)
index 0000000..b1c5296
--- /dev/null
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * intel-pasid.h - PASID idr, table and entry header
+ *
+ * Copyright (C) 2018 Intel Corporation
+ *
+ * Author: Lu Baolu <baolu.lu@linux.intel.com>
+ */
+
+#ifndef __INTEL_PASID_H
+#define __INTEL_PASID_H
+
+#define PASID_MIN                      0x1
+#define PASID_MAX                      0x100000
+
+extern u32 intel_pasid_max_id;
+int intel_pasid_alloc_id(void *ptr, int start, int end, gfp_t gfp);
+void intel_pasid_free_id(int pasid);
+void *intel_pasid_lookup_id(int pasid);
+
+#endif /* __INTEL_PASID_H */