summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/arm64/include/asm/ptdump.h2
-rw-r--r--arch/arm64/mm/mmu.c43
-rw-r--r--arch/arm64/mm/ptdump.c11
-rw-r--r--mm/vmalloc.c15
4 files changed, 9 insertions, 62 deletions
diff --git a/arch/arm64/include/asm/ptdump.h b/arch/arm64/include/asm/ptdump.h
index 5b374a6ab34a..50a195eda8ed 100644
--- a/arch/arm64/include/asm/ptdump.h
+++ b/arch/arm64/include/asm/ptdump.h
@@ -7,8 +7,6 @@
#include <linux/ptdump.h>
-DECLARE_STATIC_KEY_FALSE(arm64_ptdump_lock_key);
-
#ifdef CONFIG_PTDUMP
#include <linux/mm_types.h>
diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
index 18a8b0d3714e..d4de88770ecf 100644
--- a/arch/arm64/mm/mmu.c
+++ b/arch/arm64/mm/mmu.c
@@ -49,8 +49,6 @@
#define NO_CONT_MAPPINGS BIT(1)
#define NO_EXEC_MAPPINGS BIT(2) /* assumes FEAT_HPDS is not used */
-DEFINE_STATIC_KEY_FALSE(arm64_ptdump_lock_key);
-
u64 kimage_voffset __ro_after_init;
EXPORT_SYMBOL(kimage_voffset);
@@ -1864,8 +1862,7 @@ int pmd_clear_huge(pmd_t *pmdp)
return 1;
}
-static int __pmd_free_pte_page(pmd_t *pmdp, unsigned long addr,
- bool acquire_mmap_lock)
+int pmd_free_pte_page(pmd_t *pmdp, unsigned long addr)
{
pte_t *table;
pmd_t pmd;
@@ -1877,25 +1874,13 @@ static int __pmd_free_pte_page(pmd_t *pmdp, unsigned long addr,
return 1;
}
- /* See comment in pud_free_pmd_page for static key logic */
table = pte_offset_kernel(pmdp, addr);
pmd_clear(pmdp);
__flush_tlb_kernel_pgtable(addr);
- if (static_branch_unlikely(&arm64_ptdump_lock_key) && acquire_mmap_lock) {
- mmap_read_lock(&init_mm);
- mmap_read_unlock(&init_mm);
- }
-
pte_free_kernel(NULL, table);
return 1;
}
-int pmd_free_pte_page(pmd_t *pmdp, unsigned long addr)
-{
- /* If ptdump is walking the pagetables, acquire init_mm.mmap_lock */
- return __pmd_free_pte_page(pmdp, addr, /* acquire_mmap_lock = */ true);
-}
-
int pud_free_pmd_page(pud_t *pudp, unsigned long addr)
{
pmd_t *table;
@@ -1911,36 +1896,16 @@ int pud_free_pmd_page(pud_t *pudp, unsigned long addr)
}
table = pmd_offset(pudp, addr);
-
- /*
- * Our objective is to prevent ptdump from reading a PMD table which has
- * been freed. In this race, if pud_free_pmd_page observes the key on
- * (which got flipped by ptdump) then the mmap lock sequence here will,
- * as a result of the mmap write lock/unlock sequence in ptdump, give
- * us the correct synchronization. If not, this means that ptdump has
- * yet not started walking the pagetables - the sequence of barriers
- * issued by __flush_tlb_kernel_pgtable() guarantees that ptdump will
- * observe an empty PUD.
- */
- pud_clear(pudp);
- __flush_tlb_kernel_pgtable(addr);
- if (static_branch_unlikely(&arm64_ptdump_lock_key)) {
- mmap_read_lock(&init_mm);
- mmap_read_unlock(&init_mm);
- }
-
pmdp = table;
next = addr;
end = addr + PUD_SIZE;
do {
if (pmd_present(pmdp_get(pmdp)))
- /*
- * PMD has been isolated, so ptdump won't see it. No
- * need to acquire init_mm.mmap_lock.
- */
- __pmd_free_pte_page(pmdp, next, /* acquire_mmap_lock = */ false);
+ pmd_free_pte_page(pmdp, next);
} while (pmdp++, next += PMD_SIZE, next != end);
+ pud_clear(pudp);
+ __flush_tlb_kernel_pgtable(addr);
pmd_free(NULL, table);
return 1;
}
diff --git a/arch/arm64/mm/ptdump.c b/arch/arm64/mm/ptdump.c
index 1c20144700d7..5a76c59b5ada 100644
--- a/arch/arm64/mm/ptdump.c
+++ b/arch/arm64/mm/ptdump.c
@@ -283,13 +283,6 @@ void note_page_flush(struct ptdump_state *pt_st)
note_page(pt_st, 0, -1, pte_val(pte_zero));
}
-static void arm64_ptdump_walk_pgd(struct ptdump_state *st, struct mm_struct *mm)
-{
- static_branch_inc(&arm64_ptdump_lock_key);
- ptdump_walk_pgd(st, mm, NULL);
- static_branch_dec(&arm64_ptdump_lock_key);
-}
-
void ptdump_walk(struct seq_file *s, struct ptdump_info *info)
{
unsigned long end = ~0UL;
@@ -318,7 +311,7 @@ void ptdump_walk(struct seq_file *s, struct ptdump_info *info)
}
};
- arm64_ptdump_walk_pgd(&st.ptdump, info->mm);
+ ptdump_walk_pgd(&st.ptdump, info->mm, NULL);
}
static void __init ptdump_initialize(void)
@@ -360,7 +353,7 @@ bool ptdump_check_wx(void)
}
};
- arm64_ptdump_walk_pgd(&st.ptdump, &init_mm);
+ ptdump_walk_pgd(&st.ptdump, &init_mm, NULL);
if (st.wx_pages || st.uxn_pages) {
pr_warn("Checked W+X mappings: FAILED, %lu W+X pages found, %lu non-UXN pages found\n",
diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index d5c4d2bb770b..f4fa227a8d7f 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -169,10 +169,7 @@ static int vmap_try_huge_pmd(pmd_t *pmd, unsigned long addr, unsigned long end,
* Concurrent read lock holders are safe: each exclusively owns
* the range it operates on and cannot reach this page table.
*/
-#ifndef CONFIG_ARM64
- scoped_cond_guard(mmap_read_lock_try, return 0, &init_mm)
-#endif
- {
+ scoped_cond_guard(mmap_read_lock_try, return 0, &init_mm) {
if (!pmd_free_pte_page(pmd, addr))
return 0;
return pmd_set_huge(pmd, phys_addr, prot);
@@ -229,10 +226,7 @@ static int vmap_try_huge_pud(pud_t *pud, unsigned long addr, unsigned long end,
return pud_set_huge(pud, phys_addr, prot);
/* See comment in vmap_try_huge_pmd(). */
-#ifndef CONFIG_ARM64
- scoped_cond_guard(mmap_read_lock_try, return 0, &init_mm)
-#endif
- {
+ scoped_cond_guard(mmap_read_lock_try, return 0, &init_mm) {
if (!pud_free_pmd_page(pud, addr))
return 0;
return pud_set_huge(pud, phys_addr, prot);
@@ -289,10 +283,7 @@ static int vmap_try_huge_p4d(p4d_t *p4d, unsigned long addr, unsigned long end,
return p4d_set_huge(p4d, phys_addr, prot);
/* See comment in vmap_try_huge_pmd(). */
-#ifndef CONFIG_ARM64
- scoped_cond_guard(mmap_read_lock_try, return 0, &init_mm)
-#endif
- {
+ scoped_cond_guard(mmap_read_lock_try, return 0, &init_mm) {
if (!p4d_free_pud_page(p4d, addr))
return 0;
return p4d_set_huge(p4d, phys_addr, prot);