TianoCore EDK2 master
Loading...
Searching...
No Matches
ProcTrace.c
Go to the documentation of this file.
1
9#include "CpuCommonFeatures.h"
10
20#define MAX_TOPA_ENTRY_COUNT 2
21
25typedef enum {
26 RtitOutputSchemeSingleRange = 0,
27 RtitOutputSchemeToPA
29
30typedef struct {
31 BOOLEAN TopaSupported;
32 BOOLEAN SingleRangeSupported;
36 BOOLEAN CycPacketSupported;
38
39typedef struct {
40 UINT32 NumberOfProcessors;
41
42 UINT8 ProcTraceOutputScheme;
43 UINT32 ProcTraceMemSize;
44
45 UINTN *ThreadMemRegionTable;
46 UINTN AllocatedThreads;
47
48 UINTN *TopaMemArray;
49
50 BOOLEAN EnableOnBspOnly;
51 BOOLEAN EnablePerformanceCollecting;
52
53 PROC_TRACE_PROCESSOR_DATA *ProcessorData;
55
56typedef struct {
59
69VOID *
70EFIAPI
72 IN UINTN NumberOfProcessors
73 )
74{
75 PROC_TRACE_DATA *ConfigData;
76
77 ConfigData = AllocateZeroPool (sizeof (PROC_TRACE_DATA) + sizeof (PROC_TRACE_PROCESSOR_DATA) * NumberOfProcessors);
78 ASSERT (ConfigData != NULL);
79 ConfigData->ProcessorData = (PROC_TRACE_PROCESSOR_DATA *)((UINT8 *)ConfigData + sizeof (PROC_TRACE_DATA));
80
81 ConfigData->NumberOfProcessors = (UINT32)NumberOfProcessors;
82 ConfigData->ProcTraceMemSize = PcdGet32 (PcdCpuProcTraceMemSize);
83 ConfigData->ProcTraceOutputScheme = PcdGet8 (PcdCpuProcTraceOutputScheme);
84 ConfigData->EnableOnBspOnly = PcdGetBool (PcdCpuProcTraceBspOnly);
85 ConfigData->EnablePerformanceCollecting = PcdGetBool (PcdCpuProcTracePerformanceCollecting);
86
87 return ConfigData;
88}
89
107BOOLEAN
108EFIAPI
110 IN UINTN ProcessorNumber,
112 IN VOID *ConfigData OPTIONAL
113 )
114{
115 PROC_TRACE_DATA *ProcTraceData;
119
120 //
121 // Check if ProcTraceMemorySize option is enabled (0xFF means disable by user)
122 //
123 ProcTraceData = (PROC_TRACE_DATA *)ConfigData;
124 ASSERT (ProcTraceData != NULL);
125 if ((ProcTraceData->ProcTraceMemSize > RtitTopaMemorySize128M) ||
126 (ProcTraceData->ProcTraceOutputScheme > RtitOutputSchemeToPA))
127 {
128 return FALSE;
129 }
130
131 //
132 // Check if Processor Trace is supported
133 //
135 if (Ebx.Bits.IntelProcessorTrace == 0) {
136 return FALSE;
137 }
138
140 ProcTraceData->ProcessorData[ProcessorNumber].TopaSupported = (BOOLEAN)(ProcTraceEcx.Bits.RTIT == 1);
141 ProcTraceData->ProcessorData[ProcessorNumber].SingleRangeSupported = (BOOLEAN)(ProcTraceEcx.Bits.SingleRangeOutput == 1);
142 if ((ProcTraceData->ProcessorData[ProcessorNumber].TopaSupported && (ProcTraceData->ProcTraceOutputScheme == RtitOutputSchemeToPA)) ||
143 (ProcTraceData->ProcessorData[ProcessorNumber].SingleRangeSupported && (ProcTraceData->ProcTraceOutputScheme == RtitOutputSchemeSingleRange)))
144 {
145 ProcTraceData->ProcessorData[ProcessorNumber].RtitCtrl.Uint64 = AsmReadMsr64 (MSR_IA32_RTIT_CTL);
146 ProcTraceData->ProcessorData[ProcessorNumber].RtitOutputBase.Uint64 = AsmReadMsr64 (MSR_IA32_RTIT_OUTPUT_BASE);
147 ProcTraceData->ProcessorData[ProcessorNumber].RtitOutputMaskPtrs.Uint64 = AsmReadMsr64 (MSR_IA32_RTIT_OUTPUT_MASK_PTRS);
148 ProcTraceData->ProcessorData[ProcessorNumber].CycPacketSupported = (BOOLEAN)(ProcTraceEbx.Bits.ConfigurablePsb == 1);
149
150 return TRUE;
151 }
152
153 return FALSE;
154}
155
174RETURN_STATUS
175EFIAPI
177 IN UINTN ProcessorNumber,
179 IN VOID *ConfigData OPTIONAL,
180 IN BOOLEAN State
181 )
182{
183 UINT32 MemRegionSize;
184 UINTN Pages;
185 UINTN Alignment;
186 UINTN MemRegionBaseAddr;
187 UINTN *ThreadMemRegionTable;
188 UINTN Index;
189 UINTN TopaTableBaseAddr;
190 UINTN AlignedAddress;
191 UINTN *TopaMemArray;
192 PROC_TRACE_TOPA_TABLE *TopaTable;
193 PROC_TRACE_DATA *ProcTraceData;
194 BOOLEAN FirstIn;
199 RTIT_TOPA_TABLE_ENTRY *TopaEntryPtr;
200 BOOLEAN IsBsp;
201
202 //
203 // The scope of the MSR_IA32_RTIT_* is core for below processor type, only program
204 // MSR_IA32_RTIT_* for thread 0 in each core.
205 //
206 if (IS_GOLDMONT_PROCESSOR (CpuInfo->DisplayFamily, CpuInfo->DisplayModel) ||
207 IS_GOLDMONT_PLUS_PROCESSOR (CpuInfo->DisplayFamily, CpuInfo->DisplayModel))
208 {
209 if (CpuInfo->ProcessorInfo.Location.Thread != 0) {
210 return RETURN_SUCCESS;
211 }
212 }
213
214 ProcTraceData = (PROC_TRACE_DATA *)ConfigData;
215 ASSERT (ProcTraceData != NULL);
216
217 //
218 // Clear MSR_IA32_RTIT_CTL[0] and IA32_RTIT_STS only if MSR_IA32_RTIT_CTL[0]==1b
219 //
220 CtrlReg.Uint64 = ProcTraceData->ProcessorData[ProcessorNumber].RtitCtrl.Uint64;
221 if (CtrlReg.Bits.TraceEn != 0) {
225 CtrlReg.Bits.TraceEn = 0;
227 ProcessorNumber,
228 Msr,
230 CtrlReg.Uint64
231 );
232
236 StatusReg.Uint64 = 0x0;
238 ProcessorNumber,
239 Msr,
241 StatusReg.Uint64
242 );
243 }
244
245 if (!State) {
246 return RETURN_SUCCESS;
247 }
248
249 IsBsp = (CpuInfo->ProcessorInfo.StatusFlag & PROCESSOR_AS_BSP_BIT) ? TRUE : FALSE;
250
251 if (ProcTraceData->EnableOnBspOnly && !IsBsp) {
252 return RETURN_SUCCESS;
253 }
254
255 MemRegionBaseAddr = 0;
256 FirstIn = FALSE;
257
258 if (ProcTraceData->ThreadMemRegionTable == NULL) {
259 FirstIn = TRUE;
260 DEBUG ((DEBUG_INFO, "Initialize Processor Trace\n"));
261 }
262
266 MemRegionSize = (UINT32)(1 << (ProcTraceData->ProcTraceMemSize + 12));
267 if (FirstIn) {
268 DEBUG ((DEBUG_INFO, "ProcTrace: MemSize requested: 0x%X \n", MemRegionSize));
269 }
270
271 if (FirstIn) {
272 //
273 // Let BSP allocate and create the necessary memory region (Aligned to the size of
274 // the memory region from setup option(ProcTraceMemSize) which is an integral multiple of 4kB)
275 // for all the enabled threads to store Processor Trace debug data. Then Configure the trace
276 // address base in MSR, IA32_RTIT_OUTPUT_BASE (560h) bits 47:12. Note that all regions must be
277 // aligned based on their size, not just 4K. Thus a 2M region must have bits 20:12 cleared.
278 //
279
280 Pages = EFI_SIZE_TO_PAGES (MemRegionSize);
281 Alignment = MemRegionSize;
282 if (ProcTraceData->EnableOnBspOnly) {
283 //
284 // When only enable ProcTrace on BSP, this is the first and only time ProcTraceInitialize() runs.
285 //
286 MemRegionBaseAddr = (UINTN)AllocateAlignedReservedPages (Pages, Alignment);
287 if (MemRegionBaseAddr == 0) {
288 //
289 // Could not allocate for BSP even
290 //
291 DEBUG ((DEBUG_ERROR, "ProcTrace: Out of mem, failed to allocate buffer for BSP\n"));
293 }
294
295 DEBUG ((DEBUG_INFO, "ProcTrace: Allocated PT MemRegionBaseAddr(aligned) for BSP only: 0x%llX.\n", (UINT64)MemRegionBaseAddr));
296 } else {
297 ThreadMemRegionTable = (UINTN *)AllocatePool (ProcTraceData->NumberOfProcessors * sizeof (UINTN *));
298 if (ThreadMemRegionTable == NULL) {
299 DEBUG ((DEBUG_ERROR, "Allocate ProcTrace ThreadMemRegionTable Failed\n"));
301 }
302
303 ProcTraceData->ThreadMemRegionTable = ThreadMemRegionTable;
304
305 for (Index = 0; Index < ProcTraceData->NumberOfProcessors; Index++, ProcTraceData->AllocatedThreads++) {
306 AlignedAddress = (UINTN)AllocateAlignedReservedPages (Pages, Alignment);
307 if (AlignedAddress == 0) {
308 DEBUG ((DEBUG_ERROR, "ProcTrace: Out of mem, allocated only for %d threads\n", ProcTraceData->AllocatedThreads));
309 if (Index == 0) {
310 //
311 // Could not allocate for BSP even
312 //
313 FreePool ((VOID *)ThreadMemRegionTable);
314 ThreadMemRegionTable = NULL;
316 }
317
318 break;
319 }
320
321 ThreadMemRegionTable[Index] = AlignedAddress;
322 DEBUG ((DEBUG_INFO, "ProcTrace: PT MemRegionBaseAddr(aligned) for thread %d: 0x%llX \n", Index, (UINT64)ThreadMemRegionTable[Index]));
323 }
324
325 DEBUG ((DEBUG_INFO, "ProcTrace: Allocated PT mem for %d thread \n", ProcTraceData->AllocatedThreads));
326 }
327 }
328
329 if (!ProcTraceData->EnableOnBspOnly) {
330 if (ProcessorNumber < ProcTraceData->AllocatedThreads) {
331 MemRegionBaseAddr = ProcTraceData->ThreadMemRegionTable[ProcessorNumber];
332 } else {
333 return RETURN_SUCCESS;
334 }
335 }
336
340
341 //
342 // Single Range output scheme
343 //
344 if (ProcTraceData->ProcessorData[ProcessorNumber].SingleRangeSupported &&
345 (ProcTraceData->ProcTraceOutputScheme == RtitOutputSchemeSingleRange))
346 {
347 if (FirstIn) {
348 DEBUG ((DEBUG_INFO, "ProcTrace: Enabling Single Range Output scheme \n"));
349 }
350
351 //
352 // Clear MSR IA32_RTIT_CTL (0x570) ToPA (Bit 8)
353 //
354 CtrlReg.Bits.ToPA = 0;
356 ProcessorNumber,
357 Msr,
359 CtrlReg.Uint64
360 );
361
362 //
363 // Program MSR IA32_RTIT_OUTPUT_BASE (0x560) bits[63:7] with the allocated Memory Region
364 //
365 OutputBaseReg.Uint64 = ProcTraceData->ProcessorData[ProcessorNumber].RtitOutputBase.Uint64;
366 OutputBaseReg.Bits.Base = (MemRegionBaseAddr >> 7) & 0x01FFFFFF;
367 OutputBaseReg.Bits.BaseHi = RShiftU64 ((UINT64)MemRegionBaseAddr, 32) & 0xFFFFFFFF;
369 ProcessorNumber,
370 Msr,
372 OutputBaseReg.Uint64
373 );
374
375 //
376 // Program the Mask bits for the Memory Region to MSR IA32_RTIT_OUTPUT_MASK_PTRS (561h)
377 //
378 OutputMaskPtrsReg.Uint64 = ProcTraceData->ProcessorData[ProcessorNumber].RtitOutputMaskPtrs.Uint64;
379 OutputMaskPtrsReg.Bits.MaskOrTableOffset = ((MemRegionSize - 1) >> 7) & 0x01FFFFFF;
380 OutputMaskPtrsReg.Bits.OutputOffset = RShiftU64 (MemRegionSize - 1, 32) & 0xFFFFFFFF;
382 ProcessorNumber,
383 Msr,
385 OutputMaskPtrsReg.Uint64
386 );
387 }
388
389 //
390 // ToPA(Table of physical address) scheme
391 //
392 if (ProcTraceData->ProcessorData[ProcessorNumber].TopaSupported &&
393 (ProcTraceData->ProcTraceOutputScheme == RtitOutputSchemeToPA))
394 {
395 //
396 // Create ToPA structure aligned at 4KB for each logical thread
397 // with at least 2 entries by 8 bytes size each. The first entry
398 // should have the trace output base address in bits 47:12, 6:9
399 // for Size, bits 4,2 and 0 must be cleared. The second entry
400 // should have the base address of the table location in bits
401 // 47:12, bits 4 and 2 must be cleared and bit 0 must be set.
402 //
403 if (FirstIn) {
404 DEBUG ((DEBUG_INFO, "ProcTrace: Enabling ToPA scheme \n"));
405
406 Pages = EFI_SIZE_TO_PAGES (sizeof (PROC_TRACE_TOPA_TABLE));
407 Alignment = 0x1000;
408
409 if (ProcTraceData->EnableOnBspOnly) {
410 //
411 // When only enable ProcTrace on BSP, this is the first and only time ProcTraceInitialize() runs.
412 //
413 TopaTableBaseAddr = (UINTN)AllocateAlignedReservedPages (Pages, Alignment);
414 if (TopaTableBaseAddr == 0) {
415 DEBUG ((DEBUG_ERROR, "ProcTrace: Out of mem, failed to allocate ToPA mem for BSP"));
417 }
418
419 DEBUG ((DEBUG_INFO, "ProcTrace: Topa table address(aligned) for BSP only: 0x%llX \n", (UINT64)TopaTableBaseAddr));
420 } else {
421 //
422 // Let BSP allocate ToPA table mem for all threads
423 //
424 TopaMemArray = (UINTN *)AllocatePool (ProcTraceData->AllocatedThreads * sizeof (UINTN *));
425 if (TopaMemArray == NULL) {
426 DEBUG ((DEBUG_ERROR, "ProcTrace: Allocate mem for ToPA Failed\n"));
428 }
429
430 ProcTraceData->TopaMemArray = TopaMemArray;
431
432 for (Index = 0; Index < ProcTraceData->AllocatedThreads; Index++) {
433 AlignedAddress = (UINTN)AllocateAlignedReservedPages (Pages, Alignment);
434 if (AlignedAddress == 0) {
435 if (Index < ProcTraceData->AllocatedThreads) {
436 ProcTraceData->AllocatedThreads = Index;
437 }
438
439 DEBUG ((DEBUG_ERROR, "ProcTrace: Out of mem, allocated ToPA mem only for %d threads\n", ProcTraceData->AllocatedThreads));
440 if (Index == 0) {
441 //
442 // Could not allocate for BSP even
443 //
444 FreePool ((VOID *)TopaMemArray);
445 TopaMemArray = NULL;
447 }
448
449 break;
450 }
451
452 TopaMemArray[Index] = AlignedAddress;
453 DEBUG ((DEBUG_INFO, "ProcTrace: Topa table address(aligned) for thread %d is 0x%llX \n", Index, (UINT64)TopaMemArray[Index]));
454 }
455
456 DEBUG ((DEBUG_INFO, "ProcTrace: Allocated ToPA mem for %d thread \n", ProcTraceData->AllocatedThreads));
457 }
458 }
459
460 if (!ProcTraceData->EnableOnBspOnly) {
461 if (ProcessorNumber < ProcTraceData->AllocatedThreads) {
462 TopaTableBaseAddr = ProcTraceData->TopaMemArray[ProcessorNumber];
463 } else {
464 return RETURN_SUCCESS;
465 }
466 }
467
468 TopaTable = (PROC_TRACE_TOPA_TABLE *)TopaTableBaseAddr;
469 TopaEntryPtr = &TopaTable->TopaEntry[0];
470 TopaEntryPtr->Uint64 = 0;
471 TopaEntryPtr->Bits.Base = (MemRegionBaseAddr >> 12) & 0x000FFFFF;
472 TopaEntryPtr->Bits.BaseHi = RShiftU64 ((UINT64)MemRegionBaseAddr, 32) & 0xFFFFFFFF;
473 TopaEntryPtr->Bits.Size = ProcTraceData->ProcTraceMemSize;
474 TopaEntryPtr->Bits.END = 0;
475
476 TopaEntryPtr = &TopaTable->TopaEntry[1];
477 TopaEntryPtr->Uint64 = 0;
478 TopaEntryPtr->Bits.Base = (TopaTableBaseAddr >> 12) & 0x000FFFFF;
479 TopaEntryPtr->Bits.BaseHi = RShiftU64 ((UINT64)TopaTableBaseAddr, 32) & 0xFFFFFFFF;
480 TopaEntryPtr->Bits.END = 1;
481
482 //
483 // Program the MSR IA32_RTIT_OUTPUT_BASE (0x560) bits[63:7] with ToPA base
484 //
485 OutputBaseReg.Uint64 = ProcTraceData->ProcessorData[ProcessorNumber].RtitOutputBase.Uint64;
486 OutputBaseReg.Bits.Base = (TopaTableBaseAddr >> 7) & 0x01FFFFFF;
487 OutputBaseReg.Bits.BaseHi = RShiftU64 ((UINT64)TopaTableBaseAddr, 32) & 0xFFFFFFFF;
489 ProcessorNumber,
490 Msr,
492 OutputBaseReg.Uint64
493 );
494
495 //
496 // Set the MSR IA32_RTIT_OUTPUT_MASK (0x561) bits[63:7] to 0
497 //
498 OutputMaskPtrsReg.Uint64 = ProcTraceData->ProcessorData[ProcessorNumber].RtitOutputMaskPtrs.Uint64;
499 OutputMaskPtrsReg.Bits.MaskOrTableOffset = 0;
500 OutputMaskPtrsReg.Bits.OutputOffset = 0;
502 ProcessorNumber,
503 Msr,
505 OutputMaskPtrsReg.Uint64
506 );
507 //
508 // Enable ToPA output scheme by enabling MSR IA32_RTIT_CTL (0x570) ToPA (Bit 8)
509 //
510 CtrlReg.Bits.ToPA = 1;
512 ProcessorNumber,
513 Msr,
515 CtrlReg.Uint64
516 );
517 }
518
522 CtrlReg.Bits.OS = 1;
523 CtrlReg.Bits.User = 1;
524 CtrlReg.Bits.BranchEn = 1;
525 CtrlReg.Bits.TraceEn = 1;
526
527 //
528 // Generate CYC/TSC timing packets to collect performance data.
529 //
530 if (ProcTraceData->EnablePerformanceCollecting) {
531 if (ProcTraceData->ProcessorData[ProcessorNumber].CycPacketSupported) {
532 CtrlReg.Bits.CYCEn = 1;
533 CtrlReg.Bits.CYCThresh = 5;
534 }
535
536 //
537 // Write to TSCEn is always supported
538 //
539 CtrlReg.Bits.TSCEn = 1;
540 }
541
543 ProcessorNumber,
544 Msr,
546 CtrlReg.Uint64
547 );
548
549 return RETURN_SUCCESS;
550}
UINT64 UINTN
UINT64 EFIAPI RShiftU64(IN UINT64 Operand, IN UINTN Count)
Definition: RShiftU64.c:28
UINT32 EFIAPI AsmCpuidEx(IN UINT32 Index, IN UINT32 SubIndex, OUT UINT32 *RegisterEax OPTIONAL, OUT UINT32 *RegisterEbx OPTIONAL, OUT UINT32 *RegisterEcx OPTIONAL, OUT UINT32 *RegisterEdx OPTIONAL)
Definition: CpuIdEx.c:43
VOID *EFIAPI AllocateZeroPool(IN UINTN AllocationSize)
VOID EFIAPI FreePool(IN VOID *Buffer)
VOID *EFIAPI AllocateAlignedReservedPages(IN UINTN Pages, IN UINTN Alignment)
#define IS_GOLDMONT_PROCESSOR(DisplayFamily, DisplayModel)
Definition: GoldmontMsr.h:32
#define IS_GOLDMONT_PLUS_PROCESSOR(DisplayFamily, DisplayModel)
UINT64 EFIAPI AsmReadMsr64(IN UINT32 Index)
Definition: GccInlinePriv.c:60
#define NULL
Definition: Base.h:319
#define RETURN_OUT_OF_RESOURCES
Definition: Base.h:1114
#define RETURN_SUCCESS
Definition: Base.h:1066
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define DEBUG(Expression)
Definition: DebugLib.h:434
#define MSR_IA32_RTIT_OUTPUT_MASK_PTRS
#define MSR_IA32_RTIT_STATUS
#define MSR_IA32_RTIT_CTL
#define MSR_IA32_RTIT_OUTPUT_BASE
#define CPUID_INTEL_PROCESSOR_TRACE
Definition: Cpuid.h:2924
#define CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS
Definition: Cpuid.h:1301
#define CPUID_INTEL_PROCESSOR_TRACE_MAIN_LEAF
Definition: Cpuid.h:2951
#define PROCESSOR_AS_BSP_BIT
Definition: MpService.h:70
#define PcdGet8(TokenName)
Definition: PcdLib.h:336
#define PcdGet32(TokenName)
Definition: PcdLib.h:362
#define PcdGetBool(TokenName)
Definition: PcdLib.h:401
VOID *EFIAPI AllocatePool(IN UINTN AllocationSize)
VOID *EFIAPI ProcTraceGetConfigData(IN UINTN NumberOfProcessors)
Definition: ProcTrace.c:71
RETURN_STATUS EFIAPI ProcTraceInitialize(IN UINTN ProcessorNumber, IN REGISTER_CPU_FEATURE_INFORMATION *CpuInfo, IN VOID *ConfigData OPTIONAL, IN BOOLEAN State)
Definition: ProcTrace.c:176
#define MAX_TOPA_ENTRY_COUNT
Definition: ProcTrace.c:20
BOOLEAN EFIAPI ProcTraceSupport(IN UINTN ProcessorNumber, IN REGISTER_CPU_FEATURE_INFORMATION *CpuInfo, IN VOID *ConfigData OPTIONAL)
Definition: ProcTrace.c:109
RTIT_OUTPUT_SCHEME
Definition: ProcTrace.c:25
#define CPU_REGISTER_TABLE_WRITE64(ProcessorNumber, RegisterType, Index, Value)
#define EFI_SIZE_TO_PAGES(Size)
Definition: UefiBaseType.h:200
struct CPUID_INTEL_PROCESSOR_TRACE_MAIN_LEAF_EBX::@738 Bits
struct CPUID_INTEL_PROCESSOR_TRACE_MAIN_LEAF_ECX::@739 Bits
struct MSR_IA32_RTIT_CTL_REGISTER::@670 Bits
struct MSR_IA32_RTIT_OUTPUT_BASE_REGISTER::@667 Bits
struct MSR_IA32_RTIT_OUTPUT_MASK_PTRS_REGISTER::@668 Bits
struct RTIT_TOPA_TABLE_ENTRY::@669 Bits