From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) by ml01.01.org (Postfix) with ESMTP id CFBA51A1E96 for ; Fri, 29 Jul 2016 11:16:04 -0700 (PDT) Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by fmsmga103.fm.intel.com with ESMTP; 29 Jul 2016 11:16:06 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.28,440,1464678000"; d="scan'208";a="1016339477" Received: from jfan12-desk.ccr.corp.intel.com ([10.239.9.5]) by fmsmga001.fm.intel.com with ESMTP; 29 Jul 2016 11:16:03 -0700 From: Jeff Fan To: edk2-devel@ml01.01.org Cc: Michael Kinney , Feng Tian , Giri P Mudusuru , Laszlo Ersek Date: Sat, 30 Jul 2016 02:15:01 +0800 Message-Id: <1469816112-8200-36-git-send-email-jeff.fan@intel.com> X-Mailer: git-send-email 2.7.4.windows.1 In-Reply-To: <1469816112-8200-1-git-send-email-jeff.fan@intel.com> References: <1469816112-8200-1-git-send-email-jeff.fan@intel.com> Subject: [Patch v4 35/46] UefiCpuPkg/MpInitLib: Place APs in safe loop before hand-off to OS X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 29 Jul 2016 18:16:05 -0000 Register Exit Boot Service callback function MpInitExitBootServicesCallback() to place AP one safe loop before hand-off to OS. Allocated one reserved memory and copy the AsmRellocateApLoop() code into it. It could avoid the CPU Dxe driver (located in Boot Service data range) crashed after Exit Boot Service event. Place AP into the target Cx-State (specified by PcdCpuApTargetCstate) could save power if Monitor-mwait feature supported. In long mode, switch AP into protected mode could let AP not require page table when executing this safe loop. Page Table (located in Boot Service data range) may crashed after Exit Boot Service event. v3: 1. Rename *RellocateAp* to *RelocateAp* Cc: Michael Kinney Cc: Feng Tian Cc: Giri P Mudusuru Cc: Laszlo Ersek Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Jeff Fan --- UefiCpuPkg/Library/MpInitLib/DxeMpLib.c | 97 +++++++++++++++++++++++++++++++++ UefiCpuPkg/Library/MpInitLib/MpLib.h | 11 ++++ 2 files changed, 108 insertions(+) diff --git a/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c b/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c index 8d1854c..d34eb14 100644 --- a/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c +++ b/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c @@ -19,6 +19,7 @@ CPU_MP_DATA *mCpuMpData = NULL; EFI_EVENT mCheckAllApsEvent = NULL; +EFI_EVENT mMpInitExitBootServicesEvent = NULL; volatile BOOLEAN mStopCheckAllApsStatus = TRUE; /** @@ -183,6 +184,94 @@ CheckApsStatus ( } /** + Get Protected mode code segment from current GDT table. + + @returen Protected mode code segment value. +**/ +UINT16 +GetProtectedModeCS ( + VOID + ) +{ + IA32_DESCRIPTOR GdtrDesc; + IA32_SEGMENT_DESCRIPTOR *GdtEntry; + UINTN GdtEntryCount; + UINT16 Index; + + Index = (UINT16) -1; + AsmReadGdtr (&GdtrDesc); + GdtEntryCount = (GdtrDesc.Limit + 1) / sizeof (IA32_SEGMENT_DESCRIPTOR); + GdtEntry = (IA32_SEGMENT_DESCRIPTOR *) GdtrDesc.Base; + for (Index = 0; Index < GdtEntryCount; Index++) { + if (GdtEntry->Bits.L == 0) { + if (GdtEntry->Bits.Type > 8 && GdtEntry->Bits.L == 0) { + break; + } + } + GdtEntry++; + } + ASSERT (Index != -1); + return Index * 8; +} + +/** + Do sync on APs. + + @param[in, out] Buffer Pointer to private data buffer. +**/ +VOID +EFIAPI +RelocateApLoop ( + IN OUT VOID *Buffer + ) +{ + CPU_MP_DATA *CpuMpData; + BOOLEAN MwaitSupport; + ASM_RELOCATE_AP_LOOP AsmRelocateApLoopFunc; + + CpuMpData = GetCpuMpData (); + MwaitSupport = IsMwaitSupport (); + AsmRelocateApLoopFunc = (ASM_RELOCATE_AP_LOOP) (UINTN) Buffer; + AsmRelocateApLoopFunc (MwaitSupport, CpuMpData->ApTargetCState, CpuMpData->PmCodeSegment); + // + // It should never reach here + // + ASSERT (FALSE); +} + +/** + Callback function for ExitBootServices. + + @param[in] Event Event whose notification function is being invoked. + @param[in] Context The pointer to the notification function's context, + which is implementation-dependent. + +**/ +VOID +EFIAPI +MpInitExitBootServicesCallback ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + CPU_MP_DATA *CpuMpData; + VOID *ReservedApLoopFunc; + // + // Avoid APs access invalid buff data which allocated by BootServices, + // so we will allocate reserved data for AP loop code. + // + CpuMpData = GetCpuMpData (); + CpuMpData->PmCodeSegment = GetProtectedModeCS (); + CpuMpData->ApLoopMode = PcdGet8 (PcdCpuApLoopMode); + ReservedApLoopFunc = AllocateReservedCopyPool ( + CpuMpData->AddressMap.RelocateApLoopFuncSize, + CpuMpData->AddressMap.RelocateApLoopFuncAddress + ); + WakeUpAP (CpuMpData, TRUE, 0, RelocateApLoop, ReservedApLoopFunc); + DEBUG ((DEBUG_INFO, "MpInitExitBootServicesCallback() done!\n")); +} + +/** Initialize global data for MP support. @param[in] CpuMpData The pointer to CPU MP Data structure. @@ -214,6 +303,14 @@ InitMpGlobalData ( EFI_TIMER_PERIOD_MILLISECONDS (100) ); ASSERT_EFI_ERROR (Status); + Status = gBS->CreateEvent ( + EVT_SIGNAL_EXIT_BOOT_SERVICES, + TPL_CALLBACK, + MpInitExitBootServicesCallback, + NULL, + &mMpInitExitBootServicesEvent + ); + ASSERT_EFI_ERROR (Status); } /** diff --git a/UefiCpuPkg/Library/MpInitLib/MpLib.h b/UefiCpuPkg/Library/MpInitLib/MpLib.h index 47b8b54..9ba3f8b 100644 --- a/UefiCpuPkg/Library/MpInitLib/MpLib.h +++ b/UefiCpuPkg/Library/MpInitLib/MpLib.h @@ -495,6 +495,17 @@ MicrocodeDetect ( ); /** + Detect whether Mwait-monitor feature is supported. + + @retval TRUE Mwait-monitor feature is supported. + @retval FALSE Mwait-monitor feature is not supported. +**/ +BOOLEAN +IsMwaitSupport ( + VOID + ); + +/** Notify function on End Of PEI PPI. On S3 boot, this function will restore wakeup buffer data. -- 2.7.4.windows.1