]> xenbits.xensource.com Git - people/pauldu/linux.git/commitdiff
KVM: arm64: nvhe: Ignore SVE hint in SMCCC function ID
authorJean-Philippe Brucker <jean-philippe@linaro.org>
Mon, 11 Sep 2023 14:52:57 +0000 (15:52 +0100)
committerMarc Zyngier <maz@kernel.org>
Tue, 12 Sep 2023 12:07:37 +0000 (13:07 +0100)
When SVE is enabled, the host may set bit 16 in SMCCC function IDs, a
hint that indicates an unused SVE state. At the moment NVHE doesn't
account for this bit when inspecting the function ID, and rejects most
calls. Clear the hint bit before comparing function IDs.

About version compatibility: the host's PSCI driver initially probes the
firmware for a SMCCC version number. If the firmware implements a
protocol recent enough (1.3), subsequent SMCCC calls have the hint bit
set. Since the hint bit was reserved in earlier versions of the
protocol, clearing it is fine regardless of the version in use.

When a new hint is added to the protocol in the future, it will be added
to ARM_SMCCC_CALL_HINTS and NVHE will handle it straight away. This
patch only clears known hints and leaves reserved bits as is, because
future SMCCC versions could use reserved bits as modifiers for the
function ID, rather than hints.

Fixes: cfa7ff959a78 ("arm64: smccc: Support SMCCC v1.3 SVE register saving hint")
Reported-by: Ben Horgan <ben.horgan@arm.com>
Signed-off-by: Jean-Philippe Brucker <jean-philippe@linaro.org>
Signed-off-by: Marc Zyngier <maz@kernel.org>
Link: https://lore.kernel.org/r/20230911145254.934414-4-jean-philippe@linaro.org
arch/arm64/include/asm/kvm_hyp.h
arch/arm64/kvm/hyp/include/nvhe/ffa.h
arch/arm64/kvm/hyp/nvhe/ffa.c
arch/arm64/kvm/hyp/nvhe/hyp-init.S
arch/arm64/kvm/hyp/nvhe/hyp-main.c
arch/arm64/kvm/hyp/nvhe/psci-relay.c
include/linux/arm-smccc.h

index b7238c72a04cfaee4cdd4510e408e5f0a6c4df6f..66efd67ea7e8d6dd98dc6088a6004fdb646df2a3 100644 (file)
@@ -118,7 +118,7 @@ void deactivate_traps_vhe_put(struct kvm_vcpu *vcpu);
 
 u64 __guest_enter(struct kvm_vcpu *vcpu);
 
-bool kvm_host_psci_handler(struct kvm_cpu_context *host_ctxt);
+bool kvm_host_psci_handler(struct kvm_cpu_context *host_ctxt, u32 func_id);
 
 #ifdef __KVM_NVHE_HYPERVISOR__
 void __noreturn __hyp_do_panic(struct kvm_cpu_context *host_ctxt, u64 spsr,
index 1becb10ecd8057d49dac1730409bfb10077cd1e0..d9fd5e6c7d3cca73c1f687e64d7848cceae92f98 100644 (file)
@@ -12,6 +12,6 @@
 #define FFA_MAX_FUNC_NUM 0x7F
 
 int hyp_ffa_init(void *pages);
-bool kvm_host_ffa_handler(struct kvm_cpu_context *host_ctxt);
+bool kvm_host_ffa_handler(struct kvm_cpu_context *host_ctxt, u32 func_id);
 
 #endif /* __KVM_HYP_FFA_H */
index ab4f5d160c58f9969f4820a479dbf3d119b2d617..6e4dba9eadef522fe7c4ccc93e362d405aa259c1 100644 (file)
@@ -634,9 +634,8 @@ out_handled:
        return true;
 }
 
-bool kvm_host_ffa_handler(struct kvm_cpu_context *host_ctxt)
+bool kvm_host_ffa_handler(struct kvm_cpu_context *host_ctxt, u32 func_id)
 {
-       DECLARE_REG(u64, func_id, host_ctxt, 0);
        struct arm_smccc_res res;
 
        /*
index 90fade1b032e4bc614861ebd49e8738042768d65..1cc06e6797bda378a59b072de8c6f9a1612f6893 100644 (file)
@@ -57,6 +57,7 @@ __do_hyp_init:
        cmp     x0, #HVC_STUB_HCALL_NR
        b.lo    __kvm_handle_stub_hvc
 
+       bic     x0, x0, #ARM_SMCCC_CALL_HINTS
        mov     x3, #KVM_HOST_SMCCC_FUNC(__kvm_hyp_init)
        cmp     x0, x3
        b.eq    1f
index 857d9bc04fd48a58bedaa8ab457088bfd7817600..2385fd03ed87c6c0450a1c2dbe830e95ce235ecc 100644 (file)
@@ -368,6 +368,7 @@ 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___pkvm_prot_finalize;
 
+       id &= ~ARM_SMCCC_CALL_HINTS;
        id -= KVM_HOST_SMCCC_ID(0);
 
        if (unlikely(id < hcall_min || id >= ARRAY_SIZE(host_hcall)))
@@ -392,11 +393,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);
        bool handled;
 
-       handled = kvm_host_psci_handler(host_ctxt);
+       func_id &= ~ARM_SMCCC_CALL_HINTS;
+
+       handled = kvm_host_psci_handler(host_ctxt, func_id);
        if (!handled)
-               handled = kvm_host_ffa_handler(host_ctxt);
+               handled = kvm_host_ffa_handler(host_ctxt, func_id);
        if (!handled)
                default_host_smc_handler(host_ctxt);
 
index 24543d2a34905c66cfe39b68831b5e242359a5eb..d57bcb6ab94d25b9998bbabd5cd0cdb2fd27e794 100644 (file)
@@ -273,9 +273,8 @@ static unsigned long psci_1_0_handler(u64 func_id, struct kvm_cpu_context *host_
        }
 }
 
-bool kvm_host_psci_handler(struct kvm_cpu_context *host_ctxt)
+bool kvm_host_psci_handler(struct kvm_cpu_context *host_ctxt, u32 func_id)
 {
-       DECLARE_REG(u64, func_id, host_ctxt, 0);
        unsigned long ret;
 
        switch (kvm_host_psci_config.version) {
index 7c67c17321d4ca4e221045d172b6a62e989a0e27..083f8565371616269fa0050036ec8a3631c44357 100644 (file)
@@ -67,6 +67,8 @@
 #define ARM_SMCCC_VERSION_1_3          0x10003
 
 #define ARM_SMCCC_1_3_SVE_HINT         0x10000
+#define ARM_SMCCC_CALL_HINTS           ARM_SMCCC_1_3_SVE_HINT
+
 
 #define ARM_SMCCC_VERSION_FUNC_ID                                      \
        ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL,                         \