public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: Jian J Wang <jian.j.wang@intel.com>
To: edk2-devel@lists.01.org
Cc: Eric Dong <eric.dong@intel.com>, Laszlo Ersek <lersek@redhat.com>,
	Ruiyu Ni <ruiyu.ni@intel.com>, Jiewen Yao <jiewen.yao@intel.com>
Subject: [PATCH] UefiCpuPkg/PiSmmCpuDxeSmm: fix infinite loop issue in SMM profile
Date: Tue,  6 Feb 2018 11:02:06 +0800	[thread overview]
Message-ID: <20180206030206.112-1-jian.j.wang@intel.com> (raw)

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 3 pages to PRESENT
status instead of just 1 page. Those 3 pages include the page before
and after the page causing #PF because memory operation instruction
may have direction flag (DF) set or cleared.

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>
---
 UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfile.c | 22 ++++++++++++++++++----
 1 file changed, 18 insertions(+), 4 deletions(-)

diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfile.c b/UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfile.c
index 9588eaf029..8cdfc82a92 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,22 @@ 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. Since the direction
+  // of memory operation is unknown, the pages before and after current page
+  // should be taken into account as well.
+  //
+  RestorePageNumber = 3;
+  RestoreAddress = PFAddress - EFI_PAGE_SIZE;
+  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) {
-- 
2.14.1.windows.1



             reply	other threads:[~2018-02-06  2:56 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-02-06  3:02 Jian J Wang [this message]
2018-02-06  6:22 ` [PATCH] UefiCpuPkg/PiSmmCpuDxeSmm: fix infinite loop issue in SMM profile Yao, Jiewen
2018-02-06  6:50   ` Wang, Jian J

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20180206030206.112-1-jian.j.wang@intel.com \
    --to=devel@edk2.groups.io \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox