Hi Jiewen,

Thanks for the feedback. 

> -----Original Message-----
> From: Yao, Jiewen
> Sent: Wednesday, November 01, 2017 9:57 AM
> To: Wang, Jian J <jian.j.w...@intel.com>; edk2-devel@lists.01.org
> Cc: Zeng, Star <star.z...@intel.com>; Dong, Eric <eric.d...@intel.com>;
> Kinney, Michael D <michael.d.kin...@intel.com>
> Subject: RE: [PATCH 3/3] UefiCpuPkg/CpuExceptionHandlerLib: Add stack switch
> support
> 
> Hi Jian
> Thanks for the patch.
> 
> Can we move all IA32 defined data structure or function to MdePkg?
> Such as: AsmWriteTr, IA32_TASK_STATE_SEGMENT, IA32_TSS_DESCRIPTOR
> 

Sure we can.

> I am also curious why we use different policy for other boot mode.
> Can we use consistent policy?
> > +  if (PcdGetBool (PcdCpuStackGuard)) {
> > +    //
> > +    // Stack Guard works with the support of page table established and
> > +    // memory management. So we have to exclude those boot modes
> > without
> > +    // them.
> > +    //
> > +    switch (GetBootModeHob()) {
> > +    case BOOT_ON_FLASH_UPDATE:
> > +    case BOOT_IN_RECOVERY_MODE:
> > +    case BOOT_ON_S3_RESUME:
> > +      break;
> > +
> > +    default:
> > +      ArchSetupExcpetionStack (IdtTable);
> > +      break;
> > +    }
> > +  }
> 

As far as I'm aware of, those boot modes cannot provide both paging and
memory management, which are needed by stack guard to work. Let me know
if I'm wrong.

> 
> Thank you
> Yao Jiewen
> 
> 
> > -----Original Message-----
> > From: Wang, Jian J
> > Sent: Tuesday, October 31, 2017 10:24 PM
> > To: edk2-devel@lists.01.org
> > Cc: Zeng, Star <star.z...@intel.com>; Dong, Eric <eric.d...@intel.com>; Yao,
> > Jiewen <jiewen....@intel.com>; Kinney, Michael D
> > <michael.d.kin...@intel.com>
> > Subject: [PATCH 3/3] UefiCpuPkg/CpuExceptionHandlerLib: Add stack switch
> > support
> >
> > If Stack Guard is enabled and there's really a stack overflow happened 
> > during
> > boot, a Page Fault exception will be triggered. Because the stack is out of
> > usage, the exception handler, which shares the stack with normal UEFI 
> > driver,
> > cannot be executed and cannot dump the processor information.
> >
> > Without those information, it's very difficult for the BIOS developers 
> > locate
> > the root cause of stack overflow. And without a workable stack, the 
> > developer
> > cannot event use single step to debug the UEFI driver with JTAG debugger.
> >
> > In order to make sure the exception handler to execute normally after stack
> > overflow. We need separate stacks for exception handlers in case of unusable
> > stack.
> >
> > IA processor allows to switch to a new stack during handling interrupt and
> > exception. But X64 and IA32 provides different ways to make it. X64 provides
> > interrupt stack table (IST) to allow maximum 7 different exceptions to have
> > new stack for its handler. IA32 doesn't have IST mechanism and can only use
> > task gate to do it since task switch allows to load a new stack through its
> > task-state segment (TSS).
> >
> > Note: Stack switch needs to allocate memory pages to be new stacks. So this
> >       functionality works only in the boot phases capable of memory
> >       allocation (besides the paging, for the sake of Stack Guard). In
> >       other words, only DXE phase can supports Stack Guard with stack 
> > switch.
> >
> > Cc: Star Zeng <star.z...@intel.com>
> > Cc: Eric Dong <eric.d...@intel.com>
> > Cc: Jiewen Yao <jiewen....@intel.com>
> > Cc: Michael Kinney <michael.d.kin...@intel.com>
> > Suggested-by: Ayellet Wolman <ayellet.wol...@intel.com>
> > Contributed-under: TianoCore Contribution Agreement 1.1
> > Signed-off-by: Jian J Wang <jian.j.w...@intel.com>
> > ---
> >  .../CpuExceptionHandlerLib/CpuExceptionCommon.h    |  22 ++
> >  .../DxeCpuExceptionHandlerLib.inf                  |   5 +
> >  .../Library/CpuExceptionHandlerLib/DxeException.c  |  19 +
> >  .../Ia32/ArchExceptionHandler.c                    | 135 +++++++
> >  .../Ia32/ArchInterruptDefs.h                       | 136 +++++++
> >  .../Ia32/ExceptionTssEntryAsm.nasm                 | 398
> > +++++++++++++++++++++
> >  .../PeiCpuExceptionHandlerLib.inf                  |   1 +
> >  .../SecPeiCpuExceptionHandlerLib.inf               |   3 +
> >  .../SmmCpuExceptionHandlerLib.inf                  |   1 +
> >  .../X64/ArchExceptionHandler.c                     | 108 ++++++
> >  .../CpuExceptionHandlerLib/X64/ArchInterruptDefs.h |  40 +++
> >  .../X64/ExceptionHandlerAsm.S                      |  12 +
> >  .../X64/ExceptionHandlerAsm.asm                    |  12 +
> >  .../X64/ExceptionHandlerAsm.nasm                   |  12 +
> >  14 files changed, 904 insertions(+)
> >  create mode 100644
> >
> UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ExceptionTssEntryAsm.nasm
> >
> > diff --git
> > a/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h
> > b/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h
> > index 740a58828b..fd4a26a458 100644
> > --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h
> > +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h
> > @@ -25,6 +25,7 @@
> >  #include <Library/BaseMemoryLib.h>
> >  #include <Library/SynchronizationLib.h>
> >  #include <Library/CpuExceptionHandlerLib.h>
> > +#include <Library/MemoryAllocationLib.h>
> >
> >  #define  CPU_EXCEPTION_NUM          32
> >  #define  CPU_INTERRUPT_NUM         256
> > @@ -288,5 +289,26 @@ CommonExceptionHandlerWorker (
> >    IN EXCEPTION_HANDLER_DATA      *ExceptionHandlerData
> >    );
> >
> > +/**
> > +  Load given selector into TR register
> > +
> > +  @param Selector         Task segment selector
> > +**/
> > +VOID
> > +AsmWriteTr (
> > +  UINT16 Selector
> > +  );
> > +
> > +/**
> > +  Setup separate stack for specific exceptions.
> > +
> > +  @param[in] IdtTable        IDT table base.
> > +**/
> > +VOID
> > +EFIAPI
> > +ArchSetupExcpetionStack (
> > +  IN IA32_IDT_GATE_DESCRIPTOR           *IdtTable
> > +  );
> > +
> >  #endif
> >
> > diff --git
> >
> a/UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandlerLib.inf
> >
> b/UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandlerLib.inf
> > index f4a8d01c80..b099ef4dad 100644
> > ---
> >
> a/UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandlerLib.inf
> > +++
> >
> b/UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandlerLib.inf
> > @@ -30,6 +30,7 @@
> >  [Sources.Ia32]
> >    Ia32/ExceptionHandlerAsm.asm
> >    Ia32/ExceptionHandlerAsm.nasm
> > +  Ia32/ExceptionTssEntryAsm.nasm
> >    Ia32/ExceptionHandlerAsm.S
> >    Ia32/ArchExceptionHandler.c
> >    Ia32/ArchInterruptDefs.h
> > @@ -47,6 +48,9 @@
> >    PeiDxeSmmCpuException.c
> >    DxeException.c
> >
> > +[Pcd]
> > +  gEfiMdeModulePkgTokenSpaceGuid.PcdCpuStackGuard
> > +
> >  [Packages]
> >    MdePkg/MdePkg.dec
> >    MdeModulePkg/MdeModulePkg.dec
> > @@ -61,3 +65,4 @@
> >    PeCoffGetEntryPointLib
> >    MemoryAllocationLib
> >    DebugLib
> > +  HobLib
> > diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeException.c
> > b/UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeException.c
> > index 31febec976..e9dcd00e02 100644
> > --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeException.c
> > +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeException.c
> > @@ -16,6 +16,7 @@
> >  #include "CpuExceptionCommon.h"
> >  #include <Library/DebugLib.h>
> >  #include <Library/MemoryAllocationLib.h>
> > +#include <Library/HobLib.h>
> >
> >  CONST UINTN    mDoFarReturnFlag  = 0;
> >
> > @@ -155,6 +156,24 @@ InitializeCpuInterruptHandlers (
> >
> >    UpdateIdtTable (IdtTable, &TemplateMap, &mExceptionHandlerData);
> >
> > +  if (PcdGetBool (PcdCpuStackGuard)) {
> > +    //
> > +    // Stack Guard works with the support of page table established and
> > +    // memory management. So we have to exclude those boot modes
> > without
> > +    // them.
> > +    //
> > +    switch (GetBootModeHob()) {
> > +    case BOOT_ON_FLASH_UPDATE:
> > +    case BOOT_IN_RECOVERY_MODE:
> > +    case BOOT_ON_S3_RESUME:
> > +      break;
> > +
> > +    default:
> > +      ArchSetupExcpetionStack (IdtTable);
> > +      break;
> > +    }
> > +  }
> > +
> >    //
> >    // Load Interrupt Descriptor Table
> >    //
> > diff --git
> > a/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchExceptionHandler.c
> > b/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchExceptionHandler.c
> > index f2c39eb193..3d41df75a5 100644
> > ---
> a/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchExceptionHandler.c
> > +++
> > b/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchExceptionHandler.c
> > @@ -14,6 +14,19 @@
> >
> >  #include "CpuExceptionCommon.h"
> >
> > +//
> > +// List of exceptions needing separate stack
> > +//
> > +STATIC IA32_EXCEPTION_TS_ENTRY mExceptionsWithStack[] = {
> > +  {6,  ExceptionTaskSwtichEntry6},  //#UD: Invalid Opcode Exception
> > +  {8,  ExceptionTaskSwtichEntry8},  //#DF: Double Fault Exception
> > +  {12, ExceptionTaskSwtichEntry12}, //#SS: Stack Fault Exception
> > +  {13, ExceptionTaskSwtichEntry13}, //#GP: General Protection Exception
> > +  {14, ExceptionTaskSwtichEntry14}, //#PF: Page-Fault Exception
> > +  {17, ExceptionTaskSwtichEntry17}, //#AC: Alignment Check Exception
> > +  {18, ExceptionTaskSwtichEntry18}  //#MC: Machine-Check Exception
> > +};
> > +
> >  /**
> >    Return address map of exception handler template so that C code can
> > generate
> >    exception tables.
> > @@ -107,6 +120,128 @@ ArchRestoreExceptionContext (
> >    SystemContext.SystemContextIa32->ExceptionData =
> > ReservedVectors[ExceptionType].ExceptionData;
> >  }
> >
> > +/**
> > +  Setup separate stack for specific exceptions.
> > +
> > +   @param[in] IdtTable        IDT table base.
> > +**/
> > +VOID
> > +EFIAPI
> > +ArchSetupExcpetionStack (
> > +  IN IA32_IDT_GATE_DESCRIPTOR           *IdtTable
> > +  )
> > +{
> > +  VOID                      *NewGdt;
> > +  IA32_DESCRIPTOR           GdtDesc;
> > +  UINTN                     OldGdtSize;
> > +  TSS_ENTRIES               *TssEntry;
> > +  IA32_TSS_DESCRIPTOR       *TssDesc;
> > +  IA32_TASK_STATE_SEGMENT   *Tss;
> > +  UINTN                     StackBase;
> > +  UINTN                     StackTop;
> > +  UINTN                     StackSize;
> > +  UINTN                     Index;
> > +  UINTN                     Vector;
> > +  UINTN                     TssBase;
> > +
> > +  //
> > +  // Allocate Runtime Data for the GDT
> > +  //
> > +  AsmReadGdtr(&GdtDesc);
> > +  OldGdtSize = GdtDesc.Limit + 1;
> > +  NewGdt = AllocateRuntimeZeroPool(OldGdtSize + sizeof(TSS_ENTRIES)
> > +                                   + IA32_GDT_ALIGNMENT);
> > +  if (NewGdt == NULL) {
> > +    return;
> > +  }
> > +  NewGdt = ALIGN_POINTER (NewGdt, IA32_GDT_ALIGNMENT);
> > +
> > +  //
> > +  // Initialize new GDT entries
> > +  //
> > +  CopyMem(NewGdt, (VOID *)GdtDesc.Base, OldGdtSize);
> > +  GdtDesc.Base = (UINTN)(VOID*)NewGdt;
> > +  GdtDesc.Limit = (UINT16)(OldGdtSize + TSS_OFFSET - 1);
> > +
> > +  //
> > +  // Reserve statck memory for given exceptions
> > +  //
> > +  StackSize = ARRAY_SIZE (mExceptionsWithStack) * EXCEPTION_STACK_SIZE;
> > +  StackSize = EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (StackSize));
> > +  StackBase = (UINT64)(UINTN)AllocatePages (EFI_SIZE_TO_PAGES
> > (StackSize));
> > +  if (StackBase == 0) {
> > +    FreePool (NewGdt);
> > +    return;
> > +  }
> > +
> > +  //
> > +  // Fixup TSS descriptors and segments
> > +  //
> > +  TssEntry = (VOID *)(GdtDesc.Base + OldGdtSize);
> > +
> > +  TssBase = (UINTN)(VOID *)&TssEntry->Tss;
> > +  TssEntry->TssSeg.Limit15_0            =
> > sizeof(IA32_TASK_STATE_SEGMENT) - 1;
> > +  TssEntry->TssSeg.Base15_0             = (UINT16)TssBase;
> > +  TssEntry->TssSeg.Base23_16            = (UINT8)(TssBase >> 16);
> > +  TssEntry->TssSeg.Type                 = IA32_GDT_TYPE_TSS;
> > +  TssEntry->TssSeg.Limit19_16_and_flags = 0;
> > +  TssEntry->TssSeg.Base31_24            = (UINT8)(TssBase >> 24);
> > +
> > +  StackTop  = StackBase + StackSize - CPU_STACK_ALIGNMENT;
> > +  StackTop  = (UINTN)ALIGN_POINTER (StackTop, CPU_STACK_ALIGNMENT);
> > +  for (Index = 0; Index < ARRAY_SIZE (mExceptionsWithStack); ++Index) {
> > +    //
> > +    // Fixup TSS descriptor
> > +    //
> > +    TssBase = (UINTN)(VOID *)&TssEntry->ExceptionTss[Index];
> > +    TssDesc = &TssEntry->ExceptionTssSeg[Index];
> > +
> > +    TssDesc->Limit15_0            = sizeof(IA32_TASK_STATE_SEGMENT) - 1;
> > +    TssDesc->Base15_0             = (UINT16)TssBase;
> > +    TssDesc->Base23_16            = (UINT8)(TssBase >> 16);
> > +    TssDesc->Type                 = IA32_GDT_TYPE_TSS;
> > +    TssDesc->Limit19_16_and_flags = 0;
> > +    TssDesc->Base31_24            = (UINT8)(TssBase >> 24);
> > +
> > +    //
> > +    // Fixup TSS
> > +    //
> > +    Tss = &TssEntry->ExceptionTss[Index];
> > +    Tss->CR3    = AsmReadCr3();
> > +    Tss->EIP    = (UINT32)mExceptionsWithStack[Index].EntryPoint;
> > +    Tss->EFLAGS = 0x2;
> > +    Tss->ESP    = StackTop;
> > +    Tss->ES     = AsmReadEs();
> > +    Tss->CS     = AsmReadCs();
> > +    Tss->SS     = AsmReadSs();
> > +    Tss->DS     = AsmReadDs();
> > +    Tss->FS     = AsmReadFs();
> > +    Tss->GS     = AsmReadGs();
> > +    StackTop   -= EXCEPTION_STACK_SIZE;
> > +
> > +    //
> > +    // Change specified exceptions in IDT to use TSS
> > +    //
> > +    Vector = mExceptionsWithStack[Index].Vector;
> > +
> > +    IdtTable[Vector].Bits.OffsetLow  = 0;
> > +    IdtTable[Vector].Bits.Selector   = OldGdtSize +
> > EXCEPTION_TSS_SEL(Index);
> > +    IdtTable[Vector].Bits.Reserved_0 = 0;
> > +    IdtTable[Vector].Bits.GateType   = IA32_IDT_GATE_TYPE_TASK;
> > +    IdtTable[Vector].Bits.OffsetHigh = 0;
> > +  }
> > +
> > +  //
> > +  // Publish the changes
> > +  //
> > +  AsmWriteGdtr(&GdtDesc);
> > +
> > +  //
> > +  // Load task register
> > +  //
> > +  AsmWriteTr ((UINT16)(OldGdtSize + TSS_SEL));
> > +}
> > +
> >  /**
> >    Display processor context.
> >
> > diff --git
> > a/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchInterruptDefs.h
> > b/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchInterruptDefs.h
> > index a8d3556a80..77cc6f9919 100644
> > --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchInterruptDefs.h
> > +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchInterruptDefs.h
> > @@ -41,4 +41,140 @@ typedef struct {
> >    UINT8       HookAfterStubHeaderCode[HOOKAFTER_STUB_SIZE];
> >  } RESERVED_VECTORS_DATA;
> >
> > +#pragma pack (1)
> > +
> > +#define EXCEPTION_LIST_MAX          7
> > +#define EXCEPTION_STACK_SIZE        EFI_PAGE_SIZE
> > +#define IA32_GDT_TYPE_TSS           0x89
> > +#define IA32_GDT_ALIGNMENT          8
> > +
> > +//
> > +// IA32 TSS Definition
> > +//
> > +typedef struct {
> > +  UINT16    PreviousTaskLink; // 00
> > +  UINT16    Reserved_2;
> > +  UINT32    ESP0;             // 04
> > +  UINT16    SS0;              // 08
> > +  UINT16    Reserved_10;
> > +  UINT32    ESP1;             // 0C
> > +  UINT16    SS1;              // 10
> > +  UINT16    Reserved_18;
> > +  UINT32    ESP2;             // 14
> > +  UINT16    SS2;              // 18
> > +  UINT16    Reserved_26;
> > +  UINT32    CR3;              // 1C
> > +  UINT32    EIP;              // 20
> > +  UINT32    EFLAGS;           // 24
> > +  UINT32    EAX;              // 28
> > +  UINT32    ECX;              // 2C
> > +  UINT32    EDX;              // 30
> > +  UINT32    EBX;              // 34
> > +  UINT32    ESP;              // 38
> > +  UINT32    EBP;
> > +  UINT32    ESI;
> > +  UINT32    EDI;
> > +  UINT16    ES;
> > +  UINT16    Reserved_74;
> > +  UINT16    CS;
> > +  UINT16    Reserved_78;
> > +  UINT16    SS;
> > +  UINT16    Reserved_82;
> > +  UINT16    DS;
> > +  UINT16    Reserved_86;
> > +  UINT16    FS;
> > +  UINT16    Reserved_90;
> > +  UINT16    GS;
> > +  UINT16    Reserved_94;
> > +  UINT16    LDTSegmentSelector;
> > +  UINT16    Reserved_98;
> > +  UINT16    T;
> > +  UINT16    IOMapBaseAddress;
> > +} IA32_TASK_STATE_SEGMENT;
> > +
> > +typedef struct {
> > +  UINT16    Limit15_0;
> > +  UINT16    Base15_0;
> > +  UINT8     Base23_16;
> > +  UINT8     Type;
> > +  UINT8     Limit19_16_and_flags;
> > +  UINT8     Base31_24;
> > +} IA32_TSS_DESCRIPTOR;
> > +
> > +typedef struct {
> > +  IA32_TSS_DESCRIPTOR           TssSeg;
> > +  IA32_TSS_DESCRIPTOR           ExceptionTssSeg[EXCEPTION_LIST_MAX];
> > +  IA32_TASK_STATE_SEGMENT       Tss;
> > +  IA32_TASK_STATE_SEGMENT       ExceptionTss[EXCEPTION_LIST_MAX];
> > +} TSS_ENTRIES;
> > +
> > +#pragma pack ()
> > +
> > +#define TSS_SEL               OFFSET_OF (TSS_ENTRIES, TssSeg)
> > +#define EXCEPTION_TSS_SEL(n)  OFFSET_OF (TSS_ENTRIES,
> > ExceptionTssSeg[n])
> > +#define TSS_OFFSET            OFFSET_OF (TSS_ENTRIES, Tss)
> > +
> > +typedef VOID (*EXCEPTION_ENTRY) (VOID);
> > +
> > +typedef struct {
> > +  UINTN             Vector;
> > +  EXCEPTION_ENTRY   EntryPoint;
> > +} IA32_EXCEPTION_TS_ENTRY;
> > +
> > +/**
> > + Exception handling entry through task gate for exception #UD.
> > + **/
> > +VOID
> > +ExceptionTaskSwtichEntry6 (
> > +  VOID
> > +  );
> > +
> > +/**
> > + Exception handling entry through task gate for exception #DF.
> > + **/
> > +VOID
> > +ExceptionTaskSwtichEntry8 (
> > +  VOID
> > +  );
> > +
> > +/**
> > + Exception handling entry through task gate for exception #SS.
> > + **/
> > +VOID
> > +ExceptionTaskSwtichEntry12 (
> > +  VOID
> > +  );
> > +
> > +/**
> > + Exception handling entry through task gate for exception #GP.
> > + **/
> > +VOID
> > +ExceptionTaskSwtichEntry13 (
> > +  VOID
> > +  );
> > +
> > +/**
> > + Exception handling entry through task gate for exception #PF.
> > + **/
> > +VOID
> > +ExceptionTaskSwtichEntry14 (
> > +  VOID
> > +  );
> > +
> > +/**
> > + Exception handling entry through task gate for exception #AC.
> > + **/
> > +VOID
> > +ExceptionTaskSwtichEntry17 (
> > +  VOID
> > +  );
> > +
> > +/**
> > + Exception handling entry through task gate for exception #MC.
> > + **/
> > +VOID
> > +ExceptionTaskSwtichEntry18 (
> > +  VOID
> > +  );
> > +
> >  #endif
> > diff --git
> >
> a/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ExceptionTssEntryAsm.nas
> > m
> >
> b/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ExceptionTssEntryAsm.nas
> > m
> > new file mode 100644
> > index 0000000000..dbfbcfcf51
> > --- /dev/null
> > +++
> >
> b/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ExceptionTssEntryAsm.nas
> > m
> > @@ -0,0 +1,398 @@
> > +;------------------------------------------------------------------------------
> >  ;
> > +; Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
> > +; This program and the accompanying materials
> > +; are licensed and made available under the terms and conditions of the BSD
> > License
> > +; which accompanies this distribution.  The full text of the license may be
> found
> > at
> > +; http://opensource.org/licenses/bsd-license.php.
> > +;
> > +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> BASIS,
> > +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> EXPRESS
> > OR IMPLIED.
> > +;
> > +; Module Name:
> > +;
> > +;   ExceptionTssEntryAsm.Asm
> > +;
> > +; Abstract:
> > +;
> > +;   IA32 CPU Exception Handler with Separate Stack
> > +;
> > +; Notes:
> > +;
> > +;------------------------------------------------------------------------------
> > +
> > +;
> > +; IA32 TSS Memory Layout Description
> > +;
> > +struc IA32_TSS
> > +                    resw 1
> > +                    resw 1
> > +  .ESP0:    resd 1
> > +  .SS0:     resw 1
> > +                    resw 1
> > +  .ESP1:    resd 1
> > +  .SS1:     resw 1
> > +                    resw 1
> > +  .ESP2:    resd 1
> > +  .SS2:     resw 1
> > +                    resw 1
> > +  ._CR3:    resd 1
> > +  .EIP:     resd 1
> > +  .EFLAGS:  resd 1
> > +  ._EAX:    resd 1
> > +  ._ECX:    resd 1
> > +  ._EDX:    resd 1
> > +  ._EBX:    resd 1
> > +  ._ESP:    resd 1
> > +  ._EBP:    resd 1
> > +  ._ESI:    resd 1
> > +  ._EDI:    resd 1
> > +  ._ES:     resw 1
> > +                    resw 1
> > +  ._CS:     resw 1
> > +                    resw 1
> > +  ._SS:     resw 1
> > +                    resw 1
> > +  ._DS:     resw 1
> > +                    resw 1
> > +  ._FS:     resw 1
> > +                    resw 1
> > +  ._GS:     resw 1
> > +                    resw 1
> > +  .LDT:     resw 1
> > +                    resw 1
> > +                    resw 1
> > +                    resw 1
> > +endstruc
> > +
> > +;
> > +; CommonExceptionHandler()
> > +;
> > +extern ASM_PFX(CommonExceptionHandler)
> > +
> > +SECTION .data
> > +
> > +SECTION .text
> > +
> > +ALIGN   8
> > +
> > +;
> > +; exception handler stub table
> > +;
> > +%macro DefExceptionTaskSwtichEntry 1
> > +%%DoIret:
> > +    iretd
> > +
> > +global ASM_PFX(ExceptionTaskSwtichEntry%1)
> > +ASM_PFX(ExceptionTaskSwtichEntry%1):
> > +    db      0x6a        ; push  #VectorNum
> > +    db      %1          ; VectorNum
> > +    mov     eax, ASM_PFX(CommonTaskSwtichEntryPoint)
> > +    call    eax
> > +    mov     esp, eax    ; Restore stack top
> > +    jmp     %%DoIret
> > +%endmacro
> > +
> > +global ASM_PFX(CommonTaskSwtichEntryPoint)
> > +ASM_PFX(CommonTaskSwtichEntryPoint):
> > +    ;
> > +    ; Stack:
> > +    ; +---------------------+ <-- EBP - 8
> > +    ; +       TSS Base      +
> > +    ; +---------------------+ <-- EBP - 4
> > +    ; +      CPUID.EDX      +
> > +    ; +---------------------+ <-- EBP
> > +    ; +         EIP         +
> > +    ; +---------------------+ <-- EBP + 4
> > +    ; +    Vector Number    +
> > +    ; +---------------------+ <-- EBP + 8
> > +    ; +    Error Code       +
> > +    ; +---------------------+
> > +    ;
> > +;
> > +; Get TSS of interrupted task
> > +;
> > +    mov     ebp, esp                    ; Stack frame
> > +
> > +; Use CPUID to determine if FXSAVE/FXRESTOR and DE are supported
> > +    mov     eax, 1
> > +    cpuid
> > +    push    edx
> > +
> > +; Get TSS base of interrupted task through PreviousTaskLink field in
> > +; current TSS base
> > +    sub     esp, 8
> > +    sgdt    [esp + 2]
> > +    mov     eax, [esp + 4]              ; GDT base
> > +    add     esp, 8
> > +
> > +    xor     ebx, ebx
> > +    str     bx                          ; Current TR
> > +
> > +    mov     ecx, [eax + ebx + 2]
> > +    shl     ecx, 8
> > +    mov     cl, [eax + ebx + 7]
> > +    ror     ecx, 8                      ; ecx = Current TSS base
> > +    push    ecx                         ; keep it in stack for later use
> > +
> > +    movzx   ebx, word [ecx]             ; Previous Task Link
> > +    mov     ecx, [eax + ebx + 2]
> > +    shl     ecx, 8
> > +    mov     cl, [eax + ebx + 7]
> > +    ror     ecx, 8                      ; ecx = Previous TSS base
> > +
> > +;
> > +; Align stack to make sure that EFI_FX_SAVE_STATE_IA32 of
> > EFI_SYSTEM_CONTEXT_IA32
> > +; is 16-byte aligned
> > +;
> > +    and     esp, 0xfffffff0
> > +    sub     esp, 12
> > +
> > +;; UINT32  Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;
> > +    push    dword [ecx + IA32_TSS._EAX]
> > +    push    dword [ecx + IA32_TSS._ECX]
> > +    push    dword [ecx + IA32_TSS._EDX]
> > +    push    dword [ecx + IA32_TSS._EBX]
> > +    push    dword [ecx + IA32_TSS._ESP]
> > +    push    dword [ecx + IA32_TSS._EBP]
> > +    push    dword [ecx + IA32_TSS._ESI]
> > +    push    dword [ecx + IA32_TSS._EDI]
> > +
> > +;; UINT32  Gs, Fs, Es, Ds, Cs, Ss;
> > +    movzx   eax, word [ecx + IA32_TSS._SS]
> > +    push    eax
> > +    movzx   eax, word [ecx + IA32_TSS._CS]
> > +    push    eax
> > +    movzx   eax, word [ecx + IA32_TSS._DS]
> > +    push    eax
> > +    movzx   eax, word [ecx + IA32_TSS._ES]
> > +    push    eax
> > +    movzx   eax, word [ecx + IA32_TSS._FS]
> > +    push    eax
> > +    movzx   eax, word [ecx + IA32_TSS._GS]
> > +    push    eax
> > +
> > +;; UINT32  Eip;
> > +    push    dword [ecx + IA32_TSS.EIP]
> > +
> > +;; UINT32  Gdtr[2], Idtr[2];
> > +    sub     esp, 8
> > +    sidt    [esp]
> > +    mov     eax, [esp + 2]
> > +    xchg    eax, [esp]
> > +    and     eax, 0xFFFF
> > +    mov     [esp+4], eax
> > +
> > +    sub     esp, 8
> > +    sgdt    [esp]
> > +    mov     eax, [esp + 2]
> > +    xchg    eax, [esp]
> > +    and     eax, 0xFFFF
> > +    mov     [esp+4], eax
> > +
> > +;; UINT32  Ldtr, Tr;
> > +    mov     eax, ebx    ; ebx still keeps selector of interrupted task
> > +    push    eax
> > +    movzx   eax, word [ecx + IA32_TSS.LDT]
> > +    push    eax
> > +
> > +;; UINT32  EFlags;
> > +    push    dword [ecx + IA32_TSS.EFLAGS]
> > +
> > +;; UINT32  Cr0, Cr1, Cr2, Cr3, Cr4;
> > +    mov     eax, cr4
> > +    push    eax             ; push cr4 firstly
> > +
> > +    mov     edx, [ebp - 4]  ; cpuid.edx
> > +    test    edx, BIT24      ; Test for FXSAVE/FXRESTOR support
> > +    jz      .1
> > +    or      eax, BIT9       ; Set CR4.OSFXSR
> > +.1:
> > +    test    edx, BIT2       ; Test for Debugging Extensions support
> > +    jz      .2
> > +    or      eax, BIT3       ; Set CR4.DE
> > +.2:
> > +    mov     cr4, eax
> > +
> > +    mov     eax, cr3
> > +    push    eax
> > +    mov     eax, cr2
> > +    push    eax
> > +    xor     eax, eax
> > +    push    eax
> > +    mov     eax, cr0
> > +    push    eax
> > +
> > +;; UINT32  Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
> > +    mov     eax, dr7
> > +    push    eax
> > +    mov     eax, dr6
> > +    push    eax
> > +    mov     eax, dr3
> > +    push    eax
> > +    mov     eax, dr2
> > +    push    eax
> > +    mov     eax, dr1
> > +    push    eax
> > +    mov     eax, dr0
> > +    push    eax
> > +
> > +;; FX_SAVE_STATE_IA32 FxSaveState;
> > +;; Clear TS bit in CR0 to avoid Device Not Available Exception (#NM)
> > +;; when executing fxsave/fxrstor instruction
> > +    test    edx, BIT24  ; Test for FXSAVE/FXRESTOR support.
> > +                        ; edx still contains result from CPUID above
> > +    jz      .3
> > +    clts
> > +    sub     esp, 512
> > +    mov     edi, esp
> > +    db      0xf, 0xae, 0x7 ;fxsave [edi]
> > +.3:
> > +
> > +;; UINT32  ExceptionData;
> > +    push    dword [ebp + 8]
> > +
> > +;; UEFI calling convention for IA32 requires that Direction flag in EFLAGs 
> > is
> clear
> > +    cld
> > +
> > +;; call into exception handler
> > +    mov     esi, ecx            ; Keep TSS base to avoid overwrite
> > +    mov     eax, ASM_PFX(CommonExceptionHandler)
> > +
> > +;; Prepare parameter and call
> > +    mov     edx, esp
> > +    push    edx                 ; EFI_SYSTEM_CONTEXT
> > +    push    dword [ebp + 4]     ; EFI_EXCEPTION_TYPE (vector number)
> > +
> > +    ;
> > +    ; Call External Exception Handler
> > +    ;
> > +    call    eax
> > +    add     esp, 8              ; Restore stack before calling
> > +    mov     ecx, esi            ; Restore TSS base
> > +
> > +;; UINT32  ExceptionData;
> > +    add     esp, 4
> > +
> > +;; FX_SAVE_STATE_IA32 FxSaveState;
> > +    mov     edx, [ebp - 4]  ; cpuid.edx
> > +    test    edx, BIT24      ; Test for FXSAVE/FXRESTOR support
> > +    jz      .4
> > +    mov     esi, esp
> > +    db      0xf, 0xae, 0xe  ; fxrstor [esi]
> > +.4:
> > +    add     esp, 512
> > +
> > +;; UINT32  Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
> > +;; Skip restoration of DRx registers to support debuggers
> > +;; that set breakpoints in interrupt/exception context
> > +    add     esp, 4 * 6
> > +
> > +;; UINT32  Cr0, Cr1, Cr2, Cr3, Cr4;
> > +    pop     eax
> > +    mov     cr0, eax
> > +    add     esp, 4    ; not for Cr1
> > +    pop     eax
> > +    mov     cr2, eax
> > +    pop     eax
> > +    mov     dword [ecx + IA32_TSS._CR3], eax
> > +    pop     eax
> > +    mov     cr4, eax
> > +
> > +;; UINT32  EFlags;
> > +    pop     dword [ecx + IA32_TSS.EFLAGS]
> > +    mov     ebx, dword [ecx + IA32_TSS.EFLAGS]
> > +    btr     ebx, 9      ; Do 'cli'
> > +    mov     dword [ecx + IA32_TSS.EFLAGS], ebx
> > +
> > +;; UINT32  Ldtr, Tr;
> > +;; UINT32  Gdtr[2], Idtr[2];
> > +;; Best not let anyone mess with these particular registers...
> > +    add     esp, 24
> > +
> > +;; UINT32  Eip;
> > +    pop     dword [ecx + IA32_TSS.EIP]
> > +
> > +;; UINT32  Gs, Fs, Es, Ds, Cs, Ss;
> > +;; NOTE - modified segment registers could hang the debugger...  We
> > +;;        could attempt to insulate ourselves against this possibility,
> > +;;        but that poses risks as well.
> > +;;
> > +    pop     eax
> > +o16 mov     [ecx + IA32_TSS._GS], ax
> > +    pop     eax
> > +o16 mov     [ecx + IA32_TSS._FS], ax
> > +    pop     eax
> > +o16 mov     [ecx + IA32_TSS._ES], ax
> > +    pop     eax
> > +o16 mov     [ecx + IA32_TSS._DS], ax
> > +    pop     eax
> > +o16 mov     [ecx + IA32_TSS._CS], ax
> > +    pop     eax
> > +o16 mov     [ecx + IA32_TSS._SS], ax
> > +
> > +;; UINT32  Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;
> > +    pop     dword [ecx + IA32_TSS._EDI]
> > +    pop     dword [ecx + IA32_TSS._ESI]
> > +    add     esp, 4   ; not for ebp
> > +    add     esp, 4   ; not for esp
> > +    pop     dword [ecx + IA32_TSS._EBX]
> > +    pop     dword [ecx + IA32_TSS._EDX]
> > +    pop     dword [ecx + IA32_TSS._ECX]
> > +    pop     dword [ecx + IA32_TSS._EAX]
> > +
> > +; Set single step DB# to allow debugger to able to go back to the EIP
> > +; where the exception is triggered.
> > +
> > +;; Create return context for iretd in stub function
> > +    mov    eax, dword [ecx + IA32_TSS._ESP]      ; Get old stack pointer
> > +    mov    ebx, dword [ecx + IA32_TSS.EIP]
> > +    mov    [eax - 0xc], ebx                      ; create EIP in old stack
> > +    movzx  ebx, word [ecx + IA32_TSS._CS]
> > +    mov    [eax - 0x8], ebx                      ; create CS in old stack
> > +    mov    ebx, dword [ecx + IA32_TSS.EFLAGS]
> > +    bts    ebx, 8
> > +    mov    [eax - 0x4], ebx                      ; create eflags in old 
> > stack
> > +    mov    dword [ecx + IA32_TSS.EFLAGS], ebx    ; update eflags in old TSS
> > +    mov    eax, dword [ecx + IA32_TSS._ESP]      ; Get old stack pointer
> > +    sub    eax, 0xc                              ; minus 12 byte
> > +    mov    dword [ecx + IA32_TSS._ESP], eax      ; Set new stack pointer
> > +
> > +;; Replace the EIP of interrupted task with stub function
> > +    mov    eax, ASM_PFX(SingleStepStubFunction)
> > +    mov    dword [ecx + IA32_TSS.EIP], eax
> > +
> > +    mov     ecx, [ebp - 8]                       ; Get current TSS base
> > +    mov     eax, dword [ecx + IA32_TSS._ESP]     ; Return current stack top
> > +    mov     esp, ebp
> > +
> > +    ret
> > +
> > +global ASM_PFX(SingleStepStubFunction)
> > +ASM_PFX(SingleStepStubFunction):
> > +;
> > +; we need clean TS bit in CR0 to execute
> > +; x87 FPU/MMX/SSE/SSE2/SSE3/SSSE3/SSE4 instructions.
> > +;
> > +    clts
> > +    iretd
> > +
> > +;------------------------------------------------------------------------------
> > +; VOID
> > +; AsmWriteTr (
> > +;   UINT16 Selector
> > +;   );
> > +;------------------------------------------------------------------------------
> > +global ASM_PFX(AsmWriteTr)
> > +ASM_PFX(AsmWriteTr):
> > +    mov     eax, [esp+4]
> > +    ltr     ax
> > +    ret
> > +
> > +DefExceptionTaskSwtichEntry 6
> > +DefExceptionTaskSwtichEntry 8
> > +DefExceptionTaskSwtichEntry 12
> > +DefExceptionTaskSwtichEntry 13
> > +DefExceptionTaskSwtichEntry 14
> > +DefExceptionTaskSwtichEntry 17
> > +DefExceptionTaskSwtichEntry 18
> > +
> > diff --git
> > a/UefiCpuPkg/Library/CpuExceptionHandlerLib/PeiCpuExceptionHandlerLib.inf
> > b/UefiCpuPkg/Library/CpuExceptionHandlerLib/PeiCpuExceptionHandlerLib.inf
> > index 75443288a9..4c0d435136 100644
> > ---
> > a/UefiCpuPkg/Library/CpuExceptionHandlerLib/PeiCpuExceptionHandlerLib.inf
> > +++
> > b/UefiCpuPkg/Library/CpuExceptionHandlerLib/PeiCpuExceptionHandlerLib.inf
> > @@ -30,6 +30,7 @@
> >  [Sources.Ia32]
> >    Ia32/ExceptionHandlerAsm.asm
> >    Ia32/ExceptionHandlerAsm.nasm
> > +  Ia32/ExceptionTssEntryAsm.nasm
> >    Ia32/ExceptionHandlerAsm.S
> >    Ia32/ArchExceptionHandler.c
> >    Ia32/ArchInterruptDefs.h
> > diff --git
> >
> a/UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuExceptionHandlerLib.i
> > nf
> >
> b/UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuExceptionHandlerLib.i
> > nf
> > index d70a99c100..adb415ba5a 100644
> > ---
> >
> a/UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuExceptionHandlerLib.i
> > nf
> > +++
> >
> b/UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuExceptionHandlerLib.i
> > nf
> > @@ -30,6 +30,7 @@
> >  [Sources.Ia32]
> >    Ia32/ExceptionHandlerAsm.asm
> >    Ia32/ExceptionHandlerAsm.nasm
> > +  Ia32/ExceptionTssEntryAsm.nasm
> >    Ia32/ExceptionHandlerAsm.S
> >    Ia32/ArchExceptionHandler.c
> >    Ia32/ArchInterruptDefs.h
> > @@ -57,3 +58,5 @@
> >    PrintLib
> >    LocalApicLib
> >    PeCoffGetEntryPointLib
> > +  MemoryAllocationLib
> > +
> > diff --git
> >
> a/UefiCpuPkg/Library/CpuExceptionHandlerLib/SmmCpuExceptionHandlerLib.inf
> >
> b/UefiCpuPkg/Library/CpuExceptionHandlerLib/SmmCpuExceptionHandlerLib.inf
> > index 634ffcb21d..56b875b7c8 100644
> > ---
> >
> a/UefiCpuPkg/Library/CpuExceptionHandlerLib/SmmCpuExceptionHandlerLib.inf
> > +++
> >
> b/UefiCpuPkg/Library/CpuExceptionHandlerLib/SmmCpuExceptionHandlerLib.inf
> > @@ -30,6 +30,7 @@
> >  [Sources.Ia32]
> >    Ia32/ExceptionHandlerAsm.asm
> >    Ia32/ExceptionHandlerAsm.nasm
> > +  Ia32/ExceptionTssEntryAsm.nasm
> >    Ia32/ExceptionHandlerAsm.S
> >    Ia32/ArchExceptionHandler.c
> >    Ia32/ArchInterruptDefs.h
> > diff --git
> > a/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c
> > b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c
> > index 65f0cff680..24f2a8486a 100644
> > ---
> a/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c
> > +++
> b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c
> > @@ -14,6 +14,19 @@
> >
> >  #include "CpuExceptionCommon.h"
> >
> > +//
> > +// List of exceptions needing separate stack
> > +//
> > +STATIC UINTN  mExceptionsWithStack[] = {
> > +  6,  //#UD: Invalid Opcode Exception
> > +  8,  //#DF: Double Fault Exception
> > +  12, //#SS: Stack Fault Exception
> > +  13, //#GP: General Protection Exception
> > +  14, //#PF: Page-Fault Exception
> > +  17, //#AC: Alignment Check Exception
> > +  18  //#MC: Machine-Check Exception
> > +  };
> > +
> >  /**
> >    Return address map of exception handler template so that C code can
> > generate
> >    exception tables.
> > @@ -112,6 +125,101 @@ ArchRestoreExceptionContext (
> >    SystemContext.SystemContextX64->ExceptionData =
> > ReservedVectors[ExceptionType].ExceptionData;
> >  }
> >
> > +/**
> > +  Setup separate stack for specific exceptions.
> > +
> > +  @param[in] IdtTable        IDT table base.
> > +**/
> > +VOID
> > +EFIAPI
> > +ArchSetupExcpetionStack (
> > +  IN IA32_IDT_GATE_DESCRIPTOR           *IdtTable
> > +  )
> > +{
> > +  VOID                      *NewGdt;
> > +  IA32_DESCRIPTOR           GdtDesc;
> > +  UINTN                     OldGdtSize;
> > +  TSS_ENTRIES               *TssEntry;
> > +  UINTN                     StackBase;
> > +  UINTN                     StackTop;
> > +  UINTN                     StackSize;
> > +  UINTN                     TssBase;
> > +  UINTN                     Index;
> > +
> > +  //
> > +  // Allocate Runtime Data for the GDT
> > +  //
> > +  AsmReadGdtr(&GdtDesc);
> > +  OldGdtSize = GdtDesc.Limit + 1;
> > +  NewGdt = AllocateRuntimeZeroPool(OldGdtSize + sizeof(TSS_ENTRIES)
> > +                                + IA32_GDT_ALIGNMENT);
> > +  if (NewGdt == NULL) {
> > +    return;
> > +  }
> > +  NewGdt = ALIGN_POINTER (NewGdt, IA32_GDT_ALIGNMENT);
> > +
> > +  //
> > +  // Initialize new GDT entries
> > +  //
> > +  CopyMem(NewGdt, (VOID *)GdtDesc.Base, OldGdtSize);
> > +  GdtDesc.Base = (UINTN)(VOID*)NewGdt;
> > +  GdtDesc.Limit = (UINT16)(OldGdtSize + TSS_OFFSET - 1);
> > +
> > +  //
> > +  // Reserve statck memory for supported exceptions
> > +  //
> > +  StackSize = ARRAY_SIZE (mExceptionsWithStack) * EXCEPTION_STACK_SIZE;
> > +  StackSize = EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (StackSize));
> > +  StackBase = (UINT64)AllocatePages (EFI_SIZE_TO_PAGES (StackSize));
> > +  if (StackBase == 0) {
> > +    FreePool (NewGdt);
> > +    return;
> > +  }
> > +
> > +  //
> > +  // Fixup TSS descriptors
> > +  //
> > +  TssEntry = (VOID *)(GdtDesc.Base + OldGdtSize);
> > +  TssBase = (UINTN)(VOID *)&TssEntry->Tss;
> > +
> > +  TssEntry->TssSeg.Limit15_0            =
> > sizeof(IA32_TASK_STATE_SEGMENT) - 1;
> > +  TssEntry->TssSeg.Base15_0             = (UINT16)TssBase;
> > +  TssEntry->TssSeg.Base23_16            = (UINT8)(TssBase >> 16);
> > +  TssEntry->TssSeg.Type                 = IA32_GDT_TYPE_TSS;
> > +  TssEntry->TssSeg.Limit19_16_and_flags = 0;
> > +  TssEntry->TssSeg.Base31_24            = (UINT8)(TssBase >> 24);
> > +  TssEntry->TssSeg.Base63_32            = (UINT32)(TssBase >> 32);
> > +  TssEntry->TssSeg.Reserved             = 0;
> > +
> > +  //
> > +  // Enable Interrupt Stack Table (IST) for each required exception
> > +  //
> > +  StackTop  = StackBase + StackSize - CPU_STACK_ALIGNMENT;
> > +  StackTop  = (UINTN)ALIGN_POINTER (StackTop, CPU_STACK_ALIGNMENT);
> > +  for (Index = 0; Index < ARRAY_SIZE (mExceptionsWithStack); ++Index) {
> > +    //
> > +    // Fixup TSS
> > +    //
> > +    TssEntry->Tss.IST[Index] = StackTop;
> > +    StackTop -= EXCEPTION_STACK_SIZE;
> > +
> > +    //
> > +    // Set the IST field to 1 to enable corresponding IST
> > +    //
> > +    IdtTable[mExceptionsWithStack[Index]].Bits.Reserved_0 = (UINT8)(Index +
> > 1);
> > +  }
> > +
> > +  //
> > +  // Publish the changes
> > +  //
> > +  AsmWriteGdtr(&GdtDesc);
> > +
> > +  //
> > +  // Load task register
> > +  //
> > +  AsmWriteTr ((UINT16)(OldGdtSize + TSS_SEL));
> > +}
> > +
> >  /**
> >    Display CPU information.
> >
> > diff --git
> > a/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchInterruptDefs.h
> > b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchInterruptDefs.h
> > index 906480134a..5a913bae7b 100644
> > --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchInterruptDefs.h
> > +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchInterruptDefs.h
> > @@ -43,4 +43,44 @@ typedef struct {
> >    UINT8       HookAfterStubHeaderCode[HOOKAFTER_STUB_SIZE];
> >  } RESERVED_VECTORS_DATA;
> >
> > +#pragma pack (1)
> > +
> > +#define EXCEPTION_LIST_MAX        7
> > +#define EXCEPTION_STACK_SIZE      EFI_PAGE_SIZE
> > +#define IA32_GDT_TYPE_TSS         0x89
> > +#define IA32_GDT_ALIGNMENT        8
> > +
> > +typedef struct {
> > +  UINT32    Reserved_0;
> > +  UINT64    RSP0;
> > +  UINT64    RSP1;
> > +  UINT64    RSP2;
> > +  UINT64    Reserved_28;
> > +  UINT64    IST[7];
> > +  UINT64    Reserved_92;
> > +  UINT16    Reserved_100;
> > +  UINT16    IOMapBaseAddress;
> > +} IA32_TASK_STATE_SEGMENT;
> > +
> > +typedef struct {
> > +  UINT16    Limit15_0;
> > +  UINT16    Base15_0;
> > +  UINT8     Base23_16;
> > +  UINT8     Type;
> > +  UINT8     Limit19_16_and_flags;
> > +  UINT8     Base31_24;
> > +  UINT32    Base63_32;
> > +  UINT32    Reserved;
> > +} IA32_TSS_DESCRIPTOR;
> > +
> > +typedef struct {
> > +  IA32_TSS_DESCRIPTOR           TssSeg;
> > +  IA32_TASK_STATE_SEGMENT       Tss;
> > +} TSS_ENTRIES;
> > +
> > +#pragma pack ()
> > +
> > +#define TSS_SEL           OFFSET_OF (TSS_ENTRIES, TssSeg)
> > +#define TSS_OFFSET        OFFSET_OF (TSS_ENTRIES, Tss)
> > +
> >  #endif
> > diff --git
> > a/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ExceptionHandlerAsm.S
> > b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ExceptionHandlerAsm.S
> > index edd363cdaa..bdaf132cf5 100644
> > ---
> a/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ExceptionHandlerAsm.S
> > +++
> > b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ExceptionHandlerAsm.S
> > @@ -429,6 +429,18 @@ ASM_PFX(AsmVectorNumFixup):
> >      popq      %rbp
> >      ret
> >
> > +#------------------------------------------------------------------------------
> > +# VOID
> > +# AsmWriteTr (
> > +#   UINT16 Selector
> > +#   );
> > +#------------------------------------------------------------------------------
> > +ASM_GLOBAL ASM_PFX(AsmWriteTr)
> > +ASM_PFX(AsmWriteTr):
> > +    movl    %ecx, %eax
> > +    ltrw    %ax
> > +    ret
> > +
> >  #END
> >
> >
> > diff --git
> >
> a/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ExceptionHandlerAsm.asm
> >
> b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ExceptionHandlerAsm.asm
> > index 726c64a140..aec56ef4bf 100644
> > ---
> >
> a/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ExceptionHandlerAsm.asm
> > +++
> >
> b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ExceptionHandlerAsm.asm
> > @@ -386,4 +386,16 @@ AsmVectorNumFixup   PROC
> >      ret
> >  AsmVectorNumFixup   ENDP
> >
> > +;------------------------------------------------------------------------------
> > +; VOID
> > +; AsmWriteTr (
> > +;   UINT16 Selector
> > +;   );
> > +;------------------------------------------------------------------------------
> > +AsmWriteTr PROC PUBLIC
> > +    mov     eax, ecx
> > +    ltr     ax
> > +    ret
> > +AsmWriteTr ENDP
> > +
> >  END
> > diff --git
> >
> a/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ExceptionHandlerAsm.nasm
> >
> b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ExceptionHandlerAsm.nasm
> > index ba8993d84b..1e2ac411b0 100644
> > ---
> >
> a/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ExceptionHandlerAsm.nasm
> > +++
> >
> b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ExceptionHandlerAsm.nasm
> > @@ -385,3 +385,15 @@ ASM_PFX(AsmVectorNumFixup):
> >      mov     [rcx + (@VectorNum - HookAfterStubHeaderBegin)], al
> >      ret
> >
> > +;------------------------------------------------------------------------------
> > +; VOID
> > +; AsmWriteTr (
> > +;   UINT16 Selector
> > +;   );
> > +;------------------------------------------------------------------------------
> > +global ASM_PFX(AsmWriteTr)
> > +ASM_PFX(AsmWriteTr):
> > +    mov     eax, ecx
> > +    ltr     ax
> > +    ret
> > +
> > --
> > 2.14.1.windows.1

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel

Reply via email to