* [PATCH 0/14] Page table handling updates for AMD-IOMMU (AMD-Vi)
@ 2009-09-04 9:40 Joerg Roedel
2009-09-04 9:40 ` [PATCH 01/14] x86/amd-iommu: Make fetch_pte aware of dynamic mapping levels Joerg Roedel
` (13 more replies)
0 siblings, 14 replies; 15+ messages in thread
From: Joerg Roedel @ 2009-09-04 9:40 UTC (permalink / raw)
To: iommu, linux-kernel
Hi,
this series of patches enhance the page table handling code for
AMD-IOMMU (AMD-Vi). With these patches the page table handling code is
able to map a full 64 bit device address space. The old limit was a 39
bit address space.
This series also contains initial patches for upcoming large page
support in the AMD-Vi driver. Full large page support requires changes
to the IOMMU-API which are not part of this patch set.
Joerg
Diffstat:
arch/x86/include/asm/amd_iommu_types.h | 38 +++---
arch/x86/kernel/amd_iommu.c | 242 ++++++++++++++++++++------------
2 files changed, 170 insertions(+), 110 deletions(-)
Shortlog:
Joerg Roedel (14):
x86/amd-iommu: Make fetch_pte aware of dynamic mapping levels
x86/amd-iommu: Use fetch_pte in iommu_unmap_page
x86/amd-iommu: Use fetch_pte in amd_iommu_iova_to_phys
x86/amd-iommu: Add a gneric version of amd_iommu_flush_all_devices
x86/amd-iommu: Introduce set_dte_entry function
x86/amd-iommu: Flush domains if address space size was increased
x86/amd-iommu: Introduce increase_address_space function
x86/amd-iommu: Change alloc_pte to support 64 bit address space
x86/amd-iommu: Remove last usages of IOMMU_PTE_L0_INDEX
x86/amd-iommu: Remove bus_addr check in iommu_map_page
x86/amd-iommu: Use 2-level page tables for dma_ops domains
x86/amd-iommu: Remove old page table handling macros
x86/amd-iommu: Support higher level PTEs in iommu_page_unmap
x86/amd-iommu: Change iommu_map_page to support multiple page sizes
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 01/14] x86/amd-iommu: Make fetch_pte aware of dynamic mapping levels
2009-09-04 9:40 [PATCH 0/14] Page table handling updates for AMD-IOMMU (AMD-Vi) Joerg Roedel
@ 2009-09-04 9:40 ` Joerg Roedel
2009-09-04 9:40 ` [PATCH 02/14] x86/amd-iommu: Use fetch_pte in iommu_unmap_page Joerg Roedel
` (12 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Joerg Roedel @ 2009-09-04 9:40 UTC (permalink / raw)
To: iommu, linux-kernel; +Cc: Joerg Roedel
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>
---
arch/x86/include/asm/amd_iommu_types.h | 9 +++++++++
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 0c878ca..7fce4ef 100644
--- a/arch/x86/include/asm/amd_iommu_types.h
+++ b/arch/x86/include/asm/amd_iommu_types.h
@@ -146,12 +146,21 @@
#define PAGE_MODE_1_LEVEL 0x01
#define PAGE_MODE_2_LEVEL 0x02
#define PAGE_MODE_3_LEVEL 0x03
+#define PAGE_MODE_4_LEVEL 0x04
+#define PAGE_MODE_5_LEVEL 0x05
+#define PAGE_MODE_6_LEVEL 0x06
#define IOMMU_PDE_NL_0 0x000ULL
#define IOMMU_PDE_NL_1 0x200ULL
#define IOMMU_PDE_NL_2 0x400ULL
#define IOMMU_PDE_NL_3 0x600ULL
+#define PM_LEVEL_SHIFT(x) (12 + ((x) * 9))
+#define PM_LEVEL_SIZE(x) (((x) < 6) ? \
+ ((1ULL << PM_LEVEL_SHIFT((x))) - 1): \
+ (0xffffffffffffffffULL))
+#define PM_LEVEL_INDEX(x, a) (((a) >> PM_LEVEL_SHIFT((x))) & 0x1ffULL)
+
#define IOMMU_PTE_L2_INDEX(address) (((address) >> 30) & 0x1ffULL)
#define IOMMU_PTE_L1_INDEX(address) (((address) >> 21) & 0x1ffULL)
#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 6c99f50..29bcd35 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,
static void dma_ops_reserve_addresses(struct dma_ops_domain *dom,
unsigned long start_page,
unsigned int pages);
+static u64 *fetch_pte(struct protection_domain *domain,
+ unsigned long address);
#ifndef BUS_NOTIFY_UNBOUND_DRIVER
#define BUS_NOTIFY_UNBOUND_DRIVER 0x0005
@@ -670,24 +672,24 @@ static int init_unity_mappings_for_device(struct dma_ops_domain *dma_dom,
* This function checks if there is a PTE for a given dma address. If
* there is one, it returns the pointer to it.
*/
-static u64* fetch_pte(struct protection_domain *domain,
+static u64 *fetch_pte(struct protection_domain *domain,
unsigned long address)
{
+ int level;
u64 *pte;
- pte = &domain->pt_root[IOMMU_PTE_L2_INDEX(address)];
+ level = domain->mode - 1;
+ pte = &domain->pt_root[PM_LEVEL_INDEX(level, address)];
- if (!IOMMU_PTE_PRESENT(*pte))
- return NULL;
+ while (level > 0) {
+ if (!IOMMU_PTE_PRESENT(*pte))
+ return NULL;
- pte = IOMMU_PTE_PAGE(*pte);
- pte = &pte[IOMMU_PTE_L1_INDEX(address)];
+ level -= 1;
- if (!IOMMU_PTE_PRESENT(*pte))
- return NULL;
-
- pte = IOMMU_PTE_PAGE(*pte);
- pte = &pte[IOMMU_PTE_L0_INDEX(address)];
+ pte = IOMMU_PTE_PAGE(*pte);
+ pte = &pte[PM_LEVEL_INDEX(level, address)];
+ }
return pte;
}
--
1.6.3.3
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 02/14] x86/amd-iommu: Use fetch_pte in iommu_unmap_page
2009-09-04 9:40 [PATCH 0/14] Page table handling updates for AMD-IOMMU (AMD-Vi) Joerg Roedel
2009-09-04 9:40 ` [PATCH 01/14] x86/amd-iommu: Make fetch_pte aware of dynamic mapping levels Joerg Roedel
@ 2009-09-04 9:40 ` Joerg Roedel
2009-09-04 9:40 ` [PATCH 03/14] x86/amd-iommu: Use fetch_pte in amd_iommu_iova_to_phys Joerg Roedel
` (11 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Joerg Roedel @ 2009-09-04 9:40 UTC (permalink / raw)
To: iommu, linux-kernel; +Cc: Joerg Roedel
Instead of reimplementing existing logic use fetch_pte to
walk the page table in iommu_unmap_page.
Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
---
arch/x86/kernel/amd_iommu.c | 19 +++----------------
1 files changed, 3 insertions(+), 16 deletions(-)
diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c
index 29bcd35..5e52798 100644
--- a/arch/x86/kernel/amd_iommu.c
+++ b/arch/x86/kernel/amd_iommu.c
@@ -546,23 +546,10 @@ static int iommu_map_page(struct protection_domain *dom,
static void iommu_unmap_page(struct protection_domain *dom,
unsigned long bus_addr)
{
- u64 *pte;
-
- pte = &dom->pt_root[IOMMU_PTE_L2_INDEX(bus_addr)];
-
- if (!IOMMU_PTE_PRESENT(*pte))
- return;
-
- pte = IOMMU_PTE_PAGE(*pte);
- pte = &pte[IOMMU_PTE_L1_INDEX(bus_addr)];
-
- if (!IOMMU_PTE_PRESENT(*pte))
- return;
-
- pte = IOMMU_PTE_PAGE(*pte);
- pte = &pte[IOMMU_PTE_L1_INDEX(bus_addr)];
+ u64 *pte = fetch_pte(dom, bus_addr);
- *pte = 0;
+ if (pte)
+ *pte = 0;
}
/*
--
1.6.3.3
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 03/14] x86/amd-iommu: Use fetch_pte in amd_iommu_iova_to_phys
2009-09-04 9:40 [PATCH 0/14] Page table handling updates for AMD-IOMMU (AMD-Vi) Joerg Roedel
2009-09-04 9:40 ` [PATCH 01/14] x86/amd-iommu: Make fetch_pte aware of dynamic mapping levels Joerg Roedel
2009-09-04 9:40 ` [PATCH 02/14] x86/amd-iommu: Use fetch_pte in iommu_unmap_page Joerg Roedel
@ 2009-09-04 9:40 ` Joerg Roedel
2009-09-04 9:40 ` [PATCH 04/14] x86/amd-iommu: Add a gneric version of amd_iommu_flush_all_devices Joerg Roedel
` (10 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Joerg Roedel @ 2009-09-04 9:40 UTC (permalink / raw)
To: iommu, linux-kernel; +Cc: Joerg Roedel
Don't reimplement the page table walker in this function.
Use the generic one.
Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
---
arch/x86/kernel/amd_iommu.c | 16 ++--------------
1 files changed, 2 insertions(+), 14 deletions(-)
diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c
index 5e52798..4a54366 100644
--- a/arch/x86/kernel/amd_iommu.c
+++ b/arch/x86/kernel/amd_iommu.c
@@ -2140,21 +2140,9 @@ static phys_addr_t amd_iommu_iova_to_phys(struct iommu_domain *dom,
phys_addr_t paddr;
u64 *pte;
- pte = &domain->pt_root[IOMMU_PTE_L2_INDEX(iova)];
+ pte = fetch_pte(domain, iova);
- if (!IOMMU_PTE_PRESENT(*pte))
- return 0;
-
- pte = IOMMU_PTE_PAGE(*pte);
- pte = &pte[IOMMU_PTE_L1_INDEX(iova)];
-
- if (!IOMMU_PTE_PRESENT(*pte))
- return 0;
-
- pte = IOMMU_PTE_PAGE(*pte);
- pte = &pte[IOMMU_PTE_L0_INDEX(iova)];
-
- if (!IOMMU_PTE_PRESENT(*pte))
+ if (!pte || !IOMMU_PTE_PRESENT(*pte))
return 0;
paddr = *pte & IOMMU_PAGE_MASK;
--
1.6.3.3
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 04/14] x86/amd-iommu: Add a gneric version of amd_iommu_flush_all_devices
2009-09-04 9:40 [PATCH 0/14] Page table handling updates for AMD-IOMMU (AMD-Vi) Joerg Roedel
` (2 preceding siblings ...)
2009-09-04 9:40 ` [PATCH 03/14] x86/amd-iommu: Use fetch_pte in amd_iommu_iova_to_phys Joerg Roedel
@ 2009-09-04 9:40 ` Joerg Roedel
2009-09-04 9:40 ` [PATCH 05/14] x86/amd-iommu: Introduce set_dte_entry function Joerg Roedel
` (9 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Joerg Roedel @ 2009-09-04 9:40 UTC (permalink / raw)
To: iommu, linux-kernel; +Cc: Joerg Roedel
This patch adds a generic variant of
amd_iommu_flush_all_devices function which flushes only the
DTEs for a given protection domain.
Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
---
arch/x86/kernel/amd_iommu.c | 10 ++++++++--
1 files changed, 8 insertions(+), 2 deletions(-)
diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c
index 4a54366..5265dd1 100644
--- a/arch/x86/kernel/amd_iommu.c
+++ b/arch/x86/kernel/amd_iommu.c
@@ -481,13 +481,14 @@ void amd_iommu_flush_all_domains(void)
}
}
-void amd_iommu_flush_all_devices(void)
+static void flush_devices_by_domain(struct protection_domain *domain)
{
struct amd_iommu *iommu;
int i;
for (i = 0; i <= amd_iommu_last_bdf; ++i) {
- if (amd_iommu_pd_table[i] == NULL)
+ if ((domain == NULL && amd_iommu_pd_table[i] == NULL) ||
+ (amd_iommu_pd_table[i] != domain))
continue;
iommu = amd_iommu_rlookup_table[i];
@@ -499,6 +500,11 @@ void amd_iommu_flush_all_devices(void)
}
}
+void amd_iommu_flush_all_devices(void)
+{
+ flush_devices_by_domain(NULL);
+}
+
/****************************************************************************
*
* The functions below are used the create the page table mappings for
--
1.6.3.3
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 05/14] x86/amd-iommu: Introduce set_dte_entry function
2009-09-04 9:40 [PATCH 0/14] Page table handling updates for AMD-IOMMU (AMD-Vi) Joerg Roedel
` (3 preceding siblings ...)
2009-09-04 9:40 ` [PATCH 04/14] x86/amd-iommu: Add a gneric version of amd_iommu_flush_all_devices Joerg Roedel
@ 2009-09-04 9:40 ` Joerg Roedel
2009-09-04 9:40 ` [PATCH 06/14] x86/amd-iommu: Flush domains if address space size was increased Joerg Roedel
` (8 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Joerg Roedel @ 2009-09-04 9:40 UTC (permalink / raw)
To: iommu, linux-kernel; +Cc: Joerg Roedel
This function factors out some logic of attach_device to a
seperate function. This new function will be used to update
device table entries when necessary.
Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
---
arch/x86/kernel/amd_iommu.c | 27 +++++++++++++++++----------
1 files changed, 17 insertions(+), 10 deletions(-)
diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c
index 5265dd1..0fab1f1 100644
--- a/arch/x86/kernel/amd_iommu.c
+++ b/arch/x86/kernel/amd_iommu.c
@@ -1058,18 +1058,10 @@ static struct protection_domain *domain_for_device(u16 devid)
return dom;
}
-/*
- * If a device is not yet associated with a domain, this function does
- * assigns it visible for the hardware
- */
-static void attach_device(struct amd_iommu *iommu,
- struct protection_domain *domain,
- u16 devid)
+static void set_dte_entry(u16 devid, struct protection_domain *domain)
{
- unsigned long flags;
u64 pte_root = virt_to_phys(domain->pt_root);
-
- domain->dev_cnt += 1;
+ unsigned long flags;
pte_root |= (domain->mode & DEV_ENTRY_MODE_MASK)
<< DEV_ENTRY_MODE_SHIFT;
@@ -1082,6 +1074,21 @@ static void attach_device(struct amd_iommu *iommu,
amd_iommu_pd_table[devid] = domain;
write_unlock_irqrestore(&amd_iommu_devtable_lock, flags);
+}
+
+/*
+ * If a device is not yet associated with a domain, this function does
+ * assigns it visible for the hardware
+ */
+static void attach_device(struct amd_iommu *iommu,
+ struct protection_domain *domain,
+ u16 devid)
+{
+ /* set the DTE entry */
+ set_dte_entry(devid, domain);
+
+ /* increase reference counter */
+ domain->dev_cnt += 1;
/*
* We might boot into a crash-kernel here. The crashed kernel
--
1.6.3.3
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 06/14] x86/amd-iommu: Flush domains if address space size was increased
2009-09-04 9:40 [PATCH 0/14] Page table handling updates for AMD-IOMMU (AMD-Vi) Joerg Roedel
` (4 preceding siblings ...)
2009-09-04 9:40 ` [PATCH 05/14] x86/amd-iommu: Introduce set_dte_entry function Joerg Roedel
@ 2009-09-04 9:40 ` Joerg Roedel
2009-09-04 9:40 ` [PATCH 07/14] x86/amd-iommu: Introduce increase_address_space function Joerg Roedel
` (7 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Joerg Roedel @ 2009-09-04 9:40 UTC (permalink / raw)
To: iommu, linux-kernel; +Cc: Joerg Roedel
Thist patch introduces the update_domain function which
propagates the larger address space of a protection domain
to the device table and flushes all relevant DTEs and the
domain TLB.
Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
---
arch/x86/include/asm/amd_iommu_types.h | 1 +
arch/x86/kernel/amd_iommu.c | 32 ++++++++++++++++++++++++++++++++
2 files changed, 33 insertions(+), 0 deletions(-)
diff --git a/arch/x86/include/asm/amd_iommu_types.h b/arch/x86/include/asm/amd_iommu_types.h
index 7fce4ef..97f3d09 100644
--- a/arch/x86/include/asm/amd_iommu_types.h
+++ b/arch/x86/include/asm/amd_iommu_types.h
@@ -235,6 +235,7 @@ struct protection_domain {
int mode; /* paging mode (0-6 levels) */
u64 *pt_root; /* page table root pointer */
unsigned long flags; /* flags to find out type of domain */
+ bool updated; /* complete domain flush required */
unsigned dev_cnt; /* devices assigned to this domain */
void *priv; /* private data */
};
diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c
index 0fab1f1..5eab6a8 100644
--- a/arch/x86/kernel/amd_iommu.c
+++ b/arch/x86/kernel/amd_iommu.c
@@ -63,6 +63,7 @@ static void dma_ops_reserve_addresses(struct dma_ops_domain *dom,
unsigned int pages);
static u64 *fetch_pte(struct protection_domain *domain,
unsigned long address);
+static void update_domain(struct protection_domain *domain);
#ifndef BUS_NOTIFY_UNBOUND_DRIVER
#define BUS_NOTIFY_UNBOUND_DRIVER 0x0005
@@ -546,6 +547,8 @@ static int iommu_map_page(struct protection_domain *dom,
*pte = __pte;
+ update_domain(dom);
+
return 0;
}
@@ -762,9 +765,13 @@ static int alloc_new_range(struct amd_iommu *iommu,
dma_ops_reserve_addresses(dma_dom, i << PAGE_SHIFT, 1);
}
+ update_domain(&dma_dom->domain);
+
return 0;
out_free:
+ update_domain(&dma_dom->domain);
+
free_page((unsigned long)dma_dom->aperture[index]->bitmap);
kfree(dma_dom->aperture[index]);
@@ -1294,6 +1301,29 @@ static int get_device_resources(struct device *dev,
return 1;
}
+static void update_device_table(struct protection_domain *domain)
+{
+ int i;
+
+ for (i = 0; i <= amd_iommu_last_bdf; ++i) {
+ if (amd_iommu_pd_table[i] != domain)
+ continue;
+ set_dte_entry(i, domain);
+ }
+}
+
+static void update_domain(struct protection_domain *domain)
+{
+ if (!domain->updated)
+ return;
+
+ update_device_table(domain);
+ flush_devices_by_domain(domain);
+ iommu_flush_domain(domain->id);
+
+ domain->updated = false;
+}
+
/*
* If the pte_page is not yet allocated this function is called
*/
@@ -1351,6 +1381,8 @@ static u64* dma_ops_get_pte(struct dma_ops_domain *dom,
} else
pte += IOMMU_PTE_L0_INDEX(address);
+ update_domain(&dom->domain);
+
return pte;
}
--
1.6.3.3
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 07/14] x86/amd-iommu: Introduce increase_address_space function
2009-09-04 9:40 [PATCH 0/14] Page table handling updates for AMD-IOMMU (AMD-Vi) Joerg Roedel
` (5 preceding siblings ...)
2009-09-04 9:40 ` [PATCH 06/14] x86/amd-iommu: Flush domains if address space size was increased Joerg Roedel
@ 2009-09-04 9:40 ` Joerg Roedel
2009-09-04 9:40 ` [PATCH 08/14] x86/amd-iommu: Change alloc_pte to support 64 bit address space Joerg Roedel
` (6 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Joerg Roedel @ 2009-09-04 9:40 UTC (permalink / raw)
To: iommu, linux-kernel; +Cc: Joerg Roedel
This function will be used to increase the address space
size of a protection domain.
Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
---
arch/x86/include/asm/amd_iommu_types.h | 4 ++++
arch/x86/kernel/amd_iommu.c | 27 +++++++++++++++++++++++++++
2 files changed, 31 insertions(+), 0 deletions(-)
diff --git a/arch/x86/include/asm/amd_iommu_types.h b/arch/x86/include/asm/amd_iommu_types.h
index 97f3d09..1b4b3d6 100644
--- a/arch/x86/include/asm/amd_iommu_types.h
+++ b/arch/x86/include/asm/amd_iommu_types.h
@@ -160,6 +160,10 @@
((1ULL << PM_LEVEL_SHIFT((x))) - 1): \
(0xffffffffffffffffULL))
#define PM_LEVEL_INDEX(x, a) (((a) >> PM_LEVEL_SHIFT((x))) & 0x1ffULL)
+#define PM_LEVEL_ENC(x) (((x) << 9) & 0xe00ULL)
+#define PM_LEVEL_PDE(x, a) ((a) | PM_LEVEL_ENC((x)) | \
+ IOMMU_PTE_P | IOMMU_PTE_IR | IOMMU_PTE_IW)
+
#define IOMMU_PTE_L2_INDEX(address) (((address) >> 30) & 0x1ffULL)
#define IOMMU_PTE_L1_INDEX(address) (((address) >> 21) & 0x1ffULL)
diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c
index 5eab6a8..fc97b51 100644
--- a/arch/x86/kernel/amd_iommu.c
+++ b/arch/x86/kernel/amd_iommu.c
@@ -1325,6 +1325,33 @@ static void update_domain(struct protection_domain *domain)
}
/*
+ * This function is used to add another level to an IO page table. Adding
+ * another level increases the size of the address space by 9 bits to a size up
+ * to 64 bits.
+ */
+static bool increase_address_space(struct protection_domain *domain,
+ gfp_t gfp)
+{
+ u64 *pte;
+
+ if (domain->mode == PAGE_MODE_6_LEVEL)
+ /* address space already 64 bit large */
+ return false;
+
+ pte = (void *)get_zeroed_page(gfp);
+ if (!pte)
+ return false;
+
+ *pte = PM_LEVEL_PDE(domain->mode,
+ virt_to_phys(domain->pt_root));
+ domain->pt_root = pte;
+ domain->mode += 1;
+ domain->updated = true;
+
+ return true;
+}
+
+/*
* If the pte_page is not yet allocated this function is called
*/
static u64* alloc_pte(struct protection_domain *dom,
--
1.6.3.3
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 08/14] x86/amd-iommu: Change alloc_pte to support 64 bit address space
2009-09-04 9:40 [PATCH 0/14] Page table handling updates for AMD-IOMMU (AMD-Vi) Joerg Roedel
` (6 preceding siblings ...)
2009-09-04 9:40 ` [PATCH 07/14] x86/amd-iommu: Introduce increase_address_space function Joerg Roedel
@ 2009-09-04 9:40 ` Joerg Roedel
2009-09-04 9:40 ` [PATCH 09/14] x86/amd-iommu: Remove last usages of IOMMU_PTE_L0_INDEX Joerg Roedel
` (5 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Joerg Roedel @ 2009-09-04 9:40 UTC (permalink / raw)
To: iommu, linux-kernel; +Cc: Joerg Roedel
This patch changes the alloc_pte function to be able to map
pages into the whole 64 bit address space supported by AMD
IOMMU hardware from the old limit of 2**39 bytes.
Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
---
arch/x86/kernel/amd_iommu.c | 44 +++++++++++++++++++-----------------------
1 files changed, 20 insertions(+), 24 deletions(-)
diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c
index fc97b51..3be2b61 100644
--- a/arch/x86/kernel/amd_iommu.c
+++ b/arch/x86/kernel/amd_iommu.c
@@ -55,7 +55,7 @@ struct iommu_cmd {
static int dma_ops_unity_map(struct dma_ops_domain *dma_dom,
struct unity_map_entry *e);
static struct dma_ops_domain *find_protection_domain(u16 devid);
-static u64* alloc_pte(struct protection_domain *dom,
+static u64 *alloc_pte(struct protection_domain *domain,
unsigned long address, u64
**pte_page, gfp_t gfp);
static void dma_ops_reserve_addresses(struct dma_ops_domain *dom,
@@ -1351,39 +1351,35 @@ static bool increase_address_space(struct protection_domain *domain,
return true;
}
-/*
- * If the pte_page is not yet allocated this function is called
- */
-static u64* alloc_pte(struct protection_domain *dom,
+static u64 *alloc_pte(struct protection_domain *domain,
unsigned long address, u64 **pte_page, gfp_t gfp)
{
u64 *pte, *page;
+ int level;
- pte = &dom->pt_root[IOMMU_PTE_L2_INDEX(address)];
+ while (address > PM_LEVEL_SIZE(domain->mode))
+ increase_address_space(domain, gfp);
- if (!IOMMU_PTE_PRESENT(*pte)) {
- page = (u64 *)get_zeroed_page(gfp);
- if (!page)
- return NULL;
- *pte = IOMMU_L2_PDE(virt_to_phys(page));
- }
+ level = domain->mode - 1;
+ pte = &domain->pt_root[PM_LEVEL_INDEX(level, address)];
- pte = IOMMU_PTE_PAGE(*pte);
- pte = &pte[IOMMU_PTE_L1_INDEX(address)];
+ while (level > 0) {
+ if (!IOMMU_PTE_PRESENT(*pte)) {
+ page = (u64 *)get_zeroed_page(gfp);
+ if (!page)
+ return NULL;
+ *pte = PM_LEVEL_PDE(level, virt_to_phys(page));
+ }
- if (!IOMMU_PTE_PRESENT(*pte)) {
- page = (u64 *)get_zeroed_page(gfp);
- if (!page)
- return NULL;
- *pte = IOMMU_L1_PDE(virt_to_phys(page));
- }
+ level -= 1;
- pte = IOMMU_PTE_PAGE(*pte);
+ pte = IOMMU_PTE_PAGE(*pte);
- if (pte_page)
- *pte_page = pte;
+ if (pte_page && level == 0)
+ *pte_page = pte;
- pte = &pte[IOMMU_PTE_L0_INDEX(address)];
+ pte = &pte[PM_LEVEL_INDEX(level, address)];
+ }
return pte;
}
--
1.6.3.3
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 09/14] x86/amd-iommu: Remove last usages of IOMMU_PTE_L0_INDEX
2009-09-04 9:40 [PATCH 0/14] Page table handling updates for AMD-IOMMU (AMD-Vi) Joerg Roedel
` (7 preceding siblings ...)
2009-09-04 9:40 ` [PATCH 08/14] x86/amd-iommu: Change alloc_pte to support 64 bit address space Joerg Roedel
@ 2009-09-04 9:40 ` Joerg Roedel
2009-09-04 9:40 ` [PATCH 10/14] x86/amd-iommu: Remove bus_addr check in iommu_map_page Joerg Roedel
` (4 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Joerg Roedel @ 2009-09-04 9:40 UTC (permalink / raw)
To: iommu, linux-kernel; +Cc: Joerg Roedel
This change allows to remove these old macros later.
Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
---
arch/x86/kernel/amd_iommu.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c
index 3be2b61..ebc1c84 100644
--- a/arch/x86/kernel/amd_iommu.c
+++ b/arch/x86/kernel/amd_iommu.c
@@ -1402,7 +1402,7 @@ static u64* dma_ops_get_pte(struct dma_ops_domain *dom,
pte = alloc_pte(&dom->domain, address, &pte_page, GFP_ATOMIC);
aperture->pte_pages[APERTURE_PAGE_INDEX(address)] = pte_page;
} else
- pte += IOMMU_PTE_L0_INDEX(address);
+ pte += PM_LEVEL_INDEX(0, address);
update_domain(&dom->domain);
@@ -1466,7 +1466,7 @@ static void dma_ops_domain_unmap(struct amd_iommu *iommu,
if (!pte)
return;
- pte += IOMMU_PTE_L0_INDEX(address);
+ pte += PM_LEVEL_INDEX(0, address);
WARN_ON(!*pte);
--
1.6.3.3
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 10/14] x86/amd-iommu: Remove bus_addr check in iommu_map_page
2009-09-04 9:40 [PATCH 0/14] Page table handling updates for AMD-IOMMU (AMD-Vi) Joerg Roedel
` (8 preceding siblings ...)
2009-09-04 9:40 ` [PATCH 09/14] x86/amd-iommu: Remove last usages of IOMMU_PTE_L0_INDEX Joerg Roedel
@ 2009-09-04 9:40 ` Joerg Roedel
2009-09-04 9:40 ` [PATCH 11/14] x86/amd-iommu: Use 2-level page tables for dma_ops domains Joerg Roedel
` (3 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Joerg Roedel @ 2009-09-04 9:40 UTC (permalink / raw)
To: iommu, linux-kernel; +Cc: Joerg Roedel
The driver now supports full 64 bit device address spaces.
So this check is not longer required.
Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
---
arch/x86/kernel/amd_iommu.c | 3 +--
1 files changed, 1 insertions(+), 2 deletions(-)
diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c
index ebc1c84..6ffb3e6 100644
--- a/arch/x86/kernel/amd_iommu.c
+++ b/arch/x86/kernel/amd_iommu.c
@@ -530,8 +530,7 @@ static int iommu_map_page(struct protection_domain *dom,
bus_addr = PAGE_ALIGN(bus_addr);
phys_addr = PAGE_ALIGN(phys_addr);
- /* only support 512GB address spaces for now */
- if (bus_addr > IOMMU_MAP_SIZE_L3 || !(prot & IOMMU_PROT_MASK))
+ if (!(prot & IOMMU_PROT_MASK))
return -EINVAL;
pte = alloc_pte(dom, bus_addr, NULL, GFP_KERNEL);
--
1.6.3.3
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 11/14] x86/amd-iommu: Use 2-level page tables for dma_ops domains
2009-09-04 9:40 [PATCH 0/14] Page table handling updates for AMD-IOMMU (AMD-Vi) Joerg Roedel
` (9 preceding siblings ...)
2009-09-04 9:40 ` [PATCH 10/14] x86/amd-iommu: Remove bus_addr check in iommu_map_page Joerg Roedel
@ 2009-09-04 9:40 ` Joerg Roedel
2009-09-04 9:40 ` [PATCH 12/14] x86/amd-iommu: Remove old page table handling macros Joerg Roedel
` (2 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Joerg Roedel @ 2009-09-04 9:40 UTC (permalink / raw)
To: iommu, linux-kernel; +Cc: Joerg Roedel
The driver now supports a dynamic number of levels for IO
page tables. This allows to reduce the number of levels for
dma_ops domains by one because a dma_ops domain has usually
an address space size between 128MB and 4G.
Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
---
arch/x86/kernel/amd_iommu.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c
index 6ffb3e6..addf658 100644
--- a/arch/x86/kernel/amd_iommu.c
+++ b/arch/x86/kernel/amd_iommu.c
@@ -1010,7 +1010,7 @@ static struct dma_ops_domain *dma_ops_domain_alloc(struct amd_iommu *iommu)
dma_dom->domain.id = domain_id_alloc();
if (dma_dom->domain.id == 0)
goto free_dma_dom;
- dma_dom->domain.mode = PAGE_MODE_3_LEVEL;
+ dma_dom->domain.mode = PAGE_MODE_2_LEVEL;
dma_dom->domain.pt_root = (void *)get_zeroed_page(GFP_KERNEL);
dma_dom->domain.flags = PD_DMA_OPS_MASK;
dma_dom->domain.priv = dma_dom;
--
1.6.3.3
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 12/14] x86/amd-iommu: Remove old page table handling macros
2009-09-04 9:40 [PATCH 0/14] Page table handling updates for AMD-IOMMU (AMD-Vi) Joerg Roedel
` (10 preceding siblings ...)
2009-09-04 9:40 ` [PATCH 11/14] x86/amd-iommu: Use 2-level page tables for dma_ops domains Joerg Roedel
@ 2009-09-04 9:40 ` Joerg Roedel
2009-09-04 9:40 ` [PATCH 13/14] x86/amd-iommu: Support higher level PTEs in iommu_page_unmap Joerg Roedel
2009-09-04 9:40 ` [PATCH 14/14] x86/amd-iommu: Change iommu_map_page to support multiple page sizes Joerg Roedel
13 siblings, 0 replies; 15+ messages in thread
From: Joerg Roedel @ 2009-09-04 9:40 UTC (permalink / raw)
To: iommu, linux-kernel; +Cc: Joerg Roedel
These macros are not longer required. So remove them.
Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
---
arch/x86/include/asm/amd_iommu_types.h | 19 -------------------
1 files changed, 0 insertions(+), 19 deletions(-)
diff --git a/arch/x86/include/asm/amd_iommu_types.h b/arch/x86/include/asm/amd_iommu_types.h
index 1b4b3d6..d66430d 100644
--- a/arch/x86/include/asm/amd_iommu_types.h
+++ b/arch/x86/include/asm/amd_iommu_types.h
@@ -150,11 +150,6 @@
#define PAGE_MODE_5_LEVEL 0x05
#define PAGE_MODE_6_LEVEL 0x06
-#define IOMMU_PDE_NL_0 0x000ULL
-#define IOMMU_PDE_NL_1 0x200ULL
-#define IOMMU_PDE_NL_2 0x400ULL
-#define IOMMU_PDE_NL_3 0x600ULL
-
#define PM_LEVEL_SHIFT(x) (12 + ((x) * 9))
#define PM_LEVEL_SIZE(x) (((x) < 6) ? \
((1ULL << PM_LEVEL_SHIFT((x))) - 1): \
@@ -164,15 +159,6 @@
#define PM_LEVEL_PDE(x, a) ((a) | PM_LEVEL_ENC((x)) | \
IOMMU_PTE_P | IOMMU_PTE_IR | IOMMU_PTE_IW)
-
-#define IOMMU_PTE_L2_INDEX(address) (((address) >> 30) & 0x1ffULL)
-#define IOMMU_PTE_L1_INDEX(address) (((address) >> 21) & 0x1ffULL)
-#define IOMMU_PTE_L0_INDEX(address) (((address) >> 12) & 0x1ffULL)
-
-#define IOMMU_MAP_SIZE_L1 (1ULL << 21)
-#define IOMMU_MAP_SIZE_L2 (1ULL << 30)
-#define IOMMU_MAP_SIZE_L3 (1ULL << 39)
-
#define IOMMU_PTE_P (1ULL << 0)
#define IOMMU_PTE_TV (1ULL << 1)
#define IOMMU_PTE_U (1ULL << 59)
@@ -180,11 +166,6 @@
#define IOMMU_PTE_IR (1ULL << 61)
#define IOMMU_PTE_IW (1ULL << 62)
-#define IOMMU_L1_PDE(address) \
- ((address) | IOMMU_PDE_NL_1 | IOMMU_PTE_P | IOMMU_PTE_IR | IOMMU_PTE_IW)
-#define IOMMU_L2_PDE(address) \
- ((address) | IOMMU_PDE_NL_2 | IOMMU_PTE_P | IOMMU_PTE_IR | IOMMU_PTE_IW)
-
#define IOMMU_PAGE_MASK (((1ULL << 52) - 1) & ~0xfffULL)
#define IOMMU_PTE_PRESENT(pte) ((pte) & IOMMU_PTE_P)
#define IOMMU_PTE_PAGE(pte) (phys_to_virt((pte) & IOMMU_PAGE_MASK))
--
1.6.3.3
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 13/14] x86/amd-iommu: Support higher level PTEs in iommu_page_unmap
2009-09-04 9:40 [PATCH 0/14] Page table handling updates for AMD-IOMMU (AMD-Vi) Joerg Roedel
` (11 preceding siblings ...)
2009-09-04 9:40 ` [PATCH 12/14] x86/amd-iommu: Remove old page table handling macros Joerg Roedel
@ 2009-09-04 9:40 ` Joerg Roedel
2009-09-04 9:40 ` [PATCH 14/14] x86/amd-iommu: Change iommu_map_page to support multiple page sizes Joerg Roedel
13 siblings, 0 replies; 15+ messages in thread
From: Joerg Roedel @ 2009-09-04 9:40 UTC (permalink / raw)
To: iommu, linux-kernel; +Cc: Joerg Roedel
This patch changes fetch_pte and iommu_page_unmap to support
different page sizes too.
Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
---
arch/x86/include/asm/amd_iommu_types.h | 1 +
arch/x86/kernel/amd_iommu.c | 21 +++++++++++++--------
2 files changed, 14 insertions(+), 8 deletions(-)
diff --git a/arch/x86/include/asm/amd_iommu_types.h b/arch/x86/include/asm/amd_iommu_types.h
index d66430d..351ca39 100644
--- a/arch/x86/include/asm/amd_iommu_types.h
+++ b/arch/x86/include/asm/amd_iommu_types.h
@@ -158,6 +158,7 @@
#define PM_LEVEL_ENC(x) (((x) << 9) & 0xe00ULL)
#define PM_LEVEL_PDE(x, a) ((a) | PM_LEVEL_ENC((x)) | \
IOMMU_PTE_P | IOMMU_PTE_IR | IOMMU_PTE_IW)
+#define PM_PTE_LEVEL(pte) (((pte) >> 9) & 0x7ULL)
#define IOMMU_PTE_P (1ULL << 0)
#define IOMMU_PTE_TV (1ULL << 1)
diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c
index addf658..002cf9c 100644
--- a/arch/x86/kernel/amd_iommu.c
+++ b/arch/x86/kernel/amd_iommu.c
@@ -62,7 +62,7 @@ static void dma_ops_reserve_addresses(struct dma_ops_domain *dom,
unsigned long start_page,
unsigned int pages);
static u64 *fetch_pte(struct protection_domain *domain,
- unsigned long address);
+ unsigned long address, int map_size);
static void update_domain(struct protection_domain *domain);
#ifndef BUS_NOTIFY_UNBOUND_DRIVER
@@ -552,9 +552,9 @@ static int iommu_map_page(struct protection_domain *dom,
}
static void iommu_unmap_page(struct protection_domain *dom,
- unsigned long bus_addr)
+ unsigned long bus_addr, int map_size)
{
- u64 *pte = fetch_pte(dom, bus_addr);
+ u64 *pte = fetch_pte(dom, bus_addr, map_size);
if (pte)
*pte = 0;
@@ -668,7 +668,7 @@ static int init_unity_mappings_for_device(struct dma_ops_domain *dma_dom,
* there is one, it returns the pointer to it.
*/
static u64 *fetch_pte(struct protection_domain *domain,
- unsigned long address)
+ unsigned long address, int map_size)
{
int level;
u64 *pte;
@@ -676,7 +676,7 @@ static u64 *fetch_pte(struct protection_domain *domain,
level = domain->mode - 1;
pte = &domain->pt_root[PM_LEVEL_INDEX(level, address)];
- while (level > 0) {
+ while (level > map_size) {
if (!IOMMU_PTE_PRESENT(*pte))
return NULL;
@@ -684,6 +684,11 @@ static u64 *fetch_pte(struct protection_domain *domain,
pte = IOMMU_PTE_PAGE(*pte);
pte = &pte[PM_LEVEL_INDEX(level, address)];
+
+ if ((PM_PTE_LEVEL(*pte) == 0) && level != map_size) {
+ pte = NULL;
+ break;
+ }
}
return pte;
@@ -757,7 +762,7 @@ static int alloc_new_range(struct amd_iommu *iommu,
for (i = dma_dom->aperture[index]->offset;
i < dma_dom->aperture_size;
i += PAGE_SIZE) {
- u64 *pte = fetch_pte(&dma_dom->domain, i);
+ u64 *pte = fetch_pte(&dma_dom->domain, i, PM_MAP_4k);
if (!pte || !IOMMU_PTE_PRESENT(*pte))
continue;
@@ -2192,7 +2197,7 @@ static void amd_iommu_unmap_range(struct iommu_domain *dom,
iova &= PAGE_MASK;
for (i = 0; i < npages; ++i) {
- iommu_unmap_page(domain, iova);
+ iommu_unmap_page(domain, iova, PM_MAP_4k);
iova += PAGE_SIZE;
}
@@ -2207,7 +2212,7 @@ static phys_addr_t amd_iommu_iova_to_phys(struct iommu_domain *dom,
phys_addr_t paddr;
u64 *pte;
- pte = fetch_pte(domain, iova);
+ pte = fetch_pte(domain, iova, PM_MAP_4k);
if (!pte || !IOMMU_PTE_PRESENT(*pte))
return 0;
--
1.6.3.3
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 14/14] x86/amd-iommu: Change iommu_map_page to support multiple page sizes
2009-09-04 9:40 [PATCH 0/14] Page table handling updates for AMD-IOMMU (AMD-Vi) Joerg Roedel
` (12 preceding siblings ...)
2009-09-04 9:40 ` [PATCH 13/14] x86/amd-iommu: Support higher level PTEs in iommu_page_unmap Joerg Roedel
@ 2009-09-04 9:40 ` Joerg Roedel
13 siblings, 0 replies; 15+ messages in thread
From: Joerg Roedel @ 2009-09-04 9:40 UTC (permalink / raw)
To: iommu, linux-kernel; +Cc: Joerg Roedel
This patch adds a map_size parameter to the iommu_map_page
function which makes it generic enough to handle multiple
page sizes. This also requires a change to alloc_pte which
is also done in this patch.
Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
---
arch/x86/include/asm/amd_iommu_types.h | 6 ++++++
arch/x86/kernel/amd_iommu.c | 31 ++++++++++++++++++++-----------
2 files changed, 26 insertions(+), 11 deletions(-)
diff --git a/arch/x86/include/asm/amd_iommu_types.h b/arch/x86/include/asm/amd_iommu_types.h
index 351ca39..9e8bb97 100644
--- a/arch/x86/include/asm/amd_iommu_types.h
+++ b/arch/x86/include/asm/amd_iommu_types.h
@@ -160,6 +160,12 @@
IOMMU_PTE_P | IOMMU_PTE_IR | IOMMU_PTE_IW)
#define PM_PTE_LEVEL(pte) (((pte) >> 9) & 0x7ULL)
+#define PM_MAP_4k 0
+#define PM_ADDR_MASK 0x000ffffffffff000ULL
+#define PM_MAP_MASK(lvl) (PM_ADDR_MASK & \
+ (~((1ULL << (12 + ((lvl) * 9))) - 1)))
+#define PM_ALIGNED(lvl, addr) ((PM_MAP_MASK(lvl) & (addr)) == (addr))
+
#define IOMMU_PTE_P (1ULL << 0)
#define IOMMU_PTE_TV (1ULL << 1)
#define IOMMU_PTE_U (1ULL << 59)
diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c
index 002cf9c..45be949 100644
--- a/arch/x86/kernel/amd_iommu.c
+++ b/arch/x86/kernel/amd_iommu.c
@@ -56,8 +56,8 @@ static int dma_ops_unity_map(struct dma_ops_domain *dma_dom,
struct unity_map_entry *e);
static struct dma_ops_domain *find_protection_domain(u16 devid);
static u64 *alloc_pte(struct protection_domain *domain,
- unsigned long address, u64
- **pte_page, gfp_t gfp);
+ unsigned long address, int end_lvl,
+ u64 **pte_page, gfp_t gfp);
static void dma_ops_reserve_addresses(struct dma_ops_domain *dom,
unsigned long start_page,
unsigned int pages);
@@ -523,17 +523,21 @@ void amd_iommu_flush_all_devices(void)
static int iommu_map_page(struct protection_domain *dom,
unsigned long bus_addr,
unsigned long phys_addr,
- int prot)
+ int prot,
+ int map_size)
{
u64 __pte, *pte;
bus_addr = PAGE_ALIGN(bus_addr);
phys_addr = PAGE_ALIGN(phys_addr);
+ BUG_ON(!PM_ALIGNED(map_size, bus_addr));
+ BUG_ON(!PM_ALIGNED(map_size, phys_addr));
+
if (!(prot & IOMMU_PROT_MASK))
return -EINVAL;
- pte = alloc_pte(dom, bus_addr, NULL, GFP_KERNEL);
+ pte = alloc_pte(dom, bus_addr, map_size, NULL, GFP_KERNEL);
if (IOMMU_PTE_PRESENT(*pte))
return -EBUSY;
@@ -612,7 +616,8 @@ static int dma_ops_unity_map(struct dma_ops_domain *dma_dom,
for (addr = e->address_start; addr < e->address_end;
addr += PAGE_SIZE) {
- ret = iommu_map_page(&dma_dom->domain, addr, addr, e->prot);
+ ret = iommu_map_page(&dma_dom->domain, addr, addr, e->prot,
+ PM_MAP_4k);
if (ret)
return ret;
/*
@@ -729,7 +734,7 @@ static int alloc_new_range(struct amd_iommu *iommu,
u64 *pte, *pte_page;
for (i = 0; i < num_ptes; ++i) {
- pte = alloc_pte(&dma_dom->domain, address,
+ pte = alloc_pte(&dma_dom->domain, address, PM_MAP_4k,
&pte_page, gfp);
if (!pte)
goto out_free;
@@ -1356,7 +1361,10 @@ static bool increase_address_space(struct protection_domain *domain,
}
static u64 *alloc_pte(struct protection_domain *domain,
- unsigned long address, u64 **pte_page, gfp_t gfp)
+ unsigned long address,
+ int end_lvl,
+ u64 **pte_page,
+ gfp_t gfp)
{
u64 *pte, *page;
int level;
@@ -1367,7 +1375,7 @@ static u64 *alloc_pte(struct protection_domain *domain,
level = domain->mode - 1;
pte = &domain->pt_root[PM_LEVEL_INDEX(level, address)];
- while (level > 0) {
+ while (level > end_lvl) {
if (!IOMMU_PTE_PRESENT(*pte)) {
page = (u64 *)get_zeroed_page(gfp);
if (!page)
@@ -1379,7 +1387,7 @@ static u64 *alloc_pte(struct protection_domain *domain,
pte = IOMMU_PTE_PAGE(*pte);
- if (pte_page && level == 0)
+ if (pte_page && level == end_lvl)
*pte_page = pte;
pte = &pte[PM_LEVEL_INDEX(level, address)];
@@ -1403,7 +1411,8 @@ static u64* dma_ops_get_pte(struct dma_ops_domain *dom,
pte = aperture->pte_pages[APERTURE_PAGE_INDEX(address)];
if (!pte) {
- pte = alloc_pte(&dom->domain, address, &pte_page, GFP_ATOMIC);
+ pte = alloc_pte(&dom->domain, address, PM_MAP_4k, &pte_page,
+ GFP_ATOMIC);
aperture->pte_pages[APERTURE_PAGE_INDEX(address)] = pte_page;
} else
pte += PM_LEVEL_INDEX(0, address);
@@ -2176,7 +2185,7 @@ static int amd_iommu_map_range(struct iommu_domain *dom,
paddr &= PAGE_MASK;
for (i = 0; i < npages; ++i) {
- ret = iommu_map_page(domain, iova, paddr, prot);
+ ret = iommu_map_page(domain, iova, paddr, prot, PM_MAP_4k);
if (ret)
return ret;
--
1.6.3.3
^ permalink raw reply [flat|nested] 15+ messages in thread
end of thread, other threads:[~2009-09-04 9:44 UTC | newest]
Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-09-04 9:40 [PATCH 0/14] Page table handling updates for AMD-IOMMU (AMD-Vi) Joerg Roedel
2009-09-04 9:40 ` [PATCH 01/14] x86/amd-iommu: Make fetch_pte aware of dynamic mapping levels Joerg Roedel
2009-09-04 9:40 ` [PATCH 02/14] x86/amd-iommu: Use fetch_pte in iommu_unmap_page Joerg Roedel
2009-09-04 9:40 ` [PATCH 03/14] x86/amd-iommu: Use fetch_pte in amd_iommu_iova_to_phys Joerg Roedel
2009-09-04 9:40 ` [PATCH 04/14] x86/amd-iommu: Add a gneric version of amd_iommu_flush_all_devices Joerg Roedel
2009-09-04 9:40 ` [PATCH 05/14] x86/amd-iommu: Introduce set_dte_entry function Joerg Roedel
2009-09-04 9:40 ` [PATCH 06/14] x86/amd-iommu: Flush domains if address space size was increased Joerg Roedel
2009-09-04 9:40 ` [PATCH 07/14] x86/amd-iommu: Introduce increase_address_space function Joerg Roedel
2009-09-04 9:40 ` [PATCH 08/14] x86/amd-iommu: Change alloc_pte to support 64 bit address space Joerg Roedel
2009-09-04 9:40 ` [PATCH 09/14] x86/amd-iommu: Remove last usages of IOMMU_PTE_L0_INDEX Joerg Roedel
2009-09-04 9:40 ` [PATCH 10/14] x86/amd-iommu: Remove bus_addr check in iommu_map_page Joerg Roedel
2009-09-04 9:40 ` [PATCH 11/14] x86/amd-iommu: Use 2-level page tables for dma_ops domains Joerg Roedel
2009-09-04 9:40 ` [PATCH 12/14] x86/amd-iommu: Remove old page table handling macros Joerg Roedel
2009-09-04 9:40 ` [PATCH 13/14] x86/amd-iommu: Support higher level PTEs in iommu_page_unmap Joerg Roedel
2009-09-04 9:40 ` [PATCH 14/14] x86/amd-iommu: Change iommu_map_page to support multiple page sizes Joerg Roedel
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®