- //\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