Thread (14 messages) read the whole thread 14 messages, 3 authors, 2d ago

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

From: Fuad Tabba <fuad.tabba@linux.dev>
Date: 2026-07-30 13:48:42
Also in: kvmarm, linux-arm-kernel, lkml

Hi Marc,

On Thu, 30 Jul 2026 at 13:37, Marc Zyngier [off-list ref] wrote:
...
quoted
+/*
+ * 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.
Will Deacon mentioned the same thing yesterday (offline). I'll drop it
in v2. The count was only there because the macro that walks the pair
list is a copy of __MAP() in <linux/syscalls.h>, which gets its arity
from the SYSCALL_DEFINEn name. No better reason than that.

COUNT_ARGS() does work here. The list is (type, name) pairs, so it
counts twice the arguments, which the ladder absorbs by being indexed
on list entries:

#define __KVM_HCALL_MAP2(m, t, a, ...) m(t, a)
#define __KVM_HCALL_MAP4(m, t, a, ...) m(t, a), __KVM_HCALL_MAP2(m, __VA_ARGS__)
[...]
#define __KVM_HCALL_MAP12(m, t, a, ...) m(t, a), __KVM_HCALL_MAP10(m,
__VA_ARGS__)
#define __KVM_HCALL_MAP_N(n, m, ...) CONCATENATE(__KVM_HCALL_MAP,
n)(m, __VA_ARGS__)
#define __KVM_HCALL_MAP(m, ...)
__KVM_HCALL_MAP_N(COUNT_ARGS(__VA_ARGS__), m, __VA_ARGS__)

DECLARE_KVM_HOST_HCALL(int, __pkvm_init,
      phys_addr_t, phys, unsigned long, size,
      unsigned long *, per_cpu_base, u32, hyp_va_bits)

That drops 40 hand-written counts from the declarations and 40 from
the handler definitions. __KVM_HCALL_MAP_N() is for the handler side,
which truncates a fixed list of six argument registers, and takes its
count from COUNT_ARGS() as well.

I diffed the preprocessed output before and after: token-identical
apart from the __LINE__ values that shift with the declarations.

Cheers,
/fuad

Thanks,

        M.

--
Without deviation from the norm, progress is not possible.
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help