Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [RFC PATCH 0/3] ACPI: arm64: FFH Operation Region support for FF-A (offset 2)
@ 2026-07-29 17:56 Jamie Nguyen
  2026-07-29 17:56 ` [RFC PATCH 1/3] firmware: arm_ffa: Split the response out of ffa_msg_send_direct_req2() Jamie Nguyen
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Jamie Nguyen @ 2026-07-29 17:56 UTC (permalink / raw)
  To: Lorenzo Pieralisi, Hanjun Guo, Sudeep Holla, Catalin Marinas,
	Will Deacon, Rafael J . Wysocki
  Cc: Len Brown, Dat Mach, linux-acpi, linux-arm-kernel, linux-kernel,
	Jamie Nguyen

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, succeeding twenty times over. That method
only returns a response when the status field reads back zero, and it
does, so the status, the copied back registers and the payload are all
landing where the firmware expects them.

That firmware always names the receiver endpoint and always sends a well
formed request, so the rest was driven from test SSDTs loaded at runtime
through CONFIG_ACPI_CONFIGFS, against the same partition. Top level AML in
a dynamically loaded table runs at load, so each table is one invocation
with the register contents under test:

  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 covers FFH_FFA_NOT_SUPPORTED, since its FF-A 1.1 firmware
cannot do FFA_MSG_SEND_DIRECT_REQ2 at all. It doubles as a regression
platform: it declares no FFH Operation Regions, and an offset 2 access
there returns AE_ERROR on a distro kernel, which is what this series
removes. It also has one service UUID per endpoint, where the first
machine has six sharing one, so both partition topologies are covered.

Registration and teardown were exercised with CONFIG_ARM_FFA_TRANSPORT=m.
Nothing autoloads it, so an access before the module is loaded correctly
reports FFH_FFA_NOT_SUPPORTED; loading makes the same access reach the
FF-A driver, unloading returns it to NOT_SUPPORTED, and reloading reaches
it again.

One path is unexercised: nothing I have 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 that resolves to more than one
endpoint either, so the loop comparing endpoint IDs in
ffa_acpi_ffh_partition_id() was exercised instead with a throwaway stub
that makes a UUID filtered probe report two differing IDs. It returns
-ENOTUNIQ, no FF-A call is attempted, and AML reads back
FFH_FFA_INVALID_PARAMETERS. That case does look reachable rather than
theoretical, since ffa_device_match_uuid() already walks the descriptors a
UUID query returns looking for a matching endpoint ID.

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.

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: 3652b49adac266a3d27cb41cdfdb7d8790fc3633
-- 
2.43.0



^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2026-07-29 17:58 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-29 17:56 [RFC PATCH 0/3] ACPI: arm64: FFH Operation Region support for FF-A (offset 2) Jamie Nguyen
2026-07-29 17:56 ` [RFC PATCH 1/3] firmware: arm_ffa: Split the response out of ffa_msg_send_direct_req2() Jamie Nguyen
2026-07-29 17:56 ` [RFC PATCH 2/3] ACPI: arm64: Add support for the FF-A FFH Operation Region (offset 2) Jamie Nguyen
2026-07-29 17:56 ` [RFC PATCH 3/3] firmware: arm_ffa: Back the ACPI FF-A FFH Operation Region Jamie Nguyen

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox