- GdtTssTables = NULL;\r
- GdtTssTableSize = 0;\r
- GdtTableStepSize = 0;\r
- //\r
- // For X64 SMM, we allocate separate GDT/TSS for each CPUs to avoid TSS load contention\r
- // on each SMI entry.\r
- //\r
- if (EFI_IMAGE_MACHINE_TYPE_SUPPORTED(EFI_IMAGE_MACHINE_X64)) {\r
- GdtTssTableSize = (gcSmiGdtr.Limit + 1 + TSS_SIZE + 7) & ~7; // 8 bytes aligned\r
- GdtTssTables = (UINT8*)AllocatePages (EFI_SIZE_TO_PAGES (GdtTssTableSize * gSmmCpuPrivate->SmmCoreEntryContext.NumberOfCpus));\r
- ASSERT (GdtTssTables != NULL);\r
- GdtTableStepSize = GdtTssTableSize;\r
-\r
- for (Index = 0; Index < gSmmCpuPrivate->SmmCoreEntryContext.NumberOfCpus; Index++) {\r
- CopyMem (GdtTssTables + GdtTableStepSize * Index, (VOID*)(UINTN)gcSmiGdtr.Base, gcSmiGdtr.Limit + 1 + TSS_SIZE);\r
- if (FeaturePcdGet (PcdCpuSmmStackGuard)) {\r
- //\r
- // Setup top of known good stack as IST1 for each processor.\r
- //\r
- *(UINTN *)(GdtTssTables + GdtTableStepSize * Index + gcSmiGdtr.Limit + 1 + TSS_X64_IST1_OFFSET) = (mSmmStackArrayBase + EFI_PAGE_SIZE + Index * mSmmStackSize);\r
- }\r
- }\r
- } else if (FeaturePcdGet (PcdCpuSmmStackGuard)) {\r
-\r
- //\r
- // For IA32 SMM, if SMM Stack Guard feature is enabled, we use 2 TSS.\r
- // in this case, we allocate separate GDT/TSS for each CPUs to avoid TSS load contention\r
- // on each SMI entry.\r
- //\r
-\r
- //\r
- // Enlarge GDT to contain 2 TSS descriptors\r
- //\r
- gcSmiGdtr.Limit += (UINT16)(2 * sizeof (IA32_SEGMENT_DESCRIPTOR));\r
-\r
- GdtTssTableSize = (gcSmiGdtr.Limit + 1 + TSS_SIZE * 2 + 7) & ~7; // 8 bytes aligned\r
- GdtTssTables = (UINT8*)AllocatePages (EFI_SIZE_TO_PAGES (GdtTssTableSize * gSmmCpuPrivate->SmmCoreEntryContext.NumberOfCpus));\r
- ASSERT (GdtTssTables != NULL);\r
- GdtTableStepSize = GdtTssTableSize;\r
-\r
- for (Index = 0; Index < gSmmCpuPrivate->SmmCoreEntryContext.NumberOfCpus; Index++) {\r
- CopyMem (GdtTssTables + GdtTableStepSize * Index, (VOID*)(UINTN)gcSmiGdtr.Base, gcSmiGdtr.Limit + 1 + TSS_SIZE * 2);\r
- //\r
- // Fixup TSS descriptors\r
- //\r
- TssBase = (UINTN)(GdtTssTables + GdtTableStepSize * Index + gcSmiGdtr.Limit + 1);\r
- GdtDescriptor = (IA32_SEGMENT_DESCRIPTOR *)(TssBase) - 2;\r
- GdtDescriptor->Bits.BaseLow = (UINT16)TssBase;\r
- GdtDescriptor->Bits.BaseMid = (UINT8)(TssBase >> 16);\r
- GdtDescriptor->Bits.BaseHigh = (UINT8)(TssBase >> 24);\r
-\r
- TssBase += TSS_SIZE;\r
- GdtDescriptor++;\r
- GdtDescriptor->Bits.BaseLow = (UINT16)TssBase;\r
- GdtDescriptor->Bits.BaseMid = (UINT8)(TssBase >> 16);\r
- GdtDescriptor->Bits.BaseHigh = (UINT8)(TssBase >> 24);\r
- //\r
- // Fixup TSS segments\r
- //\r
- // ESP as known good stack\r
- //\r
- *(UINTN *)(TssBase + TSS_IA32_ESP_OFFSET) = mSmmStackArrayBase + EFI_PAGE_SIZE + Index * mSmmStackSize;\r
- *(UINT32 *)(TssBase + TSS_IA32_CR3_OFFSET) = Cr3;\r
- }\r
- }\r