Skip to content

Commit

Permalink
Merge branch 'x86/mm' of git://git.kernel.org/pub/scm/linux/kernel/gi…
Browse files Browse the repository at this point in the history
…t/tip/tip into aarch64/for-next/core

Pull in core ioremap changes from -tip, since we depend on these for
re-enabling huge I/O mappings on arm64.

Signed-off-by: Will Deacon <will.deacon@arm.com>
  • Loading branch information
Will Deacon committed Jul 6, 2018
2 parents 693350a + 5e0fb5d commit f355152
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 16 deletions.
4 changes: 2 additions & 2 deletions arch/arm64/mm/mmu.c
Original file line number Diff line number Diff line change
Expand Up @@ -977,12 +977,12 @@ int pmd_clear_huge(pmd_t *pmdp)
return 1;
}

int pud_free_pmd_page(pud_t *pud)
int pud_free_pmd_page(pud_t *pud, unsigned long addr)
{
return pud_none(*pud);
}

int pmd_free_pte_page(pmd_t *pmd)
int pmd_free_pte_page(pmd_t *pmd, unsigned long addr)
{
return pmd_none(*pmd);
}
61 changes: 53 additions & 8 deletions arch/x86/mm/pgtable.c
Original file line number Diff line number Diff line change
Expand Up @@ -719,28 +719,50 @@ int pmd_clear_huge(pmd_t *pmd)
return 0;
}

#ifdef CONFIG_X86_64
/**
* pud_free_pmd_page - Clear pud entry and free pmd page.
* @pud: Pointer to a PUD.
* @addr: Virtual address associated with pud.
*
* Context: The pud range has been unmaped and TLB purged.
* Context: The pud range has been unmapped and TLB purged.
* Return: 1 if clearing the entry succeeded. 0 otherwise.
*
* NOTE: Callers must allow a single page allocation.
*/
int pud_free_pmd_page(pud_t *pud)
int pud_free_pmd_page(pud_t *pud, unsigned long addr)
{
pmd_t *pmd;
pmd_t *pmd, *pmd_sv;
pte_t *pte;
int i;

if (pud_none(*pud))
return 1;

pmd = (pmd_t *)pud_page_vaddr(*pud);
pmd_sv = (pmd_t *)__get_free_page(GFP_KERNEL);
if (!pmd_sv)
return 0;

for (i = 0; i < PTRS_PER_PMD; i++)
if (!pmd_free_pte_page(&pmd[i]))
return 0;
for (i = 0; i < PTRS_PER_PMD; i++) {
pmd_sv[i] = pmd[i];
if (!pmd_none(pmd[i]))
pmd_clear(&pmd[i]);
}

pud_clear(pud);

/* INVLPG to clear all paging-structure caches */
flush_tlb_kernel_range(addr, addr + PAGE_SIZE-1);

for (i = 0; i < PTRS_PER_PMD; i++) {
if (!pmd_none(pmd_sv[i])) {
pte = (pte_t *)pmd_page_vaddr(pmd_sv[i]);
free_page((unsigned long)pte);
}
}

free_page((unsigned long)pmd_sv);
free_page((unsigned long)pmd);

return 1;
Expand All @@ -749,11 +771,12 @@ int pud_free_pmd_page(pud_t *pud)
/**
* pmd_free_pte_page - Clear pmd entry and free pte page.
* @pmd: Pointer to a PMD.
* @addr: Virtual address associated with pmd.
*
* Context: The pmd range has been unmaped and TLB purged.
* Context: The pmd range has been unmapped and TLB purged.
* Return: 1 if clearing the entry succeeded. 0 otherwise.
*/
int pmd_free_pte_page(pmd_t *pmd)
int pmd_free_pte_page(pmd_t *pmd, unsigned long addr)
{
pte_t *pte;

Expand All @@ -762,8 +785,30 @@ int pmd_free_pte_page(pmd_t *pmd)

pte = (pte_t *)pmd_page_vaddr(*pmd);
pmd_clear(pmd);

/* INVLPG to clear all paging-structure caches */
flush_tlb_kernel_range(addr, addr + PAGE_SIZE-1);

free_page((unsigned long)pte);

return 1;
}

#else /* !CONFIG_X86_64 */

int pud_free_pmd_page(pud_t *pud, unsigned long addr)
{
return pud_none(*pud);
}

/*
* Disable free page handling on x86-PAE. This assures that ioremap()
* does not update sync'd pmd entries. See vmalloc_sync_one().
*/
int pmd_free_pte_page(pmd_t *pmd, unsigned long addr)
{
return pmd_none(*pmd);
}

#endif /* CONFIG_X86_64 */
#endif /* CONFIG_HAVE_ARCH_HUGE_VMAP */
8 changes: 4 additions & 4 deletions include/asm-generic/pgtable.h
Original file line number Diff line number Diff line change
Expand Up @@ -1019,8 +1019,8 @@ int pud_set_huge(pud_t *pud, phys_addr_t addr, pgprot_t prot);
int pmd_set_huge(pmd_t *pmd, phys_addr_t addr, pgprot_t prot);
int pud_clear_huge(pud_t *pud);
int pmd_clear_huge(pmd_t *pmd);
int pud_free_pmd_page(pud_t *pud);
int pmd_free_pte_page(pmd_t *pmd);
int pud_free_pmd_page(pud_t *pud, unsigned long addr);
int pmd_free_pte_page(pmd_t *pmd, unsigned long addr);
#else /* !CONFIG_HAVE_ARCH_HUGE_VMAP */
static inline int p4d_set_huge(p4d_t *p4d, phys_addr_t addr, pgprot_t prot)
{
Expand All @@ -1046,11 +1046,11 @@ static inline int pmd_clear_huge(pmd_t *pmd)
{
return 0;
}
static inline int pud_free_pmd_page(pud_t *pud)
static inline int pud_free_pmd_page(pud_t *pud, unsigned long addr)
{
return 0;
}
static inline int pmd_free_pte_page(pmd_t *pmd)
static inline int pmd_free_pte_page(pmd_t *pmd, unsigned long addr)
{
return 0;
}
Expand Down
4 changes: 2 additions & 2 deletions lib/ioremap.c
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ static inline int ioremap_pmd_range(pud_t *pud, unsigned long addr,
if (ioremap_pmd_enabled() &&
((next - addr) == PMD_SIZE) &&
IS_ALIGNED(phys_addr + addr, PMD_SIZE) &&
pmd_free_pte_page(pmd)) {
pmd_free_pte_page(pmd, addr)) {
if (pmd_set_huge(pmd, phys_addr + addr, prot))
continue;
}
Expand All @@ -119,7 +119,7 @@ static inline int ioremap_pud_range(p4d_t *p4d, unsigned long addr,
if (ioremap_pud_enabled() &&
((next - addr) == PUD_SIZE) &&
IS_ALIGNED(phys_addr + addr, PUD_SIZE) &&
pud_free_pmd_page(pud)) {
pud_free_pmd_page(pud, addr)) {
if (pud_set_huge(pud, phys_addr + addr, prot))
continue;
}
Expand Down

0 comments on commit f355152

Please sign in to comment.