--- /dev/null
+/**@file\r
+ Install a callback to clear cache on all processors.\r
+ This is for conformance with the TCG "Platform Reset Attack Mitigation\r
+ Specification". Because clearing the CPU caches at boot doesn't impact\r
+ performance significantly, do it unconditionally, for simplicity's\r
+ sake.\r
+\r
+ Copyright (C) 2018, Red Hat, Inc.\r
+\r
+ This program and the accompanying materials are licensed and made available\r
+ under the terms and conditions of the BSD License which accompanies this\r
+ 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, WITHOUT\r
+ WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+**/\r
+\r
+#include <Library/CacheMaintenanceLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/PeiServicesLib.h>\r
+#include <Ppi/MpServices.h>\r
+\r
+#include "Platform.h"\r
+\r
+/**\r
+ Invalidate data & instruction caches.\r
+ All APs execute this function in parallel. The BSP executes the function\r
+ separately.\r
+\r
+ @param[in,out] WorkSpace Pointer to the input/output argument workspace\r
+ shared by all processors.\r
+**/\r
+STATIC\r
+VOID\r
+EFIAPI\r
+ClearCache (\r
+ IN OUT VOID *WorkSpace\r
+ )\r
+{\r
+ WriteBackInvalidateDataCache ();\r
+ InvalidateInstructionCache ();\r
+}\r
+\r
+/**\r
+ Notification function called when EFI_PEI_MP_SERVICES_PPI becomes available.\r
+\r
+ @param[in] PeiServices Indirect reference to the PEI Services Table.\r
+ @param[in] NotifyDescriptor Address of the notification descriptor data\r
+ structure.\r
+ @param[in] Ppi Address of the PPI that was installed.\r
+\r
+ @return Status of the notification. The status code returned from this\r
+ function is ignored.\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+ClearCacheOnMpServicesAvailable (\r
+ IN EFI_PEI_SERVICES **PeiServices,\r
+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,\r
+ IN VOID *Ppi\r
+ )\r
+{\r
+ EFI_PEI_MP_SERVICES_PPI *MpServices;\r
+ EFI_STATUS Status;\r
+\r
+ DEBUG ((DEBUG_INFO, "%a: %a\n", gEfiCallerBaseName, __FUNCTION__));\r
+\r
+ //\r
+ // Clear cache on all the APs in parallel.\r
+ //\r
+ MpServices = Ppi;\r
+ Status = MpServices->StartupAllAPs (\r
+ (CONST EFI_PEI_SERVICES **)PeiServices,\r
+ MpServices,\r
+ ClearCache, // Procedure\r
+ FALSE, // SingleThread\r
+ 0, // TimeoutInMicroSeconds: inf.\r
+ NULL // ProcedureArgument\r
+ );\r
+ if (EFI_ERROR (Status) && Status != EFI_NOT_STARTED) {\r
+ DEBUG ((DEBUG_ERROR, "%a: StartupAllAps(): %r\n", __FUNCTION__, Status));\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Now clear cache on the BSP too.\r
+ //\r
+ ClearCache (NULL);\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+//\r
+// Notification object for registering the callback, for when\r
+// EFI_PEI_MP_SERVICES_PPI becomes available.\r
+//\r
+STATIC CONST EFI_PEI_NOTIFY_DESCRIPTOR mMpServicesNotify = {\r
+ EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | // Flags\r
+ EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,\r
+ &gEfiPeiMpServicesPpiGuid, // Guid\r
+ ClearCacheOnMpServicesAvailable // Notify\r
+};\r
+\r
+VOID\r
+InstallClearCacheCallback (\r
+ VOID\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ Status = PeiServicesNotifyPpi (&mMpServicesNotify);\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((DEBUG_ERROR, "%a: failed to set up MP Services callback: %r\n",\r
+ __FUNCTION__, Status));\r
+ }\r
+}\r