]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
KVM: arm64: Prevent the host from using an smc with imm16 != 0
authorSebastian Ene <sebastianene@google.com>
Mon, 30 Mar 2026 10:54:41 +0000 (10:54 +0000)
committerMarc Zyngier <maz@kernel.org>
Wed, 1 Apr 2026 15:39:10 +0000 (16:39 +0100)
The ARM Service Calling Convention (SMCCC) specifies that the function
identifier and parameters should be passed in registers, leaving the
16-bit immediate field un-handled in pKVM when an SMC instruction is
trapped.
Since the HVC is a private interface between EL2 and the host,
enforce the host kernel running under pKVM to use an immediate value
of 0 only when using SMCs to make it clear for non-compliant software
talking to Trustzone that we only use SMCCC.

Signed-off-by: Sebastian Ene <sebastianene@google.com>
Reviewed-by: Vincent Donnefort <vdonnefort@google.com>
Link: https://patch.msgid.link/20260330105441.3226904-1-sebastianene@google.com
Signed-off-by: Marc Zyngier <maz@kernel.org>
arch/arm64/kvm/hyp/nvhe/hyp-main.c

index e7790097db93a02bbd8101babf71348acee8448b..461cf5cb5ac7c87d007c7929c3fa108c5086c1e1 100644 (file)
@@ -676,8 +676,14 @@ static void default_host_smc_handler(struct kvm_cpu_context *host_ctxt)
 static void handle_host_smc(struct kvm_cpu_context *host_ctxt)
 {
        DECLARE_REG(u64, func_id, host_ctxt, 0);
+       u64 esr = read_sysreg_el2(SYS_ESR);
        bool handled;
 
+       if (esr & ESR_ELx_xVC_IMM_MASK) {
+               cpu_reg(host_ctxt, 0) = SMCCC_RET_NOT_SUPPORTED;
+               goto exit_skip_instr;
+       }
+
        func_id &= ~ARM_SMCCC_CALL_HINTS;
 
        handled = kvm_host_psci_handler(host_ctxt, func_id);
@@ -686,6 +692,7 @@ static void handle_host_smc(struct kvm_cpu_context *host_ctxt)
        if (!handled)
                default_host_smc_handler(host_ctxt);
 
+exit_skip_instr:
        /* SMC was trapped, move ELR past the current PC. */
        kvm_skip_host_instr();
 }