]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
KVM: arm64: pkvm: Adopt MARKER() to define host hypercall ranges
authorMarc Zyngier <maz@kernel.org>
Tue, 14 Apr 2026 16:05:28 +0000 (17:05 +0100)
committerMarc Zyngier <maz@kernel.org>
Sat, 18 Apr 2026 08:07:13 +0000 (09:07 +0100)
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.

Tested-by: Fuad Tabba <tabba@google.com>
Reviewed-by: Fuad Tabba <tabba@google.com>
Link: https://patch.msgid.link/20260414160528.2218858-1-maz@kernel.org
Signed-off-by: Marc Zyngier <maz@kernel.org>
arch/arm64/include/asm/kvm_asm.h
arch/arm64/include/asm/kvm_host.h
arch/arm64/kvm/hyp/nvhe/hyp-main.c

index 11dcdf4349715c99d699617ad0b100056ad3760b..043495f7fc78b904cf2596546285cc1b40ab56ac 100644 (file)
@@ -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,
@@ -84,7 +89,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___pkvm_vcpu_load,
        __KVM_HOST_SMCCC_FUNC___pkvm_vcpu_put,
        __KVM_HOST_SMCCC_FUNC___pkvm_tlb_flush_vmid,
+
+       MARKER(__KVM_HOST_SMCCC_FUNC_MAX)
 };
 
 #define DECLARE_KVM_VHE_SYM(sym)       extern char sym[]
index 851f6171751c047c6c4f99a0e833775e154e308d..44211e86f5ebd8e69e90613f3335e2e033ee5290 100644 (file)
@@ -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 */
index 8f7582d57ab5617fad09eabe0e5b3dd902464175..1de9c70599c6561f4c8650839fffe8f0b3ee107f 100644 (file)
@@ -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))