From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received-SPF: Pass (sender SPF authorized) identity=mailfrom; client-ip=134.134.136.24; helo=mga09.intel.com; envelope-from=star.zeng@intel.com; receiver=edk2-devel-bounces@lists.01.org Received: from mga09.intel.com (mga09.intel.com [134.134.136.24]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id E9E6A211799DD; Thu, 25 Oct 2018 18:18:20 -0700 (PDT) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga006.jf.intel.com ([10.7.209.51]) by orsmga102.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 25 Oct 2018 18:18:20 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.54,426,1534834800"; d="scan'208";a="85675434" Received: from shzintpr01.sh.intel.com (HELO [10.7.209.51]) ([10.239.4.80]) by orsmga006.jf.intel.com with ESMTP; 25 Oct 2018 18:18:18 -0700 To: "Wang, Jian J" , edk2-devel , "edk2-devel@lists.01.org" Cc: "Kinney, Michael D" , "Ni, Ruiyu" , "Yao, Jiewen" , Laszlo Ersek , star.zeng@intel.com References: <20181025071805.6692-1-jian.j.wang@intel.com> <20181025071805.6692-6-jian.j.wang@intel.com> From: "Zeng, Star" Message-ID: <07f75e43-8aeb-918c-4e3e-afea1d82c924@intel.com> Date: Fri, 26 Oct 2018 09:17:48 +0800 User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; rv:52.0) Gecko/20100101 Thunderbird/52.9.1 MIME-Version: 1.0 In-Reply-To: Subject: Re: [PATCH v4 5/6] MdeModulePkg/Core: prevent re-acquire GCD memory lock X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 26 Oct 2018 01:18:21 -0000 Content-Type: text/plain; charset=utf-8; format=flowed Content-Language: en-US Content-Transfer-Encoding: 7bit On 2018/10/25 15:20, Wang, Jian J wrote: > Sorry, forgot to update commit message: > >> This issue is hidden in current code but exposed by introduction >> of freed-memory guard feature due to the fact that the feature >> will turn all pool allocation to page allocation. >> >> The solution is moving the memory allocation in CoreGetMemorySpaceMap() >> to be out of the GCD memory map lock. > > Regards, > Jian > > >> -----Original Message----- >> From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] >> Sent: Thursday, October 25, 2018 3:18 PM >> To: edk2-devel@lists.01.org >> Cc: Kinney, Michael D ; Ni, Ruiyu >> ; Yao, Jiewen ; Zeng, Star >> ; Laszlo Ersek >> Subject: [edk2] [PATCH v4 5/6] MdeModulePkg/Core: prevent re-acquire GCD >> memory lock >> >>> v4 changes: >>> a. add more comments from Laszlo >> >> This issue is hidden in current code but exposed by introduction >> of freed-memory guard feature due to the fact that the feature >> will turn all pool allocation to page allocation. >> >> The solution is move the memory allocation in CoreGetMemorySpaceMap() >> and CoreGetIoSpaceMap() to be out of the GCD memory map lock. >> >> CoreDumpGcdMemorySpaceMap() >> => CoreGetMemorySpaceMap() >> => CoreAcquireGcdMemoryLock () * >> AllocatePool() >> => InternalAllocatePool() >> => CoreAllocatePool() >> => CoreAllocatePoolI() >> => CoreAllocatePoolPagesI() >> => CoreAllocatePoolPages() >> => FindFreePages() >> => PromoteMemoryResource() >> => CoreAcquireGcdMemoryLock() ** >> >> Cc: Star Zeng >> Cc: Michael D Kinney >> Cc: Jiewen Yao >> Cc: Ruiyu Ni >> Cc: Laszlo Ersek >> Contributed-under: TianoCore Contribution Agreement 1.1 >> Signed-off-by: Jian J Wang >> --- >> MdeModulePkg/Core/Dxe/Gcd/Gcd.c | 87 +++++++++++++++++++++++++++++- >> ----------- >> 1 file changed, 62 insertions(+), 25 deletions(-) >> >> diff --git a/MdeModulePkg/Core/Dxe/Gcd/Gcd.c >> b/MdeModulePkg/Core/Dxe/Gcd/Gcd.c >> index d9c65a8045..f99d6bb933 100644 >> --- a/MdeModulePkg/Core/Dxe/Gcd/Gcd.c >> +++ b/MdeModulePkg/Core/Dxe/Gcd/Gcd.c >> @@ -1691,10 +1691,10 @@ CoreGetMemorySpaceMap ( >> OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR **MemorySpaceMap >> ) >> { >> - EFI_STATUS Status; >> LIST_ENTRY *Link; >> EFI_GCD_MAP_ENTRY *Entry; >> EFI_GCD_MEMORY_SPACE_DESCRIPTOR *Descriptor; >> + UINTN DescriptorCount; >> >> // >> // Make sure parameters are valid >> @@ -1706,38 +1706,75 @@ CoreGetMemorySpaceMap ( >> return EFI_INVALID_PARAMETER; >> } >> >> - CoreAcquireGcdMemoryLock (); >> + *NumberOfDescriptors = 0; >> + *MemorySpaceMap = NULL; >> >> // >> - // Count the number of descriptors >> + // Take the lock, for entering the loop with the lock held. >> // >> - *NumberOfDescriptors = CoreCountGcdMapEntry (&mGcdMemorySpaceMap); >> + CoreAcquireGcdMemoryLock (); >> + while (TRUE) { >> + // >> + // Count the number of descriptors. It might be done more than once How about using "Count the descriptors" here? No need to send new patch series for it. >> because >> + // there's code which has to be running outside the GCD lock. I have given comment for this line at V3 series. How about using "AllocatePool() calling code below" instead of "there's code" to be more specific? Thanks, Star >> + // >> + DescriptorCount = CoreCountGcdMapEntry (&mGcdMemorySpaceMap); >> + if (DescriptorCount == *NumberOfDescriptors) { >> + // >> + // Fill in the MemorySpaceMap if no memory space map change. >> + // >> + Descriptor = *MemorySpaceMap; >> + Link = mGcdMemorySpaceMap.ForwardLink; >> + while (Link != &mGcdMemorySpaceMap) { >> + Entry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE); >> + BuildMemoryDescriptor (Descriptor, Entry); >> + Descriptor++; >> + Link = Link->ForwardLink; >> + } >> + // >> + // We're done; exit the loop with the lock held. >> + // >> + break; >> + } >> >> - // >> - // Allocate the MemorySpaceMap >> - // >> - *MemorySpaceMap = AllocatePool (*NumberOfDescriptors * sizeof >> (EFI_GCD_MEMORY_SPACE_DESCRIPTOR)); >> - if (*MemorySpaceMap == NULL) { >> - Status = EFI_OUT_OF_RESOURCES; >> - goto Done; >> - } >> + // >> + // Release the lock before memory allocation, because it might cause >> + // GCD lock conflict in one of calling path in AllocatPool(). >> + // >> + CoreReleaseGcdMemoryLock (); >> + >> + // >> + // Allocate memory to store the MemorySpaceMap. Note it might be already >> + // allocated if there's map descriptor change during memory allocation at >> + // last time. >> + // >> + if (*MemorySpaceMap != NULL) { >> + FreePool (*MemorySpaceMap); >> + } >> >> + *MemorySpaceMap = AllocatePool (DescriptorCount * >> + sizeof (EFI_GCD_MEMORY_SPACE_DESCRIPTOR)); >> + if (*MemorySpaceMap == NULL) { >> + *NumberOfDescriptors = 0; >> + return EFI_OUT_OF_RESOURCES; >> + } >> + >> + // >> + // Save the descriptor count got before for another round of check to make >> + // sure we won't miss any, since we have code running outside the GCD lock. >> + // >> + *NumberOfDescriptors = DescriptorCount; >> + // >> + // Re-acquire the lock, for the next iteration. >> + // >> + CoreAcquireGcdMemoryLock (); >> + } >> // >> - // Fill in the MemorySpaceMap >> + // We exited the loop with the lock held, release it. >> // >> - Descriptor = *MemorySpaceMap; >> - Link = mGcdMemorySpaceMap.ForwardLink; >> - while (Link != &mGcdMemorySpaceMap) { >> - Entry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE); >> - BuildMemoryDescriptor (Descriptor, Entry); >> - Descriptor++; >> - Link = Link->ForwardLink; >> - } >> - Status = EFI_SUCCESS; >> - >> -Done: >> CoreReleaseGcdMemoryLock (); >> - return Status; >> + >> + return EFI_SUCCESS; >> } >> >> >> -- >> 2.16.2.windows.1 >> >> _______________________________________________ >> edk2-devel mailing list >> edk2-devel@lists.01.org >> https://lists.01.org/mailman/listinfo/edk2-devel