aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorJoerg Roedel <joerg.roedel@amd.com>2011-11-17 08:18:46 -0500
committerJoerg Roedel <joerg.roedel@amd.com>2011-12-12 08:55:13 -0500
commit132bd68f180dd5de9176e20532910503f6393f14 (patch)
tree1fc1a0f0417427a47c6d352a3969ca1e1bf9f5fc /drivers
parent72e1dcc4192288ad5e37888aa1dbb23b3ef4aa9a (diff)
iommu/amd: Add amd_iommu_domain_direct_map function
This function can be used to switch a domain into paging-mode 0. In this mode all devices can access physical system memory directly without any remapping. Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/iommu/amd_iommu.c38
-rw-r--r--drivers/iommu/amd_iommu_proto.h3
2 files changed, 39 insertions, 2 deletions
diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index db9b788c28ba..6ed536769102 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -1684,9 +1684,12 @@ static bool dma_ops_domain(struct protection_domain *domain)
1684 1684
1685static void set_dte_entry(u16 devid, struct protection_domain *domain, bool ats) 1685static void set_dte_entry(u16 devid, struct protection_domain *domain, bool ats)
1686{ 1686{
1687 u64 pte_root = virt_to_phys(domain->pt_root); 1687 u64 pte_root = 0;
1688 u64 flags = 0; 1688 u64 flags = 0;
1689 1689
1690 if (domain->mode != PAGE_MODE_NONE)
1691 pte_root = virt_to_phys(domain->pt_root);
1692
1690 pte_root |= (domain->mode & DEV_ENTRY_MODE_MASK) 1693 pte_root |= (domain->mode & DEV_ENTRY_MODE_MASK)
1691 << DEV_ENTRY_MODE_SHIFT; 1694 << DEV_ENTRY_MODE_SHIFT;
1692 pte_root |= IOMMU_PTE_IR | IOMMU_PTE_IW | IOMMU_PTE_P | IOMMU_PTE_TV; 1695 pte_root |= IOMMU_PTE_IR | IOMMU_PTE_IW | IOMMU_PTE_P | IOMMU_PTE_TV;
@@ -2782,7 +2785,8 @@ static void amd_iommu_domain_destroy(struct iommu_domain *dom)
2782 2785
2783 BUG_ON(domain->dev_cnt != 0); 2786 BUG_ON(domain->dev_cnt != 0);
2784 2787
2785 free_pagetable(domain); 2788 if (domain->mode != PAGE_MODE_NONE)
2789 free_pagetable(domain);
2786 2790
2787 protection_domain_free(domain); 2791 protection_domain_free(domain);
2788 2792
@@ -2846,6 +2850,9 @@ static int amd_iommu_map(struct iommu_domain *dom, unsigned long iova,
2846 int prot = 0; 2850 int prot = 0;
2847 int ret; 2851 int ret;
2848 2852
2853 if (domain->mode == PAGE_MODE_NONE)
2854 return -EINVAL;
2855
2849 if (iommu_prot & IOMMU_READ) 2856 if (iommu_prot & IOMMU_READ)
2850 prot |= IOMMU_PROT_IR; 2857 prot |= IOMMU_PROT_IR;
2851 if (iommu_prot & IOMMU_WRITE) 2858 if (iommu_prot & IOMMU_WRITE)
@@ -2864,6 +2871,9 @@ static int amd_iommu_unmap(struct iommu_domain *dom, unsigned long iova,
2864 struct protection_domain *domain = dom->priv; 2871 struct protection_domain *domain = dom->priv;
2865 unsigned long page_size, unmap_size; 2872 unsigned long page_size, unmap_size;
2866 2873
2874 if (domain->mode == PAGE_MODE_NONE)
2875 return -EINVAL;
2876
2867 page_size = 0x1000UL << gfp_order; 2877 page_size = 0x1000UL << gfp_order;
2868 2878
2869 mutex_lock(&domain->api_lock); 2879 mutex_lock(&domain->api_lock);
@@ -2883,6 +2893,9 @@ static phys_addr_t amd_iommu_iova_to_phys(struct iommu_domain *dom,
2883 phys_addr_t paddr; 2893 phys_addr_t paddr;
2884 u64 *pte, __pte; 2894 u64 *pte, __pte;
2885 2895
2896 if (domain->mode == PAGE_MODE_NONE)
2897 return iova;
2898
2886 pte = fetch_pte(domain, iova); 2899 pte = fetch_pte(domain, iova);
2887 2900
2888 if (!pte || !IOMMU_PTE_PRESENT(*pte)) 2901 if (!pte || !IOMMU_PTE_PRESENT(*pte))
@@ -2976,3 +2989,24 @@ int amd_iommu_unregister_ppr_notifier(struct notifier_block *nb)
2976 return atomic_notifier_chain_unregister(&ppr_notifier, nb); 2989 return atomic_notifier_chain_unregister(&ppr_notifier, nb);
2977} 2990}
2978EXPORT_SYMBOL(amd_iommu_unregister_ppr_notifier); 2991EXPORT_SYMBOL(amd_iommu_unregister_ppr_notifier);
2992
2993void amd_iommu_domain_direct_map(struct iommu_domain *dom)
2994{
2995 struct protection_domain *domain = dom->priv;
2996 unsigned long flags;
2997
2998 spin_lock_irqsave(&domain->lock, flags);
2999
3000 /* Update data structure */
3001 domain->mode = PAGE_MODE_NONE;
3002 domain->updated = true;
3003
3004 /* Make changes visible to IOMMUs */
3005 update_domain(domain);
3006
3007 /* Page-table is not visible to IOMMU anymore, so free it */
3008 free_pagetable(domain);
3009
3010 spin_unlock_irqrestore(&domain->lock, flags);
3011}
3012EXPORT_SYMBOL(amd_iommu_domain_direct_map);
diff --git a/drivers/iommu/amd_iommu_proto.h b/drivers/iommu/amd_iommu_proto.h
index cfe2dfc64523..2c4554e963c7 100644
--- a/drivers/iommu/amd_iommu_proto.h
+++ b/drivers/iommu/amd_iommu_proto.h
@@ -33,9 +33,12 @@ extern void amd_iommu_init_notifier(void);
33extern void amd_iommu_init_api(void); 33extern void amd_iommu_init_api(void);
34 34
35/* IOMMUv2 specific functions */ 35/* IOMMUv2 specific functions */
36struct iommu_domain;
37
36extern bool amd_iommu_v2_supported(void); 38extern bool amd_iommu_v2_supported(void);
37extern int amd_iommu_register_ppr_notifier(struct notifier_block *nb); 39extern int amd_iommu_register_ppr_notifier(struct notifier_block *nb);
38extern int amd_iommu_unregister_ppr_notifier(struct notifier_block *nb); 40extern int amd_iommu_unregister_ppr_notifier(struct notifier_block *nb);
41extern void amd_iommu_domain_direct_map(struct iommu_domain *dom);
39 42
40#ifndef CONFIG_AMD_IOMMU_STATS 43#ifndef CONFIG_AMD_IOMMU_STATS
41 44