]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Library/DxeSmmPerformanceLib/DxeSmmPerformanceLib.c
MdeModulePkg-FPDT(4): Use fixed buffer for SMM_PERF_COMMUNICATE in PerfLib.
[mirror_edk2.git] / MdeModulePkg / Library / DxeSmmPerformanceLib / DxeSmmPerformanceLib.c
index 3c69ceeb7d6a0297a2a5fff7d8f60bd5c2f91902..d8d06842734570df03bc933c386c2972c248b456 100644 (file)
@@ -5,7 +5,7 @@
   StartPerformanceMeasurement(), EndPerformanceMeasurement(), StartPerformanceMeasurementEx()\r
   and EndPerformanceMeasurementEx() are not implemented.\r
 \r
-  Copyright (c) 2011 - 2015, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2011 - 2016, Intel Corporation. All rights reserved.<BR>\r
 This program and the accompanying materials\r
 are licensed and made available under the terms and conditions of the BSD License\r
 which accompanies this distribution.  The full text of the license may be found at\r
@@ -32,15 +32,21 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 \r
 #include <Protocol/SmmCommunication.h>\r
 \r
+#include <Guid/PiSmmCommunicationRegionTable.h>\r
+#include <Library/UefiLib.h>\r
+\r
 #define SMM_PERFORMANCE_COMMUNICATION_BUFFER_SIZE (OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data)  + sizeof (SMM_PERF_COMMUNICATE))\r
 \r
 EFI_SMM_COMMUNICATION_PROTOCOL  *mSmmCommunication = NULL;\r
-UINT8                           mSmmPerformanceBuffer[SMM_PERFORMANCE_COMMUNICATION_BUFFER_SIZE];\r
+UINT8                           *mSmmPerformanceBuffer;\r
 GAUGE_DATA_ENTRY                *mGaugeData = NULL;\r
 UINTN                           mGaugeNumberOfEntries = 0;\r
 GAUGE_DATA_ENTRY_EX             *mGaugeDataEx = NULL;\r
 UINTN                           mGaugeNumberOfEntriesEx = 0;\r
 \r
+BOOLEAN                         mNoSmmPerfHandler = FALSE;\r
+BOOLEAN                         mNoSmmPerfExHandler = FALSE;\r
+\r
 //\r
 // The cached Performance Protocol and PerformanceEx Protocol interface.\r
 //\r
@@ -163,7 +169,7 @@ StartPerformanceMeasurementEx (
 /**\r
   Fills in the end time of a performance measurement.\r
 \r
-  Looks up the record that matches Handle, Token, Module and Identifier.\r
+  Looks up the record that matches Handle, Token and Module.\r
   If the record can not be found then return RETURN_NOT_FOUND.\r
   If the record is found and TimeStamp is not zero,\r
   then TimeStamp is added to the record as the end time.\r
@@ -372,7 +378,7 @@ GetByPerformanceProtocol (
                                   On exit, the key of the next performance log entry.\r
 \r
   @retval !NULL           Get all gauge data success.\r
-  @retval NULL            Get all guage data failed.\r
+  @retval NULL            Get all gauge data failed.\r
 **/\r
 GAUGE_DATA_ENTRY *\r
 EFIAPI\r
@@ -380,11 +386,26 @@ GetAllSmmGaugeData (
   IN UINTN      LogEntryKey\r
   )\r
 {\r
-  EFI_STATUS                  Status;\r
-  EFI_SMM_COMMUNICATE_HEADER  *SmmCommBufferHeader;\r
-  SMM_PERF_COMMUNICATE        *SmmPerfCommData;\r
-  UINTN                       CommSize;\r
-  UINTN                       DataSize;\r
+  EFI_STATUS                                Status;\r
+  EFI_SMM_COMMUNICATE_HEADER                *SmmCommBufferHeader;\r
+  SMM_PERF_COMMUNICATE                      *SmmPerfCommData;\r
+  UINTN                                     CommSize;\r
+  UINTN                                     DataSize;\r
+  EDKII_PI_SMM_COMMUNICATION_REGION_TABLE   *PiSmmCommunicationRegionTable;\r
+  UINT32                                    Index;\r
+  EFI_MEMORY_DESCRIPTOR                     *Entry;\r
+  UINT8                                     *Buffer;\r
+  UINTN                                     Size;\r
+  UINTN                                     NumberOfEntries;\r
+  UINTN                                     EntriesGot;\r
+\r
+  if (mNoSmmPerfHandler) {\r
+    //\r
+    // Not try to get the SMM gauge data again\r
+    // if no SMM Performance handler found.\r
+    //\r
+    return NULL;\r
+  }\r
 \r
   if (LogEntryKey != 0) {\r
     if (mGaugeData != NULL) {\r
@@ -392,7 +413,7 @@ GetAllSmmGaugeData (
     }\r
   } else {\r
     //\r
-    // Reget the SMM guage data at the first entry get.\r
+    // Reget the SMM gauge data at the first entry get.\r
     //\r
     if (mGaugeData != NULL) {\r
       FreePool (mGaugeData);\r
@@ -406,6 +427,28 @@ GetAllSmmGaugeData (
     return NULL;\r
   }\r
 \r
+  Status = EfiGetSystemConfigurationTable (\r
+             &gEdkiiPiSmmCommunicationRegionTableGuid,\r
+             (VOID **) &PiSmmCommunicationRegionTable\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    return NULL;\r
+  }\r
+  ASSERT (PiSmmCommunicationRegionTable != NULL);\r
+  Entry = (EFI_MEMORY_DESCRIPTOR *) (PiSmmCommunicationRegionTable + 1);\r
+  Size = 0;\r
+  for (Index = 0; Index < PiSmmCommunicationRegionTable->NumberOfEntries; Index++) {\r
+    if (Entry->Type == EfiConventionalMemory) {\r
+      Size = EFI_PAGES_TO_SIZE ((UINTN) Entry->NumberOfPages);\r
+      if (Size >= (SMM_PERFORMANCE_COMMUNICATION_BUFFER_SIZE + sizeof (GAUGE_DATA_ENTRY))) {\r
+        break;\r
+      }\r
+    }\r
+    Entry = (EFI_MEMORY_DESCRIPTOR *) ((UINT8 *) Entry + PiSmmCommunicationRegionTable->DescriptorSize);\r
+  }\r
+  ASSERT (Index < PiSmmCommunicationRegionTable->NumberOfEntries);\r
+  mSmmPerformanceBuffer = (UINT8 *) (UINTN) Entry->PhysicalStart;\r
+\r
   //\r
   // Initialize communicate buffer \r
   //\r
@@ -418,33 +461,49 @@ GetAllSmmGaugeData (
   CommSize = SMM_PERFORMANCE_COMMUNICATION_BUFFER_SIZE;\r
 \r
   //\r
-  // Get totol number of SMM gauge entries\r
+  // Get total number of SMM gauge entries\r
   //\r
   SmmPerfCommData->Function = SMM_PERF_FUNCTION_GET_GAUGE_ENTRY_NUMBER;\r
   Status = mSmmCommunication->Communicate (mSmmCommunication, mSmmPerformanceBuffer, &CommSize);\r
+  if (Status == EFI_NOT_FOUND) {\r
+    mNoSmmPerfHandler = TRUE;\r
+  }\r
   if (EFI_ERROR (Status) || EFI_ERROR (SmmPerfCommData->ReturnStatus) || SmmPerfCommData->NumberOfEntries == 0) {\r
     return NULL;\r
   }\r
 \r
   mGaugeNumberOfEntries = SmmPerfCommData->NumberOfEntries;\r
-  \r
+\r
+  Buffer = mSmmPerformanceBuffer + SMM_PERFORMANCE_COMMUNICATION_BUFFER_SIZE;\r
+  NumberOfEntries = (Size - SMM_PERFORMANCE_COMMUNICATION_BUFFER_SIZE) / sizeof (GAUGE_DATA_ENTRY);\r
   DataSize = mGaugeNumberOfEntries * sizeof(GAUGE_DATA_ENTRY);\r
   mGaugeData = AllocateZeroPool(DataSize);\r
   ASSERT (mGaugeData != NULL);\r
-  \r
+\r
   //\r
   // Get all SMM gauge data\r
   //  \r
   SmmPerfCommData->Function = SMM_PERF_FUNCTION_GET_GAUGE_DATA;\r
-  SmmPerfCommData->LogEntryKey = 0;\r
-  SmmPerfCommData->NumberOfEntries = mGaugeNumberOfEntries;\r
-  SmmPerfCommData->GaugeData = mGaugeData;\r
-  Status = mSmmCommunication->Communicate (mSmmCommunication, mSmmPerformanceBuffer, &CommSize);\r
-  if (EFI_ERROR (Status) || EFI_ERROR (SmmPerfCommData->ReturnStatus)) {\r
-    FreePool (mGaugeData);\r
-    mGaugeData = NULL;\r
-    mGaugeNumberOfEntries = 0;\r
-  }\r
+  SmmPerfCommData->GaugeData = (GAUGE_DATA_ENTRY *) Buffer;\r
+  EntriesGot = 0;\r
+  do {\r
+    SmmPerfCommData->LogEntryKey = EntriesGot;\r
+    if ((mGaugeNumberOfEntries - EntriesGot) >= NumberOfEntries) {\r
+      SmmPerfCommData->NumberOfEntries = NumberOfEntries;\r
+    } else {\r
+      SmmPerfCommData->NumberOfEntries = mGaugeNumberOfEntries - EntriesGot;\r
+    }\r
+    Status = mSmmCommunication->Communicate (mSmmCommunication, mSmmPerformanceBuffer, &CommSize);\r
+    if (EFI_ERROR (Status) || EFI_ERROR (SmmPerfCommData->ReturnStatus)) {\r
+      FreePool (mGaugeData);\r
+      mGaugeData = NULL;\r
+      mGaugeNumberOfEntries = 0;\r
+      return NULL;\r
+    } else {\r
+      CopyMem (&mGaugeData[EntriesGot], Buffer, SmmPerfCommData->NumberOfEntries * sizeof (GAUGE_DATA_ENTRY));\r
+    }\r
+    EntriesGot += SmmPerfCommData->NumberOfEntries;\r
+  } while (EntriesGot < mGaugeNumberOfEntries);\r
 \r
   return mGaugeData;\r
 }\r
@@ -459,7 +518,7 @@ GetAllSmmGaugeData (
                                   On exit, the key of the next performance log entry.\r
 \r
   @retval !NULL           Get all gauge data success.\r
-  @retval NULL            Get all guage data failed.\r
+  @retval NULL            Get all gauge data failed.\r
 **/\r
 GAUGE_DATA_ENTRY_EX *\r
 EFIAPI\r
@@ -467,11 +526,26 @@ GetAllSmmGaugeDataEx (
   IN UINTN      LogEntryKey\r
   )\r
 {\r
-  EFI_STATUS                  Status;\r
-  EFI_SMM_COMMUNICATE_HEADER  *SmmCommBufferHeader;\r
-  SMM_PERF_COMMUNICATE_EX     *SmmPerfCommData;\r
-  UINTN                       CommSize;\r
-  UINTN                       DataSize;\r
+  EFI_STATUS                                Status;\r
+  EFI_SMM_COMMUNICATE_HEADER                *SmmCommBufferHeader;\r
+  SMM_PERF_COMMUNICATE_EX                   *SmmPerfCommData;\r
+  UINTN                                     CommSize;\r
+  UINTN                                     DataSize;\r
+  EDKII_PI_SMM_COMMUNICATION_REGION_TABLE   *PiSmmCommunicationRegionTable;\r
+  UINT32                                    Index;\r
+  EFI_MEMORY_DESCRIPTOR                     *Entry;\r
+  UINT8                                     *Buffer;\r
+  UINTN                                     Size;\r
+  UINTN                                     NumberOfEntries;\r
+  UINTN                                     EntriesGot;\r
+\r
+  if (mNoSmmPerfExHandler) {\r
+    //\r
+    // Not try to get the SMM gauge data again\r
+    // if no SMM PerformanceEx handler found.\r
+    //\r
+    return NULL;\r
+  }\r
 \r
   if (LogEntryKey != 0) {\r
     if (mGaugeDataEx != NULL) {\r
@@ -479,7 +553,7 @@ GetAllSmmGaugeDataEx (
     }\r
   } else {\r
     //\r
-    // Reget the SMM guage data at the first entry get.\r
+    // Reget the SMM gauge data at the first entry get.\r
     //\r
     if (mGaugeDataEx != NULL) {\r
       FreePool (mGaugeDataEx);\r
@@ -493,6 +567,27 @@ GetAllSmmGaugeDataEx (
     return NULL;\r
   }\r
 \r
+  Status = EfiGetSystemConfigurationTable (\r
+             &gEdkiiPiSmmCommunicationRegionTableGuid,\r
+             (VOID **) &PiSmmCommunicationRegionTable\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    return NULL;\r
+  }\r
+  ASSERT (PiSmmCommunicationRegionTable != NULL);\r
+  Entry = (EFI_MEMORY_DESCRIPTOR *) (PiSmmCommunicationRegionTable + 1);\r
+  Size = 0;\r
+  for (Index = 0; Index < PiSmmCommunicationRegionTable->NumberOfEntries; Index++) {\r
+    if (Entry->Type == EfiConventionalMemory) {\r
+      Size = EFI_PAGES_TO_SIZE ((UINTN) Entry->NumberOfPages);\r
+      if (Size >= (SMM_PERFORMANCE_COMMUNICATION_BUFFER_SIZE + sizeof (GAUGE_DATA_ENTRY_EX))) {\r
+        break;\r
+      }\r
+    }\r
+    Entry = (EFI_MEMORY_DESCRIPTOR *) ((UINT8 *) Entry + PiSmmCommunicationRegionTable->DescriptorSize);\r
+  }\r
+  ASSERT (Index < PiSmmCommunicationRegionTable->NumberOfEntries);\r
+  mSmmPerformanceBuffer = (UINT8 *) (UINTN) Entry->PhysicalStart;\r
   //\r
   // Initialize communicate buffer \r
   //\r
@@ -505,34 +600,50 @@ GetAllSmmGaugeDataEx (
   CommSize = SMM_PERFORMANCE_COMMUNICATION_BUFFER_SIZE;\r
 \r
   //\r
-  // Get totol number of SMM gauge entries\r
+  // Get total number of SMM gauge entries\r
   //\r
   SmmPerfCommData->Function = SMM_PERF_FUNCTION_GET_GAUGE_ENTRY_NUMBER;\r
   Status = mSmmCommunication->Communicate (mSmmCommunication, mSmmPerformanceBuffer, &CommSize);\r
+  if (Status == EFI_NOT_FOUND) {\r
+    mNoSmmPerfExHandler = TRUE;\r
+  }\r
   if (EFI_ERROR (Status) || EFI_ERROR (SmmPerfCommData->ReturnStatus) || SmmPerfCommData->NumberOfEntries == 0) {\r
     return NULL;\r
   }\r
 \r
   mGaugeNumberOfEntriesEx = SmmPerfCommData->NumberOfEntries;\r
-  \r
+\r
+  Buffer = mSmmPerformanceBuffer + SMM_PERFORMANCE_COMMUNICATION_BUFFER_SIZE;\r
+  NumberOfEntries = (Size - SMM_PERFORMANCE_COMMUNICATION_BUFFER_SIZE) / sizeof (GAUGE_DATA_ENTRY_EX);\r
   DataSize = mGaugeNumberOfEntriesEx * sizeof(GAUGE_DATA_ENTRY_EX);\r
   mGaugeDataEx = AllocateZeroPool(DataSize);\r
   ASSERT (mGaugeDataEx != NULL);\r
-  \r
+\r
   //\r
   // Get all SMM gauge data\r
   //  \r
   SmmPerfCommData->Function = SMM_PERF_FUNCTION_GET_GAUGE_DATA;\r
-  SmmPerfCommData->LogEntryKey = 0;\r
-  SmmPerfCommData->NumberOfEntries = mGaugeNumberOfEntriesEx;\r
-  SmmPerfCommData->GaugeDataEx = mGaugeDataEx;\r
-  Status = mSmmCommunication->Communicate (mSmmCommunication, mSmmPerformanceBuffer, &CommSize);\r
-  if (EFI_ERROR (Status) || EFI_ERROR (SmmPerfCommData->ReturnStatus)) {\r
-    FreePool (mGaugeDataEx);\r
-    mGaugeDataEx = NULL;\r
-    mGaugeNumberOfEntriesEx = 0;\r
-  }\r
\r
+  SmmPerfCommData->GaugeDataEx = (GAUGE_DATA_ENTRY_EX *) Buffer;\r
+  EntriesGot = 0;\r
+  do {\r
+    SmmPerfCommData->LogEntryKey = EntriesGot;\r
+    if ((mGaugeNumberOfEntriesEx - EntriesGot) >= NumberOfEntries) {\r
+      SmmPerfCommData->NumberOfEntries = NumberOfEntries;\r
+    } else {\r
+      SmmPerfCommData->NumberOfEntries = mGaugeNumberOfEntriesEx - EntriesGot;\r
+    }\r
+    Status = mSmmCommunication->Communicate (mSmmCommunication, mSmmPerformanceBuffer, &CommSize);\r
+    if (EFI_ERROR (Status) || EFI_ERROR (SmmPerfCommData->ReturnStatus)) {\r
+      FreePool (mGaugeDataEx);\r
+      mGaugeDataEx = NULL;\r
+      mGaugeNumberOfEntriesEx = 0;\r
+      return NULL;\r
+    } else {\r
+      CopyMem (&mGaugeDataEx[EntriesGot], Buffer, SmmPerfCommData->NumberOfEntries * sizeof (GAUGE_DATA_ENTRY_EX));\r
+    }\r
+    EntriesGot += SmmPerfCommData->NumberOfEntries;\r
+  } while (EntriesGot < mGaugeNumberOfEntriesEx);\r
+\r
   return mGaugeDataEx;\r
 }\r
 \r
@@ -658,7 +769,15 @@ GetPerformanceMeasurementEx (
       GaugeData = (GAUGE_DATA_ENTRY_EX *) &mGaugeData[LogEntryKey++];\r
       *Identifier = 0;\r
     } else {\r
-      return 0;\r
+      return GetByPerformanceProtocol (\r
+               LogEntryKey,\r
+               Handle,\r
+               Token,\r
+               Module,\r
+               StartTimeStamp,\r
+               EndTimeStamp,\r
+               Identifier\r
+               );\r
     }\r
   }\r
 \r