[PATCH v2 16/18] KVM: arm64: Alloc pkvm_hyp_vcpu using pKVM heap allocator
Fuad Tabba
fuad.tabba at linux.dev
Wed Jul 15 06:12:37 PDT 2026
On Mon, 6 Jul 2026 at 18:54, Vincent Donnefort <vdonnefort at google.com> wrote:
...
> -int __pkvm_init_vcpu(pkvm_handle_t handle, struct kvm_vcpu *host_vcpu,
> - unsigned long vcpu_hva)
> +int __pkvm_init_vcpu(pkvm_handle_t handle, struct kvm_vcpu *host_vcpu)
> {
> struct pkvm_hyp_vcpu *hyp_vcpu;
> struct pkvm_hyp_vm *hyp_vm;
> int ret;
>
> - hyp_vcpu = map_donated_memory(vcpu_hva, sizeof(*hyp_vcpu));
> + hyp_vcpu = hyp_alloc(sizeof(*hyp_vcpu));
On Sashiko's alignment point: hyp_alloc only guarantees 8-byte
alignment while pkvm_hyp_vcpu wants 16 (the __uint128_t vregs[32]),
and the old map_donated_memory path was page-aligned, so it's a real
reduction.
But if my understanding of the ARM ARM is correct, and please note
that I just consulted the spec when replying to this, so it's a big
*if*: I don't think it faults. We run EL2 with SCTLR_EL2.A == 0
(INIT_SCTLR_EL2_MMU_ON has SA but not A), and FPSIMD save/restore is
plain LDR/STR/LDP/STP of Q registers. From the ARM ARM (DDI 0487M.c,
B2.8.2.1.1):
"When the value of SCTLR_ELx.A applicable to the current Exception
level is 0: An unaligned access is performed."
and, covering LDP/STP:
"For these instructions, the definition of an unaligned access is
based on the size of the accessed elements, not the overall size of
the memory access. This affects SIMD and SVE element and structure
loads and stores, and also load/store pair instructions."
However, the alignment here is still weaker than the
kmalloc/alloc_pages callers relied on , so it might be cleaner to give
hyp_alloc a 16-byte minimum alignment at the allocator level rather
than per-caller. What do you think?
Cheers,
/fuad
> if (!hyp_vcpu)
> - return -ENOMEM;
> + return hyp_alloc_errno();
>
> hyp_spin_lock(&vm_table_lock);
>
> @@ -926,24 +892,12 @@ int __pkvm_init_vcpu(pkvm_handle_t handle, struct kvm_vcpu *host_vcpu,
> }
> unlock:
> hyp_spin_unlock(&vm_table_lock);
> -
> if (ret)
> - unmap_donated_memory(hyp_vcpu, sizeof(*hyp_vcpu));
> + hyp_free(hyp_vcpu);
> +
> return ret;
> }
>
> -static void
> -teardown_donated_memory(struct kvm_hyp_memcache *mc, void *addr, size_t size)
> -{
> - size = PAGE_ALIGN(size);
> - memset(addr, 0, size);
> -
> - for (void *start = addr; start < addr + size; start += PAGE_SIZE)
> - push_hyp_memcache(mc, start, hyp_virt_to_phys);
> -
> - unmap_donated_memory_noclear(addr, size);
> -}
> -
> int __pkvm_reclaim_dying_guest_page(pkvm_handle_t handle, u64 gfn)
> {
> struct pkvm_hyp_vm *hyp_vm = get_pkvm_hyp_vm(handle);
> @@ -993,7 +947,7 @@ int __pkvm_start_teardown_vm(pkvm_handle_t handle)
>
> int __pkvm_finalize_teardown_vm(pkvm_handle_t handle)
> {
> - struct kvm_hyp_memcache *mc, *stage2_mc;
> + struct kvm_hyp_memcache *stage2_mc;
> struct pkvm_hyp_vm *hyp_vm;
> struct kvm *host_kvm;
> unsigned int idx;
> @@ -1014,7 +968,6 @@ int __pkvm_finalize_teardown_vm(pkvm_handle_t handle)
> hyp_spin_unlock(&vm_table_lock);
>
> /* Reclaim guest pages (including page-table pages) */
> - mc = &host_kvm->arch.pkvm.teardown_mc;
> stage2_mc = &host_kvm->arch.pkvm.stage2_teardown_mc;
> reclaim_pgtable_pages(hyp_vm, stage2_mc);
> unpin_host_vcpus(hyp_vm->vcpus, hyp_vm->kvm.created_vcpus);
> @@ -1036,7 +989,7 @@ int __pkvm_finalize_teardown_vm(pkvm_handle_t handle)
> unmap_donated_memory_noclear(addr, PAGE_SIZE);
> }
>
> - teardown_donated_memory(mc, hyp_vcpu, sizeof(*hyp_vcpu));
> + hyp_free(hyp_vcpu);
> }
>
> hyp_free(hyp_vm);
> diff --git a/arch/arm64/kvm/pkvm.c b/arch/arm64/kvm/pkvm.c
> index 8a8b5b84825c..1899b05d9fc2 100644
> --- a/arch/arm64/kvm/pkvm.c
> +++ b/arch/arm64/kvm/pkvm.c
> @@ -153,28 +153,19 @@ static void __pkvm_destroy_hyp_vm(struct kvm *kvm)
>
> kvm->arch.pkvm.handle = 0;
> kvm->arch.pkvm.is_created = false;
> - free_hyp_memcache(&kvm->arch.pkvm.teardown_mc);
> free_hyp_memcache(&kvm->arch.pkvm.stage2_teardown_mc);
> }
>
> static int __pkvm_create_hyp_vcpu(struct kvm_vcpu *vcpu)
> {
> - size_t hyp_vcpu_sz = PAGE_ALIGN(PKVM_HYP_VCPU_SIZE);
> pkvm_handle_t handle = vcpu->kvm->arch.pkvm.handle;
> - void *hyp_vcpu;
> int ret;
>
> init_hyp_stage2_memcache(&vcpu->arch.pkvm_memcache);
>
> - hyp_vcpu = alloc_pages_exact(hyp_vcpu_sz, GFP_KERNEL_ACCOUNT);
> - if (!hyp_vcpu)
> - return -ENOMEM;
> -
> - ret = kvm_call_hyp_nvhe(__pkvm_init_vcpu, handle, vcpu, hyp_vcpu);
> + ret = pkvm_call_hyp_req(__pkvm_init_vcpu, handle, vcpu);
> if (!ret)
> vcpu_set_flag(vcpu, VCPU_PKVM_FINALIZED);
> - else
> - free_pages_exact(hyp_vcpu, hyp_vcpu_sz);
>
> return ret;
> }
> --
> 2.55.0.rc2.803.g1fd1e6609c-goog
>
More information about the linux-arm-kernel
mailing list