[PATCH makedumpfile] Add confidential VM unaccepted free pages support on Linux 6.16 and later

Zhiquan Li zhiquan1.li at intel.com
Sun Jun 29 23:30:30 PDT 2025


On 2025/6/30 12:05, HAGIO KAZUHITO(萩尾 一仁) wrote:
> Hi,
> 
> thank you for the patch, and sorry for the long delay..
> 

Thanks for your time to review this patch.  There is a lot of background
knowledge behind this feature, it really needs a long time to digest them.

>> @@ -6630,6 +6633,17 @@ check_order:
>>   			nr_pages = 1 << private;
>>   			pfn_counter = &pfn_free;
>>   		}
>> +		/*
>> +		 * Exclude the unaccepted free pages not managed by buddy.
>> +		 * By convention, pages can be added to the zone.unaccepted_pages list
>> +		 * only when the order is MAX_ORDER_NR_PAGES.  Otherwise, the page is
>> +		 * accepted immediately without being on the list.
>> +		 */
>> +		else if ((info->dump_level & DL_EXCLUDE_FREE)
>> +			&& isUnaccepted(_mapcount)) {
> 
>> +			nr_pages = 1 << (ARRAY_LENGTH(zone.free_area) - 1);
> 
> just to clarify, does this mean that the order of unaccepted pages is 
> MAX_PAGE_ORDER but it's not set in struct page, so we need to set the 
> order here?
> 

Yes, the unit of operations on the buddy system for unaccepted pages is
MAX_PAGE_ORDER, and the type PGTY_unaccepted is only applied on the
first of struct page, not each struct page of MAX_PAGE_ORDER unaccepted
pages need the type.  Therefore, if we see one struct page with the
PGTY_unaccepted type, that means the next MAX_PAGE_ORDER-1 unaccepted
pages are added to zone.unaccepted_pages list.


The corresponding kernel code snippets are here:

1. the condition to add unaccepted pages to zone->unaccepted_pages list:

1428 void __meminit __free_pages_core(struct page *page, unsigned int order,
1429         enum meminit_context context)
1430 {
...
1462     if (page_contains_unaccepted(page, order)) {
1463         if (order == MAX_PAGE_ORDER && __free_unaccepted(page))
1464             return;
1465
1466         accept_memory(page_to_phys(page), PAGE_SIZE << order);
1467     }
...
1474 }

At L1463. only when the order is MAX_PAGE_ORDER, the first page is added
zone->unaccepted_pages list, otherwise, accept the unaligned pages
(whose order is not MAX_PAGE_ORDER) immediately.  As the unit is always
MAX_PAGE_ORDER (Condition 1), it's not necessary to set PGTY_unaccepted
one by one for each struct page.

https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/mm/page_alloc.c?h=v6.16-rc4#n1463


2. the operation to append unaccepted pages to zone->unaccepted_pages list:

7278 static bool __free_unaccepted(struct page *page)
7279 {
7280     struct zone *zone = page_zone(page);
...
7287     list_add_tail(&page->lru, &zone->unaccepted_pages);
7288     account_freepages(zone, MAX_ORDER_NR_PAGES, MIGRATE_MOVABLE);
7289     __mod_zone_page_state(zone, NR_UNACCEPTED, MAX_ORDER_NR_PAGES);
7290     __SetPageUnaccepted(page);
...
7294 }

As you can see, the linked list append operation and set PGTY_unaccepted
is only applied on the first page.  But the number of account and
statistic is MAX_ORDER_NR_PAGES.

https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/mm/page_alloc.c?h=v6.16-rc4#n7278


3. the operation to move unaccepted pages from zone->unaccepted_pages
list to buddy system:

7191 static void __accept_page(struct zone *zone, unsigned long *flags,
7192               struct page *page)
7193 {
7194     list_del(&page->lru);
7195     account_freepages(zone, -MAX_ORDER_NR_PAGES, MIGRATE_MOVABLE);
7196     __mod_zone_page_state(zone, NR_UNACCEPTED, -MAX_ORDER_NR_PAGES);
7197     __ClearPageUnaccepted(page);
...
7200     accept_memory(page_to_phys(page), PAGE_SIZE << MAX_PAGE_ORDER);
7201
7202     __free_pages_ok(page, MAX_PAGE_ORDER, FPI_TO_TAIL);
7203 }

As you can see, the linked list remove operation and clear
PGTY_unaccepted is only applied on the first page.  And the unit of
account and statistic is still MAX_ORDER_NR_PAGES.

Then accept the pages in size PAGE_SIZE << MAX_PAGE_ORDER at L7200 and
add the MAX_PAGE_ORDER pages to buddy system.

https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/mm/page_alloc.c?h=v6.16-rc4#n7191


The consideration for Linux kernel is the overhead of switching
operation from SEAM non-root mode -> SEAM root mode while accept page is
big, so it accepted as many pages as possible at a time.  If
makedumpfile can be aware of this feature, it can save a lot of disk
space and dump time.


Best Regards,
Zhiquan



More information about the kexec mailing list