From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received-SPF: Pass (sender SPF authorized) identity=mailfrom; client-ip=134.134.136.31; helo=mga06.intel.com; envelope-from=jiewen.yao@intel.com; receiver=edk2-devel@lists.01.org Received: from mga06.intel.com (mga06.intel.com [134.134.136.31]) (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 7F7612034A760 for ; Mon, 27 Nov 2017 18:01:59 -0800 (PST) Received: from fmsmga002.fm.intel.com ([10.253.24.26]) by orsmga104.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 27 Nov 2017 18:06:21 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.44,466,1505804400"; d="scan'208";a="1249276720" Received: from fmsmsx106.amr.corp.intel.com ([10.18.124.204]) by fmsmga002.fm.intel.com with ESMTP; 27 Nov 2017 18:06:21 -0800 Received: from fmsmsx152.amr.corp.intel.com (10.18.125.5) by FMSMSX106.amr.corp.intel.com (10.18.124.204) with Microsoft SMTP Server (TLS) id 14.3.319.2; Mon, 27 Nov 2017 18:06:21 -0800 Received: from shsmsx101.ccr.corp.intel.com (10.239.4.153) by FMSMSX152.amr.corp.intel.com (10.18.125.5) with Microsoft SMTP Server (TLS) id 14.3.319.2; Mon, 27 Nov 2017 18:06:19 -0800 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; Tue, 28 Nov 2017 10:06:18 +0800 From: "Yao, Jiewen" To: "Wang, Jian J" , "edk2-devel@lists.01.org" CC: "Kinney, Michael D" , "Dong, Eric" , "Zeng, Star" Thread-Topic: [PATCH v2 7/8] UefiCpuPkg/CpuExceptionHandlerLib: Add stack switch support Thread-Index: AQHTY25fasIJD8yp+ESaspdkZc+2NKMhdfOQ//9/OICAAIa+gP//g+0AgAeGgYCAAIuwwA== Date: Tue, 28 Nov 2017 02:06:17 +0000 Message-ID: <74D8A39837DF1E4DA445A8C0B3885C503AA2ED06@shsmsx102.ccr.corp.intel.com> References: <20171122084548.6564-1-jian.j.wang@intel.com> <20171122084548.6564-8-jian.j.wang@intel.com> <74D8A39837DF1E4DA445A8C0B3885C503AA292EF@shsmsx102.ccr.corp.intel.com> <74D8A39837DF1E4DA445A8C0B3885C503AA29365@shsmsx102.ccr.corp.intel.com> In-Reply-To: Accept-Language: zh-CN, en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-titus-metadata-40: eyJDYXRlZ29yeUxhYmVscyI6IiIsIk1ldGFkYXRhIjp7Im5zIjoiaHR0cDpcL1wvd3d3LnRpdHVzLmNvbVwvbnNcL0ludGVsMyIsImlkIjoiOGQwMGI0OWQtZDQ3MS00Yjk2LTljZjgtM2Q3YmYyZmZlYjM1IiwicHJvcHMiOlt7Im4iOiJDVFBDbGFzc2lmaWNhdGlvbiIsInZhbHMiOlt7InZhbHVlIjoiQ1RQX0lDIn1dfV19LCJTdWJqZWN0TGFiZWxzIjpbXSwiVE1DVmVyc2lvbiI6IjE3LjIuNS4xOCIsIlRydXN0ZWRMYWJlbEhhc2giOiJzWVQrYjlDWGtaRlRKVzVKUmRmK2tDeUQxNU1WcVZicGx6eUNaWEVpaVZNTlNTbGpUWFFlUTNZK3BhQ3FXOVVIIn0= 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 v2 7/8] 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: Tue, 28 Nov 2017 02:01:59 -0000 Content-Language: en-US Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable Thanks Jian. I just talked to some other person, who think it is valuable to have stack = guard in PEI as well, because they have seen stack overflow issue in PEI. I= do think we need consider that, although it is not implemented in this pat= ch series. My thought for API is that the API design for PEI/DXE/SMM should be consist= ent. When people look at the MdeModulePkg\Include\Library\CpuExceptionHandlerLib= .h, he can know clearly on which API should be called and what is done in e= ach API. If we call InitializeCpuExceptionStackSwitchHandlers() inside InitializeCpu= ExceptionHandlers(), we should document this in .H file and make PEI/DXE/SM= M version all implement in this way. If we did one way for DXE, the other way for PEI, and another way for SMM, = it might bring confusing. Thank you Yao Jiewen > -----Original Message----- > From: Wang, Jian J > Sent: Tuesday, November 28, 2017 9:39 AM > To: Yao, Jiewen ; edk2-devel@lists.01.org > Cc: Kinney, Michael D ; Dong, Eric > ; Zeng, Star > Subject: RE: [PATCH v2 7/8] UefiCpuPkg/CpuExceptionHandlerLib: Add stack > switch support >=20 > Sorry, 1.3 should be for your 1.4. I just noticed I missed your 1.3 comme= nt. > Here's my opinion for it: >=20 > Current changes (use global variables to reserve resources) to > InitializeCpuExceptionHandlers() is for DXE only. For PEI, if we really n= eed to > worry > about the stack overflow and stack switch, we can have a different way to= do it. > For > example, we don't need to call InitializeCpuExceptionStackSwitchHandlers(= ) > inside > InitializeCpuExceptionHandlers(). We could call it whenever we can reserv= e > memory blocks > and pass them to InitializeCpuExceptionStackSwitchHandlers() via paramete= r. I > think this > is one of reason we have a separate method to initialize the exception ha= ndlers > for the > sake of stack switch. >=20 > Calling InitializeCpuExceptionStackSwitchHandlers() inside > InitializeCpuExceptionHandlers() > is just for the consideration of backward compatibility. Because this new= API is > just > implemented for IA32 processor at this time, calling it in DXE core will = break the > build of > other type of processors. This is another reason we have a separate metho= d to > do > exception handler initialization in a different way. >=20 > > -----Original Message----- > > From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of > Wang, > > Jian J > > Sent: Thursday, November 23, 2017 2:44 PM > > To: Yao, Jiewen ; edk2-devel@lists.01.org > > Cc: Kinney, Michael D ; Dong, Eric > > ; Zeng, Star > > Subject: Re: [edk2] [PATCH v2 7/8] UefiCpuPkg/CpuExceptionHandlerLib: A= dd > > stack switch support > > > > 1.1) Got your point. I'll add dummy function in this patch. > > 1.2) Yep, we're on the same page. > > 1.3) Here's my opinion: > > > > Actually almost all MP code has such assumption: any AP configuration w= ill > copy > > from BSP. If we allow AP to call InitializeCpuExceptionHandlers(), we = have to > do > > a lot > > of other changes than just updating InitializeCpuExceptionHandlers(). I= f so, it > > may > > be premature to figure out a solution at this patch. > > > > In addition, CpuDxe actually calls InitializeCpuInterruptHandlers() whi= ch covers > > the > > functionalities of InitializeCpuExceptionHandlers() (its settings will = be > > overwritten). > > If we want AP to initialize interrupt and exception individually, maybe= we > should > > let AP call InitializeCpuInterruptHandlers() instead. > > > > > -----Original Message----- > > > From: Yao, Jiewen > > > Sent: Thursday, November 23, 2017 2:16 PM > > > To: Wang, Jian J ; edk2-devel@lists.01.org > > > Cc: Zeng, Star ; Dong, Eric ; > > > Kinney, Michael D > > > Subject: RE: [PATCH v2 7/8] UefiCpuPkg/CpuExceptionHandlerLib: Add st= ack > > > switch support > > > > > > Here is my thought for 1) > > > > > > 1.1) We must provide the InitializeCpuExceptionStackSwitchHandlers() > > > implementation in Pei instance and Smm instance. > > > > > > The basic requirement is a library instance must provide symbol for f= unctions > > > declared in header file. > > > It is ok to return unsupported. But we MUST provide the symbol. > > > > > > 1.2) For SMM, I think our ultimate goal is to remove SMM specific sta= ck > guard, > > > and use the common one. Duplicating code is completely unnecessary, a= nd it > is > > > easy to introduce bug. And unfortunately, we already have bug in exis= ting > > SMM > > > exception handler. -- That is a good reason to remove duplication. > > > > > > Again, it is not necessary to do it in this patch. I am totally OK to= do it in > > another > > > patch. > > > > > > 1.3) For PEI, I do not think we can use current way to allocate stack= in data > > > section, because it might be readonly in pre-mem phase. We must use s= ome > > > other way. > > > > > > 1.4) I believe this patch has a hidden assumption is that: > > > InitializeCpuExceptionHandlers() won't be called by multiple APs. > > > If 2 or more APs call the it at same time, it might be broken because= you use > > > mNewStack for all the callers.... > > > Is that right? > > > > > > > > > Thank you > > > Yao Jiewen > > > > > > > > > > -----Original Message----- > > > > From: Wang, Jian J > > > > Sent: Thursday, November 23, 2017 2:06 PM > > > > To: Yao, Jiewen ; edk2-devel@lists.01.org > > > > Cc: Zeng, Star ; Dong, Eric ; > > > Kinney, > > > > Michael D > > > > Subject: RE: [PATCH v2 7/8] UefiCpuPkg/CpuExceptionHandlerLib: Add > stack > > > > switch support > > > > > > > > > > > > > > > > > -----Original Message----- > > > > > From: Yao, Jiewen > > > > > Sent: Thursday, November 23, 2017 1:50 PM > > > > > To: Wang, Jian J ; edk2-devel@lists.01.org > > > > > Cc: Zeng, Star ; Dong, Eric ; > > > > > Kinney, Michael D > > > > > Subject: RE: [PATCH v2 7/8] UefiCpuPkg/CpuExceptionHandlerLib: Ad= d > > stack > > > > > switch support > > > > > > > > > > Some thought: > > > > > > > > > > 1) I found InitializeCpuExceptionStackSwitchHandlers() is only > implemented > > > in > > > > > DxeException.c. > > > > > What about Pei/Smm instance? > > > > > > > > > > I think it is OK to not implement it at this moment. But we need = make sure > > no > > > > > architecture issue if we want to enable it some time later. > > > > > > > > > Like what we discussed before, this series of patch is for Stack Gu= ard > feature > > > > which > > > > is only available for DXE (because Stack Guard needs paging to work= ). Stack > > > > switch > > > > is enabled for the sake of Stack Guard feature. So I think it's eno= ugh to > > > > implement > > > > it in DxeException.c. In addition, SMM has its own implementation o= f stack > > > guard > > > > and stack switch. It's not necessary to do it again. > > > > > > > > I agree with you that we should merge those common code but I think= we > > > should > > > > do > > > > it in a separate patch series since it's not Stack Guard relevant. = And I've > > > removed > > > > all architecture issues I can think of. Current stack switch initia= lization > should > > > work > > > > for both PEI and SMM as well. > > > > > > > > > 2) #define IA32_GDT_TYPE_TSS 0x9 > > > > > This is generic, can we move to BaseLib.h? > > > > > > > > > > > > > > > Thank you > > > > > Yao Jiewen > > > > > > > > > > > > > > > > -----Original Message----- > > > > > > From: Wang, Jian J > > > > > > Sent: Wednesday, November 22, 2017 4:46 PM > > > > > > To: edk2-devel@lists.01.org > > > > > > Cc: Zeng, Star ; Dong, Eric > ; > > > Yao, > > > > > > Jiewen ; Kinney, Michael D > > > > > > > > > > > > Subject: [PATCH v2 7/8] UefiCpuPkg/CpuExceptionHandlerLib: Add > stack > > > > > switch > > > > > > support > > > > > > > > > > > > > v2: > > > > > > > a. Move common TSS structure and API definitions to BaseLi= b.h > > > > > > > b. Add EXCEPTION_STACK_SWITCH_DATA to convery data used > to > > > > setup > > > > > > stack > > > > > > > switch. This can avoid allocating memory for it in this= library. > > > > > > > c. Add globals to reserve memory for stack switch initiali= zed in > early > > > > > > > phase of DXE core. > > > > > > > d. Remove the filter code used to exclude boot modes which > doesn't > > > > > > support > > > > > > > memory allocation because those memory can passed in by > > > > parameter > > > > > > now. > > > > > > > e. Remove the nasm macro to define exception handler one b= y > one > > > > and > > > > > > add a > > > > > > > function to return the start address of each handler. > > > > > > > > > > > > If Stack Guard is enabled and there's really a stack overflow h= appened > > > during > > > > > > boot, a Page Fault exception will be triggered. Because the sta= ck is out > of > > > > > > usage, the exception handler, which shares the stack with norma= l UEFI > > > driver, > > > > > > cannot be executed and cannot dump the processor information. > > > > > > > > > > > > Without those information, it's very difficult for the BIOS dev= elopers > > 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 cas= e of > > > unusable > > > > > > stack. > > > > > > > > > > > > IA processor allows to switch to a new stack during handling in= terrupt > > and > > > > > > exception. But X64 and IA32 provides different ways to make it.= X64 > > > provides > > > > > > interrupt stack table (IST) to allow maximum 7 different except= ions to > > have > > > > > > new stack for its handler. IA32 doesn't have IST mechanism and = can > only > > > use > > > > > > task gate to do it since task switch allows to load a new stack= through its > > > > > > task-state segment (TSS). > > > > > > > > > > > > Cc: Star Zeng > > > > > > 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 | 50 +++ > > > > > > .../DxeCpuExceptionHandlerLib.inf | 6 + > > > > > > .../Library/CpuExceptionHandlerLib/DxeException.c | 53 ++- > > > > > > .../Ia32/ArchExceptionHandler.c | 167 > +++++++++ > > > > > > .../Ia32/ArchInterruptDefs.h | 8 + > > > > > > .../Ia32/ExceptionTssEntryAsm.nasm | 398 > > > > > > +++++++++++++++++++++ > > > > > > .../PeiCpuExceptionHandlerLib.inf | 1 + > > > > > > .../SecPeiCpuExceptionHandlerLib.inf | 1 + > > > > > > .../SmmCpuExceptionHandlerLib.inf | 1 + > > > > > > .../X64/ArchExceptionHandler.c | 133 > +++++++ > > > > > > .../CpuExceptionHandlerLib/X64/ArchInterruptDefs.h | 3 + > > > > > > 11 files changed, 820 insertions(+), 1 deletion(-) > > > > > > create mode 100644 > > > > > > > > > > > > > > > > > > > > > UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ExceptionTssEntryAsm.nasm > > > > > > > > > > > > diff --git > > > > > > > a/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h > > > > > > > b/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h > > > > > > index 740a58828b..30334105d2 100644 > > > > > > --- > > > a/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h > > > > > > +++ > > > > b/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h > > > > > > @@ -48,6 +48,32 @@ > > > > > > 0xb21d9148, 0x9211, 0x4d8f, { 0xad, 0xd3, 0x66, 0xb1, 0x89= , > 0xc9, > > 0x2c, > > > > > 0x83 } > > > > > > \ > > > > > > } > > > > > > > > > > > > +#define CPU_STACK_SWITCH_EXCEPTION_NUMBER \ > > > > > > + FixedPcdGetSize (PcdCpuStackSwitchExceptionList) > > > > > > + > > > > > > +#define CPU_STACK_SWITCH_EXCEPTION_LIST \ > > > > > > + FixedPcdGetPtr (PcdCpuStackSwitchExceptionList) > > > > > > + > > > > > > +#define CPU_KNOWN_GOOD_STACK_SIZE \ > > > > > > + FixedPcdGet32 (PcdCpuKnownGoodStackSize) > > > > > > + > > > > > > +#define CPU_TSS_GDT_SIZE (SIZE_2KB + CPU_TSS_DESC_SIZE + > > > > > CPU_TSS_SIZE) > > > > > > + > > > > > > +#define IA32_GDT_TYPE_TSS 0x9 > > > > > > +#define IA32_GDT_ALIGNMENT 8 > > > > > > + > > > > > > +typedef struct { > > > > > > + UINTN StackTop; > > > > > > + UINTN StackSize; > > > > > > + UINT8 *Exceptions; > > > > > > + UINTN ExceptionNumber; > > > > > > + IA32_IDT_GATE_DESCRIPTOR *IdtTable; > > > > > > + IA32_SEGMENT_DESCRIPTOR *GdtTable; > > > > > > + UINTN GdtSize; > > > > > > + IA32_TSS_DESCRIPTOR *TssDesc; > > > > > > + IA32_TASK_STATE_SEGMENT *Tss; > > > > > > +} EXCEPTION_STACK_SWITCH_DATA; > > > > > > + > > > > > > // > > > > > > // Record exception handler information > > > > > > // > > > > > > @@ -288,5 +314,29 @@ CommonExceptionHandlerWorker ( > > > > > > IN EXCEPTION_HANDLER_DATA *ExceptionHandlerData > > > > > > ); > > > > > > > > > > > > +/** > > > > > > + Setup separate stack for specific exceptions. > > > > > > + > > > > > > + @param[in] IdtTable IDT table base. > > > > > > +**/ > > > > > > +EFI_STATUS > > > > > > +EFIAPI > > > > > > +ArchSetupExcpetionStack ( > > > > > > + IN EXCEPTION_STACK_SWITCH_DATA *StackSwitchData > > > > > > + ); > > > > > > + > > > > > > +/** > > > > > > + Return address map of exception handler template so that C c= ode > can > > > > > > generate > > > > > > + exception tables. The template is only for exceptions using = task gate > > > > instead > > > > > > + of interrupt gate. > > > > > > + > > > > > > + @param AddressMap Pointer to a buffer where the address map > is > > > > > > returned. > > > > > > +**/ > > > > > > +VOID > > > > > > +EFIAPI > > > > > > +AsmGetTssTemplateMap ( > > > > > > + OUT EXCEPTION_HANDLER_TEMPLATE_MAP *AddressMap > > > > > > + ); > > > > > > + > > > > > > #endif > > > > > > > > > > > > diff --git > > > > > > > > > > > > > > > > > > > > > a/UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandlerLib.inf > > > > > > > > > > > > > > > > > > > > > b/UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandlerLib.inf > > > > > > index f4a8d01c80..58e55a8a2e 100644 > > > > > > --- > > > > > > > > > > > > > > > > > > > > > a/UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandlerLib.inf > > > > > > +++ > > > > > > > > > > > > > > > > > > > > > b/UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandlerLib.inf > > > > > > @@ -30,6 +30,7 @@ > > > > > > [Sources.Ia32] > > > > > > Ia32/ExceptionHandlerAsm.asm > > > > > > Ia32/ExceptionHandlerAsm.nasm > > > > > > + Ia32/ExceptionTssEntryAsm.nasm > > > > > > Ia32/ExceptionHandlerAsm.S > > > > > > Ia32/ArchExceptionHandler.c > > > > > > Ia32/ArchInterruptDefs.h > > > > > > @@ -47,6 +48,11 @@ > > > > > > PeiDxeSmmCpuException.c > > > > > > DxeException.c > > > > > > > > > > > > +[Pcd] > > > > > > + gEfiMdeModulePkgTokenSpaceGuid.PcdCpuStackGuard > > > > > > + gUefiCpuPkgTokenSpaceGuid.PcdCpuStackSwitchExceptionList > > > > > > + gUefiCpuPkgTokenSpaceGuid.PcdCpuKnownGoodStackSize > > > > > > + > > > > > > [Packages] > > > > > > MdePkg/MdePkg.dec > > > > > > MdeModulePkg/MdeModulePkg.dec > > > > > > diff --git > a/UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeException.c > > > > > > b/UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeException.c > > > > > > index 31febec976..c0b2c615aa 100644 > > > > > > --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeException.c > > > > > > +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeException.c > > > > > > @@ -25,6 +25,10 @@ UINTN > > > > mEnabledInterruptNum =3D > > > > > > 0; > > > > > > > > > > > > EXCEPTION_HANDLER_DATA mExceptionHandlerData; > > > > > > > > > > > > +UINT8 > > > > > > mNewStack[CPU_STACK_SWITCH_EXCEPTION_NUMBER * > > > > > > + > > > > CPU_KNOWN_GOOD_STACK_SIZE] > > > > > > =3D {0}; > > > > > > +UINT8 mNewGdt[CPU_TSS_GDT_SIZE] =3D > {0}; > > > > > > + > > > > > > /** > > > > > > Common exception handler. > > > > > > > > > > > > @@ -63,10 +67,34 @@ InitializeCpuExceptionHandlers ( > > > > > > IN EFI_VECTOR_HANDOFF_INFO *VectorInfo OPTIONAL > > > > > > ) > > > > > > { > > > > > > + EFI_STATUS Status; > > > > > > + EXCEPTION_STACK_SWITCH_DATA StackSwitchData; > > > > > > + IA32_DESCRIPTOR Idtr; > > > > > > + IA32_DESCRIPTOR Gdtr; > > > > > > + > > > > > > mExceptionHandlerData.ReservedVectors =3D > > > > > > mReservedVectorsData; > > > > > > mExceptionHandlerData.ExternalInterruptHandler =3D > > > > > > mExternalInterruptHandlerTable; > > > > > > InitializeSpinLock > (&mExceptionHandlerData.DisplayMessageSpinLock); > > > > > > - return InitializeCpuExceptionHandlersWorker (VectorInfo, > > > > > > &mExceptionHandlerData); > > > > > > + Status =3D InitializeCpuExceptionHandlersWorker (VectorInfo, > > > > > > &mExceptionHandlerData); > > > > > > + if (!EFI_ERROR (Status) && PcdGetBool (PcdCpuStackGuard)) { > > > > > > + AsmReadIdtr (&Idtr); > > > > > > + AsmReadGdtr (&Gdtr); > > > > > > + > > > > > > + StackSwitchData.StackTop =3D (UINTN)mNewStack; > > > > > > + StackSwitchData.StackSize =3D CPU_KNOWN_GOOD_STACK_SIZE; > > > > > > + StackSwitchData.Exceptions =3D > CPU_STACK_SWITCH_EXCEPTION_LIST; > > > > > > + StackSwitchData.ExceptionNumber =3D > > > > > > CPU_STACK_SWITCH_EXCEPTION_NUMBER; > > > > > > + StackSwitchData.IdtTable =3D (IA32_IDT_GATE_DESCRIPTOR > *)Idtr.Base; > > > > > > + StackSwitchData.GdtTable =3D (IA32_SEGMENT_DESCRIPTOR > > > > *)mNewGdt; > > > > > > + StackSwitchData.GdtSize =3D sizeof (mNewGdt); > > > > > > + StackSwitchData.TssDesc =3D (IA32_TSS_DESCRIPTOR *)(mNewGd= t > + > > > > > > Gdtr.Limit + 1); > > > > > > + StackSwitchData.Tss =3D (IA32_TASK_STATE_SEGMENT > *)(mNewGdt + > > > > > > Gdtr.Limit + 1 + > > > > > > + > > > > > > CPU_TSS_DESC_SIZE); > > > > > > + Status =3D InitializeCpuExceptionStackSwitchHandlers ( > > > > > > + &StackSwitchData > > > > > > + ); > > > > > > + } > > > > > > + return Status; > > > > > > } > > > > > > > > > > > > /** > > > > > > @@ -197,3 +225,26 @@ RegisterCpuInterruptHandler ( > > > > > > { > > > > > > return RegisterCpuInterruptHandlerWorker (InterruptType, > > > > InterruptHandler, > > > > > > &mExceptionHandlerData); > > > > > > } > > > > > > + > > > > > > +/** > > > > > > + Setup separate stack for given exceptions. This is required = by > > > > > > + PcdCpuStackGuard feature. > > > > > > + > > > > > > + Note: For IA32 processor, StackSwitchData is a required para= meter. > > > > > > + > > > > > > + @param[in] StackSwitchData Pointer to data required for > setuping > > > > up > > > > > > + stack switch. > > > > > > + > > > > > > + @retval EFI_SUCCESS The exceptions have been > > > > successfully > > > > > > + initialized. > > > > > > + @retval EFI_INVALID_PARAMETER StackSwitchData contains > invalid > > > > > > content. > > > > > > + > > > > > > +**/ > > > > > > +EFI_STATUS > > > > > > +EFIAPI > > > > > > +InitializeCpuExceptionStackSwitchHandlers ( > > > > > > + IN VOID *StackSwitchData OPTIONAL > > > > > > + ) > > > > > > +{ > > > > > > + return ArchSetupExcpetionStack (StackSwitchData); > > > > > > +} > > > > > > diff --git > > > > > > > > > > a/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchExceptionHandler.c > > > > > > > > > > b/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchExceptionHandler.c > > > > > > index f2c39eb193..0aaf794795 100644 > > > > > > --- > > > > > > > > > a/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchExceptionHandler.c > > > > > > +++ > > > > > > > > > > b/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchExceptionHandler.c > > > > > > @@ -107,6 +107,173 @@ ArchRestoreExceptionContext ( > > > > > > SystemContext.SystemContextIa32->ExceptionData =3D > > > > > > ReservedVectors[ExceptionType].ExceptionData; > > > > > > } > > > > > > > > > > > > +/** > > > > > > + Setup separate stack for given exceptions. > > > > > > + > > > > > > + @param[in] StackSwitchData Pointer to data required f= or > > > > setuping > > > > > > up > > > > > > + stack switch. > > > > > > + @retval EFI_SUCCESS The exceptions have been > > > > successfully > > > > > > + initialized. > > > > > > + @retval EFI_INVALID_PARAMETER StackSwitchData contains > invalid > > > > > > content. > > > > > > + > > > > > > +**/ > > > > > > +EFI_STATUS > > > > > > +EFIAPI > > > > > > +ArchSetupExcpetionStack ( > > > > > > + IN EXCEPTION_STACK_SWITCH_DATA *StackSwitchData > > > > > > + ) > > > > > > +{ > > > > > > + IA32_DESCRIPTOR Gdtr; > > > > > > + IA32_DESCRIPTOR Idtr; > > > > > > + IA32_IDT_GATE_DESCRIPTOR *IdtTable; > > > > > > + IA32_TSS_DESCRIPTOR *TssDesc; > > > > > > + IA32_TASK_STATE_SEGMENT *Tss; > > > > > > + UINTN StackTop; > > > > > > + UINTN Index; > > > > > > + UINTN Vector; > > > > > > + UINTN TssBase; > > > > > > + UINTN GdtSize; > > > > > > + EXCEPTION_HANDLER_TEMPLATE_MAP TemplateMap; > > > > > > + > > > > > > + if (StackSwitchData =3D=3D NULL || > > > > > > + StackSwitchData->StackTop =3D=3D 0 || > > > > > > + StackSwitchData->StackSize =3D=3D 0 || > > > > > > + StackSwitchData->Exceptions =3D=3D NULL || > > > > > > + StackSwitchData->ExceptionNumber =3D=3D 0 || > > > > > > + StackSwitchData->GdtTable =3D=3D NULL || > > > > > > + StackSwitchData->IdtTable =3D=3D NULL || > > > > > > + StackSwitchData->TssDesc =3D=3D NULL || > > > > > > + StackSwitchData->Tss =3D=3D NULL) { > > > > > > + return EFI_INVALID_PARAMETER; > > > > > > + } > > > > > > + > > > > > > + // > > > > > > + // The caller is responsible for that the GDT table, no matt= er the > > existing > > > > > > + // one or newly allocated, has enough space to hold descript= ors for > > > > > exception > > > > > > + // task-state segments. > > > > > > + // > > > > > > + if (((UINTN)StackSwitchData->GdtTable & (IA32_GDT_ALIGNMENT > - > > > 1)) !=3D > > > > 0) > > > > > { > > > > > > + return EFI_INVALID_PARAMETER; > > > > > > + } > > > > > > + > > > > > > + if ((UINTN)StackSwitchData->TssDesc < (UINTN)(StackSwitchDat= a- > > > > > >GdtTable)) > > > > > > { > > > > > > + return EFI_INVALID_PARAMETER; > > > > > > + } > > > > > > + > > > > > > + if ((UINTN)StackSwitchData->TssDesc >=3D > > > > > > + ((UINTN)(StackSwitchData->GdtTable) + > > > > StackSwitchData->GdtSize)) > > > > > > { > > > > > > + return EFI_INVALID_PARAMETER; > > > > > > + } > > > > > > + > > > > > > + GdtSize =3D (UINTN)StackSwitchData->TssDesc - > > > > > > + (UINTN)(StackSwitchData->GdtTable) + > > > > > > + sizeof (IA32_TSS_DESCRIPTOR) * > > > > > > + (StackSwitchData->ExceptionNumber + 1); > > > > > > + if (GdtSize > StackSwitchData->GdtSize) { > > > > > > + return EFI_INVALID_PARAMETER; > > > > > > + } > > > > > > + > > > > > > + // > > > > > > + // Initialize new GDT table and/or IDT table, if any > > > > > > + // > > > > > > + AsmReadIdtr (&Idtr); > > > > > > + AsmReadGdtr (&Gdtr); > > > > > > + if ((UINTN)StackSwitchData->GdtTable !=3D Gdtr.Base) { > > > > > > + CopyMem (StackSwitchData->GdtTable, (VOID *)Gdtr.Base, > Gdtr.Limit > > + > > > > 1); > > > > > > + Gdtr.Base =3D (UINTN)StackSwitchData->GdtTable; > > > > > > + Gdtr.Limit =3D (UINT16)StackSwitchData->GdtSize - 1; > > > > > > + } > > > > > > + > > > > > > + if ((UINTN)StackSwitchData->IdtTable !=3D Idtr.Base) { > > > > > > + Idtr.Base =3D (UINTN)StackSwitchData->IdtTable; > > > > > > + } > > > > > > + > > > > > > + // > > > > > > + // Fixup current task descriptor. Task-state segment for cur= rent task > > will > > > > > > + // be filled by processor during task switching. > > > > > > + // > > > > > > + TssDesc =3D StackSwitchData->TssDesc; > > > > > > + Tss =3D StackSwitchData->Tss; > > > > > > + > > > > > > + TssBase =3D (UINTN)Tss; > > > > > > + TssDesc->Bits.LimitLow =3D sizeof(IA32_TASK_STATE_SEGMENT)= - > 1; > > > > > > + TssDesc->Bits.BaseLow =3D (UINT16)TssBase; > > > > > > + TssDesc->Bits.BaseMid =3D (UINT8)(TssBase >> 16); > > > > > > + TssDesc->Bits.Type =3D IA32_GDT_TYPE_TSS; > > > > > > + TssDesc->Bits.P =3D 1; > > > > > > + TssDesc->Bits.LimitHigh =3D 0; > > > > > > + TssDesc->Bits.BaseHigh =3D (UINT8)(TssBase >> 24); > > > > > > + > > > > > > + // > > > > > > + // Fixup exception task descriptor and task-state segment > > > > > > + // > > > > > > + AsmGetTssTemplateMap (&TemplateMap); > > > > > > + StackTop =3D StackSwitchData->StackTop - CPU_STACK_ALIGNMENT= ; > > > > > > + StackTop =3D (UINTN)ALIGN_POINTER (StackTop, > > > > CPU_STACK_ALIGNMENT); > > > > > > + IdtTable =3D StackSwitchData->IdtTable; > > > > > > + for (Index =3D 0; Index < StackSwitchData->ExceptionNumber; > ++Index) { > > > > > > + TssDesc +=3D 1; > > > > > > + Tss +=3D 1; > > > > > > + > > > > > > + // > > > > > > + // Fixup TSS descriptor > > > > > > + // > > > > > > + TssBase =3D (UINTN)Tss; > > > > > > + > > > > > > + TssDesc->Bits.LimitLow =3D sizeof(IA32_TASK_STATE_SEGMENT= ) - > 1; > > > > > > + TssDesc->Bits.BaseLow =3D (UINT16)TssBase; > > > > > > + TssDesc->Bits.BaseMid =3D (UINT8)(TssBase >> 16); > > > > > > + TssDesc->Bits.Type =3D IA32_GDT_TYPE_TSS; > > > > > > + TssDesc->Bits.P =3D 1; > > > > > > + TssDesc->Bits.LimitHigh =3D 0; > > > > > > + TssDesc->Bits.BaseHigh =3D (UINT8)(TssBase >> 24); > > > > > > + > > > > > > + // > > > > > > + // Fixup TSS > > > > > > + // > > > > > > + Vector =3D StackSwitchData->Exceptions[Index]; > > > > > > + Tss->EIP =3D (UINT32)(TemplateMap.ExceptionStart > > > > > > + + Vector * > > > > > > TemplateMap.ExceptionStubHeaderSize); > > > > > > + Tss->EFLAGS =3D 0x2; > > > > > > + Tss->ESP =3D StackTop; > > > > > > + Tss->CR3 =3D AsmReadCr3 (); > > > > > > + 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 StackSwitchData->StackSize; > > > > > > + > > > > > > + // > > > > > > + // Update IDT to use Task Gate for given exception > > > > > > + // > > > > > > + IdtTable[Vector].Bits.OffsetLow =3D 0; > > > > > > + IdtTable[Vector].Bits.Selector =3D (UINT16)((UINTN)TssDe= sc - > > > > Gdtr.Base); > > > > > > + IdtTable[Vector].Bits.Reserved_0 =3D 0; > > > > > > + IdtTable[Vector].Bits.GateType =3D IA32_IDT_GATE_TYPE_TA= SK; > > > > > > + IdtTable[Vector].Bits.OffsetHigh =3D 0; > > > > > > + } > > > > > > + > > > > > > + // > > > > > > + // Publish GDT > > > > > > + // > > > > > > + AsmWriteGdtr (&Gdtr); > > > > > > + > > > > > > + // > > > > > > + // Load current task > > > > > > + // > > > > > > + AsmWriteTr ((UINT16)((UINTN)StackSwitchData->TssDesc - > Gdtr.Base)); > > > > > > + > > > > > > + // > > > > > > + // Publish IDT > > > > > > + // > > > > > > + AsmWriteIdtr (&Idtr); > > > > > > + > > > > > > + return EFI_SUCCESS; > > > > > > +} > > > > > > + > > > > > > /** > > > > > > Display processor context. > > > > > > > > > > > > diff --git > > > > > > > a/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchInterruptDefs.h > > > > > > > b/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchInterruptDefs.h > > > > > > index a8d3556a80..d9ded5977f 100644 > > > > > > --- > > > a/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchInterruptDefs.h > > > > > > +++ > > > > b/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchInterruptDefs.= h > > > > > > @@ -41,4 +41,12 @@ typedef struct { > > > > > > UINT8 > HookAfterStubHeaderCode[HOOKAFTER_STUB_SIZE]; > > > > > > } RESERVED_VECTORS_DATA; > > > > > > > > > > > > +#define CPU_TSS_DESC_SIZE \ > > > > > > + (sizeof (IA32_TSS_DESCRIPTOR) * \ > > > > > > + (PcdGetSize (PcdCpuStackSwitchExceptionList) + 1)) > > > > > > + > > > > > > +#define CPU_TSS_SIZE \ > > > > > > + (sizeof (IA32_TASK_STATE_SEGMENT) * \ > > > > > > + (PcdGetSize (PcdCpuStackSwitchExceptionList) + 1)) > > > > > > + > > > > > > #endif > > > > > > diff --git > > > > > > > > > > > > > > > > > > > > > a/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ExceptionTssEntryAsm.nas > > > > > > m > > > > > > > > > > > > > > > > > > > > > b/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ExceptionTssEntryAsm.nas > > > > > > m > > > > > > new file mode 100644 > > > > > > index 0000000000..62bcedea1a > > > > > > --- /dev/null > > > > > > +++ > > > > > > > > > > > > > > > > > > > > > b/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ExceptionTssEntryAsm.nas > > > > > > m > > > > > > @@ -0,0 +1,398 @@ > > > > > > +;-------------------------------------------------------------= ----------------- ; > > > > > > +; Copyright (c) 2017, Intel Corporation. All rights reserved.<= BR> > > > > > > +; This program and the accompanying materials > > > > > > +; are licensed and made available under the terms and conditio= ns of > the > > > BSD > > > > > > License > > > > > > +; which accompanies this distribution. The full text of the l= icense may > > be > > > > > found > > > > > > at > > > > > > +; http://opensource.org/licenses/bsd-license.php. > > > > > > +; > > > > > > +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS > > IS" > > > > > BASIS, > > > > > > +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER > > > > > EXPRESS > > > > > > OR IMPLIED. > > > > > > +; > > > > > > +; Module Name: > > > > > > +; > > > > > > +; ExceptionTssEntryAsm.Asm > > > > > > +; > > > > > > +; Abstract: > > > > > > +; > > > > > > +; IA32 CPU Exception Handler with Separate Stack > > > > > > +; > > > > > > +; Notes: > > > > > > +; > > > > > > +;-------------------------------------------------------------= ----------------- > > > > > > + > > > > > > +; > > > > > > +; IA32 TSS Memory Layout Description > > > > > > +; > > > > > > +struc IA32_TSS > > > > > > + resw 1 > > > > > > + resw 1 > > > > > > + .ESP0: resd 1 > > > > > > + .SS0: resw 1 > > > > > > + resw 1 > > > > > > + .ESP1: resd 1 > > > > > > + .SS1: resw 1 > > > > > > + resw 1 > > > > > > + .ESP2: resd 1 > > > > > > + .SS2: resw 1 > > > > > > + resw 1 > > > > > > + ._CR3: resd 1 > > > > > > + .EIP: resd 1 > > > > > > + .EFLAGS: resd 1 > > > > > > + ._EAX: resd 1 > > > > > > + ._ECX: resd 1 > > > > > > + ._EDX: resd 1 > > > > > > + ._EBX: resd 1 > > > > > > + ._ESP: resd 1 > > > > > > + ._EBP: resd 1 > > > > > > + ._ESI: resd 1 > > > > > > + ._EDI: resd 1 > > > > > > + ._ES: resw 1 > > > > > > + resw 1 > > > > > > + ._CS: resw 1 > > > > > > + resw 1 > > > > > > + ._SS: resw 1 > > > > > > + resw 1 > > > > > > + ._DS: resw 1 > > > > > > + resw 1 > > > > > > + ._FS: resw 1 > > > > > > + resw 1 > > > > > > + ._GS: resw 1 > > > > > > + resw 1 > > > > > > + .LDT: resw 1 > > > > > > + resw 1 > > > > > > + resw 1 > > > > > > + resw 1 > > > > > > +endstruc > > > > > > + > > > > > > +; > > > > > > +; CommonExceptionHandler() > > > > > > +; > > > > > > +extern ASM_PFX(CommonExceptionHandler) > > > > > > + > > > > > > +SECTION .data > > > > > > + > > > > > > +SECTION .text > > > > > > + > > > > > > +ALIGN 8 > > > > > > + > > > > > > +; > > > > > > +; Exception handler stub table > > > > > > +; > > > > > > +AsmExceptionEntryBegin: > > > > > > +%assign Vector 0 > > > > > > +%rep 32 > > > > > > + > > > > > > +DoIret%[Vector]: > > > > > > + iretd > > > > > > +ASM_PFX(ExceptionTaskSwtichEntry%[Vector]): > > > > > > + db 0x6a ; push #VectorNum > > > > > > + db %[Vector] > > > > > > + mov eax, ASM_PFX(CommonTaskSwtichEntryPoint) > > > > > > + call eax > > > > > > + mov esp, eax ; Restore stack top > > > > > > + jmp DoIret%[Vector] > > > > > > + > > > > > > +%assign Vector Vector+1 > > > > > > +%endrep > > > > > > +AsmExceptionEntryEnd: > > > > > > + > > > > > > +; > > > > > > +; Common part of exception handler > > > > > > +; > > > > > > +global ASM_PFX(CommonTaskSwtichEntryPoint) > > > > > > +ASM_PFX(CommonTaskSwtichEntryPoint): > > > > > > + ; > > > > > > + ; Stack: > > > > > > + ; +---------------------+ <-- EBP - 8 > > > > > > + ; + TSS Base + > > > > > > + ; +---------------------+ <-- EBP - 4 > > > > > > + ; + CPUID.EDX + > > > > > > + ; +---------------------+ <-- EBP > > > > > > + ; + EIP + > > > > > > + ; +---------------------+ <-- EBP + 4 > > > > > > + ; + Vector Number + > > > > > > + ; +---------------------+ <-- EBP + 8 > > > > > > + ; + Error Code + > > > > > > + ; +---------------------+ > > > > > > + ; > > > > > > + > > > > > > + mov ebp, esp ; Stack frame > > > > > > + > > > > > > +; Use CPUID to determine if FXSAVE/FXRESTOR and DE are support= ed > > > > > > + mov eax, 1 > > > > > > + cpuid > > > > > > + push edx > > > > > > + > > > > > > +; Get TSS base of interrupted task through PreviousTaskLink fi= eld 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 interrup= ted 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 su= pport > > > > > > + 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 fl= ag 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 pos= sibility, > > > > > > +;; 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 sta= ck > > > > 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 i= n > old stack > > > > > > + mov ebx, dword [ecx + IA32_TSS.EFLAGS] > > > > > > + bts ebx, 8 > > > > > > + mov [eax - 0x4], ebx ; create efla= gs > in old > > > > stack > > > > > > + mov dword [ecx + IA32_TSS.EFLAGS], ebx ; update efla= gs > in old > > > > TSS > > > > > > + mov eax, dword [ecx + IA32_TSS._ESP] ; Get old sta= ck > > > > pointer > > > > > > + sub eax, 0xc ; minus 12 > byte > > > > > > + mov dword [ecx + IA32_TSS._ESP], eax ; Set new sta= ck > > > > pointer > > > > > > + > > > > > > +;; Replace the EIP of interrupted task with stub function > > > > > > + mov eax, ASM_PFX(SingleStepStubFunction) > > > > > > + mov dword [ecx + IA32_TSS.EIP], eax > > > > > > + > > > > > > + mov ecx, [ebp - 8] ; Get current > TSS base > > > > > > + mov eax, dword [ecx + IA32_TSS._ESP] ; Return > current stack > > > > top > > > > > > + mov esp, ebp > > > > > > + > > > > > > + ret > > > > > > + > > > > > > +global ASM_PFX(SingleStepStubFunction) > > > > > > +ASM_PFX(SingleStepStubFunction): > > > > > > +; > > > > > > +; we need clean TS bit in CR0 to execute > > > > > > +; x87 FPU/MMX/SSE/SSE2/SSE3/SSSE3/SSE4 instructions. > > > > > > +; > > > > > > + clts > > > > > > + iretd > > > > > > + > > > > > > +global ASM_PFX(AsmGetTssTemplateMap) > > > > > > +ASM_PFX(AsmGetTssTemplateMap): > > > > > > + push ebp ; C prolog > > > > > > + mov ebp, esp > > > > > > + pushad > > > > > > + > > > > > > + mov ebx, dword [ebp + 0x8] > > > > > > + mov dword [ebx], ASM_PFX(ExceptionTaskSwtichEntry0) > > > > > > + mov dword [ebx + 0x4], (AsmExceptionEntryEnd - > > > > AsmExceptionEntryBegin) > > > > > > / 32 > > > > > > + mov dword [ebx + 0x8], 0 > > > > > > + > > > > > > + popad > > > > > > + pop ebp > > > > > > + ret > > > > > > + > > > > > > diff --git > > > > > > > > > > > > a/UefiCpuPkg/Library/CpuExceptionHandlerLib/PeiCpuExceptionHandlerLib.i= nf > > > > > > > > > > > > > b/UefiCpuPkg/Library/CpuExceptionHandlerLib/PeiCpuExceptionHandlerLib.inf > > > > > > index 75443288a9..4c0d435136 100644 > > > > > > --- > > > > > > > > > > > > a/UefiCpuPkg/Library/CpuExceptionHandlerLib/PeiCpuExceptionHandlerLib.i= nf > > > > > > +++ > > > > > > > > > > > > > b/UefiCpuPkg/Library/CpuExceptionHandlerLib/PeiCpuExceptionHandlerLib.inf > > > > > > @@ -30,6 +30,7 @@ > > > > > > [Sources.Ia32] > > > > > > Ia32/ExceptionHandlerAsm.asm > > > > > > Ia32/ExceptionHandlerAsm.nasm > > > > > > + Ia32/ExceptionTssEntryAsm.nasm > > > > > > Ia32/ExceptionHandlerAsm.S > > > > > > Ia32/ArchExceptionHandler.c > > > > > > Ia32/ArchInterruptDefs.h > > > > > > diff --git > > > > > > > > > > > > > > > > > > > > > a/UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuExceptionHandlerLib.= i > > > > > > nf > > > > > > > > > > > > > > > > > > > > > b/UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuExceptionHandlerLib.= i > > > > > > nf > > > > > > index d70a99c100..e5c03c16c9 100644 > > > > > > --- > > > > > > > > > > > > > > > > > > > > > a/UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuExceptionHandlerLib.= i > > > > > > nf > > > > > > +++ > > > > > > > > > > > > > > > > > > > > > b/UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuExceptionHandlerLib.= i > > > > > > nf > > > > > > @@ -30,6 +30,7 @@ > > > > > > [Sources.Ia32] > > > > > > Ia32/ExceptionHandlerAsm.asm > > > > > > Ia32/ExceptionHandlerAsm.nasm > > > > > > + Ia32/ExceptionTssEntryAsm.nasm > > > > > > Ia32/ExceptionHandlerAsm.S > > > > > > Ia32/ArchExceptionHandler.c > > > > > > Ia32/ArchInterruptDefs.h > > > > > > diff --git > > > > > > > > > > > > > > > > > > > > > a/UefiCpuPkg/Library/CpuExceptionHandlerLib/SmmCpuExceptionHandlerLib.in > f > > > > > > > > > > > > > > > > > > > > > b/UefiCpuPkg/Library/CpuExceptionHandlerLib/SmmCpuExceptionHandlerLib.in > f > > > > > > index 634ffcb21d..56b875b7c8 100644 > > > > > > --- > > > > > > > > > > > > > > > > > > > > > a/UefiCpuPkg/Library/CpuExceptionHandlerLib/SmmCpuExceptionHandlerLib.in > f > > > > > > +++ > > > > > > > > > > > > > > > > > > > > > b/UefiCpuPkg/Library/CpuExceptionHandlerLib/SmmCpuExceptionHandlerLib.in > f > > > > > > @@ -30,6 +30,7 @@ > > > > > > [Sources.Ia32] > > > > > > Ia32/ExceptionHandlerAsm.asm > > > > > > Ia32/ExceptionHandlerAsm.nasm > > > > > > + Ia32/ExceptionTssEntryAsm.nasm > > > > > > Ia32/ExceptionHandlerAsm.S > > > > > > Ia32/ArchExceptionHandler.c > > > > > > Ia32/ArchInterruptDefs.h > > > > > > diff --git > > > > > > > > > a/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.= c > > > > > > > > > b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.= c > > > > > > index 65f0cff680..214aafcc13 100644 > > > > > > --- > > > > > > > a/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c > > > > > > +++ > > > > > > > b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c > > > > > > @@ -112,6 +112,139 @@ ArchRestoreExceptionContext ( > > > > > > SystemContext.SystemContextX64->ExceptionData =3D > > > > > > ReservedVectors[ExceptionType].ExceptionData; > > > > > > } > > > > > > > > > > > > +/** > > > > > > + Setup separate stack for given exceptions. > > > > > > + > > > > > > + @param[in] StackSwitchData Pointer to data required for > setuping > > > > up > > > > > > + stack switch. > > > > > > + > > > > > > + @retval EFI_SUCCESS The exceptions have been > > > > successfully > > > > > > + initialized. > > > > > > + @retval EFI_INVALID_PARAMETER StackSwitchData contains > invalid > > > > > > content. > > > > > > + > > > > > > +**/ > > > > > > +EFI_STATUS > > > > > > +EFIAPI > > > > > > +ArchSetupExcpetionStack ( > > > > > > + IN EXCEPTION_STACK_SWITCH_DATA *StackSwitchData > > > > > > + ) > > > > > > +{ > > > > > > + IA32_DESCRIPTOR Gdtr; > > > > > > + IA32_DESCRIPTOR Idtr; > > > > > > + IA32_IDT_GATE_DESCRIPTOR *IdtTable; > > > > > > + IA32_TSS_DESCRIPTOR *TssDesc; > > > > > > + IA32_TASK_STATE_SEGMENT *Tss; > > > > > > + UINTN StackTop; > > > > > > + UINTN Index; > > > > > > + UINTN TssBase; > > > > > > + UINTN GdtSize; > > > > > > + > > > > > > + if (StackSwitchData =3D=3D NULL || > > > > > > + StackSwitchData->StackTop =3D=3D 0 || > > > > > > + StackSwitchData->StackSize =3D=3D 0 || > > > > > > + StackSwitchData->Exceptions =3D=3D NULL || > > > > > > + StackSwitchData->ExceptionNumber =3D=3D 0 || > > > > > > + StackSwitchData->GdtTable =3D=3D NULL || > > > > > > + StackSwitchData->IdtTable =3D=3D NULL || > > > > > > + StackSwitchData->TssDesc =3D=3D NULL || > > > > > > + StackSwitchData->Tss =3D=3D NULL) { > > > > > > + return EFI_INVALID_PARAMETER; > > > > > > + } > > > > > > + > > > > > > + // > > > > > > + // The caller is responsible for that the GDT table, no matt= er the > > existing > > > > > > + // one or newly allocated, has enough space to hold descript= ors for > > > > > exception > > > > > > + // task-state segments. > > > > > > + // > > > > > > + if (((UINTN)StackSwitchData->GdtTable & (IA32_GDT_ALIGNMENT > - > > > 1)) !=3D > > > > 0) > > > > > { > > > > > > + return EFI_INVALID_PARAMETER; > > > > > > + } > > > > > > + > > > > > > + if ((UINTN)StackSwitchData->TssDesc < (UINTN)(StackSwitchDat= a- > > > > > >GdtTable)) > > > > > > { > > > > > > + return EFI_INVALID_PARAMETER; > > > > > > + } > > > > > > + > > > > > > + if ((UINTN)StackSwitchData->TssDesc >=3D > > > > > > + ((UINTN)(StackSwitchData->GdtTable) + > > > > StackSwitchData->GdtSize)) > > > > > > { > > > > > > + return EFI_INVALID_PARAMETER; > > > > > > + } > > > > > > + > > > > > > + GdtSize =3D (UINTN)StackSwitchData->TssDesc - > > > > > > + (UINTN)(StackSwitchData->GdtTable) + > > > > > > + sizeof (IA32_TSS_DESCRIPTOR); > > > > > > + if (GdtSize > StackSwitchData->GdtSize) { > > > > > > + return EFI_INVALID_PARAMETER; > > > > > > + } > > > > > > + > > > > > > + // > > > > > > + // Initialize new GDT table and/or IDT table, if any > > > > > > + // > > > > > > + AsmReadIdtr (&Idtr); > > > > > > + AsmReadGdtr (&Gdtr); > > > > > > + if ((UINTN)StackSwitchData->GdtTable !=3D Gdtr.Base) { > > > > > > + CopyMem (StackSwitchData->GdtTable, (VOID *)Gdtr.Base, > Gdtr.Limit > > + > > > > 1); > > > > > > + Gdtr.Base =3D (UINTN)StackSwitchData->GdtTable; > > > > > > + Gdtr.Limit =3D (UINT16)GdtSize - 1; > > > > > > + } > > > > > > + > > > > > > + if ((UINTN)StackSwitchData->IdtTable !=3D Idtr.Base) { > > > > > > + Idtr.Base =3D (UINTN)StackSwitchData->IdtTable; > > > > > > + } > > > > > > + > > > > > > + // > > > > > > + // Fixup current task descriptor. Task-state segment for cur= rent task > > will > > > > > > + // be filled by processor during task switching. > > > > > > + // > > > > > > + TssDesc =3D StackSwitchData->TssDesc; > > > > > > + Tss =3D StackSwitchData->Tss; > > > > > > + > > > > > > + TssBase =3D (UINTN)Tss; > > > > > > + TssDesc->Bits.LimitLow =3D sizeof(IA32_TASK_STATE_SEGMENT)= - > 1; > > > > > > + TssDesc->Bits.BaseLow =3D (UINT16)TssBase; > > > > > > + TssDesc->Bits.BaseMidl =3D (UINT8)(TssBase >> 16); > > > > > > + TssDesc->Bits.Type =3D IA32_GDT_TYPE_TSS; > > > > > > + TssDesc->Bits.P =3D 1; > > > > > > + TssDesc->Bits.LimitHigh =3D 0; > > > > > > + TssDesc->Bits.BaseMidh =3D (UINT8)(TssBase >> 24); > > > > > > + TssDesc->Bits.BaseHigh =3D (UINT32)(TssBase >> 32); > > > > > > + > > > > > > + // > > > > > > + // Fixup exception task descriptor and task-state segment > > > > > > + // > > > > > > + StackTop =3D StackSwitchData->StackTop - CPU_STACK_ALIGNMENT= ; > > > > > > + StackTop =3D (UINTN)ALIGN_POINTER (StackTop, > > > > CPU_STACK_ALIGNMENT); > > > > > > + IdtTable =3D StackSwitchData->IdtTable; > > > > > > + for (Index =3D 0; Index < StackSwitchData->ExceptionNumber; > ++Index) { > > > > > > + // > > > > > > + // Fixup IST > > > > > > + // > > > > > > + Tss->IST[Index] =3D StackTop; > > > > > > + StackTop -=3D StackSwitchData->StackSize; > > > > > > + > > > > > > + // > > > > > > + // Set the IST field to enable corresponding IST > > > > > > + // > > > > > > + IdtTable[StackSwitchData->Exceptions[Index]].Bits.Reserved= _0 =3D > > > > > > (UINT8)(Index + 1); > > > > > > + } > > > > > > + > > > > > > + // > > > > > > + // Publish GDT > > > > > > + // > > > > > > + AsmWriteGdtr (&Gdtr); > > > > > > + > > > > > > + // > > > > > > + // Load current task > > > > > > + // > > > > > > + AsmWriteTr ((UINT16)((UINTN)StackSwitchData->TssDesc - > Gdtr.Base)); > > > > > > + > > > > > > + // > > > > > > + // Publish IDT > > > > > > + // > > > > > > + AsmWriteIdtr (&Idtr); > > > > > > + > > > > > > + return EFI_SUCCESS; > > > > > > +} > > > > > > + > > > > > > /** > > > > > > Display CPU information. > > > > > > > > > > > > diff --git > > > > > > > a/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchInterruptDefs.h > > > > > > > b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchInterruptDefs.h > > > > > > index 906480134a..c88be46286 100644 > > > > > > --- > > > a/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchInterruptDefs.h > > > > > > +++ > > > b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchInterruptDefs.h > > > > > > @@ -43,4 +43,7 @@ typedef struct { > > > > > > UINT8 > HookAfterStubHeaderCode[HOOKAFTER_STUB_SIZE]; > > > > > > } RESERVED_VECTORS_DATA; > > > > > > > > > > > > +#define CPU_TSS_DESC_SIZE sizeof (IA32_TSS_DESCRIPTOR) > > > > > > +#define CPU_TSS_SIZE sizeof (IA32_TASK_STATE_SEGMENT) > > > > > > + > > > > > > #endif > > > > > > -- > > > > > > 2.14.1.windows.1 > > > > _______________________________________________ > > edk2-devel mailing list > > edk2-devel@lists.01.org > > https://lists.01.org/mailman/listinfo/edk2-devel