ArmPkg: Handle FFA_BUSY response for MM communication

MM communicate is used at runtime, and the secure partition it is
communicating with may provide services access through other means then
the UEFI runtime services. As such, the MM communication library must not
assume that the partition will be in the waiting state. Instead it must
handle the case where the partition is busy and retry the communication
to some limit.

Signed-off-by: Chris Fernald <chfernal@microsoft.com>
This commit is contained in:
Chris Fernald 2026-06-17 12:10:13 -07:00 committed by mergify[bot]
parent af41063d81
commit 6f2b09986b

View file

@ -29,6 +29,11 @@
#define COMM_BUFFER_ATTRS (EFI_MEMORY_WB | EFI_MEMORY_XP | EFI_MEMORY_RUNTIME)
// This an absurdly high number. The timer cannot be used reliably at runtime so having some upper bound is necessary.
// This number is chosen with back-of-the-envelope calculations where the rough time to get a BUSY response it around
// 10 microseconds, so 500,000 retries is roughly 5 seconds.
#define MAX_BUSY_RETRIES 500000
//
// Partition ID if FF-A support is enabled
//
@ -64,16 +69,31 @@ SendFfaMmCommunicate (
{
EFI_STATUS Status;
DIRECT_MSG_ARGS CommunicateArgs;
UINT64 Retries;
ZeroMem (&CommunicateArgs, sizeof (DIRECT_MSG_ARGS));
Retries = 0;
while (TRUE) {
ZeroMem (&CommunicateArgs, sizeof (DIRECT_MSG_ARGS));
CommunicateArgs.Arg0 = (UINTN)mNsCommBuffMemRegion.PhysicalBase;
CommunicateArgs.Arg0 = (UINTN)mNsCommBuffMemRegion.PhysicalBase;
Status = ArmFfaLibMsgSendDirectReq (
mStMmPartId,
0,
&CommunicateArgs
);
Status = ArmFfaLibMsgSendDirectReq (
mStMmPartId,
0,
&CommunicateArgs
);
if (Status == EFI_NO_RESPONSE) {
// Only try for so long before just failing.
if (Retries >= MAX_BUSY_RETRIES) {
return EFI_TIMEOUT;
}
Retries++;
continue;
}
break;
}
while (Status == EFI_INTERRUPT_PENDING) {
// We are assuming vCPU0 of the StMM SP since it is UP.