Re: [PATCH v9 18/41] KVM: TDX: Make source page optional for KVM_TDX_INIT_MEM_REGION

Xiaoyao Li <[email protected]>
Newsgroups org.kernel.vger.linux-kselftest,dev.linux.lists.linux-coco,org.kernel.vger.kvm,org.kernel.vger.linux-doc,org.kernel.vger.linux-kernel,org.kernel.vger.linux-trace-kernel,org.kvack.linux-mm
Message-ID <[email protected]>
On 7/29/2026 8:35 AM, Ackerley Tng via B4 Relay wrote:
> From: Ackerley Tng <[email protected]>
> 
> Update tdx_gmem_post_populate() to handle cases where userspace requests
> "no source page". To handle "no source page", populate (perform
> TDH.MEM.PAGE.ADD) using memory in-place at the target PFN.
> 
> Signed-off-by: Sean Christopherson <[email protected]>
> Tested-by: Shivank Garg <[email protected]>
> Signed-off-by: Ackerley Tng <[email protected]>
> ---
>   Documentation/virt/kvm/x86/intel-tdx.rst | 4 ++++
>   arch/x86/kvm/vmx/tdx.c                   | 8 +++++---
>   2 files changed, 9 insertions(+), 3 deletions(-)
> 
> diff --git a/Documentation/virt/kvm/x86/intel-tdx.rst b/Documentation/virt/kvm/x86/intel-tdx.rst
> index 6a222e9d09541..d8d9409120e61 100644
> --- a/Documentation/virt/kvm/x86/intel-tdx.rst
> +++ b/Documentation/virt/kvm/x86/intel-tdx.rst
> @@ -158,6 +158,10 @@ KVM_TDX_INIT_MEM_REGION
>   Initialize @nr_pages TDX guest private memory starting from @gpa with userspace
>   provided data from @source_addr. @source_addr must be PAGE_SIZE-aligned.
>   
> +If guest_memfd in-place conversion is enabled, pass 0 for @source_addr
> +to represent "no source page". A source page is required if in-place
> +conversion is not enabled or not supported.
> +
>   Note, before calling this sub command, memory attribute of the range
>   [gpa, gpa + nr_pages] needs to be private.  Userspace can use
>   KVM_SET_MEMORY_ATTRIBUTES to set the attribute.
> diff --git a/arch/x86/kvm/vmx/tdx.c b/arch/x86/kvm/vmx/tdx.c
> index d1af0a752e97e..e890da5f18aed 100644
> --- a/arch/x86/kvm/vmx/tdx.c
> +++ b/arch/x86/kvm/vmx/tdx.c
> @@ -3192,7 +3192,7 @@ static int tdx_gmem_post_populate(struct kvm *kvm, gfn_t gfn, kvm_pfn_t pfn,
>   	if (KVM_BUG_ON(kvm_tdx->page_add_src, kvm))
>   		return -EIO;
>   
> -	kvm_tdx->page_add_src = src_page;
> +	kvm_tdx->page_add_src = src_page ?: pfn_to_page(pfn);
>   	ret = kvm_tdp_mmu_map_private_pfn(arg->vcpu, gfn, pfn);
>   	kvm_tdx->page_add_src = NULL;
>   
> @@ -3238,7 +3238,8 @@ static int tdx_vcpu_init_mem_region(struct kvm_vcpu *vcpu, struct kvm_tdx_cmd *c
>   	if (copy_from_user(&region, u64_to_user_ptr(cmd->data), sizeof(region)))
>   		return -EFAULT;
>   
> -	if (!PAGE_ALIGNED(region.source_addr) || !region.source_addr ||
> +	if (!PAGE_ALIGNED(region.source_addr) ||
> +	    (!gmem_in_place_conversion && !region.source_addr) ||

Sorry, I still want to discuss why we only allow in-place PAGE.ADD for 
gmem_in_place_conversion only. Though Yan raised this opinion[1] in 
previous v8, I'm not quite following her argument. So let me try again.

I think in-place PAGE.ADD of TDX doesn't need to depend on 
gmem_in_place_conversion. There are two use cases actually.

1). Userspace sets the gmem page as private, and invokes the in-place 
PAGE.ADD by passing a 0 source_addr. Due to patch 16, the target PFN 
will be ADD'ed to TD as a all-0 page.

2). Userspace sets the gmem page as shared, and writes the desired 
content to it. Then converts the page to private, and invokes the 
in-place PAGE.ADD by passing a 0 source_addr. The target PFN will be 
ADD'ed to TD with desired content.

For gmem_in_place_conversion == false, only case 1) is possible.
For gmem_in_place_conversion == true, both case 1) and 2) are possible.

Basically, this patch is changing the behavior of 
KVM_TDX_INIT_MEM_REGION. Before, it returns -EINVAL when 
region.source_addr == 0. Now it wants to allow the "region.source_addr 
== 0" case. If we can allow it unconditionally, why bother adding the 
restriction to allow it only when gmem_in_place_conversion == true?


[1] https://lore.kernel.org/all/[email protected]/

>   	    !PAGE_ALIGNED(region.gpa) || !region.nr_pages ||
>   	    region.gpa + (region.nr_pages << PAGE_SHIFT) <= region.gpa ||
>   	    !vt_is_tdx_private_gpa(kvm, region.gpa) ||
> @@ -3269,7 +3270,8 @@ static int tdx_vcpu_init_mem_region(struct kvm_vcpu *vcpu, struct kvm_tdx_cmd *c
>   			break;
>   		}
>   
> -		region.source_addr += PAGE_SIZE;
> +		if (region.source_addr)
> +			region.source_addr += PAGE_SIZE;
>   		region.gpa += PAGE_SIZE;
>   		region.nr_pages--;
>   
>
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.