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 5E7A2D81111 for ; Wed, 3 Apr 2024 07:50:51 +0000 (UTC) DKIM-Signature: a=rsa-sha256; bh=Z1eN4PFlDOwKo8yWUMohhz5BZa9sv8FAK6NfacV5f2g=; c=relaxed/simple; d=groups.io; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References:MIME-Version:Precedence:List-Subscribe:List-Help:Sender:List-Id:Mailing-List:Delivered-To:Resent-Date:Resent-From:Reply-To:List-Unsubscribe-Post:List-Unsubscribe:Content-Transfer-Encoding; s=20240206; t=1712130650; v=1; b=jfmQ2DxZ9F4JurJX0yIFZi5LgWzzTtZBijWEJbowwls9Di2SwGpCv0Wx9ZUBMDCBgWP+Jj7s IqLFf/8h8XuaEZyUbftlBYzR7R6Xn5nl9wYwlHPV2vYFyneVU6tP60Jk90rE9Th3M8x5dQHOfCK BrIpxlJpS2Mel6Y58Rt9eRgJJU6d8PemZ80hUkWHafwuE7P26WdkE7jgKKNPtjLLNGFri0xF/Ki A7Ejwo26JIhkkiCQBtglPAW9TEE0N0M7J2x1A9+uB752YejT/MKGR/f0AwkFIL+ftFIi4P6/e6U 2EKwEBEVMr4k3T3QEk4YfmorKfmgNbqFq/7nHG338LM6Q== X-Received: by 127.0.0.2 with SMTP id hqmTYY7687511x8uSmLYkrto; Wed, 03 Apr 2024 00:50:50 -0700 X-Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.13]) by mx.groups.io with SMTP id smtpd.web11.5859.1712130636141857502 for ; Wed, 03 Apr 2024 00:50:49 -0700 X-CSE-ConnectionGUID: CPxIckgnSKSB2znfs21ECA== X-CSE-MsgGUID: YETq9uYHT+GzFEqWG7vNfQ== X-IronPort-AV: E=McAfee;i="6600,9927,11032"; a="10311975" X-IronPort-AV: E=Sophos;i="6.07,176,1708416000"; d="scan'208";a="10311975" X-Received: from fmviesa009.fm.intel.com ([10.60.135.149]) by fmvoesa107.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 03 Apr 2024 00:50:49 -0700 X-CSE-ConnectionGUID: TMnVprQeSqKRLY1LOAX/AQ== X-CSE-MsgGUID: X6w3Mz3zS7a8d0FpjAkoow== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.07,176,1708416000"; d="scan'208";a="18399099" X-Received: from shwdesfp01.ccr.corp.intel.com ([10.239.158.151]) by fmviesa009-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 03 Apr 2024 00:50:47 -0700 From: "Zhiguang Liu" To: devel@edk2.groups.io Cc: Zhiguang Liu , Liming Gao , Jiaxin Wu , Ray Ni , Laszlo Ersek , Ard Biesheuvel , Sami Mujawar Subject: [edk2-devel] [PATCH v2 6/6] StandaloneMmPkg: Support to unregister MMI handler in MMI handlers Date: Wed, 3 Apr 2024 15:50:17 +0800 Message-Id: <20240403075017.1997-7-zhiguang.liu@intel.com> In-Reply-To: <20240403075017.1997-1-zhiguang.liu@intel.com> References: <20240403075017.1997-1-zhiguang.liu@intel.com> MIME-Version: 1.0 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 Resent-Date: Wed, 03 Apr 2024 00:50:49 -0700 Resent-From: zhiguang.liu@intel.com Reply-To: devel@edk2.groups.io,zhiguang.liu@intel.com List-Unsubscribe-Post: List-Unsubscribe=One-Click List-Unsubscribe: X-Gm-Message-State: 9czS0EJH7rW03dJXer0x7sbIx7686176AA= Content-Transfer-Encoding: 8bit X-GND-Status: LEGIT Authentication-Results: spool.mail.gandi.net; dkim=pass header.d=groups.io header.s=20240206 header.b=jfmQ2DxZ; 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=fail reason="SPF not aligned (relaxed), DKIM not aligned (relaxed)" header.from=intel.com (policy=none) Unregistering MMI handler will free the MMI_HANDLER. However, the MmiManage() may be using the link node from MMI_HANDLER for loop if the unregistering happens in MMI handlers. To avoid that, the idea is to inform MmiHandlerUnRegister() whether it's running or not running on the stack of MmiManage(), and to postpone MMI_HANDLER deletion until after the loop finishes. Cc: Liming Gao Cc: Jiaxin Wu Cc: Ray Ni Cc: Laszlo Ersek Cc: Ray Ni Cc: Laszlo Ersek Cc: Ard Biesheuvel Cc: Sami Mujawar Signed-off-by: Zhiguang Liu --- StandaloneMmPkg/Core/Mmi.c | 149 +++++++++++++++++++++++++++++++------ 1 file changed, 126 insertions(+), 23 deletions(-) diff --git a/StandaloneMmPkg/Core/Mmi.c b/StandaloneMmPkg/Core/Mmi.c index 0de6fd17fc..b13c7a3bc6 100644 --- a/StandaloneMmPkg/Core/Mmi.c +++ b/StandaloneMmPkg/Core/Mmi.c @@ -34,11 +34,50 @@ typedef struct { LIST_ENTRY Link; // Link on MMI_ENTRY.MmiHandlers EFI_MM_HANDLER_ENTRY_POINT Handler; // The mm handler's entry point MMI_ENTRY *MmiEntry; + BOOLEAN ToDelete; // To delete this MMI_HANDLER later } MMI_HANDLER; +// +// mMmiManageCallingDepth is used to track the depth of recursive calls of MmiManage. +// +UINTN mMmiManageCallingDepth = 0; + LIST_ENTRY mRootMmiHandlerList = INITIALIZE_LIST_HEAD_VARIABLE (mRootMmiHandlerList); LIST_ENTRY mMmiEntryList = INITIALIZE_LIST_HEAD_VARIABLE (mMmiEntryList); +/** + Remove MmiHandler and free the memory it used. + If MmiEntry is empty, remove MmiEntry and free the memory it used. + + @param MmiHandler Points to MMI handler. + @param MmiEntry Points to MMI Entry or NULL for root MMI handlers. + + @retval TRUE MmiEntry is removed. + @retval FALSE MmiEntry is not removed. +**/ +BOOLEAN +RemoveMmiHandler ( + IN MMI_HANDLER *MmiHandler, + IN MMI_ENTRY *MmiEntry + ) +{ + RemoveEntryList (&MmiHandler->Link); + FreePool (MmiHandler); + + if (MmiEntry != NULL) { + if (IsListEmpty (&MmiEntry->MmiHandlers)) { + // + // No handler registered for this MMI_ENTRY, remove the MMI_ENTRY + // + RemoveEntryList (&MmiEntry->AllEntries); + FreePool (MmiEntry); + return TRUE; + } + } + + return FALSE; +} + /** Finds the MMI entry for the requested handler type. @@ -126,13 +165,16 @@ MmiManage ( { LIST_ENTRY *Link; LIST_ENTRY *Head; + LIST_ENTRY *EntryLink; MMI_ENTRY *MmiEntry; MMI_HANDLER *MmiHandler; - BOOLEAN SuccessReturn; + EFI_STATUS ReturnStatus; + BOOLEAN WillReturn; EFI_STATUS Status; - Status = EFI_NOT_FOUND; - SuccessReturn = FALSE; + mMmiManageCallingDepth++; + Status = EFI_NOT_FOUND; + ReturnStatus = Status; if (HandlerType == NULL) { // // Root MMI handler @@ -171,7 +213,16 @@ MmiManage ( // no additional handlers will be processed and EFI_INTERRUPT_PENDING will be returned. // if (HandlerType != NULL) { - return EFI_INTERRUPT_PENDING; + ReturnStatus = EFI_INTERRUPT_PENDING; + WillReturn = TRUE; + } else { + // + // If any other handler's result sets ReturnStatus as EFI_SUCCESS, the return status + // will be EFI_SUCCESS. + // + if (ReturnStatus != EFI_SUCCESS) { + ReturnStatus = Status; + } } break; @@ -183,10 +234,10 @@ MmiManage ( // additional handlers will be processed. // if (HandlerType != NULL) { - return EFI_SUCCESS; + WillReturn = TRUE; } - SuccessReturn = TRUE; + ReturnStatus = EFI_SUCCESS; break; case EFI_WARN_INTERRUPT_SOURCE_QUIESCED: @@ -194,7 +245,7 @@ MmiManage ( // If at least one of the handlers returns EFI_WARN_INTERRUPT_SOURCE_QUIESCED // then the function will return EFI_SUCCESS. // - SuccessReturn = TRUE; + ReturnStatus = EFI_SUCCESS; break; case EFI_WARN_INTERRUPT_SOURCE_PENDING: @@ -202,6 +253,10 @@ MmiManage ( // If all the handlers returned EFI_WARN_INTERRUPT_SOURCE_PENDING // then EFI_WARN_INTERRUPT_SOURCE_PENDING will be returned. // + if (ReturnStatus != EFI_SUCCESS) { + ReturnStatus = Status; + } + break; default: @@ -211,13 +266,67 @@ MmiManage ( ASSERT_EFI_ERROR (Status); break; } + + if (WillReturn) { + break; + } } - if (SuccessReturn) { - Status = EFI_SUCCESS; + ASSERT (mMmiManageCallingDepth > 0); + mMmiManageCallingDepth--; + + // + // The MmiHandlerUnRegister won't take effect inside MmiManage. + // Before returned from MmiManage, delete the MmiHandler which is + // marked as ToDelete. + // Note that MmiManage can be called recursively. + // + if (mMmiManageCallingDepth == 0) { + // + // Go through all MmiHandler in root Mmi handlers + // + for ( Link = GetFirstNode (&mRootMmiHandlerList) + ; !IsNull (&mRootMmiHandlerList, Link); + ) + { + MmiHandler = CR (Link, MMI_HANDLER, Link, MMI_HANDLER_SIGNATURE); + Link = GetNextNode (&mRootMmiHandlerList, Link); + if (MmiHandler->ToDelete) { + // + // Remove MmiHandler if the ToDelete is set. + // + RemoveMmiHandler (MmiHandler, NULL); + } + } + + // + // Go through all MmiHandler in non-root MMI handlers + // + for ( EntryLink = GetFirstNode (&mMmiEntryList) + ; !IsNull (&mMmiEntryList, EntryLink); + ) + { + MmiEntry = CR (EntryLink, MMI_ENTRY, AllEntries, MMI_ENTRY_SIGNATURE); + EntryLink = GetNextNode (&mMmiEntryList, EntryLink); + for ( Link = GetFirstNode (&MmiEntry->MmiHandlers) + ; !IsNull (&MmiEntry->MmiHandlers, Link); + ) + { + MmiHandler = CR (Link, MMI_HANDLER, Link, MMI_HANDLER_SIGNATURE); + Link = GetNextNode (&MmiEntry->MmiHandlers, Link); + if (MmiHandler->ToDelete) { + // + // Remove MmiHandler if the ToDelete is set. + // + if (RemoveMmiHandler (MmiHandler, MmiEntry)) { + break; + } + } + } + } } - return Status; + return ReturnStatus; } /** @@ -254,6 +363,7 @@ MmiHandlerRegister ( MmiHandler->Signature = MMI_HANDLER_SIGNATURE; MmiHandler->Handler = Handler; + MmiHandler->ToDelete = FALSE; if (HandlerType == NULL) { // @@ -311,24 +421,17 @@ MmiHandlerUnRegister ( MmiEntry = MmiHandler->MmiEntry; - RemoveEntryList (&MmiHandler->Link); - FreePool (MmiHandler); - - if (MmiEntry == NULL) { + if (mMmiManageCallingDepth > 0) { // - // This is root MMI handler + // This function is called from MmiManage() + // Do not delete or remove MmiHandler or MmiEntry now. + // Set the ToDelete field in MmiHandler so that MmiManage will delete it later // + MmiHandler->ToDelete = TRUE; return EFI_SUCCESS; } - if (IsListEmpty (&MmiEntry->MmiHandlers)) { - // - // No handler registered for this interrupt now, remove the MMI_ENTRY - // - RemoveEntryList (&MmiEntry->AllEntries); - - FreePool (MmiEntry); - } + RemoveMmiHandler (MmiHandler, MmiEntry); return EFI_SUCCESS; } -- 2.31.1.windows.1 -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#117354): https://edk2.groups.io/g/devel/message/117354 Mute This Topic: https://groups.io/mt/105304511/7686176 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io] -=-=-=-=-=-=-=-=-=-=-=-