1 /** @file 2 SMM CPU misc functions for x64 arch specific. 3 4 Copyright (c) 2015, Intel Corporation. All rights reserved.<BR> 5 This program and the accompanying materials 6 are licensed and made available under the terms and conditions of the BSD License 7 which accompanies this distribution. The full text of the license may be found at 8 http://opensource.org/licenses/bsd-license.php 9 10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 12 13 **/ 14 15 #include "PiSmmCpuDxeSmm.h" 16 17 /** 18 Initialize Gdt for all processors. 19 20 @param[in] Cr3 CR3 value. 21 @param[out] GdtStepSize The step size for GDT table. 22 23 @return GdtBase for processor 0. 24 GdtBase for processor X is: GdtBase + (GdtStepSize * X) 25 **/ 26 VOID * InitGdt(IN UINTN Cr3,OUT UINTN * GdtStepSize)27InitGdt ( 28 IN UINTN Cr3, 29 OUT UINTN *GdtStepSize 30 ) 31 { 32 UINTN Index; 33 IA32_SEGMENT_DESCRIPTOR *GdtDescriptor; 34 UINTN TssBase; 35 UINTN GdtTssTableSize; 36 UINT8 *GdtTssTables; 37 UINTN GdtTableStepSize; 38 39 // 40 // For X64 SMM, we allocate separate GDT/TSS for each CPUs to avoid TSS load contention 41 // on each SMI entry. 42 // 43 GdtTssTableSize = (gcSmiGdtr.Limit + 1 + TSS_SIZE + 7) & ~7; // 8 bytes aligned 44 GdtTssTables = (UINT8*)AllocatePages (EFI_SIZE_TO_PAGES (GdtTssTableSize * gSmmCpuPrivate->SmmCoreEntryContext.NumberOfCpus)); 45 ASSERT (GdtTssTables != NULL); 46 GdtTableStepSize = GdtTssTableSize; 47 48 for (Index = 0; Index < gSmmCpuPrivate->SmmCoreEntryContext.NumberOfCpus; Index++) { 49 CopyMem (GdtTssTables + GdtTableStepSize * Index, (VOID*)(UINTN)gcSmiGdtr.Base, gcSmiGdtr.Limit + 1 + TSS_SIZE); 50 51 // 52 // Fixup TSS descriptors 53 // 54 TssBase = (UINTN)(GdtTssTables + GdtTableStepSize * Index + gcSmiGdtr.Limit + 1); 55 GdtDescriptor = (IA32_SEGMENT_DESCRIPTOR *)(TssBase) - 2; 56 GdtDescriptor->Bits.BaseLow = (UINT16)(UINTN)TssBase; 57 GdtDescriptor->Bits.BaseMid = (UINT8)((UINTN)TssBase >> 16); 58 GdtDescriptor->Bits.BaseHigh = (UINT8)((UINTN)TssBase >> 24); 59 60 if (FeaturePcdGet (PcdCpuSmmStackGuard)) { 61 // 62 // Setup top of known good stack as IST1 for each processor. 63 // 64 *(UINTN *)(TssBase + TSS_X64_IST1_OFFSET) = (mSmmStackArrayBase + EFI_PAGE_SIZE + Index * mSmmStackSize); 65 } 66 } 67 68 *GdtStepSize = GdtTableStepSize; 69 return GdtTssTables; 70 } 71