summaryrefslogtreecommitdiffstats
path: root/UefiCpuPkg
diff options
context:
space:
mode:
authorLaszlo Ersek <lersek@redhat.com>2013-12-13 03:22:33 +0000
committerlzeng14 <lzeng14@6f19259b-4bc3-4df7-8a09-765794883524>2013-12-13 03:22:33 +0000
commitf98f5ec304ec22d3bbc8bee2a78d22fea28e1321 (patch)
treee5b7bb1e3f142242e7804851ff29394d776f64bc /UefiCpuPkg
parentddc0be58660a396471e1035e2d45d2b4a33ebd9f (diff)
downloadedk2-f98f5ec304ec22d3bbc8bee2a78d22fea28e1321.tar.gz
edk2-f98f5ec304ec22d3bbc8bee2a78d22fea28e1321.tar.bz2
edk2-f98f5ec304ec22d3bbc8bee2a78d22fea28e1321.zip
UefiCpuPkg: S3Resume2Pei: align return stacks explicitly
S3RestoreConfig2() can optionally stack-switch to the SMM S3 Resume Entry Point and ask it to transfer to S3ResumeExecuteBootScript(). Similarly, S3ResumeExecuteBootScript() stack-switches explicitly to the boot script executor, and asks it to transfer to S3ResumeBootOs(). Currently the stack pointers specified for the SMM S3 Resume Entry Point and the boot script executor to use for returning are derived from addresses of the first local variables in S3RestoreConfig2() and S3ResumeExecuteBootScript(), respectively. Since (theoretically) the stack grows down as local variables are defined and functions are called, the idea is presumably to allow the respective callee to overwrite the caller's local variables. (The callees in question can never return normally, only by explicit stack switching.) Taking the address of "Status" is less portable than optimal however. Compilers are free to juggle local variables at build time as they please, including order and alignment on the stack. For example, when the code is built for 64-bit PEI with gcc-4.8.2, the address of "Status" trips up the alignment assertion in SwitchStack(). Let's align the address of "Status" down to CPU_STACK_ALIGNMENT explicitly. If a compiler ensures such alignment and places "Status" at the highest address automatically, then this change has no effect. Otherwise, we'll prepare ReturnStackPointer values that (a) are correctly aligned, (b) preserve the same amount or more (but never less) from the caller's local variables than before, which should be safe. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Laszlo Ersek <lersek@redhat.com> Reviewed by: Jiewen Yao <Jiewen.Yao@intel.com> git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@14977 6f19259b-4bc3-4df7-8a09-765794883524
Diffstat (limited to 'UefiCpuPkg')
-rw-r--r--UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume.c14
1 files changed, 12 insertions, 2 deletions
diff --git a/UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume.c b/UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume.c
index e57398b504..814e29fee1 100644
--- a/UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume.c
+++ b/UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume.c
@@ -48,6 +48,16 @@
#include <Library/LockBoxLib.h>
#include <IndustryStandard/Acpi.h>
+/**
+ This macro aligns the address of a variable with auto storage
+ duration down to CPU_STACK_ALIGNMENT.
+
+ Since the stack grows downward, the result preserves more of the
+ stack than the original address (or the same amount), not less.
+**/
+#define STACK_ALIGN_DOWN(Ptr) \
+ ((UINTN)(Ptr) & ~(UINTN)(CPU_STACK_ALIGNMENT - 1))
+
#pragma pack(1)
typedef union {
struct {
@@ -846,7 +856,7 @@ S3ResumeExecuteBootScript (
DEBUG (( EFI_D_ERROR, "PeiS3ResumeState - %x\r\n", PeiS3ResumeState));
PeiS3ResumeState->ReturnCs = 0x10;
PeiS3ResumeState->ReturnEntryPoint = (EFI_PHYSICAL_ADDRESS)(UINTN)S3ResumeBootOs;
- PeiS3ResumeState->ReturnStackPointer = (EFI_PHYSICAL_ADDRESS)(UINTN)&Status;
+ PeiS3ResumeState->ReturnStackPointer = (EFI_PHYSICAL_ADDRESS)STACK_ALIGN_DOWN (&Status);
//
// Save IDT
//
@@ -1038,7 +1048,7 @@ S3RestoreConfig2 (
SmmS3ResumeState->ReturnEntryPoint = (EFI_PHYSICAL_ADDRESS)(UINTN)S3ResumeExecuteBootScript;
SmmS3ResumeState->ReturnContext1 = (EFI_PHYSICAL_ADDRESS)(UINTN)AcpiS3Context;
SmmS3ResumeState->ReturnContext2 = (EFI_PHYSICAL_ADDRESS)(UINTN)EfiBootScriptExecutorVariable;
- SmmS3ResumeState->ReturnStackPointer = (EFI_PHYSICAL_ADDRESS)(UINTN)&Status;
+ SmmS3ResumeState->ReturnStackPointer = (EFI_PHYSICAL_ADDRESS)STACK_ALIGN_DOWN (&Status);
DEBUG (( EFI_D_ERROR, "SMM S3 Signature = %x\n", SmmS3ResumeState->Signature));
DEBUG (( EFI_D_ERROR, "SMM S3 Stack Base = %x\n", SmmS3ResumeState->SmmS3StackBase));