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