]> git.proxmox.com Git - mirror_edk2.git/blame - UefiCpuPkg/Library/CpuCommonFeaturesLib/ProcTrace.c
EmbeddedPkg/PrePiLib: remove dead status code reporting code
[mirror_edk2.git] / UefiCpuPkg / Library / CpuCommonFeaturesLib / ProcTrace.c
CommitLineData
bc230057
ED
1/** @file\r
2 Intel Processor Trace feature.\r
3\r
7367cc6c 4 Copyright (c) 2017 - 2018, Intel Corporation. All rights reserved.<BR>\r
0acd8697 5 SPDX-License-Identifier: BSD-2-Clause-Patent\r
bc230057
ED
6\r
7**/\r
8\r
9#include "CpuCommonFeatures.h"\r
10\r
bc230057 11///\r
b2b0ffc9 12/// This macro define the max entries in the Topa table.\r
7367cc6c
LG
13/// Each entry in the table contains some attribute bits, a pointer to an output region, and the size of the region.\r
14/// The last entry in the table may hold a pointer to the next table. This pointer can either point to the top of the\r
15/// current table (for circular array) or to the base of another table.\r
16/// At least 2 entries are needed because the list of entries must\r
17/// be terminated by an entry with the END bit set to 1, so 2\r
b2b0ffc9 18/// entries are required to use a single valid entry.\r
bc230057 19///\r
b2b0ffc9
ED
20#define MAX_TOPA_ENTRY_COUNT 2\r
21\r
bc230057
ED
22\r
23///\r
24/// Processor trace output scheme selection.\r
25///\r
26typedef enum {\r
330021fa
ED
27 RtitOutputSchemeSingleRange = 0,\r
28 RtitOutputSchemeToPA\r
29} RTIT_OUTPUT_SCHEME;\r
bc230057
ED
30\r
31typedef struct {\r
32 BOOLEAN ProcTraceSupported;\r
33 BOOLEAN TopaSupported;\r
34 BOOLEAN SingleRangeSupported;\r
35} PROC_TRACE_PROCESSOR_DATA;\r
36\r
37typedef struct {\r
38 UINT32 NumberOfProcessors;\r
39\r
7367cc6c 40 UINT8 ProcTraceOutputScheme;\r
bc230057
ED
41 UINT32 ProcTraceMemSize;\r
42\r
43 UINTN *ThreadMemRegionTable;\r
44 UINTN AllocatedThreads;\r
45\r
46 UINTN *TopaMemArray;\r
47 UINTN TopaMemArrayCount;\r
48\r
49 PROC_TRACE_PROCESSOR_DATA *ProcessorData;\r
50} PROC_TRACE_DATA;\r
51\r
52typedef struct {\r
b2b0ffc9 53 RTIT_TOPA_TABLE_ENTRY TopaEntry[MAX_TOPA_ENTRY_COUNT];\r
bc230057
ED
54} PROC_TRACE_TOPA_TABLE;\r
55\r
56/**\r
57 Prepares for the data used by CPU feature detection and initialization.\r
58\r
59 @param[in] NumberOfProcessors The number of CPUs in the platform.\r
60\r
61 @return Pointer to a buffer of CPU related configuration data.\r
62\r
63 @note This service could be called by BSP only.\r
64**/\r
65VOID *\r
66EFIAPI\r
67ProcTraceGetConfigData (\r
68 IN UINTN NumberOfProcessors\r
69 )\r
70{\r
71 PROC_TRACE_DATA *ConfigData;\r
72\r
73 ConfigData = AllocateZeroPool (sizeof (PROC_TRACE_DATA) + sizeof (PROC_TRACE_PROCESSOR_DATA) * NumberOfProcessors);\r
74 ASSERT (ConfigData != NULL);\r
75 ConfigData->ProcessorData = (PROC_TRACE_PROCESSOR_DATA *) ((UINT8*) ConfigData + sizeof (PROC_TRACE_DATA));\r
76\r
77 ConfigData->NumberOfProcessors = (UINT32) NumberOfProcessors;\r
78 ConfigData->ProcTraceMemSize = PcdGet32 (PcdCpuProcTraceMemSize);\r
79 ConfigData->ProcTraceOutputScheme = PcdGet8 (PcdCpuProcTraceOutputScheme);\r
80\r
81 return ConfigData;\r
82}\r
83\r
84/**\r
7367cc6c 85 Detects if Intel Processor Trace feature supported on current\r
bc230057
ED
86 processor.\r
87\r
88 @param[in] ProcessorNumber The index of the CPU executing this function.\r
89 @param[in] CpuInfo A pointer to the REGISTER_CPU_FEATURE_INFORMATION\r
90 structure for the CPU executing this function.\r
91 @param[in] ConfigData A pointer to the configuration buffer returned\r
92 by CPU_FEATURE_GET_CONFIG_DATA. NULL if\r
93 CPU_FEATURE_GET_CONFIG_DATA was not provided in\r
94 RegisterCpuFeature().\r
95\r
96 @retval TRUE Processor Trace feature is supported.\r
97 @retval FALSE Processor Trace feature is not supported.\r
98\r
99 @note This service could be called by BSP/APs.\r
100**/\r
101BOOLEAN\r
102EFIAPI\r
103ProcTraceSupport (\r
104 IN UINTN ProcessorNumber,\r
105 IN REGISTER_CPU_FEATURE_INFORMATION *CpuInfo,\r
106 IN VOID *ConfigData OPTIONAL\r
107 )\r
108{\r
109 PROC_TRACE_DATA *ProcTraceData;\r
110 CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS_EBX Ebx;\r
111 CPUID_INTEL_PROCESSOR_TRACE_MAIN_LEAF_ECX Ecx;\r
112\r
113 //\r
114 // Check if ProcTraceMemorySize option is enabled (0xFF means disable by user)\r
115 //\r
116 ProcTraceData = (PROC_TRACE_DATA *) ConfigData;\r
3dcb5325 117 ASSERT (ProcTraceData != NULL);\r
b2b0ffc9 118 if ((ProcTraceData->ProcTraceMemSize > RtitTopaMemorySize128M) ||\r
330021fa 119 (ProcTraceData->ProcTraceOutputScheme > RtitOutputSchemeToPA)) {\r
bc230057
ED
120 return FALSE;\r
121 }\r
122\r
123 //\r
124 // Check if Processor Trace is supported\r
125 //\r
126 AsmCpuidEx (CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS, 0, NULL, &Ebx.Uint32, NULL, NULL);\r
127 ProcTraceData->ProcessorData[ProcessorNumber].ProcTraceSupported = (BOOLEAN) (Ebx.Bits.IntelProcessorTrace == 1);\r
128 if (!ProcTraceData->ProcessorData[ProcessorNumber].ProcTraceSupported) {\r
129 return FALSE;\r
130 }\r
131\r
132 AsmCpuidEx (CPUID_INTEL_PROCESSOR_TRACE, CPUID_INTEL_PROCESSOR_TRACE_MAIN_LEAF, NULL, NULL, &Ecx.Uint32, NULL);\r
133 ProcTraceData->ProcessorData[ProcessorNumber].TopaSupported = (BOOLEAN) (Ecx.Bits.RTIT == 1);\r
134 ProcTraceData->ProcessorData[ProcessorNumber].SingleRangeSupported = (BOOLEAN) (Ecx.Bits.SingleRangeOutput == 1);\r
330021fa
ED
135 if ((ProcTraceData->ProcessorData[ProcessorNumber].TopaSupported && (ProcTraceData->ProcTraceOutputScheme == RtitOutputSchemeToPA)) ||\r
136 (ProcTraceData->ProcessorData[ProcessorNumber].SingleRangeSupported && (ProcTraceData->ProcTraceOutputScheme == RtitOutputSchemeSingleRange))) {\r
bc230057
ED
137 return TRUE;\r
138 }\r
139\r
140 return FALSE;\r
141}\r
142\r
143/**\r
144 Initializes Intel Processor Trace feature to specific state.\r
145\r
146 @param[in] ProcessorNumber The index of the CPU executing this function.\r
147 @param[in] CpuInfo A pointer to the REGISTER_CPU_FEATURE_INFORMATION\r
148 structure for the CPU executing this function.\r
149 @param[in] ConfigData A pointer to the configuration buffer returned\r
150 by CPU_FEATURE_GET_CONFIG_DATA. NULL if\r
151 CPU_FEATURE_GET_CONFIG_DATA was not provided in\r
152 RegisterCpuFeature().\r
153 @param[in] State If TRUE, then the Processor Trace feature must be\r
154 enabled.\r
155 If FALSE, then the Processor Trace feature must be\r
156 disabled.\r
157\r
158 @retval RETURN_SUCCESS Intel Processor Trace feature is initialized.\r
159\r
160**/\r
161RETURN_STATUS\r
162EFIAPI\r
163ProcTraceInitialize (\r
164 IN UINTN ProcessorNumber,\r
165 IN REGISTER_CPU_FEATURE_INFORMATION *CpuInfo,\r
166 IN VOID *ConfigData, OPTIONAL\r
167 IN BOOLEAN State\r
168 )\r
169{\r
bc230057
ED
170 UINT32 MemRegionSize;\r
171 UINTN Pages;\r
172 UINTN Alignment;\r
173 UINTN MemRegionBaseAddr;\r
174 UINTN *ThreadMemRegionTable;\r
175 UINTN Index;\r
176 UINTN TopaTableBaseAddr;\r
177 UINTN AlignedAddress;\r
178 UINTN *TopaMemArray;\r
179 PROC_TRACE_TOPA_TABLE *TopaTable;\r
180 PROC_TRACE_DATA *ProcTraceData;\r
181 BOOLEAN FirstIn;\r
b2b0ffc9
ED
182 MSR_IA32_RTIT_CTL_REGISTER CtrlReg;\r
183 MSR_IA32_RTIT_STATUS_REGISTER StatusReg;\r
184 MSR_IA32_RTIT_OUTPUT_BASE_REGISTER OutputBaseReg;\r
185 MSR_IA32_RTIT_OUTPUT_MASK_PTRS_REGISTER OutputMaskPtrsReg;\r
186 RTIT_TOPA_TABLE_ENTRY *TopaEntryPtr;\r
bc230057 187\r
d28daadd
ED
188 //\r
189 // The scope of the MSR_IA32_RTIT_* is core for below processor type, only program\r
190 // MSR_IA32_RTIT_* for thread 0 in each core.\r
191 //\r
192 if (IS_GOLDMONT_PROCESSOR (CpuInfo->DisplayFamily, CpuInfo->DisplayModel) ||\r
193 IS_GOLDMONT_PLUS_PROCESSOR (CpuInfo->DisplayFamily, CpuInfo->DisplayModel)) {\r
194 if (CpuInfo->ProcessorInfo.Location.Thread != 0) {\r
195 return RETURN_SUCCESS;\r
196 }\r
197 }\r
198\r
bc230057 199 ProcTraceData = (PROC_TRACE_DATA *) ConfigData;\r
3dcb5325 200 ASSERT (ProcTraceData != NULL);\r
bc230057
ED
201\r
202 MemRegionBaseAddr = 0;\r
203 FirstIn = FALSE;\r
204\r
205 if (ProcTraceData->ThreadMemRegionTable == NULL) {\r
206 FirstIn = TRUE;\r
207 DEBUG ((DEBUG_INFO, "Initialize Processor Trace\n"));\r
208 }\r
209\r
210 ///\r
211 /// Refer to PROC_TRACE_MEM_SIZE Table for Size Encoding\r
212 ///\r
213 MemRegionSize = (UINT32) (1 << (ProcTraceData->ProcTraceMemSize + 12));\r
214 if (FirstIn) {\r
215 DEBUG ((DEBUG_INFO, "ProcTrace: MemSize requested: 0x%X \n", MemRegionSize));\r
216 }\r
217\r
218 //\r
219 // Clear MSR_IA32_RTIT_CTL[0] and IA32_RTIT_STS only if MSR_IA32_RTIT_CTL[0]==1b\r
220 //\r
b2b0ffc9
ED
221 CtrlReg.Uint64 = AsmReadMsr64 (MSR_IA32_RTIT_CTL);\r
222 if (CtrlReg.Bits.TraceEn != 0) {\r
bc230057
ED
223 ///\r
224 /// Clear bit 0 in MSR IA32_RTIT_CTL (570)\r
225 ///\r
b2b0ffc9 226 CtrlReg.Bits.TraceEn = 0;\r
bc230057
ED
227 CPU_REGISTER_TABLE_WRITE64 (\r
228 ProcessorNumber,\r
229 Msr,\r
230 MSR_IA32_RTIT_CTL,\r
b2b0ffc9 231 CtrlReg.Uint64\r
bc230057
ED
232 );\r
233\r
234 ///\r
235 /// Clear MSR IA32_RTIT_STS (571h) to all zeros\r
236 ///\r
b2b0ffc9 237 StatusReg.Uint64 = 0x0;\r
bc230057
ED
238 CPU_REGISTER_TABLE_WRITE64 (\r
239 ProcessorNumber,\r
240 Msr,\r
241 MSR_IA32_RTIT_STATUS,\r
b2b0ffc9 242 StatusReg.Uint64\r
bc230057
ED
243 );\r
244 }\r
245\r
246 if (FirstIn) {\r
247 //\r
248 // Let BSP allocate and create the necessary memory region (Aligned to the size of\r
249 // the memory region from setup option(ProcTraceMemSize) which is an integral multiple of 4kB)\r
250 // for the all the enabled threads for storing Processor Trace debug data. Then Configure the trace\r
251 // address base in MSR, IA32_RTIT_OUTPUT_BASE (560h) bits 47:12. Note that all regions must be\r
252 // aligned based on their size, not just 4K. Thus a 2M region must have bits 20:12 clear.\r
253 //\r
254 ThreadMemRegionTable = (UINTN *) AllocatePool (ProcTraceData->NumberOfProcessors * sizeof (UINTN *));\r
255 if (ThreadMemRegionTable == NULL) {\r
256 DEBUG ((DEBUG_ERROR, "Allocate ProcTrace ThreadMemRegionTable Failed\n"));\r
257 return RETURN_OUT_OF_RESOURCES;\r
258 }\r
259 ProcTraceData->ThreadMemRegionTable = ThreadMemRegionTable;\r
260\r
261 for (Index = 0; Index < ProcTraceData->NumberOfProcessors; Index++, ProcTraceData->AllocatedThreads++) {\r
262 Pages = EFI_SIZE_TO_PAGES (MemRegionSize);\r
263 Alignment = MemRegionSize;\r
264 AlignedAddress = (UINTN) AllocateAlignedReservedPages (Pages, Alignment);\r
265 if (AlignedAddress == 0) {\r
266 DEBUG ((DEBUG_ERROR, "ProcTrace: Out of mem, allocated only for %d threads\n", ProcTraceData->AllocatedThreads));\r
267 if (Index == 0) {\r
268 //\r
269 // Could not allocate for BSP even\r
270 //\r
271 FreePool ((VOID *) ThreadMemRegionTable);\r
272 ThreadMemRegionTable = NULL;\r
273 return RETURN_OUT_OF_RESOURCES;\r
274 }\r
275 break;\r
276 }\r
277\r
278 ThreadMemRegionTable[Index] = AlignedAddress;\r
279 DEBUG ((DEBUG_INFO, "ProcTrace: PT MemRegionBaseAddr(aligned) for thread %d: 0x%llX \n", Index, (UINT64) ThreadMemRegionTable[Index]));\r
280 }\r
281\r
282 DEBUG ((DEBUG_INFO, "ProcTrace: Allocated PT mem for %d thread \n", ProcTraceData->AllocatedThreads));\r
283 MemRegionBaseAddr = ThreadMemRegionTable[0];\r
284 } else {\r
285 if (ProcessorNumber < ProcTraceData->AllocatedThreads) {\r
286 MemRegionBaseAddr = ProcTraceData->ThreadMemRegionTable[ProcessorNumber];\r
287 } else {\r
288 return RETURN_SUCCESS;\r
289 }\r
290 }\r
291\r
292 ///\r
293 /// Check Processor Trace output scheme: Single Range output or ToPA table\r
294 ///\r
295\r
296 //\r
297 // Single Range output scheme\r
298 //\r
7367cc6c 299 if (ProcTraceData->ProcessorData[ProcessorNumber].SingleRangeSupported &&\r
330021fa 300 (ProcTraceData->ProcTraceOutputScheme == RtitOutputSchemeSingleRange)) {\r
bc230057
ED
301 if (FirstIn) {\r
302 DEBUG ((DEBUG_INFO, "ProcTrace: Enabling Single Range Output scheme \n"));\r
303 }\r
304\r
305 //\r
306 // Clear MSR IA32_RTIT_CTL (0x570) ToPA (Bit 8)\r
307 //\r
b2b0ffc9
ED
308 CtrlReg.Uint64 = AsmReadMsr64 (MSR_IA32_RTIT_CTL);\r
309 CtrlReg.Bits.ToPA = 0;\r
bc230057
ED
310 CPU_REGISTER_TABLE_WRITE64 (\r
311 ProcessorNumber,\r
312 Msr,\r
313 MSR_IA32_RTIT_CTL,\r
b2b0ffc9 314 CtrlReg.Uint64\r
bc230057
ED
315 );\r
316\r
317 //\r
b2b0ffc9 318 // Program MSR IA32_RTIT_OUTPUT_BASE (0x560) bits[63:7] with the allocated Memory Region\r
bc230057 319 //\r
b2b0ffc9
ED
320 OutputBaseReg.Bits.Base = (MemRegionBaseAddr >> 7) & 0x01FFFFFF;\r
321 OutputBaseReg.Bits.BaseHi = RShiftU64 ((UINT64) MemRegionBaseAddr, 32) & 0xFFFFFFFF;\r
bc230057
ED
322 CPU_REGISTER_TABLE_WRITE64 (\r
323 ProcessorNumber,\r
324 Msr,\r
325 MSR_IA32_RTIT_OUTPUT_BASE,\r
b2b0ffc9 326 OutputBaseReg.Uint64\r
bc230057
ED
327 );\r
328\r
329 //\r
330 // Program the Mask bits for the Memory Region to MSR IA32_RTIT_OUTPUT_MASK_PTRS (561h)\r
331 //\r
b2b0ffc9 332 OutputMaskPtrsReg.Bits.MaskOrTableOffset = ((MemRegionSize - 1) >> 7) & 0x01FFFFFF;\r
821f24b1 333 OutputMaskPtrsReg.Bits.OutputOffset = RShiftU64 (MemRegionSize - 1, 32) & 0xFFFFFFFF;\r
bc230057
ED
334 CPU_REGISTER_TABLE_WRITE64 (\r
335 ProcessorNumber,\r
336 Msr,\r
337 MSR_IA32_RTIT_OUTPUT_MASK_PTRS,\r
b2b0ffc9 338 OutputMaskPtrsReg.Uint64\r
bc230057 339 );\r
bc230057
ED
340 }\r
341\r
342 //\r
343 // ToPA(Table of physical address) scheme\r
344 //\r
7367cc6c 345 if (ProcTraceData->ProcessorData[ProcessorNumber].TopaSupported &&\r
330021fa 346 (ProcTraceData->ProcTraceOutputScheme == RtitOutputSchemeToPA)) {\r
bc230057
ED
347 //\r
348 // Create ToPA structure aligned at 4KB for each logical thread\r
349 // with at least 2 entries by 8 bytes size each. The first entry\r
350 // should have the trace output base address in bits 47:12, 6:9\r
351 // for Size, bits 4,2 and 0 must be cleared. The second entry\r
352 // should have the base address of the table location in bits\r
353 // 47:12, bits 4 and 2 must be cleared and bit 0 must be set.\r
354 //\r
355 if (FirstIn) {\r
356 DEBUG ((DEBUG_INFO, "ProcTrace: Enabling ToPA scheme \n"));\r
357 //\r
358 // Let BSP allocate ToPA table mem for all threads\r
359 //\r
360 TopaMemArray = (UINTN *) AllocatePool (ProcTraceData->AllocatedThreads * sizeof (UINTN *));\r
361 if (TopaMemArray == NULL) {\r
362 DEBUG ((DEBUG_ERROR, "ProcTrace: Allocate mem for ToPA Failed\n"));\r
363 return RETURN_OUT_OF_RESOURCES;\r
364 }\r
365 ProcTraceData->TopaMemArray = TopaMemArray;\r
366\r
367 for (Index = 0; Index < ProcTraceData->AllocatedThreads; Index++) {\r
368 Pages = EFI_SIZE_TO_PAGES (sizeof (PROC_TRACE_TOPA_TABLE));\r
369 Alignment = 0x1000;\r
370 AlignedAddress = (UINTN) AllocateAlignedReservedPages (Pages, Alignment);\r
371 if (AlignedAddress == 0) {\r
372 if (Index < ProcTraceData->AllocatedThreads) {\r
373 ProcTraceData->AllocatedThreads = Index;\r
374 }\r
375 DEBUG ((DEBUG_ERROR, "ProcTrace: Out of mem, allocating ToPA mem only for %d threads\n", ProcTraceData->AllocatedThreads));\r
376 if (Index == 0) {\r
377 //\r
378 // Could not allocate for BSP\r
379 //\r
380 FreePool ((VOID *) TopaMemArray);\r
381 TopaMemArray = NULL;\r
382 return RETURN_OUT_OF_RESOURCES;\r
383 }\r
384 break;\r
385 }\r
386\r
387 TopaMemArray[Index] = AlignedAddress;\r
388 DEBUG ((DEBUG_INFO, "ProcTrace: Topa table address(aligned) for thread %d is 0x%llX \n", Index, (UINT64) TopaMemArray[Index]));\r
389 }\r
390\r
391 DEBUG ((DEBUG_INFO, "ProcTrace: Allocated ToPA mem for %d thread \n", ProcTraceData->AllocatedThreads));\r
392 //\r
393 // BSP gets the first block\r
394 //\r
395 TopaTableBaseAddr = TopaMemArray[0];\r
396 } else {\r
397 //\r
398 // Count for currently executing AP.\r
399 //\r
400 if (ProcessorNumber < ProcTraceData->AllocatedThreads) {\r
401 TopaTableBaseAddr = ProcTraceData->TopaMemArray[ProcessorNumber];\r
402 } else {\r
403 return RETURN_SUCCESS;\r
404 }\r
405 }\r
406\r
407 TopaTable = (PROC_TRACE_TOPA_TABLE *) TopaTableBaseAddr;\r
b2b0ffc9
ED
408 TopaEntryPtr = &TopaTable->TopaEntry[0];\r
409 TopaEntryPtr->Bits.Base = (MemRegionBaseAddr >> 12) & 0x000FFFFF;\r
410 TopaEntryPtr->Bits.BaseHi = RShiftU64 ((UINT64) MemRegionBaseAddr, 32) & 0xFFFFFFFF;\r
411 TopaEntryPtr->Bits.Size = ProcTraceData->ProcTraceMemSize;\r
412 TopaEntryPtr->Bits.END = 0;\r
413\r
414 TopaEntryPtr = &TopaTable->TopaEntry[1];\r
415 TopaEntryPtr->Bits.Base = (TopaTableBaseAddr >> 12) & 0x000FFFFF;\r
416 TopaEntryPtr->Bits.BaseHi = RShiftU64 ((UINT64) TopaTableBaseAddr, 32) & 0xFFFFFFFF;\r
417 TopaEntryPtr->Bits.END = 1;\r
bc230057
ED
418\r
419 //\r
b2b0ffc9 420 // Program the MSR IA32_RTIT_OUTPUT_BASE (0x560) bits[63:7] with ToPA base\r
bc230057 421 //\r
b2b0ffc9
ED
422 OutputBaseReg.Bits.Base = (TopaTableBaseAddr >> 7) & 0x01FFFFFF;\r
423 OutputBaseReg.Bits.BaseHi = RShiftU64 ((UINT64) TopaTableBaseAddr, 32) & 0xFFFFFFFF;\r
bc230057
ED
424 CPU_REGISTER_TABLE_WRITE64 (\r
425 ProcessorNumber,\r
426 Msr,\r
427 MSR_IA32_RTIT_OUTPUT_BASE,\r
b2b0ffc9 428 OutputBaseReg.Uint64\r
bc230057
ED
429 );\r
430\r
431 //\r
432 // Set the MSR IA32_RTIT_OUTPUT_MASK (0x561) bits[63:7] to 0\r
433 //\r
b2b0ffc9
ED
434 OutputMaskPtrsReg.Bits.MaskOrTableOffset = 0;\r
435 OutputMaskPtrsReg.Bits.OutputOffset = 0;\r
bc230057
ED
436 CPU_REGISTER_TABLE_WRITE64 (\r
437 ProcessorNumber,\r
438 Msr,\r
439 MSR_IA32_RTIT_OUTPUT_MASK_PTRS,\r
b2b0ffc9 440 OutputMaskPtrsReg.Uint64\r
bc230057
ED
441 );\r
442 //\r
443 // Enable ToPA output scheme by enabling MSR IA32_RTIT_CTL (0x570) ToPA (Bit 8)\r
444 //\r
b2b0ffc9
ED
445 CtrlReg.Uint64 = AsmReadMsr64 (MSR_IA32_RTIT_CTL);\r
446 CtrlReg.Bits.ToPA = 1;\r
bc230057
ED
447 CPU_REGISTER_TABLE_WRITE64 (\r
448 ProcessorNumber,\r
449 Msr,\r
450 MSR_IA32_RTIT_CTL,\r
b2b0ffc9 451 CtrlReg.Uint64\r
bc230057
ED
452 );\r
453 }\r
454\r
455 ///\r
456 /// Enable the Processor Trace feature from MSR IA32_RTIT_CTL (570h)\r
457 ///\r
b2b0ffc9
ED
458 CtrlReg.Uint64 = AsmReadMsr64 (MSR_IA32_RTIT_CTL);\r
459 CtrlReg.Bits.OS = 1;\r
460 CtrlReg.Bits.User = 1;\r
461 CtrlReg.Bits.BranchEn = 1;\r
bc230057 462 if (!State) {\r
b2b0ffc9
ED
463 CtrlReg.Bits.TraceEn = 0;\r
464 } else {\r
465 CtrlReg.Bits.TraceEn = 1;\r
bc230057
ED
466 }\r
467 CPU_REGISTER_TABLE_WRITE64 (\r
468 ProcessorNumber,\r
469 Msr,\r
470 MSR_IA32_RTIT_CTL,\r
b2b0ffc9 471 CtrlReg.Uint64\r
bc230057
ED
472 );\r
473\r
474 return RETURN_SUCCESS;\r
475}\r