aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYouquan Song <youquan.song@intel.com>2008-10-16 19:31:55 -0400
committerDavid Woodhouse <David.Woodhouse@intel.com>2008-10-17 03:03:14 -0400
commit3481f21097cb560392c411377893b5109fbde557 (patch)
tree5bc3165cb45a0d4bc04ce3d945b5ec8483939ed7
parentf05810c9962bba3e809f07619bda1bfdebbfbfb9 (diff)
dmar: context cache and IOTLB invalidation using queued invalidation
Implement context cache invalidate and IOTLB invalidation using queued invalidation interface. This interface will be used by DMA remapping, when queued invalidation is supported. Signed-off-by: Youquan Song <youquan.song@intel.com> Signed-off-by: Suresh Siddha <suresh.b.siddha@intel.com> Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
-rw-r--r--drivers/pci/dmar.c56
-rw-r--r--include/linux/intel-iommu.h21
2 files changed, 77 insertions, 0 deletions
diff --git a/drivers/pci/dmar.c b/drivers/pci/dmar.c
index b64cec190542..0f409e23631e 100644
--- a/drivers/pci/dmar.c
+++ b/drivers/pci/dmar.c
@@ -645,6 +645,62 @@ void qi_global_iec(struct intel_iommu *iommu)
645 qi_submit_sync(&desc, iommu); 645 qi_submit_sync(&desc, iommu);
646} 646}
647 647
648int qi_flush_context(struct intel_iommu *iommu, u16 did, u16 sid, u8 fm,
649 u64 type, int non_present_entry_flush)
650{
651
652 struct qi_desc desc;
653
654 if (non_present_entry_flush) {
655 if (!cap_caching_mode(iommu->cap))
656 return 1;
657 else
658 did = 0;
659 }
660
661 desc.low = QI_CC_FM(fm) | QI_CC_SID(sid) | QI_CC_DID(did)
662 | QI_CC_GRAN(type) | QI_CC_TYPE;
663 desc.high = 0;
664
665 qi_submit_sync(&desc, iommu);
666
667 return 0;
668
669}
670
671int qi_flush_iotlb(struct intel_iommu *iommu, u16 did, u64 addr,
672 unsigned int size_order, u64 type,
673 int non_present_entry_flush)
674{
675 u8 dw = 0, dr = 0;
676
677 struct qi_desc desc;
678 int ih = 0;
679
680 if (non_present_entry_flush) {
681 if (!cap_caching_mode(iommu->cap))
682 return 1;
683 else
684 did = 0;
685 }
686
687 if (cap_write_drain(iommu->cap))
688 dw = 1;
689
690 if (cap_read_drain(iommu->cap))
691 dr = 1;
692
693 desc.low = QI_IOTLB_DID(did) | QI_IOTLB_DR(dr) | QI_IOTLB_DW(dw)
694 | QI_IOTLB_GRAN(type) | QI_IOTLB_TYPE;
695 desc.high = QI_IOTLB_ADDR(addr) | QI_IOTLB_IH(ih)
696 | QI_IOTLB_AM(size_order);
697
698 qi_submit_sync(&desc, iommu);
699
700 return 0;
701
702}
703
648/* 704/*
649 * Enable Queued Invalidation interface. This is a must to support 705 * Enable Queued Invalidation interface. This is a must to support
650 * interrupt-remapping. Also used by DMA-remapping, which replaces 706 * interrupt-remapping. Also used by DMA-remapping, which replaces
diff --git a/include/linux/intel-iommu.h b/include/linux/intel-iommu.h
index 2e117f30a76c..0c5f5e49107b 100644
--- a/include/linux/intel-iommu.h
+++ b/include/linux/intel-iommu.h
@@ -127,6 +127,7 @@ static inline void dmar_writeq(void __iomem *addr, u64 val)
127 127
128 128
129/* IOTLB_REG */ 129/* IOTLB_REG */
130#define DMA_TLB_FLUSH_GRANU_OFFSET 60
130#define DMA_TLB_GLOBAL_FLUSH (((u64)1) << 60) 131#define DMA_TLB_GLOBAL_FLUSH (((u64)1) << 60)
131#define DMA_TLB_DSI_FLUSH (((u64)2) << 60) 132#define DMA_TLB_DSI_FLUSH (((u64)2) << 60)
132#define DMA_TLB_PSI_FLUSH (((u64)3) << 60) 133#define DMA_TLB_PSI_FLUSH (((u64)3) << 60)
@@ -140,6 +141,7 @@ static inline void dmar_writeq(void __iomem *addr, u64 val)
140#define DMA_TLB_MAX_SIZE (0x3f) 141#define DMA_TLB_MAX_SIZE (0x3f)
141 142
142/* INVALID_DESC */ 143/* INVALID_DESC */
144#define DMA_CCMD_INVL_GRANU_OFFSET 61
143#define DMA_ID_TLB_GLOBAL_FLUSH (((u64)1) << 3) 145#define DMA_ID_TLB_GLOBAL_FLUSH (((u64)1) << 3)
144#define DMA_ID_TLB_DSI_FLUSH (((u64)2) << 3) 146#define DMA_ID_TLB_DSI_FLUSH (((u64)2) << 3)
145#define DMA_ID_TLB_PSI_FLUSH (((u64)3) << 3) 147#define DMA_ID_TLB_PSI_FLUSH (((u64)3) << 3)
@@ -238,6 +240,19 @@ enum {
238#define QI_IWD_STATUS_DATA(d) (((u64)d) << 32) 240#define QI_IWD_STATUS_DATA(d) (((u64)d) << 32)
239#define QI_IWD_STATUS_WRITE (((u64)1) << 5) 241#define QI_IWD_STATUS_WRITE (((u64)1) << 5)
240 242
243#define QI_IOTLB_DID(did) (((u64)did) << 16)
244#define QI_IOTLB_DR(dr) (((u64)dr) << 7)
245#define QI_IOTLB_DW(dw) (((u64)dw) << 6)
246#define QI_IOTLB_GRAN(gran) (((u64)gran) >> (DMA_TLB_FLUSH_GRANU_OFFSET-4))
247#define QI_IOTLB_ADDR(addr) (((u64)addr) & PAGE_MASK_4K)
248#define QI_IOTLB_IH(ih) (((u64)ih) << 6)
249#define QI_IOTLB_AM(am) (((u8)am))
250
251#define QI_CC_FM(fm) (((u64)fm) << 48)
252#define QI_CC_SID(sid) (((u64)sid) << 32)
253#define QI_CC_DID(did) (((u64)did) << 16)
254#define QI_CC_GRAN(gran) (((u64)gran) >> (DMA_CCMD_INVL_GRANU_OFFSET-4))
255
241struct qi_desc { 256struct qi_desc {
242 u64 low, high; 257 u64 low, high;
243}; 258};
@@ -303,6 +318,12 @@ extern void free_iommu(struct intel_iommu *iommu);
303extern int dmar_enable_qi(struct intel_iommu *iommu); 318extern int dmar_enable_qi(struct intel_iommu *iommu);
304extern void qi_global_iec(struct intel_iommu *iommu); 319extern void qi_global_iec(struct intel_iommu *iommu);
305 320
321extern int qi_flush_context(struct intel_iommu *iommu, u16 did, u16 sid,
322 u8 fm, u64 type, int non_present_entry_flush);
323extern int qi_flush_iotlb(struct intel_iommu *iommu, u16 did, u64 addr,
324 unsigned int size_order, u64 type,
325 int non_present_entry_flush);
326
306extern void qi_submit_sync(struct qi_desc *desc, struct intel_iommu *iommu); 327extern void qi_submit_sync(struct qi_desc *desc, struct intel_iommu *iommu);
307 328
308void intel_iommu_domain_exit(struct dmar_domain *domain); 329void intel_iommu_domain_exit(struct dmar_domain *domain);