From: Fuad Tabba <fuad.tabba@linux.dev>
To: maz@kernel.org, oupton@kernel.org
Cc: kvmarm@lists.linux.dev, linux-arm-kernel@lists.infradead.org,
linux-kernel@vger.kernel.org, joey.gouly@arm.com,
seiden@linux.ibm.com, suzuki.poulose@arm.com,
yuzenghui@huawei.com, catalin.marinas@arm.com, will@kernel.org,
mark.rutland@arm.com, vdonnefort@google.com,
ryan.roberts@arm.com, qperret@google.com, steven.price@arm.com,
tabba@google.com
Subject: [PATCH] KVM: arm64: Keep firmware Spectre-v4 mitigation on for protected guests
Date: Fri, 13 Nov 2026 08:19:34 +0000 [thread overview]
Message-ID: <20261113081934.1715497-1-fuad.tabba@linux.dev> (raw)
EL2 handles a protected guest's ARM_SMCCC_ARCH_WORKAROUND_2 discovery
query from the host's Spectre-v4 state at init. If the system is
mitigated and the guest doesn't have SSBS, it returns NOT_REQUIRED,
which means that firmware mitigation is permanently enabled. However,
the host can disable the mitigation before running a protected vCPU,
with an ARM_SMCCC_ARCH_WORKAROUND_2 call that EL2 forwards to the
firmware.
The host makes that call for its own userspace, so keep forwarding it,
without hints so that the firmware decodes it as EL2 does. Track it per
CPU, and on a mitigated system enable the mitigation again before
running a protected vCPU on a CPU where the host has disabled it.
Firmware enables it when a CPU powers up, so the tracked state isn't
reset on CPU_ON or resume.
Fixes: fe40ff87ead5c ("KVM: arm64: Implement HVC handling for protected guests at EL2")
Reported-by: Ryan Roberts <ryan.roberts@arm.com>
Closes: https://lore.kernel.org/all/5fa8a1fb-4e2c-4746-8a70-a47f387ef0d6@arm.com/
Signed-off-by: Fuad Tabba <fuad.tabba@linux.dev>
---
Notes:
Tested on QEMU with TF-A. Upstream TF-A implements the dynamic
workaround only for Cortex-A76, so I patched it to advertise the
workaround on the Cortex-A57 that QEMU models. With a host that
disables the mitigation before running a protected vCPU, TF-A gets the
call to enable it again from EL2 with this patch, and doesn't without
it. TF-A's handler for the call does nothing there and QEMU doesn't
model the mitigation, so this tests the calls and not their effect.
Calling the firmware before every protected vCPU run would do without
the tracking, at the cost of an SMC per run.
Based on Linux 7.4-rc2 (7475ea8b58616).
arch/arm64/kvm/hyp/nvhe/hyp-main.c | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/arch/arm64/kvm/hyp/nvhe/hyp-main.c b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
index 179d7c8277b88..081a8780fa3b7 100644
--- a/arch/arm64/kvm/hyp/nvhe/hyp-main.c
+++ b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
@@ -21,6 +21,7 @@
#include <asm/kvm_mmu.h>
#include <nvhe/alloc.h>
+#include <nvhe/arm-smccc.h>
#include <nvhe/ffa.h>
#include <nvhe/mem_protect.h>
#include <nvhe/mm.h>
@@ -30,6 +31,8 @@
DEFINE_PER_CPU(struct kvm_nvhe_init_params, kvm_init_params);
+static DEFINE_PER_CPU(bool, host_ssbd_disabled);
+
/*
* Define a hypercall handler: handle_<name> unmarshals the arguments from
* the host context and hands them, correctly typed, to the body that
@@ -940,6 +943,17 @@ DEFINE_KVM_HOST_HCALL(int, __kvm_vcpu_run, struct kvm_vcpu __kern *, vcpu)
return ret;
}
+ /*
+ * Firmware Spectre-v4 mitigation can be advertised to a
+ * protected guest as permanent. The host kernel runs with it
+ * enabled, so nothing is restored on exit.
+ */
+ if (pkvm_hyp_vcpu_is_protected(hyp_vcpu) && spectre_v4_state == SPECTRE_MITIGATED &&
+ __this_cpu_read(host_ssbd_disabled)) {
+ hyp_smccc_1_1_smc(ARM_SMCCC_ARCH_WORKAROUND_2, true, NULL);
+ __this_cpu_write(host_ssbd_disabled, false);
+ }
+
flush_hyp_vcpu(hyp_vcpu);
ret = __kvm_vcpu_run(&hyp_vcpu->vcpu);
@@ -1671,6 +1685,12 @@ static void handle_host_smc(struct kvm_cpu_context *host_ctxt)
goto exit_skip_instr;
}
+ if (func_id == ARM_SMCCC_ARCH_WORKAROUND_2) {
+ /* Drop the hints, so that the firmware decodes the ID as EL2 did. */
+ cpu_reg(host_ctxt, 0) = func_id;
+ __this_cpu_write(host_ssbd_disabled, !lower_32_bits(cpu_reg(host_ctxt, 1)));
+ }
+
handled = kvm_host_psci_handler(host_ctxt, func_id);
if (!handled)
handled = kvm_host_ffa_handler(host_ctxt, func_id);
base-commit: 7475ea8b58616b33c04afb976cf0fbaad9dd63fb
--
2.47.3
reply other threads:[~2026-11-13 8:19 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261113081934.1715497-1-fuad.tabba@linux.dev \
--to=fuad.tabba@linux.dev \
--cc=catalin.marinas@arm.com \
--cc=joey.gouly@arm.com \
--cc=kvmarm@lists.linux.dev \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mark.rutland@arm.com \
--cc=maz@kernel.org \
--cc=oupton@kernel.org \
--cc=qperret@google.com \
--cc=ryan.roberts@arm.com \
--cc=seiden@linux.ibm.com \
--cc=steven.price@arm.com \
--cc=suzuki.poulose@arm.com \
--cc=tabba@google.com \
--cc=vdonnefort@google.com \
--cc=will@kernel.org \
--cc=yuzenghui@huawei.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox