Move Gdt initialization from InitializeMpServiceData() to CPU Arch specific 
function.
We create SmmFuncsArch.c for hold CPU specific function, so that
EFI_IMAGE_MACHINE_TYPE_SUPPORTED(EFI_IMAGE_MACHINE_X64) can be removed.

For IA32 version, we always allocate new page for GDT entry, for easy 
maintenance.
For X64 version, we fixed TssBase in GDT entry to make sure TSS data is correct.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Yao, Jiewen <[email protected]>
Cc: Fan, Jeff <[email protected]>
Cc: Kinney, Michael D <[email protected]>
---
 UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/SmmFuncsArch.c | 96 +++++++++++++++++++++++++++
 UefiCpuPkg/PiSmmCpuDxeSmm/MpService.c         | 82 ++---------------------
 UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h    | 15 +++++
 UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf  |  2 +
 UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmmFuncsArch.c  | 70 +++++++++++++++++++
 5 files changed, 187 insertions(+), 78 deletions(-)
 create mode 100644 UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/SmmFuncsArch.c
 create mode 100644 UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmmFuncsArch.c

diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/SmmFuncsArch.c 
b/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/SmmFuncsArch.c
new file mode 100644
index 0000000..545b534
--- /dev/null
+++ b/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/SmmFuncsArch.c
@@ -0,0 +1,96 @@
+/** @file
+  SMM CPU misc functions for Ia32 arch specific.
+  
+Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
+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 "PiSmmCpuDxeSmm.h"
+
+/**
+  Initialize Gdt for all processors.
+  
+  @param[in]   Cr3          CR3 value.
+  @param[out]  GdtStepSize  The step size for GDT table.
+
+  @return GdtBase for processor 0.
+          GdtBase for processor X is: GdtBase + (GdtStepSize * X)
+**/
+VOID *
+InitGdt (
+  IN  UINTN  Cr3,
+  OUT UINTN  *GdtStepSize
+  )
+{
+  UINTN                     Index;
+  IA32_SEGMENT_DESCRIPTOR   *GdtDescriptor;
+  UINTN                     TssBase;
+  UINTN                     GdtTssTableSize;
+  UINT8                     *GdtTssTables;
+  UINTN                     GdtTableStepSize;
+
+  if (FeaturePcdGet (PcdCpuSmmStackGuard)) {
+    //
+    // For IA32 SMM, if SMM Stack Guard feature is enabled, we use 2 TSS.
+    // in this case, we allocate separate GDT/TSS for each CPUs to avoid TSS 
load contention
+    // on each SMI entry.
+    //
+
+    //
+    // Enlarge GDT to contain 2 TSS descriptors
+    //
+    gcSmiGdtr.Limit += (UINT16)(2 * sizeof (IA32_SEGMENT_DESCRIPTOR));
+
+    GdtTssTableSize = (gcSmiGdtr.Limit + 1 + TSS_SIZE * 2 + 7) & ~7; // 8 
bytes aligned
+    GdtTssTables = (UINT8*)AllocatePages (EFI_SIZE_TO_PAGES (GdtTssTableSize * 
gSmmCpuPrivate->SmmCoreEntryContext.NumberOfCpus));
+    ASSERT (GdtTssTables != NULL);
+    GdtTableStepSize = GdtTssTableSize;
+
+    for (Index = 0; Index < gSmmCpuPrivate->SmmCoreEntryContext.NumberOfCpus; 
Index++) {
+      CopyMem (GdtTssTables + GdtTableStepSize * Index, 
(VOID*)(UINTN)gcSmiGdtr.Base, gcSmiGdtr.Limit + 1 + TSS_SIZE * 2);
+      //
+      // Fixup TSS descriptors
+      //
+      TssBase = (UINTN)(GdtTssTables + GdtTableStepSize * Index + 
gcSmiGdtr.Limit + 1);
+      GdtDescriptor = (IA32_SEGMENT_DESCRIPTOR *)(TssBase) - 2;
+      GdtDescriptor->Bits.BaseLow = (UINT16)TssBase;
+      GdtDescriptor->Bits.BaseMid = (UINT8)(TssBase >> 16);
+      GdtDescriptor->Bits.BaseHigh = (UINT8)(TssBase >> 24);
+
+      TssBase += TSS_SIZE;
+      GdtDescriptor++;
+      GdtDescriptor->Bits.BaseLow = (UINT16)TssBase;
+      GdtDescriptor->Bits.BaseMid = (UINT8)(TssBase >> 16);
+      GdtDescriptor->Bits.BaseHigh = (UINT8)(TssBase >> 24);
+      //
+      // Fixup TSS segments
+      //
+      // ESP as known good stack
+      //
+      *(UINTN *)(TssBase + TSS_IA32_ESP_OFFSET) =  mSmmStackArrayBase + 
EFI_PAGE_SIZE + Index * mSmmStackSize;
+      *(UINT32 *)(TssBase + TSS_IA32_CR3_OFFSET) = Cr3;
+    }
+  } else {
+    //
+    // Just use original table, AllocatePage and copy them here to make sure 
GDTs are covered in page memory.
+    //
+    GdtTssTableSize = gcSmiGdtr.Limit + 1;
+    GdtTssTables = (UINT8*)AllocatePages (EFI_SIZE_TO_PAGES (GdtTssTableSize * 
gSmmCpuPrivate->SmmCoreEntryContext.NumberOfCpus));
+    ASSERT (GdtTssTables != NULL);
+    GdtTableStepSize = GdtTssTableSize;
+
+    for (Index = 0; Index < gSmmCpuPrivate->SmmCoreEntryContext.NumberOfCpus; 
Index++) {
+      CopyMem (GdtTssTables + GdtTableStepSize * Index, 
(VOID*)(UINTN)gcSmiGdtr.Base, gcSmiGdtr.Limit + 1);
+    }
+  }
+
+  *GdtStepSize = GdtTableStepSize;
+  return GdtTssTables;
+}
diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/MpService.c 
b/UefiCpuPkg/PiSmmCpuDxeSmm/MpService.c
index d9c5ae4..d191786 100644
--- a/UefiCpuPkg/PiSmmCpuDxeSmm/MpService.c
+++ b/UefiCpuPkg/PiSmmCpuDxeSmm/MpService.c
@@ -1152,10 +1152,7 @@ InitializeMpServiceData (
   UINTN                     Index;
   MTRR_SETTINGS             *Mtrr;
   PROCESSOR_SMM_DESCRIPTOR  *Psd;
-  UINTN                     GdtTssTableSize;
   UINT8                     *GdtTssTables;
-  IA32_SEGMENT_DESCRIPTOR   *GdtDescriptor;
-  UINTN                     TssBase;
   UINTN                     GdtTableStepSize;
 
   //
@@ -1171,71 +1168,10 @@ InitializeMpServiceData (
   //
   Cr3 = SmmInitPageTable ();
 
-  GdtTssTables    = NULL;
-  GdtTssTableSize = 0;
-  GdtTableStepSize = 0;
   //
-  // For X64 SMM, we allocate separate GDT/TSS for each CPUs to avoid TSS load 
contention
-  // on each SMI entry.
+  // Initialize GDT
   //
-  if (EFI_IMAGE_MACHINE_TYPE_SUPPORTED(EFI_IMAGE_MACHINE_X64)) {
-    GdtTssTableSize = (gcSmiGdtr.Limit + 1 + TSS_SIZE + 7) & ~7; // 8 bytes 
aligned
-    GdtTssTables = (UINT8*)AllocatePages (EFI_SIZE_TO_PAGES (GdtTssTableSize * 
gSmmCpuPrivate->SmmCoreEntryContext.NumberOfCpus));
-    ASSERT (GdtTssTables != NULL);
-    GdtTableStepSize = GdtTssTableSize;
-
-    for (Index = 0; Index < gSmmCpuPrivate->SmmCoreEntryContext.NumberOfCpus; 
Index++) {
-      CopyMem (GdtTssTables + GdtTableStepSize * Index, 
(VOID*)(UINTN)gcSmiGdtr.Base, gcSmiGdtr.Limit + 1 + TSS_SIZE);
-      if (FeaturePcdGet (PcdCpuSmmStackGuard)) {
-        //
-        // Setup top of known good stack as IST1 for each processor.
-        //
-        *(UINTN *)(GdtTssTables + GdtTableStepSize * Index + gcSmiGdtr.Limit + 
1 + TSS_X64_IST1_OFFSET) = (mSmmStackArrayBase + EFI_PAGE_SIZE + Index * 
mSmmStackSize);
-      }
-    }
-  } else if (FeaturePcdGet (PcdCpuSmmStackGuard)) {
-
-    //
-    // For IA32 SMM, if SMM Stack Guard feature is enabled, we use 2 TSS.
-    // in this case, we allocate separate GDT/TSS for each CPUs to avoid TSS 
load contention
-    // on each SMI entry.
-    //
-
-    //
-    // Enlarge GDT to contain 2 TSS descriptors
-    //
-    gcSmiGdtr.Limit += (UINT16)(2 * sizeof (IA32_SEGMENT_DESCRIPTOR));
-
-    GdtTssTableSize = (gcSmiGdtr.Limit + 1 + TSS_SIZE * 2 + 7) & ~7; // 8 
bytes aligned
-    GdtTssTables = (UINT8*)AllocatePages (EFI_SIZE_TO_PAGES (GdtTssTableSize * 
gSmmCpuPrivate->SmmCoreEntryContext.NumberOfCpus));
-    ASSERT (GdtTssTables != NULL);
-    GdtTableStepSize = GdtTssTableSize;
-
-    for (Index = 0; Index < gSmmCpuPrivate->SmmCoreEntryContext.NumberOfCpus; 
Index++) {
-      CopyMem (GdtTssTables + GdtTableStepSize * Index, 
(VOID*)(UINTN)gcSmiGdtr.Base, gcSmiGdtr.Limit + 1 + TSS_SIZE * 2);
-      //
-      // Fixup TSS descriptors
-      //
-      TssBase = (UINTN)(GdtTssTables + GdtTableStepSize * Index + 
gcSmiGdtr.Limit + 1);
-      GdtDescriptor = (IA32_SEGMENT_DESCRIPTOR *)(TssBase) - 2;
-      GdtDescriptor->Bits.BaseLow = (UINT16)TssBase;
-      GdtDescriptor->Bits.BaseMid = (UINT8)(TssBase >> 16);
-      GdtDescriptor->Bits.BaseHigh = (UINT8)(TssBase >> 24);
-
-      TssBase += TSS_SIZE;
-      GdtDescriptor++;
-      GdtDescriptor->Bits.BaseLow = (UINT16)TssBase;
-      GdtDescriptor->Bits.BaseMid = (UINT8)(TssBase >> 16);
-      GdtDescriptor->Bits.BaseHigh = (UINT8)(TssBase >> 24);
-      //
-      // Fixup TSS segments
-      //
-      // ESP as known good stack
-      //
-      *(UINTN *)(TssBase + TSS_IA32_ESP_OFFSET) =  mSmmStackArrayBase + 
EFI_PAGE_SIZE + Index * mSmmStackSize;
-      *(UINT32 *)(TssBase + TSS_IA32_CR3_OFFSET) = Cr3;
-    }
-  }
+  GdtTssTables = InitGdt (Cr3, &GdtTableStepSize);
 
   //
   // Initialize PROCESSOR_SMM_DESCRIPTOR for each CPU
@@ -1243,18 +1179,8 @@ InitializeMpServiceData (
   for (Index = 0; Index < mMaxNumberOfCpus; Index++) {
     Psd = (PROCESSOR_SMM_DESCRIPTOR *)(VOID 
*)(UINTN)(mCpuHotPlugData.SmBase[Index] + SMM_PSD_OFFSET);
     CopyMem (Psd, &gcPsd, sizeof (gcPsd));
-    if (EFI_IMAGE_MACHINE_TYPE_SUPPORTED (EFI_IMAGE_MACHINE_X64)) {
-      //
-      // For X64 SMM, set GDT to the copy allocated above.
-      //
-      Psd->SmmGdtPtr = (UINT64)(UINTN)(GdtTssTables + GdtTableStepSize * 
Index);
-    } else if (FeaturePcdGet (PcdCpuSmmStackGuard)) {
-      //
-      // For IA32 SMM, if SMM Stack Guard feature is enabled, set GDT to the 
copy allocated above.
-      //
-      Psd->SmmGdtPtr = (UINT64)(UINTN)(GdtTssTables + GdtTableStepSize * 
Index);
-      Psd->SmmGdtSize = gcSmiGdtr.Limit + 1;
-    }
+    Psd->SmmGdtPtr = (UINT64)(UINTN)(GdtTssTables + GdtTableStepSize * Index);
+    Psd->SmmGdtSize = gcSmiGdtr.Limit + 1;
 
     //
     // Install SMI handler
diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h 
b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h
index cfbf2ca..106e674 100644
--- a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h
+++ b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h
@@ -428,6 +428,21 @@ InitializeIDTSmmStackGuard (
   );
 
 /**
+  Initialize Gdt for all processors.
+  
+  @param[in]   Cr3          CR3 value.
+  @param[out]  GdtStepSize  The step size for GDT table.
+
+  @return GdtBase for processor 0.
+          GdtBase for processor X is: GdtBase + (GdtStepSize * X)
+**/
+VOID *
+InitGdt (
+  IN  UINTN  Cr3,
+  OUT UINTN  *GdtStepSize
+  );
+
+/**
 
   Register the SMM Foundation entry point.
 
diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf 
b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf
index a293a88..122318f 100644
--- a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf
+++ b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf
@@ -48,6 +48,7 @@
 [Sources.Ia32]
   Ia32/Semaphore.c
   Ia32/PageTbl.c
+  Ia32/SmmFuncsArch.c
   Ia32/SmmProfileArch.c
   Ia32/SmmProfileArch.h
   Ia32/SmmInit.asm      | MSFT
@@ -68,6 +69,7 @@
 [Sources.X64]
   X64/Semaphore.c
   X64/PageTbl.c
+  X64/SmmFuncsArch.c
   X64/SmmProfileArch.c
   X64/SmmProfileArch.h
   X64/SmmInit.asm      | MSFT
diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmmFuncsArch.c 
b/UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmmFuncsArch.c
new file mode 100644
index 0000000..b53aa45
--- /dev/null
+++ b/UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmmFuncsArch.c
@@ -0,0 +1,70 @@
+/** @file
+  SMM CPU misc functions for x64 arch specific.
+  
+Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
+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 "PiSmmCpuDxeSmm.h"
+
+/**
+  Initialize Gdt for all processors.
+  
+  @param[in]   Cr3          CR3 value.
+  @param[out]  GdtStepSize  The step size for GDT table.
+
+  @return GdtBase for processor 0.
+          GdtBase for processor X is: GdtBase + (GdtStepSize * X)
+**/
+VOID *
+InitGdt (
+  IN  UINTN  Cr3,
+  OUT UINTN  *GdtStepSize
+  )
+{
+  UINTN                     Index;
+  IA32_SEGMENT_DESCRIPTOR   *GdtDescriptor;
+  UINTN                     TssBase;
+  UINTN                     GdtTssTableSize;
+  UINT8                     *GdtTssTables;
+  UINTN                     GdtTableStepSize;
+
+  //
+  // For X64 SMM, we allocate separate GDT/TSS for each CPUs to avoid TSS load 
contention
+  // on each SMI entry.
+  //
+  GdtTssTableSize = (gcSmiGdtr.Limit + 1 + TSS_SIZE + 7) & ~7; // 8 bytes 
aligned
+  GdtTssTables = (UINT8*)AllocatePages (EFI_SIZE_TO_PAGES (GdtTssTableSize * 
gSmmCpuPrivate->SmmCoreEntryContext.NumberOfCpus));
+  ASSERT (GdtTssTables != NULL);
+  GdtTableStepSize = GdtTssTableSize;
+
+  for (Index = 0; Index < gSmmCpuPrivate->SmmCoreEntryContext.NumberOfCpus; 
Index++) {
+    CopyMem (GdtTssTables + GdtTableStepSize * Index, 
(VOID*)(UINTN)gcSmiGdtr.Base, gcSmiGdtr.Limit + 1 + TSS_SIZE);
+
+    //
+    // Fixup TSS descriptors
+    //
+    TssBase = (UINTN)(GdtTssTables + GdtTableStepSize * Index + 
gcSmiGdtr.Limit + 1);
+    GdtDescriptor = (IA32_SEGMENT_DESCRIPTOR *)(TssBase) - 2;
+    GdtDescriptor->Bits.BaseLow = (UINT16)(UINTN)TssBase;
+    GdtDescriptor->Bits.BaseMid = (UINT8)((UINTN)TssBase >> 16);
+    GdtDescriptor->Bits.BaseHigh = (UINT8)((UINTN)TssBase >> 24);
+
+    if (FeaturePcdGet (PcdCpuSmmStackGuard)) {
+      //
+      // Setup top of known good stack as IST1 for each processor.
+      //
+      *(UINTN *)(TssBase + TSS_X64_IST1_OFFSET) = (mSmmStackArrayBase + 
EFI_PAGE_SIZE + Index * mSmmStackSize);
+    }
+  }
+
+  *GdtStepSize = GdtTableStepSize;
+  return GdtTssTables;
+}
-- 
1.9.5.msysgit.0

_______________________________________________
edk2-devel mailing list
[email protected]
https://lists.01.org/mailman/listinfo/edk2-devel

Reply via email to