From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received-SPF: Pass (sender SPF authorized) identity=mailfrom; client-ip=192.55.52.120; helo=mga04.intel.com; envelope-from=jian.j.wang@intel.com; receiver=edk2-devel@lists.01.org Received: from mga04.intel.com (mga04.intel.com [192.55.52.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id 5174720352610 for ; Tue, 31 Oct 2017 19:32:17 -0700 (PDT) Received: from fmsmga005.fm.intel.com ([10.253.24.32]) by fmsmga104.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 31 Oct 2017 19:36:09 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.44,326,1505804400"; d="scan'208";a="169740454" Received: from fmsmsx104.amr.corp.intel.com ([10.18.124.202]) by fmsmga005.fm.intel.com with ESMTP; 31 Oct 2017 19:36:09 -0700 Received: from shsmsx104.ccr.corp.intel.com (10.239.4.70) by fmsmsx104.amr.corp.intel.com (10.18.124.202) with Microsoft SMTP Server (TLS) id 14.3.319.2; Tue, 31 Oct 2017 19:36:08 -0700 Received: from shsmsx103.ccr.corp.intel.com ([169.254.4.213]) by SHSMSX104.ccr.corp.intel.com ([169.254.5.152]) with mapi id 14.03.0319.002; Wed, 1 Nov 2017 10:36:06 +0800 From: "Wang, Jian J" To: "Yao, Jiewen" , "edk2-devel@lists.01.org" CC: "Zeng, Star" , "Dong, Eric" , "Kinney, Michael D" Thread-Topic: [PATCH 3/3] UefiCpuPkg/CpuExceptionHandlerLib: Add stack switch support Thread-Index: AQHTUlQt7kMmlPjLfkaS9nSj0Ju2aqL+wnPggAAMGWA= Date: Wed, 1 Nov 2017 02:36:06 +0000 Message-ID: References: <20171031142412.21680-1-jian.j.wang@intel.com> <20171031142412.21680-4-jian.j.wang@intel.com> <74D8A39837DF1E4DA445A8C0B3885C503AA0AED6@shsmsx102.ccr.corp.intel.com> In-Reply-To: <74D8A39837DF1E4DA445A8C0B3885C503AA0AED6@shsmsx102.ccr.corp.intel.com> Accept-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-titus-metadata-40: eyJDYXRlZ29yeUxhYmVscyI6IiIsIk1ldGFkYXRhIjp7Im5zIjoiaHR0cDpcL1wvd3d3LnRpdHVzLmNvbVwvbnNcL0ludGVsMyIsImlkIjoiYTA4ZjVlYjYtMWRlZS00NjgwLWJmZTMtYzEzMWJmMzJjMzBhIiwicHJvcHMiOlt7Im4iOiJDVFBDbGFzc2lmaWNhdGlvbiIsInZhbHMiOlt7InZhbHVlIjoiQ1RQX0lDIn1dfV19LCJTdWJqZWN0TGFiZWxzIjpbXSwiVE1DVmVyc2lvbiI6IjE3LjIuNS4xOCIsIlRydXN0ZWRMYWJlbEhhc2giOiJROHFLcE1HUEhtNFNkU3R2bzJseFl1UUlKVStqRHdVU0dWT0I5N3VZdXorTVFLbFc3THdCNVJtQ0wrdkQ2cTZEIn0= x-ctpclassification: CTP_IC dlp-product: dlpe-windows dlp-version: 11.0.0.116 dlp-reaction: no-action x-originating-ip: [10.239.127.40] MIME-Version: 1.0 Subject: Re: [PATCH 3/3] UefiCpuPkg/CpuExceptionHandlerLib: Add stack switch support X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.22 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 01 Nov 2017 02:32:17 -0000 Content-Language: en-US Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable Hi Jiewen, Thanks for the feedback.=20 > -----Original Message----- > From: Yao, Jiewen > Sent: Wednesday, November 01, 2017 9:57 AM > To: Wang, Jian J ; edk2-devel@lists.01.org > Cc: Zeng, Star ; Dong, Eric ; > Kinney, Michael D > Subject: RE: [PATCH 3/3] UefiCpuPkg/CpuExceptionHandlerLib: Add stack swi= tch > support >=20 > Hi Jian > Thanks for the patch. >=20 > Can we move all IA32 defined data structure or function to MdePkg? > Such as: AsmWriteTr, IA32_TASK_STATE_SEGMENT, IA32_TSS_DESCRIPTOR >=20 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 an= d > > + // 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; > > + } > > + } >=20 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. >=20 > Thank you > Yao Jiewen >=20 >=20 > > -----Original Message----- > > From: Wang, Jian J > > Sent: Tuesday, October 31, 2017 10:24 PM > > To: edk2-devel@lists.01.org > > Cc: Zeng, Star ; Dong, Eric ;= Yao, > > Jiewen ; Kinney, Michael D > > > > Subject: [PATCH 3/3] UefiCpuPkg/CpuExceptionHandlerLib: Add stack switc= h > > 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 ou= t of > > usage, the exception handler, which shares the stack with normal UEFI d= river, > > 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 dev= eloper > > cannot event use single step to debug the UEFI driver with JTAG debugge= r. > > > > In order to make sure the exception handler to execute normally after s= tack > > overflow. We need separate stacks for exception handlers in case of unu= sable > > 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 pro= vides > > 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 s= witch. > > > > Cc: Star Zeng > > Cc: Eric Dong > > Cc: Jiewen Yao > > Cc: Michael Kinney > > Suggested-by: Ayellet Wolman > > Contributed-under: TianoCore Contribution Agreement 1.1 > > Signed-off-by: Jian J Wang > > --- > > .../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 > > #include > > #include > > +#include > > > > #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 > > #include > > +#include > > > > CONST UINTN mDoFarReturnFlag =3D 0; > > > > @@ -155,6 +156,24 @@ InitializeCpuInterruptHandlers ( > > > > UpdateIdtTable (IdtTable, &TemplateMap, &mExceptionHandlerData); > > > > + if (PcdGetBool (PcdCpuStackGuard)) { > > + // > > + // Stack Guard works with the support of page table established an= d > > + // 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[] =3D { > > + {6, ExceptionTaskSwtichEntry6}, //#UD: Invalid Opcode Exception > > + {8, ExceptionTaskSwtichEntry8}, //#DF: Double Fault Exception > > + {12, ExceptionTaskSwtichEntry12}, //#SS: Stack Fault Exception > > + {13, ExceptionTaskSwtichEntry13}, //#GP: General Protection Exceptio= n > > + {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 =3D > > 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 =3D GdtDesc.Limit + 1; > > + NewGdt =3D AllocateRuntimeZeroPool(OldGdtSize + sizeof(TSS_ENTRIES) > > + + IA32_GDT_ALIGNMENT); > > + if (NewGdt =3D=3D NULL) { > > + return; > > + } > > + NewGdt =3D ALIGN_POINTER (NewGdt, IA32_GDT_ALIGNMENT); > > + > > + // > > + // Initialize new GDT entries > > + // > > + CopyMem(NewGdt, (VOID *)GdtDesc.Base, OldGdtSize); > > + GdtDesc.Base =3D (UINTN)(VOID*)NewGdt; > > + GdtDesc.Limit =3D (UINT16)(OldGdtSize + TSS_OFFSET - 1); > > + > > + // > > + // Reserve statck memory for given exceptions > > + // > > + StackSize =3D ARRAY_SIZE (mExceptionsWithStack) * EXCEPTION_STACK_SI= ZE; > > + StackSize =3D EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (StackSize)); > > + StackBase =3D (UINT64)(UINTN)AllocatePages (EFI_SIZE_TO_PAGES > > (StackSize)); > > + if (StackBase =3D=3D 0) { > > + FreePool (NewGdt); > > + return; > > + } > > + > > + // > > + // Fixup TSS descriptors and segments > > + // > > + TssEntry =3D (VOID *)(GdtDesc.Base + OldGdtSize); > > + > > + TssBase =3D (UINTN)(VOID *)&TssEntry->Tss; > > + TssEntry->TssSeg.Limit15_0 =3D > > sizeof(IA32_TASK_STATE_SEGMENT) - 1; > > + TssEntry->TssSeg.Base15_0 =3D (UINT16)TssBase; > > + TssEntry->TssSeg.Base23_16 =3D (UINT8)(TssBase >> 16); > > + TssEntry->TssSeg.Type =3D IA32_GDT_TYPE_TSS; > > + TssEntry->TssSeg.Limit19_16_and_flags =3D 0; > > + TssEntry->TssSeg.Base31_24 =3D (UINT8)(TssBase >> 24); > > + > > + StackTop =3D StackBase + StackSize - CPU_STACK_ALIGNMENT; > > + StackTop =3D (UINTN)ALIGN_POINTER (StackTop, CPU_STACK_ALIGNMENT); > > + for (Index =3D 0; Index < ARRAY_SIZE (mExceptionsWithStack); ++Index= ) { > > + // > > + // Fixup TSS descriptor > > + // > > + TssBase =3D (UINTN)(VOID *)&TssEntry->ExceptionTss[Index]; > > + TssDesc =3D &TssEntry->ExceptionTssSeg[Index]; > > + > > + TssDesc->Limit15_0 =3D sizeof(IA32_TASK_STATE_SEGMENT) = - 1; > > + TssDesc->Base15_0 =3D (UINT16)TssBase; > > + TssDesc->Base23_16 =3D (UINT8)(TssBase >> 16); > > + TssDesc->Type =3D IA32_GDT_TYPE_TSS; > > + TssDesc->Limit19_16_and_flags =3D 0; > > + TssDesc->Base31_24 =3D (UINT8)(TssBase >> 24); > > + > > + // > > + // Fixup TSS > > + // > > + Tss =3D &TssEntry->ExceptionTss[Index]; > > + Tss->CR3 =3D AsmReadCr3(); > > + Tss->EIP =3D (UINT32)mExceptionsWithStack[Index].EntryPoint; > > + Tss->EFLAGS =3D 0x2; > > + Tss->ESP =3D StackTop; > > + Tss->ES =3D AsmReadEs(); > > + Tss->CS =3D AsmReadCs(); > > + Tss->SS =3D AsmReadSs(); > > + Tss->DS =3D AsmReadDs(); > > + Tss->FS =3D AsmReadFs(); > > + Tss->GS =3D AsmReadGs(); > > + StackTop -=3D EXCEPTION_STACK_SIZE; > > + > > + // > > + // Change specified exceptions in IDT to use TSS > > + // > > + Vector =3D mExceptionsWithStack[Index].Vector; > > + > > + IdtTable[Vector].Bits.OffsetLow =3D 0; > > + IdtTable[Vector].Bits.Selector =3D OldGdtSize + > > EXCEPTION_TSS_SEL(Index); > > + IdtTable[Vector].Bits.Reserved_0 =3D 0; > > + IdtTable[Vector].Bits.GateType =3D IA32_IDT_GATE_TYPE_TASK; > > + IdtTable[Vector].Bits.OffsetHigh =3D 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.
> > +; This program and the accompanying materials > > +; are licensed and made available under the terms and conditions of th= e BSD > > License > > +; which accompanies this distribution. The full text of the license m= ay 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 =3D Current TSS base > > + push ecx ; keep it in stack for later u= se > > + > > + movzx ebx, word [ecx] ; Previous Task Link > > + mov ecx, [eax + ebx + 2] > > + shl ecx, 8 > > + mov cl, [eax + ebx + 7] > > + ror ecx, 8 ; ecx =3D 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 EF= LAGs 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 point= er > > + mov ebx, dword [ecx + IA32_TSS.EIP] > > + mov [eax - 0xc], ebx ; create EIP in old s= tack > > + movzx ebx, word [ecx + IA32_TSS._CS] > > + mov [eax - 0x8], ebx ; create CS in old st= ack > > + mov ebx, dword [ecx + IA32_TSS.EFLAGS] > > + bts ebx, 8 > > + mov [eax - 0x4], ebx ; create eflags in ol= d stack > > + mov dword [ecx + IA32_TSS.EFLAGS], ebx ; update eflags in ol= d TSS > > + mov eax, dword [ecx + IA32_TSS._ESP] ; Get old stack point= er > > + sub eax, 0xc ; minus 12 byte > > + mov dword [ecx + IA32_TSS._ESP], eax ; Set new stack point= er > > + > > +;; 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 bas= e > > + mov eax, dword [ecx + IA32_TSS._ESP] ; Return current stac= k 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.i= nf > > b/UefiCpuPkg/Library/CpuExceptionHandlerLib/PeiCpuExceptionHandlerLib.i= nf > > index 75443288a9..4c0d435136 100644 > > --- > > a/UefiCpuPkg/Library/CpuExceptionHandlerLib/PeiCpuExceptionHandlerLib.i= nf > > +++ > > b/UefiCpuPkg/Library/CpuExceptionHandlerLib/PeiCpuExceptionHandlerLib.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/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[] =3D { > > + 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 =3D > > 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 =3D GdtDesc.Limit + 1; > > + NewGdt =3D AllocateRuntimeZeroPool(OldGdtSize + sizeof(TSS_ENTRIES) > > + + IA32_GDT_ALIGNMENT); > > + if (NewGdt =3D=3D NULL) { > > + return; > > + } > > + NewGdt =3D ALIGN_POINTER (NewGdt, IA32_GDT_ALIGNMENT); > > + > > + // > > + // Initialize new GDT entries > > + // > > + CopyMem(NewGdt, (VOID *)GdtDesc.Base, OldGdtSize); > > + GdtDesc.Base =3D (UINTN)(VOID*)NewGdt; > > + GdtDesc.Limit =3D (UINT16)(OldGdtSize + TSS_OFFSET - 1); > > + > > + // > > + // Reserve statck memory for supported exceptions > > + // > > + StackSize =3D ARRAY_SIZE (mExceptionsWithStack) * EXCEPTION_STACK_SI= ZE; > > + StackSize =3D EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (StackSize)); > > + StackBase =3D (UINT64)AllocatePages (EFI_SIZE_TO_PAGES (StackSize)); > > + if (StackBase =3D=3D 0) { > > + FreePool (NewGdt); > > + return; > > + } > > + > > + // > > + // Fixup TSS descriptors > > + // > > + TssEntry =3D (VOID *)(GdtDesc.Base + OldGdtSize); > > + TssBase =3D (UINTN)(VOID *)&TssEntry->Tss; > > + > > + TssEntry->TssSeg.Limit15_0 =3D > > sizeof(IA32_TASK_STATE_SEGMENT) - 1; > > + TssEntry->TssSeg.Base15_0 =3D (UINT16)TssBase; > > + TssEntry->TssSeg.Base23_16 =3D (UINT8)(TssBase >> 16); > > + TssEntry->TssSeg.Type =3D IA32_GDT_TYPE_TSS; > > + TssEntry->TssSeg.Limit19_16_and_flags =3D 0; > > + TssEntry->TssSeg.Base31_24 =3D (UINT8)(TssBase >> 24); > > + TssEntry->TssSeg.Base63_32 =3D (UINT32)(TssBase >> 32); > > + TssEntry->TssSeg.Reserved =3D 0; > > + > > + // > > + // Enable Interrupt Stack Table (IST) for each required exception > > + // > > + StackTop =3D StackBase + StackSize - CPU_STACK_ALIGNMENT; > > + StackTop =3D (UINTN)ALIGN_POINTER (StackTop, CPU_STACK_ALIGNMENT); > > + for (Index =3D 0; Index < ARRAY_SIZE (mExceptionsWithStack); ++Index= ) { > > + // > > + // Fixup TSS > > + // > > + TssEntry->Tss.IST[Index] =3D StackTop; > > + StackTop -=3D EXCEPTION_STACK_SIZE; > > + > > + // > > + // Set the IST field to 1 to enable corresponding IST > > + // > > + IdtTable[mExceptionsWithStack[Index]].Bits.Reserved_0 =3D (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