Skip to content

Commit

Permalink
x86/amd-iommu: Move some pte allocation functions in the right section
Browse files Browse the repository at this point in the history
This patch moves alloc_pte() and fetch_pte() into the page
table handling code section so that the forward declarations
for them could be removed.

Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
  • Loading branch information
Joerg Roedel committed Nov 27, 2009
1 parent 87a64d5 commit 308973d
Showing 1 changed file with 94 additions and 99 deletions.
193 changes: 94 additions & 99 deletions arch/x86/kernel/amd_iommu.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,15 +59,10 @@ struct iommu_cmd {

static int dma_ops_unity_map(struct dma_ops_domain *dma_dom,
struct unity_map_entry *e);
static u64 *alloc_pte(struct protection_domain *domain,
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);
static void reset_iommu_command_buffer(struct amd_iommu *iommu);
static u64 *fetch_pte(struct protection_domain *domain,
unsigned long address, int map_size);
static void update_domain(struct protection_domain *domain);

/****************************************************************************
Expand Down Expand Up @@ -664,6 +659,100 @@ void amd_iommu_flush_all_devices(void)
*
****************************************************************************/

/*
* 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;
}

static u64 *alloc_pte(struct protection_domain *domain,
unsigned long address,
int end_lvl,
u64 **pte_page,
gfp_t gfp)
{
u64 *pte, *page;
int level;

while (address > PM_LEVEL_SIZE(domain->mode))
increase_address_space(domain, gfp);

level = domain->mode - 1;
pte = &domain->pt_root[PM_LEVEL_INDEX(level, address)];

while (level > end_lvl) {
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 == end_lvl)
*pte_page = pte;

pte = &pte[PM_LEVEL_INDEX(level, address)];
}

return pte;
}

/*
* 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,
unsigned long address, int map_size)
{
int level;
u64 *pte;

level = domain->mode - 1;
pte = &domain->pt_root[PM_LEVEL_INDEX(level, address)];

while (level > map_size) {
if (!IOMMU_PTE_PRESENT(*pte))
return NULL;

level -= 1;

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;
}

/*
* Generic mapping functions. It maps a physical address into a DMA
* address space. It allocates the page table pages if necessary.
Expand Down Expand Up @@ -819,37 +908,6 @@ static int init_unity_mappings_for_device(struct dma_ops_domain *dma_dom,
* called with domain->lock held
*/

/*
* 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,
unsigned long address, int map_size)
{
int level;
u64 *pte;

level = domain->mode - 1;
pte = &domain->pt_root[PM_LEVEL_INDEX(level, address)];

while (level > map_size) {
if (!IOMMU_PTE_PRESENT(*pte))
return NULL;

level -= 1;

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;
}

/*
* This function is used to add a new aperture range to an existing
* aperture in case of dma_ops domain allocation or address allocation
Expand Down Expand Up @@ -1534,69 +1592,6 @@ static void update_domain(struct protection_domain *domain)
domain->updated = false;
}

/*
* 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;
}

static u64 *alloc_pte(struct protection_domain *domain,
unsigned long address,
int end_lvl,
u64 **pte_page,
gfp_t gfp)
{
u64 *pte, *page;
int level;

while (address > PM_LEVEL_SIZE(domain->mode))
increase_address_space(domain, gfp);

level = domain->mode - 1;
pte = &domain->pt_root[PM_LEVEL_INDEX(level, address)];

while (level > end_lvl) {
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 == end_lvl)
*pte_page = pte;

pte = &pte[PM_LEVEL_INDEX(level, address)];
}

return pte;
}

/*
* This function fetches the PTE for a given address in the aperture
*/
Expand Down

0 comments on commit 308973d

Please sign in to comment.