diff options
author | Joerg Roedel <joerg.roedel@amd.com> | 2011-11-17 08:18:46 -0500 |
---|---|---|
committer | Joerg Roedel <joerg.roedel@amd.com> | 2011-12-12 08:55:13 -0500 |
commit | 132bd68f180dd5de9176e20532910503f6393f14 (patch) | |
tree | 1fc1a0f0417427a47c6d352a3969ca1e1bf9f5fc /drivers | |
parent | 72e1dcc4192288ad5e37888aa1dbb23b3ef4aa9a (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.c | 38 | ||||
-rw-r--r-- | drivers/iommu/amd_iommu_proto.h | 3 |
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 | ||
1685 | static void set_dte_entry(u16 devid, struct protection_domain *domain, bool ats) | 1685 | static 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 | } |
2978 | EXPORT_SYMBOL(amd_iommu_unregister_ppr_notifier); | 2991 | EXPORT_SYMBOL(amd_iommu_unregister_ppr_notifier); |
2992 | |||
2993 | void 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 | } | ||
3012 | EXPORT_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); | |||
33 | extern void amd_iommu_init_api(void); | 33 | extern void amd_iommu_init_api(void); |
34 | 34 | ||
35 | /* IOMMUv2 specific functions */ | 35 | /* IOMMUv2 specific functions */ |
36 | struct iommu_domain; | ||
37 | |||
36 | extern bool amd_iommu_v2_supported(void); | 38 | extern bool amd_iommu_v2_supported(void); |
37 | extern int amd_iommu_register_ppr_notifier(struct notifier_block *nb); | 39 | extern int amd_iommu_register_ppr_notifier(struct notifier_block *nb); |
38 | extern int amd_iommu_unregister_ppr_notifier(struct notifier_block *nb); | 40 | extern int amd_iommu_unregister_ppr_notifier(struct notifier_block *nb); |
41 | extern 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 | ||