Re: [edk2-devel] [PATCH] UefiCpuPkg/MpInitLib: Add check for CR3/GDT/IDT.
On 09/03/20 17:21, Dong, Eric wrote: > - modify the following functions in MpInitLib: > > - MpInitLibStartupAllAPs > - MpInitLibStartupThisAP > - MpInitLibSwitchBSP > - MpInitLibEnableDisableAP > [Eric] I found above 4 API need to wake up AP to do the task, so I add code > to check the CR3/GDT/IDT. > Below 3 API does not need to wake up AP, so I don’t add the check. > > - MpInitLibGetNumberOfProcessors > - MpInitLibGetProcessorInfo > - MpInitLibWhoAmI That's even better, thanks! Laszlo -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#65010): https://edk2.groups.io/g/devel/message/65010 Mute This Topic: https://groups.io/mt/76573401/21656 Group Owner: devel+ow...@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com] -=-=-=-=-=-=-=-=-=-=-=-
Re: [edk2-devel] [PATCH] UefiCpuPkg/MpInitLib: Add check for CR3/GDT/IDT.
Hi Laszlo, Thanks for your comments, I send out v2 change. I agree with you suggest adding PCD to control this check. Detail see v2 change. Add other comments inline below. From: Laszlo Ersek Sent: Thursday, September 3, 2020 3:59 PM To: Dong, Eric ; devel@edk2.groups.io Cc: Ni, Ray Subject: Re: [edk2-devel] [PATCH] UefiCpuPkg/MpInitLib: Add check for CR3/GDT/IDT. On 09/03/20 03:47, Dong, Eric wrote: > Hi Laszlo, > > Thanks for your detail review and good comments, add my reply in > below. > > This issue was reported by tester. They use a shell application to do > the test. In the test, it first moves the page table to above 4G range > then calls StartUpThisAp to let AP run the test procedure. The system > will hang during the test. > > Add more comments in below inline. Thanks. Let me summarize my understanding: (1) During normal boot, and normal MP services PPI usage, and normal MP services protocol usage, there is no issue. [Eric] Correct. (2) Right now, we have not identified the exact edk2 core modules and locations that are responsible for allocating the IDT / GDT / page tables. [Eric] I don’t check the IDT/GDT yet. For page table, it created by DxeIpl driver and used for later boot phase. Nonetheless, the allocations are all placed in the 32-bit address space, and so there is no problem with AP startup, during normal usage (see point (1)). [Eric] Correct. (3) There is a UEFI shell application that isn't more closely identified in this discussion. It first moves at least one of the IDT / GDT / page tables above 4GB, and then calls some member functions of the MP services protocol. This causes a hang, experienced during the execution of the UEFI shell application. [Eric] Correct. (4) The present patch recognizes the issue in FillExchangeInfoData(), and returns an error. In the relevant use case (UEFI shell application), this causes the called MP services protocol member function to fail, synchronously. This means the application still doesn't work, but there is no hang at least. [Eric] Correct. Is my understanding correct? If it is, then I have the following comments: - Please file a TianoCore BZ for this issue, and capture the use case in it (= UEFI shell application that changes the IDT / GDT / page tables base). Please feel free to copy parts of the above description, if you think that's useful. - I'm quite doubtful that the use case is valid, in the first place. A UEFI application is supposed to consume the services described in the UEFI specification. Messing with the page tables is something that a UEFI application should *not* do, in my opinion. Such page table manipulation is expected to interfere with various DXE drivers in the platform firmware. - Another comment on the UEFI shell application, and the present patch, is that their *combination* will still break ExitBootServices(). Assume that the patch is applied, and the UEFI shell application is invoked. The application now fails gracefully, and exits. Then we attempt to boot an OS (this is a valid thing to do). Because the application moved the IDT / GDT / page tables "out of range", MpInitChangeApLoopCallback() will do the wrong thing. - Most importantly: in MpInitLib, there is a *large* amount of call sites, and a large number of call paths that lead to WakeUpAP(), and ultimately to FillExchangeInfoData(). This means that changing the return type of FillExchangeInfoData() from VOID to EFI_STATUS has a "ripple effect" -- many call paths would have to deal with error checking, error propagation, and resource release (!!!) along those error paths. - For example, your current patch leaks resources in WakeUpAP(), when FillExchangeInfoData() fails -- see AllocateResetVector() and AllocateSevEsAPMemory(). - For another example, your current patch does not handle several WakeUpAP() call sites, such as the ones in ResetProcessorToIdleState() and CheckAllAPs(). Whereas in reality, from the applications point of view, we only need the MP services protocol member functions to fail cleanly. Therefore we should address this problem *early*; that is, *much less deep* in the call stack. I suggest the following: - introduce a feature PCD (default value FALSE) - modify the following functions in MpInitLib: - MpInitLibStartupAllAPs - MpInitLibStartupThisAP - MpInitLibSwitchBSP - MpInitLibEnableDisableAP [Eric] I found above 4 API need to wake up AP to do the task, so I add code to check the CR3/GDT/IDT. Below 3 API does not need to wake up AP, so I don’t add the check. - MpInitLibGetNumberOfProcessors - MpInitLibGetProcessorInfo - MpInitLibWhoAmI - each modified function should check the feature PCD *very early*. If the PCD is true, then the function should pre-emptively verify the IDT / GDT / root page table location. If any on
Re: [edk2-devel] [PATCH] UefiCpuPkg/MpInitLib: Add check for CR3/GDT/IDT.
On 09/03/20 03:47, Dong, Eric wrote: > Hi Laszlo, > > Thanks for your detail review and good comments, add my reply in > below. > > This issue was reported by tester. They use a shell application to do > the test. In the test, it first moves the page table to above 4G range > then calls StartUpThisAp to let AP run the test procedure. The system > will hang during the test. > > Add more comments in below inline. Thanks. Let me summarize my understanding: (1) During normal boot, and normal MP services PPI usage, and normal MP services protocol usage, there is no issue. (2) Right now, we have not identified the exact edk2 core modules and locations that are responsible for allocating the IDT / GDT / page tables. Nonetheless, the allocations are all placed in the 32-bit address space, and so there is no problem with AP startup, during normal usage (see point (1)). (3) There is a UEFI shell application that isn't more closely identified in this discussion. It first moves at least one of the IDT / GDT / page tables above 4GB, and then calls some member functions of the MP services protocol. This causes a hang, experienced during the execution of the UEFI shell application. (4) The present patch recognizes the issue in FillExchangeInfoData(), and returns an error. In the relevant use case (UEFI shell application), this causes the called MP services protocol member function to fail, synchronously. This means the application still doesn't work, but there is no hang at least. Is my understanding correct? If it is, then I have the following comments: - Please file a TianoCore BZ for this issue, and capture the use case in it (= UEFI shell application that changes the IDT / GDT / page tables base). Please feel free to copy parts of the above description, if you think that's useful. - I'm quite doubtful that the use case is valid, in the first place. A UEFI application is supposed to consume the services described in the UEFI specification. Messing with the page tables is something that a UEFI application should *not* do, in my opinion. Such page table manipulation is expected to interfere with various DXE drivers in the platform firmware. - Another comment on the UEFI shell application, and the present patch, is that their *combination* will still break ExitBootServices(). Assume that the patch is applied, and the UEFI shell application is invoked. The application now fails gracefully, and exits. Then we attempt to boot an OS (this is a valid thing to do). Because the application moved the IDT / GDT / page tables "out of range", MpInitChangeApLoopCallback() will do the wrong thing. - Most importantly: in MpInitLib, there is a *large* amount of call sites, and a large number of call paths that lead to WakeUpAP(), and ultimately to FillExchangeInfoData(). This means that changing the return type of FillExchangeInfoData() from VOID to EFI_STATUS has a "ripple effect" -- many call paths would have to deal with error checking, error propagation, and resource release (!!!) along those error paths. - For example, your current patch leaks resources in WakeUpAP(), when FillExchangeInfoData() fails -- see AllocateResetVector() and AllocateSevEsAPMemory(). - For another example, your current patch does not handle several WakeUpAP() call sites, such as the ones in ResetProcessorToIdleState() and CheckAllAPs(). Whereas in reality, from the applications point of view, we only need the MP services protocol member functions to fail cleanly. Therefore we should address this problem *early*; that is, *much less deep* in the call stack. I suggest the following: - introduce a feature PCD (default value FALSE) - modify the following functions in MpInitLib: - MpInitLibGetNumberOfProcessors - MpInitLibGetProcessorInfo - MpInitLibStartupAllAPs - MpInitLibStartupThisAP - MpInitLibSwitchBSP - MpInitLibEnableDisableAP - MpInitLibWhoAmI - each modified function should check the feature PCD *very early*. If the PCD is true, then the function should pre-emptively verify the IDT / GDT / root page table location. If any one of those objects is outside of the 32-bit address space, then the function should fail immediately. - We need to consider the event handlers in DxeMpInitLib: - CheckApsStatus() is not a problem, because the above short-circuits in the public MpInitLib functions will guarantee that "mStopCheckAllApsStatus" is always TRUE. - For exit-boot-services and legacy-boot, we need to modify MpInitChangeApLoopCallback() however. MpInitChangeApLoopCallback() should do the same as the above-listed functions (check the PCD, check the IDT / GDT / root page table), and if one of them is above 4GB, then MpInitChangeApLoopCallback() should hang *hard* -- call CpuDeadLoop() --, even in RELEASE builds. This is because the UEFI application in question
Re: [edk2-devel] [PATCH] UefiCpuPkg/MpInitLib: Add check for CR3/GDT/IDT.
Hi Laszlo, Thanks for your detail review and good comments, add my reply in below. This issue was reported by tester. They use a shell application to do the test. In the test, it first moves the page table to above 4G range then calls StartUpThisAp to let AP run the test procedure. The system will hang during the test. Add more comments in below inline. From: Laszlo Ersek mailto:ler...@redhat.com>> Sent: Wednesday, September 2, 2020 3:43 PM To: devel@edk2.groups.io<mailto:devel@edk2.groups.io>; Dong, Eric mailto:eric.d...@intel.com>> Cc: Ni, Ray mailto:ray...@intel.com>> Subject: Re: [edk2-devel] [PATCH] UefiCpuPkg/MpInitLib: Add check for CR3/GDT/IDT. Hi Eric, On 09/02/20 02:43, Dong, Eric wrote: > 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. > > Signed-off-by: Eric Dong mailto:eric.d...@intel.com>> > Cc: Ray Ni mailto:ray...@intel.com>> > Cc: Laszlo Ersek mailto:ler...@redhat.com>> > --- > UefiCpuPkg/Library/MpInitLib/DxeMpLib.c | 8 +- > UefiCpuPkg/Library/MpInitLib/MpLib.c| 108 +++- > UefiCpuPkg/Library/MpInitLib/MpLib.h| 6 +- > 3 files changed, 97 insertions(+), 25 deletions(-) (1) This is not for edk2-stable202008, correct? [Eric] Yes, just a bug fix for the issue I received recently. (2) If I understand correctly, this patch does not solve the problem when any one of the IDT, GDT, and CR3, are out of 32-bit address space. Instead, the patch makes the failure symptoms more graceful. Is that correct? [Eric] yes, current result is the system hang, I just add error handling to avoid hang. If so, can you explain in the commit message what happens without the patch, versus with the patch, when the IDT / GDT / CR3 are out of 32-bit address space? [Eric] got it, will include it in next version patch. Like, if we abandon MpInitChangeApLoopCallback() mid-way, then (AIUI) the AP "pen" (HLT loop) will not be relocated to reserved memory at ExitBootServces(). I don't think that simply giving up can end well for the OS! [Eric] agree. I don’t find a good way to handle it, so I add an error console log In it. I will also add “ASSERT (FALSE)” code to highlight the error. (3) Can you remind us in the commit message where the IDT / GDT / page tables are actually allocated? That is, can you please name the component that is usually responsible for keeping the allocations in the 32-bit address space? And once we know where the IDT / GDT / page tables come from -- shouldn't we rather modify those modules, to allocate IDT / GDT / page tables in the 32-bit address space? [Eric] This issue trigged by a shell application, so I can’t provide the module or driver that cause this failure. More below: > diff --git a/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c > b/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c > index 2c00d72dde..27f12a75a8 100644 > --- a/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c > +++ b/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c > @@ -393,13 +393,19 @@ MpInitChangeApLoopCallback ( >) > { >CPU_MP_DATA *CpuMpData; > + EFI_STATUSStatus; > >CpuMpData = GetCpuMpData (); >CpuMpData->PmCodeSegment = GetProtectedModeCS (); >CpuMpData->Pm16CodeSegment = GetProtectedMode16CS (); >CpuMpData->ApLoopMode = PcdGet8 (PcdCpuApLoopMode); >mNumberToFinish = CpuMpData->CpuCount - 1; > - WakeUpAP (CpuMpData, TRUE, 0, RelocateApLoop, NULL, TRUE); > + Status = WakeUpAP (CpuMpData, TRUE, 0, RelocateApLoop, NULL, TRUE); > + if (EFI_ERROR (Status)) { > +DEBUG ((DEBUG_ERROR, "ERROR :: %a() Change Ap Loop Mode failed!\n", > __FUNCTION__)); > +return; > + } > + >while (mNumberToFinish > 0) { > CpuPause (); >} > diff --git a/UefiCpuPkg/Library/MpInitLib/MpLib.c > b/UefiCpuPkg/Library/MpInitLib/MpLib.c > index 07426274f6..21b17a7b40 100644 > --- a/UefiCpuPkg/Library/MpInitLib/MpLib.c > +++ b/UefiCpuPkg/Library/MpInitLib/MpLib.c > @@ -470,7 +470,7 @@ GetProcessorNumber ( > >@return CPU count detected > **/ > -UINTN > +EFI_STATUS > CollectProcessorCount ( >IN CPU_MP_DATA *CpuMpData >) > @@ -478,12 +478,17 @@ CollectProcessorCount ( >UINTN Index; >CPU_INFO_IN_HOB*CpuInfoInHob; >BOOLEANX2Apic; > + EFI_STATUS
Re: [edk2-devel] [PATCH] UefiCpuPkg/MpInitLib: Add check for CR3/GDT/IDT.
Hi Eric, On 09/02/20 02:43, Dong, Eric wrote: > 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. > > Signed-off-by: Eric Dong > Cc: Ray Ni > Cc: Laszlo Ersek > --- > UefiCpuPkg/Library/MpInitLib/DxeMpLib.c | 8 +- > UefiCpuPkg/Library/MpInitLib/MpLib.c| 108 +++- > UefiCpuPkg/Library/MpInitLib/MpLib.h| 6 +- > 3 files changed, 97 insertions(+), 25 deletions(-) (1) This is not for edk2-stable202008, correct? (2) If I understand correctly, this patch does not solve the problem when any one of the IDT, GDT, and CR3, are out of 32-bit address space. Instead, the patch makes the failure symptoms more graceful. Is that correct? If so, can you explain in the commit message what happens without the patch, versus with the patch, when the IDT / GDT / CR3 are out of 32-bit address space? Like, if we abandon MpInitChangeApLoopCallback() mid-way, then (AIUI) the AP "pen" (HLT loop) will not be relocated to reserved memory at ExitBootServces(). I don't think that simply giving up can end well for the OS! (3) Can you remind us in the commit message where the IDT / GDT / page tables are actually allocated? That is, can you please name the component that is usually responsible for keeping the allocations in the 32-bit address space? And once we know where the IDT / GDT / page tables come from -- shouldn't we rather modify those modules, to allocate IDT / GDT / page tables in the 32-bit address space? More below: > diff --git a/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c > b/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c > index 2c00d72dde..27f12a75a8 100644 > --- a/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c > +++ b/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c > @@ -393,13 +393,19 @@ MpInitChangeApLoopCallback ( >) > { >CPU_MP_DATA *CpuMpData; > + EFI_STATUSStatus; > >CpuMpData = GetCpuMpData (); >CpuMpData->PmCodeSegment = GetProtectedModeCS (); >CpuMpData->Pm16CodeSegment = GetProtectedMode16CS (); >CpuMpData->ApLoopMode = PcdGet8 (PcdCpuApLoopMode); >mNumberToFinish = CpuMpData->CpuCount - 1; > - WakeUpAP (CpuMpData, TRUE, 0, RelocateApLoop, NULL, TRUE); > + Status = WakeUpAP (CpuMpData, TRUE, 0, RelocateApLoop, NULL, TRUE); > + if (EFI_ERROR (Status)) { > +DEBUG ((DEBUG_ERROR, "ERROR :: %a() Change Ap Loop Mode failed!\n", > __FUNCTION__)); > +return; > + } > + >while (mNumberToFinish > 0) { > CpuPause (); >} > diff --git a/UefiCpuPkg/Library/MpInitLib/MpLib.c > b/UefiCpuPkg/Library/MpInitLib/MpLib.c > index 07426274f6..21b17a7b40 100644 > --- a/UefiCpuPkg/Library/MpInitLib/MpLib.c > +++ b/UefiCpuPkg/Library/MpInitLib/MpLib.c > @@ -470,7 +470,7 @@ GetProcessorNumber ( > >@return CPU count detected > **/ > -UINTN > +EFI_STATUS > CollectProcessorCount ( >IN CPU_MP_DATA *CpuMpData >) > @@ -478,12 +478,17 @@ CollectProcessorCount ( >UINTN Index; >CPU_INFO_IN_HOB*CpuInfoInHob; >BOOLEANX2Apic; > + EFI_STATUS Status; > >// >// Send 1st broadcast IPI to APs to wakeup APs >// >CpuMpData->InitFlag = ApInitConfig; > - WakeUpAP (CpuMpData, TRUE, 0, NULL, NULL, TRUE); > + Status = WakeUpAP (CpuMpData, TRUE, 0, NULL, NULL, TRUE); > + if (EFI_ERROR (Status)) { > +return Status; > + } > + >CpuMpData->InitFlag = ApInitDone; >ASSERT (CpuMpData->CpuCount <= PcdGet32 (PcdCpuMaxLogicalProcessorNumber)); >// > @@ -520,7 +525,11 @@ CollectProcessorCount ( > // > // Wakeup all APs to enable x2APIC mode > // > -WakeUpAP (CpuMpData, TRUE, 0, ApFuncEnableX2Apic, NULL, TRUE); > +Status = WakeUpAP (CpuMpData, TRUE, 0, ApFuncEnableX2Apic, NULL, TRUE); > +if (EFI_ERROR (Status)) { > + return Status; > +} > + > // > // Wait for all known APs finished > // > @@ -546,7 +555,7 @@ CollectProcessorCount ( > >DEBUG ((DEBUG_INFO, "MpInitLib: Find %d processors in system.\n", > CpuMpData->CpuCount)); > > - return CpuMpData->CpuCount; > + return EFI_SUCCESS; > } > > /** > @@ -990,7 +999,7 @@ WaitApWakeup ( >@param[in] CpuMpData Pointer to CPU MP Data > > **/ > -VOID > +EFI_STATUS > FillExchangeInfoData ( >IN CPU_MP_DATA *CpuMpData >) > @@ -1001,6 +1010,35 @@ FillExchangeInfoData ( >IA32_CR4 Cr4; > >ExchangeInfo = CpuMpData->MpCpuExchangeInfo; > + ExchangeInfo->Cr3 = AsmReadCr3 (); > + if
[edk2-devel] [PATCH] UefiCpuPkg/MpInitLib: Add check for CR3/GDT/IDT.
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. Signed-off-by: Eric Dong Cc: Ray Ni Cc: Laszlo Ersek --- UefiCpuPkg/Library/MpInitLib/DxeMpLib.c | 8 +- UefiCpuPkg/Library/MpInitLib/MpLib.c| 108 +++- UefiCpuPkg/Library/MpInitLib/MpLib.h| 6 +- 3 files changed, 97 insertions(+), 25 deletions(-) diff --git a/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c b/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c index 2c00d72dde..27f12a75a8 100644 --- a/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c +++ b/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c @@ -393,13 +393,19 @@ MpInitChangeApLoopCallback ( ) { CPU_MP_DATA *CpuMpData; + EFI_STATUSStatus; CpuMpData = GetCpuMpData (); CpuMpData->PmCodeSegment = GetProtectedModeCS (); CpuMpData->Pm16CodeSegment = GetProtectedMode16CS (); CpuMpData->ApLoopMode = PcdGet8 (PcdCpuApLoopMode); mNumberToFinish = CpuMpData->CpuCount - 1; - WakeUpAP (CpuMpData, TRUE, 0, RelocateApLoop, NULL, TRUE); + Status = WakeUpAP (CpuMpData, TRUE, 0, RelocateApLoop, NULL, TRUE); + if (EFI_ERROR (Status)) { +DEBUG ((DEBUG_ERROR, "ERROR :: %a() Change Ap Loop Mode failed!\n", __FUNCTION__)); +return; + } + while (mNumberToFinish > 0) { CpuPause (); } diff --git a/UefiCpuPkg/Library/MpInitLib/MpLib.c b/UefiCpuPkg/Library/MpInitLib/MpLib.c index 07426274f6..21b17a7b40 100644 --- a/UefiCpuPkg/Library/MpInitLib/MpLib.c +++ b/UefiCpuPkg/Library/MpInitLib/MpLib.c @@ -470,7 +470,7 @@ GetProcessorNumber ( @return CPU count detected **/ -UINTN +EFI_STATUS CollectProcessorCount ( IN CPU_MP_DATA *CpuMpData ) @@ -478,12 +478,17 @@ CollectProcessorCount ( UINTN Index; CPU_INFO_IN_HOB*CpuInfoInHob; BOOLEANX2Apic; + EFI_STATUS Status; // // Send 1st broadcast IPI to APs to wakeup APs // CpuMpData->InitFlag = ApInitConfig; - WakeUpAP (CpuMpData, TRUE, 0, NULL, NULL, TRUE); + Status = WakeUpAP (CpuMpData, TRUE, 0, NULL, NULL, TRUE); + if (EFI_ERROR (Status)) { +return Status; + } + CpuMpData->InitFlag = ApInitDone; ASSERT (CpuMpData->CpuCount <= PcdGet32 (PcdCpuMaxLogicalProcessorNumber)); // @@ -520,7 +525,11 @@ CollectProcessorCount ( // // Wakeup all APs to enable x2APIC mode // -WakeUpAP (CpuMpData, TRUE, 0, ApFuncEnableX2Apic, NULL, TRUE); +Status = WakeUpAP (CpuMpData, TRUE, 0, ApFuncEnableX2Apic, NULL, TRUE); +if (EFI_ERROR (Status)) { + return Status; +} + // // Wait for all known APs finished // @@ -546,7 +555,7 @@ CollectProcessorCount ( DEBUG ((DEBUG_INFO, "MpInitLib: Find %d processors in system.\n", CpuMpData->CpuCount)); - return CpuMpData->CpuCount; + return EFI_SUCCESS; } /** @@ -990,7 +999,7 @@ WaitApWakeup ( @param[in] CpuMpData Pointer to CPU MP Data **/ -VOID +EFI_STATUS FillExchangeInfoData ( IN CPU_MP_DATA *CpuMpData ) @@ -1001,6 +1010,35 @@ FillExchangeInfoData ( IA32_CR4 Cr4; ExchangeInfo = CpuMpData->MpCpuExchangeInfo; + ExchangeInfo->Cr3 = AsmReadCr3 (); + if (ExchangeInfo->Cr3 > 0x) { +// +// 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. +// Here add check for the CR3, GDT.Base and IDT.Base to not above 32 bits +// limitation. +// +return EFI_UNSUPPORTED; + } + + // + // Get the BSP's data of GDT and IDT + // + AsmReadGdtr ((IA32_DESCRIPTOR *) >GdtrProfile); + if (ExchangeInfo->GdtrProfile.Base > 0x) { +return EFI_UNSUPPORTED; + } + + AsmReadIdtr ((IA32_DESCRIPTOR *) >IdtrProfile); + if (ExchangeInfo->IdtrProfile.Base > 0x) { +return EFI_UNSUPPORTED; + } + ExchangeInfo->Lock= 0; ExchangeInfo->StackStart = CpuMpData->Buffer; ExchangeInfo->StackSize = CpuMpData->CpuApStackSize; @@ -1009,9 +1047,6 @@ FillExchangeInfoData ( ExchangeInfo->CodeSegment = AsmReadCs (); ExchangeInfo->DataSegment = AsmReadDs (); - - ExchangeInfo->Cr3 = AsmReadCr3 (); - ExchangeInfo->CFunction