summaryrefslogtreecommitdiff
path: root/EDK/Foundation/Library/Pei/PeiLib/Perf.c
diff options
context:
space:
mode:
Diffstat (limited to 'EDK/Foundation/Library/Pei/PeiLib/Perf.c')
-rw-r--r--EDK/Foundation/Library/Pei/PeiLib/Perf.c362
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;
+}