]> git.proxmox.com Git - mirror_edk2.git/blobdiff - UefiCpuPkg/CpuDxe/CpuMp.c
UefiCpuPkg: Simplify InitializeSeparateExceptionStacks
[mirror_edk2.git] / UefiCpuPkg / CpuDxe / CpuMp.c
index e385f585c7f15f455086a19aa0f29a2f82f72e5e..f3ca813d2a1ce19c875dffcc8aa82c75b33df6d2 100644 (file)
@@ -596,23 +596,13 @@ CollectBistDataFromHob (
   }\r
 }\r
 \r
-/**\r
-  Get GDT register value.\r
-\r
-  This function is mainly for AP purpose because AP may have different GDT\r
-  table than BSP.\r
-\r
-  @param[in,out] Buffer  The pointer to private data buffer.\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-GetGdtr (\r
-  IN OUT VOID  *Buffer\r
-  )\r
-{\r
-  AsmReadGdtr ((IA32_DESCRIPTOR *)Buffer);\r
-}\r
+//\r
+// Structure for InitializeSeparateExceptionStacks\r
+//\r
+typedef struct {\r
+  VOID     *Buffer;\r
+  UINTN    *BufferSize;\r
+} EXCEPTION_STACK_SWITCH_CONTEXT;\r
 \r
 /**\r
   Initializes CPU exceptions handlers for the sake of stack switch requirement.\r
@@ -629,27 +619,17 @@ InitializeExceptionStackSwitchHandlers (
   IN OUT VOID  *Buffer\r
   )\r
 {\r
-  CPU_EXCEPTION_INIT_DATA  *EssData;\r
-  IA32_DESCRIPTOR          Idtr;\r
-  EFI_STATUS               Status;\r
+  EXCEPTION_STACK_SWITCH_CONTEXT  *SwitchStackData;\r
 \r
-  EssData = Buffer;\r
-  //\r
-  // We don't plan to replace IDT table with a new one, but we should not assume\r
-  // the AP's IDT is the same as BSP's IDT either.\r
-  //\r
-  AsmReadIdtr (&Idtr);\r
-  EssData->Ia32.IdtTable     = (VOID *)Idtr.Base;\r
-  EssData->Ia32.IdtTableSize = Idtr.Limit + 1;\r
-  Status                     = InitializeSeparateExceptionStacks (EssData);\r
-  ASSERT_EFI_ERROR (Status);\r
+  SwitchStackData = (EXCEPTION_STACK_SWITCH_CONTEXT *)Buffer;\r
+  InitializeSeparateExceptionStacks (SwitchStackData->Buffer, SwitchStackData->BufferSize);\r
 }\r
 \r
 /**\r
   Initializes MP exceptions handlers for the sake of stack switch requirement.\r
 \r
   This function will allocate required resources required to setup stack switch\r
-  and pass them through CPU_EXCEPTION_INIT_DATA to each logic processor.\r
+  and pass them through SwitchStackData to each logic processor.\r
 \r
 **/\r
 VOID\r
@@ -657,129 +637,53 @@ InitializeMpExceptionStackSwitchHandlers (
   VOID\r
   )\r
 {\r
-  UINTN                    Index;\r
-  UINTN                    Bsp;\r
-  UINTN                    ExceptionNumber;\r
-  UINTN                    OldGdtSize;\r
-  UINTN                    NewGdtSize;\r
-  UINTN                    NewStackSize;\r
-  IA32_DESCRIPTOR          Gdtr;\r
-  CPU_EXCEPTION_INIT_DATA  EssData;\r
-  UINT8                    *GdtBuffer;\r
-  UINT8                    *StackTop;\r
-\r
-  ExceptionNumber = FixedPcdGetSize (PcdCpuStackSwitchExceptionList);\r
-  NewStackSize    = FixedPcdGet32 (PcdCpuKnownGoodStackSize) * ExceptionNumber;\r
-\r
-  StackTop = AllocateRuntimeZeroPool (NewStackSize * mNumberOfProcessors);\r
-  ASSERT (StackTop != NULL);\r
-  StackTop += NewStackSize  * mNumberOfProcessors;\r
-\r
-  //\r
-  // The default exception handlers must have been initialized. Let's just skip\r
-  // it in this method.\r
-  //\r
-  EssData.Ia32.Revision            = CPU_EXCEPTION_INIT_DATA_REV;\r
-  EssData.Ia32.InitDefaultHandlers = FALSE;\r
-\r
-  EssData.Ia32.StackSwitchExceptions      = FixedPcdGetPtr (PcdCpuStackSwitchExceptionList);\r
-  EssData.Ia32.StackSwitchExceptionNumber = ExceptionNumber;\r
-  EssData.Ia32.KnownGoodStackSize         = FixedPcdGet32 (PcdCpuKnownGoodStackSize);\r
+  UINTN                           Index;\r
+  UINTN                           Bsp;\r
+  EXCEPTION_STACK_SWITCH_CONTEXT  SwitchStackData;\r
+  UINTN                           BufferSize;\r
 \r
-  //\r
-  // Initialize Gdtr to suppress incorrect compiler/analyzer warnings.\r
-  //\r
-  Gdtr.Base  = 0;\r
-  Gdtr.Limit = 0;\r
+  SwitchStackData.BufferSize = &BufferSize;\r
   MpInitLibWhoAmI (&Bsp);\r
+\r
   for (Index = 0; Index < mNumberOfProcessors; ++Index) {\r
-    //\r
-    // To support stack switch, we need to re-construct GDT but not IDT.\r
-    //\r
+    SwitchStackData.Buffer = NULL;\r
+    BufferSize             = 0;\r
+\r
     if (Index == Bsp) {\r
-      GetGdtr (&Gdtr);\r
+      InitializeExceptionStackSwitchHandlers (&SwitchStackData);\r
     } else {\r
       //\r
-      // AP might have different size of GDT from BSP.\r
+      // AP might need different buffer size from BSP.\r
       //\r
-      MpInitLibStartupThisAP (GetGdtr, Index, NULL, 0, (VOID *)&Gdtr, NULL);\r
+      MpInitLibStartupThisAP (InitializeExceptionStackSwitchHandlers, Index, NULL, 0, (VOID *)&SwitchStackData, NULL);\r
     }\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. Since AP is not supposed to allocate\r
-    // memory, we have to do it in BSP. To simplify the code, we allocate\r
-    // memory for IA32 case to cover both IA32 and X64 exception stack\r
-    // switch.\r
-    //\r
-    // Layout of memory to allocate 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
-    OldGdtSize                        = Gdtr.Limit + 1;\r
-    EssData.Ia32.ExceptionTssDescSize = sizeof (IA32_TSS_DESCRIPTOR) *\r
-                                        (ExceptionNumber + 1);\r
-    EssData.Ia32.ExceptionTssSize = sizeof (IA32_TASK_STATE_SEGMENT) *\r
-                                    (ExceptionNumber + 1);\r
-    NewGdtSize = sizeof (IA32_TSS_DESCRIPTOR) +\r
-                 OldGdtSize +\r
-                 EssData.Ia32.ExceptionTssDescSize +\r
-                 EssData.Ia32.ExceptionTssSize;\r
-\r
-    GdtBuffer = AllocateRuntimeZeroPool (NewGdtSize);\r
-    ASSERT (GdtBuffer != NULL);\r
-\r
-    //\r
-    // Make sure GDT table alignment\r
-    //\r
-    EssData.Ia32.GdtTable     = ALIGN_POINTER (GdtBuffer, sizeof (IA32_TSS_DESCRIPTOR));\r
-    NewGdtSize               -= ((UINT8 *)EssData.Ia32.GdtTable - GdtBuffer);\r
-    EssData.Ia32.GdtTableSize = NewGdtSize;\r
-\r
-    EssData.Ia32.ExceptionTssDesc = ((UINT8 *)EssData.Ia32.GdtTable + OldGdtSize);\r
-    EssData.Ia32.ExceptionTss     = ((UINT8 *)EssData.Ia32.GdtTable + OldGdtSize +\r
-                                     EssData.Ia32.ExceptionTssDescSize);\r
+    if (BufferSize == 0) {\r
+      continue;\r
+    }\r
 \r
-    EssData.Ia32.KnownGoodStackTop = (UINTN)StackTop;\r
+    SwitchStackData.Buffer = AllocateRuntimeZeroPool (BufferSize);\r
+    ASSERT (SwitchStackData.Buffer != NULL);\r
     DEBUG ((\r
       DEBUG_INFO,\r
-      "Exception stack top[cpu%lu]: 0x%lX\n",\r
+      "Buffer[cpu%lu] for InitializeExceptionStackSwitchHandlers: 0x%lX with size 0x%x\n",\r
       (UINT64)(UINTN)Index,\r
-      (UINT64)(UINTN)StackTop\r
+      (UINT64)(UINTN)SwitchStackData.Buffer,\r
+      (UINT32)BufferSize\r
       ));\r
 \r
     if (Index == Bsp) {\r
-      InitializeExceptionStackSwitchHandlers (&EssData);\r
+      InitializeExceptionStackSwitchHandlers (&SwitchStackData);\r
     } else {\r
       MpInitLibStartupThisAP (\r
         InitializeExceptionStackSwitchHandlers,\r
         Index,\r
         NULL,\r
         0,\r
-        (VOID *)&EssData,\r
+        (VOID *)&SwitchStackData,\r
         NULL\r
         );\r
     }\r
-\r
-    StackTop -= NewStackSize;\r
   }\r
 }\r
 \r