MdeModulePkg-FPDT(4): Use fixed buffer for SMM_PERF_COMMUNICATE in PerfLib.
authorLiming Gao <liming.gao@intel.com>
Fri, 22 Apr 2016 07:32:30 +0000 (15:32 +0800)
committerJiewen Yao <jiewen.yao@intel.com>
Fri, 29 Apr 2016 04:49:21 +0000 (12:49 +0800)
This patch enhance performance data SMM communication by using fixed
SMM communication buffer.

Update PerformanceLib to use fixed SMM communication buffer to get
performance data by SMM_PERF_COMMUNICATE API.

This is designed to meet Microsoft WSMT table definition on FIXED_COMM_BUFFERS
requirement.

Cc: Liming Gao <liming.gao@intel.com>
Cc: Feng Tian <feng.tian@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Liming Gao <liming.gao@intel.com>
Reviewed-by: Feng Tian <feng.tian@intel.com>
MdeModulePkg/Library/DxeSmmPerformanceLib/DxeSmmPerformanceLib.c
MdeModulePkg/Library/DxeSmmPerformanceLib/DxeSmmPerformanceLib.inf

index 218cf8b..d8d0684 100644 (file)
@@ -32,10 +32,13 @@ 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
@@ -383,11 +386,18 @@ 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
@@ -417,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
@@ -441,24 +473,37 @@ GetAllSmmGaugeData (
   }\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
@@ -481,11 +526,18 @@ 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
@@ -515,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
@@ -539,25 +612,38 @@ GetAllSmmGaugeDataEx (
   }\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
index a661328..2dbaa7c 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
@@ -54,6 +54,7 @@
   gPerformanceExProtocolGuid            ## SOMETIMES_CONSUMES   ## UNDEFINED # Locate protocol\r
   gSmmPerformanceProtocolGuid           ## SOMETIMES_PRODUCES   ## UNDEFINED # Used to do smm communication\r
   gSmmPerformanceExProtocolGuid         ## SOMETIMES_PRODUCES   ## UNDEFINED # Used to do smm communication\r
+  gEdkiiPiSmmCommunicationRegionTableGuid    ## CONSUMES ## SystemTable\r
 \r
 [Protocols]\r
   gEfiSmmCommunicationProtocolGuid      ## CONSUMES\r