diff options
author | raywu <raywu0301@gmail.com> | 2018-06-15 00:00:50 +0800 |
---|---|---|
committer | raywu <raywu0301@gmail.com> | 2018-06-15 00:00:50 +0800 |
commit | b7c51c9cf4864df6aabb99a1ae843becd577237c (patch) | |
tree | eebe9b0d0ca03062955223097e57da84dd618b9a /EDK/Foundation/Library/Pei/PeiLib/Perf.c | |
download | zprj-b7c51c9cf4864df6aabb99a1ae843becd577237c.tar.xz |
Diffstat (limited to 'EDK/Foundation/Library/Pei/PeiLib/Perf.c')
-rw-r--r-- | EDK/Foundation/Library/Pei/PeiLib/Perf.c | 362 |
1 files changed, 362 insertions, 0 deletions
diff --git a/EDK/Foundation/Library/Pei/PeiLib/Perf.c b/EDK/Foundation/Library/Pei/PeiLib/Perf.c new file mode 100644 index 0000000..86b8d62 --- /dev/null +++ b/EDK/Foundation/Library/Pei/PeiLib/Perf.c @@ -0,0 +1,362 @@ +/*++ + +Copyright (c) 2004 - 2012, Intel Corporation +All rights reserved. This program and the accompanying materials +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 +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + Perf.c + +Abstract: + + Support for FPDT performance structures. + +--*/ + +#include "Tiano.h" +#include "Pei.h" +#include "PeiLib.h" +#include "PeiHob.h" +#include "CpuIA32.h" +#include "EfiCommonLib.h" + +#include EFI_GUID_DEFINITION (PeiPerformanceHob) + +#define MSR_PLATFORM_INFO 0xce +#define MAX_NON_TURBO_RATIO_OFFSET 8 +#define MAX_NON_TURBO_RATIO_MASK 0xff +#define LOCAL_APIC_BASE 0xfee00000 +#define APIC_ID_REGISTER 0x20 +#define MSR_EXT_XAPIC_LOGICAL_APIC_ID 0x802 +#define MSR_XAPIC_BASE 0x1b +#define MSR_XAPIC_BASE_MASK 0x0c00 + +#define MAX_FIRMWARE_PERFORMANCE_ENTRIES 80 + +// +// Prototype functions +// +UINT64 +IA32API +EfiReadMsr ( + IN UINT32 Index + ); + +UINT64 GetTimeInNanoSec ( + UINT64 Ticker + ) +/*++ + +Routine Description: + + Internal routine to convert TSC value into nano second value + +Arguments: + + Ticker - OPTIONAL. TSC value supplied by caller function + +Returns: + + UINT64 - returns calculated timer value + +--*/ +{ + UINT64 Tick, pi; + UINT8 Ratio; + + if(Ticker != 0){ + Tick = Ticker; + } else { + Tick = EfiReadTsc(); + } + + pi = EfiReadMsr(MSR_PLATFORM_INFO); + Ratio = (UINT8)( ((UINT32)(UINTN)RShiftU64(pi, MAX_NON_TURBO_RATIO_OFFSET)) & MAX_NON_TURBO_RATIO_MASK); + + return (UINT64)DivU64x32(MultU64x32(Tick, 10), (UINTN)(Ratio), NULL); +} + + +UINT32 GetApicId ( + VOID + ) +/*++ + +Routine Description: + + Internal routine to retrieve current APIC Id + +Arguments: + + None + +Returns: + + UINT32 - returns Apic Id value + +--*/ +{ + BOOLEAN x2ApicEnabled; + UINT32 ApicId; + + x2ApicEnabled = (BOOLEAN)(((EfiReadMsr (MSR_XAPIC_BASE)) & (MSR_XAPIC_BASE_MASK)) == MSR_XAPIC_BASE_MASK); + if (x2ApicEnabled) { + ApicId = (UINT32) EfiReadMsr (MSR_EXT_XAPIC_LOGICAL_APIC_ID); + } else { + ApicId = (UINT8) (*(volatile UINT32 *) (UINTN) (LOCAL_APIC_BASE + APIC_ID_REGISTER) >> 24); + } + + return ApicId; +} + +VOID +PeiPerfMeasureEx ( + EFI_PEI_SERVICES **PeiServices, + IN UINT16 *Token, + IN EFI_FFS_FILE_HEADER *FileHeader, + IN UINT16 Identifier, + IN BOOLEAN EntryExit, + IN UINT64 Value + ) +/*++ + +Routine Description: + + Log an extended timestamp value. + +Arguments: + + PeiServices - Pointer to the PEI Core Services table + + Token - Pointer to Token Name + + FileHeader - Pointer to the file header + + Identifier - Identifier of the record + + EntryExit - Indicates start or stop measurement + + Value - The TSC value + +Returns: + + None + +--*/ +{ + EFI_STATUS Status; + EFI_PEI_PPI_DESCRIPTOR *PerfHobDescriptor; + PEI_FIRMWARE_PERFORMANCE_HOB *FirmwarePerformanceHob; + PEI_GUID_EVENT_REC *PeiGuidRec; + // + // Locate the Pei Performance Log Hob. + // + Status = (*PeiServices)->LocatePpi ( + PeiServices, + &gPeiFirmwarePerformanceGuid, + 0, + &PerfHobDescriptor, + NULL + ); + if (!EFI_ERROR(Status)) { + FirmwarePerformanceHob = (PEI_FIRMWARE_PERFORMANCE_HOB *)(((UINT8 *)(PerfHobDescriptor)) - + ((sizeof(PEI_GUID_EVENT_REC) * (MAX_FIRMWARE_PERFORMANCE_ENTRIES-1)) + + sizeof(PEI_FIRMWARE_PERFORMANCE_HOB) + ) + ); + + // + // return if performance buffer has filled up + // + if (FirmwarePerformanceHob->NumberOfEntries >= MAX_FIRMWARE_PERFORMANCE_ENTRIES) { + return; + } + + PeiGuidRec = &(FirmwarePerformanceHob->GuidEventRecord[FirmwarePerformanceHob->NumberOfEntries]); + (*PeiServices)->SetMem (PeiGuidRec, sizeof(PEI_GUID_EVENT_REC), 0); + + // + // Get the GUID name + // + if (FileHeader != NULL) { + PeiGuidRec->Guid = FileHeader->Name; + } + + // + // Record the time stamp nanosec value. + // + PeiGuidRec->Timestamp = GetTimeInNanoSec(Value); + + // + // Copy the progress ID + // + PeiGuidRec->ProgressID = Identifier; + + // + // Record the APIC Id + // + PeiGuidRec->ApicID = GetApicId(); + + // + // Increment the number of valid log entries. + // + FirmwarePerformanceHob->NumberOfEntries++; + } + + return; +} + +VOID +PeiPerfMeasure ( + EFI_PEI_SERVICES **PeiServices, + IN UINT16 *Token, + IN EFI_FFS_FILE_HEADER *FileHeader, + IN BOOLEAN EntryExit, + IN UINT64 Value + ) +/*++ + +Routine Description: + + Log a timestamp count. + +Arguments: + + PeiServices - Pointer to the PEI Core Services table + + Token - Pointer to Token Name + + FileHeader - Pointer to the file header + + EntryExit - Indicates start or stop measurement + + Value - The start time or the stop time + +Returns: + +--*/ +{ + EFI_STATUS Status; + EFI_HOB_GUID_TYPE *Hob; + PEI_FIRMWARE_PERFORMANCE_HOB *FirmwarePerformanceHob; + EFI_PEI_PPI_DESCRIPTOR *PerfHobDescriptor; + PEI_GUID_EVENT_REC *PeiGuidRec; + // + // Locate the Pei Performance Log Hob. + // + Status = (*PeiServices)->LocatePpi ( + PeiServices, + &gPeiFirmwarePerformanceGuid, + 0, + &PerfHobDescriptor, + NULL + ); + + // + // If the Performance Hob was not found, build and install one. + // + if (EFI_ERROR(Status)) { + Status = PeiBuildHobGuid ( + PeiServices, + &gPeiFirmwarePerformanceGuid, + (sizeof(PEI_FIRMWARE_PERFORMANCE_HOB) + + ((MAX_FIRMWARE_PERFORMANCE_ENTRIES-1) * + sizeof(PEI_GUID_EVENT_REC)) + + sizeof(EFI_PEI_PPI_DESCRIPTOR) + ), + &Hob + ); + ASSERT_PEI_ERROR(PeiServices, Status); + + FirmwarePerformanceHob = (PEI_FIRMWARE_PERFORMANCE_HOB *)(Hob+1); + FirmwarePerformanceHob->NumberOfEntries = 0; + FirmwarePerformanceHob->Reserved = 0; + + PerfHobDescriptor = (EFI_PEI_PPI_DESCRIPTOR *)((UINT8 *)(FirmwarePerformanceHob+1) + + (sizeof(PEI_GUID_EVENT_REC) * + (MAX_FIRMWARE_PERFORMANCE_ENTRIES-1) + ) + ); + PerfHobDescriptor->Flags = (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST); + PerfHobDescriptor->Guid = &gPeiFirmwarePerformanceGuid; + PerfHobDescriptor->Ppi = NULL; + + (*PeiServices)->InstallPpi (PeiServices, PerfHobDescriptor); + ASSERT_PEI_ERROR(PeiServices, Status); + } + + FirmwarePerformanceHob = (PEI_FIRMWARE_PERFORMANCE_HOB *)(((UINT8 *)(PerfHobDescriptor)) - + ((sizeof(PEI_GUID_EVENT_REC) * + (MAX_FIRMWARE_PERFORMANCE_ENTRIES-1) + ) + + sizeof(PEI_FIRMWARE_PERFORMANCE_HOB) + ) + ); + + if (FirmwarePerformanceHob->NumberOfEntries >= MAX_FIRMWARE_PERFORMANCE_ENTRIES) { + return; + } + + PeiGuidRec = &(FirmwarePerformanceHob->GuidEventRecord[FirmwarePerformanceHob->NumberOfEntries]); + (*PeiServices)->SetMem (PeiGuidRec, sizeof(PEI_GUID_EVENT_REC), 0); + + // + // If not NULL pointer, copy the file name + // + if (FileHeader != NULL) { + PeiGuidRec->Guid = FileHeader->Name; + } + + // + // Record the time stamp nanosec value. + // + PeiGuidRec->Timestamp = GetTimeInNanoSec(Value); + + // + // Record the Progress Id based upon token field + // + if (!EfiStrCmp (Token, L"PEIM")) { + if(!EntryExit) { + PeiGuidRec->ProgressID = PEIM_START_ID; + } else { + PeiGuidRec->ProgressID = PEIM_END_ID; + } + } else if (!EfiStrCmp (Token, L"PreMem")) { + if(!EntryExit) { + PeiGuidRec->ProgressID = PREMEM_START_ID; + } else { + PeiGuidRec->ProgressID = PREMEM_END_ID; + } + } else if (!EfiStrCmp (Token, L"DisMem")) { + if(!EntryExit) { + PeiGuidRec->ProgressID = DISMEM_START_ID; + } else { + PeiGuidRec->ProgressID = DISMEM_END_ID; + } + } else if (!EfiStrCmp (Token, L"PostMem")) { + if(!EntryExit) { + PeiGuidRec->ProgressID = POSTMEM_START_ID; + } else { + PeiGuidRec->ProgressID = POSTMEM_END_ID; + } + } else { + return ; + } + // + // Record the APIC Id + // + PeiGuidRec->ApicID = GetApicId(); + + // + // Increment the number of valid log entries. + // + FirmwarePerformanceHob->NumberOfEntries++; + + return; +} |