Re: [PATCH v3 06/24] KVM: x86/mmu: Disallow page merging (huge page adjustment) for mirror root

From: Yan Zhao

Date: Fri Jan 16 2026 - 02:57:44 EST


Hi Sean,
Thanks for the review!

On Thu, Jan 15, 2026 at 02:49:59PM -0800, Sean Christopherson wrote:
> On Tue, Jan 06, 2026, Yan Zhao wrote:
> > From: Rick P Edgecombe <rick.p.edgecombe@xxxxxxxxx>
> >
> > Disallow page merging (huge page adjustment) for the mirror root by
> > utilizing disallowed_hugepage_adjust().
>
> Why? What is this actually doing? The below explains "how" but I'm baffled as
> to the purpose. I'm guessing there are hints in the surrounding patches, but I
> haven't read them in depth, and shouldn't need to in order to understand the
> primary reason behind a change.
Sorry for missing the background. I will explain the "why" in the patch log in
the next version.

The reason for introducing this patch is to disallow page merging for TDX. I
explained the reasons to disallow page merging in the cover letter:

"
7. Page merging (page promotion)

Promotion is disallowed, because:

- The current TDX module requires all 4KB leafs to be either all PENDING
or all ACCEPTED before a successful promotion to 2MB. This requirement
prevents successful page merging after partially converting a 2MB
range from private to shared and then back to private, which is the
primary scenario necessitating page promotion.

- tdh_mem_page_promote() depends on tdh_mem_range_block() in the current
TDX module. Consequently, handling BUSY errors is complex, as page
merging typically occurs in the fault path under shared mmu_lock.

- Limited amount of initial private memory (typically ~4MB) means the
need for page merging during TD build time is minimal.
"

Without this patch, page promotion may be triggered in the following scenario:

1. guest_memfd allocates a 2MB folio for GPA X, so the max mapping level is 2MB.
2. KVM maps GPA X at 4KB level during TD build time.
3. Guest converts GPA X to shared, zapping the 4KB leaf private mapping while
keeping the 2MB non-leaf private mapping.
3. Guest converts GPA X to private and accepts it at 2MB level.
4. KVM maps GPA X at 2MB level, triggering page merging.

However, we currently don't support page merging yet. Specifically for the above
scenario, the purpose is to avoid handling the error from
tdh_mem_page_promote(), which SEAMCALL currently needs to be preceded by
tdh_mem_range_block(). To handle the promotion error (e.g., due to busy) under
read mmu_lock, we may need to introduce several spinlocks and guarantees from
the guest to ensure the success of tdh_mem_range_unblock() to restore the S-EPT
status.

Therefore, we introduced this patch for simplicity, and because the promotion
scenario is not common.