public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: "Yao, Jiewen" <jiewen.yao@intel.com>
To: "Wang, Jian J" <jian.j.wang@intel.com>,
	"edk2-devel@lists.01.org" <edk2-devel@lists.01.org>
Cc: "Zeng, Star" <star.zeng@intel.com>,
	"Dong, Eric" <eric.dong@intel.com>,
	"Kinney, Michael D" <michael.d.kinney@intel.com>
Subject: Re: [PATCH v2 7/8] UefiCpuPkg/CpuExceptionHandlerLib: Add stack switch support
Date: Thu, 23 Nov 2017 05:50:05 +0000	[thread overview]
Message-ID: <74D8A39837DF1E4DA445A8C0B3885C503AA292EF@shsmsx102.ccr.corp.intel.com> (raw)
In-Reply-To: <20171122084548.6564-8-jian.j.wang@intel.com>

Some thought:

1) I found InitializeCpuExceptionStackSwitchHandlers() is only implemented in DxeException.c.
What about Pei/Smm instance?

I think it is OK to not implement it at this moment. But we need make sure no architecture issue if we want to enable it some time later.

2) #define IA32_GDT_TYPE_TSS           0x9
This is generic, can we move to BaseLib.h?


Thank you
Yao Jiewen


> -----Original Message-----
> From: Wang, Jian J
> Sent: Wednesday, November 22, 2017 4:46 PM
> To: edk2-devel@lists.01.org
> Cc: Zeng, Star <star.zeng@intel.com>; Dong, Eric <eric.dong@intel.com>; Yao,
> Jiewen <jiewen.yao@intel.com>; Kinney, Michael D
> <michael.d.kinney@intel.com>
> Subject: [PATCH v2 7/8] UefiCpuPkg/CpuExceptionHandlerLib: Add stack switch
> support
> 
> > v2:
> >    a. Move common TSS structure and API definitions to BaseLib.h
> >    b. Add EXCEPTION_STACK_SWITCH_DATA to convery data used to setup
> stack
> >       switch. This can avoid allocating memory for it in this library.
> >    c. Add globals to reserve memory for stack switch initialized in early
> >       phase of DXE core.
> >    d. Remove the filter code used to exclude boot modes which doesn't
> support
> >       memory allocation because those memory can passed in by parameter
> now.
> >    e. Remove the nasm macro to define exception handler one by one and
> add a
> >       function to return the start address of each handler.
> 
> 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).
> 
> Cc: Star Zeng <star.zeng@intel.com>
> Cc: Eric Dong <eric.dong@intel.com>
> Cc: Jiewen Yao <jiewen.yao@intel.com>
> Cc: Michael Kinney <michael.d.kinney@intel.com>
> Suggested-by: Ayellet Wolman <ayellet.wolman@intel.com>
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Jian J Wang <jian.j.wang@intel.com>
> ---
>  .../CpuExceptionHandlerLib/CpuExceptionCommon.h    |  50 +++
>  .../DxeCpuExceptionHandlerLib.inf                  |   6 +
>  .../Library/CpuExceptionHandlerLib/DxeException.c  |  53 ++-
>  .../Ia32/ArchExceptionHandler.c                    | 167 +++++++++
>  .../Ia32/ArchInterruptDefs.h                       |   8 +
>  .../Ia32/ExceptionTssEntryAsm.nasm                 | 398
> +++++++++++++++++++++
>  .../PeiCpuExceptionHandlerLib.inf                  |   1 +
>  .../SecPeiCpuExceptionHandlerLib.inf               |   1 +
>  .../SmmCpuExceptionHandlerLib.inf                  |   1 +
>  .../X64/ArchExceptionHandler.c                     | 133 +++++++
>  .../CpuExceptionHandlerLib/X64/ArchInterruptDefs.h |   3 +
>  11 files changed, 820 insertions(+), 1 deletion(-)
>  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..30334105d2 100644
> --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h
> +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h
> @@ -48,6 +48,32 @@
>      0xb21d9148, 0x9211, 0x4d8f, { 0xad, 0xd3, 0x66, 0xb1, 0x89, 0xc9, 0x2c, 0x83 }
> \
>    }
> 
> +#define CPU_STACK_SWITCH_EXCEPTION_NUMBER \
> +  FixedPcdGetSize (PcdCpuStackSwitchExceptionList)
> +
> +#define CPU_STACK_SWITCH_EXCEPTION_LIST \
> +  FixedPcdGetPtr (PcdCpuStackSwitchExceptionList)
> +
> +#define CPU_KNOWN_GOOD_STACK_SIZE \
> +  FixedPcdGet32 (PcdCpuKnownGoodStackSize)
> +
> +#define CPU_TSS_GDT_SIZE (SIZE_2KB + CPU_TSS_DESC_SIZE + CPU_TSS_SIZE)
> +
> +#define IA32_GDT_TYPE_TSS           0x9
> +#define IA32_GDT_ALIGNMENT          8
> +
> +typedef struct {
> +  UINTN                     StackTop;
> +  UINTN                     StackSize;
> +  UINT8                     *Exceptions;
> +  UINTN                     ExceptionNumber;
> +  IA32_IDT_GATE_DESCRIPTOR  *IdtTable;
> +  IA32_SEGMENT_DESCRIPTOR   *GdtTable;
> +  UINTN                     GdtSize;
> +  IA32_TSS_DESCRIPTOR       *TssDesc;
> +  IA32_TASK_STATE_SEGMENT   *Tss;
> +} EXCEPTION_STACK_SWITCH_DATA;
> +
>  //
>  // Record exception handler information
>  //
> @@ -288,5 +314,29 @@ CommonExceptionHandlerWorker (
>    IN EXCEPTION_HANDLER_DATA      *ExceptionHandlerData
>    );
> 
> +/**
> +  Setup separate stack for specific exceptions.
> +
> +  @param[in] IdtTable        IDT table base.
> +**/
> +EFI_STATUS
> +EFIAPI
> +ArchSetupExcpetionStack (
> +  IN EXCEPTION_STACK_SWITCH_DATA      *StackSwitchData
> +  );
> +
> +/**
> +  Return address map of exception handler template so that C code can
> generate
> +  exception tables. The template is only for exceptions using task gate instead
> +  of interrupt gate.
> +
> +  @param AddressMap  Pointer to a buffer where the address map is
> returned.
> +**/
> +VOID
> +EFIAPI
> +AsmGetTssTemplateMap (
> +  OUT EXCEPTION_HANDLER_TEMPLATE_MAP  *AddressMap
> +  );
> +
>  #endif
> 
> diff --git
> a/UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandlerLib.inf
> b/UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandlerLib.inf
> index f4a8d01c80..58e55a8a2e 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,11 @@
>    PeiDxeSmmCpuException.c
>    DxeException.c
> 
> +[Pcd]
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdCpuStackGuard
> +  gUefiCpuPkgTokenSpaceGuid.PcdCpuStackSwitchExceptionList
> +  gUefiCpuPkgTokenSpaceGuid.PcdCpuKnownGoodStackSize
> +
>  [Packages]
>    MdePkg/MdePkg.dec
>    MdeModulePkg/MdeModulePkg.dec
> diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeException.c
> b/UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeException.c
> index 31febec976..c0b2c615aa 100644
> --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeException.c
> +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeException.c
> @@ -25,6 +25,10 @@ UINTN                       mEnabledInterruptNum =
> 0;
> 
>  EXCEPTION_HANDLER_DATA      mExceptionHandlerData;
> 
> +UINT8
> mNewStack[CPU_STACK_SWITCH_EXCEPTION_NUMBER *
> +                                      CPU_KNOWN_GOOD_STACK_SIZE]
> = {0};
> +UINT8                       mNewGdt[CPU_TSS_GDT_SIZE] = {0};
> +
>  /**
>    Common exception handler.
> 
> @@ -63,10 +67,34 @@ InitializeCpuExceptionHandlers (
>    IN EFI_VECTOR_HANDOFF_INFO       *VectorInfo OPTIONAL
>    )
>  {
> +  EFI_STATUS                        Status;
> +  EXCEPTION_STACK_SWITCH_DATA       StackSwitchData;
> +  IA32_DESCRIPTOR                   Idtr;
> +  IA32_DESCRIPTOR                   Gdtr;
> +
>    mExceptionHandlerData.ReservedVectors          =
> mReservedVectorsData;
>    mExceptionHandlerData.ExternalInterruptHandler =
> mExternalInterruptHandlerTable;
>    InitializeSpinLock (&mExceptionHandlerData.DisplayMessageSpinLock);
> -  return InitializeCpuExceptionHandlersWorker (VectorInfo,
> &mExceptionHandlerData);
> +  Status = InitializeCpuExceptionHandlersWorker (VectorInfo,
> &mExceptionHandlerData);
> +  if (!EFI_ERROR (Status) && PcdGetBool (PcdCpuStackGuard)) {
> +    AsmReadIdtr (&Idtr);
> +    AsmReadGdtr (&Gdtr);
> +
> +    StackSwitchData.StackTop = (UINTN)mNewStack;
> +    StackSwitchData.StackSize = CPU_KNOWN_GOOD_STACK_SIZE;
> +    StackSwitchData.Exceptions = CPU_STACK_SWITCH_EXCEPTION_LIST;
> +    StackSwitchData.ExceptionNumber =
> CPU_STACK_SWITCH_EXCEPTION_NUMBER;
> +    StackSwitchData.IdtTable = (IA32_IDT_GATE_DESCRIPTOR *)Idtr.Base;
> +    StackSwitchData.GdtTable = (IA32_SEGMENT_DESCRIPTOR *)mNewGdt;
> +    StackSwitchData.GdtSize = sizeof (mNewGdt);
> +    StackSwitchData.TssDesc = (IA32_TSS_DESCRIPTOR *)(mNewGdt +
> Gdtr.Limit + 1);
> +    StackSwitchData.Tss = (IA32_TASK_STATE_SEGMENT *)(mNewGdt +
> Gdtr.Limit + 1 +
> +
> CPU_TSS_DESC_SIZE);
> +    Status = InitializeCpuExceptionStackSwitchHandlers (
> +               &StackSwitchData
> +               );
> +  }
> +  return Status;
>  }
> 
>  /**
> @@ -197,3 +225,26 @@ RegisterCpuInterruptHandler (
>  {
>    return RegisterCpuInterruptHandlerWorker (InterruptType, InterruptHandler,
> &mExceptionHandlerData);
>  }
> +
> +/**
> +  Setup separate stack for given exceptions. This is required by
> +  PcdCpuStackGuard feature.
> +
> +  Note: For IA32 processor, StackSwitchData is a required parameter.
> +
> +  @param[in] StackSwitchData      Pointer to data required for setuping up
> +                                  stack switch.
> +
> +  @retval EFI_SUCCESS             The exceptions have been successfully
> +                                  initialized.
> +  @retval EFI_INVALID_PARAMETER   StackSwitchData contains invalid
> content.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +InitializeCpuExceptionStackSwitchHandlers (
> +  IN VOID       *StackSwitchData OPTIONAL
> +  )
> +{
> +  return ArchSetupExcpetionStack (StackSwitchData);
> +}
> diff --git
> a/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchExceptionHandler.c
> b/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchExceptionHandler.c
> index f2c39eb193..0aaf794795 100644
> --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchExceptionHandler.c
> +++
> b/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchExceptionHandler.c
> @@ -107,6 +107,173 @@ ArchRestoreExceptionContext (
>    SystemContext.SystemContextIa32->ExceptionData =
> ReservedVectors[ExceptionType].ExceptionData;
>  }
> 
> +/**
> +  Setup separate stack for given exceptions.
> +
> +  @param[in] StackSwitchData        Pointer to data required for setuping
> up
> +                                    stack switch.
> +  @retval EFI_SUCCESS             The exceptions have been successfully
> +                                  initialized.
> +  @retval EFI_INVALID_PARAMETER   StackSwitchData contains invalid
> content.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +ArchSetupExcpetionStack (
> +  IN EXCEPTION_STACK_SWITCH_DATA   *StackSwitchData
> +  )
> +{
> +  IA32_DESCRIPTOR                   Gdtr;
> +  IA32_DESCRIPTOR                   Idtr;
> +  IA32_IDT_GATE_DESCRIPTOR          *IdtTable;
> +  IA32_TSS_DESCRIPTOR               *TssDesc;
> +  IA32_TASK_STATE_SEGMENT           *Tss;
> +  UINTN                             StackTop;
> +  UINTN                             Index;
> +  UINTN                             Vector;
> +  UINTN                             TssBase;
> +  UINTN                             GdtSize;
> +  EXCEPTION_HANDLER_TEMPLATE_MAP    TemplateMap;
> +
> +  if (StackSwitchData == NULL ||
> +      StackSwitchData->StackTop == 0 ||
> +      StackSwitchData->StackSize == 0 ||
> +      StackSwitchData->Exceptions == NULL ||
> +      StackSwitchData->ExceptionNumber == 0 ||
> +      StackSwitchData->GdtTable == NULL ||
> +      StackSwitchData->IdtTable == NULL ||
> +      StackSwitchData->TssDesc == NULL ||
> +      StackSwitchData->Tss == NULL) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  //
> +  // The caller is responsible for that the GDT table, no matter the existing
> +  // one or newly allocated, has enough space to hold descriptors for exception
> +  // task-state segments.
> +  //
> +  if (((UINTN)StackSwitchData->GdtTable & (IA32_GDT_ALIGNMENT - 1)) != 0) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  if ((UINTN)StackSwitchData->TssDesc < (UINTN)(StackSwitchData->GdtTable))
> {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  if ((UINTN)StackSwitchData->TssDesc >=
> +          ((UINTN)(StackSwitchData->GdtTable) + StackSwitchData->GdtSize))
> {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  GdtSize = (UINTN)StackSwitchData->TssDesc -
> +            (UINTN)(StackSwitchData->GdtTable) +
> +            sizeof (IA32_TSS_DESCRIPTOR) *
> +            (StackSwitchData->ExceptionNumber + 1);
> +  if (GdtSize > StackSwitchData->GdtSize) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  //
> +  // Initialize new GDT table and/or IDT table, if any
> +  //
> +  AsmReadIdtr (&Idtr);
> +  AsmReadGdtr (&Gdtr);
> +  if ((UINTN)StackSwitchData->GdtTable != Gdtr.Base) {
> +    CopyMem (StackSwitchData->GdtTable, (VOID *)Gdtr.Base, Gdtr.Limit + 1);
> +    Gdtr.Base = (UINTN)StackSwitchData->GdtTable;
> +    Gdtr.Limit = (UINT16)StackSwitchData->GdtSize - 1;
> +  }
> +
> +  if ((UINTN)StackSwitchData->IdtTable != Idtr.Base) {
> +    Idtr.Base = (UINTN)StackSwitchData->IdtTable;
> +  }
> +
> +  //
> +  // Fixup current task descriptor. Task-state segment for current task will
> +  // be filled by processor during task switching.
> +  //
> +  TssDesc = StackSwitchData->TssDesc;
> +  Tss     = StackSwitchData->Tss;
> +
> +  TssBase = (UINTN)Tss;
> +  TssDesc->Bits.LimitLow   = sizeof(IA32_TASK_STATE_SEGMENT) - 1;
> +  TssDesc->Bits.BaseLow    = (UINT16)TssBase;
> +  TssDesc->Bits.BaseMid    = (UINT8)(TssBase >> 16);
> +  TssDesc->Bits.Type       = IA32_GDT_TYPE_TSS;
> +  TssDesc->Bits.P          = 1;
> +  TssDesc->Bits.LimitHigh  = 0;
> +  TssDesc->Bits.BaseHigh   = (UINT8)(TssBase >> 24);
> +
> +  //
> +  // Fixup exception task descriptor and task-state segment
> +  //
> +  AsmGetTssTemplateMap (&TemplateMap);
> +  StackTop = StackSwitchData->StackTop - CPU_STACK_ALIGNMENT;
> +  StackTop = (UINTN)ALIGN_POINTER (StackTop, CPU_STACK_ALIGNMENT);
> +  IdtTable = StackSwitchData->IdtTable;
> +  for (Index = 0; Index < StackSwitchData->ExceptionNumber; ++Index) {
> +    TssDesc += 1;
> +    Tss     += 1;
> +
> +    //
> +    // Fixup TSS descriptor
> +    //
> +    TssBase = (UINTN)Tss;
> +
> +    TssDesc->Bits.LimitLow  = sizeof(IA32_TASK_STATE_SEGMENT) - 1;
> +    TssDesc->Bits.BaseLow   = (UINT16)TssBase;
> +    TssDesc->Bits.BaseMid   = (UINT8)(TssBase >> 16);
> +    TssDesc->Bits.Type      = IA32_GDT_TYPE_TSS;
> +    TssDesc->Bits.P         = 1;
> +    TssDesc->Bits.LimitHigh = 0;
> +    TssDesc->Bits.BaseHigh  = (UINT8)(TssBase >> 24);
> +
> +    //
> +    // Fixup TSS
> +    //
> +    Vector = StackSwitchData->Exceptions[Index];
> +    Tss->EIP    = (UINT32)(TemplateMap.ExceptionStart
> +                           + Vector *
> TemplateMap.ExceptionStubHeaderSize);
> +    Tss->EFLAGS = 0x2;
> +    Tss->ESP    = StackTop;
> +    Tss->CR3    = AsmReadCr3 ();
> +    Tss->ES     = AsmReadEs ();
> +    Tss->CS     = AsmReadCs ();
> +    Tss->SS     = AsmReadSs ();
> +    Tss->DS     = AsmReadDs ();
> +    Tss->FS     = AsmReadFs ();
> +    Tss->GS     = AsmReadGs ();
> +
> +    StackTop   -= StackSwitchData->StackSize;
> +
> +    //
> +    // Update IDT to use Task Gate for given exception
> +    //
> +    IdtTable[Vector].Bits.OffsetLow  = 0;
> +    IdtTable[Vector].Bits.Selector   = (UINT16)((UINTN)TssDesc - Gdtr.Base);
> +    IdtTable[Vector].Bits.Reserved_0 = 0;
> +    IdtTable[Vector].Bits.GateType   = IA32_IDT_GATE_TYPE_TASK;
> +    IdtTable[Vector].Bits.OffsetHigh = 0;
> +  }
> +
> +  //
> +  // Publish GDT
> +  //
> +  AsmWriteGdtr (&Gdtr);
> +
> +  //
> +  // Load current task
> +  //
> +  AsmWriteTr ((UINT16)((UINTN)StackSwitchData->TssDesc - Gdtr.Base));
> +
> +  //
> +  // Publish IDT
> +  //
> +  AsmWriteIdtr (&Idtr);
> +
> +  return EFI_SUCCESS;
> +}
> +
>  /**
>    Display processor context.
> 
> diff --git
> a/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchInterruptDefs.h
> b/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchInterruptDefs.h
> index a8d3556a80..d9ded5977f 100644
> --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchInterruptDefs.h
> +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchInterruptDefs.h
> @@ -41,4 +41,12 @@ typedef struct {
>    UINT8       HookAfterStubHeaderCode[HOOKAFTER_STUB_SIZE];
>  } RESERVED_VECTORS_DATA;
> 
> +#define CPU_TSS_DESC_SIZE \
> +  (sizeof (IA32_TSS_DESCRIPTOR) * \
> +   (PcdGetSize (PcdCpuStackSwitchExceptionList) + 1))
> +
> +#define CPU_TSS_SIZE \
> +  (sizeof (IA32_TASK_STATE_SEGMENT) * \
> +   (PcdGetSize (PcdCpuStackSwitchExceptionList) + 1))
> +
>  #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..62bcedea1a
> --- /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
> +;
> +AsmExceptionEntryBegin:
> +%assign Vector 0
> +%rep  32
> +
> +DoIret%[Vector]:
> +    iretd
> +ASM_PFX(ExceptionTaskSwtichEntry%[Vector]):
> +    db      0x6a        ; push  #VectorNum
> +    db      %[Vector]
> +    mov     eax, ASM_PFX(CommonTaskSwtichEntryPoint)
> +    call    eax
> +    mov     esp, eax    ; Restore stack top
> +    jmp     DoIret%[Vector]
> +
> +%assign Vector Vector+1
> +%endrep
> +AsmExceptionEntryEnd:
> +
> +;
> +; Common part of exception handler
> +;
> +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       +
> +    ; +---------------------+
> +    ;
> +
> +    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
> +
> +global ASM_PFX(AsmGetTssTemplateMap)
> +ASM_PFX(AsmGetTssTemplateMap):
> +    push    ebp                 ; C prolog
> +    mov     ebp, esp
> +    pushad
> +
> +    mov ebx, dword [ebp + 0x8]
> +    mov dword [ebx],       ASM_PFX(ExceptionTaskSwtichEntry0)
> +    mov dword [ebx + 0x4], (AsmExceptionEntryEnd - AsmExceptionEntryBegin)
> / 32
> +    mov dword [ebx + 0x8], 0
> +
> +    popad
> +    pop     ebp
> +    ret
> +
> 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..e5c03c16c9 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
> 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..214aafcc13 100644
> --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c
> +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c
> @@ -112,6 +112,139 @@ ArchRestoreExceptionContext (
>    SystemContext.SystemContextX64->ExceptionData =
> ReservedVectors[ExceptionType].ExceptionData;
>  }
> 
> +/**
> +  Setup separate stack for given exceptions.
> +
> +  @param[in] StackSwitchData      Pointer to data required for setuping up
> +                                  stack switch.
> +
> +  @retval EFI_SUCCESS             The exceptions have been successfully
> +                                  initialized.
> +  @retval EFI_INVALID_PARAMETER   StackSwitchData contains invalid
> content.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +ArchSetupExcpetionStack (
> +  IN EXCEPTION_STACK_SWITCH_DATA        *StackSwitchData
> +  )
> +{
> +  IA32_DESCRIPTOR                   Gdtr;
> +  IA32_DESCRIPTOR                   Idtr;
> +  IA32_IDT_GATE_DESCRIPTOR          *IdtTable;
> +  IA32_TSS_DESCRIPTOR               *TssDesc;
> +  IA32_TASK_STATE_SEGMENT           *Tss;
> +  UINTN                             StackTop;
> +  UINTN                             Index;
> +  UINTN                             TssBase;
> +  UINTN                             GdtSize;
> +
> +  if (StackSwitchData == NULL ||
> +      StackSwitchData->StackTop == 0 ||
> +      StackSwitchData->StackSize == 0 ||
> +      StackSwitchData->Exceptions == NULL ||
> +      StackSwitchData->ExceptionNumber == 0 ||
> +      StackSwitchData->GdtTable == NULL ||
> +      StackSwitchData->IdtTable == NULL ||
> +      StackSwitchData->TssDesc == NULL ||
> +      StackSwitchData->Tss == NULL) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  //
> +  // The caller is responsible for that the GDT table, no matter the existing
> +  // one or newly allocated, has enough space to hold descriptors for exception
> +  // task-state segments.
> +  //
> +  if (((UINTN)StackSwitchData->GdtTable & (IA32_GDT_ALIGNMENT - 1)) != 0) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  if ((UINTN)StackSwitchData->TssDesc < (UINTN)(StackSwitchData->GdtTable))
> {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  if ((UINTN)StackSwitchData->TssDesc >=
> +          ((UINTN)(StackSwitchData->GdtTable) + StackSwitchData->GdtSize))
> {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  GdtSize = (UINTN)StackSwitchData->TssDesc -
> +            (UINTN)(StackSwitchData->GdtTable) +
> +            sizeof (IA32_TSS_DESCRIPTOR);
> +  if (GdtSize > StackSwitchData->GdtSize) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  //
> +  // Initialize new GDT table and/or IDT table, if any
> +  //
> +  AsmReadIdtr (&Idtr);
> +  AsmReadGdtr (&Gdtr);
> +  if ((UINTN)StackSwitchData->GdtTable != Gdtr.Base) {
> +    CopyMem (StackSwitchData->GdtTable, (VOID *)Gdtr.Base, Gdtr.Limit + 1);
> +    Gdtr.Base = (UINTN)StackSwitchData->GdtTable;
> +    Gdtr.Limit = (UINT16)GdtSize - 1;
> +  }
> +
> +  if ((UINTN)StackSwitchData->IdtTable != Idtr.Base) {
> +    Idtr.Base = (UINTN)StackSwitchData->IdtTable;
> +  }
> +
> +  //
> +  // Fixup current task descriptor. Task-state segment for current task will
> +  // be filled by processor during task switching.
> +  //
> +  TssDesc = StackSwitchData->TssDesc;
> +  Tss     = StackSwitchData->Tss;
> +
> +  TssBase = (UINTN)Tss;
> +  TssDesc->Bits.LimitLow   = sizeof(IA32_TASK_STATE_SEGMENT) - 1;
> +  TssDesc->Bits.BaseLow    = (UINT16)TssBase;
> +  TssDesc->Bits.BaseMidl   = (UINT8)(TssBase >> 16);
> +  TssDesc->Bits.Type       = IA32_GDT_TYPE_TSS;
> +  TssDesc->Bits.P          = 1;
> +  TssDesc->Bits.LimitHigh  = 0;
> +  TssDesc->Bits.BaseMidh   = (UINT8)(TssBase >> 24);
> +  TssDesc->Bits.BaseHigh   = (UINT32)(TssBase >> 32);
> +
> +  //
> +  // Fixup exception task descriptor and task-state segment
> +  //
> +  StackTop = StackSwitchData->StackTop - CPU_STACK_ALIGNMENT;
> +  StackTop = (UINTN)ALIGN_POINTER (StackTop, CPU_STACK_ALIGNMENT);
> +  IdtTable = StackSwitchData->IdtTable;
> +  for (Index = 0; Index < StackSwitchData->ExceptionNumber; ++Index) {
> +    //
> +    // Fixup IST
> +    //
> +    Tss->IST[Index] = StackTop;
> +    StackTop -= StackSwitchData->StackSize;
> +
> +    //
> +    // Set the IST field to enable corresponding IST
> +    //
> +    IdtTable[StackSwitchData->Exceptions[Index]].Bits.Reserved_0 =
> (UINT8)(Index + 1);
> +  }
> +
> +  //
> +  // Publish GDT
> +  //
> +  AsmWriteGdtr (&Gdtr);
> +
> +  //
> +  // Load current task
> +  //
> +  AsmWriteTr ((UINT16)((UINTN)StackSwitchData->TssDesc - Gdtr.Base));
> +
> +  //
> +  // Publish IDT
> +  //
> +  AsmWriteIdtr (&Idtr);
> +
> +  return EFI_SUCCESS;
> +}
> +
>  /**
>    Display CPU information.
> 
> diff --git
> a/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchInterruptDefs.h
> b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchInterruptDefs.h
> index 906480134a..c88be46286 100644
> --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchInterruptDefs.h
> +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchInterruptDefs.h
> @@ -43,4 +43,7 @@ typedef struct {
>    UINT8       HookAfterStubHeaderCode[HOOKAFTER_STUB_SIZE];
>  } RESERVED_VECTORS_DATA;
> 
> +#define CPU_TSS_DESC_SIZE sizeof (IA32_TSS_DESCRIPTOR)
> +#define CPU_TSS_SIZE      sizeof (IA32_TASK_STATE_SEGMENT)
> +
>  #endif
> --
> 2.14.1.windows.1



  reply	other threads:[~2017-11-23  5:45 UTC|newest]

Thread overview: 35+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-11-22  8:45 [PATCH v2 0/8] Implement stack guard feature Jian J Wang
2017-11-22  8:45 ` [PATCH v2 1/8] MdeModulePkg/metafile: Add PCD PcdCpuStackGuard Jian J Wang
2017-11-22  8:45 ` [PATCH v2 2/8] MdeModulePkg/CpuExceptionHandlerLib.h: Add a new API Jian J Wang
2017-11-23  4:07   ` Yao, Jiewen
2017-11-23  5:06     ` Wang, Jian J
2017-11-25 13:17       ` 答复: " Fan Jeff
2017-11-27  2:20         ` Wang, Jian J
2017-11-22  8:45 ` [PATCH v2 3/8] MdePkg/BaseLib: Add stack switch related definitions for IA32 Jian J Wang
2017-11-22  8:45 ` [PATCH v2 4/8] MdeModulePkg/DxeIpl: Enable paging for Stack Guard Jian J Wang
2017-11-22  8:45 ` [PATCH v2 5/8] UefiCpuPkg/UefiCpuPkg.dec: Add two new PCDs for stack switch Jian J Wang
2017-11-22  8:45 ` [PATCH v2 6/8] UefiCpuPkg/MpLib: Add GDTR, IDTR and TR in saved AP data Jian J Wang
2017-11-22  8:45 ` [PATCH v2 7/8] UefiCpuPkg/CpuExceptionHandlerLib: Add stack switch support Jian J Wang
2017-11-23  5:50   ` Yao, Jiewen [this message]
2017-11-23  5:59     ` Yao, Jiewen
2017-11-23  6:09       ` Wang, Jian J
2017-11-23  6:25         ` Yao, Jiewen
2017-11-23  7:54           ` Wang, Jian J
2017-11-23  6:05     ` Wang, Jian J
2017-11-23  6:16       ` Yao, Jiewen
2017-11-23  6:43         ` Wang, Jian J
2017-11-25 13:27           ` 答复: " Fan Jeff
2017-11-27  2:21             ` Wang, Jian J
2017-11-28  1:38           ` Wang, Jian J
2017-11-28  2:06             ` Yao, Jiewen
2017-11-25 13:35   ` 答复: " Fan Jeff
2017-11-22  8:45 ` [PATCH v2 8/8] UefiCpuPkg/CpuDxe: Initialize stack switch for MP Jian J Wang
2017-11-23  4:13   ` Yao, Jiewen
2017-11-23  5:03     ` Wang, Jian J
2017-11-23  5:19       ` Wang, Jian J
2017-11-23  5:39         ` Yao, Jiewen
2017-11-23  3:47 ` [PATCH v2 0/8] Implement stack guard feature Yao, Jiewen
2017-11-23  5:09   ` Wang, Jian J
2017-11-23  5:40     ` Yao, Jiewen
2017-11-25 13:44       ` 答复: " Fan Jeff
2017-11-25 13:55         ` Yao, Jiewen

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=74D8A39837DF1E4DA445A8C0B3885C503AA292EF@shsmsx102.ccr.corp.intel.com \
    --to=devel@edk2.groups.io \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox