Skip to content

Commit 49f5d15

Browse files
committed
ArmPkg/Library: optimise StandaloneMmMmuLib with FF-A v1.3
commit 4ca452c ("ArmPkg/Library: Update StandaloneMmuLib with FF-A v1.2 with page granularity") introduced page-granular memory permission updates to fix the StandaloneMm load failure. However, this approach results in issuing an SMC call per page when updating permissions over a region. Since FF-A Memory Management Protocol v1.3 [0], FFA_MEM_PERM_GET has been updated to return the number of contiguous pages that share the same memory permission starting from a base address. With this change, update memory permissions in bulk (per contiguous page range) to reduce the number of SMC calls, leveraging FF-A Memory Management Protocol v1.3 [0]. Link: https://developer.arm.com/documentation/den0140/latest [0] Signed-off-by: Yeoreum Yun <yeoreum.yun@arm.com>
1 parent f5c6c98 commit 49f5d15

File tree

1 file changed

+103
-19
lines changed

1 file changed

+103
-19
lines changed

ArmPkg/Library/StandaloneMmMmuLib/ArmMmuStandaloneMmLib.c

Lines changed: 103 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@
3535
StMM Core invokes this library before constructors are called and before the
3636
StMM image itself is relocated.
3737
38+
@param[out] MajorVersion Major Version of ABI.
39+
@param[out] MinorVersion Minor Version of ABI.
40+
3841
@retval TRUE Use FF-A MemPerm ABIs.
3942
@retval FALSE Use MM MemPerm ABIs.
4043
@@ -43,20 +46,21 @@ STATIC
4346
BOOLEAN
4447
EFIAPI
4548
IsFfaMemoryAbiSupported (
46-
IN VOID
49+
OUT UINT16 *MajorVersion,
50+
OUT UINT16 *MinorVersion
4751
)
4852
{
4953
EFI_STATUS Status;
50-
UINT16 CurrentMajorVersion;
51-
UINT16 CurrentMinorVersion;
54+
55+
*MajorVersion = 0;
56+
*MinorVersion = 0;
5257

5358
Status = ArmFfaLibGetVersion (
5459
ARM_FFA_MAJOR_VERSION,
5560
ARM_FFA_MINOR_VERSION,
56-
&CurrentMajorVersion,
57-
&CurrentMinorVersion
61+
MajorVersion,
62+
MinorVersion
5863
);
59-
6064
if (EFI_ERROR (Status)) {
6165
return FALSE;
6266
}
@@ -147,8 +151,13 @@ SendMemoryPermissionRequest (
147151
/** Request the permission attributes of a memory region from S-EL0.
148152
149153
@param [in] UseFfaAbis Use FF-A abis or not.
154+
@param [in] AbiMajorVersion ABI Major Version
155+
@param [in] AbiMinorVersion ABI Minor Version
150156
@param [in] BaseAddress Base address for the memory region.
157+
@param [in] Length Size of memory region.
151158
@param [out] MemoryAttributes Pointer to return the memory attributes.
159+
@param [out] PageCount Number of page sharing the same attribute from
160+
BaseAddress
152161
153162
@retval EFI_SUCCESS Request successfull.
154163
@retval EFI_INVALID_PARAMETER A parameter is invalid.
@@ -165,8 +174,12 @@ STATIC
165174
EFI_STATUS
166175
GetMemoryPermissions (
167176
IN BOOLEAN UseFfaAbis,
177+
IN UINT16 AbiMajorVersion,
178+
IN UINT16 AbiMinorVersion,
168179
IN EFI_PHYSICAL_ADDRESS BaseAddress,
169-
OUT UINT32 *MemoryAttributes
180+
IN UINT64 Length,
181+
OUT UINT32 *MemoryAttributes,
182+
OUT UINT32 *PageCount
170183
)
171184
{
172185
EFI_STATUS Status;
@@ -187,11 +200,34 @@ GetMemoryPermissions (
187200
SvcArgs.Arg0 = Fid;
188201
SvcArgs.Arg1 = BaseAddress;
189202

203+
if (UseFfaAbis && ((AbiMajorVersion > 1) || (AbiMinorVersion > 2))) {
204+
/*
205+
* The input page count is encoded as (page count - 1),
206+
* so subtract 1 from the actual page count.
207+
* See the FF-A Memory Management Protocol Spec version 1.3-ALP1
208+
* 2.8 FFA_MEM_PERM_GET
209+
*/
210+
SvcArgs.Arg2 = EFI_SIZE_TO_PAGES (Length) - 1;
211+
}
212+
190213
Status = SendMemoryPermissionRequest (UseFfaAbis, &SvcArgs, &Ret);
191214
if (EFI_ERROR (Status)) {
192215
*MemoryAttributes = 0;
216+
*PageCount = 0;
193217
} else {
194218
*MemoryAttributes = Ret;
219+
if (UseFfaAbis && ((AbiMajorVersion > 1) || (AbiMinorVersion > 2))) {
220+
/*
221+
* The output page count is encoded as (page count - 1),
222+
* so add 1 to get the actual page count.
223+
* See the FF-A Memory Management Protocol Spec version 1.3-ALP1
224+
* 2.8 FFA_MEM_PERM_GET
225+
*/
226+
*PageCount = SvcArgs.Arg3 + 1;
227+
ASSERT (*PageCount > EFI_SIZE_TO_PAGES (Length));
228+
} else {
229+
*PageCount = 1;
230+
}
195231
}
196232

197233
return Status;
@@ -253,17 +289,29 @@ ArmSetMemoryRegionNoExec (
253289
UINT32 MemoryAttributes;
254290
UINT32 PermissionRequest;
255291
BOOLEAN UseFfaAbis;
292+
UINT16 MajorVersion;
293+
UINT16 MinorVersion;
256294
UINTN Size;
295+
UINT32 PageCount;
257296

258-
UseFfaAbis = IsFfaMemoryAbiSupported ();
259-
Size = EFI_PAGE_SIZE;
297+
UseFfaAbis = IsFfaMemoryAbiSupported (&MajorVersion, &MinorVersion);
260298

261299
while (Length > 0) {
262-
Status = GetMemoryPermissions (UseFfaAbis, BaseAddress, &MemoryAttributes);
300+
Status = GetMemoryPermissions (
301+
UseFfaAbis,
302+
MajorVersion,
303+
MinorVersion,
304+
BaseAddress,
305+
Length,
306+
&MemoryAttributes,
307+
&PageCount
308+
);
263309
if (EFI_ERROR (Status)) {
264310
break;
265311
}
266312

313+
Size = EFI_PAGES_TO_SIZE (PageCount);
314+
267315
if (UseFfaAbis) {
268316
PermissionRequest = ARM_FFA_SET_MEM_ATTR_MAKE_PERM_REQUEST (
269317
MemoryAttributes,
@@ -307,17 +355,29 @@ ArmClearMemoryRegionNoExec (
307355
UINT32 MemoryAttributes;
308356
UINT32 PermissionRequest;
309357
BOOLEAN UseFfaAbis;
358+
UINT16 MajorVersion;
359+
UINT16 MinorVersion;
310360
UINTN Size;
361+
UINT32 PageCount;
311362

312-
UseFfaAbis = IsFfaMemoryAbiSupported ();
313-
Size = EFI_PAGE_SIZE;
363+
UseFfaAbis = IsFfaMemoryAbiSupported (&MajorVersion, &MinorVersion);
314364

315365
while (Length > 0) {
316-
Status = GetMemoryPermissions (UseFfaAbis, BaseAddress, &MemoryAttributes);
366+
Status = GetMemoryPermissions (
367+
UseFfaAbis,
368+
MajorVersion,
369+
MinorVersion,
370+
BaseAddress,
371+
Length,
372+
&MemoryAttributes,
373+
&PageCount
374+
);
317375
if (EFI_ERROR (Status)) {
318376
break;
319377
}
320378

379+
Size = EFI_PAGES_TO_SIZE (PageCount);
380+
321381
if (UseFfaAbis) {
322382
PermissionRequest = ARM_FFA_SET_MEM_ATTR_MAKE_PERM_REQUEST (
323383
MemoryAttributes,
@@ -361,17 +421,29 @@ ArmSetMemoryRegionReadOnly (
361421
UINT32 MemoryAttributes;
362422
UINT32 PermissionRequest;
363423
BOOLEAN UseFfaAbis;
424+
UINT16 MajorVersion;
425+
UINT16 MinorVersion;
364426
UINTN Size;
427+
UINT32 PageCount;
365428

366-
UseFfaAbis = IsFfaMemoryAbiSupported ();
367-
Size = EFI_PAGE_SIZE;
429+
UseFfaAbis = IsFfaMemoryAbiSupported (&MajorVersion, &MinorVersion);
368430

369431
while (Length > 0) {
370-
Status = GetMemoryPermissions (UseFfaAbis, BaseAddress, &MemoryAttributes);
432+
Status = GetMemoryPermissions (
433+
UseFfaAbis,
434+
MajorVersion,
435+
MinorVersion,
436+
BaseAddress,
437+
Length,
438+
&MemoryAttributes,
439+
&PageCount
440+
);
371441
if (EFI_ERROR (Status)) {
372442
break;
373443
}
374444

445+
Size = EFI_PAGES_TO_SIZE (PageCount);
446+
375447
if (UseFfaAbis) {
376448
PermissionRequest = ARM_FFA_SET_MEM_ATTR_MAKE_PERM_REQUEST (
377449
ARM_FFA_SET_MEM_ATTR_DATA_PERM_RO,
@@ -415,17 +487,29 @@ ArmClearMemoryRegionReadOnly (
415487
UINT32 MemoryAttributes;
416488
UINT32 PermissionRequest;
417489
BOOLEAN UseFfaAbis;
490+
UINT16 MajorVersion;
491+
UINT16 MinorVersion;
418492
UINTN Size;
493+
UINT32 PageCount;
419494

420-
UseFfaAbis = IsFfaMemoryAbiSupported ();
421-
Size = EFI_PAGE_SIZE;
495+
UseFfaAbis = IsFfaMemoryAbiSupported (&MajorVersion, &MinorVersion);
422496

423497
while (Length > 0) {
424-
Status = GetMemoryPermissions (UseFfaAbis, BaseAddress, &MemoryAttributes);
498+
Status = GetMemoryPermissions (
499+
UseFfaAbis,
500+
MajorVersion,
501+
MinorVersion,
502+
BaseAddress,
503+
Length,
504+
&MemoryAttributes,
505+
&PageCount
506+
);
425507
if (EFI_ERROR (Status)) {
426508
break;
427509
}
428510

511+
Size = EFI_PAGES_TO_SIZE (PageCount);
512+
429513
if (UseFfaAbis) {
430514
PermissionRequest = ARM_FFA_SET_MEM_ATTR_MAKE_PERM_REQUEST (
431515
ARM_FFA_SET_MEM_ATTR_DATA_PERM_RW,

0 commit comments

Comments
 (0)