From: Anshuman Khandual <anshuman.khandual@arm.com>
To: Ryan Roberts <ryan.roberts@arm.com>,
Catalin Marinas <catalin.marinas@arm.com>,
Will Deacon <will@kernel.org>,
Muchun Song <muchun.song@linux.dev>,
Pasha Tatashin <pasha.tatashin@soleen.com>,
Andrew Morton <akpm@linux-foundation.org>,
Uladzislau Rezki <urezki@gmail.com>,
Christoph Hellwig <hch@infradead.org>,
Mark Rutland <mark.rutland@arm.com>,
Ard Biesheuvel <ardb@kernel.org>, Dev Jain <dev.jain@arm.com>,
Alexandre Ghiti <alexghiti@rivosinc.com>,
Steve Capper <steve.capper@linaro.org>,
Kevin Brodsky <kevin.brodsky@arm.com>
Cc: linux-arm-kernel@lists.infradead.org, linux-mm@kvack.org,
linux-kernel@vger.kernel.org
Subject: Re: [PATCH v1 15/16] mm: Generalize arch_sync_kernel_mappings()
Date: Mon, 10 Feb 2025 13:15:50 +0530 [thread overview]
Message-ID: <43c256b6-7e44-41bb-b0c5-866fd4faab5c@arm.com> (raw)
In-Reply-To: <20250205151003.88959-16-ryan.roberts@arm.com>
On 2/5/25 20:39, Ryan Roberts wrote:
> arch_sync_kernel_mappings() is an optional hook for arches to allow them
> to synchonize certain levels of the kernel pgtables after modification.
> But arm64 could benefit from a hook similar to this, paired with a call
> prior to starting the batch of modifications.
>
> So let's introduce arch_update_kernel_mappings_begin() and
> arch_update_kernel_mappings_end(). Both have a default implementation
> which can be overridden by the arch code. The default for the former is
> a nop, and the default for the latter is to call
> arch_sync_kernel_mappings(), so the latter replaces previous
> arch_sync_kernel_mappings() callsites. So by default, the resulting
> behaviour is unchanged.
>
> To avoid include hell, the pgtbl_mod_mask type and it's associated
> macros are moved to their own header.
>
> In a future patch, arm64 will opt-in to overriding both functions.
>
> Signed-off-by: Ryan Roberts <ryan.roberts@arm.com>
> ---
> include/linux/pgtable.h | 24 +----------------
> include/linux/pgtable_modmask.h | 32 ++++++++++++++++++++++
> include/linux/vmalloc.h | 47 +++++++++++++++++++++++++++++++++
> mm/memory.c | 5 ++--
> mm/vmalloc.c | 15 ++++++-----
> 5 files changed, 92 insertions(+), 31 deletions(-)
> create mode 100644 include/linux/pgtable_modmask.h
>
> diff --git a/include/linux/pgtable.h b/include/linux/pgtable.h
> index 94d267d02372..7f70786a73b3 100644
> --- a/include/linux/pgtable.h
> +++ b/include/linux/pgtable.h
> @@ -4,6 +4,7 @@
>
> #include <linux/pfn.h>
> #include <asm/pgtable.h>
> +#include <linux/pgtable_modmask.h>
>
> #define PMD_ORDER (PMD_SHIFT - PAGE_SHIFT)
> #define PUD_ORDER (PUD_SHIFT - PAGE_SHIFT)
> @@ -1786,29 +1787,6 @@ static inline bool arch_has_pfn_modify_check(void)
> # define PAGE_KERNEL_EXEC PAGE_KERNEL
> #endif
>
> -/*
> - * Page Table Modification bits for pgtbl_mod_mask.
> - *
> - * These are used by the p?d_alloc_track*() set of functions an in the generic
> - * vmalloc/ioremap code to track at which page-table levels entries have been
> - * modified. Based on that the code can better decide when vmalloc and ioremap
> - * mapping changes need to be synchronized to other page-tables in the system.
> - */
> -#define __PGTBL_PGD_MODIFIED 0
> -#define __PGTBL_P4D_MODIFIED 1
> -#define __PGTBL_PUD_MODIFIED 2
> -#define __PGTBL_PMD_MODIFIED 3
> -#define __PGTBL_PTE_MODIFIED 4
> -
> -#define PGTBL_PGD_MODIFIED BIT(__PGTBL_PGD_MODIFIED)
> -#define PGTBL_P4D_MODIFIED BIT(__PGTBL_P4D_MODIFIED)
> -#define PGTBL_PUD_MODIFIED BIT(__PGTBL_PUD_MODIFIED)
> -#define PGTBL_PMD_MODIFIED BIT(__PGTBL_PMD_MODIFIED)
> -#define PGTBL_PTE_MODIFIED BIT(__PGTBL_PTE_MODIFIED)
> -
> -/* Page-Table Modification Mask */
> -typedef unsigned int pgtbl_mod_mask;
> -
> #endif /* !__ASSEMBLY__ */
>
> #if !defined(MAX_POSSIBLE_PHYSMEM_BITS) && !defined(CONFIG_64BIT)
> diff --git a/include/linux/pgtable_modmask.h b/include/linux/pgtable_modmask.h
> new file mode 100644
> index 000000000000..5a21b1bb8df3
> --- /dev/null
> +++ b/include/linux/pgtable_modmask.h
> @@ -0,0 +1,32 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +#ifndef _LINUX_PGTABLE_MODMASK_H
> +#define _LINUX_PGTABLE_MODMASK_H
> +
> +#ifndef __ASSEMBLY__
> +
> +/*
> + * Page Table Modification bits for pgtbl_mod_mask.
> + *
> + * These are used by the p?d_alloc_track*() set of functions an in the generic
> + * vmalloc/ioremap code to track at which page-table levels entries have been
> + * modified. Based on that the code can better decide when vmalloc and ioremap
> + * mapping changes need to be synchronized to other page-tables in the system.
> + */
> +#define __PGTBL_PGD_MODIFIED 0
> +#define __PGTBL_P4D_MODIFIED 1
> +#define __PGTBL_PUD_MODIFIED 2
> +#define __PGTBL_PMD_MODIFIED 3
> +#define __PGTBL_PTE_MODIFIED 4
> +
> +#define PGTBL_PGD_MODIFIED BIT(__PGTBL_PGD_MODIFIED)
> +#define PGTBL_P4D_MODIFIED BIT(__PGTBL_P4D_MODIFIED)
> +#define PGTBL_PUD_MODIFIED BIT(__PGTBL_PUD_MODIFIED)
> +#define PGTBL_PMD_MODIFIED BIT(__PGTBL_PMD_MODIFIED)
> +#define PGTBL_PTE_MODIFIED BIT(__PGTBL_PTE_MODIFIED)
> +
> +/* Page-Table Modification Mask */
> +typedef unsigned int pgtbl_mod_mask;
> +
> +#endif /* !__ASSEMBLY__ */
> +
> +#endif /* _LINUX_PGTABLE_MODMASK_H */
> diff --git a/include/linux/vmalloc.h b/include/linux/vmalloc.h
> index 16dd4cba64f2..cb5d8f1965a1 100644
> --- a/include/linux/vmalloc.h
> +++ b/include/linux/vmalloc.h
> @@ -11,6 +11,7 @@
> #include <asm/page.h> /* pgprot_t */
> #include <linux/rbtree.h>
> #include <linux/overflow.h>
> +#include <linux/pgtable_modmask.h>
>
> #include <asm/vmalloc.h>
>
> @@ -213,6 +214,26 @@ extern int remap_vmalloc_range(struct vm_area_struct *vma, void *addr,
> int vmap_pages_range(unsigned long addr, unsigned long end, pgprot_t prot,
> struct page **pages, unsigned int page_shift);
>
> +#ifndef arch_update_kernel_mappings_begin
> +/**
> + * arch_update_kernel_mappings_begin - A batch of kernel pgtable mappings are
> + * about to be updated.
> + * @start: Virtual address of start of range to be updated.
> + * @end: Virtual address of end of range to be updated.
> + *
> + * An optional hook to allow architecture code to prepare for a batch of kernel
> + * pgtable mapping updates. An architecture may use this to enter a lazy mode
> + * where some operations can be deferred until the end of the batch.
> + *
> + * Context: Called in task context and may be preemptible.
> + */
> +static inline void arch_update_kernel_mappings_begin(unsigned long start,
> + unsigned long end)
> +{
> +}
> +#endif
> +
> +#ifndef arch_update_kernel_mappings_end
> /*
> * Architectures can set this mask to a combination of PGTBL_P?D_MODIFIED values
> * and let generic vmalloc and ioremap code know when arch_sync_kernel_mappings()
> @@ -229,6 +250,32 @@ int vmap_pages_range(unsigned long addr, unsigned long end, pgprot_t prot,
> */
> void arch_sync_kernel_mappings(unsigned long start, unsigned long end);
>
> +/**
> + * arch_update_kernel_mappings_end - A batch of kernel pgtable mappings have
> + * been updated.
> + * @start: Virtual address of start of range that was updated.
> + * @end: Virtual address of end of range that was updated.
> + *
> + * An optional hook to inform architecture code that a batch update is complete.
> + * This balances a previous call to arch_update_kernel_mappings_begin().
> + *
> + * An architecture may override this for any purpose, such as exiting a lazy
> + * mode previously entered with arch_update_kernel_mappings_begin() or syncing
> + * kernel mappings to a secondary pgtable. The default implementation calls an
> + * arch-provided arch_sync_kernel_mappings() if any arch-defined pgtable level
> + * was updated.
> + *
> + * Context: Called in task context and may be preemptible.
> + */
> +static inline void arch_update_kernel_mappings_end(unsigned long start,
> + unsigned long end,
> + pgtbl_mod_mask mask)
> +{
> + if (mask & ARCH_PAGE_TABLE_SYNC_MASK)
> + arch_sync_kernel_mappings(start, end);
> +}
One arch call back calling yet another arch call back sounds bit odd. Also
should not ARCH_PAGE_TABLE_SYNC_MASK be checked both for __begin and __end
callbacks in case a platform subscribes into this framework. Instead the
following changes sound more reasonable, but will also require some more
updates for the current platforms using arch_sync_kernel_mappings().
if (mask & ARCH_PAGE_TABLE_SYNC_MASK)
arch_update_kernel_mappings_begin()
if (mask & ARCH_PAGE_TABLE_SYNC_MASK)
arch_update_kernel_mappings_end()
Basically when any platform defines ARCH_PAGE_TABLE_SYNC_MASK and subscribes
this framework, it will also provide arch_update_kernel_mappings_begin/end()
callbacks as required.
> +#endif
> +
> /*
> * Lowlevel-APIs (not for driver use!)
> */
> diff --git a/mm/memory.c b/mm/memory.c
> index a15f7dd500ea..f80930bc19f6 100644
> --- a/mm/memory.c
> +++ b/mm/memory.c
> @@ -3035,6 +3035,8 @@ static int __apply_to_page_range(struct mm_struct *mm, unsigned long addr,
> if (WARN_ON(addr >= end))
> return -EINVAL;
>
> + arch_update_kernel_mappings_begin(start, end);
> +
> pgd = pgd_offset(mm, addr);
> do {
> next = pgd_addr_end(addr, end);
> @@ -3055,8 +3057,7 @@ static int __apply_to_page_range(struct mm_struct *mm, unsigned long addr,
> break;
> } while (pgd++, addr = next, addr != end);
>
> - if (mask & ARCH_PAGE_TABLE_SYNC_MASK)
> - arch_sync_kernel_mappings(start, start + size);
> + arch_update_kernel_mappings_end(start, end, mask);
>
> return err;
> }
> diff --git a/mm/vmalloc.c b/mm/vmalloc.c
> index 50fd44439875..c5c51d86ef78 100644
> --- a/mm/vmalloc.c
> +++ b/mm/vmalloc.c
> @@ -312,10 +312,10 @@ int vmap_page_range(unsigned long addr, unsigned long end,
> pgtbl_mod_mask mask = 0;
> int err;
>
> + arch_update_kernel_mappings_begin(addr, end);
> err = vmap_range_noflush(addr, end, phys_addr, pgprot_nx(prot),
> ioremap_max_page_shift, &mask);
> - if (mask & ARCH_PAGE_TABLE_SYNC_MASK)
> - arch_sync_kernel_mappings(addr, end);
> + arch_update_kernel_mappings_end(addr, end, mask);
>
> flush_cache_vmap(addr, end);
> if (!err)
> @@ -463,6 +463,9 @@ void __vunmap_range_noflush(unsigned long start, unsigned long end)
> pgtbl_mod_mask mask = 0;
>
> BUG_ON(addr >= end);
> +
> + arch_update_kernel_mappings_begin(start, end);
> +
> pgd = pgd_offset_k(addr);
> do {
> next = pgd_addr_end(addr, end);
> @@ -473,8 +476,7 @@ void __vunmap_range_noflush(unsigned long start, unsigned long end)
> vunmap_p4d_range(pgd, addr, next, &mask);
> } while (pgd++, addr = next, addr != end);
>
> - if (mask & ARCH_PAGE_TABLE_SYNC_MASK)
> - arch_sync_kernel_mappings(start, end);
> + arch_update_kernel_mappings_end(start, end, mask);
> }
>
> void vunmap_range_noflush(unsigned long start, unsigned long end)
> @@ -625,6 +627,8 @@ int __vmap_pages_range_noflush(unsigned long addr, unsigned long end,
>
> WARN_ON(page_shift < PAGE_SHIFT);
>
> + arch_update_kernel_mappings_begin(start, end);
> +
> if (!IS_ENABLED(CONFIG_HAVE_ARCH_HUGE_VMALLOC) ||
> page_shift == PAGE_SHIFT) {
> err = vmap_small_pages_range_noflush(addr, end, prot, pages,
> @@ -642,8 +646,7 @@ int __vmap_pages_range_noflush(unsigned long addr, unsigned long end,
> }
> }
>
> - if (mask & ARCH_PAGE_TABLE_SYNC_MASK)
> - arch_sync_kernel_mappings(start, end);
> + arch_update_kernel_mappings_end(start, end, mask);
>
> return err;
> }
next prev parent reply other threads:[~2025-02-10 7:47 UTC|newest]
Thread overview: 62+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-02-05 15:09 [PATCH v1 00/16] hugetlb and vmalloc fixes and perf improvements Ryan Roberts
2025-02-05 15:09 ` [PATCH v1 01/16] mm: hugetlb: Add huge page size param to huge_ptep_get_and_clear() Ryan Roberts
2025-02-06 5:03 ` Anshuman Khandual
2025-02-06 12:15 ` Ryan Roberts
2025-02-05 15:09 ` [PATCH v1 02/16] arm64: hugetlb: Fix huge_ptep_get_and_clear() for non-present ptes Ryan Roberts
2025-02-06 6:15 ` Anshuman Khandual
2025-02-06 12:55 ` Ryan Roberts
2025-02-12 14:44 ` Ryan Roberts
2025-02-05 15:09 ` [PATCH v1 03/16] arm64: hugetlb: Fix flush_hugetlb_tlb_range() invalidation level Ryan Roberts
2025-02-06 6:46 ` Anshuman Khandual
2025-02-06 13:04 ` Ryan Roberts
2025-02-13 4:57 ` Anshuman Khandual
2025-02-05 15:09 ` [PATCH v1 04/16] arm64: hugetlb: Refine tlb maintenance scope Ryan Roberts
2025-02-05 15:09 ` [PATCH v1 05/16] mm/page_table_check: Batch-check pmds/puds just like ptes Ryan Roberts
2025-02-06 10:55 ` Anshuman Khandual
2025-02-06 13:07 ` Ryan Roberts
2025-02-05 15:09 ` [PATCH v1 06/16] arm64/mm: Refactor __set_ptes() and __ptep_get_and_clear() Ryan Roberts
2025-02-06 11:48 ` Anshuman Khandual
2025-02-06 13:26 ` Ryan Roberts
2025-02-07 9:38 ` Ryan Roberts
2025-02-12 15:29 ` Ryan Roberts
2025-02-05 15:09 ` [PATCH v1 07/16] arm64: hugetlb: Use ___set_ptes() and ___ptep_get_and_clear() Ryan Roberts
2025-02-07 4:09 ` Anshuman Khandual
2025-02-07 10:00 ` Ryan Roberts
2025-02-05 15:09 ` [PATCH v1 08/16] arm64/mm: Hoist barriers out of ___set_ptes() loop Ryan Roberts
2025-02-07 5:35 ` Anshuman Khandual
2025-02-07 10:38 ` Ryan Roberts
2025-02-12 16:00 ` Ryan Roberts
2025-02-05 15:09 ` [PATCH v1 09/16] arm64/mm: Avoid barriers for invalid or userspace mappings Ryan Roberts
2025-02-07 8:11 ` Anshuman Khandual
2025-02-07 10:53 ` Ryan Roberts
2025-02-12 16:48 ` Ryan Roberts
2025-02-05 15:09 ` [PATCH v1 10/16] mm/vmalloc: Warn on improper use of vunmap_range() Ryan Roberts
2025-02-07 8:41 ` Anshuman Khandual
2025-02-07 10:59 ` Ryan Roberts
2025-02-13 6:36 ` Anshuman Khandual
2025-02-05 15:09 ` [PATCH v1 11/16] mm/vmalloc: Gracefully unmap huge ptes Ryan Roberts
2025-02-07 9:19 ` Anshuman Khandual
2025-02-05 15:09 ` [PATCH v1 12/16] arm64/mm: Support huge pte-mapped pages in vmap Ryan Roberts
2025-02-07 10:04 ` Anshuman Khandual
2025-02-07 11:20 ` Ryan Roberts
2025-02-13 6:32 ` Anshuman Khandual
2025-02-13 9:09 ` Ryan Roberts
2025-02-17 4:33 ` Anshuman Khandual
2025-02-05 15:09 ` [PATCH v1 13/16] mm: Don't skip arch_sync_kernel_mappings() in error paths Ryan Roberts
2025-02-07 10:21 ` Anshuman Khandual
2025-02-05 15:09 ` [PATCH v1 14/16] mm/vmalloc: Batch arch_sync_kernel_mappings() more efficiently Ryan Roberts
2025-02-10 7:11 ` Anshuman Khandual
2025-02-05 15:09 ` [PATCH v1 15/16] mm: Generalize arch_sync_kernel_mappings() Ryan Roberts
2025-02-10 7:45 ` Anshuman Khandual [this message]
2025-02-10 11:04 ` Ryan Roberts
2025-02-13 5:57 ` Anshuman Khandual
2025-02-13 9:17 ` Ryan Roberts
2025-02-05 15:09 ` [PATCH v1 16/16] arm64/mm: Defer barriers when updating kernel mappings Ryan Roberts
2025-02-10 8:03 ` Anshuman Khandual
2025-02-10 11:12 ` Ryan Roberts
2025-02-13 5:30 ` Anshuman Khandual
2025-02-13 9:38 ` Ryan Roberts
2025-02-17 4:48 ` Anshuman Khandual
2025-02-17 9:40 ` Ryan Roberts
2025-02-06 7:52 ` [PATCH v1 00/16] hugetlb and vmalloc fixes and perf improvements Andrew Morton
2025-02-06 11:59 ` Ryan Roberts
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=43c256b6-7e44-41bb-b0c5-866fd4faab5c@arm.com \
--to=anshuman.khandual@arm.com \
--cc=akpm@linux-foundation.org \
--cc=alexghiti@rivosinc.com \
--cc=ardb@kernel.org \
--cc=catalin.marinas@arm.com \
--cc=dev.jain@arm.com \
--cc=hch@infradead.org \
--cc=kevin.brodsky@arm.com \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=mark.rutland@arm.com \
--cc=muchun.song@linux.dev \
--cc=pasha.tatashin@soleen.com \
--cc=ryan.roberts@arm.com \
--cc=steve.capper@linaro.org \
--cc=urezki@gmail.com \
--cc=will@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.