IN UINT64 Length\r
);\r
\r
+VOID\r
+ArmReplaceLiveTranslationEntry (\r
+ IN UINT64 *Entry,\r
+ IN UINT64 Value\r
+ );\r
+\r
#endif // __ARM_LIB__\r
INF_VERSION = 0x00010005\r
BASE_NAME = AArch64Lib\r
FILE_GUID = ef20ddf5-b334-47b3-94cf-52ff44c29138\r
- MODULE_TYPE = DXE_DRIVER\r
+ MODULE_TYPE = BASE\r
VERSION_STRING = 1.0\r
LIBRARY_CLASS = ArmLib\r
+ CONSTRUCTOR = AArch64LibConstructor\r
\r
[Sources.AARCH64]\r
AArch64Lib.c\r
\r
../Common/AArch64/ArmLibSupport.S\r
../Common/ArmLib.c\r
+ AArch64LibConstructor.c\r
\r
[Packages]\r
ArmPkg/ArmPkg.dec\r
\r
[LibraryClasses]\r
MemoryAllocationLib\r
+ CacheMaintenanceLib\r
\r
[Protocols]\r
gEfiCpuArchProtocolGuid\r
--- /dev/null
+#/* @file\r
+#\r
+# Copyright (c) 2016, Linaro Limited. All rights reserved.\r
+#\r
+# This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions of the BSD License\r
+# which accompanies this distribution. The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+#\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+#*/\r
+\r
+#include <Base.h>\r
+\r
+#include <Library/ArmLib.h>\r
+#include <Library/CacheMaintenanceLib.h>\r
+\r
+RETURN_STATUS\r
+EFIAPI\r
+AArch64LibConstructor (\r
+ VOID\r
+ )\r
+{\r
+ extern UINT32 ArmReplaceLiveTranslationEntrySize;\r
+\r
+ //\r
+ // The ArmReplaceLiveTranslationEntry () helper function may be invoked\r
+ // with the MMU off so we have to ensure that it gets cleaned to the PoC\r
+ //\r
+ WriteBackDataCacheRange (ArmReplaceLiveTranslationEntry,\r
+ ArmReplaceLiveTranslationEntrySize);\r
+\r
+ return RETURN_SUCCESS;\r
+}\r
}\r
}\r
\r
+STATIC\r
+VOID\r
+ReplaceLiveEntry (\r
+ IN UINT64 *Entry,\r
+ IN UINT64 Value\r
+ )\r
+{\r
+ if (!ArmMmuEnabled ()) {\r
+ *Entry = Value;\r
+ } else {\r
+ ArmReplaceLiveTranslationEntry (Entry, Value);\r
+ }\r
+}\r
+\r
STATIC\r
VOID\r
LookupAddresstoRootTable (\r
}\r
\r
// Fill the BlockEntry with the new TranslationTable\r
- *BlockEntry = ((UINTN)TranslationTable & TT_ADDRESS_MASK_DESCRIPTION_TABLE) | TableAttributes | TT_TYPE_TABLE_ENTRY;\r
+ ReplaceLiveEntry (BlockEntry,\r
+ ((UINTN)TranslationTable & TT_ADDRESS_MASK_DESCRIPTION_TABLE) | TableAttributes | TT_TYPE_TABLE_ENTRY);\r
}\r
} else {\r
if (IndexLevel != PageLevel) {\r
GCC_ASM_EXPORT (ArmWriteHcr)\r
GCC_ASM_EXPORT (ArmReadHcr)\r
GCC_ASM_EXPORT (ArmReadCurrentEL)\r
+GCC_ASM_EXPORT (ArmReplaceLiveTranslationEntry)\r
+GCC_ASM_EXPORT (ArmReplaceLiveTranslationEntrySize)\r
\r
.set CTRL_M_BIT, (1 << 0)\r
.set CTRL_A_BIT, (1 << 1)\r
mrs x0, CurrentEL\r
ret\r
\r
+\r
+ .macro __replace_entry, el\r
+\r
+ // disable the MMU\r
+ mrs x8, sctlr_el\el\r
+ bic x9, x8, #CTRL_M_BIT\r
+ msr sctlr_el\el, x9\r
+ isb\r
+\r
+ // write updated entry\r
+ str x1, [x0]\r
+\r
+ // invalidate again to get rid of stale clean cachelines that may\r
+ // have been filled speculatively since the last invalidate\r
+ dmb sy\r
+ dc ivac, x0\r
+\r
+ // flush the TLBs\r
+ .if \el == 1\r
+ tlbi vmalle1\r
+ .else\r
+ tlbi alle\el\r
+ .endif\r
+ dsb sy\r
+\r
+ // re-enable the MMU\r
+ msr sctlr_el\el, x8\r
+ isb\r
+ .endm\r
+\r
+//VOID\r
+//ArmReplaceLiveTranslationEntry (\r
+// IN UINT64 *Entry,\r
+// IN UINT64 Value\r
+// )\r
+ASM_PFX(ArmReplaceLiveTranslationEntry):\r
+\r
+ // disable interrupts\r
+ mrs x2, daif\r
+ msr daifset, #0xf\r
+ isb\r
+\r
+ // clean and invalidate first so that we don't clobber\r
+ // adjacent entries that are dirty in the caches\r
+ dc civac, x0\r
+ dsb ish\r
+\r
+ EL1_OR_EL2_OR_EL3(x3)\r
+1:__replace_entry 1\r
+ b 4f\r
+2:__replace_entry 2\r
+ b 4f\r
+3:__replace_entry 3\r
+\r
+4:msr daif, x2\r
+ ret\r
+\r
+ASM_PFX(ArmReplaceLiveTranslationEntrySize):\r
+ .long . - ArmReplaceLiveTranslationEntry\r
+\r
ASM_FUNCTION_REMOVE_IF_UNREFERENCED\r