aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoerg Roedel <joerg.roedel@amd.com>2009-09-02 08:24:08 -0400
committerJoerg Roedel <joerg.roedel@amd.com>2009-09-03 10:03:34 -0400
commit9355a08186e52b7c120adea91c984923b54efa10 (patch)
tree563c92011f7733fc20dfced74a058c809813ed0c
parent37d0892c5a94e208cf863e3b7bac014edee4346d (diff)
x86/amd-iommu: Make fetch_pte aware of dynamic mapping levels
This patch changes the fetch_pte function in the AMD IOMMU driver to support dynamic mapping levels. Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
-rw-r--r--arch/x86/include/asm/amd_iommu_types.h9
-rw-r--r--arch/x86/kernel/amd_iommu.c24
2 files changed, 22 insertions, 11 deletions
diff --git a/arch/x86/include/asm/amd_iommu_types.h b/arch/x86/include/asm/amd_iommu_types.h
index 0c878caaa0a2..7fce4ef77bdd 100644
--- a/arch/x86/include/asm/amd_iommu_types.h
+++ b/arch/x86/include/asm/amd_iommu_types.h
@@ -146,12 +146,21 @@
146#define PAGE_MODE_1_LEVEL 0x01 146#define PAGE_MODE_1_LEVEL 0x01
147#define PAGE_MODE_2_LEVEL 0x02 147#define PAGE_MODE_2_LEVEL 0x02
148#define PAGE_MODE_3_LEVEL 0x03 148#define PAGE_MODE_3_LEVEL 0x03
149#define PAGE_MODE_4_LEVEL 0x04
150#define PAGE_MODE_5_LEVEL 0x05
151#define PAGE_MODE_6_LEVEL 0x06
149 152
150#define IOMMU_PDE_NL_0 0x000ULL 153#define IOMMU_PDE_NL_0 0x000ULL
151#define IOMMU_PDE_NL_1 0x200ULL 154#define IOMMU_PDE_NL_1 0x200ULL
152#define IOMMU_PDE_NL_2 0x400ULL 155#define IOMMU_PDE_NL_2 0x400ULL
153#define IOMMU_PDE_NL_3 0x600ULL 156#define IOMMU_PDE_NL_3 0x600ULL
154 157
158#define PM_LEVEL_SHIFT(x) (12 + ((x) * 9))
159#define PM_LEVEL_SIZE(x) (((x) < 6) ? \
160 ((1ULL << PM_LEVEL_SHIFT((x))) - 1): \
161 (0xffffffffffffffffULL))
162#define PM_LEVEL_INDEX(x, a) (((a) >> PM_LEVEL_SHIFT((x))) & 0x1ffULL)
163
155#define IOMMU_PTE_L2_INDEX(address) (((address) >> 30) & 0x1ffULL) 164#define IOMMU_PTE_L2_INDEX(address) (((address) >> 30) & 0x1ffULL)
156#define IOMMU_PTE_L1_INDEX(address) (((address) >> 21) & 0x1ffULL) 165#define IOMMU_PTE_L1_INDEX(address) (((address) >> 21) & 0x1ffULL)
157#define IOMMU_PTE_L0_INDEX(address) (((address) >> 12) & 0x1ffULL) 166#define IOMMU_PTE_L0_INDEX(address) (((address) >> 12) & 0x1ffULL)
diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c
index 6c99f5037801..29bcd358b6ce 100644
--- a/arch/x86/kernel/amd_iommu.c
+++ b/arch/x86/kernel/amd_iommu.c
@@ -61,6 +61,8 @@ static u64* alloc_pte(struct protection_domain *dom,
61static void dma_ops_reserve_addresses(struct dma_ops_domain *dom, 61static void dma_ops_reserve_addresses(struct dma_ops_domain *dom,
62 unsigned long start_page, 62 unsigned long start_page,
63 unsigned int pages); 63 unsigned int pages);
64static u64 *fetch_pte(struct protection_domain *domain,
65 unsigned long address);
64 66
65#ifndef BUS_NOTIFY_UNBOUND_DRIVER 67#ifndef BUS_NOTIFY_UNBOUND_DRIVER
66#define BUS_NOTIFY_UNBOUND_DRIVER 0x0005 68#define BUS_NOTIFY_UNBOUND_DRIVER 0x0005
@@ -670,24 +672,24 @@ static int init_unity_mappings_for_device(struct dma_ops_domain *dma_dom,
670 * This function checks if there is a PTE for a given dma address. If 672 * This function checks if there is a PTE for a given dma address. If
671 * there is one, it returns the pointer to it. 673 * there is one, it returns the pointer to it.
672 */ 674 */
673static u64* fetch_pte(struct protection_domain *domain, 675static u64 *fetch_pte(struct protection_domain *domain,
674 unsigned long address) 676 unsigned long address)
675{ 677{
678 int level;
676 u64 *pte; 679 u64 *pte;
677 680
678 pte = &domain->pt_root[IOMMU_PTE_L2_INDEX(address)]; 681 level = domain->mode - 1;
682 pte = &domain->pt_root[PM_LEVEL_INDEX(level, address)];
679 683
680 if (!IOMMU_PTE_PRESENT(*pte)) 684 while (level > 0) {
681 return NULL; 685 if (!IOMMU_PTE_PRESENT(*pte))
686 return NULL;
682 687
683 pte = IOMMU_PTE_PAGE(*pte); 688 level -= 1;
684 pte = &pte[IOMMU_PTE_L1_INDEX(address)];
685 689
686 if (!IOMMU_PTE_PRESENT(*pte)) 690 pte = IOMMU_PTE_PAGE(*pte);
687 return NULL; 691 pte = &pte[PM_LEVEL_INDEX(level, address)];
688 692 }
689 pte = IOMMU_PTE_PAGE(*pte);
690 pte = &pte[IOMMU_PTE_L0_INDEX(address)];
691 693
692 return pte; 694 return pte;
693} 695}