From: Fan Jeff <vanjeff_919@hotmail.com>
To: "Wang, Jian J" <jian.j.wang@intel.com>,
"Yao, Jiewen" <jiewen.yao@intel.com>,
"edk2-devel@lists.01.org" <edk2-devel@lists.01.org>
Cc: "Kinney, Michael D" <michael.d.kinney@intel.com>,
"Dong, Eric" <eric.dong@intel.com>,
"Zeng, Star" <star.zeng@intel.com>
Subject: 答复: [PATCH 3/3] UefiCpuPkg/CpuExceptionHandlerLib: Add stack switch support
Date: Wed, 1 Nov 2017 03:45:48 +0000 [thread overview]
Message-ID: <CY1PR19MB028383004797BFDC60A81D5FD75F0@CY1PR19MB0283.namprd19.prod.outlook.com> (raw)
In-Reply-To: <D827630B58408649ACB04F44C510003624CA70B4@SHSMSX103.ccr.corp.intel.com>
Jian,
You are right! The exception handler setup in DxeIplPeim does not need stack at all. Thanks your clarification.
Jeff
发件人: Wang, Jian J<mailto:jian.j.wang@intel.com>
发送时间: 2017年11月1日 11:12
收件人: Wang, Jian J<mailto:jian.j.wang@intel.com>; Fan Jeff<mailto:vanjeff_919@hotmail.com>; Yao, Jiewen<mailto:jiewen.yao@intel.com>; edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>
抄送: Kinney, Michael D<mailto:michael.d.kinney@intel.com>; Dong, Eric<mailto:eric.dong@intel.com>; Zeng, Star<mailto:star.zeng@intel.com>
主题: RE: [PATCH 3/3] UefiCpuPkg/CpuExceptionHandlerLib: Add stack switch support
Jeff,
Sorry for the misunderstanding. I think stack switch cannot work with NULL exception handler. But without exception handler, what do we need stack switch for?
Thanks,
Jian
> -----Original Message-----
> From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of Wang,
> Jian J
> Sent: Wednesday, November 01, 2017 11:09 AM
> To: Fan Jeff <vanjeff_919@hotmail.com>; Yao, Jiewen <jiewen.yao@intel.com>;
> edk2-devel@lists.01.org
> Cc: Kinney, Michael D <michael.d.kinney@intel.com>; Dong, Eric
> <eric.dong@intel.com>; Zeng, Star <star.zeng@intel.com>
> Subject: Re: [edk2] [PATCH 3/3] UefiCpuPkg/CpuExceptionHandlerLib: Add stack
> switch support
>
> Jeff,
>
> Stack guard will still work. But the developer cannot know what’s going on
> without exception dumping message when stack overflow occurs.
>
> Thanks,
> Jian
>
> From: Fan Jeff [mailto:vanjeff_919@hotmail.com]
> Sent: Wednesday, November 01, 2017 10:59 AM
> To: Wang, Jian J <jian.j.wang@intel.com>; Yao, Jiewen <jiewen.yao@intel.com>;
> edk2-devel@lists.01.org
> Cc: Kinney, Michael D <michael.d.kinney@intel.com>; Dong, Eric
> <eric.dong@intel.com>; Zeng, Star <star.zeng@intel.com>
> Subject: 答复: [PATCH 3/3] UefiCpuPkg/CpuExceptionHandlerLib: Add stack
> switch support
>
> Jian,
>
> No. I suggest to fix #109 in another separate patch.
>
> But to fix #109, we have to makes sure AsmWriteTr() and some definitions are in
> MdePkg.
> But I have no strong opinion to add them into MdePkg in this patch.
>
> I have another question: If NULL CPU exception handler instance is chosen,
> could Stack Switch work if PCD PcdCpuStackGuard is set to TRUE.
>
> Thanks!
> Jeff
>
> 发件人: Wang, Jian J<mailto:jian.j.wang@intel.com>
> 发送时间: 2017年11月1日 10:48
> 收件人: Fan Jeff<mailto:vanjeff_919@hotmail.com>; Yao,
> Jiewen<mailto:jiewen.yao@intel.com>; edk2-devel@lists.01.org<mailto:edk2-
> devel@lists.01.org>
> 抄送: Kinney, Michael D<mailto:michael.d.kinney@intel.com>; Dong,
> Eric<mailto:eric.dong@intel.com>; Zeng, Star<mailto:star.zeng@intel.com>
> 主题: RE: [PATCH 3/3] UefiCpuPkg/CpuExceptionHandlerLib: Add stack switch
> support
>
> Hi Jeff,
>
> Thanks for the feedback. Are you suggesting to fix Bugzilla 109 in this patch?
>
> Thanks,
> Jian
>
> From: Fan Jeff [mailto:vanjeff_919@hotmail.com]
> Sent: Wednesday, November 01, 2017 10:33 AM
> To: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>;
> Wang, Jian J <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; edk2-
> devel@lists.01.org<mailto:edk2-devel@lists.01.org>
> Cc: Kinney, Michael D
> <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>; Dong, Eric
> <eric.dong@intel.com<mailto:eric.dong@intel.com>>; Zeng, Star
> <star.zeng@intel.com<mailto:star.zeng@intel.com>>
> Subject: 答复: [PATCH 3/3] UefiCpuPkg/CpuExceptionHandlerLib: Add stack
> switch support
>
> Per https://bugzilla.tianocore.org/show_bug.cgi?id=109, TR should be setup
> (Such as in DxeIplPeim) even though NULL Cpu Exception Handler instance is
> chosen.
>
> For long term, I agree we need to move AsmWriteTr,
> IA32_TASK_STATE_SEGMENT, IA32_TSS_DESCRIPTOR to MdePkg(Such as
> BaseLib)
> For this patch, I have no strong opinion.
>
>
> 发件人: Yao, Jiewen<mailto:jiewen.yao@intel.com>
> 发送时间: 2017年11月1日 9:56
> 收件人: Wang, Jian J<mailto:jian.j.wang@intel.com>; edk2-
> devel@lists.01.org<mailto:edk2-devel@lists.01.org>
> 抄送: Kinney, Michael D<mailto:michael.d.kinney@intel.com>; Dong,
> Eric<mailto:eric.dong@intel.com>; Zeng, Star<mailto:star.zeng@intel.com>
> 主题: Re: [edk2] [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
>
> 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;
> > + }
> > + }
>
>
> Thank you
> Yao Jiewen
>
>
> > -----Original Message-----
> > From: Wang, Jian J
> > Sent: Tuesday, October 31, 2017 10:24 PM
> > To: edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>
> > Cc: Zeng, Star <star.zeng@intel.com<mailto:star.zeng@intel.com>>; Dong,
> Eric <eric.dong@intel.com<mailto:eric.dong@intel.com>>; Yao,
> > Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Kinney,
> Michael D
> > <michael.d.kinney@intel.com<mailto:michael.d.kinney@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.zeng@intel.com<mailto:star.zeng@intel.com>>
> > Cc: Eric Dong <eric.dong@intel.com<mailto:eric.dong@intel.com>>
> > Cc: Jiewen Yao <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>
> > Cc: Michael Kinney
> <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>
> > Suggested-by: Ayellet Wolman
> <ayellet.wolman@intel.com<mailto:ayellet.wolman@intel.com>>
> > Contributed-under: TianoCore Contribution Agreement 1.1
> > Signed-off-by: Jian J Wang
> <jian.j.wang@intel.com<mailto:jian.j.wang@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<mailto:edk2-devel@lists.01.org>
> https://lists.01.org/mailman/listinfo/edk2-devel
>
>
> _______________________________________________
> edk2-devel mailing list
> edk2-devel@lists.01.org
> https://lists.01.org/mailman/listinfo/edk2-devel
next prev parent reply other threads:[~2017-11-01 3:41 UTC|newest]
Thread overview: 28+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-10-31 14:24 [PATCH 0/3] Implement stack guard feature Jian J Wang
2017-10-31 14:24 ` [PATCH 1/3] MdeModulePkg/metafile: Add PCD PcdCpuStackGuard Jian J Wang
2017-10-31 14:24 ` [PATCH 2/3] MdeModulePkg/DxeIpl: Enable paging for stack guard Jian J Wang
2017-10-31 14:24 ` [PATCH 3/3] UefiCpuPkg/CpuExceptionHandlerLib: Add stack switch support Jian J Wang
2017-11-01 1:56 ` Yao, Jiewen
2017-11-01 2:33 ` 答复: " Fan Jeff
2017-11-01 2:48 ` Wang, Jian J
2017-11-01 2:59 ` 答复: " Fan Jeff
2017-11-01 3:08 ` Wang, Jian J
2017-11-01 3:12 ` Wang, Jian J
2017-11-01 3:45 ` Fan Jeff [this message]
2017-11-01 3:12 ` 答复: " Fan Jeff
2017-11-01 15:42 ` Kinney, Michael D
2017-11-03 1:24 ` Yao, Jiewen
2017-11-03 2:10 ` Wang, Jian J
2017-11-03 2:27 ` Yao, Jiewen
2017-11-03 2:30 ` Wang, Jian J
2017-11-03 8:21 ` 答复: " Fan Jeff
2017-11-03 8:58 ` Fan Jeff
2017-11-06 0:30 ` Wang, Jian J
2017-11-06 1:54 ` Yao, Jiewen
2017-11-06 2:27 ` Wang, Jian J
2017-11-06 3:47 ` Yao, Jiewen
2017-11-06 3:10 ` 答复: " Fan Jeff
2017-11-06 2:00 ` Fan Jeff
2017-11-01 2:36 ` Wang, Jian J
2017-11-01 2:37 ` 答复: " Fan Jeff
2017-11-01 2:45 ` Wang, Jian J
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=CY1PR19MB028383004797BFDC60A81D5FD75F0@CY1PR19MB0283.namprd19.prod.outlook.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