Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

KVM: arm64: pkvm: Adopt MARKER() to define host hypercall ranges

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>

+15 -10
+10 -2
arch/arm64/include/asm/kvm_asm.h
··· 50 50 51 51 #include <linux/mm.h> 52 52 53 + #define MARKER(m) \ 54 + m, __after_##m = m - 1 55 + 53 56 enum __kvm_host_smccc_func { 54 57 /* Hypercalls that are unavailable once pKVM has finalised. */ 55 58 /* __KVM_HOST_SMCCC_FUNC___kvm_hyp_init */ ··· 62 59 __KVM_HOST_SMCCC_FUNC___kvm_enable_ssbs, 63 60 __KVM_HOST_SMCCC_FUNC___vgic_v3_init_lrs, 64 61 __KVM_HOST_SMCCC_FUNC___vgic_v3_get_gic_config, 62 + 63 + MARKER(__KVM_HOST_SMCCC_FUNC_MIN_PKVM), 64 + 65 65 __KVM_HOST_SMCCC_FUNC___pkvm_prot_finalize, 66 - __KVM_HOST_SMCCC_FUNC_MIN_PKVM = __KVM_HOST_SMCCC_FUNC___pkvm_prot_finalize, 67 66 68 67 /* Hypercalls that are always available and common to [nh]VHE/pKVM. */ 69 68 __KVM_HOST_SMCCC_FUNC___kvm_adjust_pc, ··· 89 84 __KVM_HOST_SMCCC_FUNC___vgic_v3_restore_vmcr_aprs, 90 85 __KVM_HOST_SMCCC_FUNC___vgic_v5_save_apr, 91 86 __KVM_HOST_SMCCC_FUNC___vgic_v5_restore_vmcr_apr, 92 - __KVM_HOST_SMCCC_FUNC_MAX_NO_PKVM = __KVM_HOST_SMCCC_FUNC___vgic_v5_restore_vmcr_apr, 87 + 88 + MARKER(__KVM_HOST_SMCCC_FUNC_PKVM_ONLY), 93 89 94 90 /* Hypercalls that are available only when pKVM has finalised. */ 95 91 __KVM_HOST_SMCCC_FUNC___pkvm_host_share_hyp, ··· 114 108 __KVM_HOST_SMCCC_FUNC___pkvm_vcpu_load, 115 109 __KVM_HOST_SMCCC_FUNC___pkvm_vcpu_put, 116 110 __KVM_HOST_SMCCC_FUNC___pkvm_tlb_flush_vmid, 111 + 112 + MARKER(__KVM_HOST_SMCCC_FUNC_MAX) 117 113 }; 118 114 119 115 #define DECLARE_KVM_VHE_SYM(sym) extern char sym[]
-3
arch/arm64/include/asm/kvm_host.h
··· 450 450 r = __VNCR_START__ + ((VNCR_ ## r) / 8), \ 451 451 __after_##r = __MAX__(__before_##r - 1, r) 452 452 453 - #define MARKER(m) \ 454 - m, __after_##m = m - 1 455 - 456 453 enum vcpu_sysreg { 457 454 __INVALID_SYSREG__, /* 0 is reserved as an invalid value */ 458 455 MPIDR_EL1, /* MultiProcessor Affinity Register */
+5 -5
arch/arm64/kvm/hyp/nvhe/hyp-main.c
··· 748 748 static void handle_host_hcall(struct kvm_cpu_context *host_ctxt) 749 749 { 750 750 DECLARE_REG(unsigned long, id, host_ctxt, 0); 751 - unsigned long hcall_min = 0, hcall_max = -1; 751 + unsigned long hcall_min = 0, hcall_max = __KVM_HOST_SMCCC_FUNC_MAX; 752 752 hcall_t hfn; 753 + 754 + BUILD_BUG_ON(ARRAY_SIZE(host_hcall) != __KVM_HOST_SMCCC_FUNC_MAX); 753 755 754 756 /* 755 757 * If pKVM has been initialised then reject any calls to the ··· 765 763 if (static_branch_unlikely(&kvm_protected_mode_initialized)) { 766 764 hcall_min = __KVM_HOST_SMCCC_FUNC_MIN_PKVM; 767 765 } else { 768 - hcall_max = __KVM_HOST_SMCCC_FUNC_MAX_NO_PKVM; 766 + hcall_max = __KVM_HOST_SMCCC_FUNC_PKVM_ONLY; 769 767 } 770 768 771 769 id &= ~ARM_SMCCC_CALL_HINTS; 772 770 id -= KVM_HOST_SMCCC_ID(0); 773 771 774 - if (unlikely(id < hcall_min || id > hcall_max || 775 - id >= ARRAY_SIZE(host_hcall))) { 772 + if (unlikely(id < hcall_min || id >= hcall_max)) 776 773 goto inval; 777 - } 778 774 779 775 hfn = host_hcall[id]; 780 776 if (unlikely(!hfn))