[PATCH 23/30] KVM: arm64: Add hvc handler at EL2 for hypercalls from protected VMs

Vincent Donnefort vdonnefort at google.com
Tue Jan 6 07:52:48 PST 2026


On Mon, Jan 05, 2026 at 03:49:31PM +0000, Will Deacon wrote:
> Add a hypercall handler at EL2 for hypercalls originating from protected
> VMs. For now, this implements only the FEATURES and MEMINFO calls, but
> subsequent patches will implement the SHARE and UNSHARE functions
> necessary for virtio.
> 
> Unhandled hypercalls (including PSCI) are passed back to the host.
> 
> Signed-off-by: Will Deacon <will at kernel.org>

Reviewed-by: Vincent Donnefort <vdonnefort at google.com>

> ---
>  arch/arm64/kvm/hyp/include/nvhe/pkvm.h |  1 +
>  arch/arm64/kvm/hyp/nvhe/pkvm.c         | 37 ++++++++++++++++++++++++++
>  arch/arm64/kvm/hyp/nvhe/switch.c       |  1 +
>  3 files changed, 39 insertions(+)
> 
> diff --git a/arch/arm64/kvm/hyp/include/nvhe/pkvm.h b/arch/arm64/kvm/hyp/include/nvhe/pkvm.h
> index a5a7bb453f3e..c904647d2f76 100644
> --- a/arch/arm64/kvm/hyp/include/nvhe/pkvm.h
> +++ b/arch/arm64/kvm/hyp/include/nvhe/pkvm.h
> @@ -88,6 +88,7 @@ struct pkvm_hyp_vm *get_pkvm_hyp_vm(pkvm_handle_t handle);
>  struct pkvm_hyp_vm *get_np_pkvm_hyp_vm(pkvm_handle_t handle);
>  void put_pkvm_hyp_vm(struct pkvm_hyp_vm *hyp_vm);
>  
> +bool kvm_handle_pvm_hvc64(struct kvm_vcpu *vcpu, u64 *exit_code);
>  bool kvm_handle_pvm_sysreg(struct kvm_vcpu *vcpu, u64 *exit_code);
>  bool kvm_handle_pvm_restricted(struct kvm_vcpu *vcpu, u64 *exit_code);
>  void kvm_init_pvm_id_regs(struct kvm_vcpu *vcpu);
> diff --git a/arch/arm64/kvm/hyp/nvhe/pkvm.c b/arch/arm64/kvm/hyp/nvhe/pkvm.c
> index df340de59eed..5cdec49e989b 100644
> --- a/arch/arm64/kvm/hyp/nvhe/pkvm.c
> +++ b/arch/arm64/kvm/hyp/nvhe/pkvm.c
> @@ -4,6 +4,8 @@
>   * Author: Fuad Tabba <tabba at google.com>
>   */
>  
> +#include <kvm/arm_hypercalls.h>
> +
>  #include <linux/kvm_host.h>
>  #include <linux/mm.h>
>  
> @@ -934,3 +936,38 @@ int __pkvm_finalize_teardown_vm(pkvm_handle_t handle)
>  	hyp_spin_unlock(&vm_table_lock);
>  	return err;
>  }
> +/*
> + * Handler for protected VM HVC calls.
> + *
> + * Returns true if the hypervisor has handled the exit (and control
> + * should return to the guest) or false if it hasn't (and the handling
> + * should be performed by the host).
> + */
> +bool kvm_handle_pvm_hvc64(struct kvm_vcpu *vcpu, u64 *exit_code)
> +{
> +	u64 val[4] = { SMCCC_RET_INVALID_PARAMETER };
> +	bool handled = true;
> +
> +	switch (smccc_get_function(vcpu)) {
> +	case ARM_SMCCC_VENDOR_HYP_KVM_FEATURES_FUNC_ID:
> +		val[0] = BIT(ARM_SMCCC_KVM_FUNC_FEATURES);
> +		val[0] |= BIT(ARM_SMCCC_KVM_FUNC_HYP_MEMINFO);
> +		break;
> +	case ARM_SMCCC_VENDOR_HYP_KVM_HYP_MEMINFO_FUNC_ID:
> +		if (smccc_get_arg1(vcpu) ||
> +		    smccc_get_arg2(vcpu) ||
> +		    smccc_get_arg3(vcpu)) {
> +			break;
> +		}
> +
> +		val[0] = PAGE_SIZE;
> +		break;
> +	default:
> +		/* Punt everything else back to the host, for now. */
> +		handled = false;
> +	}
> +
> +	if (handled)
> +		smccc_set_retval(vcpu, val[0], val[1], val[2], val[3]);
> +	return handled;
> +}
> diff --git a/arch/arm64/kvm/hyp/nvhe/switch.c b/arch/arm64/kvm/hyp/nvhe/switch.c
> index d3b9ec8a7c28..b62e25e8bb7e 100644
> --- a/arch/arm64/kvm/hyp/nvhe/switch.c
> +++ b/arch/arm64/kvm/hyp/nvhe/switch.c
> @@ -190,6 +190,7 @@ static const exit_handler_fn hyp_exit_handlers[] = {
>  
>  static const exit_handler_fn pvm_exit_handlers[] = {
>  	[0 ... ESR_ELx_EC_MAX]		= NULL,
> +	[ESR_ELx_EC_HVC64]		= kvm_handle_pvm_hvc64,
>  	[ESR_ELx_EC_SYS64]		= kvm_handle_pvm_sys64,
>  	[ESR_ELx_EC_SVE]		= kvm_handle_pvm_restricted,
>  	[ESR_ELx_EC_FP_ASIMD]		= kvm_hyp_handle_fpsimd,
> -- 
> 2.52.0.351.gbe84eed79e-goog
> 



More information about the linux-arm-kernel mailing list