Re: [PATCH 08/17] KVM: arm64: Implement HVC handling for protected guests at EL2
From: Joey Gouly
Date: Thu Sep 03 2026 - 11:23:59 EST
On Mon, Aug 31, 2026 at 05:34:12PM +0100, Fuad Tabba wrote:
> Extend kvm_handle_pvm_hvc64() to handle SMCCC_VERSION,
> SMCCC_ARCH_FEATURES and the vendor hypervisor call UID at EL2, so
> these queries do not reach the host. ARCH_FEATURES is mandatory from
> SMCCC 1.1, the version EL2 reports: it returns SUCCESS for itself and
> for SMCCC_VERSION, and NOT_SUPPORTED for anything else.
>
> Add handle_pvm_entry_hvc64() and handle_pvm_exit_hvc64(), which
> forward a protected guest's HVCs to the host and return the reply; a
> later patch wires them into the per-EC dispatch tables.
These two functions are unused in this commit, and are modified in the
next commit, while still being unused. Then handle_pvm_entry_hvc64()
becomes a wrapper for handle_pvm_entry_psci() (which was the whole body
of handle_pvm_entry_hvc64). It's quite hard to follow. If these
functions are really unused and then modified, maybe it's just better to
remove them from this commit?
Thanks,
Joey
>
> Signed-off-by: Fuad Tabba <fuad.tabba@xxxxxxxxx>
> ---
> arch/arm64/kvm/hyp/nvhe/hyp-main.c | 28 ++++++++++++++++++++++++++++
> arch/arm64/kvm/hyp/nvhe/pkvm.c | 29 +++++++++++++++++++++++++++++
> 2 files changed, 57 insertions(+)
>
> diff --git a/arch/arm64/kvm/hyp/nvhe/hyp-main.c b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
> index d4b0f69ff130c..62864db1e099a 100644
> --- a/arch/arm64/kvm/hyp/nvhe/hyp-main.c
> +++ b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
> @@ -4,6 +4,8 @@
> * Author: Andrew Scull <ascull@xxxxxxxxxx>
> */
>
> +#include <kvm/arm_hypercalls.h>
> +
> #include <hyp/adjust_pc.h>
> #include <hyp/switch.h>
>
> @@ -33,6 +35,32 @@ void __kvm_hyp_host_forward_smc(struct kvm_cpu_context *host_ctxt);
>
> typedef void (*hyp_entry_exit_handler_fn)(struct pkvm_hyp_vcpu *);
>
> +static void __maybe_unused handle_pvm_entry_hvc64(struct pkvm_hyp_vcpu *hyp_vcpu)
> +{
> + int i;
> +
> + for (i = 0; i < 4; i++) {
> + u64 ret =
> + READ_ONCE(hyp_vcpu->host_vcpu->arch.ctxt.regs.regs[i]);
> + vcpu_set_reg(&hyp_vcpu->vcpu, i, ret);
> + }
> +}
> +
> +static void __maybe_unused handle_pvm_exit_hvc64(struct pkvm_hyp_vcpu *hyp_vcpu)
> +{
> + struct kvm_vcpu *host_vcpu = hyp_vcpu->host_vcpu;
> + int i;
> +
> + WRITE_ONCE(host_vcpu->arch.fault.esr_el2,
> + hyp_vcpu->vcpu.arch.fault.esr_el2);
> +
> + /* Pass the HVC function id (r0) and its arguments. */
> + for (i = 0; i < 8; i++) {
> + WRITE_ONCE(host_vcpu->arch.ctxt.regs.regs[i],
> + vcpu_get_reg(&hyp_vcpu->vcpu, i));
> + }
> +}
> +
> static void handle_vm_entry_generic(struct pkvm_hyp_vcpu *hyp_vcpu)
> {
> vcpu_copy_flag(&hyp_vcpu->vcpu, hyp_vcpu->host_vcpu, PC_UPDATE_REQ);
> diff --git a/arch/arm64/kvm/hyp/nvhe/pkvm.c b/arch/arm64/kvm/hyp/nvhe/pkvm.c
> index af334318d0a03..0fe11f95e2e26 100644
> --- a/arch/arm64/kvm/hyp/nvhe/pkvm.c
> +++ b/arch/arm64/kvm/hyp/nvhe/pkvm.c
> @@ -1144,8 +1144,37 @@ bool kvm_handle_pvm_hvc64(struct kvm_vcpu *vcpu, u64 *exit_code)
> {
> u64 val[4] = { SMCCC_RET_INVALID_PARAMETER };
> bool handled = true;
> + u32 feature;
> + uuid_t uuid;
>
> switch (smccc_get_function(vcpu)) {
> + case ARM_SMCCC_VERSION_FUNC_ID:
> + /* Nothing to be handled by the host. Go back to the guest. */
> + val[0] = ARM_SMCCC_VERSION_1_1;
> + val[1] = 0;
> + val[2] = 0;
> + val[3] = 0;
> + break;
> + case ARM_SMCCC_ARCH_FEATURES_FUNC_ID:
> + /* SUCCESS only for the architecture calls EL2 implements. */
> + feature = smccc_get_arg1(vcpu);
> + switch (feature) {
> + case ARM_SMCCC_VERSION_FUNC_ID:
> + case ARM_SMCCC_ARCH_FEATURES_FUNC_ID:
> + val[0] = SMCCC_RET_SUCCESS;
> + break;
> + default:
> + val[0] = SMCCC_RET_NOT_SUPPORTED;
> + break;
> + }
> + break;
> + case ARM_SMCCC_VENDOR_HYP_CALL_UID_FUNC_ID:
> + uuid = ARM_SMCCC_VENDOR_HYP_UID_KVM;
> + val[0] = smccc_uuid_to_reg(&uuid, 0);
> + val[1] = smccc_uuid_to_reg(&uuid, 1);
> + val[2] = smccc_uuid_to_reg(&uuid, 2);
> + val[3] = smccc_uuid_to_reg(&uuid, 3);
> + break;
> 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);
> --
> 2.39.5
>