Re: [PATCH v1 09/11] KVM: arm64: Type-check hypercall arguments at the caller

Marc Zyngier <[email protected]>
Newsgroups dev.linux.lists.kvmarm,org.infradead.lists.linux-arm-kernel,org.kernel.vger.linux-kernel,org.kernel.vger.linux-trace-kernel
Message-ID <[email protected]>
On Mon, 20 Jul 2026 17:13:41 +0100,
Fuad Tabba <[email protected]> wrote:
> 
> kvm_call_hyp_nvhe() reduces its target to an SMCCC function number, so
> the compiler never sees a callable: arguments that are wrong in number,
> type or order are silently marshalled into registers. The kvm_call_hyp()
> wrappers only catch this on the VHE branch, and the pKVM-only hypercalls
> have no such branch.
> 
> Declare each hypercall's signature once in kvm_hcall.h and generate a
> typed stub from it, in the mold of the syscall wrappers. Make
> kvm_call_hyp_nvhe() resolve to the stub so every caller is checked
> against the declared signature; a stale or mistyped call now fails to
> compile. The stubs inline to the same SMCCC call the untyped macro used
> to make: the compiled callers are unchanged, apart from hypercall
> returns now being tested at their declared width.
> 
> The stage-2 protection arguments are declared u64 rather than
> enum kvm_pgtable_prot, as kvm_pgtable.h includes linux/kvm_host.h and
> the enum cannot be completed here.
> 
> Assisted-by: Antigravity:gemini-3.1-pro
> Signed-off-by: Fuad Tabba <[email protected]>
> ---
>  arch/arm64/include/asm/kvm_hcall.h | 165 ++++++++++++++++++++++++++++-
>  arch/arm64/kvm/hyp_trace.c         |   2 +-
>  2 files changed, 165 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/arm64/include/asm/kvm_hcall.h b/arch/arm64/include/asm/kvm_hcall.h
> index d925b2c28a3d8..51bfd14748464 100644
> --- a/arch/arm64/include/asm/kvm_hcall.h
> +++ b/arch/arm64/include/asm/kvm_hcall.h
> @@ -16,12 +16,35 @@
>  
>  #include <asm/barrier.h>
>  #include <asm/kvm_asm.h>
> +#include <asm/spectre.h>
>  #include <asm/virt.h>
>  
>  typedef u16 pkvm_handle_t;
>  
> +struct kvm;
> +struct kvm_s2_mmu;
> +struct kvm_vcpu;
> +struct vgic_v3_cpu_if;
> +struct vgic_v5_cpu_if;
> +
> +/*
> + * Hypercall signatures are declared as (type, name) argument pairs.
> + * __KVM_HCALL_MAP() applies a macro to each pair, in the mold of __MAP()
> + * in <linux/syscalls.h>.
> + */
> +#define __KVM_HCALL_MAP1(m, t, a, ...) m(t, a)
> +#define __KVM_HCALL_MAP2(m, t, a, ...) m(t, a), __KVM_HCALL_MAP1(m, __VA_ARGS__)
> +#define __KVM_HCALL_MAP3(m, t, a, ...) m(t, a), __KVM_HCALL_MAP2(m, __VA_ARGS__)
> +#define __KVM_HCALL_MAP4(m, t, a, ...) m(t, a), __KVM_HCALL_MAP3(m, __VA_ARGS__)
> +#define __KVM_HCALL_MAP5(m, t, a, ...) m(t, a), __KVM_HCALL_MAP4(m, __VA_ARGS__)
> +#define __KVM_HCALL_MAP6(m, t, a, ...) m(t, a), __KVM_HCALL_MAP5(m, __VA_ARGS__)
> +#define __KVM_HCALL_MAP(n, ...) __KVM_HCALL_MAP##n(__VA_ARGS__)
> +
> +#define __KVM_HCALL_DECL(t, a)	t a
> +#define __KVM_HCALL_ARGS(t, a)	a
> +
>  #ifndef __KVM_NVHE_HYPERVISOR__
> -#define kvm_call_hyp_nvhe(f, ...)					\
> +#define __kvm_call_hyp_nvhe(f, ...)					\
>  	({								\
>  		struct arm_smccc_res res;				\
>  									\
> @@ -33,6 +56,43 @@ typedef u16 pkvm_handle_t;
>  		res.a1;							\
>  	})
>  
> +/*
> + * Generate a typed stub for each declared hypercall. kvm_call_hyp_nvhe()
> + * resolves to the stub, so a call with the wrong argument count or types
> + * fails to compile instead of being silently truncated to an SMCCC function
> + * number and a pile of registers. The stub inlines to the same SMCCC call
> + * the untyped macro used to make.
> + */
> +#define DECLARE_KVM_HOST_HCALL(ret, name, x, ...)			\
> +	static __always_inline						\
> +	ret nvhe_hvc_##name(__KVM_HCALL_MAP(x, __KVM_HCALL_DECL, __VA_ARGS__)) \
> +	{								\
> +		return (ret)__kvm_call_hyp_nvhe(name,			\
> +			__KVM_HCALL_MAP(x, __KVM_HCALL_ARGS, __VA_ARGS__)); \
> +	}

One thing I find absolutely horrible is to have to specify the number
of parameters here. It is already bad to have to comma-separate
everything, but having to count them is too hard for me ;-).

We already have facilities to count the number of parameters to a
macro (see the COUNT_ARGS macro). You could make use of it all over
the place.

Thanks,

	M.

-- 
Without deviation from the norm, progress is not possible.
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.