summaryrefslogtreecommitdiffstats
path: root/UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmmFuncsArch.c
diff options
context:
space:
mode:
authorJiewen Yao <jiewen.yao@intel.com>2016-11-23 21:24:32 +0800
committerJiewen Yao <jiewen.yao@intel.com>2016-12-07 13:13:55 +0800
commite4435f710cea2d2f10cd7343d545920867780086 (patch)
tree4ba5de7b66f9ba6b67464ec2794bb53153d72340 /UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmmFuncsArch.c
parentf1afa0a92d12ed307cb4f7189bcc7ec6abf8e90a (diff)
downloadedk2-e4435f710cea2d2f10cd7343d545920867780086.tar.gz
edk2-e4435f710cea2d2f10cd7343d545920867780086.tar.bz2
edk2-e4435f710cea2d2f10cd7343d545920867780086.zip
UefiCpuPkg/PiSmmCpu: Fixed #double fault on #page fault.
This patch fixes https://bugzilla.tianocore.org/show_bug.cgi?id=246 Previously, when SMM exception happens after EndOfDxe, with StackGuard enabled on IA32, the #double fault exception is reported instead of #page fault. Root cause is below: Current EDKII SMM page protection will lock GDT. If IA32 stack guard is enabled, the page fault handler will do task switch. This task switch need write busy flag in GDT, and write TSS. However, the GDT and TSS is locked at that time, so the double fault happens. We decide to not lock GDT for IA32 StackGuard enabled. This issue does not exist on X64, or IA32 without StackGuard. Cc: Laszlo Ersek <lersek@redhat.com> Cc: Jeff Fan <jeff.fan@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Jiewen Yao <jiewen.yao@intel.com> Reviewed-by: Jeff Fan <jeff.fan@intel.com> Regression-tested-by: Laszlo Ersek <lersek@redhat.com>
Diffstat (limited to 'UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmmFuncsArch.c')
-rw-r--r--UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmmFuncsArch.c49
1 files changed, 48 insertions, 1 deletions
diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmmFuncsArch.c b/UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmmFuncsArch.c
index 9fc00c1578..9d26e44a9a 100644
--- a/UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmmFuncsArch.c
+++ b/UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmmFuncsArch.c
@@ -96,6 +96,54 @@ InitGdt (
}
/**
+ This function sets GDT/IDT buffer to be RO and XP.
+**/
+VOID
+PatchGdtIdtMap (
+ VOID
+ )
+{
+ EFI_PHYSICAL_ADDRESS BaseAddress;
+ UINTN Size;
+
+ //
+ // GDT
+ //
+ DEBUG ((DEBUG_INFO, "PatchGdtIdtMap - GDT:\n"));
+
+ BaseAddress = mGdtBuffer;
+ Size = ALIGN_VALUE(mGdtBufferSize, SIZE_4KB);
+ SmmSetMemoryAttributes (
+ BaseAddress,
+ Size,
+ EFI_MEMORY_RO
+ );
+ SmmSetMemoryAttributes (
+ BaseAddress,
+ Size,
+ EFI_MEMORY_XP
+ );
+
+ //
+ // IDT
+ //
+ DEBUG ((DEBUG_INFO, "PatchGdtIdtMap - IDT:\n"));
+
+ BaseAddress = gcSmiIdtr.Base;
+ Size = ALIGN_VALUE(gcSmiIdtr.Limit + 1, SIZE_4KB);
+ SmmSetMemoryAttributes (
+ BaseAddress,
+ Size,
+ EFI_MEMORY_RO
+ );
+ SmmSetMemoryAttributes (
+ BaseAddress,
+ Size,
+ EFI_MEMORY_XP
+ );
+}
+
+/**
Get Protected mode code segment from current GDT table.
@return Protected mode code segment value.
@@ -154,4 +202,3 @@ TransferApToSafeState (
ASSERT (FALSE);
}
-