Re: [PATCH v3 16/26] mm: add definitions for allocating unmapped pages

"Brendan Jackman" <[email protected]>
Newsgroups gmane.linux.kernel,gmane.linux.kernel.mm
Message-ID <[email protected]>
On Tue Aug 4, 2026 at 8:53 PM BST, Yosry Ahmed wrote:
> On Sun, Jul 26, 2026 at 10:22:49PM +0000, Brendan Jackman wrote:
>> Create ALLOC_UNMAPPED, which requests pages that are not present in the
>> direct map. Since this feature has a cost (e.g. more freelists), it's
>> behind a kconfig. Unlike other conditionally-defined alloc flags, it
>> doesn't fall back to being 0. This prevents building code that uses
>> ALLOC_UNMAPPED but doesn't depend on the necessary kconfig, since that
>> would lead to invisible security issues.
>> 
>> Create a freetype flag to record that pages on the freelists with this
>> flag are unmapped. This is currently only needed for MIGRATE_UNMOVABLE
>> pages, so the freetype encoding remains trivial.
>> 
>> Also create the corresponding pageblock flag to record the same thing.
>> 
>> To keep patches from being too overwhelming, the actual implementation
>> is added separately, this is just types, Kconfig boilerplate, etc.
>> 
>> Acked-by: Vlastimil Babka (SUSE) <[email protected]>
>> Signed-off-by: Brendan Jackman <[email protected]>
>> ---
>>  include/linux/freetype.h | 70 ++++++++++++++++++++++++++++++++++++++++--------
>>  mm/Kconfig               |  3 +++
>>  mm/page_alloc.h          | 18 +++++++++++++
>>  3 files changed, 80 insertions(+), 11 deletions(-)
>> 
>> diff --git a/include/linux/freetype.h b/include/linux/freetype.h
>> index 3b0d44023b6a1..37e88dcccdecc 100644
>> --- a/include/linux/freetype.h
>> +++ b/include/linux/freetype.h
>> @@ -2,6 +2,7 @@
>>  #ifndef _LINUX_FREETYPE_H
>>  #define _LINUX_FREETYPE_H
>>  
>> +#include <linux/log2.h>
>>  #include <linux/types.h>
>>  #include <linux/mmdebug.h>
>>  
>> @@ -64,20 +65,47 @@ static inline bool migratetype_is_mergeable(int mt)
>>  	return mt < MIGRATE_PCPTYPES;
>>  }
>>  
>> +enum {
>> +	/* Defined unconditionally as a hack to avoid a zero-width bitfield. */
>> +	FREETYPE_UNMAPPED_BIT,
>> +	NUM_FREETYPE_FLAGS,
>> +};
>> +
>>  /*
>>   * A freetype is the identifier for a page freelist. This consists of a
>>   * migratetype, and other bits which encode orthogonal properties of memory.
>>   */
>>  typedef struct {
>> -	int migratetype;
>> +	unsigned int migratetype : order_base_2(MIGRATE_TYPES);
>> +	unsigned int flags : NUM_FREETYPE_FLAGS;
>>  } freetype_t;
>>  
>> +#ifdef CONFIG_PAGE_ALLOC_UNMAPPED
>> +#define FREETYPE_UNMAPPED			BIT(FREETYPE_UNMAPPED_BIT)
>> +#define NUM_UNMAPPED_FREETYPES			1
>> +#else
>> +#define FREETYPE_UNMAPPED			0
>> +#define NUM_UNMAPPED_FREETYPES			0
>> +#endif
>> +
>> +#define FREETYPE_FLAGS_MASK FREETYPE_UNMAPPED
>> +
>>  /*
>>   * Return a dense linear index for freetypes that have lists in the free area.
>>   * Return -1 for other freetypes.
>>   */
>>  static inline int freetype_idx(freetype_t freetype)
>>  {
>> +	/* For FREETYPE_UNMAPPED, only MIGRATE_UNMOVABLE has an index. */
>> +	if (freetype.flags & FREETYPE_UNMAPPED) {
>> +		VM_WARN_ON_ONCE(freetype.flags & ~FREETYPE_UNMAPPED);
>
> If we move this to the beginning of the function we can drop the
> VM_WARN_ON_ONCE() below, right?

This one says "assert no flags are set that are incompatible with
FREETYPE_UNMAPPED", the one below says "assert no completely invalid
freetype flags are set". Right now those are the same thing so we
_could_ combine them, but just happenstance.

>> +		if (freetype.migratetype != MIGRATE_UNMOVABLE)
>> +			return -1;
>> +		return MIGRATE_TYPES;
>> +	}
>> +	/* No other flags are supported. */
>> +	VM_WARN_ON_ONCE(freetype.flags);
>> +
>>  	return freetype.migratetype;
>>  }
>>  
>> @@ -85,33 +113,53 @@ static inline freetype_t freetype_from_idx(unsigned int idx)
>>  {
>>  	freetype_t freetype;
>>  
>> -	freetype.migratetype = idx;
>
> Do we need a comment here? Something like this maybe:
>
> 	/*
> 	 * There is one freetype per migratetype, as well as one extra
> 	 * free type for unmovable unmapped pages.
> 	 */
>
>> +	if (idx == MIGRATE_TYPES) {

Well we have basically that exact comment on the definition of
NR_FREETYPE_IDXS. Do you think we should move it here?

>
>> +		freetype.flags = FREETYPE_UNMAPPED;
>> +		freetype.migratetype = MIGRATE_UNMOVABLE;
>> +	} else {
>> +		VM_WARN_ON_ONCE(idx < 0 || idx > MIGRATE_TYPES);
>> +		freetype.flags = 0;
>> +		freetype.migratetype = idx;
>> +	}
>>  	return freetype;
>>  }
> [..]
>> diff --git a/mm/page_alloc.h b/mm/page_alloc.h
>> index 9928aa9012588..fac8e5304bb03 100644
>> --- a/mm/page_alloc.h
>> +++ b/mm/page_alloc.h
>> @@ -56,6 +56,24 @@
>>   * alloc_tag_sub_check().
>>   */
>>  #define ALLOC_NO_CODETAG       0x1000
>> +#ifdef CONFIG_PAGE_ALLOC_UNMAPPED
>> +/*
>> + * Allocate pages that aren't present in the direct map. If the caller changes
>> + * direct map presence, it must be restored to the previous state before freeing
>> + * the page. (This is true regardless of ALLOC_UNMAPPED).
>> + *
>> + * This uses the mermap (when __GFP_ZERO), so it's only valid to allocate with
>> + * this flag where that's valid, namely from process context after the mermap
>> + * has been initialised for that process. This also means that the allocator
>> + * leaves behind stale TLB entries in the mermap region. The caller is
>> + * responsible for ensuring they are flushed as needed.
>
> I think this is no longer true as the allocator does not use the mermap
> with __GFP_ZERO anymore?

Oops, yep thanks.

>> + *
>> + * This is currently incompatible with __GFP_MOVABLE and __GFP_RECLAIMABLE, but
>> + * only because of allocator implementation details, if a usecase arises this
>> + * restriction could be dropped.
>
> It would help to explain why it's incompatible with __GFP_MOVABLE and
> __GFP_RECLAIMABLE, here or in the changelog. I assume mainly because we
> only have one freetype for unmapped unmovable, but there are also some
> more interesting details like compaction needing to support copying
> unmapped pages (e.g. via the mermap)?

Yeah the latter is the reason I had in mind (also not just copying them
when they're unmapped but also being aware of when it needs to "promote"
a compaction to generate an entire block). 

And yeah it makes sense to have that in a comment. This is a kinda "API
comment" so spiritually it doesn't really belong here but I'd probably
put it here anyway in parans just coz that's where it will actually be
seen...
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.