summaryrefslogtreecommitdiff
path: root/UefiCpuPkg
diff options
context:
space:
mode:
authorJian J Wang <jian.j.wang@intel.com>2018-02-06 10:08:25 +0800
committerRuiyu Ni <ruiyu.ni@intel.com>2018-02-08 12:47:17 +0800
commit890d9ee554b793633114a00971aeafba9e35b04f (patch)
treee58f83da94af95fd1b7e6d6257bf066b1bd7e837 /UefiCpuPkg
parent7823611cdad37cc3821526d325bc120f322a2d96 (diff)
downloadedk2-890d9ee554b793633114a00971aeafba9e35b04f.zip
edk2-890d9ee554b793633114a00971aeafba9e35b04f.tar.gz
edk2-890d9ee554b793633114a00971aeafba9e35b04f.tar.bz2
UefiCpuPkg/PiSmmCpuDxeSmm: fix infinite loop issue in SMM profile
> v2: > Reduce the number of page to update/restore from 3 to 2 because DF > has no effect in this issue. The infinite loop is caused by the memory instruction, such as "rep mov", operating on memory block crossing boundary of NON-PRESENT pages. Because the address triggering page fault set in CR2 will be in the first page, SmmProfilePFHandler() will only change the first page into PRESENT. The page following will be still in NON-PRESENT status. Since SmmProfilePFHandler() will setup single-step trap for the instruction causing #PF, when the handler returns back to the instruction and re-execute it, both #DB and #PF will be triggered because the instruction wants to access both first and second page but only first page is PRESENT. Normally #DB exception will be handled first and its handler will change first page back to NON-PRESENT status. Then #PF is handled and its handler will change first page to PRESENT status again and setup another single-step for the instruction triggering #PF. Then the whole system falls into an infinite loop and the memory operation will never move on. This patch fix above situation by always changing 2 pages to PRESENT status instead of just 1 page. Those 2 pages include the page causing #PF and the page after it. Cc: Eric Dong <eric.dong@intel.com> Cc: Laszlo Ersek <lersek@redhat.com> Cc: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Jiewen Yao <jiewen.yao@intel.com> Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Jian J Wang <jian.j.wang@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
Diffstat (limited to 'UefiCpuPkg')
-rw-r--r--UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfile.c21
1 files changed, 17 insertions, 4 deletions
diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfile.c b/UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfile.c
index 9588eaf..c90167f 100644
--- a/UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfile.c
+++ b/UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfile.c
@@ -1302,6 +1302,8 @@ SmmProfilePFHandler (
{
UINT64 *PageTable;
UINT64 PFAddress;
+ UINT64 RestoreAddress;
+ UINTN RestorePageNumber;
UINTN CpuIndex;
UINTN Index;
UINT64 InstructionAddress;
@@ -1331,10 +1333,21 @@ SmmProfilePFHandler (
PFAddress = AsmReadCr2 ();
CpuIndex = GetCpuIndex ();
- if (PFAddress <= 0xFFFFFFFF) {
- RestorePageTableBelow4G (PageTable, PFAddress, CpuIndex, ErrorCode);
- } else {
- RestorePageTableAbove4G (PageTable, PFAddress, CpuIndex, ErrorCode, &IsValidPFAddress);
+ //
+ // Memory operation cross pages, like "rep mov" instruction, will cause
+ // infinite loop between this and Debug Trap handler. We have to make sure
+ // that current page and the page followed are both in PRESENT state.
+ //
+ RestorePageNumber = 2;
+ RestoreAddress = PFAddress;
+ while (RestorePageNumber > 0) {
+ if (RestoreAddress <= 0xFFFFFFFF) {
+ RestorePageTableBelow4G (PageTable, RestoreAddress, CpuIndex, ErrorCode);
+ } else {
+ RestorePageTableAbove4G (PageTable, RestoreAddress, CpuIndex, ErrorCode, &IsValidPFAddress);
+ }
+ RestoreAddress += EFI_PAGE_SIZE;
+ RestorePageNumber--;
}
if (!IsValidPFAddress) {