REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3737 Apply uncrustify changes to .c/.h files in the UefiCpuPkg package Cc: Andrew Fish <afish@apple.com> Cc: Leif Lindholm <leif@nuviainc.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com> Reviewed-by: Ray Ni <ray.ni@intel.com>
		
			
				
	
	
		
			483 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			483 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /** @file
 | |
|   Intel Processor Trace feature.
 | |
| 
 | |
|   Copyright (c) 2017 - 2018, Intel Corporation. All rights reserved.<BR>
 | |
|   SPDX-License-Identifier: BSD-2-Clause-Patent
 | |
| 
 | |
| **/
 | |
| 
 | |
| #include "CpuCommonFeatures.h"
 | |
| 
 | |
| ///
 | |
| /// This macro define the max entries in the Topa table.
 | |
| /// Each entry in the table contains some attribute bits, a pointer to an output region, and the size of the region.
 | |
| /// The last entry in the table may hold a pointer to the next table. This pointer can either point to the top of the
 | |
| /// current table (for circular array) or to the base of another table.
 | |
| /// At least 2 entries are needed because the list of entries must
 | |
| /// be terminated by an entry with the END bit set to 1, so 2
 | |
| /// entries are required to use a single valid entry.
 | |
| ///
 | |
| #define MAX_TOPA_ENTRY_COUNT  2
 | |
| 
 | |
| ///
 | |
| /// Processor trace output scheme selection.
 | |
| ///
 | |
| typedef enum {
 | |
|   RtitOutputSchemeSingleRange = 0,
 | |
|   RtitOutputSchemeToPA
 | |
| } RTIT_OUTPUT_SCHEME;
 | |
| 
 | |
| typedef struct  {
 | |
|   BOOLEAN                                    TopaSupported;
 | |
|   BOOLEAN                                    SingleRangeSupported;
 | |
|   MSR_IA32_RTIT_CTL_REGISTER                 RtitCtrl;
 | |
|   MSR_IA32_RTIT_OUTPUT_BASE_REGISTER         RtitOutputBase;
 | |
|   MSR_IA32_RTIT_OUTPUT_MASK_PTRS_REGISTER    RtitOutputMaskPtrs;
 | |
| } PROC_TRACE_PROCESSOR_DATA;
 | |
| 
 | |
| typedef struct  {
 | |
|   UINT32                       NumberOfProcessors;
 | |
| 
 | |
|   UINT8                        ProcTraceOutputScheme;
 | |
|   UINT32                       ProcTraceMemSize;
 | |
| 
 | |
|   UINTN                        *ThreadMemRegionTable;
 | |
|   UINTN                        AllocatedThreads;
 | |
| 
 | |
|   UINTN                        *TopaMemArray;
 | |
| 
 | |
|   PROC_TRACE_PROCESSOR_DATA    *ProcessorData;
 | |
| } PROC_TRACE_DATA;
 | |
| 
 | |
| typedef struct {
 | |
|   RTIT_TOPA_TABLE_ENTRY    TopaEntry[MAX_TOPA_ENTRY_COUNT];
 | |
| } PROC_TRACE_TOPA_TABLE;
 | |
| 
 | |
| /**
 | |
|   Prepares for the data used by CPU feature detection and initialization.
 | |
| 
 | |
|   @param[in]  NumberOfProcessors  The number of CPUs in the platform.
 | |
| 
 | |
|   @return  Pointer to a buffer of CPU related configuration data.
 | |
| 
 | |
|   @note This service could be called by BSP only.
 | |
| **/
 | |
| VOID *
 | |
| EFIAPI
 | |
| ProcTraceGetConfigData (
 | |
|   IN UINTN  NumberOfProcessors
 | |
|   )
 | |
| {
 | |
|   PROC_TRACE_DATA  *ConfigData;
 | |
| 
 | |
|   ConfigData = AllocateZeroPool (sizeof (PROC_TRACE_DATA) + sizeof (PROC_TRACE_PROCESSOR_DATA) * NumberOfProcessors);
 | |
|   ASSERT (ConfigData != NULL);
 | |
|   ConfigData->ProcessorData = (PROC_TRACE_PROCESSOR_DATA *)((UINT8 *)ConfigData + sizeof (PROC_TRACE_DATA));
 | |
| 
 | |
|   ConfigData->NumberOfProcessors    = (UINT32)NumberOfProcessors;
 | |
|   ConfigData->ProcTraceMemSize      = PcdGet32 (PcdCpuProcTraceMemSize);
 | |
|   ConfigData->ProcTraceOutputScheme = PcdGet8 (PcdCpuProcTraceOutputScheme);
 | |
| 
 | |
|   return ConfigData;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Detects if Intel Processor Trace feature supported on current
 | |
|   processor.
 | |
| 
 | |
|   @param[in]  ProcessorNumber  The index of the CPU executing this function.
 | |
|   @param[in]  CpuInfo          A pointer to the REGISTER_CPU_FEATURE_INFORMATION
 | |
|                                structure for the CPU executing this function.
 | |
|   @param[in]  ConfigData       A pointer to the configuration buffer returned
 | |
|                                by CPU_FEATURE_GET_CONFIG_DATA.  NULL if
 | |
|                                CPU_FEATURE_GET_CONFIG_DATA was not provided in
 | |
|                                RegisterCpuFeature().
 | |
| 
 | |
|   @retval TRUE     Processor Trace feature is supported.
 | |
|   @retval FALSE    Processor Trace feature is not supported.
 | |
| 
 | |
|   @note This service could be called by BSP/APs.
 | |
| **/
 | |
| BOOLEAN
 | |
| EFIAPI
 | |
| ProcTraceSupport (
 | |
|   IN UINTN                             ProcessorNumber,
 | |
|   IN REGISTER_CPU_FEATURE_INFORMATION  *CpuInfo,
 | |
|   IN VOID                              *ConfigData  OPTIONAL
 | |
|   )
 | |
| {
 | |
|   PROC_TRACE_DATA                              *ProcTraceData;
 | |
|   CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS_EBX  Ebx;
 | |
|   CPUID_INTEL_PROCESSOR_TRACE_MAIN_LEAF_ECX    Ecx;
 | |
| 
 | |
|   //
 | |
|   // Check if ProcTraceMemorySize option is enabled (0xFF means disable by user)
 | |
|   //
 | |
|   ProcTraceData = (PROC_TRACE_DATA *)ConfigData;
 | |
|   ASSERT (ProcTraceData != NULL);
 | |
|   if ((ProcTraceData->ProcTraceMemSize > RtitTopaMemorySize128M) ||
 | |
|       (ProcTraceData->ProcTraceOutputScheme > RtitOutputSchemeToPA))
 | |
|   {
 | |
|     return FALSE;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Check if Processor Trace is supported
 | |
|   //
 | |
|   AsmCpuidEx (CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS, 0, NULL, &Ebx.Uint32, NULL, NULL);
 | |
|   if (Ebx.Bits.IntelProcessorTrace == 0) {
 | |
|     return FALSE;
 | |
|   }
 | |
| 
 | |
|   AsmCpuidEx (CPUID_INTEL_PROCESSOR_TRACE, CPUID_INTEL_PROCESSOR_TRACE_MAIN_LEAF, NULL, NULL, &Ecx.Uint32, NULL);
 | |
|   ProcTraceData->ProcessorData[ProcessorNumber].TopaSupported        = (BOOLEAN)(Ecx.Bits.RTIT == 1);
 | |
|   ProcTraceData->ProcessorData[ProcessorNumber].SingleRangeSupported = (BOOLEAN)(Ecx.Bits.SingleRangeOutput == 1);
 | |
|   if ((ProcTraceData->ProcessorData[ProcessorNumber].TopaSupported && (ProcTraceData->ProcTraceOutputScheme == RtitOutputSchemeToPA)) ||
 | |
|       (ProcTraceData->ProcessorData[ProcessorNumber].SingleRangeSupported && (ProcTraceData->ProcTraceOutputScheme == RtitOutputSchemeSingleRange)))
 | |
|   {
 | |
|     ProcTraceData->ProcessorData[ProcessorNumber].RtitCtrl.Uint64           = AsmReadMsr64 (MSR_IA32_RTIT_CTL);
 | |
|     ProcTraceData->ProcessorData[ProcessorNumber].RtitOutputBase.Uint64     = AsmReadMsr64 (MSR_IA32_RTIT_OUTPUT_BASE);
 | |
|     ProcTraceData->ProcessorData[ProcessorNumber].RtitOutputMaskPtrs.Uint64 = AsmReadMsr64 (MSR_IA32_RTIT_OUTPUT_MASK_PTRS);
 | |
|     return TRUE;
 | |
|   }
 | |
| 
 | |
|   return FALSE;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Initializes Intel Processor Trace feature to specific state.
 | |
| 
 | |
|   @param[in]  ProcessorNumber  The index of the CPU executing this function.
 | |
|   @param[in]  CpuInfo          A pointer to the REGISTER_CPU_FEATURE_INFORMATION
 | |
|                                structure for the CPU executing this function.
 | |
|   @param[in]  ConfigData       A pointer to the configuration buffer returned
 | |
|                                by CPU_FEATURE_GET_CONFIG_DATA.  NULL if
 | |
|                                CPU_FEATURE_GET_CONFIG_DATA was not provided in
 | |
|                                RegisterCpuFeature().
 | |
|   @param[in]  State            If TRUE, then the Processor Trace feature must be
 | |
|                                enabled.
 | |
|                                If FALSE, then the Processor Trace feature must be
 | |
|                                disabled.
 | |
| 
 | |
|   @retval RETURN_SUCCESS       Intel Processor Trace feature is initialized.
 | |
| 
 | |
| **/
 | |
| RETURN_STATUS
 | |
| EFIAPI
 | |
| ProcTraceInitialize (
 | |
|   IN UINTN                             ProcessorNumber,
 | |
|   IN REGISTER_CPU_FEATURE_INFORMATION  *CpuInfo,
 | |
|   IN VOID                              *ConfigData   OPTIONAL,
 | |
|   IN BOOLEAN                           State
 | |
|   )
 | |
| {
 | |
|   UINT32                                   MemRegionSize;
 | |
|   UINTN                                    Pages;
 | |
|   UINTN                                    Alignment;
 | |
|   UINTN                                    MemRegionBaseAddr;
 | |
|   UINTN                                    *ThreadMemRegionTable;
 | |
|   UINTN                                    Index;
 | |
|   UINTN                                    TopaTableBaseAddr;
 | |
|   UINTN                                    AlignedAddress;
 | |
|   UINTN                                    *TopaMemArray;
 | |
|   PROC_TRACE_TOPA_TABLE                    *TopaTable;
 | |
|   PROC_TRACE_DATA                          *ProcTraceData;
 | |
|   BOOLEAN                                  FirstIn;
 | |
|   MSR_IA32_RTIT_CTL_REGISTER               CtrlReg;
 | |
|   MSR_IA32_RTIT_STATUS_REGISTER            StatusReg;
 | |
|   MSR_IA32_RTIT_OUTPUT_BASE_REGISTER       OutputBaseReg;
 | |
|   MSR_IA32_RTIT_OUTPUT_MASK_PTRS_REGISTER  OutputMaskPtrsReg;
 | |
|   RTIT_TOPA_TABLE_ENTRY                    *TopaEntryPtr;
 | |
| 
 | |
|   //
 | |
|   // The scope of the MSR_IA32_RTIT_* is core for below processor type, only program
 | |
|   // MSR_IA32_RTIT_* for thread 0 in each core.
 | |
|   //
 | |
|   if (IS_GOLDMONT_PROCESSOR (CpuInfo->DisplayFamily, CpuInfo->DisplayModel) ||
 | |
|       IS_GOLDMONT_PLUS_PROCESSOR (CpuInfo->DisplayFamily, CpuInfo->DisplayModel))
 | |
|   {
 | |
|     if (CpuInfo->ProcessorInfo.Location.Thread != 0) {
 | |
|       return RETURN_SUCCESS;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   ProcTraceData = (PROC_TRACE_DATA *)ConfigData;
 | |
|   ASSERT (ProcTraceData != NULL);
 | |
| 
 | |
|   //
 | |
|   // Clear MSR_IA32_RTIT_CTL[0] and IA32_RTIT_STS only if MSR_IA32_RTIT_CTL[0]==1b
 | |
|   //
 | |
|   CtrlReg.Uint64 = ProcTraceData->ProcessorData[ProcessorNumber].RtitCtrl.Uint64;
 | |
|   if (CtrlReg.Bits.TraceEn != 0) {
 | |
|     ///
 | |
|     /// Clear bit 0 in MSR IA32_RTIT_CTL (570)
 | |
|     ///
 | |
|     CtrlReg.Bits.TraceEn = 0;
 | |
|     CPU_REGISTER_TABLE_WRITE64 (
 | |
|       ProcessorNumber,
 | |
|       Msr,
 | |
|       MSR_IA32_RTIT_CTL,
 | |
|       CtrlReg.Uint64
 | |
|       );
 | |
| 
 | |
|     ///
 | |
|     /// Clear MSR IA32_RTIT_STS (571h) to all zeros
 | |
|     ///
 | |
|     StatusReg.Uint64 = 0x0;
 | |
|     CPU_REGISTER_TABLE_WRITE64 (
 | |
|       ProcessorNumber,
 | |
|       Msr,
 | |
|       MSR_IA32_RTIT_STATUS,
 | |
|       StatusReg.Uint64
 | |
|       );
 | |
|   }
 | |
| 
 | |
|   if (!State) {
 | |
|     return RETURN_SUCCESS;
 | |
|   }
 | |
| 
 | |
|   MemRegionBaseAddr = 0;
 | |
|   FirstIn           = FALSE;
 | |
| 
 | |
|   if (ProcTraceData->ThreadMemRegionTable == NULL) {
 | |
|     FirstIn = TRUE;
 | |
|     DEBUG ((DEBUG_INFO, "Initialize Processor Trace\n"));
 | |
|   }
 | |
| 
 | |
|   ///
 | |
|   /// Refer to PROC_TRACE_MEM_SIZE Table for Size Encoding
 | |
|   ///
 | |
|   MemRegionSize = (UINT32)(1 << (ProcTraceData->ProcTraceMemSize + 12));
 | |
|   if (FirstIn) {
 | |
|     DEBUG ((DEBUG_INFO, "ProcTrace: MemSize requested: 0x%X \n", MemRegionSize));
 | |
|   }
 | |
| 
 | |
|   if (FirstIn) {
 | |
|     //
 | |
|     //   Let BSP allocate and create the necessary memory region (Aligned to the size of
 | |
|     //   the memory region from setup option(ProcTraceMemSize) which is an integral multiple of 4kB)
 | |
|     //   for all the enabled threads to store Processor Trace debug data. Then Configure the trace
 | |
|     //   address base in MSR, IA32_RTIT_OUTPUT_BASE (560h) bits 47:12. Note that all regions must be
 | |
|     //   aligned based on their size, not just 4K. Thus a 2M region must have bits 20:12 cleared.
 | |
|     //
 | |
|     ThreadMemRegionTable = (UINTN *)AllocatePool (ProcTraceData->NumberOfProcessors * sizeof (UINTN *));
 | |
|     if (ThreadMemRegionTable == NULL) {
 | |
|       DEBUG ((DEBUG_ERROR, "Allocate ProcTrace ThreadMemRegionTable Failed\n"));
 | |
|       return RETURN_OUT_OF_RESOURCES;
 | |
|     }
 | |
| 
 | |
|     ProcTraceData->ThreadMemRegionTable = ThreadMemRegionTable;
 | |
| 
 | |
|     for (Index = 0; Index < ProcTraceData->NumberOfProcessors; Index++, ProcTraceData->AllocatedThreads++) {
 | |
|       Pages          = EFI_SIZE_TO_PAGES (MemRegionSize);
 | |
|       Alignment      = MemRegionSize;
 | |
|       AlignedAddress = (UINTN)AllocateAlignedReservedPages (Pages, Alignment);
 | |
|       if (AlignedAddress == 0) {
 | |
|         DEBUG ((DEBUG_ERROR, "ProcTrace: Out of mem, allocated only for %d threads\n", ProcTraceData->AllocatedThreads));
 | |
|         if (Index == 0) {
 | |
|           //
 | |
|           // Could not allocate for BSP even
 | |
|           //
 | |
|           FreePool ((VOID *)ThreadMemRegionTable);
 | |
|           ThreadMemRegionTable = NULL;
 | |
|           return RETURN_OUT_OF_RESOURCES;
 | |
|         }
 | |
| 
 | |
|         break;
 | |
|       }
 | |
| 
 | |
|       ThreadMemRegionTable[Index] = AlignedAddress;
 | |
|       DEBUG ((DEBUG_INFO, "ProcTrace: PT MemRegionBaseAddr(aligned) for thread %d: 0x%llX \n", Index, (UINT64)ThreadMemRegionTable[Index]));
 | |
|     }
 | |
| 
 | |
|     DEBUG ((DEBUG_INFO, "ProcTrace: Allocated PT mem for %d thread \n", ProcTraceData->AllocatedThreads));
 | |
|   }
 | |
| 
 | |
|   if (ProcessorNumber < ProcTraceData->AllocatedThreads) {
 | |
|     MemRegionBaseAddr = ProcTraceData->ThreadMemRegionTable[ProcessorNumber];
 | |
|   } else {
 | |
|     return RETURN_SUCCESS;
 | |
|   }
 | |
| 
 | |
|   ///
 | |
|   /// Check Processor Trace output scheme: Single Range output or ToPA table
 | |
|   ///
 | |
| 
 | |
|   //
 | |
|   //  Single Range output scheme
 | |
|   //
 | |
|   if (ProcTraceData->ProcessorData[ProcessorNumber].SingleRangeSupported &&
 | |
|       (ProcTraceData->ProcTraceOutputScheme == RtitOutputSchemeSingleRange))
 | |
|   {
 | |
|     if (FirstIn) {
 | |
|       DEBUG ((DEBUG_INFO, "ProcTrace: Enabling Single Range Output scheme \n"));
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     // Clear MSR IA32_RTIT_CTL (0x570) ToPA (Bit 8)
 | |
|     //
 | |
|     CtrlReg.Bits.ToPA = 0;
 | |
|     CPU_REGISTER_TABLE_WRITE64 (
 | |
|       ProcessorNumber,
 | |
|       Msr,
 | |
|       MSR_IA32_RTIT_CTL,
 | |
|       CtrlReg.Uint64
 | |
|       );
 | |
| 
 | |
|     //
 | |
|     // Program MSR IA32_RTIT_OUTPUT_BASE (0x560) bits[63:7] with the allocated Memory Region
 | |
|     //
 | |
|     OutputBaseReg.Uint64      = ProcTraceData->ProcessorData[ProcessorNumber].RtitOutputBase.Uint64;
 | |
|     OutputBaseReg.Bits.Base   = (MemRegionBaseAddr >> 7) & 0x01FFFFFF;
 | |
|     OutputBaseReg.Bits.BaseHi = RShiftU64 ((UINT64)MemRegionBaseAddr, 32) & 0xFFFFFFFF;
 | |
|     CPU_REGISTER_TABLE_WRITE64 (
 | |
|       ProcessorNumber,
 | |
|       Msr,
 | |
|       MSR_IA32_RTIT_OUTPUT_BASE,
 | |
|       OutputBaseReg.Uint64
 | |
|       );
 | |
| 
 | |
|     //
 | |
|     // Program the Mask bits for the Memory Region to MSR IA32_RTIT_OUTPUT_MASK_PTRS (561h)
 | |
|     //
 | |
|     OutputMaskPtrsReg.Uint64                 = ProcTraceData->ProcessorData[ProcessorNumber].RtitOutputMaskPtrs.Uint64;
 | |
|     OutputMaskPtrsReg.Bits.MaskOrTableOffset = ((MemRegionSize - 1) >> 7) & 0x01FFFFFF;
 | |
|     OutputMaskPtrsReg.Bits.OutputOffset      = RShiftU64 (MemRegionSize - 1, 32) & 0xFFFFFFFF;
 | |
|     CPU_REGISTER_TABLE_WRITE64 (
 | |
|       ProcessorNumber,
 | |
|       Msr,
 | |
|       MSR_IA32_RTIT_OUTPUT_MASK_PTRS,
 | |
|       OutputMaskPtrsReg.Uint64
 | |
|       );
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   //  ToPA(Table of physical address) scheme
 | |
|   //
 | |
|   if (ProcTraceData->ProcessorData[ProcessorNumber].TopaSupported &&
 | |
|       (ProcTraceData->ProcTraceOutputScheme == RtitOutputSchemeToPA))
 | |
|   {
 | |
|     //
 | |
|     //  Create ToPA structure aligned at 4KB for each logical thread
 | |
|     //  with at least 2 entries by 8 bytes size each. The first entry
 | |
|     //  should have the trace output base address in bits 47:12, 6:9
 | |
|     //  for Size, bits 4,2 and 0 must be cleared. The second entry
 | |
|     //  should have the base address of the table location in bits
 | |
|     //  47:12, bits 4 and 2 must be cleared and bit 0 must be set.
 | |
|     //
 | |
|     if (FirstIn) {
 | |
|       DEBUG ((DEBUG_INFO, "ProcTrace: Enabling ToPA scheme \n"));
 | |
|       //
 | |
|       // Let BSP allocate ToPA table mem for all threads
 | |
|       //
 | |
|       TopaMemArray = (UINTN *)AllocatePool (ProcTraceData->AllocatedThreads * sizeof (UINTN *));
 | |
|       if (TopaMemArray == NULL) {
 | |
|         DEBUG ((DEBUG_ERROR, "ProcTrace: Allocate mem for ToPA Failed\n"));
 | |
|         return RETURN_OUT_OF_RESOURCES;
 | |
|       }
 | |
| 
 | |
|       ProcTraceData->TopaMemArray = TopaMemArray;
 | |
| 
 | |
|       for (Index = 0; Index < ProcTraceData->AllocatedThreads; Index++) {
 | |
|         Pages          = EFI_SIZE_TO_PAGES (sizeof (PROC_TRACE_TOPA_TABLE));
 | |
|         Alignment      = 0x1000;
 | |
|         AlignedAddress = (UINTN)AllocateAlignedReservedPages (Pages, Alignment);
 | |
|         if (AlignedAddress == 0) {
 | |
|           if (Index < ProcTraceData->AllocatedThreads) {
 | |
|             ProcTraceData->AllocatedThreads = Index;
 | |
|           }
 | |
| 
 | |
|           DEBUG ((DEBUG_ERROR, "ProcTrace:  Out of mem, allocated ToPA mem only for %d threads\n", ProcTraceData->AllocatedThreads));
 | |
|           if (Index == 0) {
 | |
|             //
 | |
|             // Could not allocate for BSP even
 | |
|             //
 | |
|             FreePool ((VOID *)TopaMemArray);
 | |
|             TopaMemArray = NULL;
 | |
|             return RETURN_OUT_OF_RESOURCES;
 | |
|           }
 | |
| 
 | |
|           break;
 | |
|         }
 | |
| 
 | |
|         TopaMemArray[Index] = AlignedAddress;
 | |
|         DEBUG ((DEBUG_INFO, "ProcTrace: Topa table address(aligned) for thread %d is 0x%llX \n", Index, (UINT64)TopaMemArray[Index]));
 | |
|       }
 | |
| 
 | |
|       DEBUG ((DEBUG_INFO, "ProcTrace: Allocated ToPA mem for %d thread \n", ProcTraceData->AllocatedThreads));
 | |
|     }
 | |
| 
 | |
|     if (ProcessorNumber < ProcTraceData->AllocatedThreads) {
 | |
|       TopaTableBaseAddr = ProcTraceData->TopaMemArray[ProcessorNumber];
 | |
|     } else {
 | |
|       return RETURN_SUCCESS;
 | |
|     }
 | |
| 
 | |
|     TopaTable                 = (PROC_TRACE_TOPA_TABLE *)TopaTableBaseAddr;
 | |
|     TopaEntryPtr              = &TopaTable->TopaEntry[0];
 | |
|     TopaEntryPtr->Uint64      = 0;
 | |
|     TopaEntryPtr->Bits.Base   = (MemRegionBaseAddr >> 12) & 0x000FFFFF;
 | |
|     TopaEntryPtr->Bits.BaseHi = RShiftU64 ((UINT64)MemRegionBaseAddr, 32) & 0xFFFFFFFF;
 | |
|     TopaEntryPtr->Bits.Size   = ProcTraceData->ProcTraceMemSize;
 | |
|     TopaEntryPtr->Bits.END    = 0;
 | |
| 
 | |
|     TopaEntryPtr              = &TopaTable->TopaEntry[1];
 | |
|     TopaEntryPtr->Uint64      = 0;
 | |
|     TopaEntryPtr->Bits.Base   = (TopaTableBaseAddr >> 12) & 0x000FFFFF;
 | |
|     TopaEntryPtr->Bits.BaseHi = RShiftU64 ((UINT64)TopaTableBaseAddr, 32) & 0xFFFFFFFF;
 | |
|     TopaEntryPtr->Bits.END    = 1;
 | |
| 
 | |
|     //
 | |
|     // Program the MSR IA32_RTIT_OUTPUT_BASE (0x560) bits[63:7] with ToPA base
 | |
|     //
 | |
|     OutputBaseReg.Uint64      = ProcTraceData->ProcessorData[ProcessorNumber].RtitOutputBase.Uint64;
 | |
|     OutputBaseReg.Bits.Base   = (TopaTableBaseAddr >> 7) & 0x01FFFFFF;
 | |
|     OutputBaseReg.Bits.BaseHi = RShiftU64 ((UINT64)TopaTableBaseAddr, 32) & 0xFFFFFFFF;
 | |
|     CPU_REGISTER_TABLE_WRITE64 (
 | |
|       ProcessorNumber,
 | |
|       Msr,
 | |
|       MSR_IA32_RTIT_OUTPUT_BASE,
 | |
|       OutputBaseReg.Uint64
 | |
|       );
 | |
| 
 | |
|     //
 | |
|     // Set the MSR IA32_RTIT_OUTPUT_MASK (0x561) bits[63:7] to 0
 | |
|     //
 | |
|     OutputMaskPtrsReg.Uint64                 = ProcTraceData->ProcessorData[ProcessorNumber].RtitOutputMaskPtrs.Uint64;
 | |
|     OutputMaskPtrsReg.Bits.MaskOrTableOffset = 0;
 | |
|     OutputMaskPtrsReg.Bits.OutputOffset      = 0;
 | |
|     CPU_REGISTER_TABLE_WRITE64 (
 | |
|       ProcessorNumber,
 | |
|       Msr,
 | |
|       MSR_IA32_RTIT_OUTPUT_MASK_PTRS,
 | |
|       OutputMaskPtrsReg.Uint64
 | |
|       );
 | |
|     //
 | |
|     // Enable ToPA output scheme by enabling MSR IA32_RTIT_CTL (0x570) ToPA (Bit 8)
 | |
|     //
 | |
|     CtrlReg.Bits.ToPA = 1;
 | |
|     CPU_REGISTER_TABLE_WRITE64 (
 | |
|       ProcessorNumber,
 | |
|       Msr,
 | |
|       MSR_IA32_RTIT_CTL,
 | |
|       CtrlReg.Uint64
 | |
|       );
 | |
|   }
 | |
| 
 | |
|   ///
 | |
|   /// Enable the Processor Trace feature from MSR IA32_RTIT_CTL (570h)
 | |
|   ///
 | |
|   CtrlReg.Bits.OS       = 1;
 | |
|   CtrlReg.Bits.User     = 1;
 | |
|   CtrlReg.Bits.BranchEn = 1;
 | |
|   CtrlReg.Bits.TraceEn  = 1;
 | |
|   CPU_REGISTER_TABLE_WRITE64 (
 | |
|     ProcessorNumber,
 | |
|     Msr,
 | |
|     MSR_IA32_RTIT_CTL,
 | |
|     CtrlReg.Uint64
 | |
|     );
 | |
| 
 | |
|   return RETURN_SUCCESS;
 | |
| }
 |