diff options
Diffstat (limited to 'include/linux/intel-iommu.h')
-rw-r--r-- | include/linux/intel-iommu.h | 139 |
1 files changed, 124 insertions, 15 deletions
diff --git a/include/linux/intel-iommu.h b/include/linux/intel-iommu.h index 6240063bdcac..821273ca4873 100644 --- a/include/linux/intel-iommu.h +++ b/include/linux/intel-iommu.h | |||
@@ -1,5 +1,9 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2006, Intel Corporation. | 2 | * Copyright © 2006-2015, Intel Corporation. |
3 | * | ||
4 | * Authors: Ashok Raj <ashok.raj@intel.com> | ||
5 | * Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com> | ||
6 | * David Woodhouse <David.Woodhouse@intel.com> | ||
3 | * | 7 | * |
4 | * This program is free software; you can redistribute it and/or modify it | 8 | * This program is free software; you can redistribute it and/or modify it |
5 | * under the terms and conditions of the GNU General Public License, | 9 | * under the terms and conditions of the GNU General Public License, |
@@ -13,10 +17,6 @@ | |||
13 | * You should have received a copy of the GNU General Public License along with | 17 | * You should have received a copy of the GNU General Public License along with |
14 | * this program; if not, write to the Free Software Foundation, Inc., 59 Temple | 18 | * this program; if not, write to the Free Software Foundation, Inc., 59 Temple |
15 | * Place - Suite 330, Boston, MA 02111-1307 USA. | 19 | * Place - Suite 330, Boston, MA 02111-1307 USA. |
16 | * | ||
17 | * Copyright (C) 2006-2008 Intel Corporation | ||
18 | * Author: Ashok Raj <ashok.raj@intel.com> | ||
19 | * Author: Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com> | ||
20 | */ | 20 | */ |
21 | 21 | ||
22 | #ifndef _INTEL_IOMMU_H_ | 22 | #ifndef _INTEL_IOMMU_H_ |
@@ -25,7 +25,10 @@ | |||
25 | #include <linux/types.h> | 25 | #include <linux/types.h> |
26 | #include <linux/iova.h> | 26 | #include <linux/iova.h> |
27 | #include <linux/io.h> | 27 | #include <linux/io.h> |
28 | #include <linux/idr.h> | ||
28 | #include <linux/dma_remapping.h> | 29 | #include <linux/dma_remapping.h> |
30 | #include <linux/mmu_notifier.h> | ||
31 | #include <linux/list.h> | ||
29 | #include <asm/cacheflush.h> | 32 | #include <asm/cacheflush.h> |
30 | #include <asm/iommu.h> | 33 | #include <asm/iommu.h> |
31 | 34 | ||
@@ -57,16 +60,21 @@ | |||
57 | #define DMAR_IQA_REG 0x90 /* Invalidation queue addr register */ | 60 | #define DMAR_IQA_REG 0x90 /* Invalidation queue addr register */ |
58 | #define DMAR_ICS_REG 0x9c /* Invalidation complete status register */ | 61 | #define DMAR_ICS_REG 0x9c /* Invalidation complete status register */ |
59 | #define DMAR_IRTA_REG 0xb8 /* Interrupt remapping table addr register */ | 62 | #define DMAR_IRTA_REG 0xb8 /* Interrupt remapping table addr register */ |
63 | #define DMAR_PQH_REG 0xc0 /* Page request queue head register */ | ||
64 | #define DMAR_PQT_REG 0xc8 /* Page request queue tail register */ | ||
65 | #define DMAR_PQA_REG 0xd0 /* Page request queue address register */ | ||
66 | #define DMAR_PRS_REG 0xdc /* Page request status register */ | ||
67 | #define DMAR_PECTL_REG 0xe0 /* Page request event control register */ | ||
68 | #define DMAR_PEDATA_REG 0xe4 /* Page request event interrupt data register */ | ||
69 | #define DMAR_PEADDR_REG 0xe8 /* Page request event interrupt addr register */ | ||
70 | #define DMAR_PEUADDR_REG 0xec /* Page request event Upper address register */ | ||
60 | 71 | ||
61 | #define OFFSET_STRIDE (9) | 72 | #define OFFSET_STRIDE (9) |
62 | /* | 73 | |
63 | #define dmar_readl(dmar, reg) readl(dmar + reg) | 74 | #ifdef CONFIG_64BIT |
64 | #define dmar_readq(dmar, reg) ({ \ | 75 | #define dmar_readq(a) readq(a) |
65 | u32 lo, hi; \ | 76 | #define dmar_writeq(a,v) writeq(v,a) |
66 | lo = readl(dmar + reg); \ | 77 | #else |
67 | hi = readl(dmar + reg + 4); \ | ||
68 | (((u64) hi) << 32) + lo; }) | ||
69 | */ | ||
70 | static inline u64 dmar_readq(void __iomem *addr) | 78 | static inline u64 dmar_readq(void __iomem *addr) |
71 | { | 79 | { |
72 | u32 lo, hi; | 80 | u32 lo, hi; |
@@ -80,6 +88,7 @@ static inline void dmar_writeq(void __iomem *addr, u64 val) | |||
80 | writel((u32)val, addr); | 88 | writel((u32)val, addr); |
81 | writel((u32)(val >> 32), addr + 4); | 89 | writel((u32)(val >> 32), addr + 4); |
82 | } | 90 | } |
91 | #endif | ||
83 | 92 | ||
84 | #define DMAR_VER_MAJOR(v) (((v) & 0xf0) >> 4) | 93 | #define DMAR_VER_MAJOR(v) (((v) & 0xf0) >> 4) |
85 | #define DMAR_VER_MINOR(v) ((v) & 0x0f) | 94 | #define DMAR_VER_MINOR(v) ((v) & 0x0f) |
@@ -123,7 +132,7 @@ static inline void dmar_writeq(void __iomem *addr, u64 val) | |||
123 | #define ecap_srs(e) ((e >> 31) & 0x1) | 132 | #define ecap_srs(e) ((e >> 31) & 0x1) |
124 | #define ecap_ers(e) ((e >> 30) & 0x1) | 133 | #define ecap_ers(e) ((e >> 30) & 0x1) |
125 | #define ecap_prs(e) ((e >> 29) & 0x1) | 134 | #define ecap_prs(e) ((e >> 29) & 0x1) |
126 | /* PASID support used to be on bit 28 */ | 135 | #define ecap_broken_pasid(e) ((e >> 28) & 0x1) |
127 | #define ecap_dis(e) ((e >> 27) & 0x1) | 136 | #define ecap_dis(e) ((e >> 27) & 0x1) |
128 | #define ecap_nest(e) ((e >> 26) & 0x1) | 137 | #define ecap_nest(e) ((e >> 26) & 0x1) |
129 | #define ecap_mts(e) ((e >> 25) & 0x1) | 138 | #define ecap_mts(e) ((e >> 25) & 0x1) |
@@ -253,6 +262,11 @@ enum { | |||
253 | #define QI_DIOTLB_TYPE 0x3 | 262 | #define QI_DIOTLB_TYPE 0x3 |
254 | #define QI_IEC_TYPE 0x4 | 263 | #define QI_IEC_TYPE 0x4 |
255 | #define QI_IWD_TYPE 0x5 | 264 | #define QI_IWD_TYPE 0x5 |
265 | #define QI_EIOTLB_TYPE 0x6 | ||
266 | #define QI_PC_TYPE 0x7 | ||
267 | #define QI_DEIOTLB_TYPE 0x8 | ||
268 | #define QI_PGRP_RESP_TYPE 0x9 | ||
269 | #define QI_PSTRM_RESP_TYPE 0xa | ||
256 | 270 | ||
257 | #define QI_IEC_SELECTIVE (((u64)1) << 4) | 271 | #define QI_IEC_SELECTIVE (((u64)1) << 4) |
258 | #define QI_IEC_IIDEX(idx) (((u64)(idx & 0xffff) << 32)) | 272 | #define QI_IEC_IIDEX(idx) (((u64)(idx & 0xffff) << 32)) |
@@ -280,6 +294,53 @@ enum { | |||
280 | #define QI_DEV_IOTLB_SIZE 1 | 294 | #define QI_DEV_IOTLB_SIZE 1 |
281 | #define QI_DEV_IOTLB_MAX_INVS 32 | 295 | #define QI_DEV_IOTLB_MAX_INVS 32 |
282 | 296 | ||
297 | #define QI_PC_PASID(pasid) (((u64)pasid) << 32) | ||
298 | #define QI_PC_DID(did) (((u64)did) << 16) | ||
299 | #define QI_PC_GRAN(gran) (((u64)gran) << 4) | ||
300 | |||
301 | #define QI_PC_ALL_PASIDS (QI_PC_TYPE | QI_PC_GRAN(0)) | ||
302 | #define QI_PC_PASID_SEL (QI_PC_TYPE | QI_PC_GRAN(1)) | ||
303 | |||
304 | #define QI_EIOTLB_ADDR(addr) ((u64)(addr) & VTD_PAGE_MASK) | ||
305 | #define QI_EIOTLB_GL(gl) (((u64)gl) << 7) | ||
306 | #define QI_EIOTLB_IH(ih) (((u64)ih) << 6) | ||
307 | #define QI_EIOTLB_AM(am) (((u64)am)) | ||
308 | #define QI_EIOTLB_PASID(pasid) (((u64)pasid) << 32) | ||
309 | #define QI_EIOTLB_DID(did) (((u64)did) << 16) | ||
310 | #define QI_EIOTLB_GRAN(gran) (((u64)gran) << 4) | ||
311 | |||
312 | #define QI_DEV_EIOTLB_ADDR(a) ((u64)(a) & VTD_PAGE_MASK) | ||
313 | #define QI_DEV_EIOTLB_SIZE (((u64)1) << 11) | ||
314 | #define QI_DEV_EIOTLB_GLOB(g) ((u64)g) | ||
315 | #define QI_DEV_EIOTLB_PASID(p) (((u64)p) << 32) | ||
316 | #define QI_DEV_EIOTLB_SID(sid) ((u64)((sid) & 0xffff) << 32) | ||
317 | #define QI_DEV_EIOTLB_QDEP(qd) (((qd) & 0x1f) << 16) | ||
318 | #define QI_DEV_EIOTLB_MAX_INVS 32 | ||
319 | |||
320 | #define QI_PGRP_IDX(idx) (((u64)(idx)) << 55) | ||
321 | #define QI_PGRP_PRIV(priv) (((u64)(priv)) << 32) | ||
322 | #define QI_PGRP_RESP_CODE(res) ((u64)(res)) | ||
323 | #define QI_PGRP_PASID(pasid) (((u64)(pasid)) << 32) | ||
324 | #define QI_PGRP_DID(did) (((u64)(did)) << 16) | ||
325 | #define QI_PGRP_PASID_P(p) (((u64)(p)) << 4) | ||
326 | |||
327 | #define QI_PSTRM_ADDR(addr) (((u64)(addr)) & VTD_PAGE_MASK) | ||
328 | #define QI_PSTRM_DEVFN(devfn) (((u64)(devfn)) << 4) | ||
329 | #define QI_PSTRM_RESP_CODE(res) ((u64)(res)) | ||
330 | #define QI_PSTRM_IDX(idx) (((u64)(idx)) << 55) | ||
331 | #define QI_PSTRM_PRIV(priv) (((u64)(priv)) << 32) | ||
332 | #define QI_PSTRM_BUS(bus) (((u64)(bus)) << 24) | ||
333 | #define QI_PSTRM_PASID(pasid) (((u64)(pasid)) << 4) | ||
334 | |||
335 | #define QI_RESP_SUCCESS 0x0 | ||
336 | #define QI_RESP_INVALID 0x1 | ||
337 | #define QI_RESP_FAILURE 0xf | ||
338 | |||
339 | #define QI_GRAN_ALL_ALL 0 | ||
340 | #define QI_GRAN_NONG_ALL 1 | ||
341 | #define QI_GRAN_NONG_PASID 2 | ||
342 | #define QI_GRAN_PSI_PASID 3 | ||
343 | |||
283 | struct qi_desc { | 344 | struct qi_desc { |
284 | u64 low, high; | 345 | u64 low, high; |
285 | }; | 346 | }; |
@@ -327,6 +388,10 @@ enum { | |||
327 | #define VTD_FLAG_TRANS_PRE_ENABLED (1 << 0) | 388 | #define VTD_FLAG_TRANS_PRE_ENABLED (1 << 0) |
328 | #define VTD_FLAG_IRQ_REMAP_PRE_ENABLED (1 << 1) | 389 | #define VTD_FLAG_IRQ_REMAP_PRE_ENABLED (1 << 1) |
329 | 390 | ||
391 | struct pasid_entry; | ||
392 | struct pasid_state_entry; | ||
393 | struct page_req_dsc; | ||
394 | |||
330 | struct intel_iommu { | 395 | struct intel_iommu { |
331 | void __iomem *reg; /* Pointer to hardware regs, virtual addr */ | 396 | void __iomem *reg; /* Pointer to hardware regs, virtual addr */ |
332 | u64 reg_phys; /* physical address of hw register set */ | 397 | u64 reg_phys; /* physical address of hw register set */ |
@@ -338,7 +403,7 @@ struct intel_iommu { | |||
338 | int seq_id; /* sequence id of the iommu */ | 403 | int seq_id; /* sequence id of the iommu */ |
339 | int agaw; /* agaw of this iommu */ | 404 | int agaw; /* agaw of this iommu */ |
340 | int msagaw; /* max sagaw of this iommu */ | 405 | int msagaw; /* max sagaw of this iommu */ |
341 | unsigned int irq; | 406 | unsigned int irq, pr_irq; |
342 | u16 segment; /* PCI segment# */ | 407 | u16 segment; /* PCI segment# */ |
343 | unsigned char name[13]; /* Device Name */ | 408 | unsigned char name[13]; /* Device Name */ |
344 | 409 | ||
@@ -350,6 +415,18 @@ struct intel_iommu { | |||
350 | 415 | ||
351 | struct iommu_flush flush; | 416 | struct iommu_flush flush; |
352 | #endif | 417 | #endif |
418 | #ifdef CONFIG_INTEL_IOMMU_SVM | ||
419 | /* These are large and need to be contiguous, so we allocate just | ||
420 | * one for now. We'll maybe want to rethink that if we truly give | ||
421 | * devices away to userspace processes (e.g. for DPDK) and don't | ||
422 | * want to trust that userspace will use *only* the PASID it was | ||
423 | * told to. But while it's all driver-arbitrated, we're fine. */ | ||
424 | struct pasid_entry *pasid_table; | ||
425 | struct pasid_state_entry *pasid_state_table; | ||
426 | struct page_req_dsc *prq; | ||
427 | unsigned char prq_name[16]; /* Name for PRQ interrupt */ | ||
428 | struct idr pasid_idr; | ||
429 | #endif | ||
353 | struct q_inval *qi; /* Queued invalidation info */ | 430 | struct q_inval *qi; /* Queued invalidation info */ |
354 | u32 *iommu_state; /* Store iommu states between suspend and resume.*/ | 431 | u32 *iommu_state; /* Store iommu states between suspend and resume.*/ |
355 | 432 | ||
@@ -389,6 +466,38 @@ extern int qi_submit_sync(struct qi_desc *desc, struct intel_iommu *iommu); | |||
389 | 466 | ||
390 | extern int dmar_ir_support(void); | 467 | extern int dmar_ir_support(void); |
391 | 468 | ||
469 | #ifdef CONFIG_INTEL_IOMMU_SVM | ||
470 | extern int intel_svm_alloc_pasid_tables(struct intel_iommu *iommu); | ||
471 | extern int intel_svm_free_pasid_tables(struct intel_iommu *iommu); | ||
472 | extern int intel_svm_enable_prq(struct intel_iommu *iommu); | ||
473 | extern int intel_svm_finish_prq(struct intel_iommu *iommu); | ||
474 | |||
475 | struct svm_dev_ops; | ||
476 | |||
477 | struct intel_svm_dev { | ||
478 | struct list_head list; | ||
479 | struct rcu_head rcu; | ||
480 | struct device *dev; | ||
481 | struct svm_dev_ops *ops; | ||
482 | int users; | ||
483 | u16 did; | ||
484 | u16 dev_iotlb:1; | ||
485 | u16 sid, qdep; | ||
486 | }; | ||
487 | |||
488 | struct intel_svm { | ||
489 | struct mmu_notifier notifier; | ||
490 | struct mm_struct *mm; | ||
491 | struct intel_iommu *iommu; | ||
492 | int flags; | ||
493 | int pasid; | ||
494 | struct list_head devs; | ||
495 | }; | ||
496 | |||
497 | extern int intel_iommu_enable_pasid(struct intel_iommu *iommu, struct intel_svm_dev *sdev); | ||
498 | extern struct intel_iommu *intel_svm_device_to_iommu(struct device *dev); | ||
499 | #endif | ||
500 | |||
392 | extern const struct attribute_group *intel_iommu_groups[]; | 501 | extern const struct attribute_group *intel_iommu_groups[]; |
393 | 502 | ||
394 | #endif | 503 | #endif |