lkml.org 
[lkml]   [2021]   [Nov]   [15]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v6 01/23] mm: Introduce PTE_MARKER swap entry
    Date
    This patch introduces a new swap entry type called PTE_MARKER.  It can be
    installed for any pte that maps a file-backed memory when the pte is
    temporarily zapped, so as to maintain per-pte information.

    The information that kept in the pte is called a "marker". Here we define the
    marker as "unsigned long" just to match pgoff_t, however it will only work if
    it still fits in swp_offset(), which is e.g. currently 58 bits on x86_64.

    A new config CONFIG_PTE_MARKER is introduced too; it's by default off. A bunch
    of helpers are defined altogether to service the rest of the pte marker code.

    Signed-off-by: Peter Xu <peterx@redhat.com>
    ---
    include/asm-generic/hugetlb.h | 9 ++++
    include/linux/swap.h | 15 ++++++-
    include/linux/swapops.h | 78 +++++++++++++++++++++++++++++++++++
    mm/Kconfig | 7 ++++
    4 files changed, 108 insertions(+), 1 deletion(-)

    diff --git a/include/asm-generic/hugetlb.h b/include/asm-generic/hugetlb.h
    index 8e1e6244a89d..f39cad20ffc6 100644
    --- a/include/asm-generic/hugetlb.h
    +++ b/include/asm-generic/hugetlb.h
    @@ -2,6 +2,9 @@
    #ifndef _ASM_GENERIC_HUGETLB_H
    #define _ASM_GENERIC_HUGETLB_H

    +#include <linux/swap.h>
    +#include <linux/swapops.h>
    +
    static inline pte_t mk_huge_pte(struct page *page, pgprot_t pgprot)
    {
    return mk_pte(page, pgprot);
    @@ -80,6 +83,12 @@ static inline int huge_pte_none(pte_t pte)
    }
    #endif

    +/* Please refer to comments above pte_none_mostly() for the usage */
    +static inline int huge_pte_none_mostly(pte_t pte)
    +{
    + return huge_pte_none(pte) || is_pte_marker(pte);
    +}
    +
    #ifndef __HAVE_ARCH_HUGE_PTE_WRPROTECT
    static inline pte_t huge_pte_wrprotect(pte_t pte)
    {
    diff --git a/include/linux/swap.h b/include/linux/swap.h
    index d1ea44b31f19..cc9adcfd666f 100644
    --- a/include/linux/swap.h
    +++ b/include/linux/swap.h
    @@ -55,6 +55,19 @@ static inline int current_is_kswapd(void)
    * actions on faults.
    */

    +/*
    + * PTE markers are used to persist information onto PTEs that are mapped with
    + * file-backed memories. As its name "PTE" hints, it should only be applied to
    + * the leaves of pgtables.
    + */
    +#ifdef CONFIG_PTE_MARKER
    +#define SWP_PTE_MARKER_NUM 1
    +#define SWP_PTE_MARKER (MAX_SWAPFILES + SWP_HWPOISON_NUM + \
    + SWP_MIGRATION_NUM + SWP_DEVICE_NUM)
    +#else
    +#define SWP_PTE_MARKER_NUM 0
    +#endif
    +
    /*
    * Unaddressable device memory support. See include/linux/hmm.h and
    * Documentation/vm/hmm.rst. Short description is we need struct pages for
    @@ -100,7 +113,7 @@ static inline int current_is_kswapd(void)

    #define MAX_SWAPFILES \
    ((1 << MAX_SWAPFILES_SHIFT) - SWP_DEVICE_NUM - \
    - SWP_MIGRATION_NUM - SWP_HWPOISON_NUM)
    + SWP_MIGRATION_NUM - SWP_HWPOISON_NUM - SWP_PTE_MARKER_NUM)

    /*
    * Magic header for a swap area. The first part of the union is
    diff --git a/include/linux/swapops.h b/include/linux/swapops.h
    index d356ab4047f7..5103d2a4ae38 100644
    --- a/include/linux/swapops.h
    +++ b/include/linux/swapops.h
    @@ -247,6 +247,84 @@ static inline int is_writable_migration_entry(swp_entry_t entry)

    #endif

    +typedef unsigned long pte_marker;
    +
    +#define PTE_MARKER_MASK (0)
    +
    +#ifdef CONFIG_PTE_MARKER
    +
    +static inline swp_entry_t make_pte_marker_entry(pte_marker marker)
    +{
    + return swp_entry(SWP_PTE_MARKER, marker);
    +}
    +
    +static inline bool is_pte_marker_entry(swp_entry_t entry)
    +{
    + return swp_type(entry) == SWP_PTE_MARKER;
    +}
    +
    +static inline pte_marker pte_marker_get(swp_entry_t entry)
    +{
    + return swp_offset(entry) & PTE_MARKER_MASK;
    +}
    +
    +static inline bool is_pte_marker(pte_t pte)
    +{
    + return is_swap_pte(pte) && is_pte_marker_entry(pte_to_swp_entry(pte));
    +}
    +
    +#else /* CONFIG_PTE_MARKER */
    +
    +static inline swp_entry_t make_pte_marker_entry(pte_marker marker)
    +{
    + /* This should never be called if !CONFIG_PTE_MARKER */
    + WARN_ON_ONCE(1);
    + return swp_entry(0, 0);
    +}
    +
    +static inline bool is_pte_marker_entry(swp_entry_t entry)
    +{
    + return false;
    +}
    +
    +static inline pte_marker pte_marker_get(swp_entry_t entry)
    +{
    + return 0;
    +}
    +
    +static inline bool is_pte_marker(pte_t pte)
    +{
    + return false;
    +}
    +
    +#endif /* CONFIG_PTE_MARKER */
    +
    +static inline pte_t make_pte_marker(pte_marker marker)
    +{
    + return swp_entry_to_pte(make_pte_marker_entry(marker));
    +}
    +
    +/*
    + * This is a special version to check pte_none() just to cover the case when
    + * the pte is a pte marker. It existed because in many cases the pte marker
    + * should be seen as a none pte; it's just that we have stored some information
    + * onto the none pte so it becomes not-none any more.
    + *
    + * It should be used when the pte is file-backed, ram-based and backing
    + * userspace pages, like shmem. It is not needed upon pgtables that do not
    + * support pte markers at all. For example, it's not needed on anonymous
    + * memory, kernel-only memory (including when the system is during-boot),
    + * non-ram based generic file-system. It's fine to be used even there, but the
    + * extra pte marker check will be pure overhead.
    + *
    + * For systems configured with !CONFIG_PTE_MARKER this will be automatically
    + * optimized to pte_none().
    + */
    +static inline int pte_none_mostly(pte_t pte)
    +{
    + return pte_none(pte) || is_pte_marker(pte);
    +}
    +
    static inline struct page *pfn_swap_entry_to_page(swp_entry_t entry)
    {
    struct page *p = pfn_to_page(swp_offset(entry));
    diff --git a/mm/Kconfig b/mm/Kconfig
    index 068ce591a13a..66f23c6c2032 100644
    --- a/mm/Kconfig
    +++ b/mm/Kconfig
    @@ -897,6 +897,13 @@ config IO_MAPPING
    config SECRETMEM
    def_bool ARCH_HAS_SET_DIRECT_MAP && !EMBEDDED

    +config PTE_MARKER
    + def_bool n
    + bool "Marker PTEs support"
    +
    + help
    + Allows to create marker PTEs for file-backed memory.
    +
    source "mm/damon/Kconfig"

    endmenu
    --
    2.32.0
    \
     
     \ /
      Last update: 2021-11-15 08:57    [W:3.137 / U:0.016 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site