[PATCH v2 0/3] ACPI: arm64: FFH Operation Region support for FF-A (offset 2)

Jamie Nguyen <[email protected]>
Newsgroups org.kernel.vger.linux-acpi,org.infradead.lists.linux-arm-kernel,org.kernel.vger.linux-kernel
Message-ID <[email protected]>
Arm DEN0048D (Functional Fixed Hardware Specification v1.3), published in
March 2026, adds a third FFH Operation Region flavour:

  https://developer.arm.com/documentation/den0048/latest/

An Operation Region declared with an Offset of 0x2 triggers an
FFA_MSG_SEND_DIRECT_REQ2 call instead of a bare SMC or HVC:

  OperationRegion (AFFH, FFixedHW, 2, 40)
  Field (AFFH, BufferAcc, NoLock, Preserve) { FFAD, 320 }

Each 64-bit field is one register, ordered from X0. X0 carries the call
status on return, X1[15:0] the receiver endpoint ID (or zero, which asks
OSPM to resolve it from the UUID), X2-X3 the service UUID written with
ToUUID(), and X4-X17 the payload. The region Length is 32 + 8 * N bytes
with 1 <= N <= 14, so X0-X4 at minimum and X0-X17 at most.

The spec recommends offset 0x2 for new platforms on the grounds that not
every OSPM implements offsets 0x0 and 0x1. Linux has had both since v6.2
but nothing for 0x2, so AML using the recommended encoding currently gets
AE_ERROR back.

These patches implement it. I could not find any prior posting of this on
linux-acpi or linux-arm-kernel, so apologies if I have missed one and
duplicated someone's work.

All three patches are co-developed with Dat Mach.

Design
------

drivers/acpi/arm64/ffh.c holds the DEN0048D side: region length
validation, the X0-X17 layout, the ToUUID() to FF-A UUID byte order
conversion, and the table 3 status codes. drivers/firmware/arm_ffa/ holds
the FF-A side: resolving a service UUID to an endpoint, and the call
itself, including the FFA_YIELD and FFA_INTERRUPT re-invocation DEN0048D
asks for.

The two talk through an ops structure the FF-A driver registers rather
than a direct call, because ffh.c is built in under a bool Kconfig symbol
while CONFIG_ARM_FFA_TRANSPORT is a tristate. Unregistration takes the
rwsem for writing, so it cannot race with an access already in flight.

None of what the handler needs was reachable through the existing
ffa_device interface. ffa_sync_send_receive2() always addresses
dev->vm_id, so a receiver endpoint ID supplied by AML cannot be honoured.
UUID to endpoint resolution had no in-kernel user at all. And
ffa_msg_send_direct_req2() throws away the response registers DEN0048D
wants copied back to AML. Patch 1 splits those out, leaving what existing
callers see unchanged.

Testing
-------

Built on arm64 with CONFIG_ACPI_FFH=y and CONFIG_ARM_FFA_TRANSPORT both =y
and =m, and with CONFIG_ACPI_FFH=n, W=1 clean. Every patch builds on its
own.

Runtime tested on an Arm server whose firmware reports FF-A 1.3 and picks
offset 2 in its TPM Physical Presence Interface method. Reading
/sys/class/tpm/tpm0/ppi/response drives it; kprobes show the call reaching
ffa_acpi_ffh_direct_req2() with the endpoint and the fourteen payload
registers the region implies. That method only returns a response when the
status field reads back zero, and it does.

That firmware only ever sends well formed requests naming the endpoint, so
the rest was driven from test SSDTs loaded through CONFIG_ACPI_CONFIGFS
against the same partition, one invocation per table:

  X1 zero, UUID set      endpoint resolved from the UUID, call succeeds
  X1 zero, UUID nil      rejected before any FF-A call
  X1 an unknown endpoint call attempted rather than refused, and the
                         callee's FFA_ERROR reported as FFH_FFA_CALL_FAILED
                         with the FF-A error code in X2 per table 3
  length 0x28, the min   one payload register, call succeeds
  length 0x24, invalid   rejected before any FF-A call

A second server, whose FF-A 1.1 firmware cannot do
FFA_MSG_SEND_DIRECT_REQ2, covers FFH_FFA_NOT_SUPPORTED and regressions: it
declares no FFH Operation Regions, and an offset 2 access there returns
AE_ERROR without this series. It has one service UUID per endpoint where
the first machine has six sharing one, covering both topologies.

With CONFIG_ARM_FFA_TRANSPORT=m, which nothing autoloads, an access before
the module is loaded reports FFH_FFA_NOT_SUPPORTED, loading makes it reach
the FF-A driver, unloading returns it to NOT_SUPPORTED, and reloading
reaches it again.

One path is unexercised: nothing provokes a response that is neither
FFA_ERROR nor FFA_MSG_SEND_DIRECT_RESP2, so the -EPROTO mapping is
untested. Neither platform has a UUID resolving to more than one endpoint,
so the endpoint ID comparison in ffa_acpi_ffh_partition_id() was exercised
with a throwaway stub reporting two differing IDs: it returns -ENOTUNIQ,
no FF-A call is attempted, and AML reads back FFH_FFA_INVALID_PARAMETERS.
ffa_device_match_uuid() already walks the descriptors a UUID query
returns, so that case looks reachable rather than theoretical.

Open question
-------------

1. ffa_msg_send_wait_for_completion() loops on FFA_YIELD and FFA_INTERRUPT
   with no bound, sleeping 1 ms per FFA_YIELD round. The loop predates this
   series and DEN0048D does require the reinvocation, but until now it was
   only reachable from in-kernel FF-A drivers. This series opens it up to
   any control method that writes the Operation Region, including at
   enumeration time, so a partition that keeps yielding would stall an AML
   thread indefinitely.

   Bounding it would affect the existing FF-A callers too, and table 3 has
   no status code for a call that was abandoned, so it may be out of scope
   for this series unless you disagree.

v1: https://lore.kernel.org/all/[email protected]/

Changes since v1:
 - Rebased onto v7.3-rc1. The code is byte for byte identical to v1; only
   the base moved, and it applies to current linux-next as well.
 - The testing above was repeated on v7.3-rc1: the build matrix
   (CONFIG_ACPI_FFH=y and =n, CONFIG_ARM_FFA_TRANSPORT=y and =m, W=1 over
   both directories, and each patch on its own), and the runtime testing on
   both machines. On the FF-A 1.1 machine a diff against an unpatched
   v7.3-rc1 shows FF-A bringup, partitions, driver bindings and the whole
   dmesg error set unchanged, with the offset 2 access moving from AE_ERROR
   to FFH_FFA_NOT_SUPPORTED.
 - Not repeated on rc1: the throwaway stub for the endpoint ID comparison,
   and the CONFIG_ARM_FFA_TRANSPORT=m load and unload cycle. Both were run
   on the v1 base.
 - No review comments were received on v1.

Jamie Nguyen (3):
  firmware: arm_ffa: Split the response out of
    ffa_msg_send_direct_req2()
  ACPI: arm64: Add support for the FF-A FFH Operation Region (offset 2)
  firmware: arm_ffa: Back the ACPI FF-A FFH Operation Region

 drivers/acpi/arm64/ffh.c          | 185 ++++++++++++++++++++++++++++++
 drivers/firmware/arm_ffa/driver.c | 169 +++++++++++++++++++++++++--
 include/linux/acpi.h              |  41 +++++++
 3 files changed, 386 insertions(+), 9 deletions(-)


base-commit: cee9395acd8043be0644b25c34bfa86623f2b935
-- 
2.43.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.