Re: [PATCH 19/30] KVM: arm64: Annotate guest donations with handle and gfn in host stage-2

Fuad Tabba
2026-01-06T16:02:06Z

Hi Will,

On Mon, 5 Jan 2026 at 15:50, Will Deacon <will@kernel.org> wrote:
>
> Handling host kernel faults arising from accesses to donated guest
> memory will require an rmap-like mechanism to identify the guest mapping
> of the faulting page.
>
> Extend the page donation logic to encode the guest handle and gfn
> alongside the owner information in the host stage-2 pte.
>
> Signed-off-by: Will Deacon <will@kernel.org>
> ---
> arch/arm64/kvm/hyp/nvhe/mem_protect.c | 18 +++++++++++++++++-
> 1 file changed, 17 insertions(+), 1 deletion(-)
>
> diff --git a/arch/arm64/kvm/hyp/nvhe/mem_protect.c b/arch/arm64/kvm/hyp/nvhe/mem_protect.c
> index 7d1844e2888d..1a341337b272 100644
> --- a/arch/arm64/kvm/hyp/nvhe/mem_protect.c
> +++ b/arch/arm64/kvm/hyp/nvhe/mem_protect.c
> @@ -1063,6 +1063,19 @@ static void hyp_poison_page(phys_addr_t phys)
> hyp_fixmap_unmap();
> }
>
> +#define KVM_HOST_INVALID_PTE_GUEST_HANDLE_MASK GENMASK(15, 0)
> +#define KVM_HOST_INVALID_PTE_GUEST_GFN_MASK GENMASK(56, 16)
> +static u64 host_stage2_encode_gfn_meta(struct pkvm_hyp_vm *vm, u64 gfn)
> +{
> + pkvm_handle_t handle = vm->kvm.arch.pkvm.handle;
> +
> + WARN_ON(!FIELD_FIT(KVM_HOST_INVALID_PTE_GUEST_HANDLE_MASK, handle));

Instead of (or in addition to) this check, should we also have a
compile time check to ensure that the handle fits? We have
KVM_MAX_PVMS and HANDLE_OFFSET, albeit HANDLE_OFFSET, so we can
calculate whether it fits.

Cheers,
/fuad

> + WARN_ON(!FIELD_FIT(KVM_HOST_INVALID_PTE_GUEST_GFN_MASK, gfn));
> +
> + return FIELD_PREP(KVM_HOST_INVALID_PTE_GUEST_HANDLE_MASK, handle) |
> + FIELD_PREP(KVM_HOST_INVALID_PTE_GUEST_GFN_MASK, gfn);
> +}
> +
> int __pkvm_host_reclaim_page_guest(u64 gfn, struct pkvm_hyp_vm *vm)
> {
> u64 ipa = hyp_pfn_to_phys(gfn);
> @@ -1105,6 +1118,7 @@ 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);
> + u64 meta;
> int ret;
>
> host_lock_component();
> @@ -1118,7 +1132,9 @@ int __pkvm_host_donate_guest(u64 pfn, u64 gfn, struct pkvm_hyp_vcpu *vcpu)
> if (ret)
> goto unlock;
>
> - WARN_ON(host_stage2_set_owner_locked(phys, PAGE_SIZE, PKVM_ID_GUEST));
> + meta = host_stage2_encode_gfn_meta(vm, gfn);
> + WARN_ON(host_stage2_set_owner_metadata_locked(phys, PAGE_SIZE,
> + PKVM_ID_GUEST, meta));
> 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));
> --
> 2.52.0.351.gbe84eed79e-goog
>