* Re: 回复: 回复: [edk2-devel] [PATCH v2] UefiCpuPkg/MpInitLib: Add check for CR3/GDT/IDT. [not found] <163188258B195C29.8972@groups.io> @ 2020-09-04 11:17 ` Fan Jeff 2020-09-04 11:48 ` Yao, Jiewen 0 siblings, 1 reply; 6+ messages in thread From: Fan Jeff @ 2020-09-04 11:17 UTC (permalink / raw) To: vanjeff_919, jiewen.yao, devel, lersek, eric.dong, ray.ni; +Cc: Lou, Yun [-- Attachment #1: Type: text/html, Size: 23962 bytes --] ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: 回复: 回复: [edk2-devel] [PATCH v2] UefiCpuPkg/MpInitLib: Add check for CR3/GDT/IDT. 2020-09-04 11:17 ` 回复: 回复: [edk2-devel] [PATCH v2] UefiCpuPkg/MpInitLib: Add check for CR3/GDT/IDT Fan Jeff @ 2020-09-04 11:48 ` Yao, Jiewen 2020-09-04 12:08 ` Laszlo Ersek 0 siblings, 1 reply; 6+ messages in thread From: Yao, Jiewen @ 2020-09-04 11:48 UTC (permalink / raw) To: devel@edk2.groups.io, vanjeff_919@hotmail.com, lersek@redhat.com, Dong, Eric, Ni, Ray Cc: Lou, Yun [-- Attachment #1: Type: text/plain, Size: 12161 bytes --] Jeff I think the CR3 should be managed by the CPU driver. And it should NOT be changed by other module during post phase without a clear contract. Since CPU driver managed the value (or DebugAgent managing it under contract), it should *always* be valid. I don’t see the value to check the value managed by the module itself, and return EFI_UNSUPPORTED. If CPU driver sets CR3 above 4G and sync it to AP, then it is a bug. We should fix the CPU driver or MP Library to *make it always work*. There are multiple options. For example, the CPU driver can always set a dedicate CR3/GDT/IDT for AP (below 4G). Then no matter BSP state is changed, we can always wake up AP correctly with a pre-defined state. Syncing BSP state to AP just an implementation choice, it is not absolute necessary. In a system boot, the ability to wake up AP is very important. Especially when the BIOS transfers the state to OS, the BSP need wake up AP to put AP in a good state, such as protected mode with paging disabled. Without doing that, we may get random system crash during boot. If we really really want to do some check to ensure AP state is good, I would rather to prepare a dedicated known good state for AP and always use this known good state for AP wakeup. Giving up and returning UNSUPPORTED is definitely NOT my preference. Thank you Yao Jiewen From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Fan Jeff Sent: Friday, September 4, 2020 7:17 PM To: vanjeff_919@hotmail.com; Yao, Jiewen <jiewen.yao@intel.com>; devel@edk2.groups.io; lersek@redhat.com; Dong, Eric <eric.dong@intel.com>; Ni, Ray <ray.ni@intel.com> Cc: Lou, Yun <yun.lou@intel.com> Subject: Re: 回复: 回复: [edk2-devel] [PATCH v2] UefiCpuPkg/MpInitLib: Add check for CR3/GDT/IDT. Jiewen, Maybe my word "valid during post phase" confused you. My point is that those values maybe changed during post phase. So, if their spaces above 4GB are not legal, i agree not to do anything. If legal, then we need to something. Jeff 在 Fan Jeff <vanjeff_919@hotmail.com<mailto:vanjeff_919@hotmail.com>>,2020年9月4日 下午4:44写道: Jiewen, I don’t think AP need to validate everyting. BSP should make sure CR3/GDT/IDT corrently firstly. Othersize, everything does not make sense. For CR3 case, if we assume CR3 above 4GB space is legal for BSP (If there are any limitation on it, please corrent me) but the current CPU AP wakeup method does not allow CR3 above 4GB space, this maybe the CPU driver’s bug or implementation limitation. The key is that CR3 above 4GB is legal or not. If we think this is bug, we need to enhance CPU driver to fix it. If we think this is one limiation, we need to validate the CR3 value and tell the caller. Jeff 发件人: Yao, Jiewen<mailto:jiewen.yao@intel.com> 发送时间: 2020年9月4日 16:07 收件人: devel@edk2.groups.io<mailto:devel@edk2.groups.io>; vanjeff_919@hotmail.com<mailto:vanjeff_919@hotmail.com>; Laszlo Ersek<mailto:lersek@redhat.com>; Dong, Eric<mailto:eric.dong@intel.com>; Ni, Ray<mailto:ray.ni@intel.com> 抄送: Lou, Yun<mailto:yun.lou@intel.com> 主题: RE: 回复: [edk2-devel] [PATCH v2] UefiCpuPkg/MpInitLib: Add check for CR3/GDT/IDT. When we say “validate”, we need get clear on what is the contract between caller and callee, and what is the expectation of the validation. For example, in this case, the validation is limited to 4G or not 4G. Why? This function does not verify following, why? 1. if the GDT table is valid. 2. if the IDT table is valid 3. if the exception handler is valid 4. if the timer handler still works 5. if the page table is valid 6. if the page table is 1:1 mapping 7. if the page table still enforce the expected protection, such as RO, NX 8. …… If an application creates a crazy state, CpuDxe may pass the validation with below 4G page table, but still fail to wake up APs. If it is the app’s responsibility to ensure the system in good state, the validation is unnecessary. If it is the CpuDxe’s responsibility to ensure the system in good state, the validation is insufficient. I think we should wait. I am working with Eric to collect the requirement on why test case is designed in this way. DebugAgentDxe is a good case. It is for debug purpose. I believe there must be contract between CPU driver and DebugAgentDxe that which status DebugAgentDxe may modify and which state DebugAgentDxe may not. It is DebugAgentDxe’s responsibility to ensure the new system state is correct and compatible with the CPU driver. With the contract, I don’t think CPU driver need validate the system state changed by DebugAgentDxe. If DebugAgentDxe put system in a wrong state, CPUDriver has no chance to run. From: devel@edk2.groups.io<mailto:devel@edk2.groups.io> <devel@edk2.groups.io<mailto:devel@edk2.groups.io>> On Behalf Of Fan Jeff Sent: Friday, September 4, 2020 3:32 PM To: Laszlo Ersek <lersek@redhat.com<mailto:lersek@redhat.com>>; devel@edk2.groups.io<mailto:devel@edk2.groups.io>; Dong, Eric <eric.dong@intel.com<mailto:eric.dong@intel.com>>; Ni, Ray <ray.ni@intel.com<mailto:ray.ni@intel.com>> Cc: Lou, Yun <yun.lou@intel.com<mailto:yun.lou@intel.com>> Subject: 回复: 回复: [edk2-devel] [PATCH v2] UefiCpuPkg/MpInitLib: Add check for CR3/GDT/IDT. Laszlo, Why sync the BSP’s CR3/GDT/IDT values for AP when AP wakes up instead of using old cached BSP’s CR3/GDT/IDT values when CPU driver initiallly dispatched is that we CANNOT assume original values are still valid during POST phase. On this senario, BSP’s CR3/GDT/IDT are just like input parameters for one function. Validating them are necessary. For example, DebugAgentDxe driver may be loaded in UEFI shell to setup source level debugging enviroment of EDKII debugger tools. It may setup new IDT space. Jeff 发件人: Laszlo Ersek<mailto:lersek@redhat.com> 发送时间: 2020年9月4日 14:58 收件人: Fan Jeff<mailto:vanjeff_919@hotmail.com>; devel@edk2.groups.io<mailto:devel@edk2.groups.io>; eric.dong@intel.com<mailto:eric.dong@intel.com>; Ni, Ray<mailto:ray.ni@intel.com> 抄送: Lou, Yun<mailto:yun.lou@intel.com> 主题: Re: 回复: [edk2-devel] [PATCH v2] UefiCpuPkg/MpInitLib: Add check for CR3/GDT/IDT. On 09/04/20 04:18, Fan Jeff wrote: > Laszlo & Eric, > > Introducing one new PCD to handle such rare test case is too heavy. I think We could do validating CR3/GDT/IDT space < 4GB address always in MpInitLib. I disagree. What the UEFI application does (interfere with GDT / IDT / CR3 placement) is invalid. It changes system properties under the feet of platform DXE drivers. UEFI applications are supposed to be written against public protocols and services in the UEFI spec (and maybe in the PI spec). If this application is a test application that purposely massages low-level system properties, that's fine; but then, if we change core edk2 components to be somewhat compatible with this application, then we should make sure that platforms that do not care about this specific use case do not suffer a performance hit or a code complexity hit. What I could accept, under your proposal, is the following: add three ASSERT()s to FillExchangeInfoData(), where we fetch the IDTR / GDTR / CR3 anyway. This would be fine because it only expresses existing assumptions / requirements. However, my understanding is that this would not solve Eric's problem. The system would hang -- in DEBUG / NOOPT builds -- or crash -- in a RELEASE build -- just the same as before. Now, *if* FillExchangeInfoData() is currently *wrong* to have these 32-bit assumptions, because edk2 modules themselves can break those assumptions (without the custom UEFI application), then we have a more serious problem. But for that problem, just "checking and rejecting" is not a sufficient solution, regardless of how and where we check and reject. Thanks Laszlo > > Jeff > > 发件人: Dong, Eric<mailto:eric.dong@intel.com> > 发送时间: 2020年9月4日 10:01 > 收件人: Ni, Ray<mailto:ray.ni@intel.com>; devel@edk2.groups.io<mailto:devel@edk2.groups.io<mailto:devel@edk2.groups.io%3cmailto:devel@edk2.groups.io>>; lersek@redhat.com<mailto:lersek@redhat.com> > 抄送: Lou, Yun<mailto:yun.lou@intel.com> > 主题: Re: [edk2-devel] [PATCH v2] UefiCpuPkg/MpInitLib: Add check for CR3/GDT/IDT. > > I guess Laszlo think this check is not always needed, just used for this special shell application case. He wants to use default FALSE to always ignore this check and make code logic clear. > > Thanks, > Eric > > From: Ni, Ray <ray.ni@intel.com<mailto:ray.ni@intel.com>> > Sent: Friday, September 4, 2020 9:34 AM > To: devel@edk2.groups.io<mailto:devel@edk2.groups.io>; lersek@redhat.com<mailto:lersek@redhat.com>; Dong, Eric <eric.dong@intel.com<mailto:eric.dong@intel.com>> > Cc: Lou, Yun <yun.lou@intel.com<mailto:yun.lou@intel.com>> > Subject: Re: [edk2-devel] [PATCH v2] UefiCpuPkg/MpInitLib: Add check for CR3/GDT/IDT. > > Why do we need a new PCD to control such check? Under what circumstance the PCD is false? > We may need to move such check out of MpLib.c. Because when bps runs at 32bit mode, AP doesn’t need to switch to long mode, such check is not needed and also always passes. > > We should not assume PEI runs at 32 bit mode. > > > 发件人: devel@edk2.groups.io<mailto:devel@edk2.groups.io<mailto:devel@edk2.groups.io%3cmailto:devel@edk2.groups.io>> <devel@edk2.groups.io<mailto:devel@edk2.groups.io<mailto:devel@edk2.groups.io%3cmailto:devel@edk2.groups.io>>> 代表 Laszlo Ersek <lersek@redhat.com<mailto:lersek@redhat.com<mailto:lersek@redhat.com%3cmailto:lersek@redhat.com>>> > 发送时间: Friday, September 4, 2020 3:55:47 AM > 收件人: Dong, Eric <eric.dong@intel.com<mailto:eric.dong@intel.com<mailto:eric.dong@intel.com%3cmailto:eric.dong@intel.com>>>; devel@edk2.groups.io<mailto:devel@edk2.groups.io<mailto:devel@edk2.groups.io%3cmailto:devel@edk2.groups.io>> <devel@edk2.groups.io<mailto:devel@edk2.groups.io<mailto:devel@edk2.groups.io%3cmailto:devel@edk2.groups.io>>> > 抄送: Ni, Ray <ray.ni@intel.com<mailto:ray.ni@intel.com<mailto:ray.ni@intel.com%3cmailto:ray.ni@intel.com>>> > 主题: Re: [edk2-devel] [PATCH v2] UefiCpuPkg/MpInitLib: Add check for CR3/GDT/IDT. > > On 09/03/20 21:00, Laszlo Ersek wrote: > >> (10) More importantly, ValidCR3GdtIdtCheck() should not be called in the >> Worker functions for StartupAllAPs, StartupThisAP, SwitchBSP, and >> EnableDisableAP, in "UefiCpuPkg/Library/MpInitLib/MpLib.c". >> >> Instead, the calls should be made in the DXE instance of the library >> ("UefiCpuPkg/Library/MpInitLib/DxeMpLib.c"), at the very top of the >> functions: >> >> - MpInitLibStartupAllAPs >> - MpInitLibStartupThisAP >> - MpInitLibSwitchBSP >> - MpInitLibEnableDisableAP >> >> Here's why: >> >> (a) The symptom does not affect the PEI phase -- by the time the UEFI >> application is executed, the PEI phase has ended; there's no need to >> modify the PEI instance of the library. >> >> (b) The currently proposed failure exits are too late. For example, in >> the SwitchBSPWorker() function, by the time we exit, we have called >> DisableApicTimerInterrupt(), SaveAndDisableInterrupts(), and >> DisableLvtInterrupts() -- and the error path does not restore the >> original environment. >> >> (c) According to the PI spec (v1.7), the StartupAllAPs(), >> StartupThisAP(), SwitchBSP(), EnableDisableAP() member functions of >> EFI_MP_SERVICES_PROTOCOL may only be called on the (current) BSP. >> Because of this, it is OK to call ValidCR3GdtIdtCheck() as the very >> first action in the above-listed DxeMpLib functions. >> >> (Assuming the protocol members are called from an AP, and consequently >> we check CR3 / GDTR / IDTR on the AP (and not on the BSP), that's the >> *caller's* fault, per spec!) > > This means we can move the ValidCr3GdtIdtCheck() function to > "DxeMpLib.c", and it is not necessary to modify "MpLib.h". > > Thanks > Laszlo > > [-- Attachment #2: Type: text/html, Size: 30471 bytes --] ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: 回复: 回复: [edk2-devel] [PATCH v2] UefiCpuPkg/MpInitLib: Add check for CR3/GDT/IDT. 2020-09-04 11:48 ` Yao, Jiewen @ 2020-09-04 12:08 ` Laszlo Ersek 0 siblings, 0 replies; 6+ messages in thread From: Laszlo Ersek @ 2020-09-04 12:08 UTC (permalink / raw) To: Yao, Jiewen, devel@edk2.groups.io, vanjeff_919@hotmail.com, Dong, Eric, Ni, Ray Cc: Lou, Yun On 09/04/20 13:48, Yao, Jiewen wrote: > Jeff > I think the CR3 should be managed by the CPU driver. And it should NOT be changed by other module during post phase without a clear contract. > > Since CPU driver managed the value (or DebugAgent managing it under contract), it should *always* be valid. I don’t see the value to check the value managed by the module itself, and return EFI_UNSUPPORTED. > > If CPU driver sets CR3 above 4G and sync it to AP, then it is a bug. > We should fix the CPU driver or MP Library to *make it always work*. > > There are multiple options. For example, the CPU driver can always set a dedicate CR3/GDT/IDT for AP (below 4G). Then no matter BSP state is changed, we can always wake up AP correctly with a pre-defined state. Syncing BSP state to AP just an implementation choice, it is not absolute necessary. > > In a system boot, the ability to wake up AP is very important. Especially when the BIOS transfers the state to OS, the BSP need wake up AP to put AP in a good state, such as protected mode with paging disabled. Without doing that, we may get random system crash during boot. > > If we really really want to do some check to ensure AP state is good, I would rather to prepare a dedicated known good state for AP and always use this known good state for AP wakeup. > Giving up and returning UNSUPPORTED is definitely NOT my preference. Should we audit the various AllocatePageTableMemory() function implementations in edk2? Or is there more stuff we need to look at? Thanks Laszlo ^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH v2] UefiCpuPkg/MpInitLib: Add check for CR3/GDT/IDT. @ 2020-09-03 15:11 Dong, Eric 2020-09-03 19:00 ` Laszlo Ersek 0 siblings, 1 reply; 6+ messages in thread From: Dong, Eric @ 2020-09-03 15:11 UTC (permalink / raw) To: devel; +Cc: Ray Ni, Laszlo Ersek REF: https://bugzilla.tianocore.org/show_bug.cgi?id=2954 AP needs to run from real mode to 32bit mode to LONG mode. Page table (pointed by CR3) and GDT are necessary to set up to correct value when CPU execution mode is switched to LONG mode. AP uses the same location page table (CR3) and GDT as what BSP uses. But when the page table or GDT is above 4GB, it's impossible for CPU to use because GDTR.base and CR3 are 32bits before switching to LONG mode. This patch adds check for the CR3, GDT.Base and IDT.Base to not above 32 bits restriction. Change-Id: I231180f45d9f542641082c57d001e38e3f6759d5 Signed-off-by: Eric Dong <eric.dong@intel.com> Cc: Ray Ni <ray.ni@intel.com> Cc: Laszlo Ersek <lersek@redhat.com> --- V2: Change the check point. Just in the different caller to make the logic clear. V1 patch add check just before the use of the code. It make the logic complicated. UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf | 1 + UefiCpuPkg/Library/MpInitLib/DxeMpLib.c | 9 +++ UefiCpuPkg/Library/MpInitLib/MpLib.c | 76 +++++++++++++++++++ UefiCpuPkg/Library/MpInitLib/MpLib.h | 12 +++ UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf | 1 + UefiCpuPkg/UefiCpuPkg.dec | 4 + 6 files changed, 103 insertions(+) diff --git a/UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf b/UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf index 1771575c69..20851f251a 100644 --- a/UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf +++ b/UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf @@ -76,3 +76,4 @@ gUefiCpuPkgTokenSpaceGuid.PcdSevEsWorkAreaBase ## SOMETIMES_CONSUMES gEfiMdeModulePkgTokenSpaceGuid.PcdCpuStackGuard ## CONSUMES gEfiMdeModulePkgTokenSpaceGuid.PcdGhcbBase ## CONSUMES + gUefiCpuPkgTokenSpaceGuid.PcdEnableCpuApCr3GdtIdtCheck ## CONSUMES \ No newline at end of file diff --git a/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c b/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c index 2c00d72dde..f598372c4d 100644 --- a/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c +++ b/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c @@ -394,6 +394,15 @@ MpInitChangeApLoopCallback ( { CPU_MP_DATA *CpuMpData; + // + // Check the CR3/GDT/IDT before waking up AP. + // If the check return fail, it will block later + // OS boot, so halt the system here. + // + if (!ValidCR3GdtIdtCheck()) { + CpuDeadLoop (); + } + CpuMpData = GetCpuMpData (); CpuMpData->PmCodeSegment = GetProtectedModeCS (); CpuMpData->Pm16CodeSegment = GetProtectedMode16CS (); diff --git a/UefiCpuPkg/Library/MpInitLib/MpLib.c b/UefiCpuPkg/Library/MpInitLib/MpLib.c index 07426274f6..69a0372df7 100644 --- a/UefiCpuPkg/Library/MpInitLib/MpLib.c +++ b/UefiCpuPkg/Library/MpInitLib/MpLib.c @@ -1909,6 +1909,54 @@ CheckAllAPs ( return EFI_NOT_READY; } +/** + Check whether CR3/GDT/IDT value valid for AP. + + @retval TRUE Pass the check. + @retval FALSE Fail the check. + +**/ +BOOLEAN +ValidCR3GdtIdtCheck ( + VOID + ) +{ + IA32_DESCRIPTOR Gdtr; + IA32_DESCRIPTOR Idtr; + + if (!PcdGetBool (PcdEnableCpuApCr3GdtIdtCheck)) { + return TRUE; + } + + // + // AP needs to run from real mode to 32bit mode to LONG mode. Page table + // (pointed by CR3) and GDT are necessary to set up to correct value when + // CPU execution mode is switched to LONG mode. IDT also necessary if the + // exception happened. + // AP uses the same location page table (CR3) and GDT/IDT as what BSP uses. + // But when the page table or GDT is above 4GB, it's impossible for CPU + // to use because GDTR.base and CR3 are 32bits before switching to LONG + // mode. + // Here add check for the CR3, GDT.Base and range, IDT.Base and range are + // not above 32 bits limitation. + // + if (AsmReadCr3 () >= BASE_4GB) { + return FALSE; + } + + AsmReadGdtr ((IA32_DESCRIPTOR *) &Gdtr); + if ((Gdtr.Base >= BASE_4GB) || (Gdtr.Base + Gdtr.Limit >= BASE_4GB)) { + return FALSE; + } + + AsmReadIdtr ((IA32_DESCRIPTOR *) &Idtr); + if ((Idtr.Base >= BASE_4GB) || (Idtr.Base + Idtr.Limit >= BASE_4GB)) { + return FALSE; + } + + return TRUE; +} + /** MP Initialize Library initialization. @@ -2318,6 +2366,13 @@ SwitchBSPWorker ( return EFI_NOT_READY; } + // + // Check whether CR3/GDT/IDT valid for AP. + // + if (!ValidCR3GdtIdtCheck()) { + return EFI_INVALID_PARAMETER; + } + CpuMpData->BSPInfo.State = CPU_SWITCH_STATE_IDLE; CpuMpData->APInfo.State = CPU_SWITCH_STATE_IDLE; CpuMpData->SwitchBspFlag = TRUE; @@ -2420,6 +2475,13 @@ EnableDisableApWorker ( return EFI_NOT_FOUND; } + // + // Check whether CR3/GDT/IDT valid for AP. + // + if (!ValidCR3GdtIdtCheck()) { + return EFI_INVALID_PARAMETER; + } + if (!EnableAP) { SetApState (&CpuMpData->CpuData[ProcessorNumber], CpuStateDisabled); } else { @@ -2607,6 +2669,13 @@ StartupAllCPUsWorker ( return EFI_DEVICE_ERROR; } + // + // Check whether CR3/GDT/IDT valid for AP. + // + if (!ValidCR3GdtIdtCheck()) { + return EFI_INVALID_PARAMETER; + } + // // Update AP state // @@ -2772,6 +2841,13 @@ StartupThisAPWorker ( return EFI_INVALID_PARAMETER; } + // + // Check whether CR3/GDT/IDT valid for AP. + // + if (!ValidCR3GdtIdtCheck()) { + return EFI_INVALID_PARAMETER; + } + // // Update AP state // diff --git a/UefiCpuPkg/Library/MpInitLib/MpLib.h b/UefiCpuPkg/Library/MpInitLib/MpLib.h index 02652eaae1..4ac5cb51e3 100644 --- a/UefiCpuPkg/Library/MpInitLib/MpLib.h +++ b/UefiCpuPkg/Library/MpInitLib/MpLib.h @@ -740,5 +740,17 @@ PlatformShadowMicrocode ( IN OUT CPU_MP_DATA *CpuMpData ); +/** + Check whether CR3/GDT/IDT value valid for AP. + + @retval TRUE Pass the check. + @retval FALSE Fail the check. + +**/ +BOOLEAN +ValidCR3GdtIdtCheck ( + VOID + ); + #endif diff --git a/UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf b/UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf index 34abf25d43..0ca86fcdaa 100644 --- a/UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf +++ b/UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf @@ -65,6 +65,7 @@ gUefiCpuPkgTokenSpaceGuid.PcdSevEsIsEnabled ## CONSUMES gUefiCpuPkgTokenSpaceGuid.PcdSevEsWorkAreaBase ## SOMETIMES_CONSUMES gEfiMdeModulePkgTokenSpaceGuid.PcdGhcbBase ## CONSUMES + gUefiCpuPkgTokenSpaceGuid.PcdEnableCpuApCr3GdtIdtCheck ## CONSUMES [Ppis] gEdkiiPeiShadowMicrocodePpiGuid ## SOMETIMES_CONSUMES diff --git a/UefiCpuPkg/UefiCpuPkg.dec b/UefiCpuPkg/UefiCpuPkg.dec index d83c084467..467ec5e001 100644 --- a/UefiCpuPkg/UefiCpuPkg.dec +++ b/UefiCpuPkg/UefiCpuPkg.dec @@ -187,6 +187,10 @@ # @Prompt Configure stack size for Application Processor (AP) gUefiCpuPkgTokenSpaceGuid.PcdCpuApStackSize|0x8000|UINT32|0x00000003 + ## This value specifies whether need to check the CR3/GDT/IDT value for AP. + # @Prompt Whether need to check the CR3/GDT/IDT value for AP + gUefiCpuPkgTokenSpaceGuid.PcdEnableCpuApCr3GdtIdtCheck|FALSE|BOOLEAN|0x30000044 + ## Specifies stack size in the temporary RAM. 0 means half of TemporaryRamSize. # @Prompt Stack size in the temporary RAM. gUefiCpuPkgTokenSpaceGuid.PcdPeiTemporaryRamStackSize|0|UINT32|0x10001003 -- 2.23.0.windows.1 ^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH v2] UefiCpuPkg/MpInitLib: Add check for CR3/GDT/IDT. 2020-09-03 15:11 Dong, Eric @ 2020-09-03 19:00 ` Laszlo Ersek 2020-09-03 19:55 ` Laszlo Ersek 0 siblings, 1 reply; 6+ messages in thread From: Laszlo Ersek @ 2020-09-03 19:00 UTC (permalink / raw) To: Eric Dong, devel; +Cc: Ray Ni On 09/03/20 17:11, Eric Dong wrote: > REF: https://bugzilla.tianocore.org/show_bug.cgi?id=2954 > > AP needs to run from real mode to 32bit mode to LONG mode. Page table > (pointed by CR3) and GDT are necessary to set up to correct value when > CPU execution mode is switched to LONG mode. > AP uses the same location page table (CR3) and GDT as what BSP uses. > But when the page table or GDT is above 4GB, it's impossible for CPU > to use because GDTR.base and CR3 are 32bits before switching to LONG > mode. > This patch adds check for the CR3, GDT.Base and IDT.Base to not above > 32 bits restriction. > > Change-Id: I231180f45d9f542641082c57d001e38e3f6759d5 (1) Please drop the Change-Id line. (2) We should document that the motivation for this patch is a special UEFI shell application that changes the GDT / CR3 to above 4GB. Currently, neither the bugzilla, nor the commit message, nor the PCD documentation in the DEC file explains this. So one is left wondering if and why they should change the PCD to TRUE on their platform. Please append the following two paragraphs to the commit message: """ The check is avoided -- assumed successful -- if the new PcdEnableCpuApCr3GdtIdtCheck is FALSE (which is the default). The reason is that the 32-bit requirement is always ensured by edk2 itself; the requirement is only possibly invalidated by a particular UEFI shell application that manually moves the GDT/IDT/CR3 above 4GB. Platforms that don't intend to be compatible with such UEFI applications need not set the PCD to TRUE. If the PCD is TRUE and the check fails, then the StartupAllAPs(), StartupThisAP(), SwitchBSP() and EnableDisableAP() MP service APIs are rejected at once. Reporting an error immediately is more graceful than hanging when the APs attempt to switch to long mode. """ > Signed-off-by: Eric Dong <eric.dong@intel.com> > Cc: Ray Ni <ray.ni@intel.com> > Cc: Laszlo Ersek <lersek@redhat.com> > --- > > V2: > Change the check point. Just in the different caller to make the logic > clear. V1 patch add check just before the use of the code. It make the > logic complicated. > > UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf | 1 + > UefiCpuPkg/Library/MpInitLib/DxeMpLib.c | 9 +++ > UefiCpuPkg/Library/MpInitLib/MpLib.c | 76 +++++++++++++++++++ > UefiCpuPkg/Library/MpInitLib/MpLib.h | 12 +++ > UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf | 1 + > UefiCpuPkg/UefiCpuPkg.dec | 4 + > 6 files changed, 103 insertions(+) > > diff --git a/UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf b/UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf > index 1771575c69..20851f251a 100644 > --- a/UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf > +++ b/UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf > @@ -76,3 +76,4 @@ > gUefiCpuPkgTokenSpaceGuid.PcdSevEsWorkAreaBase ## SOMETIMES_CONSUMES > gEfiMdeModulePkgTokenSpaceGuid.PcdCpuStackGuard ## CONSUMES > gEfiMdeModulePkgTokenSpaceGuid.PcdGhcbBase ## CONSUMES > + gUefiCpuPkgTokenSpaceGuid.PcdEnableCpuApCr3GdtIdtCheck ## CONSUMES > \ No newline at end of file (3) Can you insert this new line just after "gUefiCpuPkgTokenSpaceGuid.PcdSevEsWorkAreaBase" please? In order to keep the "gUefiCpuPkgTokenSpaceGuid" PCDs grouped together. > diff --git a/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c b/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c > index 2c00d72dde..f598372c4d 100644 > --- a/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c > +++ b/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c > @@ -394,6 +394,15 @@ MpInitChangeApLoopCallback ( > { > CPU_MP_DATA *CpuMpData; > > + // > + // Check the CR3/GDT/IDT before waking up AP. > + // If the check return fail, it will block later > + // OS boot, so halt the system here. > + // > + if (!ValidCR3GdtIdtCheck()) { (4) Missing space character after "ValidCR3GdtIdtCheck". (Applies to all the other call sites as well.) > + CpuDeadLoop (); > + } > + > CpuMpData = GetCpuMpData (); > CpuMpData->PmCodeSegment = GetProtectedModeCS (); > CpuMpData->Pm16CodeSegment = GetProtectedMode16CS (); > diff --git a/UefiCpuPkg/Library/MpInitLib/MpLib.c b/UefiCpuPkg/Library/MpInitLib/MpLib.c > index 07426274f6..69a0372df7 100644 > --- a/UefiCpuPkg/Library/MpInitLib/MpLib.c > +++ b/UefiCpuPkg/Library/MpInitLib/MpLib.c > @@ -1909,6 +1909,54 @@ CheckAllAPs ( > return EFI_NOT_READY; > } > > +/** > + Check whether CR3/GDT/IDT value valid for AP. > + > + @retval TRUE Pass the check. > + @retval FALSE Fail the check. > + > +**/ > +BOOLEAN > +ValidCR3GdtIdtCheck ( > + VOID > + ) > +{ > + IA32_DESCRIPTOR Gdtr; > + IA32_DESCRIPTOR Idtr; > + > + if (!PcdGetBool (PcdEnableCpuApCr3GdtIdtCheck)) { > + return TRUE; > + } > + > + // > + // AP needs to run from real mode to 32bit mode to LONG mode. Page table > + // (pointed by CR3) and GDT are necessary to set up to correct value when > + // CPU execution mode is switched to LONG mode. IDT also necessary if the > + // exception happened. > + // AP uses the same location page table (CR3) and GDT/IDT as what BSP uses. > + // But when the page table or GDT is above 4GB, it's impossible for CPU > + // to use because GDTR.base and CR3 are 32bits before switching to LONG > + // mode. > + // Here add check for the CR3, GDT.Base and range, IDT.Base and range are > + // not above 32 bits limitation. > + // > + if (AsmReadCr3 () >= BASE_4GB) { > + return FALSE; > + } > + > + AsmReadGdtr ((IA32_DESCRIPTOR *) &Gdtr); (5) The cast is superfluous, please remove it. According to <BaseLib.h>, AsmReadGdtr() takes the following parameter: OUT IA32_DESCRIPTOR *Gdtr > + if ((Gdtr.Base >= BASE_4GB) || (Gdtr.Base + Gdtr.Limit >= BASE_4GB)) { > + return FALSE; > + } I agree that both checks (even the second one) should use ">=", given that Limit is an inclusive boundary. My understanding is that we don't have to worry about any UINTN overflow in the addition here, as Base and Limit come from the "live" GDTR. (6) So we could even eliminate the first expression, and only do: if (Gdtr.Base + Gdtr.Limit >= BASE_4GB) { return FALSE; } Because, given that we do not expect any overflows here, if this (2nd) condition is FALSE, then the 1st condition must be FALSE too. I don't insist on this simplification. If you also like the simplification, then please - update the commit message - update the code comment above because we will no longer check Base in itself. > + > + AsmReadIdtr ((IA32_DESCRIPTOR *) &Idtr); (7) The cast is superfluous. > + if ((Idtr.Base >= BASE_4GB) || (Idtr.Base + Idtr.Limit >= BASE_4GB)) { > + return FALSE; > + } (8) Same comment as (6) -- please consider removing the 1st condition as a simplification (if you disagree, that's OK too). > + > + return TRUE; > +} > + > /** > MP Initialize Library initialization. > > @@ -2318,6 +2366,13 @@ SwitchBSPWorker ( > return EFI_NOT_READY; > } > > + // > + // Check whether CR3/GDT/IDT valid for AP. > + // > + if (!ValidCR3GdtIdtCheck()) { > + return EFI_INVALID_PARAMETER; > + } > + > CpuMpData->BSPInfo.State = CPU_SWITCH_STATE_IDLE; > CpuMpData->APInfo.State = CPU_SWITCH_STATE_IDLE; > CpuMpData->SwitchBspFlag = TRUE; (9) I think we should return EFI_UNSUPPORTED, not EFI_INVALID_PARAMETER. (10) More importantly, ValidCR3GdtIdtCheck() should not be called in the Worker functions for StartupAllAPs, StartupThisAP, SwitchBSP, and EnableDisableAP, in "UefiCpuPkg/Library/MpInitLib/MpLib.c". Instead, the calls should be made in the DXE instance of the library ("UefiCpuPkg/Library/MpInitLib/DxeMpLib.c"), at the very top of the functions: - MpInitLibStartupAllAPs - MpInitLibStartupThisAP - MpInitLibSwitchBSP - MpInitLibEnableDisableAP Here's why: (a) The symptom does not affect the PEI phase -- by the time the UEFI application is executed, the PEI phase has ended; there's no need to modify the PEI instance of the library. (b) The currently proposed failure exits are too late. For example, in the SwitchBSPWorker() function, by the time we exit, we have called DisableApicTimerInterrupt(), SaveAndDisableInterrupts(), and DisableLvtInterrupts() -- and the error path does not restore the original environment. (c) According to the PI spec (v1.7), the StartupAllAPs(), StartupThisAP(), SwitchBSP(), EnableDisableAP() member functions of EFI_MP_SERVICES_PROTOCOL may only be called on the (current) BSP. Because of this, it is OK to call ValidCR3GdtIdtCheck() as the very first action in the above-listed DxeMpLib functions. (Assuming the protocol members are called from an AP, and consequently we check CR3 / GDTR / IDTR on the AP (and not on the BSP), that's the *caller's* fault, per spec!) > @@ -2420,6 +2475,13 @@ EnableDisableApWorker ( > return EFI_NOT_FOUND; > } > > + // > + // Check whether CR3/GDT/IDT valid for AP. > + // > + if (!ValidCR3GdtIdtCheck()) { > + return EFI_INVALID_PARAMETER; > + } > + > if (!EnableAP) { > SetApState (&CpuMpData->CpuData[ProcessorNumber], CpuStateDisabled); > } else { > @@ -2607,6 +2669,13 @@ StartupAllCPUsWorker ( > return EFI_DEVICE_ERROR; > } > > + // > + // Check whether CR3/GDT/IDT valid for AP. > + // > + if (!ValidCR3GdtIdtCheck()) { > + return EFI_INVALID_PARAMETER; > + } > + > // > // Update AP state > // > @@ -2772,6 +2841,13 @@ StartupThisAPWorker ( > return EFI_INVALID_PARAMETER; > } > > + // > + // Check whether CR3/GDT/IDT valid for AP. > + // > + if (!ValidCR3GdtIdtCheck()) { > + return EFI_INVALID_PARAMETER; > + } > + > // > // Update AP state > // > diff --git a/UefiCpuPkg/Library/MpInitLib/MpLib.h b/UefiCpuPkg/Library/MpInitLib/MpLib.h > index 02652eaae1..4ac5cb51e3 100644 > --- a/UefiCpuPkg/Library/MpInitLib/MpLib.h > +++ b/UefiCpuPkg/Library/MpInitLib/MpLib.h > @@ -740,5 +740,17 @@ PlatformShadowMicrocode ( > IN OUT CPU_MP_DATA *CpuMpData > ); > > +/** > + Check whether CR3/GDT/IDT value valid for AP. > + > + @retval TRUE Pass the check. > + @retval FALSE Fail the check. > + > +**/ > +BOOLEAN > +ValidCR3GdtIdtCheck ( (11) In the function name, please write "Cr3", not "CR3". (See also: AsmReadCr3().) > + VOID > + ); > + > #endif > > diff --git a/UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf b/UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf > index 34abf25d43..0ca86fcdaa 100644 > --- a/UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf > +++ b/UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf > @@ -65,6 +65,7 @@ > gUefiCpuPkgTokenSpaceGuid.PcdSevEsIsEnabled ## CONSUMES > gUefiCpuPkgTokenSpaceGuid.PcdSevEsWorkAreaBase ## SOMETIMES_CONSUMES > gEfiMdeModulePkgTokenSpaceGuid.PcdGhcbBase ## CONSUMES > + gUefiCpuPkgTokenSpaceGuid.PcdEnableCpuApCr3GdtIdtCheck ## CONSUMES > > [Ppis] > gEdkiiPeiShadowMicrocodePpiGuid ## SOMETIMES_CONSUMES (12) Superficially, comment (3) applies -- please keep the PCDs in the UefiCpuPkg token space grouped together. However, per my point (10), the PEI instance of the library should not be modified at all; so please drop this hunk. > diff --git a/UefiCpuPkg/UefiCpuPkg.dec b/UefiCpuPkg/UefiCpuPkg.dec > index d83c084467..467ec5e001 100644 > --- a/UefiCpuPkg/UefiCpuPkg.dec > +++ b/UefiCpuPkg/UefiCpuPkg.dec > @@ -187,6 +187,10 @@ > # @Prompt Configure stack size for Application Processor (AP) > gUefiCpuPkgTokenSpaceGuid.PcdCpuApStackSize|0x8000|UINT32|0x00000003 > > + ## This value specifies whether need to check the CR3/GDT/IDT value for AP. > + # @Prompt Whether need to check the CR3/GDT/IDT value for AP > + gUefiCpuPkgTokenSpaceGuid.PcdEnableCpuApCr3GdtIdtCheck|FALSE|BOOLEAN|0x30000044 > + > ## Specifies stack size in the temporary RAM. 0 means half of TemporaryRamSize. > # @Prompt Stack size in the temporary RAM. > gUefiCpuPkgTokenSpaceGuid.PcdPeiTemporaryRamStackSize|0|UINT32|0x10001003 > OK, so this is [PcdsFixedAtBuild, PcdsPatchableInModule], not a FeaturePCD. I proposed FeaturePCD because optimizing compilers are supposed to eliminate it... But, I can see that BaseTools generates the same kind of code for Fixed BOOLEAN PCDs as well. OK! (13) I think you should modify the UNI file in accordance with the DEC file. Thanks! Laszlo ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v2] UefiCpuPkg/MpInitLib: Add check for CR3/GDT/IDT. 2020-09-03 19:00 ` Laszlo Ersek @ 2020-09-03 19:55 ` Laszlo Ersek 2020-09-04 1:34 ` [edk2-devel] " Ni, Ray 0 siblings, 1 reply; 6+ messages in thread From: Laszlo Ersek @ 2020-09-03 19:55 UTC (permalink / raw) To: Eric Dong, devel; +Cc: Ray Ni On 09/03/20 21:00, Laszlo Ersek wrote: > (10) More importantly, ValidCR3GdtIdtCheck() should not be called in the > Worker functions for StartupAllAPs, StartupThisAP, SwitchBSP, and > EnableDisableAP, in "UefiCpuPkg/Library/MpInitLib/MpLib.c". > > Instead, the calls should be made in the DXE instance of the library > ("UefiCpuPkg/Library/MpInitLib/DxeMpLib.c"), at the very top of the > functions: > > - MpInitLibStartupAllAPs > - MpInitLibStartupThisAP > - MpInitLibSwitchBSP > - MpInitLibEnableDisableAP > > Here's why: > > (a) The symptom does not affect the PEI phase -- by the time the UEFI > application is executed, the PEI phase has ended; there's no need to > modify the PEI instance of the library. > > (b) The currently proposed failure exits are too late. For example, in > the SwitchBSPWorker() function, by the time we exit, we have called > DisableApicTimerInterrupt(), SaveAndDisableInterrupts(), and > DisableLvtInterrupts() -- and the error path does not restore the > original environment. > > (c) According to the PI spec (v1.7), the StartupAllAPs(), > StartupThisAP(), SwitchBSP(), EnableDisableAP() member functions of > EFI_MP_SERVICES_PROTOCOL may only be called on the (current) BSP. > Because of this, it is OK to call ValidCR3GdtIdtCheck() as the very > first action in the above-listed DxeMpLib functions. > > (Assuming the protocol members are called from an AP, and consequently > we check CR3 / GDTR / IDTR on the AP (and not on the BSP), that's the > *caller's* fault, per spec!) This means we can move the ValidCr3GdtIdtCheck() function to "DxeMpLib.c", and it is not necessary to modify "MpLib.h". Thanks Laszlo ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [edk2-devel] [PATCH v2] UefiCpuPkg/MpInitLib: Add check for CR3/GDT/IDT. 2020-09-03 19:55 ` Laszlo Ersek @ 2020-09-04 1:34 ` Ni, Ray 2020-09-04 2:00 ` Dong, Eric 0 siblings, 1 reply; 6+ messages in thread From: Ni, Ray @ 2020-09-04 1:34 UTC (permalink / raw) To: devel@edk2.groups.io, lersek@redhat.com, Dong, Eric; +Cc: Lou, Yun [-- Attachment #1: Type: text/plain, Size: 2398 bytes --] Why do we need a new PCD to control such check? Under what circumstance the PCD is false? We may need to move such check out of MpLib.c. Because when bps runs at 32bit mode, AP doesn’t need to switch to long mode, such check is not needed and also always passes. We should not assume PEI runs at 32 bit mode. ________________________________ 发件人: devel@edk2.groups.io <devel@edk2.groups.io> 代表 Laszlo Ersek <lersek@redhat.com> 发送时间: Friday, September 4, 2020 3:55:47 AM 收件人: Dong, Eric <eric.dong@intel.com>; devel@edk2.groups.io <devel@edk2.groups.io> 抄送: Ni, Ray <ray.ni@intel.com> 主题: Re: [edk2-devel] [PATCH v2] UefiCpuPkg/MpInitLib: Add check for CR3/GDT/IDT. On 09/03/20 21:00, Laszlo Ersek wrote: > (10) More importantly, ValidCR3GdtIdtCheck() should not be called in the > Worker functions for StartupAllAPs, StartupThisAP, SwitchBSP, and > EnableDisableAP, in "UefiCpuPkg/Library/MpInitLib/MpLib.c". > > Instead, the calls should be made in the DXE instance of the library > ("UefiCpuPkg/Library/MpInitLib/DxeMpLib.c"), at the very top of the > functions: > > - MpInitLibStartupAllAPs > - MpInitLibStartupThisAP > - MpInitLibSwitchBSP > - MpInitLibEnableDisableAP > > Here's why: > > (a) The symptom does not affect the PEI phase -- by the time the UEFI > application is executed, the PEI phase has ended; there's no need to > modify the PEI instance of the library. > > (b) The currently proposed failure exits are too late. For example, in > the SwitchBSPWorker() function, by the time we exit, we have called > DisableApicTimerInterrupt(), SaveAndDisableInterrupts(), and > DisableLvtInterrupts() -- and the error path does not restore the > original environment. > > (c) According to the PI spec (v1.7), the StartupAllAPs(), > StartupThisAP(), SwitchBSP(), EnableDisableAP() member functions of > EFI_MP_SERVICES_PROTOCOL may only be called on the (current) BSP. > Because of this, it is OK to call ValidCR3GdtIdtCheck() as the very > first action in the above-listed DxeMpLib functions. > > (Assuming the protocol members are called from an AP, and consequently > we check CR3 / GDTR / IDTR on the AP (and not on the BSP), that's the > *caller's* fault, per spec!) This means we can move the ValidCr3GdtIdtCheck() function to "DxeMpLib.c", and it is not necessary to modify "MpLib.h". Thanks Laszlo [-- Attachment #2: Type: text/html, Size: 3519 bytes --] ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [edk2-devel] [PATCH v2] UefiCpuPkg/MpInitLib: Add check for CR3/GDT/IDT. 2020-09-04 1:34 ` [edk2-devel] " Ni, Ray @ 2020-09-04 2:00 ` Dong, Eric 2020-09-04 2:18 ` 回复: " vanjeff_919 0 siblings, 1 reply; 6+ messages in thread From: Dong, Eric @ 2020-09-04 2:00 UTC (permalink / raw) To: Ni, Ray, devel@edk2.groups.io, lersek@redhat.com; +Cc: Lou, Yun [-- Attachment #1: Type: text/plain, Size: 3095 bytes --] I guess Laszlo think this check is not always needed, just used for this special shell application case. He wants to use default FALSE to always ignore this check and make code logic clear. Thanks, Eric From: Ni, Ray <ray.ni@intel.com> Sent: Friday, September 4, 2020 9:34 AM To: devel@edk2.groups.io; lersek@redhat.com; Dong, Eric <eric.dong@intel.com> Cc: Lou, Yun <yun.lou@intel.com> Subject: Re: [edk2-devel] [PATCH v2] UefiCpuPkg/MpInitLib: Add check for CR3/GDT/IDT. Why do we need a new PCD to control such check? Under what circumstance the PCD is false? We may need to move such check out of MpLib.c. Because when bps runs at 32bit mode, AP doesn’t need to switch to long mode, such check is not needed and also always passes. We should not assume PEI runs at 32 bit mode. ________________________________ 发件人: devel@edk2.groups.io<mailto:devel@edk2.groups.io> <devel@edk2.groups.io<mailto:devel@edk2.groups.io>> 代表 Laszlo Ersek <lersek@redhat.com<mailto:lersek@redhat.com>> 发送时间: Friday, September 4, 2020 3:55:47 AM 收件人: Dong, Eric <eric.dong@intel.com<mailto:eric.dong@intel.com>>; devel@edk2.groups.io<mailto:devel@edk2.groups.io> <devel@edk2.groups.io<mailto:devel@edk2.groups.io>> 抄送: Ni, Ray <ray.ni@intel.com<mailto:ray.ni@intel.com>> 主题: Re: [edk2-devel] [PATCH v2] UefiCpuPkg/MpInitLib: Add check for CR3/GDT/IDT. On 09/03/20 21:00, Laszlo Ersek wrote: > (10) More importantly, ValidCR3GdtIdtCheck() should not be called in the > Worker functions for StartupAllAPs, StartupThisAP, SwitchBSP, and > EnableDisableAP, in "UefiCpuPkg/Library/MpInitLib/MpLib.c". > > Instead, the calls should be made in the DXE instance of the library > ("UefiCpuPkg/Library/MpInitLib/DxeMpLib.c"), at the very top of the > functions: > > - MpInitLibStartupAllAPs > - MpInitLibStartupThisAP > - MpInitLibSwitchBSP > - MpInitLibEnableDisableAP > > Here's why: > > (a) The symptom does not affect the PEI phase -- by the time the UEFI > application is executed, the PEI phase has ended; there's no need to > modify the PEI instance of the library. > > (b) The currently proposed failure exits are too late. For example, in > the SwitchBSPWorker() function, by the time we exit, we have called > DisableApicTimerInterrupt(), SaveAndDisableInterrupts(), and > DisableLvtInterrupts() -- and the error path does not restore the > original environment. > > (c) According to the PI spec (v1.7), the StartupAllAPs(), > StartupThisAP(), SwitchBSP(), EnableDisableAP() member functions of > EFI_MP_SERVICES_PROTOCOL may only be called on the (current) BSP. > Because of this, it is OK to call ValidCR3GdtIdtCheck() as the very > first action in the above-listed DxeMpLib functions. > > (Assuming the protocol members are called from an AP, and consequently > we check CR3 / GDTR / IDTR on the AP (and not on the BSP), that's the > *caller's* fault, per spec!) This means we can move the ValidCr3GdtIdtCheck() function to "DxeMpLib.c", and it is not necessary to modify "MpLib.h". Thanks Laszlo [-- Attachment #2: Type: text/html, Size: 8498 bytes --] ^ permalink raw reply [flat|nested] 6+ messages in thread
* 回复: [edk2-devel] [PATCH v2] UefiCpuPkg/MpInitLib: Add check for CR3/GDT/IDT. 2020-09-04 2:00 ` Dong, Eric @ 2020-09-04 2:18 ` vanjeff_919 2020-09-04 6:58 ` Laszlo Ersek 0 siblings, 1 reply; 6+ messages in thread From: vanjeff_919 @ 2020-09-04 2:18 UTC (permalink / raw) To: devel@edk2.groups.io, eric.dong@intel.com, Ni, Ray, lersek@redhat.com Cc: Lou, Yun [-- Attachment #1.1: Type: text/plain, Size: 3571 bytes --] Laszlo & Eric, Introducing one new PCD to handle such rare test case is too heavy. I think We could do validating CR3/GDT/IDT space < 4GB address always in MpInitLib. Jeff 发件人: Dong, Eric<mailto:eric.dong@intel.com> 发送时间: 2020年9月4日 10:01 收件人: Ni, Ray<mailto:ray.ni@intel.com>; devel@edk2.groups.io<mailto:devel@edk2.groups.io>; lersek@redhat.com<mailto:lersek@redhat.com> 抄送: Lou, Yun<mailto:yun.lou@intel.com> 主题: Re: [edk2-devel] [PATCH v2] UefiCpuPkg/MpInitLib: Add check for CR3/GDT/IDT. I guess Laszlo think this check is not always needed, just used for this special shell application case. He wants to use default FALSE to always ignore this check and make code logic clear. Thanks, Eric From: Ni, Ray <ray.ni@intel.com> Sent: Friday, September 4, 2020 9:34 AM To: devel@edk2.groups.io; lersek@redhat.com; Dong, Eric <eric.dong@intel.com> Cc: Lou, Yun <yun.lou@intel.com> Subject: Re: [edk2-devel] [PATCH v2] UefiCpuPkg/MpInitLib: Add check for CR3/GDT/IDT. Why do we need a new PCD to control such check? Under what circumstance the PCD is false? We may need to move such check out of MpLib.c. Because when bps runs at 32bit mode, AP doesn’t need to switch to long mode, such check is not needed and also always passes. We should not assume PEI runs at 32 bit mode. 发件人: devel@edk2.groups.io<mailto:devel@edk2.groups.io> <devel@edk2.groups.io<mailto:devel@edk2.groups.io>> 代表 Laszlo Ersek <lersek@redhat.com<mailto:lersek@redhat.com>> 发送时间: Friday, September 4, 2020 3:55:47 AM 收件人: Dong, Eric <eric.dong@intel.com<mailto:eric.dong@intel.com>>; devel@edk2.groups.io<mailto:devel@edk2.groups.io> <devel@edk2.groups.io<mailto:devel@edk2.groups.io>> 抄送: Ni, Ray <ray.ni@intel.com<mailto:ray.ni@intel.com>> 主题: Re: [edk2-devel] [PATCH v2] UefiCpuPkg/MpInitLib: Add check for CR3/GDT/IDT. On 09/03/20 21:00, Laszlo Ersek wrote: > (10) More importantly, ValidCR3GdtIdtCheck() should not be called in the > Worker functions for StartupAllAPs, StartupThisAP, SwitchBSP, and > EnableDisableAP, in "UefiCpuPkg/Library/MpInitLib/MpLib.c". > > Instead, the calls should be made in the DXE instance of the library > ("UefiCpuPkg/Library/MpInitLib/DxeMpLib.c"), at the very top of the > functions: > > - MpInitLibStartupAllAPs > - MpInitLibStartupThisAP > - MpInitLibSwitchBSP > - MpInitLibEnableDisableAP > > Here's why: > > (a) The symptom does not affect the PEI phase -- by the time the UEFI > application is executed, the PEI phase has ended; there's no need to > modify the PEI instance of the library. > > (b) The currently proposed failure exits are too late. For example, in > the SwitchBSPWorker() function, by the time we exit, we have called > DisableApicTimerInterrupt(), SaveAndDisableInterrupts(), and > DisableLvtInterrupts() -- and the error path does not restore the > original environment. > > (c) According to the PI spec (v1.7), the StartupAllAPs(), > StartupThisAP(), SwitchBSP(), EnableDisableAP() member functions of > EFI_MP_SERVICES_PROTOCOL may only be called on the (current) BSP. > Because of this, it is OK to call ValidCR3GdtIdtCheck() as the very > first action in the above-listed DxeMpLib functions. > > (Assuming the protocol members are called from an AP, and consequently > we check CR3 / GDTR / IDTR on the AP (and not on the BSP), that's the > *caller's* fault, per spec!) This means we can move the ValidCr3GdtIdtCheck() function to "DxeMpLib.c", and it is not necessary to modify "MpLib.h". Thanks Laszlo [-- Attachment #1.2: Type: text/html, Size: 11940 bytes --] [-- Attachment #2: 89184FA29A184BD3AE9BDABEFEE0BA6A.png --] [-- Type: image/png, Size: 144 bytes --] [-- Attachment #3: 435BFC14D84B499EABDAF41539376076.png --] [-- Type: image/png, Size: 132 bytes --] ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: 回复: [edk2-devel] [PATCH v2] UefiCpuPkg/MpInitLib: Add check for CR3/GDT/IDT. 2020-09-04 2:18 ` 回复: " vanjeff_919 @ 2020-09-04 6:58 ` Laszlo Ersek 2020-09-04 7:32 ` 回复: " Fan Jeff 0 siblings, 1 reply; 6+ messages in thread From: Laszlo Ersek @ 2020-09-04 6:58 UTC (permalink / raw) To: Fan Jeff, devel@edk2.groups.io, eric.dong@intel.com, Ni, Ray; +Cc: Lou, Yun On 09/04/20 04:18, Fan Jeff wrote: > Laszlo & Eric, > > Introducing one new PCD to handle such rare test case is too heavy. I think We could do validating CR3/GDT/IDT space < 4GB address always in MpInitLib. I disagree. What the UEFI application does (interfere with GDT / IDT / CR3 placement) is invalid. It changes system properties under the feet of platform DXE drivers. UEFI applications are supposed to be written against public protocols and services in the UEFI spec (and maybe in the PI spec). If this application is a test application that purposely massages low-level system properties, that's fine; but then, if we change core edk2 components to be somewhat compatible with this application, then we should make sure that platforms that do not care about this specific use case do not suffer a performance hit or a code complexity hit. What I could accept, under your proposal, is the following: add three ASSERT()s to FillExchangeInfoData(), where we fetch the IDTR / GDTR / CR3 anyway. This would be fine because it only expresses existing assumptions / requirements. However, my understanding is that this would not solve Eric's problem. The system would hang -- in DEBUG / NOOPT builds -- or crash -- in a RELEASE build -- just the same as before. Now, *if* FillExchangeInfoData() is currently *wrong* to have these 32-bit assumptions, because edk2 modules themselves can break those assumptions (without the custom UEFI application), then we have a more serious problem. But for that problem, just "checking and rejecting" is not a sufficient solution, regardless of how and where we check and reject. Thanks Laszlo > > Jeff > > 发件人: Dong, Eric<mailto:eric.dong@intel.com> > 发送时间: 2020年9月4日 10:01 > 收件人: Ni, Ray<mailto:ray.ni@intel.com>; devel@edk2.groups.io<mailto:devel@edk2.groups.io>; lersek@redhat.com<mailto:lersek@redhat.com> > 抄送: Lou, Yun<mailto:yun.lou@intel.com> > 主题: Re: [edk2-devel] [PATCH v2] UefiCpuPkg/MpInitLib: Add check for CR3/GDT/IDT. > > I guess Laszlo think this check is not always needed, just used for this special shell application case. He wants to use default FALSE to always ignore this check and make code logic clear. > > Thanks, > Eric > > From: Ni, Ray <ray.ni@intel.com> > Sent: Friday, September 4, 2020 9:34 AM > To: devel@edk2.groups.io; lersek@redhat.com; Dong, Eric <eric.dong@intel.com> > Cc: Lou, Yun <yun.lou@intel.com> > Subject: Re: [edk2-devel] [PATCH v2] UefiCpuPkg/MpInitLib: Add check for CR3/GDT/IDT. > > Why do we need a new PCD to control such check? Under what circumstance the PCD is false? > We may need to move such check out of MpLib.c. Because when bps runs at 32bit mode, AP doesn’t need to switch to long mode, such check is not needed and also always passes. > > We should not assume PEI runs at 32 bit mode. > > > 发件人: devel@edk2.groups.io<mailto:devel@edk2.groups.io> <devel@edk2.groups.io<mailto:devel@edk2.groups.io>> 代表 Laszlo Ersek <lersek@redhat.com<mailto:lersek@redhat.com>> > 发送时间: Friday, September 4, 2020 3:55:47 AM > 收件人: Dong, Eric <eric.dong@intel.com<mailto:eric.dong@intel.com>>; devel@edk2.groups.io<mailto:devel@edk2.groups.io> <devel@edk2.groups.io<mailto:devel@edk2.groups.io>> > 抄送: Ni, Ray <ray.ni@intel.com<mailto:ray.ni@intel.com>> > 主题: Re: [edk2-devel] [PATCH v2] UefiCpuPkg/MpInitLib: Add check for CR3/GDT/IDT. > > On 09/03/20 21:00, Laszlo Ersek wrote: > >> (10) More importantly, ValidCR3GdtIdtCheck() should not be called in the >> Worker functions for StartupAllAPs, StartupThisAP, SwitchBSP, and >> EnableDisableAP, in "UefiCpuPkg/Library/MpInitLib/MpLib.c". >> >> Instead, the calls should be made in the DXE instance of the library >> ("UefiCpuPkg/Library/MpInitLib/DxeMpLib.c"), at the very top of the >> functions: >> >> - MpInitLibStartupAllAPs >> - MpInitLibStartupThisAP >> - MpInitLibSwitchBSP >> - MpInitLibEnableDisableAP >> >> Here's why: >> >> (a) The symptom does not affect the PEI phase -- by the time the UEFI >> application is executed, the PEI phase has ended; there's no need to >> modify the PEI instance of the library. >> >> (b) The currently proposed failure exits are too late. For example, in >> the SwitchBSPWorker() function, by the time we exit, we have called >> DisableApicTimerInterrupt(), SaveAndDisableInterrupts(), and >> DisableLvtInterrupts() -- and the error path does not restore the >> original environment. >> >> (c) According to the PI spec (v1.7), the StartupAllAPs(), >> StartupThisAP(), SwitchBSP(), EnableDisableAP() member functions of >> EFI_MP_SERVICES_PROTOCOL may only be called on the (current) BSP. >> Because of this, it is OK to call ValidCR3GdtIdtCheck() as the very >> first action in the above-listed DxeMpLib functions. >> >> (Assuming the protocol members are called from an AP, and consequently >> we check CR3 / GDTR / IDTR on the AP (and not on the BSP), that's the >> *caller's* fault, per spec!) > > This means we can move the ValidCr3GdtIdtCheck() function to > "DxeMpLib.c", and it is not necessary to modify "MpLib.h". > > Thanks > Laszlo > > > ^ permalink raw reply [flat|nested] 6+ messages in thread
* 回复: 回复: [edk2-devel] [PATCH v2] UefiCpuPkg/MpInitLib: Add check for CR3/GDT/IDT. 2020-09-04 6:58 ` Laszlo Ersek @ 2020-09-04 7:32 ` Fan Jeff 2020-09-04 8:06 ` Yao, Jiewen 2020-09-04 8:23 ` Laszlo Ersek 0 siblings, 2 replies; 6+ messages in thread From: Fan Jeff @ 2020-09-04 7:32 UTC (permalink / raw) To: Laszlo Ersek, devel@edk2.groups.io, eric.dong@intel.com, Ni, Ray; +Cc: Lou, Yun [-- Attachment #1: Type: text/plain, Size: 6121 bytes --] Laszlo, Why sync the BSP’s CR3/GDT/IDT values for AP when AP wakes up instead of using old cached BSP’s CR3/GDT/IDT values when CPU driver initiallly dispatched is that we CANNOT assume original values are still valid during POST phase. On this senario, BSP’s CR3/GDT/IDT are just like input parameters for one function. Validating them are necessary. For example, DebugAgentDxe driver may be loaded in UEFI shell to setup source level debugging enviroment of EDKII debugger tools. It may setup new IDT space. Jeff 发件人: Laszlo Ersek<mailto:lersek@redhat.com> 发送时间: 2020年9月4日 14:58 收件人: Fan Jeff<mailto:vanjeff_919@hotmail.com>; devel@edk2.groups.io<mailto:devel@edk2.groups.io>; eric.dong@intel.com<mailto:eric.dong@intel.com>; Ni, Ray<mailto:ray.ni@intel.com> 抄送: Lou, Yun<mailto:yun.lou@intel.com> 主题: Re: 回复: [edk2-devel] [PATCH v2] UefiCpuPkg/MpInitLib: Add check for CR3/GDT/IDT. On 09/04/20 04:18, Fan Jeff wrote: > Laszlo & Eric, > > Introducing one new PCD to handle such rare test case is too heavy. I think We could do validating CR3/GDT/IDT space < 4GB address always in MpInitLib. I disagree. What the UEFI application does (interfere with GDT / IDT / CR3 placement) is invalid. It changes system properties under the feet of platform DXE drivers. UEFI applications are supposed to be written against public protocols and services in the UEFI spec (and maybe in the PI spec). If this application is a test application that purposely massages low-level system properties, that's fine; but then, if we change core edk2 components to be somewhat compatible with this application, then we should make sure that platforms that do not care about this specific use case do not suffer a performance hit or a code complexity hit. What I could accept, under your proposal, is the following: add three ASSERT()s to FillExchangeInfoData(), where we fetch the IDTR / GDTR / CR3 anyway. This would be fine because it only expresses existing assumptions / requirements. However, my understanding is that this would not solve Eric's problem. The system would hang -- in DEBUG / NOOPT builds -- or crash -- in a RELEASE build -- just the same as before. Now, *if* FillExchangeInfoData() is currently *wrong* to have these 32-bit assumptions, because edk2 modules themselves can break those assumptions (without the custom UEFI application), then we have a more serious problem. But for that problem, just "checking and rejecting" is not a sufficient solution, regardless of how and where we check and reject. Thanks Laszlo > > Jeff > > 发件人: Dong, Eric<mailto:eric.dong@intel.com> > 发送时间: 2020年9月4日 10:01 > 收件人: Ni, Ray<mailto:ray.ni@intel.com>; devel@edk2.groups.io<mailto:devel@edk2.groups.io>; lersek@redhat.com<mailto:lersek@redhat.com> > 抄送: Lou, Yun<mailto:yun.lou@intel.com> > 主题: Re: [edk2-devel] [PATCH v2] UefiCpuPkg/MpInitLib: Add check for CR3/GDT/IDT. > > I guess Laszlo think this check is not always needed, just used for this special shell application case. He wants to use default FALSE to always ignore this check and make code logic clear. > > Thanks, > Eric > > From: Ni, Ray <ray.ni@intel.com> > Sent: Friday, September 4, 2020 9:34 AM > To: devel@edk2.groups.io; lersek@redhat.com; Dong, Eric <eric.dong@intel.com> > Cc: Lou, Yun <yun.lou@intel.com> > Subject: Re: [edk2-devel] [PATCH v2] UefiCpuPkg/MpInitLib: Add check for CR3/GDT/IDT. > > Why do we need a new PCD to control such check? Under what circumstance the PCD is false? > We may need to move such check out of MpLib.c. Because when bps runs at 32bit mode, AP doesn’t need to switch to long mode, such check is not needed and also always passes. > > We should not assume PEI runs at 32 bit mode. > > > 发件人: devel@edk2.groups.io<mailto:devel@edk2.groups.io> <devel@edk2.groups.io<mailto:devel@edk2.groups.io>> 代表 Laszlo Ersek <lersek@redhat.com<mailto:lersek@redhat.com>> > 发送时间: Friday, September 4, 2020 3:55:47 AM > 收件人: Dong, Eric <eric.dong@intel.com<mailto:eric.dong@intel.com>>; devel@edk2.groups.io<mailto:devel@edk2.groups.io> <devel@edk2.groups.io<mailto:devel@edk2.groups.io>> > 抄送: Ni, Ray <ray.ni@intel.com<mailto:ray.ni@intel.com>> > 主题: Re: [edk2-devel] [PATCH v2] UefiCpuPkg/MpInitLib: Add check for CR3/GDT/IDT. > > On 09/03/20 21:00, Laszlo Ersek wrote: > >> (10) More importantly, ValidCR3GdtIdtCheck() should not be called in the >> Worker functions for StartupAllAPs, StartupThisAP, SwitchBSP, and >> EnableDisableAP, in "UefiCpuPkg/Library/MpInitLib/MpLib.c". >> >> Instead, the calls should be made in the DXE instance of the library >> ("UefiCpuPkg/Library/MpInitLib/DxeMpLib.c"), at the very top of the >> functions: >> >> - MpInitLibStartupAllAPs >> - MpInitLibStartupThisAP >> - MpInitLibSwitchBSP >> - MpInitLibEnableDisableAP >> >> Here's why: >> >> (a) The symptom does not affect the PEI phase -- by the time the UEFI >> application is executed, the PEI phase has ended; there's no need to >> modify the PEI instance of the library. >> >> (b) The currently proposed failure exits are too late. For example, in >> the SwitchBSPWorker() function, by the time we exit, we have called >> DisableApicTimerInterrupt(), SaveAndDisableInterrupts(), and >> DisableLvtInterrupts() -- and the error path does not restore the >> original environment. >> >> (c) According to the PI spec (v1.7), the StartupAllAPs(), >> StartupThisAP(), SwitchBSP(), EnableDisableAP() member functions of >> EFI_MP_SERVICES_PROTOCOL may only be called on the (current) BSP. >> Because of this, it is OK to call ValidCR3GdtIdtCheck() as the very >> first action in the above-listed DxeMpLib functions. >> >> (Assuming the protocol members are called from an AP, and consequently >> we check CR3 / GDTR / IDTR on the AP (and not on the BSP), that's the >> *caller's* fault, per spec!) > > This means we can move the ValidCr3GdtIdtCheck() function to > "DxeMpLib.c", and it is not necessary to modify "MpLib.h". > > Thanks > Laszlo > > > [-- Attachment #2: Type: text/html, Size: 11264 bytes --] ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: 回复: [edk2-devel] [PATCH v2] UefiCpuPkg/MpInitLib: Add check for CR3/GDT/IDT. 2020-09-04 7:32 ` 回复: " Fan Jeff @ 2020-09-04 8:06 ` Yao, Jiewen 2020-09-04 8:43 ` 回复: " Fan Jeff 2020-09-04 8:23 ` Laszlo Ersek 1 sibling, 1 reply; 6+ messages in thread From: Yao, Jiewen @ 2020-09-04 8:06 UTC (permalink / raw) To: devel@edk2.groups.io, vanjeff_919@hotmail.com, Laszlo Ersek, Dong, Eric, Ni, Ray Cc: Lou, Yun [-- Attachment #1: Type: text/plain, Size: 8707 bytes --] When we say “validate”, we need get clear on what is the contract between caller and callee, and what is the expectation of the validation. For example, in this case, the validation is limited to 4G or not 4G. Why? This function does not verify following, why? 1. if the GDT table is valid. 2. if the IDT table is valid 3. if the exception handler is valid 4. if the timer handler still works 5. if the page table is valid 6. if the page table is 1:1 mapping 7. if the page table still enforce the expected protection, such as RO, NX 8. …… If an application creates a crazy state, CpuDxe may pass the validation with below 4G page table, but still fail to wake up APs. If it is the app’s responsibility to ensure the system in good state, the validation is unnecessary. If it is the CpuDxe’s responsibility to ensure the system in good state, the validation is insufficient. I think we should wait. I am working with Eric to collect the requirement on why test case is designed in this way. DebugAgentDxe is a good case. It is for debug purpose. I believe there must be contract between CPU driver and DebugAgentDxe that which status DebugAgentDxe may modify and which state DebugAgentDxe may not. It is DebugAgentDxe’s responsibility to ensure the new system state is correct and compatible with the CPU driver. With the contract, I don’t think CPU driver need validate the system state changed by DebugAgentDxe. If DebugAgentDxe put system in a wrong state, CPUDriver has no chance to run. From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Fan Jeff Sent: Friday, September 4, 2020 3:32 PM To: Laszlo Ersek <lersek@redhat.com>; devel@edk2.groups.io; Dong, Eric <eric.dong@intel.com>; Ni, Ray <ray.ni@intel.com> Cc: Lou, Yun <yun.lou@intel.com> Subject: 回复: 回复: [edk2-devel] [PATCH v2] UefiCpuPkg/MpInitLib: Add check for CR3/GDT/IDT. Laszlo, Why sync the BSP’s CR3/GDT/IDT values for AP when AP wakes up instead of using old cached BSP’s CR3/GDT/IDT values when CPU driver initiallly dispatched is that we CANNOT assume original values are still valid during POST phase. On this senario, BSP’s CR3/GDT/IDT are just like input parameters for one function. Validating them are necessary. For example, DebugAgentDxe driver may be loaded in UEFI shell to setup source level debugging enviroment of EDKII debugger tools. It may setup new IDT space. Jeff 发件人: Laszlo Ersek<mailto:lersek@redhat.com> 发送时间: 2020年9月4日 14:58 收件人: Fan Jeff<mailto:vanjeff_919@hotmail.com>; devel@edk2.groups.io<mailto:devel@edk2.groups.io>; eric.dong@intel.com<mailto:eric.dong@intel.com>; Ni, Ray<mailto:ray.ni@intel.com> 抄送: Lou, Yun<mailto:yun.lou@intel.com> 主题: Re: 回复: [edk2-devel] [PATCH v2] UefiCpuPkg/MpInitLib: Add check for CR3/GDT/IDT. On 09/04/20 04:18, Fan Jeff wrote: > Laszlo & Eric, > > Introducing one new PCD to handle such rare test case is too heavy. I think We could do validating CR3/GDT/IDT space < 4GB address always in MpInitLib. I disagree. What the UEFI application does (interfere with GDT / IDT / CR3 placement) is invalid. It changes system properties under the feet of platform DXE drivers. UEFI applications are supposed to be written against public protocols and services in the UEFI spec (and maybe in the PI spec). If this application is a test application that purposely massages low-level system properties, that's fine; but then, if we change core edk2 components to be somewhat compatible with this application, then we should make sure that platforms that do not care about this specific use case do not suffer a performance hit or a code complexity hit. What I could accept, under your proposal, is the following: add three ASSERT()s to FillExchangeInfoData(), where we fetch the IDTR / GDTR / CR3 anyway. This would be fine because it only expresses existing assumptions / requirements. However, my understanding is that this would not solve Eric's problem. The system would hang -- in DEBUG / NOOPT builds -- or crash -- in a RELEASE build -- just the same as before. Now, *if* FillExchangeInfoData() is currently *wrong* to have these 32-bit assumptions, because edk2 modules themselves can break those assumptions (without the custom UEFI application), then we have a more serious problem. But for that problem, just "checking and rejecting" is not a sufficient solution, regardless of how and where we check and reject. Thanks Laszlo > > Jeff > > 发件人: Dong, Eric<mailto:eric.dong@intel.com> > 发送时间: 2020年9月4日 10:01 > 收件人: Ni, Ray<mailto:ray.ni@intel.com>; devel@edk2.groups.io<mailto:devel@edk2.groups.io<mailto:devel@edk2.groups.io%3cmailto:devel@edk2.groups.io>>; lersek@redhat.com<mailto:lersek@redhat.com> > 抄送: Lou, Yun<mailto:yun.lou@intel.com> > 主题: Re: [edk2-devel] [PATCH v2] UefiCpuPkg/MpInitLib: Add check for CR3/GDT/IDT. > > I guess Laszlo think this check is not always needed, just used for this special shell application case. He wants to use default FALSE to always ignore this check and make code logic clear. > > Thanks, > Eric > > From: Ni, Ray <ray.ni@intel.com<mailto:ray.ni@intel.com>> > Sent: Friday, September 4, 2020 9:34 AM > To: devel@edk2.groups.io<mailto:devel@edk2.groups.io>; lersek@redhat.com<mailto:lersek@redhat.com>; Dong, Eric <eric.dong@intel.com<mailto:eric.dong@intel.com>> > Cc: Lou, Yun <yun.lou@intel.com<mailto:yun.lou@intel.com>> > Subject: Re: [edk2-devel] [PATCH v2] UefiCpuPkg/MpInitLib: Add check for CR3/GDT/IDT. > > Why do we need a new PCD to control such check? Under what circumstance the PCD is false? > We may need to move such check out of MpLib.c. Because when bps runs at 32bit mode, AP doesn’t need to switch to long mode, such check is not needed and also always passes. > > We should not assume PEI runs at 32 bit mode. > > > 发件人: devel@edk2.groups.io<mailto:devel@edk2.groups.io<mailto:devel@edk2.groups.io%3cmailto:devel@edk2.groups.io>> <devel@edk2.groups.io<mailto:devel@edk2.groups.io<mailto:devel@edk2.groups.io%3cmailto:devel@edk2.groups.io>>> 代表 Laszlo Ersek <lersek@redhat.com<mailto:lersek@redhat.com<mailto:lersek@redhat.com%3cmailto:lersek@redhat.com>>> > 发送时间: Friday, September 4, 2020 3:55:47 AM > 收件人: Dong, Eric <eric.dong@intel.com<mailto:eric.dong@intel.com<mailto:eric.dong@intel.com%3cmailto:eric.dong@intel.com>>>; devel@edk2.groups.io<mailto:devel@edk2.groups.io<mailto:devel@edk2.groups.io%3cmailto:devel@edk2.groups.io>> <devel@edk2.groups.io<mailto:devel@edk2.groups.io<mailto:devel@edk2.groups.io%3cmailto:devel@edk2.groups.io>>> > 抄送: Ni, Ray <ray.ni@intel.com<mailto:ray.ni@intel.com<mailto:ray.ni@intel.com%3cmailto:ray.ni@intel.com>>> > 主题: Re: [edk2-devel] [PATCH v2] UefiCpuPkg/MpInitLib: Add check for CR3/GDT/IDT. > > On 09/03/20 21:00, Laszlo Ersek wrote: > >> (10) More importantly, ValidCR3GdtIdtCheck() should not be called in the >> Worker functions for StartupAllAPs, StartupThisAP, SwitchBSP, and >> EnableDisableAP, in "UefiCpuPkg/Library/MpInitLib/MpLib.c". >> >> Instead, the calls should be made in the DXE instance of the library >> ("UefiCpuPkg/Library/MpInitLib/DxeMpLib.c"), at the very top of the >> functions: >> >> - MpInitLibStartupAllAPs >> - MpInitLibStartupThisAP >> - MpInitLibSwitchBSP >> - MpInitLibEnableDisableAP >> >> Here's why: >> >> (a) The symptom does not affect the PEI phase -- by the time the UEFI >> application is executed, the PEI phase has ended; there's no need to >> modify the PEI instance of the library. >> >> (b) The currently proposed failure exits are too late. For example, in >> the SwitchBSPWorker() function, by the time we exit, we have called >> DisableApicTimerInterrupt(), SaveAndDisableInterrupts(), and >> DisableLvtInterrupts() -- and the error path does not restore the >> original environment. >> >> (c) According to the PI spec (v1.7), the StartupAllAPs(), >> StartupThisAP(), SwitchBSP(), EnableDisableAP() member functions of >> EFI_MP_SERVICES_PROTOCOL may only be called on the (current) BSP. >> Because of this, it is OK to call ValidCR3GdtIdtCheck() as the very >> first action in the above-listed DxeMpLib functions. >> >> (Assuming the protocol members are called from an AP, and consequently >> we check CR3 / GDTR / IDTR on the AP (and not on the BSP), that's the >> *caller's* fault, per spec!) > > This means we can move the ValidCr3GdtIdtCheck() function to > "DxeMpLib.c", and it is not necessary to modify "MpLib.h". > > Thanks > Laszlo > > [-- Attachment #2: Type: text/html, Size: 20568 bytes --] ^ permalink raw reply [flat|nested] 6+ messages in thread
* 回复: 回复: [edk2-devel] [PATCH v2] UefiCpuPkg/MpInitLib: Add check for CR3/GDT/IDT. 2020-09-04 8:06 ` Yao, Jiewen @ 2020-09-04 8:43 ` Fan Jeff 0 siblings, 0 replies; 6+ messages in thread From: Fan Jeff @ 2020-09-04 8:43 UTC (permalink / raw) To: Yao, Jiewen, devel@edk2.groups.io, Laszlo Ersek, Dong, Eric, Ni, Ray Cc: Lou, Yun [-- Attachment #1.1: Type: text/plain, Size: 9715 bytes --] Jiewen, I don’t think AP need to validate everyting. BSP should make sure CR3/GDT/IDT corrently firstly. Othersize, everything does not make sense. For CR3 case, if we assume CR3 above 4GB space is legal for BSP (If there are any limitation on it, please corrent me) but the current CPU AP wakeup method does not allow CR3 above 4GB space, this maybe the CPU driver’s bug or implementation limitation. The key is that CR3 above 4GB is legal or not. If we think this is bug, we need to enhance CPU driver to fix it. If we think this is one limiation, we need to validate the CR3 value and tell the caller. Jeff 发件人: Yao, Jiewen<mailto:jiewen.yao@intel.com> 发送时间: 2020年9月4日 16:07 收件人: devel@edk2.groups.io<mailto:devel@edk2.groups.io>; vanjeff_919@hotmail.com<mailto:vanjeff_919@hotmail.com>; Laszlo Ersek<mailto:lersek@redhat.com>; Dong, Eric<mailto:eric.dong@intel.com>; Ni, Ray<mailto:ray.ni@intel.com> 抄送: Lou, Yun<mailto:yun.lou@intel.com> 主题: RE: 回复: [edk2-devel] [PATCH v2] UefiCpuPkg/MpInitLib: Add check for CR3/GDT/IDT. When we say “validate”, we need get clear on what is the contract between caller and callee, and what is the expectation of the validation. For example, in this case, the validation is limited to 4G or not 4G. Why? This function does not verify following, why? 1. if the GDT table is valid. 2. if the IDT table is valid 3. if the exception handler is valid 4. if the timer handler still works 5. if the page table is valid 6. if the page table is 1:1 mapping 7. if the page table still enforce the expected protection, such as RO, NX 8. …… If an application creates a crazy state, CpuDxe may pass the validation with below 4G page table, but still fail to wake up APs. If it is the app’s responsibility to ensure the system in good state, the validation is unnecessary. If it is the CpuDxe’s responsibility to ensure the system in good state, the validation is insufficient. I think we should wait. I am working with Eric to collect the requirement on why test case is designed in this way. DebugAgentDxe is a good case. It is for debug purpose. I believe there must be contract between CPU driver and DebugAgentDxe that which status DebugAgentDxe may modify and which state DebugAgentDxe may not. It is DebugAgentDxe’s responsibility to ensure the new system state is correct and compatible with the CPU driver. With the contract, I don’t think CPU driver need validate the system state changed by DebugAgentDxe. If DebugAgentDxe put system in a wrong state, CPUDriver has no chance to run. From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Fan Jeff Sent: Friday, September 4, 2020 3:32 PM To: Laszlo Ersek <lersek@redhat.com>; devel@edk2.groups.io; Dong, Eric <eric.dong@intel.com>; Ni, Ray <ray.ni@intel.com> Cc: Lou, Yun <yun.lou@intel.com> Subject: 回复: 回复: [edk2-devel] [PATCH v2] UefiCpuPkg/MpInitLib: Add check for CR3/GDT/IDT. Laszlo, Why sync the BSP’s CR3/GDT/IDT values for AP when AP wakes up instead of using old cached BSP’s CR3/GDT/IDT values when CPU driver initiallly dispatched is that we CANNOT assume original values are still valid during POST phase. On this senario, BSP’s CR3/GDT/IDT are just like input parameters for one function. Validating them are necessary. For example, DebugAgentDxe driver may be loaded in UEFI shell to setup source level debugging enviroment of EDKII debugger tools. It may setup new IDT space. Jeff 发件人: Laszlo Ersek<mailto:lersek@redhat.com> 发送时间: 2020年9月4日 14:58 收件人: Fan Jeff<mailto:vanjeff_919@hotmail.com>; devel@edk2.groups.io<mailto:devel@edk2.groups.io>; eric.dong@intel.com<mailto:eric.dong@intel.com>; Ni, Ray<mailto:ray.ni@intel.com> 抄送: Lou, Yun<mailto:yun.lou@intel.com> 主题: Re: 回复: [edk2-devel] [PATCH v2] UefiCpuPkg/MpInitLib: Add check for CR3/GDT/IDT. On 09/04/20 04:18, Fan Jeff wrote: > Laszlo & Eric, > > Introducing one new PCD to handle such rare test case is too heavy. I think We could do validating CR3/GDT/IDT space < 4GB address always in MpInitLib. I disagree. What the UEFI application does (interfere with GDT / IDT / CR3 placement) is invalid. It changes system properties under the feet of platform DXE drivers. UEFI applications are supposed to be written against public protocols and services in the UEFI spec (and maybe in the PI spec). If this application is a test application that purposely massages low-level system properties, that's fine; but then, if we change core edk2 components to be somewhat compatible with this application, then we should make sure that platforms that do not care about this specific use case do not suffer a performance hit or a code complexity hit. What I could accept, under your proposal, is the following: add three ASSERT()s to FillExchangeInfoData(), where we fetch the IDTR / GDTR / CR3 anyway. This would be fine because it only expresses existing assumptions / requirements. However, my understanding is that this would not solve Eric's problem. The system would hang -- in DEBUG / NOOPT builds -- or crash -- in a RELEASE build -- just the same as before. Now, *if* FillExchangeInfoData() is currently *wrong* to have these 32-bit assumptions, because edk2 modules themselves can break those assumptions (without the custom UEFI application), then we have a more serious problem. But for that problem, just "checking and rejecting" is not a sufficient solution, regardless of how and where we check and reject. Thanks Laszlo > > Jeff > > 发件人: Dong, Eric<mailto:eric.dong@intel.com> > 发送时间: 2020年9月4日 10:01 > 收件人: Ni, Ray<mailto:ray.ni@intel.com>; devel@edk2.groups.io<mailto:devel@edk2.groups.io<mailto:devel@edk2.groups.io%3cmailto:devel@edk2.groups.io>>; lersek@redhat.com<mailto:lersek@redhat.com> > 抄送: Lou, Yun<mailto:yun.lou@intel.com> > 主题: Re: [edk2-devel] [PATCH v2] UefiCpuPkg/MpInitLib: Add check for CR3/GDT/IDT. > > I guess Laszlo think this check is not always needed, just used for this special shell application case. He wants to use default FALSE to always ignore this check and make code logic clear. > > Thanks, > Eric > > From: Ni, Ray <ray.ni@intel.com<mailto:ray.ni@intel.com>> > Sent: Friday, September 4, 2020 9:34 AM > To: devel@edk2.groups.io<mailto:devel@edk2.groups.io>; lersek@redhat.com<mailto:lersek@redhat.com>; Dong, Eric <eric.dong@intel.com<mailto:eric.dong@intel.com>> > Cc: Lou, Yun <yun.lou@intel.com<mailto:yun.lou@intel.com>> > Subject: Re: [edk2-devel] [PATCH v2] UefiCpuPkg/MpInitLib: Add check for CR3/GDT/IDT. > > Why do we need a new PCD to control such check? Under what circumstance the PCD is false? > We may need to move such check out of MpLib.c. Because when bps runs at 32bit mode, AP doesn’t need to switch to long mode, such check is not needed and also always passes. > > We should not assume PEI runs at 32 bit mode. > > > 发件人: devel@edk2.groups.io<mailto:devel@edk2.groups.io<mailto:devel@edk2.groups.io%3cmailto:devel@edk2.groups.io>> <devel@edk2.groups.io<mailto:devel@edk2.groups.io<mailto:devel@edk2.groups.io%3cmailto:devel@edk2.groups.io>>> 代表 Laszlo Ersek <lersek@redhat.com<mailto:lersek@redhat.com<mailto:lersek@redhat.com%3cmailto:lersek@redhat.com>>> > 发送时间: Friday, September 4, 2020 3:55:47 AM > 收件人: Dong, Eric <eric.dong@intel.com<mailto:eric.dong@intel.com<mailto:eric.dong@intel.com%3cmailto:eric.dong@intel.com>>>; devel@edk2.groups.io<mailto:devel@edk2.groups.io<mailto:devel@edk2.groups.io%3cmailto:devel@edk2.groups.io>> <devel@edk2.groups.io<mailto:devel@edk2.groups.io<mailto:devel@edk2.groups.io%3cmailto:devel@edk2.groups.io>>> > 抄送: Ni, Ray <ray.ni@intel.com<mailto:ray.ni@intel.com<mailto:ray.ni@intel.com%3cmailto:ray.ni@intel.com>>> > 主题: Re: [edk2-devel] [PATCH v2] UefiCpuPkg/MpInitLib: Add check for CR3/GDT/IDT. > > On 09/03/20 21:00, Laszlo Ersek wrote: > >> (10) More importantly, ValidCR3GdtIdtCheck() should not be called in the >> Worker functions for StartupAllAPs, StartupThisAP, SwitchBSP, and >> EnableDisableAP, in "UefiCpuPkg/Library/MpInitLib/MpLib.c". >> >> Instead, the calls should be made in the DXE instance of the library >> ("UefiCpuPkg/Library/MpInitLib/DxeMpLib.c"), at the very top of the >> functions: >> >> - MpInitLibStartupAllAPs >> - MpInitLibStartupThisAP >> - MpInitLibSwitchBSP >> - MpInitLibEnableDisableAP >> >> Here's why: >> >> (a) The symptom does not affect the PEI phase -- by the time the UEFI >> application is executed, the PEI phase has ended; there's no need to >> modify the PEI instance of the library. >> >> (b) The currently proposed failure exits are too late. For example, in >> the SwitchBSPWorker() function, by the time we exit, we have called >> DisableApicTimerInterrupt(), SaveAndDisableInterrupts(), and >> DisableLvtInterrupts() -- and the error path does not restore the >> original environment. >> >> (c) According to the PI spec (v1.7), the StartupAllAPs(), >> StartupThisAP(), SwitchBSP(), EnableDisableAP() member functions of >> EFI_MP_SERVICES_PROTOCOL may only be called on the (current) BSP. >> Because of this, it is OK to call ValidCR3GdtIdtCheck() as the very >> first action in the above-listed DxeMpLib functions. >> >> (Assuming the protocol members are called from an AP, and consequently >> we check CR3 / GDTR / IDTR on the AP (and not on the BSP), that's the >> *caller's* fault, per spec!) > > This means we can move the ValidCr3GdtIdtCheck() function to > "DxeMpLib.c", and it is not necessary to modify "MpLib.h". > > Thanks > Laszlo > > [-- Attachment #1.2: Type: text/html, Size: 24085 bytes --] [-- Attachment #2: 154E6E9E578E47869D1F0A70DF84BCF0.png --] [-- Type: image/png, Size: 144 bytes --] ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: 回复: 回复: [edk2-devel] [PATCH v2] UefiCpuPkg/MpInitLib: Add check for CR3/GDT/IDT. 2020-09-04 7:32 ` 回复: " Fan Jeff 2020-09-04 8:06 ` Yao, Jiewen @ 2020-09-04 8:23 ` Laszlo Ersek 1 sibling, 0 replies; 6+ messages in thread From: Laszlo Ersek @ 2020-09-04 8:23 UTC (permalink / raw) To: Fan Jeff, devel@edk2.groups.io, eric.dong@intel.com, Ni, Ray; +Cc: Lou, Yun On 09/04/20 09:32, Fan Jeff wrote: > Laszlo, > > Why sync the BSP's CR3/GDT/IDT values for AP when AP wakes up instead > of using old cached BSP's CR3/GDT/IDT values when CPU driver > initiallly dispatched is that we CANNOT assume original values are > still valid during POST phase. > > On this senario, BSP's CR3/GDT/IDT are just like input parameters for > one function. Validating them are necessary. > > For example, DebugAgentDxe driver may be loaded in UEFI shell to setup > source level debugging enviroment of EDKII debugger tools. It may > setup new IDT space. Then DebugAgentDxe should be changed to allocate the new IDT in the 32-bit address space. I don't think it's acceptable that loading DebugAgentDxe from the UEFI shell may or may not render the MP services protocol unusable. What if the programmer wants to debug something related to MP services? "I've loaded DebugAgentDxe, but now I cannot start the payload I want to debug." As far as I can see, "SourceLevelDebugPkg/Library/DebugAgent/DxeDebugAgent/DxeDebugAgentLib.c" uses the static variable "mIdtEntryTable" as IDT. I think it should be possible to replace "mIdtEntryTable" with a dynamically allocated object. The allocation should be restricted to 32-bit. It should be possible to perform the allocation very early (perhaps in the library constructor). Again, I'm OK with adding ASSERT()s to FillExchangeInfoData(). If IDT / GDT / CR3 are out of 32-bit address space, then that's a programming error, or a platform misconfiguration. It's not something we should try to dynamically recover from. The MP services protocol implementation may not expect that the CR3/GDT/IDT remain unchanged on the BSP during the DXE/BDS phases, but it does expect them to remain under 4GB. - A UEFI driver or app must not break this assumption at all, because a UEFI driver or app has no business messing with these artifacts. - Whereas a DXE driver (such as DebugAgentDxe), exactly because it is part of the platform firmware, is expected to collaborate with CpuDxe / MpInitLib, and to satisfy the invariants. Thanks, Laszlo ^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2020-09-04 12:09 UTC | newest] Thread overview: 6+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- [not found] <163188258B195C29.8972@groups.io> 2020-09-04 11:17 ` 回复: 回复: [edk2-devel] [PATCH v2] UefiCpuPkg/MpInitLib: Add check for CR3/GDT/IDT Fan Jeff 2020-09-04 11:48 ` Yao, Jiewen 2020-09-04 12:08 ` Laszlo Ersek 2020-09-03 15:11 Dong, Eric 2020-09-03 19:00 ` Laszlo Ersek 2020-09-03 19:55 ` Laszlo Ersek 2020-09-04 1:34 ` [edk2-devel] " Ni, Ray 2020-09-04 2:00 ` Dong, Eric 2020-09-04 2:18 ` 回复: " vanjeff_919 2020-09-04 6:58 ` Laszlo Ersek 2020-09-04 7:32 ` 回复: " Fan Jeff 2020-09-04 8:06 ` Yao, Jiewen 2020-09-04 8:43 ` 回复: " Fan Jeff 2020-09-04 8:23 ` Laszlo Ersek
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox