MdeModulePkg Variable: Enhance variable performance by reading from existed memory cache.

Current variable driver already have memory cache to improve performance.
Change the code which read from physical MMIO address to read from memory cache.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Derek Lin <derek.lin2@hpe.com>
Reviewed-by: Samer El-Haj-Mahmoud <elhaj@hpe.com>
Reviewed-by: Star Zeng <star.zeng@intel.com>

git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@18654 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
Derek Lin 2015-10-23 05:28:38 +00:00 committed by lzeng14
parent fbd2dfadfe
commit 9b18845a4b
2 changed files with 45 additions and 34 deletions

View File

@ -17,6 +17,7 @@
integer overflow. It should also check attribute to avoid authentication bypass. integer overflow. It should also check attribute to avoid authentication bypass.
Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR> Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR>
(C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>
This program and the accompanying materials This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at which accompanies this distribution. The full text of the license may be found at
@ -36,6 +37,11 @@ VARIABLE_MODULE_GLOBAL *mVariableModuleGlobal;
/// ///
VARIABLE_STORE_HEADER *mNvVariableCache = NULL; VARIABLE_STORE_HEADER *mNvVariableCache = NULL;
///
/// Memory cache of Fv Header.
///
EFI_FIRMWARE_VOLUME_HEADER *mNvFvHeaderCache = NULL;
/// ///
/// The memory entry used for variable statistics data. /// The memory entry used for variable statistics data.
/// ///
@ -333,7 +339,7 @@ UpdateVariableStore (
return EFI_INVALID_PARAMETER; return EFI_INVALID_PARAMETER;
} }
for (PtrBlockMapEntry = FwVolHeader->BlockMap; PtrBlockMapEntry->NumBlocks != 0; PtrBlockMapEntry++) { for (PtrBlockMapEntry = mNvFvHeaderCache->BlockMap; PtrBlockMapEntry->NumBlocks != 0; PtrBlockMapEntry++) {
for (BlockIndex2 = 0; BlockIndex2 < PtrBlockMapEntry->NumBlocks; BlockIndex2++) { for (BlockIndex2 = 0; BlockIndex2 < PtrBlockMapEntry->NumBlocks; BlockIndex2++) {
// //
// Check to see if the Variable Writes are spanning through multiple // Check to see if the Variable Writes are spanning through multiple
@ -2209,7 +2215,8 @@ UpdateVariable (
VariableStoreHeader = (VARIABLE_STORE_HEADER *) ((UINTN) mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase); VariableStoreHeader = (VARIABLE_STORE_HEADER *) ((UINTN) mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase);
Variable = &NvVariable; Variable = &NvVariable;
Variable->StartPtr = GetStartPointer (VariableStoreHeader); Variable->StartPtr = GetStartPointer (VariableStoreHeader);
Variable->EndPtr = GetEndPointer (VariableStoreHeader); Variable->EndPtr = (VARIABLE_HEADER *)((UINTN)Variable->StartPtr + ((UINTN)CacheVariable->EndPtr - (UINTN)CacheVariable->StartPtr));
Variable->CurrPtr = (VARIABLE_HEADER *)((UINTN)Variable->StartPtr + ((UINTN)CacheVariable->CurrPtr - (UINTN)CacheVariable->StartPtr)); Variable->CurrPtr = (VARIABLE_HEADER *)((UINTN)Variable->StartPtr + ((UINTN)CacheVariable->CurrPtr - (UINTN)CacheVariable->StartPtr));
if (CacheVariable->InDeletedTransitionPtr != NULL) { if (CacheVariable->InDeletedTransitionPtr != NULL) {
Variable->InDeletedTransitionPtr = (VARIABLE_HEADER *)((UINTN)Variable->StartPtr + ((UINTN)CacheVariable->InDeletedTransitionPtr - (UINTN)CacheVariable->StartPtr)); Variable->InDeletedTransitionPtr = (VARIABLE_HEADER *)((UINTN)Variable->StartPtr + ((UINTN)CacheVariable->InDeletedTransitionPtr - (UINTN)CacheVariable->StartPtr));
@ -2247,7 +2254,7 @@ UpdateVariable (
// //
// Only variable that have NV attributes can be updated/deleted in Runtime. // Only variable that have NV attributes can be updated/deleted in Runtime.
// //
if ((Variable->CurrPtr->Attributes & EFI_VARIABLE_NON_VOLATILE) == 0) { if ((CacheVariable->CurrPtr->Attributes & EFI_VARIABLE_NON_VOLATILE) == 0) {
Status = EFI_INVALID_PARAMETER; Status = EFI_INVALID_PARAMETER;
goto Done; goto Done;
} }
@ -2255,7 +2262,7 @@ UpdateVariable (
// //
// Only variable that have RT attributes can be updated/deleted in Runtime. // Only variable that have RT attributes can be updated/deleted in Runtime.
// //
if ((Variable->CurrPtr->Attributes & EFI_VARIABLE_RUNTIME_ACCESS) == 0) { if ((CacheVariable->CurrPtr->Attributes & EFI_VARIABLE_RUNTIME_ACCESS) == 0) {
Status = EFI_INVALID_PARAMETER; Status = EFI_INVALID_PARAMETER;
goto Done; goto Done;
} }
@ -2273,7 +2280,7 @@ UpdateVariable (
// Both ADDED and IN_DELETED_TRANSITION variable are present, // Both ADDED and IN_DELETED_TRANSITION variable are present,
// set IN_DELETED_TRANSITION one to DELETED state first. // set IN_DELETED_TRANSITION one to DELETED state first.
// //
State = Variable->InDeletedTransitionPtr->State; State = CacheVariable->InDeletedTransitionPtr->State;
State &= VAR_DELETED; State &= VAR_DELETED;
Status = UpdateVariableStore ( Status = UpdateVariableStore (
&mVariableModuleGlobal->VariableGlobal, &mVariableModuleGlobal->VariableGlobal,
@ -2294,7 +2301,7 @@ UpdateVariable (
} }
} }
State = Variable->CurrPtr->State; State = CacheVariable->CurrPtr->State;
State &= VAR_DELETED; State &= VAR_DELETED;
Status = UpdateVariableStore ( Status = UpdateVariableStore (
@ -2319,8 +2326,8 @@ UpdateVariable (
// If the variable is marked valid, and the same data has been passed in, // If the variable is marked valid, and the same data has been passed in,
// then return to the caller immediately. // then return to the caller immediately.
// //
if (DataSizeOfVariable (Variable->CurrPtr) == DataSize && if (DataSizeOfVariable (CacheVariable->CurrPtr) == DataSize &&
(CompareMem (Data, GetVariableDataPtr (Variable->CurrPtr), DataSize) == 0) && (CompareMem (Data, GetVariableDataPtr (CacheVariable->CurrPtr), DataSize) == 0) &&
((Attributes & EFI_VARIABLE_APPEND_WRITE) == 0) && ((Attributes & EFI_VARIABLE_APPEND_WRITE) == 0) &&
(TimeStamp == NULL)) { (TimeStamp == NULL)) {
// //
@ -2329,8 +2336,8 @@ UpdateVariable (
UpdateVariableInfo (VariableName, VendorGuid, Variable->Volatile, FALSE, TRUE, FALSE, FALSE); UpdateVariableInfo (VariableName, VendorGuid, Variable->Volatile, FALSE, TRUE, FALSE, FALSE);
Status = EFI_SUCCESS; Status = EFI_SUCCESS;
goto Done; goto Done;
} else if ((Variable->CurrPtr->State == VAR_ADDED) || } else if ((CacheVariable->CurrPtr->State == VAR_ADDED) ||
(Variable->CurrPtr->State == (VAR_ADDED & VAR_IN_DELETED_TRANSITION))) { (CacheVariable->CurrPtr->State == (VAR_ADDED & VAR_IN_DELETED_TRANSITION))) {
// //
// EFI_VARIABLE_APPEND_WRITE attribute only effects for existing variable. // EFI_VARIABLE_APPEND_WRITE attribute only effects for existing variable.
@ -2340,9 +2347,9 @@ UpdateVariable (
// NOTE: From 0 to DataOffset of NextVariable is reserved for Variable Header and Name. // NOTE: From 0 to DataOffset of NextVariable is reserved for Variable Header and Name.
// From DataOffset of NextVariable is to save the existing variable data. // From DataOffset of NextVariable is to save the existing variable data.
// //
DataOffset = GetVariableDataOffset (Variable->CurrPtr); DataOffset = GetVariableDataOffset (CacheVariable->CurrPtr);
BufferForMerge = (UINT8 *) ((UINTN) NextVariable + DataOffset); BufferForMerge = (UINT8 *) ((UINTN) NextVariable + DataOffset);
CopyMem (BufferForMerge, (UINT8 *) ((UINTN) Variable->CurrPtr + DataOffset), DataSizeOfVariable (Variable->CurrPtr)); CopyMem (BufferForMerge, (UINT8 *) ((UINTN) CacheVariable->CurrPtr + DataOffset), DataSizeOfVariable (CacheVariable->CurrPtr));
// //
// Set Max Common/Auth Variable Data Size as default MaxDataSize. // Set Max Common/Auth Variable Data Size as default MaxDataSize.
@ -2361,15 +2368,15 @@ UpdateVariable (
MaxDataSize = PcdGet32 (PcdMaxHardwareErrorVariableSize) - DataOffset; MaxDataSize = PcdGet32 (PcdMaxHardwareErrorVariableSize) - DataOffset;
} }
if (DataSizeOfVariable (Variable->CurrPtr) + DataSize > MaxDataSize) { if (DataSizeOfVariable (CacheVariable->CurrPtr) + DataSize > MaxDataSize) {
// //
// Existing data size + new data size exceed maximum variable size limitation. // Existing data size + new data size exceed maximum variable size limitation.
// //
Status = EFI_INVALID_PARAMETER; Status = EFI_INVALID_PARAMETER;
goto Done; goto Done;
} }
CopyMem ((UINT8*) ((UINTN) BufferForMerge + DataSizeOfVariable (Variable->CurrPtr)), Data, DataSize); CopyMem ((UINT8*) ((UINTN) BufferForMerge + DataSizeOfVariable (CacheVariable->CurrPtr)), Data, DataSize);
MergedBufSize = DataSizeOfVariable (Variable->CurrPtr) + DataSize; MergedBufSize = DataSizeOfVariable (CacheVariable->CurrPtr) + DataSize;
// //
// BufferForMerge(from DataOffset of NextVariable) has included the merged existing and new data. // BufferForMerge(from DataOffset of NextVariable) has included the merged existing and new data.
@ -2382,7 +2389,7 @@ UpdateVariable (
// //
// Mark the old variable as in delete transition. // Mark the old variable as in delete transition.
// //
State = Variable->CurrPtr->State; State = CacheVariable->CurrPtr->State;
State &= VAR_IN_DELETED_TRANSITION; State &= VAR_IN_DELETED_TRANSITION;
Status = UpdateVariableStore ( Status = UpdateVariableStore (
@ -2456,7 +2463,7 @@ UpdateVariable (
// with the variable, we need associate the new timestamp with the updated value. // with the variable, we need associate the new timestamp with the updated value.
// //
if (Variable->CurrPtr != NULL) { if (Variable->CurrPtr != NULL) {
if (VariableCompareTimeStampInternal (&(((AUTHENTICATED_VARIABLE_HEADER *) Variable->CurrPtr)->TimeStamp), TimeStamp)) { if (VariableCompareTimeStampInternal (&(((AUTHENTICATED_VARIABLE_HEADER *) CacheVariable->CurrPtr)->TimeStamp), TimeStamp)) {
CopyMem (&AuthVariable->TimeStamp, TimeStamp, sizeof (EFI_TIME)); CopyMem (&AuthVariable->TimeStamp, TimeStamp, sizeof (EFI_TIME));
} }
} }
@ -2712,7 +2719,7 @@ UpdateVariable (
// Both ADDED and IN_DELETED_TRANSITION old variable are present, // Both ADDED and IN_DELETED_TRANSITION old variable are present,
// set IN_DELETED_TRANSITION one to DELETED state first. // set IN_DELETED_TRANSITION one to DELETED state first.
// //
State = Variable->InDeletedTransitionPtr->State; State = CacheVariable->InDeletedTransitionPtr->State;
State &= VAR_DELETED; State &= VAR_DELETED;
Status = UpdateVariableStore ( Status = UpdateVariableStore (
&mVariableModuleGlobal->VariableGlobal, &mVariableModuleGlobal->VariableGlobal,
@ -3679,10 +3686,13 @@ InitNonVolatileVariableStore (
VariableStoreBase = (EFI_PHYSICAL_ADDRESS) ((UINTN) FvHeader + FvHeader->HeaderLength); VariableStoreBase = (EFI_PHYSICAL_ADDRESS) ((UINTN) FvHeader + FvHeader->HeaderLength);
VariableStoreLength = (UINT64) (NvStorageSize - FvHeader->HeaderLength); VariableStoreLength = (UINT64) (NvStorageSize - FvHeader->HeaderLength);
mNvFvHeaderCache = FvHeader;
mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase = VariableStoreBase; mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase = VariableStoreBase;
mNvVariableCache = (VARIABLE_STORE_HEADER *) (UINTN) VariableStoreBase; mNvVariableCache = (VARIABLE_STORE_HEADER *) (UINTN) VariableStoreBase;
if (GetVariableStoreStatus (mNvVariableCache) != EfiValid) { if (GetVariableStoreStatus (mNvVariableCache) != EfiValid) {
FreePool (NvStorageData); FreePool (NvStorageData);
mNvFvHeaderCache = NULL;
mNvVariableCache = NULL;
DEBUG((EFI_D_ERROR, "Variable Store header is corrupted\n")); DEBUG((EFI_D_ERROR, "Variable Store header is corrupted\n"));
return EFI_VOLUME_CORRUPTED; return EFI_VOLUME_CORRUPTED;
} }
@ -3858,7 +3868,6 @@ VariableWriteServiceInitialize (
) )
{ {
EFI_STATUS Status; EFI_STATUS Status;
VARIABLE_STORE_HEADER *VariableStoreHeader;
UINTN Index; UINTN Index;
UINT8 Data; UINT8 Data;
EFI_PHYSICAL_ADDRESS VariableStoreBase; EFI_PHYSICAL_ADDRESS VariableStoreBase;
@ -3871,18 +3880,17 @@ VariableWriteServiceInitialize (
if (NvStorageBase == 0) { if (NvStorageBase == 0) {
NvStorageBase = (EFI_PHYSICAL_ADDRESS) PcdGet32 (PcdFlashNvStorageVariableBase); NvStorageBase = (EFI_PHYSICAL_ADDRESS) PcdGet32 (PcdFlashNvStorageVariableBase);
} }
VariableStoreBase = NvStorageBase + (((EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)(NvStorageBase))->HeaderLength); VariableStoreBase = NvStorageBase + (mNvFvHeaderCache->HeaderLength);
// //
// Let NonVolatileVariableBase point to flash variable store base directly after FTW ready. // Let NonVolatileVariableBase point to flash variable store base directly after FTW ready.
// //
mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase = VariableStoreBase; mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase = VariableStoreBase;
VariableStoreHeader = (VARIABLE_STORE_HEADER *)(UINTN)VariableStoreBase;
// //
// Check if the free area is really free. // Check if the free area is really free.
// //
for (Index = mVariableModuleGlobal->NonVolatileLastVariableOffset; Index < VariableStoreHeader->Size; Index++) { for (Index = mVariableModuleGlobal->NonVolatileLastVariableOffset; Index < mNvVariableCache->Size; Index++) {
Data = ((UINT8 *) mNvVariableCache)[Index]; Data = ((UINT8 *) mNvVariableCache)[Index];
if (Data != 0xff) { if (Data != 0xff) {
// //

View File

@ -4,6 +4,7 @@
Copyright (C) 2013, Red Hat, Inc. Copyright (C) 2013, Red Hat, Inc.
Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR> Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR>
(C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>
This program and the accompanying materials This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at which accompanies this distribution. The full text of the license may be found at
@ -16,18 +17,19 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include "Variable.h" #include "Variable.h"
extern VARIABLE_STORE_HEADER *mNvVariableCache; extern VARIABLE_STORE_HEADER *mNvVariableCache;
extern VARIABLE_INFO_ENTRY *gVariableInfo; extern EFI_FIRMWARE_VOLUME_HEADER *mNvFvHeaderCache;
EFI_HANDLE mHandle = NULL; extern VARIABLE_INFO_ENTRY *gVariableInfo;
EFI_EVENT mVirtualAddressChangeEvent = NULL; EFI_HANDLE mHandle = NULL;
EFI_EVENT mFtwRegistration = NULL; EFI_EVENT mVirtualAddressChangeEvent = NULL;
extern BOOLEAN mEndOfDxe; EFI_EVENT mFtwRegistration = NULL;
VOID ***mVarCheckAddressPointer = NULL; extern BOOLEAN mEndOfDxe;
UINTN mVarCheckAddressPointerCount = 0; VOID ***mVarCheckAddressPointer = NULL;
EDKII_VARIABLE_LOCK_PROTOCOL mVariableLock = { VariableLockRequestToLock }; UINTN mVarCheckAddressPointerCount = 0;
EDKII_VAR_CHECK_PROTOCOL mVarCheck = { VarCheckRegisterSetVariableCheckHandler, EDKII_VARIABLE_LOCK_PROTOCOL mVariableLock = { VariableLockRequestToLock };
VarCheckVariablePropertySet, EDKII_VAR_CHECK_PROTOCOL mVarCheck = { VarCheckRegisterSetVariableCheckHandler,
VarCheckVariablePropertyGet }; VarCheckVariablePropertySet,
VarCheckVariablePropertyGet };
/** /**
Return TRUE if ExitBootServices () has been called. Return TRUE if ExitBootServices () has been called.
@ -243,6 +245,7 @@ VariableClassAddressChangeEvent (
EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->VariableGlobal.HobVariableBase); EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->VariableGlobal.HobVariableBase);
EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal); EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal);
EfiConvertPointer (0x0, (VOID **) &mNvVariableCache); EfiConvertPointer (0x0, (VOID **) &mNvVariableCache);
EfiConvertPointer (0x0, (VOID **) &mNvFvHeaderCache);
if (mAuthContextOut.AddressPointer != NULL) { if (mAuthContextOut.AddressPointer != NULL) {
for (Index = 0; Index < mAuthContextOut.AddressPointerCount; Index++) { for (Index = 0; Index < mAuthContextOut.AddressPointerCount; Index++) {