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=jiewen.yao@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 6B5512034CF96 for ; Tue, 31 Oct 2017 18:52:57 -0700 (PDT) Received: from fmsmga003.fm.intel.com ([10.253.24.29]) by fmsmga104.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 31 Oct 2017 18:56:49 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.44,326,1505804400"; d="scan'208";a="916060339" Received: from fmsmsx105.amr.corp.intel.com ([10.18.124.203]) by FMSMGA003.fm.intel.com with ESMTP; 31 Oct 2017 18:56:49 -0700 Received: from FMSMSX110.amr.corp.intel.com (10.18.116.10) by FMSMSX105.amr.corp.intel.com (10.18.124.203) with Microsoft SMTP Server (TLS) id 14.3.319.2; Tue, 31 Oct 2017 18:56:49 -0700 Received: from shsmsx101.ccr.corp.intel.com (10.239.4.153) by fmsmsx110.amr.corp.intel.com (10.18.116.10) with Microsoft SMTP Server (TLS) id 14.3.319.2; Tue, 31 Oct 2017 18:56:47 -0700 Received: from shsmsx102.ccr.corp.intel.com ([169.254.2.175]) by SHSMSX101.ccr.corp.intel.com ([169.254.1.159]) with mapi id 14.03.0319.002; Wed, 1 Nov 2017 09:56:46 +0800 From: "Yao, Jiewen" To: "Wang, Jian J" , "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+wnPg Date: Wed, 1 Nov 2017 01:56:45 +0000 Message-ID: <74D8A39837DF1E4DA445A8C0B3885C503AA0AED6@shsmsx102.ccr.corp.intel.com> References: <20171031142412.21680-1-jian.j.wang@intel.com> <20171031142412.21680-4-jian.j.wang@intel.com> In-Reply-To: <20171031142412.21680-4-jian.j.wang@intel.com> Accept-Language: zh-CN, 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 01:52:57 -0000 Content-Language: en-US Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable 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 > Cc: Zeng, Star ; Dong, Eric ; Y= ao, > Jiewen ; Kinney, Michael D > > Subject: [PATCH 3/3] UefiCpuPkg/CpuExceptionHandlerLib: Add stack switch > support >=20 > If Stack Guard is enabled and there's really a stack overflow happened du= ring > 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 dri= ver, > cannot be executed and cannot dump the processor information. >=20 > Without those information, it's very difficult for the BIOS developers lo= cate > the root cause of stack overflow. And without a workable stack, the devel= oper > cannot event use single step to debug the UEFI driver with JTAG debugger. >=20 > In order to make sure the exception handler to execute normally after sta= ck > overflow. We need separate stacks for exception handlers in case of unusa= ble > stack. >=20 > IA processor allows to switch to a new stack during handling interrupt an= d > exception. But X64 and IA32 provides different ways to make it. X64 provi= des > interrupt stack table (IST) to allow maximum 7 different exceptions to ha= ve > new stack for its handler. IA32 doesn't have IST mechanism and can only u= se > task gate to do it since task switch allows to load a new stack through i= ts > task-state segment (TSS). >=20 > Note: Stack switch needs to allocate memory pages to be new stacks. So th= is > 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 swi= tch. >=20 > 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 >=20 > 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 >=20 > #define CPU_EXCEPTION_NUM 32 > #define CPU_INTERRUPT_NUM 256 > @@ -288,5 +289,26 @@ CommonExceptionHandlerWorker ( > IN EXCEPTION_HANDLER_DATA *ExceptionHandlerData > ); >=20 > +/** > + 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 >=20 > 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 >=20 > +[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 >=20 > CONST UINTN mDoFarReturnFlag =3D 0; >=20 > @@ -155,6 +156,24 @@ InitializeCpuInterruptHandlers ( >=20 > UpdateIdtTable (IdtTable, &TemplateMap, &mExceptionHandlerData); >=20 > + 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 @@ >=20 > #include "CpuExceptionCommon.h" >=20 > +// > +// 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 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 =3D > ReservedVectors[ExceptionType].ExceptionData; > } >=20 > +/** > + 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_SIZE= ; > + 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. >=20 > 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; >=20 > +#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 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 =3D 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 =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 EFLA= Gs 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 sta= ck > + movzx ebx, word [ecx + IA32_TSS._CS] > + mov [eax - 0x8], ebx ; create CS in old stac= k > + 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 @@ >=20 > #include "CpuExceptionCommon.h" >=20 > +// > +// 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; > } >=20 > +/** > + 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_SIZE= ; > + 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)(In= dex + > 1); > + } > + > + // > + // Publish the changes > + // > + AsmWriteGdtr(&GdtDesc); > + > + // > + // Load task register > + // > + AsmWriteTr ((UINT16)(OldGdtSize + TSS_SEL)); > +} > + > /** > Display CPU information. >=20 > 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; >=20 > +#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 >=20 > +#-----------------------------------------------------------------------= ------- > +# VOID > +# AsmWriteTr ( > +# UINT16 Selector > +# ); > +#-----------------------------------------------------------------------= ------- > +ASM_GLOBAL ASM_PFX(AsmWriteTr) > +ASM_PFX(AsmWriteTr): > + movl %ecx, %eax > + ltrw %ax > + ret > + > #END >=20 >=20 > 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 >=20 > +;-----------------------------------------------------------------------= ------- > +; 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 >=20 > +;-----------------------------------------------------------------------= ------- > +; VOID > +; AsmWriteTr ( > +; UINT16 Selector > +; ); > +;-----------------------------------------------------------------------= ------- > +global ASM_PFX(AsmWriteTr) > +ASM_PFX(AsmWriteTr): > + mov eax, ecx > + ltr ax > + ret > + > -- > 2.14.1.windows.1