x86/amd-iommu: Change alloc_pte to support 64 bit address space
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>
This commit is contained in:
Родитель
50020fb632
Коммит
8bc3e12742
|
@ -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,40 +1351,36 @@ 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)];
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
level -= 1;
|
||||
|
||||
pte = IOMMU_PTE_PAGE(*pte);
|
||||
|
||||
if (pte_page && level == 0)
|
||||
*pte_page = pte;
|
||||
|
||||
pte = &pte[PM_LEVEL_INDEX(level, address)];
|
||||
}
|
||||
|
||||
pte = IOMMU_PTE_PAGE(*pte);
|
||||
pte = &pte[IOMMU_PTE_L1_INDEX(address)];
|
||||
|
||||
if (!IOMMU_PTE_PRESENT(*pte)) {
|
||||
page = (u64 *)get_zeroed_page(gfp);
|
||||
if (!page)
|
||||
return NULL;
|
||||
*pte = IOMMU_L1_PDE(virt_to_phys(page));
|
||||
}
|
||||
|
||||
pte = IOMMU_PTE_PAGE(*pte);
|
||||
|
||||
if (pte_page)
|
||||
*pte_page = pte;
|
||||
|
||||
pte = &pte[IOMMU_PTE_L0_INDEX(address)];
|
||||
|
||||
return pte;
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче