From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received-SPF: Pass (sender SPF authorized) identity=mailfrom; client-ip=134.134.136.31; helo=mga06.intel.com; envelope-from=jordan.l.justen@intel.com; receiver=edk2-devel@lists.01.org Received: from mga06.intel.com (mga06.intel.com [134.134.136.31]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id D8B092194EB7F for ; Sun, 17 Feb 2019 20:12:00 -0800 (PST) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga005.fm.intel.com ([10.253.24.32]) by orsmga104.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 17 Feb 2019 20:12:00 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.58,383,1544515200"; d="scan'208";a="321197983" Received: from mmdandap-mobl1.amr.corp.intel.com (HELO jljusten-skl.amr.corp.intel.com) ([10.254.8.66]) by fmsmga005.fm.intel.com with ESMTP; 17 Feb 2019 20:12:00 -0800 From: Jordan Justen To: edk2-devel@lists.01.org Cc: Jordan Justen , Jian J Wang , Hao Wu , Ray Ni , Star Zeng Date: Sun, 17 Feb 2019 20:11:38 -0800 Message-Id: <20190218041141.21363-8-jordan.l.justen@intel.com> X-Mailer: git-send-email 2.20.0.rc1 In-Reply-To: <20190218041141.21363-1-jordan.l.justen@intel.com> References: <20190218041141.21363-1-jordan.l.justen@intel.com> MIME-Version: 1.0 Subject: [PATCH 07/10] MdeModePkg/Core/Pei: Add code path to allow assembly temp-ram migration X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 18 Feb 2019 04:12:01 -0000 Content-Transfer-Encoding: 8bit There is potential problem with PEI Core's usage of the TemporaryRamMigration PPI. When the TemporaryRamMigration function is called, it returns to C based code after changing the stack to the new permanent memory copy of the stack. But, the C compiler may have stored pointers to addresses on the old temporary RAM stack. Even though the stack is copied to a new permanent memory location, it is not possible to adjust all pointers that the C compiler may have added within the stack data. For this reason, it is only safe to return to assembly code after calling TemporaryRamMigration. The assembly code can make sure the old temporary RAM stack is not used before calling a new C function. When the new function is called, it will use the new permanent memory stack, so it is safe to use C code again. This code adds new function named PeiTemporaryRamMigration which can be implemented in assembly code as described above. PeiTemporaryRamMigration must call the TemporaryRamMigration function, and then calls a new C PeiTemporaryRamMigrated function. This guanantees PeiTemporaryRamMigrated will only use the permanent memory stack. For now, this patch should have no effect, since it still uses C to implement PeiTemporaryRamMigration. But, PeiTemporaryRamMigration can then be changed into an assembly code function to fix the issue described above. Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Jordan Justen Cc: Jian J Wang Cc: Hao Wu Cc: Ray Ni Cc: Star Zeng --- MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c | 59 ++++++++++++------- .../Pei/Dispatcher/TemporaryRamMigration.c | 52 ++++++++++++++++ MdeModulePkg/Core/Pei/PeiMain.h | 52 ++++++++++++++++ MdeModulePkg/Core/Pei/PeiMain.inf | 1 + 4 files changed, 143 insertions(+), 21 deletions(-) create mode 100644 MdeModulePkg/Core/Pei/Dispatcher/TemporaryRamMigration.c diff --git a/MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c b/MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c index 68670f43e0..8e3fa161dd 100644 --- a/MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c +++ b/MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c @@ -688,6 +688,7 @@ PeiCheckAndSwitchStack ( EFI_PHYSICAL_ADDRESS TempBase2; UINTN TempSize2; UINTN Index; + PEI_CORE_TEMPORARY_RAM_TRANSITION TempRamTransitionData; PeiServices = (CONST EFI_PEI_SERVICES **) &Private->Ps; @@ -822,30 +823,20 @@ PeiCheckAndSwitchStack ( Private = (PEI_CORE_INSTANCE *)((UINTN)(VOID *)Private - StackOffset); } - // - // Temporary Ram Support PPI is provided by platform, it will copy - // temporary memory to permanent memory and do stack switching. - // After invoking Temporary Ram Support PPI, the following code's - // stack is in permanent memory. - // - TemporaryRamSupportPpi->TemporaryRamMigration ( - PeiServices, - TemporaryRamBase, - (EFI_PHYSICAL_ADDRESS)(UINTN)(TopOfNewStack - TemporaryStackSize), - TemporaryRamSize - ); - - // - // Migrate memory pages allocated in pre-memory phase. - // It could not be called before calling TemporaryRamSupportPpi->TemporaryRamMigration() - // as the migrated memory pages may be overridden by TemporaryRamSupportPpi->TemporaryRamMigration(). - // - MigrateMemoryPages (Private, TRUE); + TempRamTransitionData.TemporaryRamMigration = + TemporaryRamSupportPpi->TemporaryRamMigration; + TempRamTransitionData.PeiServices = PeiServices; + TempRamTransitionData.TemporaryMemoryBase = TemporaryRamBase; + TempRamTransitionData.PermanentMemoryBase = + (EFI_PHYSICAL_ADDRESS)(UINTN)(TopOfNewStack - TemporaryStackSize); + TempRamTransitionData.CopySize = TemporaryRamSize; + TempRamTransitionData.Private = Private; + TempRamTransitionData.SecCoreData = SecCoreData; // - // Entry PEI Phase 2 + // Migrate Temporary RAM and enter PEI Phase 2 // - PeiCore (SecCoreData, NULL, Private); + PeiTemporaryRamMigration(&TempRamTransitionData); } else { // // Migrate memory pages allocated in pre-memory phase. @@ -958,6 +949,32 @@ PeiCheckAndSwitchStack ( } } +VOID +EFIAPI +PeiTemporaryRamMigrated ( + IN VOID *CallbackContext + ) +{ + PEI_CORE_TEMPORARY_RAM_TRANSITION *TempRamTransitionData = + (PEI_CORE_TEMPORARY_RAM_TRANSITION*)CallbackContext; + + // + // Migrate memory pages allocated in pre-memory phase. + // It could not be called before calling TemporaryRamSupportPpi->TemporaryRamMigration() + // as the migrated memory pages may be overridden by TemporaryRamSupportPpi->TemporaryRamMigration(). + // + MigrateMemoryPages (TempRamTransitionData->Private, TRUE); + + // + // Entry PEI Phase 2 + // + PeiCore ( + TempRamTransitionData->SecCoreData, + NULL, + TempRamTransitionData->Private + ); +} + /** Conduct PEIM dispatch. diff --git a/MdeModulePkg/Core/Pei/Dispatcher/TemporaryRamMigration.c b/MdeModulePkg/Core/Pei/Dispatcher/TemporaryRamMigration.c new file mode 100644 index 0000000000..9e9d0854ed --- /dev/null +++ b/MdeModulePkg/Core/Pei/Dispatcher/TemporaryRamMigration.c @@ -0,0 +1,52 @@ +/** @file + EFI PEI Core temporary RAM migration + +Copyright (c) 2018, Intel Corporation. All rights reserved.
+ +This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "PeiMain.h" + +/** + To call the TemporaryRamMigration PPI, we might not be able to rely + on C code's handling of the stack. In these cases we use an assembly + function to make sure the old stack is not used after the + TemporaryRamMigration PPI is used. + + After calling the TemporaryRamMigration PPI, this function calls + PeiTemporaryRamMigrated. + + This C based function provides an implementation that may work for + some architectures. + + @param TempRamTransitionData +**/ +VOID +EFIAPI +PeiTemporaryRamMigration ( + IN PEI_CORE_TEMPORARY_RAM_TRANSITION *TempRamTransitionData + ) +{ + // + // Temporary Ram Support PPI is provided by platform, it will copy + // temporary memory to permanent memory and do stack switching. + // After invoking Temporary Ram Support PPI, the following code's + // stack is in permanent memory. + // + TempRamTransitionData->TemporaryRamMigration ( + TempRamTransitionData->PeiServices, + TempRamTransitionData->TemporaryMemoryBase, + TempRamTransitionData->PermanentMemoryBase, + TempRamTransitionData->CopySize + ); + + PeiTemporaryRamMigrated(TempRamTransitionData); +} diff --git a/MdeModulePkg/Core/Pei/PeiMain.h b/MdeModulePkg/Core/Pei/PeiMain.h index a61da73fd8..2d48f8d5d1 100644 --- a/MdeModulePkg/Core/Pei/PeiMain.h +++ b/MdeModulePkg/Core/Pei/PeiMain.h @@ -1871,4 +1871,56 @@ PeiReinitializeFv ( IN PEI_CORE_INSTANCE *PrivateData ); +#pragma pack(1) +typedef struct { + /** + These fields are used by PeiTemporaryRamMigration to call the + TemporaryRamMigration PPI. + **/ + TEMPORARY_RAM_MIGRATION TemporaryRamMigration; + CONST EFI_PEI_SERVICES **PeiServices; + EFI_PHYSICAL_ADDRESS TemporaryMemoryBase; + EFI_PHYSICAL_ADDRESS PermanentMemoryBase; + UINTN CopySize; + + /** + These fields are used by PeiTemporaryRamMigrated. + **/ + PEI_CORE_INSTANCE *Private; + CONST EFI_SEC_PEI_HAND_OFF *SecCoreData; +} PEI_CORE_TEMPORARY_RAM_TRANSITION; +#pragma pack() + +/** + To call the TemporaryRamMigration PPI, we might not be able to rely + on C code's handling of the stack. In these cases we use an assembly + function to make sure the old stack is not used after the + TemporaryRamMigration PPI is used. + + After calling the TemporaryRamMigration PPI, this function calls + PeiTemporaryRamMigrated. + + @param TempRamTransitionData +**/ +VOID +EFIAPI +PeiTemporaryRamMigration ( + IN PEI_CORE_TEMPORARY_RAM_TRANSITION *TempRamTransitionData + ); + +/** + After PeiTemporaryRamMigration has called the TemporaryRamMigration + PPI, it will call this C based function to allow PEI to continue + after the migration using the new stack in the migrated RAM. + + @param CallbackContext Pointer to PEI_CORE_TEMPORARY_RAM_TRANSITION + data. +**/ +VOID +EFIAPI +PeiTemporaryRamMigrated ( + IN VOID *CallbackContext + ); + + #endif diff --git a/MdeModulePkg/Core/Pei/PeiMain.inf b/MdeModulePkg/Core/Pei/PeiMain.inf index 5bab2aab8c..94b26b3572 100644 --- a/MdeModulePkg/Core/Pei/PeiMain.inf +++ b/MdeModulePkg/Core/Pei/PeiMain.inf @@ -45,6 +45,7 @@ FwVol/FwVol.c FwVol/FwVol.h Dispatcher/Dispatcher.c + Dispatcher/TemporaryRamMigration.c Dependency/Dependency.c Dependency/Dependency.h BootMode/BootMode.c -- 2.20.0.rc1