Skip to content

Commit 8e2d434

Browse files
wildea01torvalds
authored andcommitted
lib/ioremap: ensure break-before-make is used for huge p4d mappings
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]>
1 parent 36ddc5a commit 8e2d434

File tree

4 files changed

+39
-6
lines changed

4 files changed

+39
-6
lines changed

arch/arm64/mm/mmu.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1043,6 +1043,11 @@ int pud_free_pmd_page(pud_t *pudp, unsigned long addr)
10431043
return 1;
10441044
}
10451045

1046+
int p4d_free_pud_page(p4d_t *p4d, unsigned long addr)
1047+
{
1048+
return 0; /* Don't attempt a block mapping */
1049+
}
1050+
10461051
#ifdef CONFIG_MEMORY_HOTPLUG
10471052
int arch_add_memory(int nid, u64 start, u64 size, struct vmem_altmap *altmap,
10481053
bool want_memblock)

arch/x86/mm/pgtable.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -794,6 +794,14 @@ int pmd_clear_huge(pmd_t *pmd)
794794
return 0;
795795
}
796796

797+
/*
798+
* Until we support 512GB pages, skip them in the vmap area.
799+
*/
800+
int p4d_free_pud_page(p4d_t *p4d, unsigned long addr)
801+
{
802+
return 0;
803+
}
804+
797805
#ifdef CONFIG_X86_64
798806
/**
799807
* pud_free_pmd_page - Clear pud entry and free pmd page.

include/asm-generic/pgtable.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1057,6 +1057,7 @@ int pud_set_huge(pud_t *pud, phys_addr_t addr, pgprot_t prot);
10571057
int pmd_set_huge(pmd_t *pmd, phys_addr_t addr, pgprot_t prot);
10581058
int pud_clear_huge(pud_t *pud);
10591059
int pmd_clear_huge(pmd_t *pmd);
1060+
int p4d_free_pud_page(p4d_t *p4d, unsigned long addr);
10601061
int pud_free_pmd_page(pud_t *pud, unsigned long addr);
10611062
int pmd_free_pte_page(pmd_t *pmd, unsigned long addr);
10621063
#else /* !CONFIG_HAVE_ARCH_HUGE_VMAP */
@@ -1084,6 +1085,10 @@ static inline int pmd_clear_huge(pmd_t *pmd)
10841085
{
10851086
return 0;
10861087
}
1088+
static inline int p4d_free_pud_page(p4d_t *p4d, unsigned long addr)
1089+
{
1090+
return 0;
1091+
}
10871092
static inline int pud_free_pmd_page(pud_t *pud, unsigned long addr)
10881093
{
10891094
return 0;

lib/ioremap.c

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,25 @@ static inline int ioremap_pud_range(p4d_t *p4d, unsigned long addr,
156156
return 0;
157157
}
158158

159+
static int ioremap_try_huge_p4d(p4d_t *p4d, unsigned long addr,
160+
unsigned long end, phys_addr_t phys_addr,
161+
pgprot_t prot)
162+
{
163+
if (!ioremap_p4d_enabled())
164+
return 0;
165+
166+
if ((end - addr) != P4D_SIZE)
167+
return 0;
168+
169+
if (!IS_ALIGNED(phys_addr, P4D_SIZE))
170+
return 0;
171+
172+
if (p4d_present(*p4d) && !p4d_free_pud_page(p4d, addr))
173+
return 0;
174+
175+
return p4d_set_huge(p4d, phys_addr, prot);
176+
}
177+
159178
static inline int ioremap_p4d_range(pgd_t *pgd, unsigned long addr,
160179
unsigned long end, phys_addr_t phys_addr, pgprot_t prot)
161180
{
@@ -168,12 +187,8 @@ static inline int ioremap_p4d_range(pgd_t *pgd, unsigned long addr,
168187
do {
169188
next = p4d_addr_end(addr, end);
170189

171-
if (ioremap_p4d_enabled() &&
172-
((next - addr) == P4D_SIZE) &&
173-
IS_ALIGNED(phys_addr, P4D_SIZE)) {
174-
if (p4d_set_huge(p4d, phys_addr, prot))
175-
continue;
176-
}
190+
if (ioremap_try_huge_p4d(p4d, addr, next, phys_addr, prot))
191+
continue;
177192

178193
if (ioremap_pud_range(p4d, addr, next, phys_addr, prot))
179194
return -ENOMEM;

0 commit comments

Comments
 (0)