What about adding this code to mStartupCodeTemplate and sending the APs there using the MP services?
Regardless of that, I think the C-based-asm would better fit in ApStartup.c. Why not just a cli-hlt loop? Maybe if the MP services were used then the separate counter goes away. How about 0 rather than 0x1234? Can you provide a nasm source block in a comment like in ApStartup.c? -Jordan On 2015-10-26 14:33:09, Laszlo Ersek wrote: > Our current callback puts the APs in wait-for-SIPI state, by sending them > an INIT IPI. This works fine as long as the APs are not woken between > ExitBootServices() and the time the runtime OS boots the APs. > > However, if a platform includes PiSmmCpuDxeSmm, and bases the runtime UEFI > services (like the variable services) on SMM and SMIs, then two problem > scenarios can be experienced: > > (a) On virtual platforms, the APs can be (spuriously?) woken by SMIs, > between ExitBootServices() and the runtime OS's AP boot; for example > by variable service calls. In this case the APs have no code to > continue executing after the RSM instruction, which causes them to > re-set. > > (b) On physical platforms, the APs might not wake from the wait-for-SIPI > state at all, causing performance (or functional) problems with > PiSmmCpuDxeSmm, dependent on the BSP/AP sync mode configured therein. > > Implement the following logic instead: > > - If there is no AP, there's no need for an ExitBootServices() callback. > > - Otherwise, reboot all APs with a minimal real-mode stub. Each AP shall > bump a shared counter atomically at first, then spiral into an infinite > HLT loop. This occurs regardless of what each AP has been doing at that > moment. > > - APs can wake from HLT due to an SMI easily. > > - The BSP in the ExitBootServices() callback will wait until all APs have > moved on to the stub. > > - Since we exit boot services time now with the original MP services > startup code abandoned by all APs, we can even allocate that startup > code in Boot Services Code type memory; only the new stub has to be > AcpiNVS. > > Cc: Chen Fan <[email protected]> > Cc: Jeff Fan <[email protected]> > Cc: Jordan Justen <[email protected]> > Cc: Michael Kinney <[email protected]> > Contributed-under: TianoCore Contribution Agreement 1.0 > Signed-off-by: Laszlo Ersek <[email protected]> > --- > > Notes: > So this would be option (2) from > <http://thread.gmane.org/gmane.comp.bios.edk2.devel/3357/focus=3403>. > With this patch in place, the AP reboots I had seen on TCG are gone. > > UefiCpuPkg/CpuDxe/ApStartup.c | 2 +- > UefiCpuPkg/CpuDxe/CpuMp.c | 84 > +++++++++++++++++++++++++++++++++++-------- > 2 files changed, 71 insertions(+), 15 deletions(-) > > diff --git a/UefiCpuPkg/CpuDxe/ApStartup.c b/UefiCpuPkg/CpuDxe/ApStartup.c > index 78fb26f..b8d736f 100644 > --- a/UefiCpuPkg/CpuDxe/ApStartup.c > +++ b/UefiCpuPkg/CpuDxe/ApStartup.c > @@ -382,7 +382,7 @@ PrepareAPStartupCode ( > StartAddress = BASE_1MB; > Status = gBS->AllocatePages ( > AllocateMaxAddress, > - EfiACPIMemoryNVS, > + EfiBootServicesCode, > EFI_SIZE_TO_PAGES (sizeof (*StartupCode)), > &StartAddress > ); > diff --git a/UefiCpuPkg/CpuDxe/CpuMp.c b/UefiCpuPkg/CpuDxe/CpuMp.c > index 04c2f1f..98976a1 100644 > --- a/UefiCpuPkg/CpuDxe/CpuMp.c > +++ b/UefiCpuPkg/CpuDxe/CpuMp.c > @@ -30,6 +30,33 @@ VOID *mApStackStart = 0; > volatile BOOLEAN mAPsAlreadyInitFinished = FALSE; > volatile BOOLEAN mStopCheckAllAPsStatus = TRUE; > > +#pragma pack (1) > +typedef struct { > + UINT8 MovAx; > + UINT16 AxValue; > + UINT8 MovDsAx[2]; > + UINT8 LockedWordCounterIncrement[6]; > + > + UINT8 Cli; > + UINT8 Hlt; > + UINT8 JmpToCli[2]; > + > + UINT16 WordCounter; > +} CPU_AP_HLT_LOOP; > +#pragma pack () > + > +STATIC CONST CPU_AP_HLT_LOOP mCpuApHltLoopTemplate = { > + 0xB8, 0x1234, // mov ax,0x1234 > + { 0x8E, 0xD8 }, // mov ds,ax > + { 0xF0, 0x3E, 0xFF, 0x06, 0x0F, 0x00 }, // lock inc word [ds:0xf] > + > + 0xFA, // cli @ offset 0xb > + 0xF4, // hlt > + { 0xEB, 0xFC }, // jmp short 0xb > + > + 0x0000 // WordCounter @ offset 0xf > +}; > + > EFI_MP_SERVICES_PROTOCOL mMpServicesTemplate = { > GetNumberOfProcessors, > GetProcessorInfo, > @@ -1659,11 +1686,31 @@ ExitBootServicesCallback ( > IN VOID *Context > ) > { > + CPU_AP_HLT_LOOP *CpuApHltLoop; > + UINT16 ApCount; > + > + CpuApHltLoop = Context; > + CopyMem (CpuApHltLoop, &mCpuApHltLoopTemplate, sizeof > mCpuApHltLoopTemplate); > + > // > - // Avoid APs access invalid buff datas which allocated by BootServices, > - // so we send INIT IPI to APs to let them wait for SIPI state. > + // Point DS via AX to the page where the routine has been allocated. > // > - SendInitIpiAllExcludingSelf (); > + CpuApHltLoop->AxValue = (UINT16)((UINTN)Context >> 4); > + DEBUG ((EFI_D_VERBOSE, "%a: %a: HLT loop routine at %04x:%04x\n", > + gEfiCallerBaseName, __FUNCTION__, CpuApHltLoop->AxValue, 0)); > + > + // > + // Force all APs to execute the HLT loop. Wait until they all enter the > code. > + // > + SendInitSipiSipiAllExcludingSelf ((UINT32)(UINTN)Context); > + > + ApCount = (UINT16)(mMpSystemData.NumberOfProcessors - 1); > + while (InterlockedCompareExchange16 ( > + &CpuApHltLoop->WordCounter, > + ApCount, > + ApCount) != ApCount) { > + CpuPause(); > + } > } > > /** > @@ -1691,9 +1738,10 @@ InitializeMpSupport ( > VOID > ) > { > - EFI_STATUS Status; > - MTRR_SETTINGS MtrrSettings; > - UINTN Timeout; > + EFI_STATUS Status; > + MTRR_SETTINGS MtrrSettings; > + UINTN Timeout; > + EFI_PHYSICAL_ADDRESS CpuApHltLoopAddress; > > gMaxLogicalProcessorNumber = (UINTN) PcdGet32 > (PcdCpuMaxLogicalProcessorNumber); > if (gMaxLogicalProcessorNumber < 1) { > @@ -1795,12 +1843,20 @@ InitializeMpSupport ( > } > } > > - Status = gBS->CreateEvent ( > - EVT_SIGNAL_EXIT_BOOT_SERVICES, > - TPL_CALLBACK, > - ExitBootServicesCallback, > - NULL, > - &mExitBootServicesEvent > - ); > - ASSERT_EFI_ERROR (Status); > + if (mMpSystemData.NumberOfProcessors > 1) { > + CpuApHltLoopAddress = BASE_1MB - 1; > + Status = gBS->AllocatePages (AllocateMaxAddress, EfiACPIMemoryNVS, > + EFI_SIZE_TO_PAGES (sizeof (CPU_AP_HLT_LOOP)), > + &CpuApHltLoopAddress); > + ASSERT_EFI_ERROR (Status); > + > + Status = gBS->CreateEvent ( > + EVT_SIGNAL_EXIT_BOOT_SERVICES, > + TPL_CALLBACK, > + ExitBootServicesCallback, > + (VOID *)(UINTN)CpuApHltLoopAddress, > + &mExitBootServicesEvent > + ); > + ASSERT_EFI_ERROR (Status); > + } > } > -- > 1.8.3.1 > _______________________________________________ edk2-devel mailing list [email protected] https://lists.01.org/mailman/listinfo/edk2-devel

