diff options
author | Joerg Roedel <joerg.roedel@amd.com> | 2009-09-02 08:24:08 -0400 |
---|---|---|
committer | Joerg Roedel <joerg.roedel@amd.com> | 2009-09-03 10:03:34 -0400 |
commit | 9355a08186e52b7c120adea91c984923b54efa10 (patch) | |
tree | 563c92011f7733fc20dfced74a058c809813ed0c | |
parent | 37d0892c5a94e208cf863e3b7bac014edee4346d (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.h | 9 | ||||
-rw-r--r-- | arch/x86/kernel/amd_iommu.c | 24 |
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, | |||
61 | static void dma_ops_reserve_addresses(struct dma_ops_domain *dom, | 61 | static 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); |
64 | static 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 | */ |
673 | static u64* fetch_pte(struct protection_domain *domain, | 675 | static 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 | } |