[PATCH] KVM: arm64: pkvm: Adopt MARKER() to define host hypercall ranges
Fuad Tabba
tabba at google.com
Wed Apr 15 02:56:17 PDT 2026
Hi Marc,
On Tue, 14 Apr 2026 at 17:05, Marc Zyngier <maz at kernel.org> wrote:
>
> The EL2 code defines ranges of host hypercalls that are either
> enabled at boot-time only, used by [nh]VHE KVM, or reserved to pKVM.
>
> The way these ranges are delineated is error prone, as the enum symbols
> defining the limits are expressed in terms of actual function symbols.
> This means that should a new function be added, special care must be
> taken to also update the limit symbol.
>
> Improve this by reusing the mechanism introduced for the vcpu_sysreg
> enum, which uses a MARKER() macro and some extra trickery to make
> the limit symbol standalone. Crucially, the limit symbol has the
> same value as the *following* symbol.
>
> The handle_host_hcall() function is then updated to make use of
> the new limit definitions and get rid of the brittle default
> upper limit. This allows for some more strict checks at build
> time, and the removal of an comparison at run time.
This is pretty neat. There is still the issue of a hole, i.e., adding
an enum in the middle but forgetting to add a function, but that is
caught in handle_host_hcall(). I can't think of an easy way to catch
that though (xarray that initializes both?)
>
> Signed-off-by: Marc Zyngier <maz at kernel.org>
Tested-by: Fuad Tabba <tabba at google.com>
Reviewed-by: Fuad Tabba <tabba at google.com>
Cheers,
/fuad
> ---
> arch/arm64/include/asm/kvm_asm.h | 12 ++++++++++--
> arch/arm64/include/asm/kvm_host.h | 3 ---
> arch/arm64/kvm/hyp/nvhe/hyp-main.c | 10 +++++-----
> 3 files changed, 15 insertions(+), 10 deletions(-)
>
> diff --git a/arch/arm64/include/asm/kvm_asm.h b/arch/arm64/include/asm/kvm_asm.h
> index 37414440cee7f..fa033be6141ad 100644
> --- a/arch/arm64/include/asm/kvm_asm.h
> +++ b/arch/arm64/include/asm/kvm_asm.h
> @@ -50,6 +50,9 @@
>
> #include <linux/mm.h>
>
> +#define MARKER(m) \
> + m, __after_##m = m - 1
> +
> enum __kvm_host_smccc_func {
> /* Hypercalls that are unavailable once pKVM has finalised. */
> /* __KVM_HOST_SMCCC_FUNC___kvm_hyp_init */
> @@ -59,8 +62,10 @@ enum __kvm_host_smccc_func {
> __KVM_HOST_SMCCC_FUNC___kvm_enable_ssbs,
> __KVM_HOST_SMCCC_FUNC___vgic_v3_init_lrs,
> __KVM_HOST_SMCCC_FUNC___vgic_v3_get_gic_config,
> +
> + MARKER(__KVM_HOST_SMCCC_FUNC_MIN_PKVM),
> +
> __KVM_HOST_SMCCC_FUNC___pkvm_prot_finalize,
> - __KVM_HOST_SMCCC_FUNC_MIN_PKVM = __KVM_HOST_SMCCC_FUNC___pkvm_prot_finalize,
>
> /* Hypercalls that are always available and common to [nh]VHE/pKVM. */
> __KVM_HOST_SMCCC_FUNC___kvm_adjust_pc,
> @@ -76,7 +81,8 @@ enum __kvm_host_smccc_func {
> __KVM_HOST_SMCCC_FUNC___vgic_v3_restore_vmcr_aprs,
> __KVM_HOST_SMCCC_FUNC___vgic_v5_save_apr,
> __KVM_HOST_SMCCC_FUNC___vgic_v5_restore_vmcr_apr,
> - __KVM_HOST_SMCCC_FUNC_MAX_NO_PKVM = __KVM_HOST_SMCCC_FUNC___vgic_v5_restore_vmcr_apr,
> +
> + MARKER(__KVM_HOST_SMCCC_FUNC_PKVM_ONLY),
>
> /* Hypercalls that are available only when pKVM has finalised. */
> __KVM_HOST_SMCCC_FUNC___pkvm_host_share_hyp,
> @@ -108,6 +114,8 @@ enum __kvm_host_smccc_func {
> __KVM_HOST_SMCCC_FUNC___tracing_reset,
> __KVM_HOST_SMCCC_FUNC___tracing_enable_event,
> __KVM_HOST_SMCCC_FUNC___tracing_write_event,
> +
> + MARKER(__KVM_HOST_SMCCC_FUNC_MAX)
> };
>
> #define DECLARE_KVM_VHE_SYM(sym) extern char sym[]
> diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
> index 851f6171751c0..44211e86f5ebd 100644
> --- a/arch/arm64/include/asm/kvm_host.h
> +++ b/arch/arm64/include/asm/kvm_host.h
> @@ -450,9 +450,6 @@ struct kvm_vcpu_fault_info {
> r = __VNCR_START__ + ((VNCR_ ## r) / 8), \
> __after_##r = __MAX__(__before_##r - 1, r)
>
> -#define MARKER(m) \
> - m, __after_##m = m - 1
> -
> enum vcpu_sysreg {
> __INVALID_SYSREG__, /* 0 is reserved as an invalid value */
> MPIDR_EL1, /* MultiProcessor Affinity Register */
> diff --git a/arch/arm64/kvm/hyp/nvhe/hyp-main.c b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
> index 73f2e0221e703..9e44c05cf780e 100644
> --- a/arch/arm64/kvm/hyp/nvhe/hyp-main.c
> +++ b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
> @@ -748,9 +748,11 @@ static const hcall_t host_hcall[] = {
> static void handle_host_hcall(struct kvm_cpu_context *host_ctxt)
> {
> DECLARE_REG(unsigned long, id, host_ctxt, 0);
> - unsigned long hcall_min = 0, hcall_max = -1;
> + unsigned long hcall_min = 0, hcall_max = __KVM_HOST_SMCCC_FUNC_MAX;
> hcall_t hfn;
>
> + BUILD_BUG_ON(ARRAY_SIZE(host_hcall) != __KVM_HOST_SMCCC_FUNC_MAX);
> +
> /*
> * If pKVM has been initialised then reject any calls to the
> * early "privileged" hypercalls. Note that we cannot reject
> @@ -763,16 +765,14 @@ static void handle_host_hcall(struct kvm_cpu_context *host_ctxt)
> if (static_branch_unlikely(&kvm_protected_mode_initialized)) {
> hcall_min = __KVM_HOST_SMCCC_FUNC_MIN_PKVM;
> } else {
> - hcall_max = __KVM_HOST_SMCCC_FUNC_MAX_NO_PKVM;
> + hcall_max = __KVM_HOST_SMCCC_FUNC_PKVM_ONLY;
> }
>
> id &= ~ARM_SMCCC_CALL_HINTS;
> id -= KVM_HOST_SMCCC_ID(0);
>
> - if (unlikely(id < hcall_min || id > hcall_max ||
> - id >= ARRAY_SIZE(host_hcall))) {
> + if (unlikely(id < hcall_min || id >= hcall_max))
> goto inval;
> - }
>
> hfn = host_hcall[id];
> if (unlikely(!hfn))
> --
> 2.47.3
>
More information about the linux-arm-kernel
mailing list