All of lore.kernel.org
 help / color / mirror / Atom feed
From: Vincent Donnefort <vdonnefort@google.com>
To: Will Deacon <will@kernel.org>
Cc: kvmarm@lists.linux.dev, linux-arm-kernel@lists.infradead.org,
	Marc Zyngier <maz@kernel.org>, Oliver Upton <oupton@kernel.org>,
	Joey Gouly <joey.gouly@arm.com>,
	Suzuki K Poulose <suzuki.poulose@arm.com>,
	Zenghui Yu <yuzenghui@huawei.com>,
	Catalin Marinas <catalin.marinas@arm.com>,
	Quentin Perret <qperret@google.com>,
	Fuad Tabba <tabba@google.com>,
	Mostafa Saleh <smostafa@google.com>
Subject: Re: [PATCH 13/30] KVM: arm64: Introduce __pkvm_reclaim_dying_guest_page()
Date: Tue, 6 Jan 2026 16:26:44 +0000	[thread overview]
Message-ID: <aV03xOYPTdurX2k4@google.com> (raw)
In-Reply-To: <20260105154939.11041-14-will@kernel.org>

On Mon, Jan 05, 2026 at 03:49:21PM +0000, Will Deacon wrote:
> To enable reclaim of pages from a protected VM during teardown,
> introduce a new hypercall to reclaim a single page from a protected
> guest that is in the dying state.
> 
> Since the EL2 code is non-preemptible, the new hypercall deliberately
> acts on a single page at a time so as to allow EL1 to reschedule
> frequently during the teardown operation.
> 
> Co-developed-by: Quentin Perret <qperret@google.com>
> Signed-off-by: Quentin Perret <qperret@google.com>
> Signed-off-by: Will Deacon <will@kernel.org>

Reviewed-by: Vincent Donnefort <vdonnefort@google.com>

> ---
>  arch/arm64/include/asm/kvm_asm.h              |  1 +
>  arch/arm64/kvm/hyp/include/nvhe/mem_protect.h |  1 +
>  arch/arm64/kvm/hyp/include/nvhe/pkvm.h        |  1 +
>  arch/arm64/kvm/hyp/nvhe/hyp-main.c            |  9 +++
>  arch/arm64/kvm/hyp/nvhe/mem_protect.c         | 79 +++++++++++++++++++
>  arch/arm64/kvm/hyp/nvhe/pkvm.c                | 14 ++++
>  6 files changed, 105 insertions(+)
> 
> diff --git a/arch/arm64/include/asm/kvm_asm.h b/arch/arm64/include/asm/kvm_asm.h
> index cad3ba5e1c5a..f14f845aeedd 100644
> --- a/arch/arm64/include/asm/kvm_asm.h
> +++ b/arch/arm64/include/asm/kvm_asm.h
> @@ -86,6 +86,7 @@ enum __kvm_host_smccc_func {
>  	__KVM_HOST_SMCCC_FUNC___pkvm_unreserve_vm,
>  	__KVM_HOST_SMCCC_FUNC___pkvm_init_vm,
>  	__KVM_HOST_SMCCC_FUNC___pkvm_init_vcpu,
> +	__KVM_HOST_SMCCC_FUNC___pkvm_reclaim_dying_guest_page,
>  	__KVM_HOST_SMCCC_FUNC___pkvm_start_teardown_vm,
>  	__KVM_HOST_SMCCC_FUNC___pkvm_finalize_teardown_vm,
>  	__KVM_HOST_SMCCC_FUNC___pkvm_vcpu_load,
> diff --git a/arch/arm64/kvm/hyp/include/nvhe/mem_protect.h b/arch/arm64/kvm/hyp/include/nvhe/mem_protect.h
> index 9c0cc53d1dc9..cde38a556049 100644
> --- a/arch/arm64/kvm/hyp/include/nvhe/mem_protect.h
> +++ b/arch/arm64/kvm/hyp/include/nvhe/mem_protect.h
> @@ -41,6 +41,7 @@ int __pkvm_hyp_donate_host(u64 pfn, u64 nr_pages);
>  int __pkvm_host_share_ffa(u64 pfn, u64 nr_pages);
>  int __pkvm_host_unshare_ffa(u64 pfn, u64 nr_pages);
>  int __pkvm_host_donate_guest(u64 pfn, u64 gfn, struct pkvm_hyp_vcpu *vcpu);
> +int __pkvm_host_reclaim_page_guest(u64 gfn, struct pkvm_hyp_vm *vm);
>  int __pkvm_host_share_guest(u64 pfn, u64 gfn, u64 nr_pages, struct pkvm_hyp_vcpu *vcpu,
>  			    enum kvm_pgtable_prot prot);
>  int __pkvm_host_unshare_guest(u64 gfn, u64 nr_pages, struct pkvm_hyp_vm *hyp_vm);
> diff --git a/arch/arm64/kvm/hyp/include/nvhe/pkvm.h b/arch/arm64/kvm/hyp/include/nvhe/pkvm.h
> index 04c7ca703014..506831804f64 100644
> --- a/arch/arm64/kvm/hyp/include/nvhe/pkvm.h
> +++ b/arch/arm64/kvm/hyp/include/nvhe/pkvm.h
> @@ -74,6 +74,7 @@ int __pkvm_init_vm(struct kvm *host_kvm, unsigned long vm_hva,
>  int __pkvm_init_vcpu(pkvm_handle_t handle, struct kvm_vcpu *host_vcpu,
>  		     unsigned long vcpu_hva);
>  
> +int __pkvm_reclaim_dying_guest_page(pkvm_handle_t handle, u64 gfn);
>  int __pkvm_start_teardown_vm(pkvm_handle_t handle);
>  int __pkvm_finalize_teardown_vm(pkvm_handle_t handle);
>  
> diff --git a/arch/arm64/kvm/hyp/nvhe/hyp-main.c b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
> index a5ee1103ce1f..b1940e639ad3 100644
> --- a/arch/arm64/kvm/hyp/nvhe/hyp-main.c
> +++ b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
> @@ -570,6 +570,14 @@ static void handle___pkvm_init_vcpu(struct kvm_cpu_context *host_ctxt)
>  	cpu_reg(host_ctxt, 1) = __pkvm_init_vcpu(handle, host_vcpu, vcpu_hva);
>  }
>  
> +static void handle___pkvm_reclaim_dying_guest_page(struct kvm_cpu_context *host_ctxt)
> +{
> +	DECLARE_REG(pkvm_handle_t, handle, host_ctxt, 1);
> +	DECLARE_REG(u64, gfn, host_ctxt, 2);
> +
> +	cpu_reg(host_ctxt, 1) = __pkvm_reclaim_dying_guest_page(handle, gfn);
> +}
> +
>  static void handle___pkvm_start_teardown_vm(struct kvm_cpu_context *host_ctxt)
>  {
>  	DECLARE_REG(pkvm_handle_t, handle, host_ctxt, 1);
> @@ -622,6 +630,7 @@ static const hcall_t host_hcall[] = {
>  	HANDLE_FUNC(__pkvm_unreserve_vm),
>  	HANDLE_FUNC(__pkvm_init_vm),
>  	HANDLE_FUNC(__pkvm_init_vcpu),
> +	HANDLE_FUNC(__pkvm_reclaim_dying_guest_page),
>  	HANDLE_FUNC(__pkvm_start_teardown_vm),
>  	HANDLE_FUNC(__pkvm_finalize_teardown_vm),
>  	HANDLE_FUNC(__pkvm_vcpu_load),
> diff --git a/arch/arm64/kvm/hyp/nvhe/mem_protect.c b/arch/arm64/kvm/hyp/nvhe/mem_protect.c
> index ae126ab9febf..edbfe0e3dc58 100644
> --- a/arch/arm64/kvm/hyp/nvhe/mem_protect.c
> +++ b/arch/arm64/kvm/hyp/nvhe/mem_protect.c
> @@ -725,6 +725,32 @@ static int __guest_check_page_state_range(struct pkvm_hyp_vm *vm, u64 addr,
>  	return check_page_state_range(&vm->pgt, addr, size, &d);
>  }
>  
> +static int get_valid_guest_pte(struct pkvm_hyp_vm *vm, u64 ipa, kvm_pte_t *ptep, u64 *physp)
> +{
> +	kvm_pte_t pte;
> +	u64 phys;
> +	s8 level;
> +	int ret;
> +
> +	ret = kvm_pgtable_get_leaf(&vm->pgt, ipa, &pte, &level);
> +	if (ret)
> +		return ret;
> +	if (!kvm_pte_valid(pte))
> +		return -ENOENT;
> +	if (level != KVM_PGTABLE_LAST_LEVEL)
> +		return -E2BIG;
> +
> +	phys = kvm_pte_to_phys(pte);
> +	ret = check_range_allowed_memory(phys, phys + PAGE_SIZE);
> +	if (WARN_ON(ret))
> +		return ret;
> +
> +	*ptep = pte;
> +	*physp = phys;
> +
> +	return 0;
> +}
> +
>  int __pkvm_host_share_hyp(u64 pfn)
>  {
>  	u64 phys = hyp_pfn_to_phys(pfn);
> @@ -958,6 +984,59 @@ static int __guest_check_transition_size(u64 phys, u64 ipa, u64 nr_pages, u64 *s
>  	return 0;
>  }
>  
> +static void hyp_poison_page(phys_addr_t phys)
> +{
> +	void *addr = hyp_fixmap_map(phys);
> +
> +	memset(addr, 0, PAGE_SIZE);
> +	/*
> +	 * Prefer kvm_flush_dcache_to_poc() over __clean_dcache_guest_page()
> +	 * here as the latter may elide the CMO under the assumption that FWB
> +	 * will be enabled on CPUs that support it. This is incorrect for the
> +	 * host stage-2 and would otherwise lead to a malicious host potentially
> +	 * being able to read the contents of newly reclaimed guest pages.
> +	 */
> +	kvm_flush_dcache_to_poc(addr, PAGE_SIZE);
> +	hyp_fixmap_unmap();
> +}
> +
> +int __pkvm_host_reclaim_page_guest(u64 gfn, struct pkvm_hyp_vm *vm)
> +{
> +	u64 ipa = hyp_pfn_to_phys(gfn);
> +	kvm_pte_t pte;
> +	u64 phys;
> +	int ret;
> +
> +	host_lock_component();
> +	guest_lock_component(vm);
> +
> +	ret = get_valid_guest_pte(vm, ipa, &pte, &phys);
> +	if (ret)
> +		goto unlock;
> +
> +	switch (guest_get_page_state(pte, ipa)) {
> +	case PKVM_PAGE_OWNED:
> +		WARN_ON(__host_check_page_state_range(phys, PAGE_SIZE, PKVM_NOPAGE));
> +		hyp_poison_page(phys);
> +		break;
> +	case PKVM_PAGE_SHARED_OWNED:
> +		WARN_ON(__host_check_page_state_range(phys, PAGE_SIZE, PKVM_PAGE_SHARED_BORROWED));
> +		break;
> +	default:
> +		ret = -EPERM;
> +		goto unlock;
> +	}
> +
> +	WARN_ON(kvm_pgtable_stage2_unmap(&vm->pgt, ipa, PAGE_SIZE));
> +	WARN_ON(host_stage2_set_owner_locked(phys, PAGE_SIZE, PKVM_ID_HOST));
> +
> +unlock:
> +	guest_unlock_component(vm);
> +	host_unlock_component();
> +
> +	return ret;
> +}
> +
>  int __pkvm_host_donate_guest(u64 pfn, u64 gfn, struct pkvm_hyp_vcpu *vcpu)
>  {
>  	struct pkvm_hyp_vm *vm = pkvm_hyp_vcpu_to_hyp_vm(vcpu);
> diff --git a/arch/arm64/kvm/hyp/nvhe/pkvm.c b/arch/arm64/kvm/hyp/nvhe/pkvm.c
> index 7f8191f96fc3..9f0997150cf5 100644
> --- a/arch/arm64/kvm/hyp/nvhe/pkvm.c
> +++ b/arch/arm64/kvm/hyp/nvhe/pkvm.c
> @@ -832,6 +832,20 @@ teardown_donated_memory(struct kvm_hyp_memcache *mc, void *addr, size_t size)
>  	unmap_donated_memory_noclear(addr, size);
>  }
>  
> +int __pkvm_reclaim_dying_guest_page(pkvm_handle_t handle, u64 gfn)
> +{
> +	struct pkvm_hyp_vm *hyp_vm;
> +	int ret = -EINVAL;
> +
> +	hyp_spin_lock(&vm_table_lock);
> +	hyp_vm = get_vm_by_handle(handle);
> +	if (hyp_vm && hyp_vm->kvm.arch.pkvm.is_dying)
> +		ret = __pkvm_host_reclaim_page_guest(gfn, hyp_vm);
> +	hyp_spin_unlock(&vm_table_lock);
> +
> +	return ret;
> +}
> +
>  int __pkvm_start_teardown_vm(pkvm_handle_t handle)
>  {
>  	struct pkvm_hyp_vm *hyp_vm;
> -- 
> 2.52.0.351.gbe84eed79e-goog
> 

  reply	other threads:[~2026-01-06 16:26 UTC|newest]

Thread overview: 68+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-01-05 15:49 [PATCH 00/30] KVM: arm64: Add support for protected guest memory with pKVM Will Deacon
2026-01-05 15:49 ` [PATCH 01/30] KVM: arm64: Invert KVM_PGTABLE_WALK_HANDLE_FAULT to fix pKVM walkers Will Deacon
2026-01-06 14:33   ` Quentin Perret
2026-01-10 10:22   ` (subset) " Oliver Upton
2026-01-05 15:49 ` [PATCH 02/30] KVM: arm64: Remove redundant 'pgt' pointer checks from MMU notifiers Will Deacon
2026-01-06 14:32   ` Quentin Perret
2026-01-09 14:31     ` Will Deacon
2026-01-09 17:31       ` Will Deacon
2026-01-05 15:49 ` [PATCH 03/30] KVM: arm64: Rename __pkvm_pgtable_stage2_unmap() Will Deacon
2026-01-05 15:49 ` [PATCH 04/30] KVM: arm64: Don't advertise unsupported features for protected guests Will Deacon
2026-01-05 15:49 ` [PATCH 05/30] KVM: arm64: Expose self-hosted debug regs as RAZ/WI " Will Deacon
2026-01-05 15:49 ` [PATCH 06/30] KVM: arm64: Remove pointless is_protected_kvm_enabled() checks from hyp Will Deacon
2026-01-06 14:40   ` Quentin Perret
2026-01-09 14:23     ` Will Deacon
2026-01-05 15:49 ` [PATCH 07/30] KVM: arm64: Ignore MMU notifier callbacks for protected VMs Will Deacon
2026-01-05 15:49 ` [PATCH 08/30] KVM: arm64: Prevent unsupported memslot operations on " Will Deacon
2026-01-05 15:49 ` [PATCH 09/30] KVM: arm64: Split teardown hypercall into two phases Will Deacon
2026-01-05 15:49 ` [PATCH 10/30] KVM: arm64: Introduce __pkvm_host_donate_guest() Will Deacon
2026-01-06 14:48   ` Quentin Perret
2026-01-09 14:30     ` Will Deacon
2026-01-09 15:10       ` Quentin Perret
2026-01-05 15:49 ` [PATCH 11/30] KVM: arm64: Hook up donation hypercall to pkvm_pgtable_stage2_map() Will Deacon
2026-01-05 15:49 ` [PATCH 12/30] KVM: arm64: Handle aborts from protected VMs Will Deacon
2026-01-05 15:49 ` [PATCH 13/30] KVM: arm64: Introduce __pkvm_reclaim_dying_guest_page() Will Deacon
2026-01-06 16:26   ` Vincent Donnefort [this message]
2026-01-05 15:49 ` [PATCH 14/30] KVM: arm64: Hook up reclaim hypercall to pkvm_pgtable_stage2_destroy() Will Deacon
2026-01-06 14:59   ` Quentin Perret
2026-01-09 14:35     ` Will Deacon
2026-01-09 14:57       ` Quentin Perret
2026-01-05 15:49 ` [PATCH 15/30] KVM: arm64: Refactor enter_exception64() Will Deacon
2026-01-05 15:49 ` [PATCH 16/30] KVM: arm64: Inject SIGSEGV on illegal accesses Will Deacon
2026-01-05 15:49 ` [PATCH 17/30] KVM: arm64: Generalise kvm_pgtable_stage2_set_owner() Will Deacon
2026-01-06 15:20   ` Quentin Perret
2026-01-09 18:46     ` Will Deacon
2026-01-17  0:03       ` Will Deacon
2026-01-05 15:49 ` [PATCH 18/30] KVM: arm64: Introduce host_stage2_set_owner_metadata_locked() Will Deacon
2026-01-05 15:49 ` [PATCH 19/30] KVM: arm64: Annotate guest donations with handle and gfn in host stage-2 Will Deacon
2026-01-06 16:01   ` Fuad Tabba
2026-01-09 14:42     ` Will Deacon
2026-01-12  9:25       ` Fuad Tabba
2026-01-05 15:49 ` [PATCH 20/30] KVM: arm64: Introduce hypercall to force reclaim of a protected page Will Deacon
2026-01-06 15:44   ` Quentin Perret
2026-01-09 17:47     ` Will Deacon
2026-01-05 15:49 ` [PATCH 21/30] KVM: arm64: Reclaim faulting page from pKVM in spurious fault handler Will Deacon
2026-01-05 15:49 ` [PATCH 22/30] KVM: arm64: Return -EFAULT from VCPU_RUN on access to a poisoned pte Will Deacon
2026-01-06 15:54   ` Quentin Perret
2026-01-09 14:57     ` Will Deacon
2026-01-09 15:29       ` Quentin Perret
2026-01-09 17:35         ` Will Deacon
2026-01-05 15:49 ` [PATCH 23/30] KVM: arm64: Add hvc handler at EL2 for hypercalls from protected VMs Will Deacon
2026-01-06 15:52   ` Vincent Donnefort
2026-01-05 15:49 ` [PATCH 24/30] KVM: arm64: Implement the MEM_SHARE hypercall for " Will Deacon
2026-01-06 15:45   ` Vincent Donnefort
2026-01-09 15:01     ` Will Deacon
2026-01-05 15:49 ` [PATCH 25/30] KVM: arm64: Implement the MEM_UNSHARE " Will Deacon
2026-01-06 15:50   ` Vincent Donnefort
2026-01-05 15:49 ` [PATCH 26/30] KVM: arm64: Allow userspace to create protected VMs when pKVM is enabled Will Deacon
2026-01-05 15:49 ` [PATCH 27/30] KVM: arm64: Add some initial documentation for pKVM Will Deacon
2026-01-06 15:59   ` Vincent Donnefort
2026-01-09 15:04     ` Will Deacon
2026-01-05 15:49 ` [PATCH 28/30] KVM: arm64: Extend pKVM page ownership selftests to cover guest donation Will Deacon
2026-01-05 15:49 ` [PATCH 29/30] KVM: arm64: Register 'selftest_vm' in the VM table Will Deacon
2026-01-05 15:49 ` [PATCH 30/30] KVM: arm64: Extend pKVM page ownership selftests to cover forced reclaim Will Deacon
2026-03-13 15:31 ` [PATCH 00/30] KVM: arm64: Add support for protected guest memory with pKVM Mostafa Saleh
2026-04-20  8:02 ` Pavan Kondeti
2026-04-20 10:00   ` Will Deacon
2026-04-20 11:26     ` Pavan Kondeti
2026-04-21  4:15       ` Pavan Kondeti

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=aV03xOYPTdurX2k4@google.com \
    --to=vdonnefort@google.com \
    --cc=catalin.marinas@arm.com \
    --cc=joey.gouly@arm.com \
    --cc=kvmarm@lists.linux.dev \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=maz@kernel.org \
    --cc=oupton@kernel.org \
    --cc=qperret@google.com \
    --cc=smostafa@google.com \
    --cc=suzuki.poulose@arm.com \
    --cc=tabba@google.com \
    --cc=will@kernel.org \
    --cc=yuzenghui@huawei.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.