Skip to content

Commit

Permalink
lib/ioremap: ensure break-before-make is used for huge p4d mappings
Browse files Browse the repository at this point in the history
Whilst no architectures actually enable support for huge p4d mappings in
the vmap area, the code that is implemented should be using
break-before-make, as we do for pud and pmd huge entries.

Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Will Deacon <[email protected]>
Reviewed-by: Toshi Kani <[email protected]>
Cc: Chintan Pandya <[email protected]>
Cc: Toshi Kani <[email protected]>
Cc: Thomas Gleixner <[email protected]>
Cc: Michal Hocko <[email protected]>
Cc: "H. Peter Anvin" <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Sean Christopherson <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
  • Loading branch information
wildea01 authored and torvalds committed Dec 28, 2018
1 parent 36ddc5a commit 8e2d434
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 6 deletions.
5 changes: 5 additions & 0 deletions arch/arm64/mm/mmu.c
Original file line number Diff line number Diff line change
Expand Up @@ -1043,6 +1043,11 @@ int pud_free_pmd_page(pud_t *pudp, unsigned long addr)
return 1;
}

int p4d_free_pud_page(p4d_t *p4d, unsigned long addr)
{
return 0; /* Don't attempt a block mapping */
}

#ifdef CONFIG_MEMORY_HOTPLUG
int arch_add_memory(int nid, u64 start, u64 size, struct vmem_altmap *altmap,
bool want_memblock)
Expand Down
8 changes: 8 additions & 0 deletions arch/x86/mm/pgtable.c
Original file line number Diff line number Diff line change
Expand Up @@ -794,6 +794,14 @@ int pmd_clear_huge(pmd_t *pmd)
return 0;
}

/*
* Until we support 512GB pages, skip them in the vmap area.
*/
int p4d_free_pud_page(p4d_t *p4d, unsigned long addr)
{
return 0;
}

#ifdef CONFIG_X86_64
/**
* pud_free_pmd_page - Clear pud entry and free pmd page.
Expand Down
5 changes: 5 additions & 0 deletions include/asm-generic/pgtable.h
Original file line number Diff line number Diff line change
Expand Up @@ -1057,6 +1057,7 @@ 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 p4d_free_pud_page(p4d_t *p4d, unsigned long addr);
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 */
Expand Down Expand Up @@ -1084,6 +1085,10 @@ static inline int pmd_clear_huge(pmd_t *pmd)
{
return 0;
}
static inline int p4d_free_pud_page(p4d_t *p4d, unsigned long addr)
{
return 0;
}
static inline int pud_free_pmd_page(pud_t *pud, unsigned long addr)
{
return 0;
Expand Down
27 changes: 21 additions & 6 deletions lib/ioremap.c
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,25 @@ static inline int ioremap_pud_range(p4d_t *p4d, unsigned long addr,
return 0;
}

static int ioremap_try_huge_p4d(p4d_t *p4d, unsigned long addr,
unsigned long end, phys_addr_t phys_addr,
pgprot_t prot)
{
if (!ioremap_p4d_enabled())
return 0;

if ((end - addr) != P4D_SIZE)
return 0;

if (!IS_ALIGNED(phys_addr, P4D_SIZE))
return 0;

if (p4d_present(*p4d) && !p4d_free_pud_page(p4d, addr))
return 0;

return p4d_set_huge(p4d, phys_addr, prot);
}

static inline int ioremap_p4d_range(pgd_t *pgd, unsigned long addr,
unsigned long end, phys_addr_t phys_addr, pgprot_t prot)
{
Expand All @@ -168,12 +187,8 @@ static inline int ioremap_p4d_range(pgd_t *pgd, unsigned long addr,
do {
next = p4d_addr_end(addr, end);

if (ioremap_p4d_enabled() &&
((next - addr) == P4D_SIZE) &&
IS_ALIGNED(phys_addr, P4D_SIZE)) {
if (p4d_set_huge(p4d, phys_addr, prot))
continue;
}
if (ioremap_try_huge_p4d(p4d, addr, next, phys_addr, prot))
continue;

if (ioremap_pud_range(p4d, addr, next, phys_addr, prot))
return -ENOMEM;
Expand Down

0 comments on commit 8e2d434

Please sign in to comment.