]> git.proxmox.com Git - mirror_edk2.git/commitdiff
UefiCpuPkg: Simplify the implementation when separate exception stacks
authorLiu, Zhiguang <Zhiguang.Liu@intel.com>
Fri, 26 Aug 2022 07:04:47 +0000 (15:04 +0800)
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Wed, 31 Aug 2022 04:23:55 +0000 (04:23 +0000)
The API of InitializeSeparateExceptionStacks is just changed before, and
makes the struct CPU_EXCEPTION_INIT_DATA an internal definition.
Furthermore, we can even remove the struct to make core simpler.

Cc: Eric Dong <eric.dong@intel.com>
Reviewed-by: Ray Ni <ray.ni@intel.com>
Cc: Rahul Kumar <rahul1.kumar@intel.com>
Signed-off-by: Zhiguang Liu <zhiguang.liu@intel.com>
UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h
UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeException.c
UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchExceptionHandler.c
UefiCpuPkg/Library/CpuExceptionHandlerLib/PeiCpuException.c
UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuExceptionHandlerLib.inf
UefiCpuPkg/Library/CpuExceptionHandlerLib/SmmCpuExceptionHandlerLib.inf
UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c
UefiCpuPkg/Library/CpuExceptionHandlerLib/Xcode5SecPeiCpuExceptionHandlerLib.inf

index 11a5624f5184d034b697413ac530d356103b61fa..4593c204a6e8ac078dac602d8ee0359a3e578b87 100644 (file)
 \r
 #define CPU_TSS_GDT_SIZE  (SIZE_2KB + CPU_TSS_DESC_SIZE + CPU_TSS_SIZE)\r
 \r
-typedef struct {\r
-  //\r
-  // The address of top of known good stack reserved for *ALL* exceptions\r
-  // listed in field StackSwitchExceptions.\r
-  //\r
-  UINTN    KnownGoodStackTop;\r
-  //\r
-  // The size of known good stack for *ONE* exception only.\r
-  //\r
-  UINTN    KnownGoodStackSize;\r
-  //\r
-  // Buffer of exception vector list for stack switch.\r
-  //\r
-  UINT8    *StackSwitchExceptions;\r
-  //\r
-  // Number of exception vectors in StackSwitchExceptions.\r
-  //\r
-  UINTN    StackSwitchExceptionNumber;\r
-  //\r
-  // Buffer of IDT table. It must be type of IA32_IDT_GATE_DESCRIPTOR.\r
-  // Normally there's no need to change IDT table size.\r
-  //\r
-  VOID     *IdtTable;\r
-  //\r
-  // Size of buffer for IdtTable.\r
-  //\r
-  UINTN    IdtTableSize;\r
-  //\r
-  // Buffer of GDT table. It must be type of IA32_SEGMENT_DESCRIPTOR.\r
-  //\r
-  VOID     *GdtTable;\r
-  //\r
-  // Size of buffer for GdtTable.\r
-  //\r
-  UINTN    GdtTableSize;\r
-  //\r
-  // Pointer to start address of descriptor of exception task gate in the\r
-  // GDT table. It must be type of IA32_TSS_DESCRIPTOR.\r
-  //\r
-  VOID     *ExceptionTssDesc;\r
-  //\r
-  // Size of buffer for ExceptionTssDesc.\r
-  //\r
-  UINTN    ExceptionTssDescSize;\r
-  //\r
-  // Buffer of task-state segment for exceptions. It must be type of\r
-  // IA32_TASK_STATE_SEGMENT.\r
-  //\r
-  VOID     *ExceptionTss;\r
-  //\r
-  // Size of buffer for ExceptionTss.\r
-  //\r
-  UINTN    ExceptionTssSize;\r
-} CPU_EXCEPTION_INIT_DATA;\r
-\r
 //\r
 // Record exception handler information\r
 //\r
@@ -345,18 +290,22 @@ CommonExceptionHandlerWorker (
   );\r
 \r
 /**\r
-  Setup separate stack for specific exceptions.\r
+  Setup separate stacks for certain exception handlers.\r
 \r
-  @param[in] StackSwitchData      Pointer to data required for setuping up\r
-                                  stack switch.\r
+  @param[in]       Buffer        Point to buffer used to separate exception stack.\r
+  @param[in, out]  BufferSize    On input, it indicates the byte size of Buffer.\r
+                                 If the size is not enough, the return status will\r
+                                 be EFI_BUFFER_TOO_SMALL, and output BufferSize\r
+                                 will be the size it needs.\r
 \r
-  @retval EFI_SUCCESS             The exceptions have been successfully\r
-                                  initialized with new stack.\r
-  @retval EFI_INVALID_PARAMETER   StackSwitchData contains invalid content.\r
+  @retval EFI_SUCCESS             The stacks are assigned successfully.\r
+  @retval EFI_BUFFER_TOO_SMALL    This BufferSize is too small.\r
+  @retval EFI_UNSUPPORTED         This function is not supported.\r
 **/\r
 EFI_STATUS\r
 ArchSetupExceptionStack (\r
-  IN CPU_EXCEPTION_INIT_DATA  *StackSwitchData\r
+  IN     VOID   *Buffer,\r
+  IN OUT UINTN  *BufferSize\r
   );\r
 \r
 /**\r
index d90c607bd71f9d2788e7b31663ec3d7fc4c565be..ee989bf0796e77f9454fc75dce40333337fce069 100644 (file)
@@ -23,9 +23,8 @@ EXCEPTION_HANDLER_DATA     mExceptionHandlerData = {
   mExternalInterruptHandlerTable\r
 };\r
 \r
-UINT8  mNewStack[CPU_STACK_SWITCH_EXCEPTION_NUMBER *\r
-                 CPU_KNOWN_GOOD_STACK_SIZE];\r
-UINT8  mNewGdt[CPU_TSS_GDT_SIZE];\r
+UINT8  mBuffer[CPU_STACK_SWITCH_EXCEPTION_NUMBER * CPU_KNOWN_GOOD_STACK_SIZE\r
+               + CPU_TSS_GDT_SIZE];\r
 \r
 /**\r
   Common exception handler.\r
@@ -123,85 +122,16 @@ InitializeSeparateExceptionStacks (
   IN OUT UINTN  *BufferSize\r
   )\r
 {\r
-  CPU_EXCEPTION_INIT_DATA  EssData;\r
-  IA32_DESCRIPTOR          Idtr;\r
-  IA32_DESCRIPTOR          Gdtr;\r
-  UINTN                    NeedBufferSize;\r
-  UINTN                    StackTop;\r
-  UINT8                    *NewGdtTable;\r
-\r
-  //\r
-  // X64 needs only one TSS of current task working for all exceptions\r
-  // because of its IST feature. IA32 needs one TSS for each exception\r
-  // in addition to current task. To simplify the code, we report the\r
-  // needed memory for IA32 case to cover both IA32 and X64 exception\r
-  // stack switch.\r
-  //\r
-  // Layout of memory needed for each processor:\r
-  //    --------------------------------\r
-  //    |            Alignment         |  (just in case)\r
-  //    --------------------------------\r
-  //    |                              |\r
-  //    |        Original GDT          |\r
-  //    |                              |\r
-  //    --------------------------------\r
-  //    |    Current task descriptor   |\r
-  //    --------------------------------\r
-  //    |                              |\r
-  //    |  Exception task descriptors  |  X ExceptionNumber\r
-  //    |                              |\r
-  //    --------------------------------\r
-  //    |  Current task-state segment  |\r
-  //    --------------------------------\r
-  //    |                              |\r
-  //    | Exception task-state segment |  X ExceptionNumber\r
-  //    |                              |\r
-  //    --------------------------------\r
-  //\r
-  AsmReadGdtr (&Gdtr);\r
+  UINTN       LocalBufferSize;\r
+  EFI_STATUS  Status;\r
+\r
   if ((Buffer == NULL) && (BufferSize == NULL)) {\r
-    SetMem (mNewGdt, sizeof (mNewGdt), 0);\r
-    StackTop    = (UINTN)mNewStack + sizeof (mNewStack);\r
-    NewGdtTable = mNewGdt;\r
+    SetMem (mBuffer, sizeof (mBuffer), 0);\r
+    LocalBufferSize = sizeof (mBuffer);\r
+    Status          = ArchSetupExceptionStack (mBuffer, &LocalBufferSize);\r
+    ASSERT_EFI_ERROR (Status);\r
+    return Status;\r
   } else {\r
-    if (BufferSize == NULL) {\r
-      return EFI_INVALID_PARAMETER;\r
-    }\r
-\r
-    //\r
-    // Total needed size includes stack size, new GDT table size, TSS size.\r
-    // Add another DESCRIPTOR size for alignment requiremet.\r
-    //\r
-    NeedBufferSize = CPU_STACK_SWITCH_EXCEPTION_NUMBER * CPU_KNOWN_GOOD_STACK_SIZE +\r
-                     CPU_TSS_DESC_SIZE + Gdtr.Limit + 1 +\r
-                     CPU_TSS_SIZE +\r
-                     sizeof (IA32_TSS_DESCRIPTOR);\r
-    if (*BufferSize < NeedBufferSize) {\r
-      *BufferSize = NeedBufferSize;\r
-      return EFI_BUFFER_TOO_SMALL;\r
-    }\r
-\r
-    if (Buffer == NULL) {\r
-      return EFI_INVALID_PARAMETER;\r
-    }\r
-\r
-    StackTop    = (UINTN)Buffer + CPU_STACK_SWITCH_EXCEPTION_NUMBER * CPU_KNOWN_GOOD_STACK_SIZE;\r
-    NewGdtTable = ALIGN_POINTER (StackTop, sizeof (IA32_TSS_DESCRIPTOR));\r
+    return ArchSetupExceptionStack (Buffer, BufferSize);\r
   }\r
-\r
-  AsmReadIdtr (&Idtr);\r
-  EssData.KnownGoodStackTop          = StackTop;\r
-  EssData.KnownGoodStackSize         = CPU_KNOWN_GOOD_STACK_SIZE;\r
-  EssData.StackSwitchExceptions      = CPU_STACK_SWITCH_EXCEPTION_LIST;\r
-  EssData.StackSwitchExceptionNumber = CPU_STACK_SWITCH_EXCEPTION_NUMBER;\r
-  EssData.IdtTable                   = (VOID *)Idtr.Base;\r
-  EssData.IdtTableSize               = Idtr.Limit + 1;\r
-  EssData.GdtTable                   = NewGdtTable;\r
-  EssData.GdtTableSize               = CPU_TSS_DESC_SIZE + Gdtr.Limit + 1;\r
-  EssData.ExceptionTssDesc           = NewGdtTable + Gdtr.Limit + 1;\r
-  EssData.ExceptionTssDescSize       = CPU_TSS_DESC_SIZE;\r
-  EssData.ExceptionTss               = NewGdtTable + Gdtr.Limit + 1 + CPU_TSS_DESC_SIZE;\r
-  EssData.ExceptionTssSize           = CPU_TSS_SIZE;\r
-\r
-  return ArchSetupExceptionStack (&EssData);\r
 }\r
index 194d3a499b264818450970415fa18bb74c6acfc2..8c398ebc5b8ad917bd041bc0dc48966c0b466da1 100644 (file)
@@ -104,108 +104,97 @@ ArchRestoreExceptionContext (
 }\r
 \r
 /**\r
-  Setup separate stack for given exceptions.\r
+  Setup separate stacks for certain exception handlers.\r
 \r
-  @param[in] StackSwitchData      Pointer to data required for setuping up\r
-                                  stack switch.\r
-\r
-  @retval EFI_SUCCESS             The exceptions have been successfully\r
-                                  initialized with new stack.\r
-  @retval EFI_INVALID_PARAMETER   StackSwitchData contains invalid content.\r
+  @param[in]       Buffer        Point to buffer used to separate exception stack.\r
+  @param[in, out]  BufferSize    On input, it indicates the byte size of Buffer.\r
+                                 If the size is not enough, the return status will\r
+                                 be EFI_BUFFER_TOO_SMALL, and output BufferSize\r
+                                 will be the size it needs.\r
 \r
+  @retval EFI_SUCCESS             The stacks are assigned successfully.\r
+  @retval EFI_BUFFER_TOO_SMALL    This BufferSize is too small.\r
 **/\r
 EFI_STATUS\r
 ArchSetupExceptionStack (\r
-  IN CPU_EXCEPTION_INIT_DATA  *StackSwitchData\r
+  IN     VOID   *Buffer,\r
+  IN OUT UINTN  *BufferSize\r
   )\r
 {\r
   IA32_DESCRIPTOR                 Gdtr;\r
   IA32_DESCRIPTOR                 Idtr;\r
   IA32_IDT_GATE_DESCRIPTOR        *IdtTable;\r
   IA32_TSS_DESCRIPTOR             *TssDesc;\r
+  IA32_TSS_DESCRIPTOR             *TssDescBase;\r
   IA32_TASK_STATE_SEGMENT         *Tss;\r
+  VOID                            *NewGdtTable;\r
   UINTN                           StackTop;\r
   UINTN                           Index;\r
   UINTN                           Vector;\r
   UINTN                           TssBase;\r
-  UINTN                           GdtSize;\r
+  UINT8                           *StackSwitchExceptions;\r
+  UINTN                           NeedBufferSize;\r
   EXCEPTION_HANDLER_TEMPLATE_MAP  TemplateMap;\r
 \r
-  if ((StackSwitchData == NULL) ||\r
-      (StackSwitchData->KnownGoodStackTop == 0) ||\r
-      (StackSwitchData->KnownGoodStackSize == 0) ||\r
-      (StackSwitchData->StackSwitchExceptions == NULL) ||\r
-      (StackSwitchData->StackSwitchExceptionNumber == 0) ||\r
-      (StackSwitchData->StackSwitchExceptionNumber > CPU_EXCEPTION_NUM) ||\r
-      (StackSwitchData->GdtTable == NULL) ||\r
-      (StackSwitchData->IdtTable == NULL) ||\r
-      (StackSwitchData->ExceptionTssDesc == NULL) ||\r
-      (StackSwitchData->ExceptionTss == NULL))\r
-  {\r
+  if (BufferSize == NULL) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
   //\r
-  // The caller is responsible for that the GDT table, no matter the existing\r
-  // one or newly allocated, has enough space to hold descriptors for exception\r
-  // task-state segments.\r
+  // Total needed size includes stack size, new GDT table size, TSS size.\r
+  // Add another DESCRIPTOR size for alignment requiremet.\r
   //\r
-  if (((UINTN)StackSwitchData->GdtTable & (IA32_GDT_ALIGNMENT - 1)) != 0) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
-  if ((UINTN)StackSwitchData->ExceptionTssDesc < (UINTN)(StackSwitchData->GdtTable)) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
-  if ((UINTN)StackSwitchData->ExceptionTssDesc + StackSwitchData->ExceptionTssDescSize >\r
-      ((UINTN)(StackSwitchData->GdtTable) + StackSwitchData->GdtTableSize))\r
-  {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
+  // Layout of memory needed for each processor:\r
+  //    --------------------------------\r
+  //    |                              |\r
+  //    |          Stack Size          |  X ExceptionNumber\r
+  //    |                              |\r
+  //    --------------------------------\r
+  //    |          Alignment           |  (just in case)\r
+  //    --------------------------------\r
+  //    |                              |\r
+  //    |         Original GDT         |\r
+  //    |                              |\r
+  //    --------------------------------\r
+  //    |    Current task descriptor   |\r
+  //    --------------------------------\r
+  //    |                              |\r
+  //    |  Exception task descriptors  |  X ExceptionNumber\r
+  //    |                              |\r
+  //    --------------------------------\r
+  //    |  Current task-state segment  |\r
+  //    --------------------------------\r
+  //    |                              |\r
+  //    | Exception task-state segment |  X ExceptionNumber\r
+  //    |                              |\r
+  //    --------------------------------\r
   //\r
-  // We need one descriptor and one TSS for current task and every exception\r
-  // specified.\r
-  //\r
-  if (StackSwitchData->ExceptionTssDescSize <\r
-      sizeof (IA32_TSS_DESCRIPTOR) * (StackSwitchData->StackSwitchExceptionNumber + 1))\r
-  {\r
-    return EFI_INVALID_PARAMETER;\r
+  AsmReadGdtr (&Gdtr);\r
+  NeedBufferSize = CPU_STACK_SWITCH_EXCEPTION_NUMBER * CPU_KNOWN_GOOD_STACK_SIZE +\r
+                   sizeof (IA32_TSS_DESCRIPTOR) +\r
+                   Gdtr.Limit + 1 + CPU_TSS_DESC_SIZE +\r
+                   CPU_TSS_SIZE;\r
+\r
+  if (*BufferSize < NeedBufferSize) {\r
+    *BufferSize = NeedBufferSize;\r
+    return EFI_BUFFER_TOO_SMALL;\r
   }\r
 \r
-  if (StackSwitchData->ExceptionTssSize <\r
-      sizeof (IA32_TASK_STATE_SEGMENT) * (StackSwitchData->StackSwitchExceptionNumber + 1))\r
-  {\r
+  if (Buffer == NULL) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
-  TssDesc = StackSwitchData->ExceptionTssDesc;\r
-  Tss     = StackSwitchData->ExceptionTss;\r
-\r
-  //\r
-  // Initialize new GDT table and/or IDT table, if any\r
-  //\r
   AsmReadIdtr (&Idtr);\r
-  AsmReadGdtr (&Gdtr);\r
-\r
-  GdtSize = (UINTN)TssDesc +\r
-            sizeof (IA32_TSS_DESCRIPTOR) *\r
-            (StackSwitchData->StackSwitchExceptionNumber + 1) -\r
-            (UINTN)(StackSwitchData->GdtTable);\r
-  if ((UINTN)StackSwitchData->GdtTable != Gdtr.Base) {\r
-    CopyMem (StackSwitchData->GdtTable, (VOID *)Gdtr.Base, Gdtr.Limit + 1);\r
-    Gdtr.Base  = (UINTN)StackSwitchData->GdtTable;\r
-    Gdtr.Limit = (UINT16)GdtSize - 1;\r
-  }\r
-\r
-  if ((UINTN)StackSwitchData->IdtTable != Idtr.Base) {\r
-    Idtr.Base = (UINTN)StackSwitchData->IdtTable;\r
-  }\r
+  StackSwitchExceptions = CPU_STACK_SWITCH_EXCEPTION_LIST;\r
+  StackTop              = (UINTN)Buffer + CPU_STACK_SWITCH_EXCEPTION_NUMBER * CPU_KNOWN_GOOD_STACK_SIZE;\r
+  NewGdtTable           = ALIGN_POINTER (StackTop, sizeof (IA32_TSS_DESCRIPTOR));\r
+  TssDesc               = (IA32_TSS_DESCRIPTOR *)((UINTN)NewGdtTable + Gdtr.Limit + 1);\r
+  Tss                   = (IA32_TASK_STATE_SEGMENT *)((UINTN)TssDesc + CPU_TSS_DESC_SIZE);\r
+  TssDescBase           = TssDesc;\r
 \r
-  if (StackSwitchData->IdtTableSize > 0) {\r
-    Idtr.Limit = (UINT16)(StackSwitchData->IdtTableSize - 1);\r
-  }\r
+  CopyMem (NewGdtTable, (VOID *)Gdtr.Base, Gdtr.Limit + 1);\r
+  Gdtr.Base  = (UINTN)NewGdtTable;\r
+  Gdtr.Limit = (UINT16)(Gdtr.Limit + CPU_TSS_DESC_SIZE);\r
 \r
   //\r
   // Fixup current task descriptor. Task-state segment for current task will\r
@@ -226,10 +215,10 @@ ArchSetupExceptionStack (
   // Fixup exception task descriptor and task-state segment\r
   //\r
   AsmGetTssTemplateMap (&TemplateMap);\r
-  StackTop = StackSwitchData->KnownGoodStackTop - CPU_STACK_ALIGNMENT;\r
+  StackTop = StackTop - CPU_STACK_ALIGNMENT;\r
   StackTop = (UINTN)ALIGN_POINTER (StackTop, CPU_STACK_ALIGNMENT);\r
-  IdtTable = StackSwitchData->IdtTable;\r
-  for (Index = 0; Index < StackSwitchData->StackSwitchExceptionNumber; ++Index) {\r
+  IdtTable = (IA32_IDT_GATE_DESCRIPTOR  *)Idtr.Base;\r
+  for (Index = 0; Index < CPU_STACK_SWITCH_EXCEPTION_NUMBER; ++Index) {\r
     TssDesc += 1;\r
     Tss     += 1;\r
 \r
@@ -250,7 +239,7 @@ ArchSetupExceptionStack (
     //\r
     // Fixup TSS\r
     //\r
-    Vector = StackSwitchData->StackSwitchExceptions[Index];\r
+    Vector = StackSwitchExceptions[Index];\r
     if ((Vector >= CPU_EXCEPTION_NUM) ||\r
         (Vector >= (Idtr.Limit + 1) / sizeof (IA32_IDT_GATE_DESCRIPTOR)))\r
     {\r
@@ -270,7 +259,7 @@ ArchSetupExceptionStack (
     Tss->FS     = AsmReadFs ();\r
     Tss->GS     = AsmReadGs ();\r
 \r
-    StackTop -= StackSwitchData->KnownGoodStackSize;\r
+    StackTop -= CPU_KNOWN_GOOD_STACK_SIZE;\r
 \r
     //\r
     // Update IDT to use Task Gate for given exception\r
@@ -290,12 +279,7 @@ ArchSetupExceptionStack (
   //\r
   // Load current task\r
   //\r
-  AsmWriteTr ((UINT16)((UINTN)StackSwitchData->ExceptionTssDesc - Gdtr.Base));\r
-\r
-  //\r
-  // Publish IDT\r
-  //\r
-  AsmWriteIdtr (&Idtr);\r
+  AsmWriteTr ((UINT16)((UINTN)TssDescBase - Gdtr.Base));\r
 \r
   return EFI_SUCCESS;\r
 }\r
index 5952295126fe1b6804a341a224c1e2a86cd2bed1..940d83a92f20d01b9bfd23960b49386572580ae5 100644 (file)
@@ -170,84 +170,9 @@ InitializeSeparateExceptionStacks (
   IN OUT UINTN  *BufferSize\r
   )\r
 {\r
-  CPU_EXCEPTION_INIT_DATA  EssData;\r
-  IA32_DESCRIPTOR          Idtr;\r
-  IA32_DESCRIPTOR          Gdtr;\r
-  UINTN                    NeedBufferSize;\r
-  UINTN                    StackTop;\r
-  UINT8                    *NewGdtTable;\r
-\r
-  //\r
-  // X64 needs only one TSS of current task working for all exceptions\r
-  // because of its IST feature. IA32 needs one TSS for each exception\r
-  // in addition to current task. To simplify the code, we report the\r
-  // needed memory for IA32 case to cover both IA32 and X64 exception\r
-  // stack switch.\r
-  //\r
-  // Layout of memory needed for each processor:\r
-  //    --------------------------------\r
-  //    |            Alignment         |  (just in case)\r
-  //    --------------------------------\r
-  //    |                              |\r
-  //    |        Original GDT          |\r
-  //    |                              |\r
-  //    --------------------------------\r
-  //    |    Current task descriptor   |\r
-  //    --------------------------------\r
-  //    |                              |\r
-  //    |  Exception task descriptors  |  X ExceptionNumber\r
-  //    |                              |\r
-  //    --------------------------------\r
-  //    |  Current task-state segment  |\r
-  //    --------------------------------\r
-  //    |                              |\r
-  //    | Exception task-state segment |  X ExceptionNumber\r
-  //    |                              |\r
-  //    --------------------------------\r
-  //\r
-\r
   if ((Buffer == NULL) && (BufferSize == NULL)) {\r
     return EFI_UNSUPPORTED;\r
   }\r
 \r
-  if (BufferSize == NULL) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
-  AsmReadGdtr (&Gdtr);\r
-  //\r
-  // Total needed size includes stack size, new GDT table size, TSS size.\r
-  // Add another DESCRIPTOR size for alignment requiremet.\r
-  //\r
-  NeedBufferSize = CPU_STACK_SWITCH_EXCEPTION_NUMBER * CPU_KNOWN_GOOD_STACK_SIZE +\r
-                   CPU_TSS_DESC_SIZE + Gdtr.Limit + 1 +\r
-                   CPU_TSS_SIZE +\r
-                   sizeof (IA32_TSS_DESCRIPTOR);\r
-  if (*BufferSize < NeedBufferSize) {\r
-    *BufferSize = NeedBufferSize;\r
-    return EFI_BUFFER_TOO_SMALL;\r
-  }\r
-\r
-  if (Buffer == NULL) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
-  StackTop    = (UINTN)Buffer + CPU_STACK_SWITCH_EXCEPTION_NUMBER * CPU_KNOWN_GOOD_STACK_SIZE;\r
-  NewGdtTable = ALIGN_POINTER (StackTop, sizeof (IA32_TSS_DESCRIPTOR));\r
-\r
-  AsmReadIdtr (&Idtr);\r
-  EssData.KnownGoodStackTop          = StackTop;\r
-  EssData.KnownGoodStackSize         = CPU_KNOWN_GOOD_STACK_SIZE;\r
-  EssData.StackSwitchExceptions      = CPU_STACK_SWITCH_EXCEPTION_LIST;\r
-  EssData.StackSwitchExceptionNumber = CPU_STACK_SWITCH_EXCEPTION_NUMBER;\r
-  EssData.IdtTable                   = (VOID *)Idtr.Base;\r
-  EssData.IdtTableSize               = Idtr.Limit + 1;\r
-  EssData.GdtTable                   = NewGdtTable;\r
-  EssData.GdtTableSize               = CPU_TSS_DESC_SIZE + Gdtr.Limit + 1;\r
-  EssData.ExceptionTssDesc           = NewGdtTable + Gdtr.Limit + 1;\r
-  EssData.ExceptionTssDescSize       = CPU_TSS_DESC_SIZE;\r
-  EssData.ExceptionTss               = NewGdtTable + Gdtr.Limit + 1 + CPU_TSS_DESC_SIZE;\r
-  EssData.ExceptionTssSize           = CPU_TSS_SIZE;\r
-\r
-  return ArchSetupExceptionStack (&EssData);\r
+  return ArchSetupExceptionStack (Buffer, BufferSize);\r
 }\r
index 8ae4feae62380b8371d67113da2df51d747a496b..6a170286c8fc7eac2db6e39391d4edff5e7c3ce8 100644 (file)
@@ -1,7 +1,7 @@
 ## @file\r
 #  CPU Exception Handler library instance for SEC/PEI modules.\r
 #\r
-#  Copyright (c) 2012 - 2018, Intel Corporation. All rights reserved.<BR>\r
+#  Copyright (c) 2012 - 2022, Intel Corporation. All rights reserved.<BR>\r
 #  SPDX-License-Identifier: BSD-2-Clause-Patent\r
 #\r
 ##\r
   PeCoffGetEntryPointLib\r
   VmgExitLib\r
 \r
+[Pcd]\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdCpuStackGuard\r
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuStackSwitchExceptionList\r
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuKnownGoodStackSize\r
+\r
 [FeaturePcd]\r
   gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmStackGuard                    ## CONSUMES\r
 \r
index c9f20da058606783c551c3a5c951c3a249f8cd74..9dde07612a042da28984ad51d73ece503ff1972d 100644 (file)
@@ -1,7 +1,7 @@
 ## @file\r
 #  CPU Exception Handler library instance for SMM modules.\r
 #\r
-#  Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.<BR>\r
+#  Copyright (c) 2013 - 2022, Intel Corporation. All rights reserved.<BR>\r
 #  SPDX-License-Identifier: BSD-2-Clause-Patent\r
 #\r
 ##\r
   DebugLib\r
   VmgExitLib\r
 \r
+[Pcd]\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdCpuStackGuard\r
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuStackSwitchExceptionList\r
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuKnownGoodStackSize\r
+\r
 [FeaturePcd]\r
   gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmStackGuard                    ## CONSUMES\r
 \r
index c14ac66c43c03f38d795715f1a4fb7518de19c91..80e9f08e5ba0ba436f5ffac9e4eed60cb958734b 100644 (file)
@@ -109,19 +109,22 @@ ArchRestoreExceptionContext (
 }\r
 \r
 /**\r
-  Setup separate stack for given exceptions.\r
+  Setup separate stacks for certain exception handlers.\r
 \r
-  @param[in] StackSwitchData      Pointer to data required for setuping up\r
-                                  stack switch.\r
-\r
-  @retval EFI_SUCCESS             The exceptions have been successfully\r
-                                  initialized with new stack.\r
-  @retval EFI_INVALID_PARAMETER   StackSwitchData contains invalid content.\r
+  @param[in]       Buffer        Point to buffer used to separate exception stack.\r
+  @param[in, out]  BufferSize    On input, it indicates the byte size of Buffer.\r
+                                 If the size is not enough, the return status will\r
+                                 be EFI_BUFFER_TOO_SMALL, and output BufferSize\r
+                                 will be the size it needs.\r
 \r
+  @retval EFI_SUCCESS             The stacks are assigned successfully.\r
+  @retval EFI_BUFFER_TOO_SMALL    This BufferSize is too small.\r
+  @retval EFI_UNSUPPORTED         This function is not supported.\r
 **/\r
 EFI_STATUS\r
 ArchSetupExceptionStack (\r
-  IN CPU_EXCEPTION_INIT_DATA  *StackSwitchData\r
+  IN     VOID   *Buffer,\r
+  IN OUT UINTN  *BufferSize\r
   )\r
 {\r
   IA32_DESCRIPTOR           Gdtr;\r
@@ -129,86 +132,75 @@ ArchSetupExceptionStack (
   IA32_IDT_GATE_DESCRIPTOR  *IdtTable;\r
   IA32_TSS_DESCRIPTOR       *TssDesc;\r
   IA32_TASK_STATE_SEGMENT   *Tss;\r
+  VOID                      *NewGdtTable;\r
   UINTN                     StackTop;\r
   UINTN                     Index;\r
   UINTN                     Vector;\r
   UINTN                     TssBase;\r
-  UINTN                     GdtSize;\r
-\r
-  if ((StackSwitchData == NULL) ||\r
-      (StackSwitchData->KnownGoodStackTop == 0) ||\r
-      (StackSwitchData->KnownGoodStackSize == 0) ||\r
-      (StackSwitchData->StackSwitchExceptions == NULL) ||\r
-      (StackSwitchData->StackSwitchExceptionNumber == 0) ||\r
-      (StackSwitchData->StackSwitchExceptionNumber > CPU_EXCEPTION_NUM) ||\r
-      (StackSwitchData->GdtTable == NULL) ||\r
-      (StackSwitchData->IdtTable == NULL) ||\r
-      (StackSwitchData->ExceptionTssDesc == NULL) ||\r
-      (StackSwitchData->ExceptionTss == NULL))\r
-  {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
-  //\r
-  // The caller is responsible for that the GDT table, no matter the existing\r
-  // one or newly allocated, has enough space to hold descriptors for exception\r
-  // task-state segments.\r
-  //\r
-  if (((UINTN)StackSwitchData->GdtTable & (IA32_GDT_ALIGNMENT - 1)) != 0) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
-  if ((UINTN)StackSwitchData->ExceptionTssDesc < (UINTN)(StackSwitchData->GdtTable)) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
-  if (((UINTN)StackSwitchData->ExceptionTssDesc + StackSwitchData->ExceptionTssDescSize) >\r
-      ((UINTN)(StackSwitchData->GdtTable) + StackSwitchData->GdtTableSize))\r
-  {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
+  UINT8                     *StackSwitchExceptions;\r
+  UINTN                     NeedBufferSize;\r
 \r
-  //\r
-  // One task gate descriptor and one task-state segment are needed.\r
-  //\r
-  if (StackSwitchData->ExceptionTssDescSize < sizeof (IA32_TSS_DESCRIPTOR)) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
-  if (StackSwitchData->ExceptionTssSize < sizeof (IA32_TASK_STATE_SEGMENT)) {\r
+  if (BufferSize == NULL) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
   //\r
   // Interrupt stack table supports only 7 vectors.\r
   //\r
-  TssDesc = StackSwitchData->ExceptionTssDesc;\r
-  Tss     = StackSwitchData->ExceptionTss;\r
-  if (StackSwitchData->StackSwitchExceptionNumber > ARRAY_SIZE (Tss->IST)) {\r
-    return EFI_INVALID_PARAMETER;\r
+  if (CPU_STACK_SWITCH_EXCEPTION_NUMBER > ARRAY_SIZE (Tss->IST)) {\r
+    return EFI_UNSUPPORTED;\r
   }\r
 \r
   //\r
-  // Initialize new GDT table and/or IDT table, if any\r
+  // Total needed size includes stack size, new GDT table size, TSS size.\r
+  // Add another DESCRIPTOR size for alignment requiremet.\r
+  //\r
+  // Layout of memory needed for each processor:\r
+  //    --------------------------------\r
+  //    |                              |\r
+  //    |          Stack Size          |  X ExceptionNumber\r
+  //    |                              |\r
+  //    --------------------------------\r
+  //    |          Alignment           |  (just in case)\r
+  //    --------------------------------\r
+  //    |                              |\r
+  //    |         Original GDT         |\r
+  //    |                              |\r
+  //    --------------------------------\r
+  //    |                              |\r
+  //    |  Exception task descriptors  |  X 1\r
+  //    |                              |\r
+  //    --------------------------------\r
+  //    |                              |\r
+  //    | Exception task-state segment |  X 1\r
+  //    |                              |\r
+  //    --------------------------------\r
   //\r
-  AsmReadIdtr (&Idtr);\r
   AsmReadGdtr (&Gdtr);\r
-\r
-  GdtSize = (UINTN)TssDesc + sizeof (IA32_TSS_DESCRIPTOR) -\r
-            (UINTN)(StackSwitchData->GdtTable);\r
-  if ((UINTN)StackSwitchData->GdtTable != Gdtr.Base) {\r
-    CopyMem (StackSwitchData->GdtTable, (VOID *)Gdtr.Base, Gdtr.Limit + 1);\r
-    Gdtr.Base  = (UINTN)StackSwitchData->GdtTable;\r
-    Gdtr.Limit = (UINT16)GdtSize - 1;\r
+  NeedBufferSize = CPU_STACK_SWITCH_EXCEPTION_NUMBER * CPU_KNOWN_GOOD_STACK_SIZE +\r
+                   sizeof (IA32_TSS_DESCRIPTOR) +\r
+                   Gdtr.Limit + 1 + CPU_TSS_DESC_SIZE +\r
+                   CPU_TSS_SIZE;\r
+\r
+  if (*BufferSize < NeedBufferSize) {\r
+    *BufferSize = NeedBufferSize;\r
+    return EFI_BUFFER_TOO_SMALL;\r
   }\r
 \r
-  if ((UINTN)StackSwitchData->IdtTable != Idtr.Base) {\r
-    Idtr.Base = (UINTN)StackSwitchData->IdtTable;\r
+  if (Buffer == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
   }\r
 \r
-  if (StackSwitchData->IdtTableSize > 0) {\r
-    Idtr.Limit = (UINT16)(StackSwitchData->IdtTableSize - 1);\r
-  }\r
+  AsmReadIdtr (&Idtr);\r
+  StackSwitchExceptions = CPU_STACK_SWITCH_EXCEPTION_LIST;\r
+  StackTop              = (UINTN)Buffer + CPU_STACK_SWITCH_EXCEPTION_NUMBER * CPU_KNOWN_GOOD_STACK_SIZE;\r
+  NewGdtTable           = ALIGN_POINTER (StackTop, sizeof (IA32_TSS_DESCRIPTOR));\r
+  TssDesc               = (IA32_TSS_DESCRIPTOR *)((UINTN)NewGdtTable + Gdtr.Limit + 1);\r
+  Tss                   = (IA32_TASK_STATE_SEGMENT *)((UINTN)TssDesc + CPU_TSS_DESC_SIZE);\r
+\r
+  CopyMem (NewGdtTable, (VOID *)Gdtr.Base, Gdtr.Limit + 1);\r
+  Gdtr.Base  = (UINTN)NewGdtTable;\r
+  Gdtr.Limit = (UINT16)(Gdtr.Limit + CPU_TSS_DESC_SIZE);\r
 \r
   //\r
   // Fixup current task descriptor. Task-state segment for current task will\r
@@ -231,20 +223,20 @@ ArchSetupExceptionStack (
   // Fixup exception task descriptor and task-state segment\r
   //\r
   ZeroMem (Tss, sizeof (*Tss));\r
-  StackTop = StackSwitchData->KnownGoodStackTop - CPU_STACK_ALIGNMENT;\r
+  StackTop = StackTop - CPU_STACK_ALIGNMENT;\r
   StackTop = (UINTN)ALIGN_POINTER (StackTop, CPU_STACK_ALIGNMENT);\r
-  IdtTable = StackSwitchData->IdtTable;\r
-  for (Index = 0; Index < StackSwitchData->StackSwitchExceptionNumber; ++Index) {\r
+  IdtTable = (IA32_IDT_GATE_DESCRIPTOR  *)Idtr.Base;\r
+  for (Index = 0; Index < CPU_STACK_SWITCH_EXCEPTION_NUMBER; ++Index) {\r
     //\r
     // Fixup IST\r
     //\r
     Tss->IST[Index] = StackTop;\r
-    StackTop       -= StackSwitchData->KnownGoodStackSize;\r
+    StackTop       -= CPU_KNOWN_GOOD_STACK_SIZE;\r
 \r
     //\r
     // Set the IST field to enable corresponding IST\r
     //\r
-    Vector = StackSwitchData->StackSwitchExceptions[Index];\r
+    Vector = StackSwitchExceptions[Index];\r
     if ((Vector >= CPU_EXCEPTION_NUM) ||\r
         (Vector >= (Idtr.Limit + 1) / sizeof (IA32_IDT_GATE_DESCRIPTOR)))\r
     {\r
@@ -262,12 +254,7 @@ ArchSetupExceptionStack (
   //\r
   // Load current task\r
   //\r
-  AsmWriteTr ((UINT16)((UINTN)StackSwitchData->ExceptionTssDesc - Gdtr.Base));\r
-\r
-  //\r
-  // Publish IDT\r
-  //\r
-  AsmWriteIdtr (&Idtr);\r
+  AsmWriteTr ((UINT16)((UINTN)TssDesc - Gdtr.Base));\r
 \r
   return EFI_SUCCESS;\r
 }\r
index a15f125d5b5e6f75e64633fa7c272ed882d7f8a2..6d2f66504a5bc3d2c8fd388c290143703b2ed068 100644 (file)
@@ -2,7 +2,7 @@
 #  CPU Exception Handler library instance for SEC/PEI modules.\r
 #\r
 #  Copyright (C) 2020, Advanced Micro Devices, Inc. All rights reserved.<BR>\r
-#  Copyright (c) 2012 - 2018, Intel Corporation. All rights reserved.<BR>\r
+#  Copyright (c) 2012 - 2022, Intel Corporation. All rights reserved.<BR>\r
 #  SPDX-License-Identifier: BSD-2-Clause-Patent\r
 #\r
 #  This is the XCODE5 variant of the SEC/PEI CpuExceptionHandlerLib. This\r
   PeCoffGetEntryPointLib\r
   VmgExitLib\r
 \r
+[Pcd]\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdCpuStackGuard\r
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuStackSwitchExceptionList\r
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuKnownGoodStackSize\r
+\r
 [FeaturePcd]\r
   gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmStackGuard                    ## CONSUMES\r
 \r