Home | History | Annotate | Download | only in FirmwarePerformanceDataTablePei
      1 /** @file
      2   This module updates S3 Resume Performance Record in ACPI Firmware Performance
      3   Data Table in S3 resume boot mode. In normal boot mode, this module consumes
      4   SecPerformance PPI produced by SEC phase and build Hob to convey the SEC
      5   performance data to DXE phase.
      6 
      7   This module register report status code listener to collect performance data
      8   for S3 Resume Performance Record on S3 resume boot path.
      9 
     10   Copyright (c) 2011 - 2015, Intel Corporation. All rights reserved.<BR>
     11   This program and the accompanying materials
     12   are licensed and made available under the terms and conditions of the BSD License
     13   which accompanies this distribution.  The full text of the license may be found at
     14   http://opensource.org/licenses/bsd-license.php
     15 
     16   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     17   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     18 
     19 **/
     20 
     21 #include <PiPei.h>
     22 
     23 #include <Ppi/ReportStatusCodeHandler.h>
     24 #include <Ppi/SecPerformance.h>
     25 
     26 #include <Guid/FirmwarePerformance.h>
     27 
     28 #include <Library/PeiServicesLib.h>
     29 #include <Library/BaseLib.h>
     30 #include <Library/DebugLib.h>
     31 #include <Library/TimerLib.h>
     32 #include <Library/BaseMemoryLib.h>
     33 #include <Library/LockBoxLib.h>
     34 #include <Library/HobLib.h>
     35 #include <Library/PcdLib.h>
     36 
     37 /**
     38   Report status code listener for PEI. This is used to record the performance
     39   data for S3 FullResume in FPDT.
     40 
     41   @param[in]  PeiServices         An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
     42   @param[in]  CodeType            Indicates the type of status code being reported.
     43   @param[in]  Value               Describes the current status of a hardware or software entity.
     44                                   This included information about the class and subclass that is used to
     45                                   classify the entity as well as an operation.
     46   @param[in]  Instance            The enumeration of a hardware or software entity within
     47                                   the system. Valid instance numbers start with 1.
     48   @param[in]  CallerId            This optional parameter may be used to identify the caller.
     49                                   This parameter allows the status code driver to apply different rules to
     50                                   different callers.
     51   @param[in]  Data                This optional parameter may be used to pass additional data.
     52 
     53   @retval EFI_SUCCESS             Status code is what we expected.
     54   @retval EFI_UNSUPPORTED         Status code not supported.
     55 
     56 **/
     57 EFI_STATUS
     58 EFIAPI
     59 FpdtStatusCodeListenerPei (
     60   IN CONST  EFI_PEI_SERVICES        **PeiServices,
     61   IN        EFI_STATUS_CODE_TYPE    CodeType,
     62   IN        EFI_STATUS_CODE_VALUE   Value,
     63   IN        UINT32                  Instance,
     64   IN CONST  EFI_GUID                *CallerId,
     65   IN CONST  EFI_STATUS_CODE_DATA    *Data
     66   )
     67 {
     68   EFI_STATUS                           Status;
     69   UINT64                               CurrentTime;
     70   UINTN                                VarSize;
     71   EFI_PHYSICAL_ADDRESS                 S3PerformanceTablePointer;
     72   S3_PERFORMANCE_TABLE                 *AcpiS3PerformanceTable;
     73   EFI_ACPI_5_0_FPDT_S3_RESUME_RECORD   *AcpiS3ResumeRecord;
     74   UINT64                               S3ResumeTotal;
     75   EFI_ACPI_5_0_FPDT_S3_SUSPEND_RECORD  S3SuspendRecord;
     76   EFI_ACPI_5_0_FPDT_S3_SUSPEND_RECORD  *AcpiS3SuspendRecord;
     77 
     78   //
     79   // Check whether status code is what we are interested in.
     80   //
     81   if (((CodeType & EFI_STATUS_CODE_TYPE_MASK) != EFI_PROGRESS_CODE) ||
     82   	  (Value != (EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_PC_OS_WAKE))) {
     83     return EFI_UNSUPPORTED;
     84   }
     85 
     86   //
     87   // Retrieve current time as early as possible.
     88   //
     89   CurrentTime = GetTimeInNanoSecond (GetPerformanceCounter ());
     90 
     91   //
     92   // Update S3 Resume Performance Record.
     93   //
     94   S3PerformanceTablePointer = 0;
     95   VarSize = sizeof (EFI_PHYSICAL_ADDRESS);
     96   Status = RestoreLockBox (&gFirmwarePerformanceS3PointerGuid, &S3PerformanceTablePointer, &VarSize);
     97   ASSERT_EFI_ERROR (Status);
     98 
     99   AcpiS3PerformanceTable = (S3_PERFORMANCE_TABLE *) (UINTN) S3PerformanceTablePointer;
    100   ASSERT (AcpiS3PerformanceTable != NULL);
    101   if (AcpiS3PerformanceTable->Header.Signature != EFI_ACPI_5_0_FPDT_S3_PERFORMANCE_TABLE_SIGNATURE) {
    102     DEBUG ((EFI_D_ERROR, "FPDT S3 performance data in ACPI memory get corrupted\n"));
    103     return EFI_ABORTED;
    104   }
    105   AcpiS3ResumeRecord = &AcpiS3PerformanceTable->S3Resume;
    106   AcpiS3ResumeRecord->FullResume = CurrentTime;
    107   //
    108   // Calculate average S3 resume time.
    109   //
    110   S3ResumeTotal = MultU64x32 (AcpiS3ResumeRecord->AverageResume, AcpiS3ResumeRecord->ResumeCount);
    111   AcpiS3ResumeRecord->ResumeCount++;
    112   AcpiS3ResumeRecord->AverageResume = DivU64x32 (S3ResumeTotal + AcpiS3ResumeRecord->FullResume, AcpiS3ResumeRecord->ResumeCount);
    113 
    114   DEBUG ((EFI_D_INFO, "FPDT: S3 Resume Performance - ResumeCount   = %d\n", AcpiS3ResumeRecord->ResumeCount));
    115   DEBUG ((EFI_D_INFO, "FPDT: S3 Resume Performance - FullResume    = %ld\n", AcpiS3ResumeRecord->FullResume));
    116   DEBUG ((EFI_D_INFO, "FPDT: S3 Resume Performance - AverageResume = %ld\n", AcpiS3ResumeRecord->AverageResume));
    117 
    118   //
    119   // Update S3 Suspend Performance Record.
    120   //
    121   AcpiS3SuspendRecord = &AcpiS3PerformanceTable->S3Suspend;
    122   VarSize = sizeof (EFI_ACPI_5_0_FPDT_S3_SUSPEND_RECORD);
    123   ZeroMem (&S3SuspendRecord, sizeof (EFI_ACPI_5_0_FPDT_S3_SUSPEND_RECORD));
    124   Status = RestoreLockBox (
    125              &gEfiFirmwarePerformanceGuid,
    126              &S3SuspendRecord,
    127              &VarSize
    128              );
    129   ASSERT_EFI_ERROR (Status);
    130 
    131   AcpiS3SuspendRecord->SuspendStart = S3SuspendRecord.SuspendStart;
    132   AcpiS3SuspendRecord->SuspendEnd   = S3SuspendRecord.SuspendEnd;
    133 
    134   DEBUG ((EFI_D_INFO, "FPDT: S3 Suspend Performance - SuspendStart = %ld\n", AcpiS3SuspendRecord->SuspendStart));
    135   DEBUG ((EFI_D_INFO, "FPDT: S3 Suspend Performance - SuspendEnd   = %ld\n", AcpiS3SuspendRecord->SuspendEnd));
    136 
    137   return EFI_SUCCESS;
    138 }
    139 
    140 /**
    141   Main entry for Firmware Performance Data Table PEIM.
    142 
    143   This routine is to register report status code listener for FPDT.
    144 
    145   @param[in]  FileHandle              Handle of the file being invoked.
    146   @param[in]  PeiServices             Pointer to PEI Services table.
    147 
    148   @retval EFI_SUCCESS Report status code listener is registered successfully.
    149 
    150 **/
    151 EFI_STATUS
    152 EFIAPI
    153 FirmwarePerformancePeiEntryPoint (
    154   IN       EFI_PEI_FILE_HANDLE  FileHandle,
    155   IN CONST EFI_PEI_SERVICES     **PeiServices
    156   )
    157 {
    158   EFI_STATUS               Status;
    159   EFI_PEI_RSC_HANDLER_PPI  *RscHandler;
    160   PEI_SEC_PERFORMANCE_PPI  *SecPerf;
    161   FIRMWARE_SEC_PERFORMANCE Performance;
    162 
    163   if (FeaturePcdGet (PcdFirmwarePerformanceDataTableS3Support)) {
    164     //
    165     // S3 resume - register status code listener for OS wake vector.
    166     //
    167     Status = PeiServicesLocatePpi (
    168                &gEfiPeiRscHandlerPpiGuid,
    169                0,
    170                NULL,
    171                (VOID **) &RscHandler
    172                );
    173     ASSERT_EFI_ERROR (Status);
    174 
    175     Status = RscHandler->Register (FpdtStatusCodeListenerPei);
    176     ASSERT_EFI_ERROR (Status);
    177   }
    178 
    179   //
    180   // Normal boot - build Hob for SEC performance data.
    181   //
    182   Status = PeiServicesLocatePpi (
    183              &gPeiSecPerformancePpiGuid,
    184              0,
    185              NULL,
    186              (VOID **) &SecPerf
    187              );
    188   if (!EFI_ERROR (Status)) {
    189     Status = SecPerf->GetPerformance (PeiServices, SecPerf, &Performance);
    190   }
    191   if (!EFI_ERROR (Status)) {
    192     BuildGuidDataHob (
    193       &gEfiFirmwarePerformanceGuid,
    194       &Performance,
    195       sizeof (FIRMWARE_SEC_PERFORMANCE)
    196     );
    197     DEBUG ((EFI_D_INFO, "FPDT: SEC Performance Hob ResetEnd = %ld\n", Performance.ResetEnd));
    198   } else {
    199     //
    200     // SEC performance PPI is not installed or fail to get performance data
    201     // from SEC Performance PPI.
    202     //
    203     DEBUG ((EFI_D_ERROR, "FPDT: WARNING: SEC Performance PPI not installed or failed!\n"));
    204   }
    205 
    206   return EFI_SUCCESS;
    207 }
    208