ArmPkg: Added CpuSetUserMemoryAttributes() for AARCH64.

This commit is contained in:
Mikhail Krichanov 2024-12-09 17:32:37 +03:00
parent 6da370bc11
commit 458983559f
9 changed files with 99 additions and 22 deletions

View File

@ -95,7 +95,7 @@ SetMemoryPermissions (
return EFI_INVALID_PARAMETER; return EFI_INVALID_PARAMETER;
} }
return ArmSetMemoryAttributes (BaseAddress, Length, Attributes, AttributeMask); return ArmSetMemoryAttributes (BaseAddress, Length, Attributes, AttributeMask, 0);
} }
STATIC CONST EDKII_MEMORY_ATTRIBUTE_PPI mMemoryAttributePpi = { STATIC CONST EDKII_MEMORY_ATTRIBUTE_PPI mMemoryAttributePpi = {

View File

@ -62,6 +62,7 @@ ArmReplaceLiveTranslationEntry (
@param[in] Length The size in bytes of the memory region. @param[in] Length The size in bytes of the memory region.
@param[in] Attributes Mask of memory attributes to set. @param[in] Attributes Mask of memory attributes to set.
@param[in] AttributeMask Mask of memory attributes to take into account. @param[in] AttributeMask Mask of memory attributes to take into account.
@param[in] UserPageTable The base address of the User page table.
@retval EFI_SUCCESS The attributes were set for the memory region. @retval EFI_SUCCESS The attributes were set for the memory region.
@retval EFI_INVALID_PARAMETER BaseAddress or Length is not suitably aligned. @retval EFI_INVALID_PARAMETER BaseAddress or Length is not suitably aligned.
@ -76,7 +77,8 @@ ArmSetMemoryAttributes (
IN EFI_PHYSICAL_ADDRESS BaseAddress, IN EFI_PHYSICAL_ADDRESS BaseAddress,
IN UINT64 Length, IN UINT64 Length,
IN UINT64 Attributes, IN UINT64 Attributes,
IN UINT64 AttributeMask IN UINT64 AttributeMask,
IN UINTN UserPageTable OPTIONAL
); );
#endif // ARM_MMU_LIB_H_ #endif // ARM_MMU_LIB_H_

View File

@ -496,6 +496,7 @@ GcdAttributeToPageAttribute (
@param[in] Length The size in bytes of the memory region. @param[in] Length The size in bytes of the memory region.
@param[in] Attributes Mask of memory attributes to set. @param[in] Attributes Mask of memory attributes to set.
@param[in] AttributeMask Mask of memory attributes to take into account. @param[in] AttributeMask Mask of memory attributes to take into account.
@param[in] UserPageTable The base address of the User page table.
@retval EFI_SUCCESS The attributes were set for the memory region. @retval EFI_SUCCESS The attributes were set for the memory region.
@retval EFI_INVALID_PARAMETER BaseAddress or Length is not suitably aligned. @retval EFI_INVALID_PARAMETER BaseAddress or Length is not suitably aligned.
@ -510,7 +511,8 @@ ArmSetMemoryAttributes (
IN EFI_PHYSICAL_ADDRESS BaseAddress, IN EFI_PHYSICAL_ADDRESS BaseAddress,
IN UINT64 Length, IN UINT64 Length,
IN UINT64 Attributes, IN UINT64 Attributes,
IN UINT64 AttributeMask IN UINT64 AttributeMask,
IN UINTN UserPageTable OPTIONAL
) )
{ {
UINT64 PageAttributes; UINT64 PageAttributes;
@ -545,14 +547,25 @@ ArmSetMemoryAttributes (
} }
} }
return UpdateRegionMapping ( if (UserPageTable == 0) {
BaseAddress, return UpdateRegionMapping (
Length, BaseAddress,
PageAttributes, Length,
PageAttributeMask, PageAttributes,
ArmGetTTBR0BaseAddress (), PageAttributeMask,
TRUE ArmGetTTBR0BaseAddress (),
); TRUE
);
} else {
return UpdateRegionMapping (
BaseAddress,
Length,
PageAttributes,
PageAttributeMask,
(UINT64 *)UserPageTable,
FALSE
);
}
} }
EFI_STATUS EFI_STATUS

View File

@ -522,6 +522,7 @@ GetMemoryRegionRec (
updated to the end address of the retrieved region. updated to the end address of the retrieved region.
@param[out] RegionLength The length of the retrieved memory region. @param[out] RegionLength The length of the retrieved memory region.
@param[out] RegionAttributes The attributes of the retrieved memory region. @param[out] RegionAttributes The attributes of the retrieved memory region.
@param[in] UserPageTable The base address of the User page table.
@retval EFI_STATUS Returns EFI_SUCCESS if the memory region is @retval EFI_STATUS Returns EFI_SUCCESS if the memory region is
retrieved successfully, or the status of the retrieved successfully, or the status of the
@ -535,7 +536,8 @@ EFI_STATUS
GetMemoryRegion ( GetMemoryRegion (
IN OUT UINTN *BaseAddress, IN OUT UINTN *BaseAddress,
OUT UINTN *RegionLength, OUT UINTN *RegionLength,
OUT UINTN *RegionAttributes OUT UINTN *RegionAttributes,
IN UINTN UserPageTable OPTIONAL
) )
{ {
EFI_STATUS Status; EFI_STATUS Status;
@ -549,7 +551,12 @@ GetMemoryRegion (
return EFI_INVALID_PARAMETER; return EFI_INVALID_PARAMETER;
} }
TranslationTable = ArmGetTTBR0BaseAddress (); if (UserPageTable == 0) {
TranslationTable = ArmGetTTBR0BaseAddress ();
} else {
TranslationTable = (UINT64 *)UserPageTable;
}
// Initialize the output parameters. These paramaters are only valid if the // Initialize the output parameters. These paramaters are only valid if the
// result is EFI_SUCCESS. // result is EFI_SUCCESS.

View File

@ -218,7 +218,8 @@ EFI_CPU_ARCH_PROTOCOL mCpu = {
CpuSetMemoryAttributes, CpuSetMemoryAttributes,
0, // NumberOfTimers 0, // NumberOfTimers
2048, // DmaBufferAlignment 2048, // DmaBufferAlignment
CpuGetMemoryAttributes CpuGetMemoryAttributes,
CpuSetUserMemoryAttributes
}; };
STATIC STATIC
@ -293,7 +294,8 @@ RemapUnusedMemoryNx (
MemoryMapEntry->PhysicalStart, MemoryMapEntry->PhysicalStart,
EFI_PAGES_TO_SIZE (MemoryMapEntry->NumberOfPages), EFI_PAGES_TO_SIZE (MemoryMapEntry->NumberOfPages),
EFI_MEMORY_XP, EFI_MEMORY_XP,
EFI_MEMORY_XP EFI_MEMORY_XP,
0
); );
} }

View File

@ -104,6 +104,16 @@ CpuGetMemoryAttributes (
OUT UINT64 *Attributes OUT UINT64 *Attributes
); );
EFI_STATUS
EFIAPI
CpuSetUserMemoryAttributes (
IN EFI_CPU_ARCH_PROTOCOL *This,
IN UINTN UserPageTable,
IN EFI_PHYSICAL_ADDRESS BaseAddress,
IN UINT64 Length,
IN UINT64 EfiAttributes
);
EFI_STATUS EFI_STATUS
InitializeExceptions ( InitializeExceptions (
IN EFI_CPU_ARCH_PROTOCOL *Cpu IN EFI_CPU_ARCH_PROTOCOL *Cpu
@ -124,7 +134,8 @@ EFI_STATUS
GetMemoryRegion ( GetMemoryRegion (
IN OUT UINTN *BaseAddress, IN OUT UINTN *BaseAddress,
OUT UINTN *RegionLength, OUT UINTN *RegionLength,
OUT UINTN *RegionAttributes OUT UINTN *RegionAttributes,
IN UINTN UserPageTable OPTIONAL
); );
EFI_STATUS EFI_STATUS

View File

@ -210,14 +210,14 @@ CpuSetMemoryAttributes (
// Get the region starting from 'BaseAddress' and its 'Attribute' // Get the region starting from 'BaseAddress' and its 'Attribute'
RegionBaseAddress = BaseAddress; RegionBaseAddress = BaseAddress;
Status = GetMemoryRegion (&RegionBaseAddress, &RegionLength, &RegionArmAttributes); Status = GetMemoryRegion (&RegionBaseAddress, &RegionLength, &RegionArmAttributes, 0);
// Data & Instruction Caches are flushed when we set new memory attributes. // Data & Instruction Caches are flushed when we set new memory attributes.
// So, we only set the attributes if the new region is different. // So, we only set the attributes if the new region is different.
if (EFI_ERROR (Status) || (RegionArmAttributes != ArmAttributes) || if (EFI_ERROR (Status) || (RegionArmAttributes != ArmAttributes) ||
((BaseAddress + Length) > (RegionBaseAddress + RegionLength))) ((BaseAddress + Length) > (RegionBaseAddress + RegionLength)))
{ {
return ArmSetMemoryAttributes (BaseAddress, Length, EfiAttributes, 0); return ArmSetMemoryAttributes (BaseAddress, Length, EfiAttributes, 0, 0);
} else { } else {
return EFI_SUCCESS; return EFI_SUCCESS;
} }
@ -237,7 +237,7 @@ CpuGetMemoryAttributes (
UINTN RegionArmAttributes; UINTN RegionArmAttributes;
RegionBaseAddress = Address; RegionBaseAddress = Address;
Status = GetMemoryRegion (&RegionBaseAddress, &RegionLength, &RegionArmAttributes); Status = GetMemoryRegion (&RegionBaseAddress, &RegionLength, &RegionArmAttributes, 0);
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
return EFI_NOT_FOUND; return EFI_NOT_FOUND;
@ -247,3 +247,43 @@ CpuGetMemoryAttributes (
return Status; return Status;
} }
EFI_STATUS
EFIAPI
CpuSetUserMemoryAttributes (
IN EFI_CPU_ARCH_PROTOCOL *This,
IN UINTN UserPageTable,
IN EFI_PHYSICAL_ADDRESS BaseAddress,
IN UINT64 Length,
IN UINT64 EfiAttributes
)
{
EFI_STATUS Status;
UINTN ArmAttributes;
UINTN RegionBaseAddress;
UINTN RegionLength;
UINTN RegionArmAttributes;
if ((BaseAddress & (SIZE_4KB - 1)) != 0) {
// Minimum granularity is SIZE_4KB (4KB on ARM)
DEBUG ((DEBUG_PAGE, "CpuSetMemoryAttributes(%lx, %lx, %lx): Minimum granularity is SIZE_4KB\n", BaseAddress, Length, EfiAttributes));
return EFI_UNSUPPORTED;
}
// Convert the 'Attribute' into ARM Attribute
ArmAttributes = EfiAttributeToArmAttribute (EfiAttributes);
// Get the region starting from 'BaseAddress' and its 'Attribute'
RegionBaseAddress = BaseAddress;
Status = GetMemoryRegion (&RegionBaseAddress, &RegionLength, &RegionArmAttributes, UserPageTable);
// Data & Instruction Caches are flushed when we set new memory attributes.
// So, we only set the attributes if the new region is different.
if (EFI_ERROR (Status) || (RegionArmAttributes != ArmAttributes) ||
((BaseAddress + Length) > (RegionBaseAddress + RegionLength)))
{
return ArmSetMemoryAttributes (BaseAddress, Length, EfiAttributes, 0, UserPageTable);
} else {
return EFI_SUCCESS;
}
}

View File

@ -107,7 +107,8 @@ GetMemoryAttributes (
Status = GetMemoryRegion ( Status = GetMemoryRegion (
&RegionAddress, &RegionAddress,
&RegionLength, &RegionLength,
&RegionAttributes &RegionAttributes,
0
); );
DEBUG (( DEBUG ((
@ -202,7 +203,7 @@ SetMemoryAttributes (
return EFI_UNSUPPORTED; return EFI_UNSUPPORTED;
} }
return ArmSetMemoryAttributes (BaseAddress, Length, Attributes, Attributes); return ArmSetMemoryAttributes (BaseAddress, Length, Attributes, Attributes, 0);
} }
/** /**
@ -263,7 +264,7 @@ ClearMemoryAttributes (
return EFI_UNSUPPORTED; return EFI_UNSUPPORTED;
} }
return ArmSetMemoryAttributes (BaseAddress, Length, 0, Attributes); return ArmSetMemoryAttributes (BaseAddress, Length, 0, Attributes, 0);
} }
EFI_MEMORY_ATTRIBUTE_PROTOCOL mMemoryAttribute = { EFI_MEMORY_ATTRIBUTE_PROTOCOL mMemoryAttribute = {

View File

@ -90,6 +90,7 @@ OpteeSharedMemoryRemap (
PhysicalAddress, PhysicalAddress,
Size, Size,
EFI_MEMORY_WB | EFI_MEMORY_XP, EFI_MEMORY_WB | EFI_MEMORY_XP,
0,
0 0
); );
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {