diff options
Diffstat (limited to 'include/linux/intel-iommu.h')
| -rw-r--r-- | include/linux/intel-iommu.h | 80 |
1 files changed, 73 insertions, 7 deletions
diff --git a/include/linux/intel-iommu.h b/include/linux/intel-iommu.h index ef169d67df92..28004d74ae04 100644 --- a/include/linux/intel-iommu.h +++ b/include/linux/intel-iommu.h | |||
| @@ -31,6 +31,7 @@ | |||
| 31 | #include <linux/list.h> | 31 | #include <linux/list.h> |
| 32 | #include <linux/iommu.h> | 32 | #include <linux/iommu.h> |
| 33 | #include <linux/io-64-nonatomic-lo-hi.h> | 33 | #include <linux/io-64-nonatomic-lo-hi.h> |
| 34 | #include <linux/dmar.h> | ||
| 34 | 35 | ||
| 35 | #include <asm/cacheflush.h> | 36 | #include <asm/cacheflush.h> |
| 36 | #include <asm/iommu.h> | 37 | #include <asm/iommu.h> |
| @@ -114,6 +115,7 @@ | |||
| 114 | * Extended Capability Register | 115 | * Extended Capability Register |
| 115 | */ | 116 | */ |
| 116 | 117 | ||
| 118 | #define ecap_dit(e) ((e >> 41) & 0x1) | ||
| 117 | #define ecap_pasid(e) ((e >> 40) & 0x1) | 119 | #define ecap_pasid(e) ((e >> 40) & 0x1) |
| 118 | #define ecap_pss(e) ((e >> 35) & 0x1f) | 120 | #define ecap_pss(e) ((e >> 35) & 0x1f) |
| 119 | #define ecap_eafs(e) ((e >> 34) & 0x1) | 121 | #define ecap_eafs(e) ((e >> 34) & 0x1) |
| @@ -284,6 +286,7 @@ enum { | |||
| 284 | #define QI_DEV_IOTLB_SID(sid) ((u64)((sid) & 0xffff) << 32) | 286 | #define QI_DEV_IOTLB_SID(sid) ((u64)((sid) & 0xffff) << 32) |
| 285 | #define QI_DEV_IOTLB_QDEP(qdep) (((qdep) & 0x1f) << 16) | 287 | #define QI_DEV_IOTLB_QDEP(qdep) (((qdep) & 0x1f) << 16) |
| 286 | #define QI_DEV_IOTLB_ADDR(addr) ((u64)(addr) & VTD_PAGE_MASK) | 288 | #define QI_DEV_IOTLB_ADDR(addr) ((u64)(addr) & VTD_PAGE_MASK) |
| 289 | #define QI_DEV_IOTLB_PFSID(pfsid) (((u64)(pfsid & 0xf) << 12) | ((u64)(pfsid & 0xfff) << 52)) | ||
| 287 | #define QI_DEV_IOTLB_SIZE 1 | 290 | #define QI_DEV_IOTLB_SIZE 1 |
| 288 | #define QI_DEV_IOTLB_MAX_INVS 32 | 291 | #define QI_DEV_IOTLB_MAX_INVS 32 |
| 289 | 292 | ||
| @@ -308,6 +311,7 @@ enum { | |||
| 308 | #define QI_DEV_EIOTLB_PASID(p) (((u64)p) << 32) | 311 | #define QI_DEV_EIOTLB_PASID(p) (((u64)p) << 32) |
| 309 | #define QI_DEV_EIOTLB_SID(sid) ((u64)((sid) & 0xffff) << 16) | 312 | #define QI_DEV_EIOTLB_SID(sid) ((u64)((sid) & 0xffff) << 16) |
| 310 | #define QI_DEV_EIOTLB_QDEP(qd) ((u64)((qd) & 0x1f) << 4) | 313 | #define QI_DEV_EIOTLB_QDEP(qd) ((u64)((qd) & 0x1f) << 4) |
| 314 | #define QI_DEV_EIOTLB_PFSID(pfsid) (((u64)(pfsid & 0xf) << 12) | ((u64)(pfsid & 0xfff) << 52)) | ||
| 311 | #define QI_DEV_EIOTLB_MAX_INVS 32 | 315 | #define QI_DEV_EIOTLB_MAX_INVS 32 |
| 312 | 316 | ||
| 313 | #define QI_PGRP_IDX(idx) (((u64)(idx)) << 55) | 317 | #define QI_PGRP_IDX(idx) (((u64)(idx)) << 55) |
| @@ -385,6 +389,42 @@ struct pasid_entry; | |||
| 385 | struct pasid_state_entry; | 389 | struct pasid_state_entry; |
| 386 | struct page_req_dsc; | 390 | struct page_req_dsc; |
| 387 | 391 | ||
| 392 | struct dmar_domain { | ||
| 393 | int nid; /* node id */ | ||
| 394 | |||
| 395 | unsigned iommu_refcnt[DMAR_UNITS_SUPPORTED]; | ||
| 396 | /* Refcount of devices per iommu */ | ||
| 397 | |||
| 398 | |||
| 399 | u16 iommu_did[DMAR_UNITS_SUPPORTED]; | ||
| 400 | /* Domain ids per IOMMU. Use u16 since | ||
| 401 | * domain ids are 16 bit wide according | ||
| 402 | * to VT-d spec, section 9.3 */ | ||
| 403 | |||
| 404 | bool has_iotlb_device; | ||
| 405 | struct list_head devices; /* all devices' list */ | ||
| 406 | struct iova_domain iovad; /* iova's that belong to this domain */ | ||
| 407 | |||
| 408 | struct dma_pte *pgd; /* virtual address */ | ||
| 409 | int gaw; /* max guest address width */ | ||
| 410 | |||
| 411 | /* adjusted guest address width, 0 is level 2 30-bit */ | ||
| 412 | int agaw; | ||
| 413 | |||
| 414 | int flags; /* flags to find out type of domain */ | ||
| 415 | |||
| 416 | int iommu_coherency;/* indicate coherency of iommu access */ | ||
| 417 | int iommu_snooping; /* indicate snooping control feature*/ | ||
| 418 | int iommu_count; /* reference count of iommu */ | ||
| 419 | int iommu_superpage;/* Level of superpages supported: | ||
| 420 | 0 == 4KiB (no superpages), 1 == 2MiB, | ||
| 421 | 2 == 1GiB, 3 == 512GiB, 4 == 1TiB */ | ||
| 422 | u64 max_addr; /* maximum mapped address */ | ||
| 423 | |||
| 424 | struct iommu_domain domain; /* generic domain data structure for | ||
| 425 | iommu core */ | ||
| 426 | }; | ||
| 427 | |||
| 388 | struct intel_iommu { | 428 | struct intel_iommu { |
| 389 | void __iomem *reg; /* Pointer to hardware regs, virtual addr */ | 429 | void __iomem *reg; /* Pointer to hardware regs, virtual addr */ |
| 390 | u64 reg_phys; /* physical address of hw register set */ | 430 | u64 reg_phys; /* physical address of hw register set */ |
| @@ -414,11 +454,9 @@ struct intel_iommu { | |||
| 414 | * devices away to userspace processes (e.g. for DPDK) and don't | 454 | * devices away to userspace processes (e.g. for DPDK) and don't |
| 415 | * want to trust that userspace will use *only* the PASID it was | 455 | * want to trust that userspace will use *only* the PASID it was |
| 416 | * told to. But while it's all driver-arbitrated, we're fine. */ | 456 | * told to. But while it's all driver-arbitrated, we're fine. */ |
| 417 | struct pasid_entry *pasid_table; | ||
| 418 | struct pasid_state_entry *pasid_state_table; | 457 | struct pasid_state_entry *pasid_state_table; |
| 419 | struct page_req_dsc *prq; | 458 | struct page_req_dsc *prq; |
| 420 | unsigned char prq_name[16]; /* Name for PRQ interrupt */ | 459 | unsigned char prq_name[16]; /* Name for PRQ interrupt */ |
| 421 | struct idr pasid_idr; | ||
| 422 | u32 pasid_max; | 460 | u32 pasid_max; |
| 423 | #endif | 461 | #endif |
| 424 | struct q_inval *qi; /* Queued invalidation info */ | 462 | struct q_inval *qi; /* Queued invalidation info */ |
| @@ -434,6 +472,27 @@ struct intel_iommu { | |||
| 434 | u32 flags; /* Software defined flags */ | 472 | u32 flags; /* Software defined flags */ |
| 435 | }; | 473 | }; |
| 436 | 474 | ||
| 475 | /* PCI domain-device relationship */ | ||
| 476 | struct device_domain_info { | ||
| 477 | struct list_head link; /* link to domain siblings */ | ||
| 478 | struct list_head global; /* link to global list */ | ||
| 479 | struct list_head table; /* link to pasid table */ | ||
| 480 | u8 bus; /* PCI bus number */ | ||
| 481 | u8 devfn; /* PCI devfn number */ | ||
| 482 | u16 pfsid; /* SRIOV physical function source ID */ | ||
| 483 | u8 pasid_supported:3; | ||
| 484 | u8 pasid_enabled:1; | ||
| 485 | u8 pri_supported:1; | ||
| 486 | u8 pri_enabled:1; | ||
| 487 | u8 ats_supported:1; | ||
| 488 | u8 ats_enabled:1; | ||
| 489 | u8 ats_qdep; | ||
| 490 | struct device *dev; /* it's NULL for PCIe-to-PCI bridge */ | ||
| 491 | struct intel_iommu *iommu; /* IOMMU used by this device */ | ||
| 492 | struct dmar_domain *domain; /* pointer to domain */ | ||
| 493 | struct pasid_table *pasid_table; /* pasid table */ | ||
| 494 | }; | ||
| 495 | |||
| 437 | static inline void __iommu_flush_cache( | 496 | static inline void __iommu_flush_cache( |
| 438 | struct intel_iommu *iommu, void *addr, int size) | 497 | struct intel_iommu *iommu, void *addr, int size) |
| 439 | { | 498 | { |
| @@ -453,16 +512,22 @@ extern void qi_flush_context(struct intel_iommu *iommu, u16 did, u16 sid, | |||
| 453 | u8 fm, u64 type); | 512 | u8 fm, u64 type); |
| 454 | extern void qi_flush_iotlb(struct intel_iommu *iommu, u16 did, u64 addr, | 513 | extern void qi_flush_iotlb(struct intel_iommu *iommu, u16 did, u64 addr, |
| 455 | unsigned int size_order, u64 type); | 514 | unsigned int size_order, u64 type); |
| 456 | extern void qi_flush_dev_iotlb(struct intel_iommu *iommu, u16 sid, u16 qdep, | 515 | extern void qi_flush_dev_iotlb(struct intel_iommu *iommu, u16 sid, u16 pfsid, |
| 457 | u64 addr, unsigned mask); | 516 | u16 qdep, u64 addr, unsigned mask); |
| 458 | |||
| 459 | extern int qi_submit_sync(struct qi_desc *desc, struct intel_iommu *iommu); | 517 | extern int qi_submit_sync(struct qi_desc *desc, struct intel_iommu *iommu); |
| 460 | 518 | ||
| 461 | extern int dmar_ir_support(void); | 519 | extern int dmar_ir_support(void); |
| 462 | 520 | ||
| 521 | struct dmar_domain *get_valid_domain_for_dev(struct device *dev); | ||
| 522 | void *alloc_pgtable_page(int node); | ||
| 523 | void free_pgtable_page(void *vaddr); | ||
| 524 | struct intel_iommu *domain_get_iommu(struct dmar_domain *domain); | ||
| 525 | int for_each_device_domain(int (*fn)(struct device_domain_info *info, | ||
| 526 | void *data), void *data); | ||
| 527 | |||
| 463 | #ifdef CONFIG_INTEL_IOMMU_SVM | 528 | #ifdef CONFIG_INTEL_IOMMU_SVM |
| 464 | extern int intel_svm_alloc_pasid_tables(struct intel_iommu *iommu); | 529 | int intel_svm_init(struct intel_iommu *iommu); |
| 465 | extern int intel_svm_free_pasid_tables(struct intel_iommu *iommu); | 530 | int intel_svm_exit(struct intel_iommu *iommu); |
| 466 | extern int intel_svm_enable_prq(struct intel_iommu *iommu); | 531 | extern int intel_svm_enable_prq(struct intel_iommu *iommu); |
| 467 | extern int intel_svm_finish_prq(struct intel_iommu *iommu); | 532 | extern int intel_svm_finish_prq(struct intel_iommu *iommu); |
| 468 | 533 | ||
| @@ -486,6 +551,7 @@ struct intel_svm { | |||
| 486 | int flags; | 551 | int flags; |
| 487 | int pasid; | 552 | int pasid; |
| 488 | struct list_head devs; | 553 | struct list_head devs; |
| 554 | struct list_head list; | ||
| 489 | }; | 555 | }; |
| 490 | 556 | ||
| 491 | extern int intel_iommu_enable_pasid(struct intel_iommu *iommu, struct intel_svm_dev *sdev); | 557 | extern int intel_iommu_enable_pasid(struct intel_iommu *iommu, struct intel_svm_dev *sdev); |
