On Monday, 15 November 2021 6:55:00 PM AEDT Peter Xu wrote: [...] > 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; I'm not sure the PTE_MARKER_MASK adds much, especially as we only have one user. I don't see a problem with open-coding these kind of checks (ie. swp_offset(entry) & PTE_MARKER_UFFD_WP) as you kind of end up doing that anyway. Alternatively if you want helper functions I think it would be better to define them for each marker. Eg: is_pte_marker_uffd_wp(). > +} > + > +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 */ Can we leave this function undefined then? That way we will get an obvious build error. Overall I'm liking the swap entry approach a lot more than the special pte approach, but maybe that's just because I'm more familiar with special swap entries :-) > + 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 >