From mboxrd@z Thu Jan 1 00:00:00 1970 Authentication-Results: mx.groups.io; dkim=missing; spf=fail (domain: intel.com, ip: , mailfrom: michael.a.kubacki@intel.com) Received: from mga01.intel.com (mga01.intel.com []) by groups.io with SMTP; Fri, 27 Sep 2019 18:47:35 -0700 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga001.jf.intel.com ([10.7.209.18]) by fmsmga101.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 27 Sep 2019 18:47:35 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.64,557,1559545200"; d="scan'208";a="274005134" Received: from makuback-desk1.amr.corp.intel.com ([10.7.159.162]) by orsmga001.jf.intel.com with ESMTP; 27 Sep 2019 18:47:35 -0700 From: "Kubacki, Michael A" To: devel@edk2.groups.io Cc: Dandan Bi , Ard Biesheuvel , Eric Dong , Laszlo Ersek , Liming Gao , Michael D Kinney , Ray Ni , Jian J Wang , Hao A Wu , Jiewen Yao Subject: [PATCH V2 8/9] MdeModulePkg/Variable: Add RT GetNextVariableName() cache support Date: Fri, 27 Sep 2019 18:47:16 -0700 Message-Id: <20190928014717.31372-9-michael.a.kubacki@intel.com> X-Mailer: git-send-email 2.16.2.windows.1 In-Reply-To: <20190928014717.31372-1-michael.a.kubacki@intel.com> References: <20190928014717.31372-1-michael.a.kubacki@intel.com> https://bugzilla.tianocore.org/show_bug.cgi?id=2220 This change implements the Runtime Service GetNextVariableName() using the Runtime Cache in VariableSmmRuntimeDxe. Runtime Service calls to GetNextVariableName() will no longer trigger a SW SMI. Overall system performance and stability will be improved by eliminating an SMI for these calls as they typically result in a relatively large number of invocations to retrieve all variable names in all variable stores present. Cc: Dandan Bi Cc: Ard Biesheuvel Cc: Eric Dong Cc: Laszlo Ersek Cc: Liming Gao Cc: Michael D Kinney Cc: Ray Ni Cc: Jian J Wang Cc: Hao A Wu Cc: Jiewen Yao Signed-off-by: Michael Kubacki --- MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.c | 118 +++++++++----------- 1 file changed, 50 insertions(+), 68 deletions(-) diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.c b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.c index 46f69765a4..bc3b56b0ce 100644 --- a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.c +++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.c @@ -799,87 +799,69 @@ RuntimeServiceGetNextVariableName ( IN OUT EFI_GUID *VendorGuid ) { - EFI_STATUS Status; - UINTN PayloadSize; - SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME *SmmGetNextVariableName; - UINTN OutVariableNameSize; - UINTN InVariableNameSize; + EFI_STATUS Status; + UINTN DelayIndex; + UINTN MaxLen; + UINTN VarNameSize; + VARIABLE_HEADER *VariablePtr; + VARIABLE_STORE_HEADER *VariableStoreHeader[VariableStoreTypeMax]; + + Status = EFI_NOT_FOUND; if (VariableNameSize == NULL || VariableName == NULL || VendorGuid == NULL) { return EFI_INVALID_PARAMETER; } - OutVariableNameSize = *VariableNameSize; - InVariableNameSize = StrSize (VariableName); - SmmGetNextVariableName = NULL; - // - // If input string exceeds SMM payload limit. Return failure + // Calculate the possible maximum length of name string, including the Null terminator. // - if (InVariableNameSize > mVariableBufferPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME, Name)) { + MaxLen = *VariableNameSize / sizeof (CHAR16); + if ((MaxLen == 0) || (StrnLenS (VariableName, MaxLen) == MaxLen)) { + // + // Null-terminator is not found in the first VariableNameSize bytes of the input VariableName buffer, + // follow spec to return EFI_INVALID_PARAMETER. + // return EFI_INVALID_PARAMETER; } - AcquireLockOnlyAtBootTime(&mVariableServicesLock); + AcquireLockOnlyAtBootTime (&mVariableServicesLock); - // - // Init the communicate buffer. The buffer data size is: - // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + PayloadSize. - // - if (OutVariableNameSize > mVariableBufferPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME, Name)) { - // - // If output buffer exceed SMM payload limit. Trim output buffer to SMM payload size - // - OutVariableNameSize = mVariableBufferPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME, Name); + for (DelayIndex = 0; mVariableRuntimeCacheReadLock && DelayIndex < VARIABLE_RT_CACHE_READ_LOCK_TIMEOUT; DelayIndex++) { + MicroSecondDelay (10); } - // - // Payload should be Guid + NameSize + MAX of Input & Output buffer - // - PayloadSize = OFFSET_OF (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME, Name) + MAX (OutVariableNameSize, InVariableNameSize); - - Status = InitCommunicateBuffer ((VOID **)&SmmGetNextVariableName, PayloadSize, SMM_VARIABLE_FUNCTION_GET_NEXT_VARIABLE_NAME); - if (EFI_ERROR (Status)) { - goto Done; - } - ASSERT (SmmGetNextVariableName != NULL); - - // - // SMM comm buffer->NameSize is buffer size for return string - // - SmmGetNextVariableName->NameSize = OutVariableNameSize; - - CopyGuid (&SmmGetNextVariableName->Guid, VendorGuid); - // - // Copy whole string - // - CopyMem (SmmGetNextVariableName->Name, VariableName, InVariableNameSize); - if (OutVariableNameSize > InVariableNameSize) { - ZeroMem ((UINT8 *) SmmGetNextVariableName->Name + InVariableNameSize, OutVariableNameSize - InVariableNameSize); - } - - // - // Send data to SMM - // - Status = SendCommunicateBuffer (PayloadSize); - - // - // Get data from SMM. - // - if (Status == EFI_SUCCESS || Status == EFI_BUFFER_TOO_SMALL) { - // - // SMM CommBuffer NameSize can be a trimed value - // Only update VariableNameSize when needed - // - *VariableNameSize = SmmGetNextVariableName->NameSize; - } - if (EFI_ERROR (Status)) { - goto Done; + if (DelayIndex < VARIABLE_RT_CACHE_READ_LOCK_TIMEOUT) { + ASSERT (!mVariableRuntimeCacheReadLock); + + CheckForRuntimeCacheSync (); + mVariableRuntimeCacheReadLock = TRUE; + + if (!mVariableRuntimeCachePendingUpdate) { + // + // 0: Volatile, 1: HOB, 2: Non-Volatile. + // The index and attributes mapping must be kept in this order as FindVariable + // makes use of this mapping to implement search algorithm. + // + VariableStoreHeader[VariableStoreTypeVolatile] = mVariableRuntimeVolatileCacheBuffer; + VariableStoreHeader[VariableStoreTypeHob] = mVariableRuntimeHobCacheBuffer; + VariableStoreHeader[VariableStoreTypeNv] = mVariableRuntimeNvCacheBuffer; + + Status = GetNextVariableEx (VariableName, VendorGuid, VariableStoreHeader, &VariablePtr); + if (!EFI_ERROR (Status)) { + VarNameSize = NameSizeOfVariable (VariablePtr); + ASSERT (VarNameSize != 0); + if (VarNameSize <= *VariableNameSize) { + CopyMem (VariableName, GetVariableNamePtr (VariablePtr), VarNameSize); + CopyMem (VendorGuid, GetVendorGuidPtr (VariablePtr), sizeof (EFI_GUID)); + Status = EFI_SUCCESS; + } else { + Status = EFI_BUFFER_TOO_SMALL; + } + + *VariableNameSize = VarNameSize; + } + } } - - CopyGuid (VendorGuid, &SmmGetNextVariableName->Guid); - CopyMem (VariableName, SmmGetNextVariableName->Name, SmmGetNextVariableName->NameSize); - -Done: + mVariableRuntimeCacheReadLock = FALSE; ReleaseLockOnlyAtBootTime (&mVariableServicesLock); return Status; } -- 2.16.2.windows.1