]> git.proxmox.com Git - mirror_edk2.git/blame - UefiCpuPkg/Library/CpuCommonFeaturesLib/ProcTrace.c
UefiCpuPkg: Enhance feature dependency check
[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
3dcb5325 123 ASSERT (ProcTraceData != NULL);\r
b2b0ffc9 124 if ((ProcTraceData->ProcTraceMemSize > RtitTopaMemorySize128M) ||\r
330021fa 125 (ProcTraceData->ProcTraceOutputScheme > RtitOutputSchemeToPA)) {\r
bc230057
ED
126 return FALSE;\r
127 }\r
128\r
129 //\r
130 // Check if Processor Trace is supported\r
131 //\r
132 AsmCpuidEx (CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS, 0, NULL, &Ebx.Uint32, NULL, NULL);\r
133 ProcTraceData->ProcessorData[ProcessorNumber].ProcTraceSupported = (BOOLEAN) (Ebx.Bits.IntelProcessorTrace == 1);\r
134 if (!ProcTraceData->ProcessorData[ProcessorNumber].ProcTraceSupported) {\r
135 return FALSE;\r
136 }\r
137\r
138 AsmCpuidEx (CPUID_INTEL_PROCESSOR_TRACE, CPUID_INTEL_PROCESSOR_TRACE_MAIN_LEAF, NULL, NULL, &Ecx.Uint32, NULL);\r
139 ProcTraceData->ProcessorData[ProcessorNumber].TopaSupported = (BOOLEAN) (Ecx.Bits.RTIT == 1);\r
140 ProcTraceData->ProcessorData[ProcessorNumber].SingleRangeSupported = (BOOLEAN) (Ecx.Bits.SingleRangeOutput == 1);\r
330021fa
ED
141 if ((ProcTraceData->ProcessorData[ProcessorNumber].TopaSupported && (ProcTraceData->ProcTraceOutputScheme == RtitOutputSchemeToPA)) ||\r
142 (ProcTraceData->ProcessorData[ProcessorNumber].SingleRangeSupported && (ProcTraceData->ProcTraceOutputScheme == RtitOutputSchemeSingleRange))) {\r
bc230057
ED
143 return TRUE;\r
144 }\r
145\r
146 return FALSE;\r
147}\r
148\r
149/**\r
150 Initializes Intel Processor Trace feature to specific state.\r
151\r
152 @param[in] ProcessorNumber The index of the CPU executing this function.\r
153 @param[in] CpuInfo A pointer to the REGISTER_CPU_FEATURE_INFORMATION\r
154 structure for the CPU executing this function.\r
155 @param[in] ConfigData A pointer to the configuration buffer returned\r
156 by CPU_FEATURE_GET_CONFIG_DATA. NULL if\r
157 CPU_FEATURE_GET_CONFIG_DATA was not provided in\r
158 RegisterCpuFeature().\r
159 @param[in] State If TRUE, then the Processor Trace feature must be\r
160 enabled.\r
161 If FALSE, then the Processor Trace feature must be\r
162 disabled.\r
163\r
164 @retval RETURN_SUCCESS Intel Processor Trace feature is initialized.\r
165\r
166**/\r
167RETURN_STATUS\r
168EFIAPI\r
169ProcTraceInitialize (\r
170 IN UINTN ProcessorNumber,\r
171 IN REGISTER_CPU_FEATURE_INFORMATION *CpuInfo,\r
172 IN VOID *ConfigData, OPTIONAL\r
173 IN BOOLEAN State\r
174 )\r
175{\r
bc230057
ED
176 UINT32 MemRegionSize;\r
177 UINTN Pages;\r
178 UINTN Alignment;\r
179 UINTN MemRegionBaseAddr;\r
180 UINTN *ThreadMemRegionTable;\r
181 UINTN Index;\r
182 UINTN TopaTableBaseAddr;\r
183 UINTN AlignedAddress;\r
184 UINTN *TopaMemArray;\r
185 PROC_TRACE_TOPA_TABLE *TopaTable;\r
186 PROC_TRACE_DATA *ProcTraceData;\r
187 BOOLEAN FirstIn;\r
b2b0ffc9
ED
188 MSR_IA32_RTIT_CTL_REGISTER CtrlReg;\r
189 MSR_IA32_RTIT_STATUS_REGISTER StatusReg;\r
190 MSR_IA32_RTIT_OUTPUT_BASE_REGISTER OutputBaseReg;\r
191 MSR_IA32_RTIT_OUTPUT_MASK_PTRS_REGISTER OutputMaskPtrsReg;\r
192 RTIT_TOPA_TABLE_ENTRY *TopaEntryPtr;\r
bc230057
ED
193\r
194 ProcTraceData = (PROC_TRACE_DATA *) ConfigData;\r
3dcb5325 195 ASSERT (ProcTraceData != NULL);\r
bc230057
ED
196\r
197 MemRegionBaseAddr = 0;\r
198 FirstIn = FALSE;\r
199\r
200 if (ProcTraceData->ThreadMemRegionTable == NULL) {\r
201 FirstIn = TRUE;\r
202 DEBUG ((DEBUG_INFO, "Initialize Processor Trace\n"));\r
203 }\r
204\r
205 ///\r
206 /// Refer to PROC_TRACE_MEM_SIZE Table for Size Encoding\r
207 ///\r
208 MemRegionSize = (UINT32) (1 << (ProcTraceData->ProcTraceMemSize + 12));\r
209 if (FirstIn) {\r
210 DEBUG ((DEBUG_INFO, "ProcTrace: MemSize requested: 0x%X \n", MemRegionSize));\r
211 }\r
212\r
213 //\r
214 // Clear MSR_IA32_RTIT_CTL[0] and IA32_RTIT_STS only if MSR_IA32_RTIT_CTL[0]==1b\r
215 //\r
b2b0ffc9
ED
216 CtrlReg.Uint64 = AsmReadMsr64 (MSR_IA32_RTIT_CTL);\r
217 if (CtrlReg.Bits.TraceEn != 0) {\r
bc230057
ED
218 ///\r
219 /// Clear bit 0 in MSR IA32_RTIT_CTL (570)\r
220 ///\r
b2b0ffc9 221 CtrlReg.Bits.TraceEn = 0;\r
bc230057
ED
222 CPU_REGISTER_TABLE_WRITE64 (\r
223 ProcessorNumber,\r
224 Msr,\r
225 MSR_IA32_RTIT_CTL,\r
b2b0ffc9 226 CtrlReg.Uint64\r
bc230057
ED
227 );\r
228\r
229 ///\r
230 /// Clear MSR IA32_RTIT_STS (571h) to all zeros\r
231 ///\r
b2b0ffc9 232 StatusReg.Uint64 = 0x0;\r
bc230057
ED
233 CPU_REGISTER_TABLE_WRITE64 (\r
234 ProcessorNumber,\r
235 Msr,\r
236 MSR_IA32_RTIT_STATUS,\r
b2b0ffc9 237 StatusReg.Uint64\r
bc230057
ED
238 );\r
239 }\r
240\r
241 if (FirstIn) {\r
242 //\r
243 // Let BSP allocate and create the necessary memory region (Aligned to the size of\r
244 // the memory region from setup option(ProcTraceMemSize) which is an integral multiple of 4kB)\r
245 // for the all the enabled threads for storing Processor Trace debug data. Then Configure the trace\r
246 // address base in MSR, IA32_RTIT_OUTPUT_BASE (560h) bits 47:12. Note that all regions must be\r
247 // aligned based on their size, not just 4K. Thus a 2M region must have bits 20:12 clear.\r
248 //\r
249 ThreadMemRegionTable = (UINTN *) AllocatePool (ProcTraceData->NumberOfProcessors * sizeof (UINTN *));\r
250 if (ThreadMemRegionTable == NULL) {\r
251 DEBUG ((DEBUG_ERROR, "Allocate ProcTrace ThreadMemRegionTable Failed\n"));\r
252 return RETURN_OUT_OF_RESOURCES;\r
253 }\r
254 ProcTraceData->ThreadMemRegionTable = ThreadMemRegionTable;\r
255\r
256 for (Index = 0; Index < ProcTraceData->NumberOfProcessors; Index++, ProcTraceData->AllocatedThreads++) {\r
257 Pages = EFI_SIZE_TO_PAGES (MemRegionSize);\r
258 Alignment = MemRegionSize;\r
259 AlignedAddress = (UINTN) AllocateAlignedReservedPages (Pages, Alignment);\r
260 if (AlignedAddress == 0) {\r
261 DEBUG ((DEBUG_ERROR, "ProcTrace: Out of mem, allocated only for %d threads\n", ProcTraceData->AllocatedThreads));\r
262 if (Index == 0) {\r
263 //\r
264 // Could not allocate for BSP even\r
265 //\r
266 FreePool ((VOID *) ThreadMemRegionTable);\r
267 ThreadMemRegionTable = NULL;\r
268 return RETURN_OUT_OF_RESOURCES;\r
269 }\r
270 break;\r
271 }\r
272\r
273 ThreadMemRegionTable[Index] = AlignedAddress;\r
274 DEBUG ((DEBUG_INFO, "ProcTrace: PT MemRegionBaseAddr(aligned) for thread %d: 0x%llX \n", Index, (UINT64) ThreadMemRegionTable[Index]));\r
275 }\r
276\r
277 DEBUG ((DEBUG_INFO, "ProcTrace: Allocated PT mem for %d thread \n", ProcTraceData->AllocatedThreads));\r
278 MemRegionBaseAddr = ThreadMemRegionTable[0];\r
279 } else {\r
280 if (ProcessorNumber < ProcTraceData->AllocatedThreads) {\r
281 MemRegionBaseAddr = ProcTraceData->ThreadMemRegionTable[ProcessorNumber];\r
282 } else {\r
283 return RETURN_SUCCESS;\r
284 }\r
285 }\r
286\r
287 ///\r
288 /// Check Processor Trace output scheme: Single Range output or ToPA table\r
289 ///\r
290\r
291 //\r
292 // Single Range output scheme\r
293 //\r
294 if (ProcTraceData->ProcessorData[ProcessorNumber].SingleRangeSupported && \r
330021fa 295 (ProcTraceData->ProcTraceOutputScheme == RtitOutputSchemeSingleRange)) {\r
bc230057
ED
296 if (FirstIn) {\r
297 DEBUG ((DEBUG_INFO, "ProcTrace: Enabling Single Range Output scheme \n"));\r
298 }\r
299\r
300 //\r
301 // Clear MSR IA32_RTIT_CTL (0x570) ToPA (Bit 8)\r
302 //\r
b2b0ffc9
ED
303 CtrlReg.Uint64 = AsmReadMsr64 (MSR_IA32_RTIT_CTL);\r
304 CtrlReg.Bits.ToPA = 0;\r
bc230057
ED
305 CPU_REGISTER_TABLE_WRITE64 (\r
306 ProcessorNumber,\r
307 Msr,\r
308 MSR_IA32_RTIT_CTL,\r
b2b0ffc9 309 CtrlReg.Uint64\r
bc230057
ED
310 );\r
311\r
312 //\r
b2b0ffc9 313 // Program MSR IA32_RTIT_OUTPUT_BASE (0x560) bits[63:7] with the allocated Memory Region\r
bc230057 314 //\r
b2b0ffc9
ED
315 OutputBaseReg.Bits.Base = (MemRegionBaseAddr >> 7) & 0x01FFFFFF;\r
316 OutputBaseReg.Bits.BaseHi = RShiftU64 ((UINT64) MemRegionBaseAddr, 32) & 0xFFFFFFFF;\r
bc230057
ED
317 CPU_REGISTER_TABLE_WRITE64 (\r
318 ProcessorNumber,\r
319 Msr,\r
320 MSR_IA32_RTIT_OUTPUT_BASE,\r
b2b0ffc9 321 OutputBaseReg.Uint64\r
bc230057
ED
322 );\r
323\r
324 //\r
325 // Program the Mask bits for the Memory Region to MSR IA32_RTIT_OUTPUT_MASK_PTRS (561h)\r
326 //\r
b2b0ffc9 327 OutputMaskPtrsReg.Bits.MaskOrTableOffset = ((MemRegionSize - 1) >> 7) & 0x01FFFFFF;\r
821f24b1 328 OutputMaskPtrsReg.Bits.OutputOffset = RShiftU64 (MemRegionSize - 1, 32) & 0xFFFFFFFF;\r
bc230057
ED
329 CPU_REGISTER_TABLE_WRITE64 (\r
330 ProcessorNumber,\r
331 Msr,\r
332 MSR_IA32_RTIT_OUTPUT_MASK_PTRS,\r
b2b0ffc9 333 OutputMaskPtrsReg.Uint64\r
bc230057 334 );\r
bc230057
ED
335 }\r
336\r
337 //\r
338 // ToPA(Table of physical address) scheme\r
339 //\r
340 if (ProcTraceData->ProcessorData[ProcessorNumber].TopaSupported && \r
330021fa 341 (ProcTraceData->ProcTraceOutputScheme == RtitOutputSchemeToPA)) {\r
bc230057
ED
342 //\r
343 // Create ToPA structure aligned at 4KB for each logical thread\r
344 // with at least 2 entries by 8 bytes size each. The first entry\r
345 // should have the trace output base address in bits 47:12, 6:9\r
346 // for Size, bits 4,2 and 0 must be cleared. The second entry\r
347 // should have the base address of the table location in bits\r
348 // 47:12, bits 4 and 2 must be cleared and bit 0 must be set.\r
349 //\r
350 if (FirstIn) {\r
351 DEBUG ((DEBUG_INFO, "ProcTrace: Enabling ToPA scheme \n"));\r
352 //\r
353 // Let BSP allocate ToPA table mem for all threads\r
354 //\r
355 TopaMemArray = (UINTN *) AllocatePool (ProcTraceData->AllocatedThreads * sizeof (UINTN *));\r
356 if (TopaMemArray == NULL) {\r
357 DEBUG ((DEBUG_ERROR, "ProcTrace: Allocate mem for ToPA Failed\n"));\r
358 return RETURN_OUT_OF_RESOURCES;\r
359 }\r
360 ProcTraceData->TopaMemArray = TopaMemArray;\r
361\r
362 for (Index = 0; Index < ProcTraceData->AllocatedThreads; Index++) {\r
363 Pages = EFI_SIZE_TO_PAGES (sizeof (PROC_TRACE_TOPA_TABLE));\r
364 Alignment = 0x1000;\r
365 AlignedAddress = (UINTN) AllocateAlignedReservedPages (Pages, Alignment);\r
366 if (AlignedAddress == 0) {\r
367 if (Index < ProcTraceData->AllocatedThreads) {\r
368 ProcTraceData->AllocatedThreads = Index;\r
369 }\r
370 DEBUG ((DEBUG_ERROR, "ProcTrace: Out of mem, allocating ToPA mem only for %d threads\n", ProcTraceData->AllocatedThreads));\r
371 if (Index == 0) {\r
372 //\r
373 // Could not allocate for BSP\r
374 //\r
375 FreePool ((VOID *) TopaMemArray);\r
376 TopaMemArray = NULL;\r
377 return RETURN_OUT_OF_RESOURCES;\r
378 }\r
379 break;\r
380 }\r
381\r
382 TopaMemArray[Index] = AlignedAddress;\r
383 DEBUG ((DEBUG_INFO, "ProcTrace: Topa table address(aligned) for thread %d is 0x%llX \n", Index, (UINT64) TopaMemArray[Index]));\r
384 }\r
385\r
386 DEBUG ((DEBUG_INFO, "ProcTrace: Allocated ToPA mem for %d thread \n", ProcTraceData->AllocatedThreads));\r
387 //\r
388 // BSP gets the first block\r
389 //\r
390 TopaTableBaseAddr = TopaMemArray[0];\r
391 } else {\r
392 //\r
393 // Count for currently executing AP.\r
394 //\r
395 if (ProcessorNumber < ProcTraceData->AllocatedThreads) {\r
396 TopaTableBaseAddr = ProcTraceData->TopaMemArray[ProcessorNumber];\r
397 } else {\r
398 return RETURN_SUCCESS;\r
399 }\r
400 }\r
401\r
402 TopaTable = (PROC_TRACE_TOPA_TABLE *) TopaTableBaseAddr;\r
b2b0ffc9
ED
403 TopaEntryPtr = &TopaTable->TopaEntry[0];\r
404 TopaEntryPtr->Bits.Base = (MemRegionBaseAddr >> 12) & 0x000FFFFF;\r
405 TopaEntryPtr->Bits.BaseHi = RShiftU64 ((UINT64) MemRegionBaseAddr, 32) & 0xFFFFFFFF;\r
406 TopaEntryPtr->Bits.Size = ProcTraceData->ProcTraceMemSize;\r
407 TopaEntryPtr->Bits.END = 0;\r
408\r
409 TopaEntryPtr = &TopaTable->TopaEntry[1];\r
410 TopaEntryPtr->Bits.Base = (TopaTableBaseAddr >> 12) & 0x000FFFFF;\r
411 TopaEntryPtr->Bits.BaseHi = RShiftU64 ((UINT64) TopaTableBaseAddr, 32) & 0xFFFFFFFF;\r
412 TopaEntryPtr->Bits.END = 1;\r
bc230057
ED
413\r
414 //\r
b2b0ffc9 415 // Program the MSR IA32_RTIT_OUTPUT_BASE (0x560) bits[63:7] with ToPA base\r
bc230057 416 //\r
b2b0ffc9
ED
417 OutputBaseReg.Bits.Base = (TopaTableBaseAddr >> 7) & 0x01FFFFFF;\r
418 OutputBaseReg.Bits.BaseHi = RShiftU64 ((UINT64) TopaTableBaseAddr, 32) & 0xFFFFFFFF;\r
bc230057
ED
419 CPU_REGISTER_TABLE_WRITE64 (\r
420 ProcessorNumber,\r
421 Msr,\r
422 MSR_IA32_RTIT_OUTPUT_BASE,\r
b2b0ffc9 423 OutputBaseReg.Uint64\r
bc230057
ED
424 );\r
425\r
426 //\r
427 // Set the MSR IA32_RTIT_OUTPUT_MASK (0x561) bits[63:7] to 0\r
428 //\r
b2b0ffc9
ED
429 OutputMaskPtrsReg.Bits.MaskOrTableOffset = 0;\r
430 OutputMaskPtrsReg.Bits.OutputOffset = 0;\r
bc230057
ED
431 CPU_REGISTER_TABLE_WRITE64 (\r
432 ProcessorNumber,\r
433 Msr,\r
434 MSR_IA32_RTIT_OUTPUT_MASK_PTRS,\r
b2b0ffc9 435 OutputMaskPtrsReg.Uint64\r
bc230057
ED
436 );\r
437 //\r
438 // Enable ToPA output scheme by enabling MSR IA32_RTIT_CTL (0x570) ToPA (Bit 8)\r
439 //\r
b2b0ffc9
ED
440 CtrlReg.Uint64 = AsmReadMsr64 (MSR_IA32_RTIT_CTL);\r
441 CtrlReg.Bits.ToPA = 1;\r
bc230057
ED
442 CPU_REGISTER_TABLE_WRITE64 (\r
443 ProcessorNumber,\r
444 Msr,\r
445 MSR_IA32_RTIT_CTL,\r
b2b0ffc9 446 CtrlReg.Uint64\r
bc230057
ED
447 );\r
448 }\r
449\r
450 ///\r
451 /// Enable the Processor Trace feature from MSR IA32_RTIT_CTL (570h)\r
452 ///\r
b2b0ffc9
ED
453 CtrlReg.Uint64 = AsmReadMsr64 (MSR_IA32_RTIT_CTL);\r
454 CtrlReg.Bits.OS = 1;\r
455 CtrlReg.Bits.User = 1;\r
456 CtrlReg.Bits.BranchEn = 1;\r
bc230057 457 if (!State) {\r
b2b0ffc9
ED
458 CtrlReg.Bits.TraceEn = 0;\r
459 } else {\r
460 CtrlReg.Bits.TraceEn = 1;\r
bc230057
ED
461 }\r
462 CPU_REGISTER_TABLE_WRITE64 (\r
463 ProcessorNumber,\r
464 Msr,\r
465 MSR_IA32_RTIT_CTL,\r
b2b0ffc9 466 CtrlReg.Uint64\r
bc230057
ED
467 );\r
468\r
469 return RETURN_SUCCESS;\r
470}\r