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