public inbox for linux-arm-kernel@lists.infradead.org
 help / color / mirror / Atom feed
* [PATCH] KVM: arm64: pkvm: Adopt MARKER() to define host hypercall ranges
@ 2026-04-14 16:05 Marc Zyngier
  2026-04-15  9:56 ` Fuad Tabba
  2026-04-17 14:23 ` Marc Zyngier
  0 siblings, 2 replies; 4+ messages in thread
From: Marc Zyngier @ 2026-04-14 16:05 UTC (permalink / raw)
  To: kvmarm, linux-arm-kernel
  Cc: Will Deacon, Vincent Donnefort, Fuad Tabba, Joey Gouly,
	Suzuki K Poulose, Oliver Upton, Zenghui Yu

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.

Signed-off-by: Marc Zyngier <maz@kernel.org>
---
 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



^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH] KVM: arm64: pkvm: Adopt MARKER() to define host hypercall ranges
  2026-04-14 16:05 [PATCH] KVM: arm64: pkvm: Adopt MARKER() to define host hypercall ranges Marc Zyngier
@ 2026-04-15  9:56 ` Fuad Tabba
  2026-04-15 13:18   ` Marc Zyngier
  2026-04-17 14:23 ` Marc Zyngier
  1 sibling, 1 reply; 4+ messages in thread
From: Fuad Tabba @ 2026-04-15  9:56 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: kvmarm, linux-arm-kernel, Will Deacon, Vincent Donnefort,
	Joey Gouly, Suzuki K Poulose, Oliver Upton, Zenghui Yu

Hi Marc,

On Tue, 14 Apr 2026 at 17:05, Marc Zyngier <maz@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@kernel.org>

Tested-by: Fuad Tabba <tabba@google.com>
Reviewed-by: Fuad Tabba <tabba@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
>


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] KVM: arm64: pkvm: Adopt MARKER() to define host hypercall ranges
  2026-04-15  9:56 ` Fuad Tabba
@ 2026-04-15 13:18   ` Marc Zyngier
  0 siblings, 0 replies; 4+ messages in thread
From: Marc Zyngier @ 2026-04-15 13:18 UTC (permalink / raw)
  To: Fuad Tabba
  Cc: kvmarm, linux-arm-kernel, Will Deacon, Vincent Donnefort,
	Joey Gouly, Suzuki K Poulose, Oliver Upton, Zenghui Yu

On Wed, 15 Apr 2026 10:56:17 +0100,
Fuad Tabba <tabba@google.com> wrote:
> 
> Hi Marc,
> 
> On Tue, 14 Apr 2026 at 17:05, Marc Zyngier <maz@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?)

Yeah, there isn't a simple way to do that at compile-time,
unfortunately.

One thing that could be done is to have a blanket initialisation with
an illegal value, override all the entries you want, and then check at
KVM init time for the presence of the canary value. If you find it,
abort the KVM initialisation.

With that, you can drop the NULL test on the handling path.

> >
> > Signed-off-by: Marc Zyngier <maz@kernel.org>
> 
> Tested-by: Fuad Tabba <tabba@google.com>
> Reviewed-by: Fuad Tabba <tabba@google.com>

Thanks,

	M.

-- 
Without deviation from the norm, progress is not possible.


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] KVM: arm64: pkvm: Adopt MARKER() to define host hypercall ranges
  2026-04-14 16:05 [PATCH] KVM: arm64: pkvm: Adopt MARKER() to define host hypercall ranges Marc Zyngier
  2026-04-15  9:56 ` Fuad Tabba
@ 2026-04-17 14:23 ` Marc Zyngier
  1 sibling, 0 replies; 4+ messages in thread
From: Marc Zyngier @ 2026-04-17 14:23 UTC (permalink / raw)
  To: kvmarm, linux-arm-kernel, Marc Zyngier
  Cc: Will Deacon, Vincent Donnefort, Fuad Tabba, Joey Gouly,
	Suzuki K Poulose, Oliver Upton, Zenghui Yu

On Tue, 14 Apr 2026 17:05:28 +0100, Marc Zyngier 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.
> 
> [...]

Applied to fixes, thanks!

[1/1] KVM: arm64: pkvm: Adopt MARKER() to define host hypercall ranges
      commit: 9b72acd3f770517d3fd4bd7193fd60f3a81d1f69

Cheers,

	M.
-- 
Without deviation from the norm, progress is not possible.




^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2026-04-17 14:24 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-04-14 16:05 [PATCH] KVM: arm64: pkvm: Adopt MARKER() to define host hypercall ranges Marc Zyngier
2026-04-15  9:56 ` Fuad Tabba
2026-04-15 13:18   ` Marc Zyngier
2026-04-17 14:23 ` Marc Zyngier

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox