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 C92F6AC0845 for ; Tue, 1 Aug 2023 04:16:02 +0000 (UTC) DKIM-Signature: a=rsa-sha256; bh=HmDeLM0T7Vsy1/hCjQlyXXqy9EoNHtzie92Rw2+yuoU=; c=relaxed/simple; d=groups.io; h=X-Received:X-Received:X-Received:X-Gm-Message-State:X-Google-Smtp-Source:X-Received:X-Received:Message-ID:Date:MIME-Version:User-Agent:Subject:To:Cc:References:From:In-Reply-To:Precedence:List-Subscribe:List-Help:Sender:List-Id:Mailing-List:Delivered-To:Reply-To:List-Unsubscribe-Post:List-Unsubscribe:Content-Type:Content-Language; s=20140610; t=1690863361; v=1; b=eNBmtejf4eKv2cWu/DWndF7DBAcQumATvFrUyNBoAUfyLmkOe7UmC6W5JIEXEMDufFybPwBE yn08HW6KUZSfVDjIB9RpA1NR8NL8eLAi4l+Q82qIE8CcxMmd+Ym9y0xG9u6XF4Ae5c5+3dVRLus j1CIIPlhguQ2f1BLX+7NM/yE= X-Received: by 127.0.0.2 with SMTP id lFlSYY7687511x4Cq19OH4Sg; Mon, 31 Jul 2023 21:16:01 -0700 X-Received: from mail-oi1-f179.google.com (mail-oi1-f179.google.com [209.85.167.179]) by mx.groups.io with SMTP id smtpd.web10.5632.1690863360323567178 for ; Mon, 31 Jul 2023 21:16:00 -0700 X-Received: by mail-oi1-f179.google.com with SMTP id 5614622812f47-3a3e1152c23so3829800b6e.2 for ; Mon, 31 Jul 2023 21:16:00 -0700 (PDT) X-Gm-Message-State: XG8jBqeE7GIDZHfFeC5sAeOlx7686176AA= X-Google-Smtp-Source: APBJJlFhSDDvhYqZq55gJU6NwdgcSQ2cYFj+EhOu75JcjwbeBqmcfku+P39ahjOtuFDxeVCYc6a5JQ== X-Received: by 2002:a05:6808:13c1:b0:3a3:7d62:ed8d with SMTP id d1-20020a05680813c100b003a37d62ed8dmr14043122oiw.15.1690863359231; Mon, 31 Jul 2023 21:15:59 -0700 (PDT) X-Received: from ?IPV6:2001:4898:d8:33:ad45:4344:fc29:a361? ([2001:4898:80e8:8:2d60:4344:fc29:a361]) by smtp.gmail.com with ESMTPSA id a15-20020a17090a70cf00b00267fbd521dbsm8457593pjm.5.2023.07.31.21.15.58 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Mon, 31 Jul 2023 21:15:58 -0700 (PDT) Message-ID: Date: Mon, 31 Jul 2023 21:15:57 -0700 MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: =?UTF-8?B?UmU6IFtlZGsyLWRldmVsXSDlm57lpI06IFtQQVRDSCB2MSAzLzRdIE1kZU1vZHVsZVBrZzogUGVpTWFpbjogSW50cm9kdWNlIGltcGxlbWVudGF0aW9uIG9mIGRlbGF5ZWQgZGlzcGF0Y2g=?= To: devel@edk2.groups.io, gaoliming@byosoft.com.cn 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> <01b901d9be9e$21a964c0$64fc2e40$@byosoft.com.cn> From: "Kun Qin" In-Reply-To: <01b901d9be9e$21a964c0$64fc2e40$@byosoft.com.cn> 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,kuqin12@gmail.com List-Unsubscribe-Post: List-Unsubscribe=One-Click List-Unsubscribe: Content-Type: multipart/alternative; boundary="------------aaZO3UKOHjuK2bVu280JhjRE" Content-Language: en-US X-GND-Status: LEGIT Authentication-Results: spool.mail.gandi.net; dkim=pass header.d=groups.io header.s=20140610 header.b=eNBmtejf; dmarc=fail reason="SPF not aligned (relaxed), DKIM not aligned (relaxed)" header.from=gmail.com (policy=none); spf=pass (spool.mail.gandi.net: domain of bounce@groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce@groups.io --------------aaZO3UKOHjuK2bVu280JhjRE Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 8bit Hi Liming, Thanks for the feedback. Per your feedback (I suggest to define MACRO in PeiCore for them. If there is real usage model, new PCD can be introduced later.) on the following new PCDs: gEfiMdeModulePkgTokenSpaceGuid.PcdDelayedDispatchMaxDelayUs gEfiMdeModulePkgTokenSpaceGuid.PcdDelayedDispatchCompletionTimeoutUs gEfiMdeModulePkgTokenSpaceGuid.PcdDelayedDispatchMaxEntries Given this feature has been used internally at Project MU for a while, I collected some feedback from the consumer platforms: - Delayed dispatch is a feature that can be used for power up sequence, and thus the value of maximum entries in this case can depend on the number of PCI devices on the platform, and thus hardcoding the value as a macro definition will limit the usage and we might come to update it very soon. - There is already usage on our platforms that would override the timeout PCDs to based on the firmware builds. For example, on a test build, we might register extra entries to the PPI and thus extend the completion timeout. I agree with your comments on other fronts. Please let me know if you have further concerns regarding the PCDs above. I can send out an updated version after your input on those. Thanks, Kun On 7/24/2023 7:17 PM, gaoliming via groups.io wrote: > Kun: > I add my comments below. > >> -----邮件原件----- >> 发件人: Kun Qin >> 发送时间: 2023年7月21日 5:07 >> 收件人:devel@edk2.groups.io >> 抄送: Jian J Wang; Dandan Bi >> ; Liming Gao; >> Debkumar De; Catharine West >> ; Mike Turner >> 主题: [PATCH v1 3/4] MdeModulePkg: PeiMain: Introduce implementation of >> delayed dispatch >> >> REF:https://bugzilla.tianocore.org/show_bug.cgi?id=4496 >> >> This change adds the implementation that fits the needs and description >> of PI spec defined Delayed Dispatch PPI in Pei Core. >> >> The PPI would allow minimal delay for registered callbacks. As well as >> allowing other functions to wait for GUIDed delayed dispatch callbacks. >> >> Cc: Jian J Wang >> Cc: Dandan Bi >> Cc: Liming Gao >> Cc: Debkumar De >> Cc: Catharine West >> >> 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(+) >> >> 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 @@ >> >> >> Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.
>> >> (C) Copyright 2016 Hewlett Packard Enterprise Development LP
>> >> +Copyright (c) Microsoft Corporation. >> >> SPDX-License-Identifier: BSD-2-Clause-Patent >> >> >> >> **/ >> >> >> >> #include "PeiMain.h" >> >> >> >> +/** >> >> + DelayedDispatchDispatcher >> >> + >> >> + ayed Dispach cycle (ie one pass) through each entry, calling functions >> when their >> >> + e has expired. When UniqueId is specified, if there are any of the >> specified entries >> >> + the dispatch queue during dispatch, repeat the DelayedDispatch cycle. >> >> + >> > [Liming] Above comments are incomplete. Please update. > >> + @param DelayedDispatchTable Pointer to dispatch table >> >> + @param OPTIONAL UniqueId used to insure particular >> time is met. >> >> + >> >> + @return BOOLEAN >> >> +**/ >> >> +BOOLEAN >> >> +DelayedDispatchDispatcher ( >> >> + IN DELAYED_DISPATCH_TABLE *DelayedDispatchTable, >> >> + IN EFI_GUID *UniqueId OPTIONAL >> >> + ); >> >> + >> >> +/** >> >> + DelayedDispatch End of PEI callback function. Insure that all of the >> delayed dispatch >> >> + entries are complete before exiting PEI. >> >> + >> >> + @param[in] PeiServices - Pointer to PEI Services Table. >> >> + @param[in] NotifyDesc - Pointer to the descriptor for the > Notification >> event that >> >> + caused this function to execute. >> >> + @param[in] Ppi - Pointer to the PPI data associated with this >> function. >> >> + >> >> + @retval EFI_STATUS - Always return EFI_SUCCESS >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +PeiDelayedDispatchOnEndOfPei ( >> >> + IN EFI_PEI_SERVICES **PeiServices, >> >> + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDesc, >> >> + IN VOID *Ppi >> >> + ); >> >> + >> >> +EFI_DELAYED_DISPATCH_PPI mDelayedDispatchPpi = >> { PeiDelayedDispatchRegister, PeiDelayedDispatchWaitOnUniqueId }; >> >> +EFI_PEI_PPI_DESCRIPTOR mDelayedDispatchDesc = { >> >> + (EFI_PEI_PPI_DESCRIPTOR_PPI | >> EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), >> >> + &gEfiPeiDelayedDispatchPpiGuid, >> >> + &mDelayedDispatchPpi >> >> +}; >> >> + >> >> +EFI_PEI_NOTIFY_DESCRIPTOR mDelayedDispatchNotifyDesc = { >> >> + EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | >> EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST, >> >> + &gEfiEndOfPeiSignalPpiGuid, >> >> + PeiDelayedDispatchOnEndOfPei >> >> +}; >> >> + >> >> +/** >> >> + Helper function to look up DELAYED_DISPATCH_TABLE published in HOB. >> >> + >> >> + @return Pointer to DELAYED_DISPATCH_TABLE from HOB >> >> +**/ >> >> +DELAYED_DISPATCH_TABLE * >> >> +GetDelayedDispatchTable ( >> >> + VOID >> >> + ) >> >> +{ >> >> + EFI_HOB_GUID_TYPE *GuidHob; >> >> + >> >> + GuidHob = GetFirstGuidHob (&gEfiDelayedDispatchTableGuid); >> >> + if (NULL == GuidHob) { >> >> + DEBUG ((DEBUG_ERROR, "Delayed Dispatch PPI ERROR - Delayed >> Dispatch Hob not available.\n")); >> >> + ASSERT (FALSE); >> >> + return NULL; >> >> + } >> >> + >> >> + return (DELAYED_DISPATCH_TABLE *)GET_GUID_HOB_DATA (GuidHob); >> >> +} >> >> + >> >> +/** >> >> +Register a callback to be called after a minimum delay has occurred. >> >> + >> >> +This service is the single member function of the >> EFI_DELAYED_DISPATCH_PPI >> >> + >> >> + @param[in] This Pointer to the EFI_DELAYED_DISPATCH_PPI >> instance >> >> + @param[in] Function Function to call back >> >> + @param[in] Context Context data >> >> + @param[in] UniqueId GUID for this Delayed Dispatch request. >> >> + @param[in] Delay Delay interval >> >> + >> >> + @retval EFI_SUCCESS Function successfully loaded >> >> + @retval EFI_INVALID_PARAMETER One of the Arguments is not >> supported >> >> + @retval EFI_OUT_OF_RESOURCES No more entries >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +PeiDelayedDispatchRegister ( >> >> + IN EFI_DELAYED_DISPATCH_PPI *This, >> >> + IN EFI_DELAYED_DISPATCH_FUNCTION Function, >> >> + IN UINT64 Context, >> >> + IN EFI_GUID *UniqueId OPTIONAL, >> >> + IN UINT32 Delay >> >> + ) >> >> +{ >> >> + DELAYED_DISPATCH_TABLE *DelayedDispatchTable; >> >> + DELAYED_DISPATCH_ENTRY *Entry; >> >> + >> >> + // Check input parameters >> >> + if ((NULL == Function) || (Delay > FixedPcdGet32 >> (PcdDelayedDispatchMaxDelayUs)) || (NULL == This)) { >> >> + DEBUG ((DEBUG_ERROR, "%a Invalid parameter\n", __func__)); >> >> + return EFI_INVALID_PARAMETER; >> >> + } >> >> + >> >> + // Get delayed dispatch table >> >> + DelayedDispatchTable = GetDelayedDispatchTable (); >> >> + if (NULL == DelayedDispatchTable) { >> >> + DEBUG ((DEBUG_ERROR, "%a Unable to locate dispatch table\n", >> __func__)); >> >> + return EFI_UNSUPPORTED; >> >> + } >> >> + >> >> + // Check for available entry slots >> >> + if (DelayedDispatchTable->Count >= FixedPcdGet32 >> (PcdDelayedDispatchMaxEntries)) { >> >> + ASSERT (DelayedDispatchTable->Count < FixedPcdGet32 >> (PcdDelayedDispatchMaxEntries)); >> >> + DEBUG ((DEBUG_ERROR, "%a Too many entries requested\n", >> __func__)); >> >> + return EFI_OUT_OF_RESOURCES; >> >> + } >> >> + >> >> + Entry = >> &(DelayedDispatchTable->Entry[DelayedDispatchTable->Count]); >> >> + Entry->Function = Function; >> >> + Entry->Context = Context; >> >> + Entry->DispatchTime = GET_TIME_IN_US () + Delay; >> >> + if (NULL != UniqueId) { >> >> + CopyGuid (&Entry->UniqueId, UniqueId); >> >> + } else { >> >> + ZeroMem (&Entry->UniqueId, sizeof (EFI_GUID)); >> >> + } >> >> + >> >> + Entry->MicrosecondDelay = Delay; >> >> + DelayedDispatchTable->Count++; >> >> + >> >> + DEBUG ((DEBUG_INFO, "%a Adding dispatch Entry\n", __func__)); >> >> + DEBUG ((DEBUG_INFO, " Requested Delay = %d\n", Delay)); >> >> + DEBUG ((DEBUG_INFO, " Trigger Time = %d\n", >> Entry->DispatchTime)); >> >> + DEBUG ((DEBUG_INFO, " Context = 0x%08lx\n", Entry->Context)); >> >> + DEBUG ((DEBUG_INFO, " Function = %p\n", Entry->Function)); >> >> + DEBUG ((DEBUG_INFO, " GuidHandle = %g\n", &(Entry->UniqueId))); >> >> + >> >> + if (0 == Delay) { >> >> + // Force early dispatch point >> >> + DelayedDispatchDispatcher (DelayedDispatchTable, NULL); >> >> + } >> >> + >> >> + return EFI_SUCCESS; >> >> +} >> >> + >> >> +/** >> >> + DelayedDispatchDispatcher >> >> + >> >> + ayed Dispach cycle (ie one pass) through each entry, calling functions >> when their >> >> + e has expired. When UniqueId is specified, if there are any of the >> specified entries >> >> + the dispatch queue during dispatch, repeat the DelayedDispatch cycle. >> >> + >> >> + @param DelayedDispatchTable Pointer to dispatch table >> >> + @param OPTIONAL UniqueId used to insure particular >> time is met. >> >> + >> >> + @return BOOLEAN >> >> +**/ >> >> +BOOLEAN >> >> +DelayedDispatchDispatcher ( >> >> + IN DELAYED_DISPATCH_TABLE *DelayedDispatchTable, >> >> + IN EFI_GUID *UniqueId OPTIONAL >> >> + ) >> >> +{ >> >> + BOOLEAN Dispatched; >> >> + UINT32 TimeCurrent; >> >> + UINT32 MaxDispatchTime; >> >> + UINTN Index1; >> >> + BOOLEAN UniqueIdPresent; >> >> + DELAYED_DISPATCH_ENTRY *Entry; >> >> + >> >> + Dispatched = FALSE; >> >> + UniqueIdPresent = TRUE; >> >> + MaxDispatchTime = GET_TIME_IN_US () + FixedPcdGet32 >> (PcdDelayedDispatchCompletionTimeoutUs); >> >> + while ((DelayedDispatchTable->Count > 0) && (UniqueIdPresent)) { >> >> + UniqueIdPresent = FALSE; >> >> + DelayedDispatchTable->DispCount++; >> >> + >> >> + // If dispatching is messed up, clear DelayedDispatchTable and exit. >> >> + TimeCurrent = GET_TIME_IN_US (); >> >> + if (TimeCurrent > MaxDispatchTime) { >> >> + DEBUG ((DEBUG_ERROR, "%a - DelayedDispatch Completion >> timeout!\n", __func__)); >> >> + ReportStatusCode ((EFI_ERROR_MAJOR | EFI_ERROR_CODE), >> (EFI_SOFTWARE_PEI_CORE | EFI_SW_EC_ABORTED)); >> >> + ASSERT (FALSE); >> >> + DelayedDispatchTable->Count = 0; >> >> + break; >> >> + } >> >> + >> >> + // Check each entry in the table for possible dispatch >> >> + for (Index1 = 0; Index1 < DelayedDispatchTable->Count;) { >> >> + Entry = &(DelayedDispatchTable->Entry[Index1]); >> >> + // If UniqueId is present, insure there is an additional check of > the >> table. >> >> + if (NULL != UniqueId) { >> >> + if (CompareGuid (UniqueId, &Entry->UniqueId)) { >> >> + UniqueIdPresent = TRUE; >> >> + } >> >> + } >> >> + >> >> + TimeCurrent = GET_TIME_IN_US (); >> >> + if (TimeCurrent >= Entry->DispatchTime) { >> >> + // Time expired, invoked the function >> >> + DEBUG (( >> >> + DEBUG_ERROR, >> >> + "Delayed dispatch entry %d @ %p, Target=%d, Act=%d >> Disp=%d\n", >> >> + Index1, >> >> + Entry->Function, >> >> + Entry->DispatchTime, >> >> + TimeCurrent, >> >> + DelayedDispatchTable->DispCount >> >> + )); >> >> + Dispatched = TRUE; >> >> + Entry->MicrosecondDelay = 0; >> >> + Entry->Function ( >> >> + &Entry->Context, >> >> + &Entry->MicrosecondDelay >> >> + ); >> >> + DEBUG ((DEBUG_ERROR, "Delayed dispatch Function returned >> delay=%d\n", Entry->MicrosecondDelay)); >> >> + if (0 == Entry->MicrosecondDelay) { >> >> + // NewTime = 0 = delete this entry from the table >> >> + DelayedDispatchTable->Count--; >> >> + CopyMem (Entry, Entry+1, sizeof (DELAYED_DISPATCH_ENTRY) >> * (DelayedDispatchTable->Count - Index1)); >> >> + } else { >> >> + if (Entry->MicrosecondDelay > FixedPcdGet32 >> (PcdDelayedDispatchMaxDelayUs)) { >> >> + DEBUG ((DEBUG_ERROR, "%a Illegal new delay %d >> requested\n", __func__, Entry->MicrosecondDelay)); >> >> + ASSERT (FALSE); >> >> + Entry->MicrosecondDelay = FixedPcdGet32 >> (PcdDelayedDispatchMaxDelayUs); >> >> + } >> >> + >> >> + // NewTime != 0 - update the time from us to Dispatch time >> >> + Entry->DispatchTime = GET_TIME_IN_US () + >> Entry->MicrosecondDelay; >> >> + Index1++; >> >> + } >> >> + } else { >> >> + Index1++; >> >> + } >> >> + } >> >> + } >> >> + >> >> + return Dispatched; >> >> +} >> >> + >> >> +/** >> >> + Wait on a registered Delayed Dispatch unit that has a UniqueId. >> Continue >> >> + to dispatch all registered delayed dispatch entries until *ALL* entries > with >> + UniqueId have completed. >> >> + >> >> + @param[in] This The Delayed Dispatch PPI pointer. >> >> + @param[in] UniqueId UniqueId of delayed dispatch entry. >> >> + >> >> + @retval EFI_SUCCESS The operation succeeds. >> >> + @retval EFI_INVALID_PARAMETER The parameters are invalid. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +PeiDelayedDispatchWaitOnUniqueId ( >> >> + IN EFI_DELAYED_DISPATCH_PPI *This, >> >> + IN EFI_GUID *UniqueId >> >> + ) >> >> +{ >> >> + PERF_FUNCTION_BEGIN (); >> >> + DELAYED_DISPATCH_TABLE *DelayedDispatchTable; >> >> + >> >> + // Get delayed dispatch table >> >> + DelayedDispatchTable = GetDelayedDispatchTable (); >> >> + if (NULL == DelayedDispatchTable) { >> >> + PERF_FUNCTION_END (); >> >> + return EFI_UNSUPPORTED; >> >> + } >> >> + >> >> + if ((NULL == UniqueId) || (IsZeroGuid (UniqueId))) { >> >> + ASSERT (FALSE); >> >> + PERF_FUNCTION_END (); >> >> + return EFI_UNSUPPORTED; >> >> + } >> >> + >> >> + DEBUG ((DEBUG_INFO, "Delayed dispatch on %g. Count=%d, >> DispatchCount=%d\n", UniqueId, DelayedDispatchTable->Count, >> DelayedDispatchTable->DispCount)); >> >> + PERF_EVENT_SIGNAL_BEGIN (UniqueId); >> >> + DelayedDispatchDispatcher (DelayedDispatchTable, UniqueId); >> >> + PERF_EVENT_SIGNAL_END (UniqueId); >> >> + >> >> + PERF_FUNCTION_END (); >> >> + return EFI_SUCCESS; >> >> +} >> >> + >> >> +/** >> >> + DelayedDispatch End of PEI callback function. Insure that all of the >> delayed dispatch >> >> + entries are complete before exiting PEI. >> >> + >> >> + @param[in] PeiServices - Pointer to PEI Services Table. >> >> + @param[in] NotifyDesc - Pointer to the descriptor for the > Notification >> event that >> >> + caused this function to execute. >> >> + @param[in] Ppi - Pointer to the PPI data associated with this >> function. >> >> + >> >> + @retval EFI_STATUS - Always return EFI_SUCCESS >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +PeiDelayedDispatchOnEndOfPei ( >> >> + IN EFI_PEI_SERVICES **PeiServices, >> >> + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDesc, >> >> + IN VOID *Ppi >> >> + ) >> >> +{ >> >> + DELAYED_DISPATCH_TABLE *DelayedDispatchTable; >> >> + >> >> + // Get delayed dispatch table >> >> + DelayedDispatchTable = GetDelayedDispatchTable (); >> >> + if (NULL == DelayedDispatchTable) { >> >> + return EFI_UNSUPPORTED; >> >> + } >> >> + >> >> + PERF_INMODULE_BEGIN ("PerfDelayedDispatchEndOfPei"); >> >> + while (DelayedDispatchTable->Count > 0) { >> >> + DelayedDispatchDispatcher (DelayedDispatchTable, NULL); >> >> + } >> >> + >> >> + DEBUG ((DEBUG_ERROR, "%a Count of dispatch cycles is %d\n", __func__, >> DelayedDispatchTable->DispCount)); >> >> + PERF_INMODULE_END ("PerfDelayedDispatchEndOfPei"); >> >> + >> >> + return EFI_SUCCESS; >> >> +} >> >> + >> >> /** >> >> >> >> Discover all PEIMs and optional Apriori file in one FV. There is at > most one >> @@ -1365,12 +1692,31 @@ PeiDispatcher ( >> EFI_PEI_FILE_HANDLE SaveCurrentFileHandle; >> >> EFI_FV_FILE_INFO FvFileInfo; >> >> PEI_CORE_FV_HANDLE *CoreFvHandle; >> >> + EFI_HOB_GUID_TYPE *GuidHob; >> >> + UINT32 TableSize; >> >> >> >> PeiServices = (CONST EFI_PEI_SERVICES **)&Private->Ps; >> >> PeimEntryPoint = NULL; >> >> PeimFileHandle = NULL; >> >> EntryPoint = 0; >> >> >> >> + if (NULL == Private->DelayedDispatchTable) { >> >> + GuidHob = GetFirstGuidHob (&gEfiDelayedDispatchTableGuid); >> >> + if (NULL != GuidHob) { >> >> + Private->DelayedDispatchTable = (DELAYED_DISPATCH_TABLE >> *)(GET_GUID_HOB_DATA (GuidHob)); >> >> + } else { >> >> + TableSize = sizeof >> (DELAYED_DISPATCH_TABLE) + ((FixedPcdGet32 >> (PcdDelayedDispatchMaxEntries) - 1) * sizeof (DELAYED_DISPATCH_ENTRY)); >> >> + Private->DelayedDispatchTable = BuildGuidHob >> (&gEfiDelayedDispatchTableGuid, TableSize); >> >> + if (NULL != Private->DelayedDispatchTable) { >> >> + ZeroMem (Private->DelayedDispatchTable, TableSize); >> >> + Status = PeiServicesInstallPpi (&mDelayedDispatchDesc); >> >> + ASSERT_EFI_ERROR (Status); >> >> + Status = PeiServicesNotifyPpi (&mDelayedDispatchNotifyDesc); >> >> + ASSERT_EFI_ERROR (Status); >> >> + } >> >> + } >> >> + } >> >> + >> >> if ((Private->PeiMemoryInstalled) && >> >> (PcdGetBool (PcdMigrateTemporaryRamFirmwareVolumes) || >> >> (Private->HobList.HandoffInformationTable->BootMode != >> BOOT_ON_S3_RESUME) || >> >> @@ -1621,6 +1967,13 @@ PeiDispatcher ( >> } >> >> } >> >> } >> >> + >> >> + // Dispatch pending delalyed dispatch requests >> >> + if (NULL != Private->DelayedDispatchTable) { >> >> + if (DelayedDispatchDispatcher (Private->DelayedDispatchTable, >> NULL)) { >> >> + ProcessDispatchNotifyList (Private); >> >> + } >> >> + } >> >> } >> >> >> >> // >> >> 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 = (EFI_PEI_FILE_HANDLE >> *)((UINT8 *)OldCoreData->TempFileHandles - OldCoreData->HeapOffset); >> >> } >> >> >> >> + // Force relocating the dispatch table >> >> + OldCoreData->DelayedDispatchTable = NULL; >> >> + >> >> // >> >> // Fixup for PeiService's address >> >> // >> >> 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 >> >> >> #include >> >> #include >> >> +#include >> >> +#include >> >> #include >> >> #include >> >> #include >> >> @@ -41,6 +43,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent >> #include >> >> #include >> >> #include >> >> +#include >> >> #include >> >> #include >> >> #include >> >> @@ -207,6 +210,29 @@ EFI_STATUS >> >> >> #define PEI_CORE_HANDLE_SIGNATURE SIGNATURE_32('P','e','i','C') >> >> >> >> +#define GET_TIME_IN_US() >> ((UINT32)DivU64x32(GetTimeInNanoSecond(GetPerformanceCounter ()), >> 1000)) >> >> + >> >> +// >> >> +// Internal structure for delayed dispatch entries. >> >> +// >> >> +#pragma pack (push, 1) >> >> + >> >> +typedef struct { >> >> + EFI_GUID UniqueId; >> >> + UINT64 Context; >> >> + EFI_DELAYED_DISPATCH_FUNCTION Function; >> >> + UINT32 DispatchTime; >> >> + UINT32 MicrosecondDelay; >> >> +} DELAYED_DISPATCH_ENTRY; >> >> + >> >> +typedef struct { >> >> + UINT32 Count; >> >> + UINT32 DispCount; >> >> + DELAYED_DISPATCH_ENTRY Entry[1]; // Actual size based on >> PCD PcdDelayedDispatchMaxEntries; >> >> +} DELAYED_DISPATCH_TABLE; >> >> + >> >> +#pragma pack (pop) >> >> + >> >> /// >> >> /// Pei Core private data structure instance >> >> /// >> >> @@ -307,6 +333,11 @@ struct _PEI_CORE_INSTANCE { >> // Those Memory Range will be migrated into physical memory. >> >> // >> >> HOLE_MEMORY_DATA >> HoleData[HOLE_MAX_NUMBER]; >> >> + >> >> + // >> >> + // Table of delayed dispatch requests >> >> + // >> >> + DELAYED_DISPATCH_TABLE *DelayedDispatchTable; >> >> }; >> >> >> >> /// >> >> @@ -2038,4 +2069,49 @@ PeiReinitializeFv ( >> IN PEI_CORE_INSTANCE *PrivateData >> >> ); >> >> >> >> +/** >> >> +Register a callback to be called after a minimum delay has occurred. >> >> + >> >> +This service is the single member function of the >> EFI_DELAYED_DISPATCH_PPI >> >> + >> >> + @param[in] This Pointer to the EFI_DELAYED_DISPATCH_PPI >> instance >> >> + @param[in] Function Function to call back >> >> + @param[in] Context Context data >> >> + @param[in] UniqueId GUID for this Delayed Dispatch request. >> >> + @param[in] Delay Delay interval >> >> + >> >> + @retval EFI_SUCCESS Function successfully loaded >> >> + @retval EFI_INVALID_PARAMETER One of the Arguments is not >> supported >> >> + @retval EFI_OUT_OF_RESOURCES No more entries >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +PeiDelayedDispatchRegister ( >> >> + IN EFI_DELAYED_DISPATCH_PPI *This, >> >> + IN EFI_DELAYED_DISPATCH_FUNCTION Function, >> >> + IN UINT64 Context, >> >> + IN EFI_GUID *UniqueId OPTIONAL, >> >> + IN UINT32 Delay >> >> + ); >> >> + >> >> +/** >> >> + Wait on a registered Delayed Dispatch unit that has a UniqueId. >> Continue >> >> + to dispatch all registered delayed dispatch entries until *ALL* entries > with >> + UniqueId have completed. >> >> + >> >> + @param[in] This The Delayed Dispatch PPI pointer. >> >> + @param[in] UniqueId UniqueId of delayed dispatch entry. >> >> + >> >> + @retval EFI_SUCCESS The operation succeeds. >> >> + @retval EFI_INVALID_PARAMETER The parameters are invalid. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +PeiDelayedDispatchWaitOnUniqueId ( >> >> + IN EFI_DELAYED_DISPATCH_PPI *This, >> >> + IN EFI_GUID *UniqueId >> >> + ); >> >> + >> >> #endif >> >> 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 >> >> PeiServicesTablePointerLib >> >> PcdLib >> >> + TimerLib >> >> >> >> [Guids] >> >> gPeiAprioriFileNameGuid ## SOMETIMES_CONSUMES ## File >> >> @@ -78,6 +79,7 @@ [Guids] >> gEfiFirmwareFileSystem3Guid >> >> gStatusCodeCallbackGuid >> >> gEdkiiMigratedFvInfoGuid ## >> SOMETIMES_PRODUCES ## HOB >> >> + gEfiDelayedDispatchTableGuid ## >> SOMETIMES_PRODUCES ## HOB >> >> >> >> [Ppis] >> >> gEfiPeiStatusCodePpiGuid ## >> SOMETIMES_CONSUMES # PeiReportStatusService is not ready if this PPI >> doesn't exist >> >> @@ -100,6 +102,8 @@ [Ppis] >> gEfiPeiReset2PpiGuid ## >> SOMETIMES_CONSUMES >> >> gEfiSecHobDataPpiGuid ## >> SOMETIMES_CONSUMES >> >> gEfiPeiCoreFvLocationPpiGuid ## >> SOMETIMES_CONSUMES >> >> + gEfiPeiDelayedDispatchPpiGuid ## >> SOMETIMES_CONSUMES >> > [Liming] Here should PRODUCES. > >> + gEfiEndOfPeiSignalPpiGuid ## CONSUMES >> >> >> >> [Pcd] >> >> gEfiMdeModulePkgTokenSpaceGuid.PcdPeiCoreMaxPeiStackSize >> ## CONSUMES >> >> @@ -112,6 +116,9 @@ [Pcd] >> gEfiMdeModulePkgTokenSpaceGuid.PcdShadowPeimOnBoot >> ## CONSUMES >> >> gEfiMdeModulePkgTokenSpaceGuid.PcdInitValueInTempStack >> ## CONSUMES >> >> >> gEfiMdeModulePkgTokenSpaceGuid.PcdMigrateTemporaryRamFirmwareVolu >> mes ## CONSUMES >> >> + gEfiMdeModulePkgTokenSpaceGuid.PcdDelayedDispatchMaxDelayUs >> ## CONSUMES >> >> + >> gEfiMdeModulePkgTokenSpaceGuid.PcdDelayedDispatchCompletionTimeout >> Us ## CONSUMES >> >> + gEfiMdeModulePkgTokenSpaceGuid.PcdDelayedDispatchMaxEntries >> ## CONSUMES >> >> >> >> # [BootMode] >> >> # S3_RESUME ## SOMETIMES_CONSUMES >> >> 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 >> >> gEdkiiMigratedFvInfoGuid = { 0xc1ab12f7, 0x74aa, 0x408d, { 0xa2, 0xf4, >> 0xc6, 0xce, 0xfd, 0x17, 0x98, 0x71 } } >> >> >> >> + ## Delayed Dispatch table GUID >> >> + gEfiDelayedDispatchTableGuid = { 0x4b733449, 0x8eff, 0x488c, {0x92, >> 0x1a, 0x15, 0x4a, 0xda, 0x25, 0x18, 0x07}} >> >> + > [Liming] This GUID is only used in PeiMain. I suggest to define the global > GUID variable in PeiCore for this usage. > >> # >> >> # GUID defined in UniversalPayload >> >> # >> >> @@ -991,6 +994,18 @@ [PcdsFixedAtBuild] >> # @ValidList 0x80000006 | 0x03058002 >> >> >> gEfiMdeModulePkgTokenSpaceGuid.PcdErrorCodeSetVariable|0x03058002|U >> INT32|0x30001040 >> >> >> >> + ## Delayed Dispatch Maximum Delay in us (microseconds) >> >> + # Maximum delay for any particular delay request - 5 seconds >> >> + >> gEfiMdeModulePkgTokenSpaceGuid.PcdDelayedDispatchMaxDelayUs|500000 >> 0|UINT32|0x3000104A >> >> + >> >> + ## Delayed Dispatch timeout in us (microseconds) >> >> + # Maximum delay when waiting for completion (ie EndOfPei) - 10 seconds >> >> + >> gEfiMdeModulePkgTokenSpaceGuid.PcdDelayedDispatchCompletionTimeout >> Us|10000000|UINT32|0x3000104B >> >> + >> >> + ## Delayed Dispatch Max Entries >> >> + # Maximum number of delayed dispatch entries >> >> + >> gEfiMdeModulePkgTokenSpaceGuid.PcdDelayedDispatchMaxEntries|8|UINT3 >> 2|0x3000104C >> >> + > [Liming] I suggest to define MACRO in PeiCore for them. If there is real > usage model, new PCD can be introduced later. > > Thanks > Liming >> ## Mask to control the NULL address detection in code for different >> phases. >> >> # If enabled, accessing NULL address in UEFI or SMM code can be >> caught.

>> >> # BIT0 - Enable NULL pointer detection for UEFI.
>> >> -- >> 2.41.0.windows.2 > > > > > > > -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#107417): https://edk2.groups.io/g/devel/message/107417 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] -=-=-=-=-=-=-=-=-=-=-=- --------------aaZO3UKOHjuK2bVu280JhjRE Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: 8bit

Hi Liming,

Thanks for the feedback.

Per your feedback (I suggest to define MACRO in PeiCore for them. If there is real usage model, new PCD can be introduced later.) on the following new PCDs:

gEfiMdeModulePkgTokenSpaceGuid.PcdDelayedDispatchMaxDelayUs
gEfiMdeModulePkgTokenSpaceGuid.PcdDelayedDispatchCompletionTimeoutUs
gEfiMdeModulePkgTokenSpaceGuid.PcdDelayedDispatchMaxEntries

Given this feature has been used internally at Project MU for a while, I
collected some feedback from the consumer platforms:

- Delayed dispatch is a feature that can be used for power up sequence, and
thus the value of maximum entries in this case can depend on the number of PCI
devices on the platform, and thus hardcoding the value as a macro definition will
limit the usage and we might come to update it very soon.

- There is already usage on our platforms that would override the timeout PCDs
to based on the firmware builds. For example, on a test build, we might register extra
entries to the PPI and thus extend the completion timeout.

I agree with your comments on other fronts. Please let me know if you have further
concerns regarding the PCDs above. I can send out an updated version after your input
on those.

Thanks,
Kun

On 7/24/2023 7:17 PM, gaoliming via groups.io wrote:
Kun: 
  I add my comments below. 

-----邮件原件-----
发件人: Kun Qin <kuqin12@gmail.com>
发送时间: 2023年7月21日 5:07
收件人: devel@edk2.groups.io
抄送: Jian J Wang <jian.j.wang@intel.com>; Dandan Bi
<dandan.bi@intel.com>; Liming Gao <gaoliming@byosoft.com.cn>;
Debkumar De <debkumar.de@intel.com>; Catharine West
<catharine.west@intel.com>; Mike Turner <mikeyt@pobox.com>
主题: [PATCH v1 3/4] MdeModulePkg: PeiMain: Introduce implementation of
delayed dispatch

REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4496

This change adds the implementation that fits the needs and description
of PI spec defined Delayed Dispatch PPI in Pei Core.

The PPI would allow minimal delay for registered callbacks. As well as
allowing other functions to wait for GUIDed delayed dispatch callbacks.

Cc: Jian J Wang <jian.j.wang@intel.com>
Cc: Dandan Bi <dandan.bi@intel.com>
Cc: Liming Gao <gaoliming@byosoft.com.cn>
Cc: Debkumar De <debkumar.de@intel.com>
Cc: Catharine West <catharine.west@intel.com>

Co-authored-by: Mike Turner <mikeyt@pobox.com>
Signed-off-by: Kun Qin <kuqin12@gmail.com>
---
 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(+)

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 @@


 Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>

 (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>

+Copyright (c) Microsoft Corporation.

 SPDX-License-Identifier: BSD-2-Clause-Patent



 **/



 #include "PeiMain.h"



+/**

+  DelayedDispatchDispatcher

+

+  ayed Dispach cycle (ie one pass) through each entry, calling functions
when their

+  e has expired.  When UniqueId is specified, if there are any of the
specified entries

+  the dispatch queue during dispatch, repeat the DelayedDispatch cycle.

+

[Liming] Above comments are incomplete. Please update. 

+  @param DelayedDispatchTable  Pointer to dispatch table

+  @param OPTIONAL              UniqueId used to insure particular
time is met.

+

+  @return BOOLEAN

+**/

+BOOLEAN

+DelayedDispatchDispatcher (

+  IN DELAYED_DISPATCH_TABLE  *DelayedDispatchTable,

+  IN EFI_GUID                *UniqueId           OPTIONAL

+  );

+

+/**

+  DelayedDispatch End of PEI callback function. Insure that all of the
delayed dispatch

+  entries are complete before exiting PEI.

+

+  @param[in] PeiServices   - Pointer to PEI Services Table.

+  @param[in] NotifyDesc    - Pointer to the descriptor for the
Notification
event that

+                             caused this function to execute.

+  @param[in] Ppi           - Pointer to the PPI data associated with this
function.

+

+  @retval EFI_STATUS       - Always return EFI_SUCCESS

+**/

+EFI_STATUS

+EFIAPI

+PeiDelayedDispatchOnEndOfPei (

+  IN EFI_PEI_SERVICES           **PeiServices,

+  IN EFI_PEI_NOTIFY_DESCRIPTOR  *NotifyDesc,

+  IN VOID                       *Ppi

+  );

+

+EFI_DELAYED_DISPATCH_PPI  mDelayedDispatchPpi  =
{ PeiDelayedDispatchRegister, PeiDelayedDispatchWaitOnUniqueId };

+EFI_PEI_PPI_DESCRIPTOR    mDelayedDispatchDesc = {

+  (EFI_PEI_PPI_DESCRIPTOR_PPI |
EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),

+  &gEfiPeiDelayedDispatchPpiGuid,

+  &mDelayedDispatchPpi

+};

+

+EFI_PEI_NOTIFY_DESCRIPTOR  mDelayedDispatchNotifyDesc = {

+  EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK |
EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,

+  &gEfiEndOfPeiSignalPpiGuid,

+  PeiDelayedDispatchOnEndOfPei

+};

+

+/**

+  Helper function to look up DELAYED_DISPATCH_TABLE published in HOB.

+

+  @return Pointer to DELAYED_DISPATCH_TABLE from HOB

+**/

+DELAYED_DISPATCH_TABLE *

+GetDelayedDispatchTable (

+  VOID

+  )

+{

+  EFI_HOB_GUID_TYPE  *GuidHob;

+

+  GuidHob = GetFirstGuidHob (&gEfiDelayedDispatchTableGuid);

+  if (NULL == GuidHob) {

+    DEBUG ((DEBUG_ERROR, "Delayed Dispatch PPI ERROR - Delayed
Dispatch Hob not available.\n"));

+    ASSERT (FALSE);

+    return NULL;

+  }

+

+  return (DELAYED_DISPATCH_TABLE *)GET_GUID_HOB_DATA (GuidHob);

+}

+

+/**

+Register a callback to be called after a minimum delay has occurred.

+

+This service is the single member function of the
EFI_DELAYED_DISPATCH_PPI

+

+  @param[in] This           Pointer to the EFI_DELAYED_DISPATCH_PPI
instance

+  @param[in] Function       Function to call back

+  @param[in] Context        Context data

+  @param[in] UniqueId       GUID for this Delayed Dispatch request.

+  @param[in] Delay          Delay interval

+

+  @retval EFI_SUCCESS               Function successfully loaded

+  @retval EFI_INVALID_PARAMETER     One of the Arguments is not
supported

+  @retval EFI_OUT_OF_RESOURCES      No more entries

+

+**/

+EFI_STATUS

+EFIAPI

+PeiDelayedDispatchRegister (

+  IN  EFI_DELAYED_DISPATCH_PPI       *This,

+  IN  EFI_DELAYED_DISPATCH_FUNCTION  Function,

+  IN  UINT64                         Context,

+  IN  EFI_GUID                       *UniqueId   OPTIONAL,

+  IN  UINT32                         Delay

+  )

+{

+  DELAYED_DISPATCH_TABLE  *DelayedDispatchTable;

+  DELAYED_DISPATCH_ENTRY  *Entry;

+

+  // Check input parameters

+  if ((NULL == Function) || (Delay > FixedPcdGet32
(PcdDelayedDispatchMaxDelayUs)) || (NULL == This)) {

+    DEBUG ((DEBUG_ERROR, "%a Invalid parameter\n", __func__));

+    return EFI_INVALID_PARAMETER;

+  }

+

+  // Get delayed dispatch table

+  DelayedDispatchTable = GetDelayedDispatchTable ();

+  if (NULL == DelayedDispatchTable) {

+    DEBUG ((DEBUG_ERROR, "%a Unable to locate dispatch table\n",
__func__));

+    return EFI_UNSUPPORTED;

+  }

+

+  // Check for available entry slots

+  if (DelayedDispatchTable->Count >= FixedPcdGet32
(PcdDelayedDispatchMaxEntries)) {

+    ASSERT (DelayedDispatchTable->Count < FixedPcdGet32
(PcdDelayedDispatchMaxEntries));

+    DEBUG ((DEBUG_ERROR, "%a Too many entries requested\n",
__func__));

+    return EFI_OUT_OF_RESOURCES;

+  }

+

+  Entry               =
&(DelayedDispatchTable->Entry[DelayedDispatchTable->Count]);

+  Entry->Function     = Function;

+  Entry->Context      = Context;

+  Entry->DispatchTime = GET_TIME_IN_US () + Delay;

+  if (NULL != UniqueId) {

+    CopyGuid (&Entry->UniqueId, UniqueId);

+  } else {

+    ZeroMem (&Entry->UniqueId, sizeof (EFI_GUID));

+  }

+

+  Entry->MicrosecondDelay = Delay;

+  DelayedDispatchTable->Count++;

+

+  DEBUG ((DEBUG_INFO, "%a  Adding dispatch Entry\n", __func__));

+  DEBUG ((DEBUG_INFO, "    Requested Delay = %d\n", Delay));

+  DEBUG ((DEBUG_INFO, "    Trigger Time = %d\n",
Entry->DispatchTime));

+  DEBUG ((DEBUG_INFO, "    Context = 0x%08lx\n", Entry->Context));

+  DEBUG ((DEBUG_INFO, "    Function = %p\n", Entry->Function));

+  DEBUG ((DEBUG_INFO, "    GuidHandle = %g\n", &(Entry->UniqueId)));

+

+  if (0 == Delay) {

+    // Force early dispatch point

+    DelayedDispatchDispatcher (DelayedDispatchTable, NULL);

+  }

+

+  return EFI_SUCCESS;

+}

+

+/**

+  DelayedDispatchDispatcher

+

+  ayed Dispach cycle (ie one pass) through each entry, calling functions
when their

+  e has expired.  When UniqueId is specified, if there are any of the
specified entries

+  the dispatch queue during dispatch, repeat the DelayedDispatch cycle.

+

+  @param DelayedDispatchTable  Pointer to dispatch table

+  @param OPTIONAL              UniqueId used to insure particular
time is met.

+

+  @return BOOLEAN

+**/

+BOOLEAN

+DelayedDispatchDispatcher (

+  IN DELAYED_DISPATCH_TABLE  *DelayedDispatchTable,

+  IN EFI_GUID                *UniqueId           OPTIONAL

+  )

+{

+  BOOLEAN                 Dispatched;

+  UINT32                  TimeCurrent;

+  UINT32                  MaxDispatchTime;

+  UINTN                   Index1;

+  BOOLEAN                 UniqueIdPresent;

+  DELAYED_DISPATCH_ENTRY  *Entry;

+

+  Dispatched      = FALSE;

+  UniqueIdPresent = TRUE;

+  MaxDispatchTime = GET_TIME_IN_US () + FixedPcdGet32
(PcdDelayedDispatchCompletionTimeoutUs);

+  while ((DelayedDispatchTable->Count > 0) && (UniqueIdPresent)) {

+    UniqueIdPresent = FALSE;

+    DelayedDispatchTable->DispCount++;

+

+    // If dispatching is messed up, clear DelayedDispatchTable and exit.

+    TimeCurrent =  GET_TIME_IN_US ();

+    if (TimeCurrent > MaxDispatchTime) {

+      DEBUG ((DEBUG_ERROR, "%a - DelayedDispatch Completion
timeout!\n", __func__));

+      ReportStatusCode ((EFI_ERROR_MAJOR | EFI_ERROR_CODE),
(EFI_SOFTWARE_PEI_CORE | EFI_SW_EC_ABORTED));

+      ASSERT (FALSE);

+      DelayedDispatchTable->Count = 0;

+      break;

+    }

+

+    // Check each entry in the table for possible dispatch

+    for (Index1 = 0; Index1 < DelayedDispatchTable->Count;) {

+      Entry = &(DelayedDispatchTable->Entry[Index1]);

+      // If UniqueId is present, insure there is an additional check of
the
table.

+      if (NULL != UniqueId) {

+        if (CompareGuid (UniqueId, &Entry->UniqueId)) {

+          UniqueIdPresent = TRUE;

+        }

+      }

+

+      TimeCurrent =  GET_TIME_IN_US ();

+      if (TimeCurrent >= Entry->DispatchTime) {

+        // Time expired, invoked the function

+        DEBUG ((

+          DEBUG_ERROR,

+          "Delayed dispatch entry %d @ %p, Target=%d, Act=%d
Disp=%d\n",

+          Index1,

+          Entry->Function,

+          Entry->DispatchTime,

+          TimeCurrent,

+          DelayedDispatchTable->DispCount

+          ));

+        Dispatched              = TRUE;

+        Entry->MicrosecondDelay = 0;

+        Entry->Function (

+                 &Entry->Context,

+                 &Entry->MicrosecondDelay

+                 );

+        DEBUG ((DEBUG_ERROR, "Delayed dispatch Function returned
delay=%d\n", Entry->MicrosecondDelay));

+        if (0 == Entry->MicrosecondDelay) {

+          // NewTime = 0 = delete this entry from the table

+          DelayedDispatchTable->Count--;

+          CopyMem (Entry, Entry+1, sizeof (DELAYED_DISPATCH_ENTRY)
* (DelayedDispatchTable->Count - Index1));

+        } else {

+          if (Entry->MicrosecondDelay > FixedPcdGet32
(PcdDelayedDispatchMaxDelayUs)) {

+            DEBUG ((DEBUG_ERROR, "%a Illegal new delay %d
requested\n", __func__, Entry->MicrosecondDelay));

+            ASSERT (FALSE);

+            Entry->MicrosecondDelay = FixedPcdGet32
(PcdDelayedDispatchMaxDelayUs);

+          }

+

+          // NewTime != 0 - update the time from us to Dispatch time

+          Entry->DispatchTime =  GET_TIME_IN_US () +
Entry->MicrosecondDelay;

+          Index1++;

+        }

+      } else {

+        Index1++;

+      }

+    }

+  }

+

+  return Dispatched;

+}

+

+/**

+  Wait on a registered Delayed Dispatch unit that has a UniqueId.
Continue

+  to dispatch all registered delayed dispatch entries until *ALL* entries
with
+  UniqueId have completed.

+

+  @param[in]     This            The Delayed Dispatch PPI pointer.

+  @param[in]     UniqueId        UniqueId of delayed dispatch entry.

+

+  @retval EFI_SUCCESS            The operation succeeds.

+  @retval EFI_INVALID_PARAMETER  The parameters are invalid.

+

+**/

+EFI_STATUS

+EFIAPI

+PeiDelayedDispatchWaitOnUniqueId (

+  IN EFI_DELAYED_DISPATCH_PPI  *This,

+  IN EFI_GUID                  *UniqueId

+  )

+{

+  PERF_FUNCTION_BEGIN ();

+  DELAYED_DISPATCH_TABLE  *DelayedDispatchTable;

+

+  // Get delayed dispatch table

+  DelayedDispatchTable = GetDelayedDispatchTable ();

+  if (NULL == DelayedDispatchTable) {

+    PERF_FUNCTION_END ();

+    return EFI_UNSUPPORTED;

+  }

+

+  if ((NULL == UniqueId) || (IsZeroGuid (UniqueId))) {

+    ASSERT (FALSE);

+    PERF_FUNCTION_END ();

+    return EFI_UNSUPPORTED;

+  }

+

+  DEBUG ((DEBUG_INFO, "Delayed dispatch on %g. Count=%d,
DispatchCount=%d\n", UniqueId, DelayedDispatchTable->Count,
DelayedDispatchTable->DispCount));

+  PERF_EVENT_SIGNAL_BEGIN (UniqueId);

+  DelayedDispatchDispatcher (DelayedDispatchTable, UniqueId);

+  PERF_EVENT_SIGNAL_END (UniqueId);

+

+  PERF_FUNCTION_END ();

+  return EFI_SUCCESS;

+}

+

+/**

+  DelayedDispatch End of PEI callback function. Insure that all of the
delayed dispatch

+  entries are complete before exiting PEI.

+

+  @param[in] PeiServices   - Pointer to PEI Services Table.

+  @param[in] NotifyDesc    - Pointer to the descriptor for the
Notification
event that

+                             caused this function to execute.

+  @param[in] Ppi           - Pointer to the PPI data associated with this
function.

+

+  @retval EFI_STATUS       - Always return EFI_SUCCESS

+**/

+EFI_STATUS

+EFIAPI

+PeiDelayedDispatchOnEndOfPei (

+  IN EFI_PEI_SERVICES           **PeiServices,

+  IN EFI_PEI_NOTIFY_DESCRIPTOR  *NotifyDesc,

+  IN VOID                       *Ppi

+  )

+{

+  DELAYED_DISPATCH_TABLE  *DelayedDispatchTable;

+

+  // Get delayed dispatch table

+  DelayedDispatchTable = GetDelayedDispatchTable ();

+  if (NULL == DelayedDispatchTable) {

+    return EFI_UNSUPPORTED;

+  }

+

+  PERF_INMODULE_BEGIN ("PerfDelayedDispatchEndOfPei");

+  while (DelayedDispatchTable->Count > 0) {

+    DelayedDispatchDispatcher (DelayedDispatchTable, NULL);

+  }

+

+  DEBUG ((DEBUG_ERROR, "%a Count of dispatch cycles is %d\n", __func__,
DelayedDispatchTable->DispCount));

+  PERF_INMODULE_END ("PerfDelayedDispatchEndOfPei");

+

+  return EFI_SUCCESS;

+}

+

 /**



   Discover all PEIMs and optional Apriori file in one FV. There is at
most one
@@ -1365,12 +1692,31 @@ PeiDispatcher (
   EFI_PEI_FILE_HANDLE     SaveCurrentFileHandle;

   EFI_FV_FILE_INFO        FvFileInfo;

   PEI_CORE_FV_HANDLE      *CoreFvHandle;

+  EFI_HOB_GUID_TYPE       *GuidHob;

+  UINT32                  TableSize;



   PeiServices    = (CONST EFI_PEI_SERVICES **)&Private->Ps;

   PeimEntryPoint = NULL;

   PeimFileHandle = NULL;

   EntryPoint     = 0;



+  if (NULL == Private->DelayedDispatchTable) {

+    GuidHob = GetFirstGuidHob (&gEfiDelayedDispatchTableGuid);

+    if (NULL != GuidHob) {

+      Private->DelayedDispatchTable = (DELAYED_DISPATCH_TABLE
*)(GET_GUID_HOB_DATA (GuidHob));

+    } else {

+      TableSize                     = sizeof
(DELAYED_DISPATCH_TABLE) + ((FixedPcdGet32
(PcdDelayedDispatchMaxEntries) - 1) * sizeof (DELAYED_DISPATCH_ENTRY));

+      Private->DelayedDispatchTable = BuildGuidHob
(&gEfiDelayedDispatchTableGuid, TableSize);

+      if (NULL != Private->DelayedDispatchTable) {

+        ZeroMem (Private->DelayedDispatchTable, TableSize);

+        Status = PeiServicesInstallPpi (&mDelayedDispatchDesc);

+        ASSERT_EFI_ERROR (Status);

+        Status = PeiServicesNotifyPpi (&mDelayedDispatchNotifyDesc);

+        ASSERT_EFI_ERROR (Status);

+      }

+    }

+  }

+

   if ((Private->PeiMemoryInstalled) &&

       (PcdGetBool (PcdMigrateTemporaryRamFirmwareVolumes) ||

        (Private->HobList.HandoffInformationTable->BootMode !=
BOOT_ON_S3_RESUME) ||

@@ -1621,6 +1967,13 @@ PeiDispatcher (
             }

           }

         }

+

+        // Dispatch pending delalyed dispatch requests

+        if (NULL != Private->DelayedDispatchTable) {

+          if (DelayedDispatchDispatcher (Private->DelayedDispatchTable,
NULL)) {

+            ProcessDispatchNotifyList (Private);

+          }

+        }

       }



       //

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 = (EFI_PEI_FILE_HANDLE
*)((UINT8 *)OldCoreData->TempFileHandles - OldCoreData->HeapOffset);

       }



+      // Force relocating the dispatch table

+      OldCoreData->DelayedDispatchTable = NULL;

+

       //

       // Fixup for PeiService's address

       //

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


 #include <PiPei.h>

 #include <Ppi/DxeIpl.h>

+#include <Ppi/DelayedDispatch.h>

+#include <Ppi/EndOfPeiPhase.h>

 #include <Ppi/MemoryDiscovered.h>

 #include <Ppi/StatusCode.h>

 #include <Ppi/Reset.h>

@@ -41,6 +43,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 #include <IndustryStandard/PeImage.h>

 #include <Library/PeiServicesTablePointerLib.h>

 #include <Library/MemoryAllocationLib.h>

+#include <Library/TimerLib.h>

 #include <Guid/FirmwareFileSystem2.h>

 #include <Guid/FirmwareFileSystem3.h>

 #include <Guid/AprioriFileName.h>

@@ -207,6 +210,29 @@ EFI_STATUS


 #define PEI_CORE_HANDLE_SIGNATURE  SIGNATURE_32('P','e','i','C')



+#define GET_TIME_IN_US()
((UINT32)DivU64x32(GetTimeInNanoSecond(GetPerformanceCounter ()),
1000))

+

+//

+// Internal structure for delayed dispatch entries.

+//

+#pragma pack (push, 1)

+

+typedef struct {

+  EFI_GUID                         UniqueId;

+  UINT64                           Context;

+  EFI_DELAYED_DISPATCH_FUNCTION    Function;

+  UINT32                           DispatchTime;

+  UINT32                           MicrosecondDelay;

+} DELAYED_DISPATCH_ENTRY;

+

+typedef struct {

+  UINT32                    Count;

+  UINT32                    DispCount;

+  DELAYED_DISPATCH_ENTRY    Entry[1];     // Actual size based on
PCD PcdDelayedDispatchMaxEntries;

+} DELAYED_DISPATCH_TABLE;

+

+#pragma pack (pop)

+

 ///

 /// Pei Core private data structure instance

 ///

@@ -307,6 +333,11 @@ struct _PEI_CORE_INSTANCE {
   // Those Memory Range will be migrated into physical memory.

   //

   HOLE_MEMORY_DATA
HoleData[HOLE_MAX_NUMBER];

+

+  //

+  // Table of delayed dispatch requests

+  //

+  DELAYED_DISPATCH_TABLE            *DelayedDispatchTable;

 };



 ///

@@ -2038,4 +2069,49 @@ PeiReinitializeFv (
   IN  PEI_CORE_INSTANCE  *PrivateData

   );



+/**

+Register a callback to be called after a minimum delay has occurred.

+

+This service is the single member function of the
EFI_DELAYED_DISPATCH_PPI

+

+  @param[in] This           Pointer to the EFI_DELAYED_DISPATCH_PPI
instance

+  @param[in] Function       Function to call back

+  @param[in] Context        Context data

+  @param[in] UniqueId       GUID for this Delayed Dispatch request.

+  @param[in] Delay          Delay interval

+

+  @retval EFI_SUCCESS               Function successfully loaded

+  @retval EFI_INVALID_PARAMETER     One of the Arguments is not
supported

+  @retval EFI_OUT_OF_RESOURCES      No more entries

+

+**/

+EFI_STATUS

+EFIAPI

+PeiDelayedDispatchRegister (

+  IN  EFI_DELAYED_DISPATCH_PPI       *This,

+  IN  EFI_DELAYED_DISPATCH_FUNCTION  Function,

+  IN  UINT64                         Context,

+  IN  EFI_GUID                       *UniqueId   OPTIONAL,

+  IN  UINT32                         Delay

+  );

+

+/**

+  Wait on a registered Delayed Dispatch unit that has a UniqueId.
Continue

+  to dispatch all registered delayed dispatch entries until *ALL* entries
with
+  UniqueId have completed.

+

+  @param[in]     This            The Delayed Dispatch PPI pointer.

+  @param[in]     UniqueId        UniqueId of delayed dispatch entry.

+

+  @retval EFI_SUCCESS            The operation succeeds.

+  @retval EFI_INVALID_PARAMETER  The parameters are invalid.

+

+**/

+EFI_STATUS

+EFIAPI

+PeiDelayedDispatchWaitOnUniqueId (

+  IN EFI_DELAYED_DISPATCH_PPI  *This,

+  IN EFI_GUID                  *UniqueId

+  );

+

 #endif

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

   PeiServicesTablePointerLib

   PcdLib

+  TimerLib



 [Guids]

   gPeiAprioriFileNameGuid       ## SOMETIMES_CONSUMES   ## File

@@ -78,6 +79,7 @@ [Guids]
   gEfiFirmwareFileSystem3Guid

   gStatusCodeCallbackGuid

   gEdkiiMigratedFvInfoGuid                      ##
SOMETIMES_PRODUCES     ## HOB

+  gEfiDelayedDispatchTableGuid                  ##
SOMETIMES_PRODUCES     ## HOB



 [Ppis]

   gEfiPeiStatusCodePpiGuid                      ##
SOMETIMES_CONSUMES # PeiReportStatusService is not ready if this PPI
doesn't exist

@@ -100,6 +102,8 @@ [Ppis]
   gEfiPeiReset2PpiGuid                          ##
SOMETIMES_CONSUMES

   gEfiSecHobDataPpiGuid                         ##
SOMETIMES_CONSUMES

   gEfiPeiCoreFvLocationPpiGuid                  ##
SOMETIMES_CONSUMES

+  gEfiPeiDelayedDispatchPpiGuid                 ##
SOMETIMES_CONSUMES

[Liming] Here should PRODUCES. 

+  gEfiEndOfPeiSignalPpiGuid                     ## CONSUMES



 [Pcd]

   gEfiMdeModulePkgTokenSpaceGuid.PcdPeiCoreMaxPeiStackSize
## CONSUMES

@@ -112,6 +116,9 @@ [Pcd]
   gEfiMdeModulePkgTokenSpaceGuid.PcdShadowPeimOnBoot
## CONSUMES

   gEfiMdeModulePkgTokenSpaceGuid.PcdInitValueInTempStack
## CONSUMES


gEfiMdeModulePkgTokenSpaceGuid.PcdMigrateTemporaryRamFirmwareVolu
mes      ## CONSUMES

+  gEfiMdeModulePkgTokenSpaceGuid.PcdDelayedDispatchMaxDelayUs
## CONSUMES

+
gEfiMdeModulePkgTokenSpaceGuid.PcdDelayedDispatchCompletionTimeout
Us      ## CONSUMES

+  gEfiMdeModulePkgTokenSpaceGuid.PcdDelayedDispatchMaxEntries
## CONSUMES



 # [BootMode]

 # S3_RESUME             ## SOMETIMES_CONSUMES

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

   gEdkiiMigratedFvInfoGuid = { 0xc1ab12f7, 0x74aa, 0x408d, { 0xa2, 0xf4,
0xc6, 0xce, 0xfd, 0x17, 0x98, 0x71 } }



+  ## Delayed Dispatch table GUID

+  gEfiDelayedDispatchTableGuid = { 0x4b733449, 0x8eff, 0x488c, {0x92,
0x1a, 0x15, 0x4a, 0xda, 0x25, 0x18, 0x07}}

+
[Liming] This GUID is only used in PeiMain. I suggest to define the global
GUID variable in PeiCore for this usage.

   #

   # GUID defined in UniversalPayload

   #

@@ -991,6 +994,18 @@ [PcdsFixedAtBuild]
   # @ValidList  0x80000006 | 0x03058002


gEfiMdeModulePkgTokenSpaceGuid.PcdErrorCodeSetVariable|0x03058002|U
INT32|0x30001040



+  ## Delayed Dispatch Maximum Delay in us (microseconds)

+  # Maximum delay for any particular delay request - 5 seconds

+
gEfiMdeModulePkgTokenSpaceGuid.PcdDelayedDispatchMaxDelayUs|500000
0|UINT32|0x3000104A

+

+  ## Delayed Dispatch timeout in us (microseconds)

+  # Maximum delay when waiting for completion (ie EndOfPei) - 10 seconds

+
gEfiMdeModulePkgTokenSpaceGuid.PcdDelayedDispatchCompletionTimeout
Us|10000000|UINT32|0x3000104B

+

+  ## Delayed Dispatch Max Entries

+  # Maximum number of delayed dispatch entries

+
gEfiMdeModulePkgTokenSpaceGuid.PcdDelayedDispatchMaxEntries|8|UINT3
2|0x3000104C

+
[Liming] I suggest to define MACRO in PeiCore for them. If there is real
usage model, new PCD can be introduced later. 

Thanks
Liming
   ## Mask to control the NULL address detection in code for different
phases.

   #  If enabled, accessing NULL address in UEFI or SMM code can be
caught.<BR><BR>

   #    BIT0    - Enable NULL pointer detection for UEFI.<BR>

--
2.41.0.windows.2







_._,_._,_

Groups.io Links:

You receive all messages sent to this group.

View/Reply Online (#107417) | | Mute This Topic | New Topic
Your Subscription | Contact Group Owner | Unsubscribe [rebecca@openfw.io]

_._,_._,_
--------------aaZO3UKOHjuK2bVu280JhjRE--