From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by spool.mail.gandi.net (Postfix) with ESMTPS id A09A2D800F6 for ; Tue, 25 Jul 2023 02:17:29 +0000 (UTC) DKIM-Signature: a=rsa-sha256; bh=xQFsokLFP3FSTFyH/tGU3B1h8stWCeAmUH5aZ5/vF3c=; c=relaxed/simple; d=groups.io; h=X-Received:X-Received:X-Received:X-Received:X-Received:X-Received:X-WM-Sender:X-Originating-IP:X-WM-AuthFlag:X-WM-AuthUser:From:To:Cc:References:In-Reply-To:Subject:Date:Message-ID:MIME-Version:Thread-Index:Precedence:List-Subscribe:List-Help:Sender:List-Id:Mailing-List:Delivered-To:Reply-To:List-Unsubscribe-Post:List-Unsubscribe:X-Gm-Message-State:Content-Type:Content-Transfer-Encoding:Content-Language; s=20140610; t=1690251448; v=1; b=skPfRA4SOPKvpFT6Fd3LES241rV8tk1fbLzJhXd1EKD+KDm2rsB7Pr4Y19bREzNJgkqeLQ7C sQ6Up6CWfiy2zBQh/uDegbdD7Or2Wh9vv7xWNIt107ZrRd6ccdYhF4hvInoEDqPJkpWY3099Pbc FSUGfZ0Un35pK3Zck+h56Qww= X-Received: by 127.0.0.2 with SMTP id p1ZKYY7687511xwIbdaw4SIR; Mon, 24 Jul 2023 19:17:28 -0700 X-Received: from zrleap.intel-email.com (zrleap.intel-email.com [114.80.218.36]) by mx.groups.io with SMTP id smtpd.web11.12045.1690251445418172863 for ; Mon, 24 Jul 2023 19:17:27 -0700 X-Received: from zrleap.intel-email.com (localhost [127.0.0.1]) by zrleap.intel-email.com (Postfix) with ESMTP id 83C14A32E015 for ; Tue, 25 Jul 2023 10:17:22 +0800 (CST) X-Received: from localhost (localhost [127.0.0.1]) by zrleap.intel-email.com (Postfix) with ESMTP id 6C433A32E011 for ; Tue, 25 Jul 2023 10:17:22 +0800 (CST) X-Received: from mail.byosoft.com.cn (mail.byosoft.com.cn [58.240.74.242]) by zrleap.intel-email.com (Postfix) with SMTP id 70C52A32DFEC for ; Tue, 25 Jul 2023 10:17:16 +0800 (CST) X-Received: from DESKTOPS6D0PVI ([58.246.60.130]) (envelope-sender ) by 192.168.6.13 with ESMTP for ; Tue, 25 Jul 2023 10:17:14 +0800 X-WM-Sender: gaoliming@byosoft.com.cn X-Originating-IP: 58.246.60.130 X-WM-AuthFlag: YES X-WM-AuthUser: gaoliming@byosoft.com.cn From: "gaoliming via groups.io" To: "'Kun Qin'" , Cc: "'Jian J Wang'" , "'Dandan Bi'" , "'Debkumar De'" , "'Catharine West'" , "'Mike Turner'" References: <20230720210729.774-1-kuqin12@gmail.com> <20230720210729.774-4-kuqin12@gmail.com> In-Reply-To: <20230720210729.774-4-kuqin12@gmail.com> Subject: =?UTF-8?B?W2VkazItZGV2ZWxdIOWbnuWkjTogW1BBVENIIHYxIDMvNF0gTWRlTW9kdWxlUGtnOiBQZWlNYWluOiBJbnRyb2R1Y2UgaW1wbGVtZW50YXRpb24gb2YgZGVsYXllZCBkaXNwYXRjaA==?= Date: Tue, 25 Jul 2023 10:17:16 +0800 Message-ID: <01b901d9be9e$21a964c0$64fc2e40$@byosoft.com.cn> MIME-Version: 1.0 Thread-Index: AQHmQqk72a+h6fM/RhcnPsN27NW3TwNcSvR8r5XTepA= Precedence: Bulk List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,gaoliming@byosoft.com.cn List-Unsubscribe-Post: List-Unsubscribe=One-Click List-Unsubscribe: X-Gm-Message-State: WCwnojzILf23EDKybM1SL6Pdx7686176AA= Content-Type: text/plain; charset="gb2312" Content-Transfer-Encoding: quoted-printable Content-Language: zh-cn X-GND-Status: LEGIT Authentication-Results: spool.mail.gandi.net; dkim=pass header.d=groups.io header.s=20140610 header.b=skPfRA4S; spf=pass (spool.mail.gandi.net: domain of bounce@groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce@groups.io; dmarc=none Kun:=20 I add my comments below.=20 > -----=D3=CA=BC=FE=D4=AD=BC=FE----- > =B7=A2=BC=FE=C8=CB: Kun Qin > =B7=A2=CB=CD=CA=B1=BC=E4: 2023=C4=EA7=D4=C221=C8=D5 5:07 > =CA=D5=BC=FE=C8=CB: devel@edk2.groups.io > =B3=AD=CB=CD: Jian J Wang ; Dandan Bi > ; Liming Gao ; > Debkumar De ; Catharine West > ; Mike Turner > =D6=F7=CC=E2: [PATCH v1 3/4] MdeModulePkg: PeiMain: Introduce implementat= ion of > delayed dispatch >=20 > REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3D4496 >=20 > This change adds the implementation that fits the needs and description > of PI spec defined Delayed Dispatch PPI in Pei Core. >=20 > The PPI would allow minimal delay for registered callbacks. As well as > allowing other functions to wait for GUIDed delayed dispatch callbacks. >=20 > Cc: Jian J Wang > Cc: Dandan Bi > Cc: Liming Gao > Cc: Debkumar De > Cc: Catharine West >=20 > Co-authored-by: Mike Turner > Signed-off-by: Kun Qin > --- > MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c | 353 > ++++++++++++++++++++ > MdeModulePkg/Core/Pei/PeiMain/PeiMain.c | 3 + > MdeModulePkg/Core/Pei/PeiMain.h | 76 +++++ > MdeModulePkg/Core/Pei/PeiMain.inf | 7 + > MdeModulePkg/MdeModulePkg.dec | 15 + > 5 files changed, 454 insertions(+) >=20 > diff --git a/MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c > b/MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c > index 5f32ebb560ae..50e59bdbe732 100644 > --- a/MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c > +++ b/MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c > @@ -3,12 +3,339 @@ >=20 >=20 > Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.
>=20 > (C) Copyright 2016 Hewlett Packard Enterprise Development LP
>=20 > +Copyright (c) Microsoft Corporation. >=20 > SPDX-License-Identifier: BSD-2-Clause-Patent >=20 >=20 >=20 > **/ >=20 >=20 >=20 > #include "PeiMain.h" >=20 >=20 >=20 > +/** >=20 > + DelayedDispatchDispatcher >=20 > + >=20 > + ayed Dispach cycle (ie one pass) through each entry, calling functions > when their >=20 > + e has expired. When UniqueId is specified, if there are any of the > specified entries >=20 > + the dispatch queue during dispatch, repeat the DelayedDispatch cycle. >=20 > + >=20 [Liming] Above comments are incomplete. Please update.=20 > + @param DelayedDispatchTable Pointer to dispatch table >=20 > + @param OPTIONAL UniqueId used to insure particular > time is met. >=20 > + >=20 > + @return BOOLEAN >=20 > +**/ >=20 > +BOOLEAN >=20 > +DelayedDispatchDispatcher ( >=20 > + IN DELAYED_DISPATCH_TABLE *DelayedDispatchTable, >=20 > + IN EFI_GUID *UniqueId OPTIONAL >=20 > + ); >=20 > + >=20 > +/** >=20 > + DelayedDispatch End of PEI callback function. Insure that all of the > delayed dispatch >=20 > + entries are complete before exiting PEI. >=20 > + >=20 > + @param[in] PeiServices - Pointer to PEI Services Table. >=20 > + @param[in] NotifyDesc - Pointer to the descriptor for the Notification > event that >=20 > + caused this function to execute. >=20 > + @param[in] Ppi - Pointer to the PPI data associated with thi= s > function. >=20 > + >=20 > + @retval EFI_STATUS - Always return EFI_SUCCESS >=20 > +**/ >=20 > +EFI_STATUS >=20 > +EFIAPI >=20 > +PeiDelayedDispatchOnEndOfPei ( >=20 > + IN EFI_PEI_SERVICES **PeiServices, >=20 > + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDesc, >=20 > + IN VOID *Ppi >=20 > + ); >=20 > + >=20 > +EFI_DELAYED_DISPATCH_PPI mDelayedDispatchPpi =3D > { PeiDelayedDispatchRegister, PeiDelayedDispatchWaitOnUniqueId }; >=20 > +EFI_PEI_PPI_DESCRIPTOR mDelayedDispatchDesc =3D { >=20 > + (EFI_PEI_PPI_DESCRIPTOR_PPI | > EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), >=20 > + &gEfiPeiDelayedDispatchPpiGuid, >=20 > + &mDelayedDispatchPpi >=20 > +}; >=20 > + >=20 > +EFI_PEI_NOTIFY_DESCRIPTOR mDelayedDispatchNotifyDesc =3D { >=20 > + EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | > EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST, >=20 > + &gEfiEndOfPeiSignalPpiGuid, >=20 > + PeiDelayedDispatchOnEndOfPei >=20 > +}; >=20 > + >=20 > +/** >=20 > + Helper function to look up DELAYED_DISPATCH_TABLE published in HOB. >=20 > + >=20 > + @return Pointer to DELAYED_DISPATCH_TABLE from HOB >=20 > +**/ >=20 > +DELAYED_DISPATCH_TABLE * >=20 > +GetDelayedDispatchTable ( >=20 > + VOID >=20 > + ) >=20 > +{ >=20 > + EFI_HOB_GUID_TYPE *GuidHob; >=20 > + >=20 > + GuidHob =3D GetFirstGuidHob (&gEfiDelayedDispatchTableGuid); >=20 > + if (NULL =3D=3D GuidHob) { >=20 > + DEBUG ((DEBUG_ERROR, "Delayed Dispatch PPI ERROR - Delayed > Dispatch Hob not available.\n")); >=20 > + ASSERT (FALSE); >=20 > + return NULL; >=20 > + } >=20 > + >=20 > + return (DELAYED_DISPATCH_TABLE *)GET_GUID_HOB_DATA (GuidHob); >=20 > +} >=20 > + >=20 > +/** >=20 > +Register a callback to be called after a minimum delay has occurred. >=20 > + >=20 > +This service is the single member function of the > EFI_DELAYED_DISPATCH_PPI >=20 > + >=20 > + @param[in] This Pointer to the EFI_DELAYED_DISPATCH_PPI > instance >=20 > + @param[in] Function Function to call back >=20 > + @param[in] Context Context data >=20 > + @param[in] UniqueId GUID for this Delayed Dispatch request. >=20 > + @param[in] Delay Delay interval >=20 > + >=20 > + @retval EFI_SUCCESS Function successfully loaded >=20 > + @retval EFI_INVALID_PARAMETER One of the Arguments is not > supported >=20 > + @retval EFI_OUT_OF_RESOURCES No more entries >=20 > + >=20 > +**/ >=20 > +EFI_STATUS >=20 > +EFIAPI >=20 > +PeiDelayedDispatchRegister ( >=20 > + IN EFI_DELAYED_DISPATCH_PPI *This, >=20 > + IN EFI_DELAYED_DISPATCH_FUNCTION Function, >=20 > + IN UINT64 Context, >=20 > + IN EFI_GUID *UniqueId OPTIONAL, >=20 > + IN UINT32 Delay >=20 > + ) >=20 > +{ >=20 > + DELAYED_DISPATCH_TABLE *DelayedDispatchTable; >=20 > + DELAYED_DISPATCH_ENTRY *Entry; >=20 > + >=20 > + // Check input parameters >=20 > + if ((NULL =3D=3D Function) || (Delay > FixedPcdGet32 > (PcdDelayedDispatchMaxDelayUs)) || (NULL =3D=3D This)) { >=20 > + DEBUG ((DEBUG_ERROR, "%a Invalid parameter\n", __func__)); >=20 > + return EFI_INVALID_PARAMETER; >=20 > + } >=20 > + >=20 > + // Get delayed dispatch table >=20 > + DelayedDispatchTable =3D GetDelayedDispatchTable (); >=20 > + if (NULL =3D=3D DelayedDispatchTable) { >=20 > + DEBUG ((DEBUG_ERROR, "%a Unable to locate dispatch table\n", > __func__)); >=20 > + return EFI_UNSUPPORTED; >=20 > + } >=20 > + >=20 > + // Check for available entry slots >=20 > + if (DelayedDispatchTable->Count >=3D FixedPcdGet32 > (PcdDelayedDispatchMaxEntries)) { >=20 > + ASSERT (DelayedDispatchTable->Count < FixedPcdGet32 > (PcdDelayedDispatchMaxEntries)); >=20 > + DEBUG ((DEBUG_ERROR, "%a Too many entries requested\n", > __func__)); >=20 > + return EFI_OUT_OF_RESOURCES; >=20 > + } >=20 > + >=20 > + Entry =3D > &(DelayedDispatchTable->Entry[DelayedDispatchTable->Count]); >=20 > + Entry->Function =3D Function; >=20 > + Entry->Context =3D Context; >=20 > + Entry->DispatchTime =3D GET_TIME_IN_US () + Delay; >=20 > + if (NULL !=3D UniqueId) { >=20 > + CopyGuid (&Entry->UniqueId, UniqueId); >=20 > + } else { >=20 > + ZeroMem (&Entry->UniqueId, sizeof (EFI_GUID)); >=20 > + } >=20 > + >=20 > + Entry->MicrosecondDelay =3D Delay; >=20 > + DelayedDispatchTable->Count++; >=20 > + >=20 > + DEBUG ((DEBUG_INFO, "%a Adding dispatch Entry\n", __func__)); >=20 > + DEBUG ((DEBUG_INFO, " Requested Delay =3D %d\n", Delay)); >=20 > + DEBUG ((DEBUG_INFO, " Trigger Time =3D %d\n", > Entry->DispatchTime)); >=20 > + DEBUG ((DEBUG_INFO, " Context =3D 0x%08lx\n", Entry->Context)); >=20 > + DEBUG ((DEBUG_INFO, " Function =3D %p\n", Entry->Function)); >=20 > + DEBUG ((DEBUG_INFO, " GuidHandle =3D %g\n", &(Entry->UniqueId))); >=20 > + >=20 > + if (0 =3D=3D Delay) { >=20 > + // Force early dispatch point >=20 > + DelayedDispatchDispatcher (DelayedDispatchTable, NULL); >=20 > + } >=20 > + >=20 > + return EFI_SUCCESS; >=20 > +} >=20 > + >=20 > +/** >=20 > + DelayedDispatchDispatcher >=20 > + >=20 > + ayed Dispach cycle (ie one pass) through each entry, calling functions > when their >=20 > + e has expired. When UniqueId is specified, if there are any of the > specified entries >=20 > + the dispatch queue during dispatch, repeat the DelayedDispatch cycle. >=20 > + >=20 > + @param DelayedDispatchTable Pointer to dispatch table >=20 > + @param OPTIONAL UniqueId used to insure particular > time is met. >=20 > + >=20 > + @return BOOLEAN >=20 > +**/ >=20 > +BOOLEAN >=20 > +DelayedDispatchDispatcher ( >=20 > + IN DELAYED_DISPATCH_TABLE *DelayedDispatchTable, >=20 > + IN EFI_GUID *UniqueId OPTIONAL >=20 > + ) >=20 > +{ >=20 > + BOOLEAN Dispatched; >=20 > + UINT32 TimeCurrent; >=20 > + UINT32 MaxDispatchTime; >=20 > + UINTN Index1; >=20 > + BOOLEAN UniqueIdPresent; >=20 > + DELAYED_DISPATCH_ENTRY *Entry; >=20 > + >=20 > + Dispatched =3D FALSE; >=20 > + UniqueIdPresent =3D TRUE; >=20 > + MaxDispatchTime =3D GET_TIME_IN_US () + FixedPcdGet32 > (PcdDelayedDispatchCompletionTimeoutUs); >=20 > + while ((DelayedDispatchTable->Count > 0) && (UniqueIdPresent)) { >=20 > + UniqueIdPresent =3D FALSE; >=20 > + DelayedDispatchTable->DispCount++; >=20 > + >=20 > + // If dispatching is messed up, clear DelayedDispatchTable and exit. >=20 > + TimeCurrent =3D GET_TIME_IN_US (); >=20 > + if (TimeCurrent > MaxDispatchTime) { >=20 > + DEBUG ((DEBUG_ERROR, "%a - DelayedDispatch Completion > timeout!\n", __func__)); >=20 > + ReportStatusCode ((EFI_ERROR_MAJOR | EFI_ERROR_CODE), > (EFI_SOFTWARE_PEI_CORE | EFI_SW_EC_ABORTED)); >=20 > + ASSERT (FALSE); >=20 > + DelayedDispatchTable->Count =3D 0; >=20 > + break; >=20 > + } >=20 > + >=20 > + // Check each entry in the table for possible dispatch >=20 > + for (Index1 =3D 0; Index1 < DelayedDispatchTable->Count;) { >=20 > + Entry =3D &(DelayedDispatchTable->Entry[Index1]); >=20 > + // If UniqueId is present, insure there is an additional check of the > table. >=20 > + if (NULL !=3D UniqueId) { >=20 > + if (CompareGuid (UniqueId, &Entry->UniqueId)) { >=20 > + UniqueIdPresent =3D TRUE; >=20 > + } >=20 > + } >=20 > + >=20 > + TimeCurrent =3D GET_TIME_IN_US (); >=20 > + if (TimeCurrent >=3D Entry->DispatchTime) { >=20 > + // Time expired, invoked the function >=20 > + DEBUG (( >=20 > + DEBUG_ERROR, >=20 > + "Delayed dispatch entry %d @ %p, Target=3D%d, Act=3D%d > Disp=3D%d\n", >=20 > + Index1, >=20 > + Entry->Function, >=20 > + Entry->DispatchTime, >=20 > + TimeCurrent, >=20 > + DelayedDispatchTable->DispCount >=20 > + )); >=20 > + Dispatched =3D TRUE; >=20 > + Entry->MicrosecondDelay =3D 0; >=20 > + Entry->Function ( >=20 > + &Entry->Context, >=20 > + &Entry->MicrosecondDelay >=20 > + ); >=20 > + DEBUG ((DEBUG_ERROR, "Delayed dispatch Function returned > delay=3D%d\n", Entry->MicrosecondDelay)); >=20 > + if (0 =3D=3D Entry->MicrosecondDelay) { >=20 > + // NewTime =3D 0 =3D delete this entry from the table >=20 > + DelayedDispatchTable->Count--; >=20 > + CopyMem (Entry, Entry+1, sizeof (DELAYED_DISPATCH_ENTRY) > * (DelayedDispatchTable->Count - Index1)); >=20 > + } else { >=20 > + if (Entry->MicrosecondDelay > FixedPcdGet32 > (PcdDelayedDispatchMaxDelayUs)) { >=20 > + DEBUG ((DEBUG_ERROR, "%a Illegal new delay %d > requested\n", __func__, Entry->MicrosecondDelay)); >=20 > + ASSERT (FALSE); >=20 > + Entry->MicrosecondDelay =3D FixedPcdGet32 > (PcdDelayedDispatchMaxDelayUs); >=20 > + } >=20 > + >=20 > + // NewTime !=3D 0 - update the time from us to Dispatch time >=20 > + Entry->DispatchTime =3D GET_TIME_IN_US () + > Entry->MicrosecondDelay; >=20 > + Index1++; >=20 > + } >=20 > + } else { >=20 > + Index1++; >=20 > + } >=20 > + } >=20 > + } >=20 > + >=20 > + return Dispatched; >=20 > +} >=20 > + >=20 > +/** >=20 > + Wait on a registered Delayed Dispatch unit that has a UniqueId. > Continue >=20 > + to dispatch all registered delayed dispatch entries until *ALL* entrie= s with >=20 > + UniqueId have completed. >=20 > + >=20 > + @param[in] This The Delayed Dispatch PPI pointer. >=20 > + @param[in] UniqueId UniqueId of delayed dispatch entry. >=20 > + >=20 > + @retval EFI_SUCCESS The operation succeeds. >=20 > + @retval EFI_INVALID_PARAMETER The parameters are invalid. >=20 > + >=20 > +**/ >=20 > +EFI_STATUS >=20 > +EFIAPI >=20 > +PeiDelayedDispatchWaitOnUniqueId ( >=20 > + IN EFI_DELAYED_DISPATCH_PPI *This, >=20 > + IN EFI_GUID *UniqueId >=20 > + ) >=20 > +{ >=20 > + PERF_FUNCTION_BEGIN (); >=20 > + DELAYED_DISPATCH_TABLE *DelayedDispatchTable; >=20 > + >=20 > + // Get delayed dispatch table >=20 > + DelayedDispatchTable =3D GetDelayedDispatchTable (); >=20 > + if (NULL =3D=3D DelayedDispatchTable) { >=20 > + PERF_FUNCTION_END (); >=20 > + return EFI_UNSUPPORTED; >=20 > + } >=20 > + >=20 > + if ((NULL =3D=3D UniqueId) || (IsZeroGuid (UniqueId))) { >=20 > + ASSERT (FALSE); >=20 > + PERF_FUNCTION_END (); >=20 > + return EFI_UNSUPPORTED; >=20 > + } >=20 > + >=20 > + DEBUG ((DEBUG_INFO, "Delayed dispatch on %g. Count=3D%d, > DispatchCount=3D%d\n", UniqueId, DelayedDispatchTable->Count, > DelayedDispatchTable->DispCount)); >=20 > + PERF_EVENT_SIGNAL_BEGIN (UniqueId); >=20 > + DelayedDispatchDispatcher (DelayedDispatchTable, UniqueId); >=20 > + PERF_EVENT_SIGNAL_END (UniqueId); >=20 > + >=20 > + PERF_FUNCTION_END (); >=20 > + return EFI_SUCCESS; >=20 > +} >=20 > + >=20 > +/** >=20 > + DelayedDispatch End of PEI callback function. Insure that all of the > delayed dispatch >=20 > + entries are complete before exiting PEI. >=20 > + >=20 > + @param[in] PeiServices - Pointer to PEI Services Table. >=20 > + @param[in] NotifyDesc - Pointer to the descriptor for the Notification > event that >=20 > + caused this function to execute. >=20 > + @param[in] Ppi - Pointer to the PPI data associated with thi= s > function. >=20 > + >=20 > + @retval EFI_STATUS - Always return EFI_SUCCESS >=20 > +**/ >=20 > +EFI_STATUS >=20 > +EFIAPI >=20 > +PeiDelayedDispatchOnEndOfPei ( >=20 > + IN EFI_PEI_SERVICES **PeiServices, >=20 > + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDesc, >=20 > + IN VOID *Ppi >=20 > + ) >=20 > +{ >=20 > + DELAYED_DISPATCH_TABLE *DelayedDispatchTable; >=20 > + >=20 > + // Get delayed dispatch table >=20 > + DelayedDispatchTable =3D GetDelayedDispatchTable (); >=20 > + if (NULL =3D=3D DelayedDispatchTable) { >=20 > + return EFI_UNSUPPORTED; >=20 > + } >=20 > + >=20 > + PERF_INMODULE_BEGIN ("PerfDelayedDispatchEndOfPei"); >=20 > + while (DelayedDispatchTable->Count > 0) { >=20 > + DelayedDispatchDispatcher (DelayedDispatchTable, NULL); >=20 > + } >=20 > + >=20 > + DEBUG ((DEBUG_ERROR, "%a Count of dispatch cycles is %d\n", __func__, > DelayedDispatchTable->DispCount)); >=20 > + PERF_INMODULE_END ("PerfDelayedDispatchEndOfPei"); >=20 > + >=20 > + return EFI_SUCCESS; >=20 > +} >=20 > + >=20 > /** >=20 >=20 >=20 > Discover all PEIMs and optional Apriori file in one FV. There is at most one >=20 > @@ -1365,12 +1692,31 @@ PeiDispatcher ( > EFI_PEI_FILE_HANDLE SaveCurrentFileHandle; >=20 > EFI_FV_FILE_INFO FvFileInfo; >=20 > PEI_CORE_FV_HANDLE *CoreFvHandle; >=20 > + EFI_HOB_GUID_TYPE *GuidHob; >=20 > + UINT32 TableSize; >=20 >=20 >=20 > PeiServices =3D (CONST EFI_PEI_SERVICES **)&Private->Ps; >=20 > PeimEntryPoint =3D NULL; >=20 > PeimFileHandle =3D NULL; >=20 > EntryPoint =3D 0; >=20 >=20 >=20 > + if (NULL =3D=3D Private->DelayedDispatchTable) { >=20 > + GuidHob =3D GetFirstGuidHob (&gEfiDelayedDispatchTableGuid); >=20 > + if (NULL !=3D GuidHob) { >=20 > + Private->DelayedDispatchTable =3D (DELAYED_DISPATCH_TABLE > *)(GET_GUID_HOB_DATA (GuidHob)); >=20 > + } else { >=20 > + TableSize =3D sizeof > (DELAYED_DISPATCH_TABLE) + ((FixedPcdGet32 > (PcdDelayedDispatchMaxEntries) - 1) * sizeof (DELAYED_DISPATCH_ENTRY)); >=20 > + Private->DelayedDispatchTable =3D BuildGuidHob > (&gEfiDelayedDispatchTableGuid, TableSize); >=20 > + if (NULL !=3D Private->DelayedDispatchTable) { >=20 > + ZeroMem (Private->DelayedDispatchTable, TableSize); >=20 > + Status =3D PeiServicesInstallPpi (&mDelayedDispatchDesc); >=20 > + ASSERT_EFI_ERROR (Status); >=20 > + Status =3D PeiServicesNotifyPpi (&mDelayedDispatchNotifyDesc); >=20 > + ASSERT_EFI_ERROR (Status); >=20 > + } >=20 > + } >=20 > + } >=20 > + >=20 > if ((Private->PeiMemoryInstalled) && >=20 > (PcdGetBool (PcdMigrateTemporaryRamFirmwareVolumes) || >=20 > (Private->HobList.HandoffInformationTable->BootMode !=3D > BOOT_ON_S3_RESUME) || >=20 > @@ -1621,6 +1967,13 @@ PeiDispatcher ( > } >=20 > } >=20 > } >=20 > + >=20 > + // Dispatch pending delalyed dispatch requests >=20 > + if (NULL !=3D Private->DelayedDispatchTable) { >=20 > + if (DelayedDispatchDispatcher (Private->DelayedDispatchTable, > NULL)) { >=20 > + ProcessDispatchNotifyList (Private); >=20 > + } >=20 > + } >=20 > } >=20 >=20 >=20 > // >=20 > diff --git a/MdeModulePkg/Core/Pei/PeiMain/PeiMain.c > b/MdeModulePkg/Core/Pei/PeiMain/PeiMain.c > index bf1719d7941a..e5643adf7027 100644 > --- a/MdeModulePkg/Core/Pei/PeiMain/PeiMain.c > +++ b/MdeModulePkg/Core/Pei/PeiMain/PeiMain.c > @@ -277,6 +277,9 @@ PeiCore ( > OldCoreData->TempFileHandles =3D (EFI_PEI_FILE_HANDLE > *)((UINT8 *)OldCoreData->TempFileHandles - OldCoreData->HeapOffset); >=20 > } >=20 >=20 >=20 > + // Force relocating the dispatch table >=20 > + OldCoreData->DelayedDispatchTable =3D NULL; >=20 > + >=20 > // >=20 > // Fixup for PeiService's address >=20 > // >=20 > diff --git a/MdeModulePkg/Core/Pei/PeiMain.h > b/MdeModulePkg/Core/Pei/PeiMain.h > index 556beddad533..3b8bbe7f25a1 100644 > --- a/MdeModulePkg/Core/Pei/PeiMain.h > +++ b/MdeModulePkg/Core/Pei/PeiMain.h > @@ -11,6 +11,8 @@ SPDX-License-Identifier: BSD-2-Clause-Patent >=20 >=20 > #include >=20 > #include >=20 > +#include >=20 > +#include >=20 > #include >=20 > #include >=20 > #include >=20 > @@ -41,6 +43,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent > #include >=20 > #include >=20 > #include >=20 > +#include >=20 > #include >=20 > #include >=20 > #include >=20 > @@ -207,6 +210,29 @@ EFI_STATUS >=20 >=20 > #define PEI_CORE_HANDLE_SIGNATURE SIGNATURE_32('P','e','i','C') >=20 >=20 >=20 > +#define GET_TIME_IN_US() > ((UINT32)DivU64x32(GetTimeInNanoSecond(GetPerformanceCounter ()), > 1000)) >=20 > + >=20 > +// >=20 > +// Internal structure for delayed dispatch entries. >=20 > +// >=20 > +#pragma pack (push, 1) >=20 > + >=20 > +typedef struct { >=20 > + EFI_GUID UniqueId; >=20 > + UINT64 Context; >=20 > + EFI_DELAYED_DISPATCH_FUNCTION Function; >=20 > + UINT32 DispatchTime; >=20 > + UINT32 MicrosecondDelay; >=20 > +} DELAYED_DISPATCH_ENTRY; >=20 > + >=20 > +typedef struct { >=20 > + UINT32 Count; >=20 > + UINT32 DispCount; >=20 > + DELAYED_DISPATCH_ENTRY Entry[1]; // Actual size based on > PCD PcdDelayedDispatchMaxEntries; >=20 > +} DELAYED_DISPATCH_TABLE; >=20 > + >=20 > +#pragma pack (pop) >=20 > + >=20 > /// >=20 > /// Pei Core private data structure instance >=20 > /// >=20 > @@ -307,6 +333,11 @@ struct _PEI_CORE_INSTANCE { > // Those Memory Range will be migrated into physical memory. >=20 > // >=20 > HOLE_MEMORY_DATA > HoleData[HOLE_MAX_NUMBER]; >=20 > + >=20 > + // >=20 > + // Table of delayed dispatch requests >=20 > + // >=20 > + DELAYED_DISPATCH_TABLE *DelayedDispatchTable; >=20 > }; >=20 >=20 >=20 > /// >=20 > @@ -2038,4 +2069,49 @@ PeiReinitializeFv ( > IN PEI_CORE_INSTANCE *PrivateData >=20 > ); >=20 >=20 >=20 > +/** >=20 > +Register a callback to be called after a minimum delay has occurred. >=20 > + >=20 > +This service is the single member function of the > EFI_DELAYED_DISPATCH_PPI >=20 > + >=20 > + @param[in] This Pointer to the EFI_DELAYED_DISPATCH_PPI > instance >=20 > + @param[in] Function Function to call back >=20 > + @param[in] Context Context data >=20 > + @param[in] UniqueId GUID for this Delayed Dispatch request. >=20 > + @param[in] Delay Delay interval >=20 > + >=20 > + @retval EFI_SUCCESS Function successfully loaded >=20 > + @retval EFI_INVALID_PARAMETER One of the Arguments is not > supported >=20 > + @retval EFI_OUT_OF_RESOURCES No more entries >=20 > + >=20 > +**/ >=20 > +EFI_STATUS >=20 > +EFIAPI >=20 > +PeiDelayedDispatchRegister ( >=20 > + IN EFI_DELAYED_DISPATCH_PPI *This, >=20 > + IN EFI_DELAYED_DISPATCH_FUNCTION Function, >=20 > + IN UINT64 Context, >=20 > + IN EFI_GUID *UniqueId OPTIONAL, >=20 > + IN UINT32 Delay >=20 > + ); >=20 > + >=20 > +/** >=20 > + Wait on a registered Delayed Dispatch unit that has a UniqueId. > Continue >=20 > + to dispatch all registered delayed dispatch entries until *ALL* entrie= s with >=20 > + UniqueId have completed. >=20 > + >=20 > + @param[in] This The Delayed Dispatch PPI pointer. >=20 > + @param[in] UniqueId UniqueId of delayed dispatch entry. >=20 > + >=20 > + @retval EFI_SUCCESS The operation succeeds. >=20 > + @retval EFI_INVALID_PARAMETER The parameters are invalid. >=20 > + >=20 > +**/ >=20 > +EFI_STATUS >=20 > +EFIAPI >=20 > +PeiDelayedDispatchWaitOnUniqueId ( >=20 > + IN EFI_DELAYED_DISPATCH_PPI *This, >=20 > + IN EFI_GUID *UniqueId >=20 > + ); >=20 > + >=20 > #endif >=20 > diff --git a/MdeModulePkg/Core/Pei/PeiMain.inf > b/MdeModulePkg/Core/Pei/PeiMain.inf > index 0cf357371a16..73738c939ac7 100644 > --- a/MdeModulePkg/Core/Pei/PeiMain.inf > +++ b/MdeModulePkg/Core/Pei/PeiMain.inf > @@ -66,6 +66,7 @@ [LibraryClasses] > PeCoffLib >=20 > PeiServicesTablePointerLib >=20 > PcdLib >=20 > + TimerLib >=20 >=20 >=20 > [Guids] >=20 > gPeiAprioriFileNameGuid ## SOMETIMES_CONSUMES ## File >=20 > @@ -78,6 +79,7 @@ [Guids] > gEfiFirmwareFileSystem3Guid >=20 > gStatusCodeCallbackGuid >=20 > gEdkiiMigratedFvInfoGuid ## > SOMETIMES_PRODUCES ## HOB >=20 > + gEfiDelayedDispatchTableGuid ## > SOMETIMES_PRODUCES ## HOB >=20 >=20 >=20 > [Ppis] >=20 > gEfiPeiStatusCodePpiGuid ## > SOMETIMES_CONSUMES # PeiReportStatusService is not ready if this PPI > doesn't exist >=20 > @@ -100,6 +102,8 @@ [Ppis] > gEfiPeiReset2PpiGuid ## > SOMETIMES_CONSUMES >=20 > gEfiSecHobDataPpiGuid ## > SOMETIMES_CONSUMES >=20 > gEfiPeiCoreFvLocationPpiGuid ## > SOMETIMES_CONSUMES >=20 > + gEfiPeiDelayedDispatchPpiGuid ## > SOMETIMES_CONSUMES >=20 [Liming] Here should PRODUCES.=20 > + gEfiEndOfPeiSignalPpiGuid ## CONSUMES >=20 >=20 >=20 > [Pcd] >=20 > gEfiMdeModulePkgTokenSpaceGuid.PcdPeiCoreMaxPeiStackSize > ## CONSUMES >=20 > @@ -112,6 +116,9 @@ [Pcd] > gEfiMdeModulePkgTokenSpaceGuid.PcdShadowPeimOnBoot > ## CONSUMES >=20 > gEfiMdeModulePkgTokenSpaceGuid.PcdInitValueInTempStack > ## CONSUMES >=20 >=20 > gEfiMdeModulePkgTokenSpaceGuid.PcdMigrateTemporaryRamFirmwareVolu > mes ## CONSUMES >=20 > + gEfiMdeModulePkgTokenSpaceGuid.PcdDelayedDispatchMaxDelayUs > ## CONSUMES >=20 > + > gEfiMdeModulePkgTokenSpaceGuid.PcdDelayedDispatchCompletionTimeout > Us ## CONSUMES >=20 > + gEfiMdeModulePkgTokenSpaceGuid.PcdDelayedDispatchMaxEntries > ## CONSUMES >=20 >=20 >=20 > # [BootMode] >=20 > # S3_RESUME ## SOMETIMES_CONSUMES >=20 > diff --git a/MdeModulePkg/MdeModulePkg.dec > b/MdeModulePkg/MdeModulePkg.dec > index 0ff058b0a9da..2f4bd2f2b773 100644 > --- a/MdeModulePkg/MdeModulePkg.dec > +++ b/MdeModulePkg/MdeModulePkg.dec > @@ -418,6 +418,9 @@ [Guids] > ## Include/Guid/MigratedFvInfo.h >=20 > gEdkiiMigratedFvInfoGuid =3D { 0xc1ab12f7, 0x74aa, 0x408d, { 0xa2, 0xf= 4, > 0xc6, 0xce, 0xfd, 0x17, 0x98, 0x71 } } >=20 >=20 >=20 > + ## Delayed Dispatch table GUID >=20 > + gEfiDelayedDispatchTableGuid =3D { 0x4b733449, 0x8eff, 0x488c, {0x92, > 0x1a, 0x15, 0x4a, 0xda, 0x25, 0x18, 0x07}} >=20 > + [Liming] This GUID is only used in PeiMain. I suggest to define the global GUID variable in PeiCore for this usage. >=20 > # >=20 > # GUID defined in UniversalPayload >=20 > # >=20 > @@ -991,6 +994,18 @@ [PcdsFixedAtBuild] > # @ValidList 0x80000006 | 0x03058002 >=20 >=20 > gEfiMdeModulePkgTokenSpaceGuid.PcdErrorCodeSetVariable|0x03058002|U > INT32|0x30001040 >=20 >=20 >=20 > + ## Delayed Dispatch Maximum Delay in us (microseconds) >=20 > + # Maximum delay for any particular delay request - 5 seconds >=20 > + > gEfiMdeModulePkgTokenSpaceGuid.PcdDelayedDispatchMaxDelayUs|500000 > 0|UINT32|0x3000104A >=20 > + >=20 > + ## Delayed Dispatch timeout in us (microseconds) >=20 > + # Maximum delay when waiting for completion (ie EndOfPei) - 10 seconds >=20 > + > gEfiMdeModulePkgTokenSpaceGuid.PcdDelayedDispatchCompletionTimeout > Us|10000000|UINT32|0x3000104B >=20 > + >=20 > + ## Delayed Dispatch Max Entries >=20 > + # Maximum number of delayed dispatch entries >=20 > + > gEfiMdeModulePkgTokenSpaceGuid.PcdDelayedDispatchMaxEntries|8|UINT3 > 2|0x3000104C >=20 > + [Liming] I suggest to define MACRO in PeiCore for them. If there is real usage model, new PCD can be introduced later.=20 Thanks Liming >=20 > ## Mask to control the NULL address detection in code for different > phases. >=20 > # If enabled, accessing NULL address in UEFI or SMM code can be > caught.

>=20 > # BIT0 - Enable NULL pointer detection for UEFI.
>=20 > -- > 2.41.0.windows.2 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#107214): https://edk2.groups.io/g/devel/message/107214 Mute This Topic: https://groups.io/mt/100343108/7686176 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-