[PATCH v2 13/18] KVM: arm64: Move hyp_vm refcount into the structure

Fuad Tabba fuad.tabba at linux.dev
Wed Jul 15 04:35:00 PDT 2026


On Mon, 6 Jul 2026 at 18:54, Vincent Donnefort <vdonnefort at google.com> wrote:
>
> In preparation for allocating hyp_vm using the pKVM heap allocator
> (hyp_alloc()), move its reference count out of the page metadata
> (vmemmap) and place it into the structure itself. This transition is
> necessary because hyp_alloc() allows multiple small objects to share the
> same physical page.
>
> Signed-off-by: Vincent Donnefort <vdonnefort at google.com>

Reviewed-by: Fuad Tabba <fuad.tabba at linux.dev>

Cheers,
/fuad


>
> diff --git a/arch/arm64/kvm/hyp/include/nvhe/pkvm.h b/arch/arm64/kvm/hyp/include/nvhe/pkvm.h
> index c904647d2f76..624367d0ef5b 100644
> --- a/arch/arm64/kvm/hyp/include/nvhe/pkvm.h
> +++ b/arch/arm64/kvm/hyp/include/nvhe/pkvm.h
> @@ -41,6 +41,7 @@ struct pkvm_hyp_vm {
>         struct kvm_pgtable pgt;
>         struct kvm_pgtable_mm_ops mm_ops;
>         struct hyp_pool pool;
> +       unsigned short refcount;
>         hyp_spinlock_t lock;
>
>         /* Array of the hyp vCPU structures for this VM. */
> @@ -65,6 +66,18 @@ static inline bool pkvm_hyp_vm_is_protected(struct pkvm_hyp_vm *hyp_vm)
>         return kvm_vm_is_protected(&hyp_vm->kvm);
>  }
>
> +static inline void pkvm_hyp_vm_ref_inc(struct pkvm_hyp_vm *hyp_vm)
> +{
> +       BUG_ON(hyp_vm->refcount == USHRT_MAX);
> +       hyp_vm->refcount++;
> +}
> +
> +static inline void pkvm_hyp_vm_ref_dec(struct pkvm_hyp_vm *hyp_vm)
> +{
> +       BUG_ON(!hyp_vm->refcount);
> +       hyp_vm->refcount--;
> +}
> +
>  void pkvm_hyp_vm_table_init(void *tbl);
>
>  int __pkvm_reserve_vm(void);
> diff --git a/arch/arm64/kvm/hyp/nvhe/pkvm.c b/arch/arm64/kvm/hyp/nvhe/pkvm.c
> index 3b2c4fbc34d8..d9ab58226889 100644
> --- a/arch/arm64/kvm/hyp/nvhe/pkvm.c
> +++ b/arch/arm64/kvm/hyp/nvhe/pkvm.c
> @@ -278,7 +278,7 @@ struct pkvm_hyp_vcpu *pkvm_load_hyp_vcpu(pkvm_handle_t handle,
>         }
>
>         hyp_vcpu->loaded_hyp_vcpu = this_cpu_ptr(&loaded_hyp_vcpu);
> -       hyp_page_ref_inc(hyp_virt_to_page(hyp_vm));
> +       pkvm_hyp_vm_ref_inc(hyp_vm);
>  unlock:
>         hyp_spin_unlock(&vm_table_lock);
>
> @@ -294,7 +294,7 @@ void pkvm_put_hyp_vcpu(struct pkvm_hyp_vcpu *hyp_vcpu)
>         hyp_spin_lock(&vm_table_lock);
>         hyp_vcpu->loaded_hyp_vcpu = NULL;
>         __this_cpu_write(loaded_hyp_vcpu, NULL);
> -       hyp_page_ref_dec(hyp_virt_to_page(hyp_vm));
> +       pkvm_hyp_vm_ref_dec(hyp_vm);
>         hyp_spin_unlock(&vm_table_lock);
>  }
>
> @@ -311,7 +311,7 @@ struct pkvm_hyp_vm *get_pkvm_hyp_vm(pkvm_handle_t handle)
>         hyp_spin_lock(&vm_table_lock);
>         hyp_vm = get_vm_by_handle(handle);
>         if (hyp_vm)
> -               hyp_page_ref_inc(hyp_virt_to_page(hyp_vm));
> +               pkvm_hyp_vm_ref_inc(hyp_vm);
>         hyp_spin_unlock(&vm_table_lock);
>
>         return hyp_vm;
> @@ -320,7 +320,7 @@ struct pkvm_hyp_vm *get_pkvm_hyp_vm(pkvm_handle_t handle)
>  void put_pkvm_hyp_vm(struct pkvm_hyp_vm *hyp_vm)
>  {
>         hyp_spin_lock(&vm_table_lock);
> -       hyp_page_ref_dec(hyp_virt_to_page(hyp_vm));
> +       pkvm_hyp_vm_ref_dec(hyp_vm);
>         hyp_spin_unlock(&vm_table_lock);
>  }
>
> @@ -966,7 +966,7 @@ static struct pkvm_hyp_vm *get_pkvm_unref_hyp_vm_locked(pkvm_handle_t handle)
>         hyp_assert_lock_held(&vm_table_lock);
>
>         hyp_vm = get_vm_by_handle(handle);
> -       if (!hyp_vm || hyp_page_count(hyp_vm))
> +       if (!hyp_vm || hyp_vm->refcount)
>                 return NULL;
>
>         return hyp_vm;
> --
> 2.55.0.rc2.803.g1fd1e6609c-goog
>



More information about the linux-arm-kernel mailing list