Hi, thank you for the patch, and sorry for the long delay..
On 2025/06/09 14:02, Zhiquan Li wrote: > UEFI Specification version 2.9 introduces the concept of memory > acceptance: some Virtual Machine platforms, such as Intel TDX or AMD > SEV-SNP, requiring memory to be accepted before it can be used by the > guest. Accepting happens via a protocol specific for the Virtual > Machine platform[1]. > > Before unaccepted memory is accepted by guest, any access from guest > will result in the guest failed, as well as the kexec'ed kernel. So, > the kexec'ed kernel will skip these pages and fill in zero data for the > reader of vmcore. > > However, it introduces a problem. When exclude a page filled with zero, > a pd_zero, which sizeof(page_desc_t) is 24 bytes, will be written into > cd_header and this part is not compressed by design. As the unaccepted > pages are exported as zero pages, which means ~1/170 of the capacity of > unaccepted memory will be added into vmcore additionally. In fact, they > should be considered as free pages and most of the time should be > excluded. > > Unaccepted memory is unusable free memory, so they are not managed by > buddy, instead, they are added to a new list zone.unaccepted_pages only > when the order is MAX_PAGE_ORDER each time conventionally. The new > page type, PGTY_unaccepted can be used to identify whether a page is > unaccepted[2]. Therefore, add following changes to exclude them like > free pages: > > 1. Add NUMBER(PAGE_UNACCEPTED_MAPCOUNT_VALUE) to identify a page is > unaccepted, a kernel patch[3] to export the value of page type > PAGE_UNACCEPTED_MAPCOUNT_VALUE since kernel 6.16. > > 2. Add a condition to exclude these unaccepted free pages. > > Dumping host kernel will not be impacted by the modification, because it > cannot enable CONFIG_UNACCEPTED_MEMORY, so the page type > PAGE_UNACCEPTED_MAPCOUNT_VALUE cannot be found in vmcoreinfo and skip > the step. > > Here is a vmcore size statistic of a freshly booted TD VM with different > memory sizes: > > VM.mem | Before After > -------+---------------- > 512G | ~4.9G ~2.0G > 256G | ~2.0G ~1.1G > > [1] > https://lore.kernel.org/all/20230606142637.5171-1-kirill.shute...@linux.intel.com/ > [2] > https://lore.kernel.org/all/20240809114854.3745464-5-kirill.shute...@linux.intel.com/ > [3] https://lore.kernel.org/all/20250405060610.860465-1-zhiquan1...@intel.com/ > > Signed-off-by: Zhiquan Li <zhiquan1...@intel.com> > --- > makedumpfile.c | 14 ++++++++++++++ > makedumpfile.h | 3 +++ > 2 files changed, 17 insertions(+) > > diff --git a/makedumpfile.c b/makedumpfile.c > index 2d3b08bb5d52..97ec2f06108b 100644 > --- a/makedumpfile.c > +++ b/makedumpfile.c > @@ -2533,6 +2533,8 @@ write_vmcoreinfo_data(void) > WRITE_NUMBER("PAGE_BUDDY_MAPCOUNT_VALUE", PAGE_BUDDY_MAPCOUNT_VALUE); > WRITE_NUMBER("PAGE_OFFLINE_MAPCOUNT_VALUE", > PAGE_OFFLINE_MAPCOUNT_VALUE); > + WRITE_NUMBER("PAGE_UNACCEPTED_MAPCOUNT_VALUE", > + PAGE_UNACCEPTED_MAPCOUNT_VALUE); > WRITE_NUMBER("phys_base", phys_base); > WRITE_NUMBER("KERNEL_IMAGE_SIZE", KERNEL_IMAGE_SIZE); > > @@ -2990,6 +2992,7 @@ read_vmcoreinfo(void) > READ_NUMBER("PAGE_HUGETLB_MAPCOUNT_VALUE", PAGE_HUGETLB_MAPCOUNT_VALUE); > READ_NUMBER("PAGE_OFFLINE_MAPCOUNT_VALUE", PAGE_OFFLINE_MAPCOUNT_VALUE); > READ_NUMBER("PAGE_SLAB_MAPCOUNT_VALUE", PAGE_SLAB_MAPCOUNT_VALUE); > + READ_NUMBER("PAGE_UNACCEPTED_MAPCOUNT_VALUE", > PAGE_UNACCEPTED_MAPCOUNT_VALUE); > READ_NUMBER("phys_base", phys_base); > READ_NUMBER("KERNEL_IMAGE_SIZE", KERNEL_IMAGE_SIZE); > > @@ -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? Thanks, Kazu > + pfn_counter = &pfn_free; > + } > /* > * Exclude the non-private cache page. > */ > diff --git a/makedumpfile.h b/makedumpfile.h > index 944397a6f865..26940e7a3f81 100644 > --- a/makedumpfile.h > +++ b/makedumpfile.h > @@ -163,6 +163,8 @@ test_bit(int nr, unsigned long addr) > && (NUMBER(PG_hwpoison) != NOT_FOUND_NUMBER)) > #define isAnon(mapping, flags, _mapcount) \ > (((unsigned long)mapping & PAGE_MAPPING_ANON) != 0 && !isSlab(flags, > _mapcount)) > +#define isUnaccepted(_mapcount) (_mapcount == > (int)NUMBER(PAGE_UNACCEPTED_MAPCOUNT_VALUE) \ > + && (NUMBER(PAGE_UNACCEPTED_MAPCOUNT_VALUE) != > NOT_FOUND_NUMBER)) > > #define PTOB(X) (((unsigned long long)(X)) << > PAGESHIFT()) > #define BTOP(X) (((unsigned long long)(X)) >> > PAGESHIFT()) > @@ -2257,6 +2259,7 @@ struct number_table { > long PAGE_HUGETLB_MAPCOUNT_VALUE; > long PAGE_OFFLINE_MAPCOUNT_VALUE; > long PAGE_SLAB_MAPCOUNT_VALUE; > + long PAGE_UNACCEPTED_MAPCOUNT_VALUE; > long SECTION_SIZE_BITS; > long MAX_PHYSMEM_BITS; > long HUGETLB_PAGE_DTOR;