diff options
-rw-r--r-- | drivers/iommu/Makefile | 2 | ||||
-rw-r--r-- | drivers/iommu/intel-iommu.c | 13 | ||||
-rw-r--r-- | drivers/iommu/intel-pasid.c | 60 | ||||
-rw-r--r-- | drivers/iommu/intel-pasid.h | 21 |
4 files changed, 95 insertions, 1 deletions
diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile index 1fb695854809..0a190b4b2ada 100644 --- a/drivers/iommu/Makefile +++ b/drivers/iommu/Makefile | |||
@@ -14,7 +14,7 @@ obj-$(CONFIG_AMD_IOMMU_V2) += amd_iommu_v2.o | |||
14 | obj-$(CONFIG_ARM_SMMU) += arm-smmu.o | 14 | obj-$(CONFIG_ARM_SMMU) += arm-smmu.o |
15 | obj-$(CONFIG_ARM_SMMU_V3) += arm-smmu-v3.o | 15 | obj-$(CONFIG_ARM_SMMU_V3) += arm-smmu-v3.o |
16 | obj-$(CONFIG_DMAR_TABLE) += dmar.o | 16 | obj-$(CONFIG_DMAR_TABLE) += dmar.o |
17 | obj-$(CONFIG_INTEL_IOMMU) += intel-iommu.o | 17 | obj-$(CONFIG_INTEL_IOMMU) += intel-iommu.o intel-pasid.o |
18 | obj-$(CONFIG_INTEL_IOMMU_SVM) += intel-svm.o | 18 | obj-$(CONFIG_INTEL_IOMMU_SVM) += intel-svm.o |
19 | obj-$(CONFIG_IPMMU_VMSA) += ipmmu-vmsa.o | 19 | obj-$(CONFIG_IPMMU_VMSA) += ipmmu-vmsa.o |
20 | obj-$(CONFIG_IRQ_REMAP) += intel_irq_remapping.o irq_remapping.o | 20 | obj-$(CONFIG_IRQ_REMAP) += intel_irq_remapping.o irq_remapping.o |
diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index 497ef94c5a8c..fa15ed036ddc 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c | |||
@@ -53,6 +53,7 @@ | |||
53 | #include <asm/iommu.h> | 53 | #include <asm/iommu.h> |
54 | 54 | ||
55 | #include "irq_remapping.h" | 55 | #include "irq_remapping.h" |
56 | #include "intel-pasid.h" | ||
56 | 57 | ||
57 | #define ROOT_SIZE VTD_PAGE_SIZE | 58 | #define ROOT_SIZE VTD_PAGE_SIZE |
58 | #define CONTEXT_SIZE VTD_PAGE_SIZE | 59 | #define CONTEXT_SIZE VTD_PAGE_SIZE |
@@ -3293,6 +3294,18 @@ static int __init init_dmars(void) | |||
3293 | } | 3294 | } |
3294 | 3295 | ||
3295 | for_each_active_iommu(iommu, drhd) { | 3296 | for_each_active_iommu(iommu, drhd) { |
3297 | /* | ||
3298 | * Find the max pasid size of all IOMMU's in the system. | ||
3299 | * We need to ensure the system pasid table is no bigger | ||
3300 | * than the smallest supported. | ||
3301 | */ | ||
3302 | if (pasid_enabled(iommu)) { | ||
3303 | u32 temp = 2 << ecap_pss(iommu->ecap); | ||
3304 | |||
3305 | intel_pasid_max_id = min_t(u32, temp, | ||
3306 | intel_pasid_max_id); | ||
3307 | } | ||
3308 | |||
3296 | g_iommus[iommu->seq_id] = iommu; | 3309 | g_iommus[iommu->seq_id] = iommu; |
3297 | 3310 | ||
3298 | intel_iommu_init_qi(iommu); | 3311 | intel_iommu_init_qi(iommu); |
diff --git a/drivers/iommu/intel-pasid.c b/drivers/iommu/intel-pasid.c new file mode 100644 index 000000000000..e918fe01ce7f --- /dev/null +++ b/drivers/iommu/intel-pasid.c | |||
@@ -0,0 +1,60 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
2 | /** | ||
3 | * intel-pasid.c - PASID idr, table and entry manipulation | ||
4 | * | ||
5 | * Copyright (C) 2018 Intel Corporation | ||
6 | * | ||
7 | * Author: Lu Baolu <baolu.lu@linux.intel.com> | ||
8 | */ | ||
9 | |||
10 | #define pr_fmt(fmt) "DMAR: " fmt | ||
11 | |||
12 | #include <linux/dmar.h> | ||
13 | #include <linux/intel-iommu.h> | ||
14 | #include <linux/iommu.h> | ||
15 | #include <linux/memory.h> | ||
16 | #include <linux/spinlock.h> | ||
17 | |||
18 | #include "intel-pasid.h" | ||
19 | |||
20 | /* | ||
21 | * Intel IOMMU system wide PASID name space: | ||
22 | */ | ||
23 | static DEFINE_SPINLOCK(pasid_lock); | ||
24 | u32 intel_pasid_max_id = PASID_MAX; | ||
25 | static DEFINE_IDR(pasid_idr); | ||
26 | |||
27 | int intel_pasid_alloc_id(void *ptr, int start, int end, gfp_t gfp) | ||
28 | { | ||
29 | int ret, min, max; | ||
30 | |||
31 | min = max_t(int, start, PASID_MIN); | ||
32 | max = min_t(int, end, intel_pasid_max_id); | ||
33 | |||
34 | WARN_ON(in_interrupt()); | ||
35 | idr_preload(gfp); | ||
36 | spin_lock(&pasid_lock); | ||
37 | ret = idr_alloc(&pasid_idr, ptr, min, max, GFP_ATOMIC); | ||
38 | spin_unlock(&pasid_lock); | ||
39 | idr_preload_end(); | ||
40 | |||
41 | return ret; | ||
42 | } | ||
43 | |||
44 | void intel_pasid_free_id(int pasid) | ||
45 | { | ||
46 | spin_lock(&pasid_lock); | ||
47 | idr_remove(&pasid_idr, pasid); | ||
48 | spin_unlock(&pasid_lock); | ||
49 | } | ||
50 | |||
51 | void *intel_pasid_lookup_id(int pasid) | ||
52 | { | ||
53 | void *p; | ||
54 | |||
55 | spin_lock(&pasid_lock); | ||
56 | p = idr_find(&pasid_idr, pasid); | ||
57 | spin_unlock(&pasid_lock); | ||
58 | |||
59 | return p; | ||
60 | } | ||
diff --git a/drivers/iommu/intel-pasid.h b/drivers/iommu/intel-pasid.h new file mode 100644 index 000000000000..b1c5296290e5 --- /dev/null +++ b/drivers/iommu/intel-pasid.h | |||
@@ -0,0 +1,21 @@ | |||
1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
2 | /* | ||
3 | * intel-pasid.h - PASID idr, table and entry header | ||
4 | * | ||
5 | * Copyright (C) 2018 Intel Corporation | ||
6 | * | ||
7 | * Author: Lu Baolu <baolu.lu@linux.intel.com> | ||
8 | */ | ||
9 | |||
10 | #ifndef __INTEL_PASID_H | ||
11 | #define __INTEL_PASID_H | ||
12 | |||
13 | #define PASID_MIN 0x1 | ||
14 | #define PASID_MAX 0x100000 | ||
15 | |||
16 | extern u32 intel_pasid_max_id; | ||
17 | int intel_pasid_alloc_id(void *ptr, int start, int end, gfp_t gfp); | ||
18 | void intel_pasid_free_id(int pasid); | ||
19 | void *intel_pasid_lookup_id(int pasid); | ||
20 | |||
21 | #endif /* __INTEL_PASID_H */ | ||