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

Quentin Perret qperret at google.com
Tue Jan 6 06:48:00 PST 2026


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
> 



More information about the linux-arm-kernel mailing list