Re: [PATCH 10/30] KVM: arm64: Introduce __pkvm_host_donate_guest()

Quentin Perret
2026-01-06T14:48:05Z

On Monday 05 Jan 2026 at 15:49:18 (+0000), Will Deacon wrote:
> +static void handle___pkvm_host_donate_guest(struct kvm_cpu_context *host_ctxt)
> +{
> + DECLARE_REG(u64, pfn, host_ctxt, 1);
> + DECLARE_REG(u64, gfn, host_ctxt, 2);
> + struct pkvm_hyp_vcpu *hyp_vcpu;
> + int ret = -EINVAL;
> +
> + hyp_vcpu = pkvm_get_loaded_hyp_vcpu();
> + if (!hyp_vcpu)

I guess we should check this is a protected VM here, else a malicious
host could donate pages to an np-guest. I didn't try to think through
the implications, perhaps it's fine, but it feels unecessary so I'd say
let's be restrictive here.

Cheers,
Quentin

> + goto out;
> +
> + ret = pkvm_refill_memcache(hyp_vcpu);
> + if (ret)
> + goto out;
> +
> + ret = __pkvm_host_donate_guest(pfn, gfn, hyp_vcpu);
> +out:
> + cpu_reg(host_ctxt, 1) = ret;
> +}
> +
> static void handle___pkvm_host_share_guest(struct kvm_cpu_context *host_ctxt)
> {
> DECLARE_REG(u64, pfn, host_ctxt, 1);
> @@ -580,6 +600,7 @@ static const hcall_t host_hcall[] = {
>
> HANDLE_FUNC(__pkvm_host_share_hyp),
> HANDLE_FUNC(__pkvm_host_unshare_hyp),
> + HANDLE_FUNC(__pkvm_host_donate_guest),
> HANDLE_FUNC(__pkvm_host_share_guest),
> HANDLE_FUNC(__pkvm_host_unshare_guest),
> HANDLE_FUNC(__pkvm_host_relax_perms_guest),
> diff --git a/arch/arm64/kvm/hyp/nvhe/mem_protect.c b/arch/arm64/kvm/hyp/nvhe/mem_protect.c
> index 49db32f3ddf7..ae126ab9febf 100644
> --- a/arch/arm64/kvm/hyp/nvhe/mem_protect.c
> +++ b/arch/arm64/kvm/hyp/nvhe/mem_protect.c
> @@ -958,6 +958,36 @@ static int __guest_check_transition_size(u64 phys, u64 ipa, u64 nr_pages, u64 *s
> return 0;
> }
>
> +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);
> + u64 phys = hyp_pfn_to_phys(pfn);
> + u64 ipa = hyp_pfn_to_phys(gfn);
> + int ret;
> +
> + host_lock_component();
> + guest_lock_component(vm);
> +
> + ret = __host_check_page_state_range(phys, PAGE_SIZE, PKVM_PAGE_OWNED);
> + if (ret)
> + goto unlock;
> +
> + ret = __guest_check_page_state_range(vm, ipa, PAGE_SIZE, PKVM_NOPAGE);
> + if (ret)
> + goto unlock;
> +
> + WARN_ON(host_stage2_set_owner_locked(phys, PAGE_SIZE, PKVM_ID_GUEST));
> + WARN_ON(kvm_pgtable_stage2_map(&vm->pgt, ipa, PAGE_SIZE, phys,
> + pkvm_mkstate(KVM_PGTABLE_PROT_RWX, PKVM_PAGE_OWNED),
> + &vcpu->vcpu.arch.pkvm_memcache, 0));
> +
> +unlock:
> + guest_unlock_component(vm);
> + host_unlock_component();
> +
> + return ret;
> +}
> +
> int __pkvm_host_share_guest(u64 pfn, u64 gfn, u64 nr_pages, struct pkvm_hyp_vcpu *vcpu,
> enum kvm_pgtable_prot prot)
> {
> --
> 2.52.0.351.gbe84eed79e-goog
>