Skip to content

Commit

Permalink
KVM: arm64: Use acquire/release to communicate FF-A version negotiation
Browse files Browse the repository at this point in the history
The pKVM FF-A proxy rejects FF-A requests other than FFA_VERSION until
version negotiation is complete, which is signalled by setting the
global 'has_version_negotiated' variable.

To avoid excessive locking, this variable is checked directly from
kvm_host_ffa_handler() in response to an FF-A call, but this can race
against another CPU performing the negotiation and potentially lead to
reading a torn value (incredibly unlikely for a 'bool') or problematic
re-ordering of the accesses to 'has_version_negotiated' and
'hyp_ffa_version' whereby a stale version number could be read by
__do_ffa_mem_xfer().

Use acquire/release primitives when writing 'has_version_negotiated'
with the version lock held and when reading without the lock held.

Cc: Sebastian Ene <sebastianene@google.com>
Cc: Sudeep Holla <sudeep.holla@arm.com>
Cc: Quentin Perret <qperret@google.com>
Cc: Oliver Upton <oliver.upton@linux.dev>
Cc: Marc Zyngier <maz@kernel.org>
Fixes: c9c0126 ("KVM: arm64: Trap FFA_VERSION host call in pKVM")
Signed-off-by: Will Deacon <will@kernel.org>
Link: https://lore.kernel.org/r/20250407152755.1041-1-will@kernel.org
Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
  • Loading branch information
Will Deacon authored and Oliver Upton committed Apr 7, 2025
1 parent c8631ea commit a344e25
Showing 1 changed file with 5 additions and 4 deletions.
9 changes: 5 additions & 4 deletions arch/arm64/kvm/hyp/nvhe/ffa.c
Original file line number Diff line number Diff line change
Expand Up @@ -730,10 +730,10 @@ static void do_ffa_version(struct arm_smccc_res *res,
hyp_ffa_version = ffa_req_version;
}

if (hyp_ffa_post_init())
if (hyp_ffa_post_init()) {
res->a0 = FFA_RET_NOT_SUPPORTED;
else {
has_version_negotiated = true;
} else {
smp_store_release(&has_version_negotiated, true);
res->a0 = hyp_ffa_version;
}
unlock:
Expand Down Expand Up @@ -809,7 +809,8 @@ bool kvm_host_ffa_handler(struct kvm_cpu_context *host_ctxt, u32 func_id)
if (!is_ffa_call(func_id))
return false;

if (!has_version_negotiated && func_id != FFA_VERSION) {
if (func_id != FFA_VERSION &&
!smp_load_acquire(&has_version_negotiated)) {
ffa_to_smccc_error(&res, FFA_RET_INVALID_PARAMETERS);
goto out_handled;
}
Expand Down

0 comments on commit a344e25

Please sign in to comment.