aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/iommu/Makefile2
-rw-r--r--drivers/iommu/intel-iommu.c13
-rw-r--r--drivers/iommu/intel-pasid.c60
-rw-r--r--drivers/iommu/intel-pasid.h21
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
14obj-$(CONFIG_ARM_SMMU) += arm-smmu.o 14obj-$(CONFIG_ARM_SMMU) += arm-smmu.o
15obj-$(CONFIG_ARM_SMMU_V3) += arm-smmu-v3.o 15obj-$(CONFIG_ARM_SMMU_V3) += arm-smmu-v3.o
16obj-$(CONFIG_DMAR_TABLE) += dmar.o 16obj-$(CONFIG_DMAR_TABLE) += dmar.o
17obj-$(CONFIG_INTEL_IOMMU) += intel-iommu.o 17obj-$(CONFIG_INTEL_IOMMU) += intel-iommu.o intel-pasid.o
18obj-$(CONFIG_INTEL_IOMMU_SVM) += intel-svm.o 18obj-$(CONFIG_INTEL_IOMMU_SVM) += intel-svm.o
19obj-$(CONFIG_IPMMU_VMSA) += ipmmu-vmsa.o 19obj-$(CONFIG_IPMMU_VMSA) += ipmmu-vmsa.o
20obj-$(CONFIG_IRQ_REMAP) += intel_irq_remapping.o irq_remapping.o 20obj-$(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 */
23static DEFINE_SPINLOCK(pasid_lock);
24u32 intel_pasid_max_id = PASID_MAX;
25static DEFINE_IDR(pasid_idr);
26
27int 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
44void 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
51void *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
16extern u32 intel_pasid_max_id;
17int intel_pasid_alloc_id(void *ptr, int start, int end, gfp_t gfp);
18void intel_pasid_free_id(int pasid);
19void *intel_pasid_lookup_id(int pasid);
20
21#endif /* __INTEL_PASID_H */