]> git.proxmox.com Git - mirror_edk2.git/blame - UefiCpuPkg/Library/CpuCommonFeaturesLib/ProcTrace.c
UefiCpuPkg/CpuCommonFeaturesLib: Use MSR data structure when change MSR value.
[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
33 OutputSchemeSingleRange = 0,\r
34 OutputSchemeToPA,\r
35 OutputSchemeInvalid\r
36} PROC_TRACE_OUTPUT_SCHEME;\r
37\r
38typedef struct {\r
39 BOOLEAN ProcTraceSupported;\r
40 BOOLEAN TopaSupported;\r
41 BOOLEAN SingleRangeSupported;\r
42} PROC_TRACE_PROCESSOR_DATA;\r
43\r
44typedef struct {\r
45 UINT32 NumberOfProcessors;\r
46\r
47 UINT8 ProcTraceOutputScheme; \r
48 UINT32 ProcTraceMemSize;\r
49\r
50 UINTN *ThreadMemRegionTable;\r
51 UINTN AllocatedThreads;\r
52\r
53 UINTN *TopaMemArray;\r
54 UINTN TopaMemArrayCount;\r
55\r
56 PROC_TRACE_PROCESSOR_DATA *ProcessorData;\r
57} PROC_TRACE_DATA;\r
58\r
59typedef struct {\r
b2b0ffc9 60 RTIT_TOPA_TABLE_ENTRY TopaEntry[MAX_TOPA_ENTRY_COUNT];\r
bc230057
ED
61} PROC_TRACE_TOPA_TABLE;\r
62\r
63/**\r
64 Prepares for the data used by CPU feature detection and initialization.\r
65\r
66 @param[in] NumberOfProcessors The number of CPUs in the platform.\r
67\r
68 @return Pointer to a buffer of CPU related configuration data.\r
69\r
70 @note This service could be called by BSP only.\r
71**/\r
72VOID *\r
73EFIAPI\r
74ProcTraceGetConfigData (\r
75 IN UINTN NumberOfProcessors\r
76 )\r
77{\r
78 PROC_TRACE_DATA *ConfigData;\r
79\r
80 ConfigData = AllocateZeroPool (sizeof (PROC_TRACE_DATA) + sizeof (PROC_TRACE_PROCESSOR_DATA) * NumberOfProcessors);\r
81 ASSERT (ConfigData != NULL);\r
82 ConfigData->ProcessorData = (PROC_TRACE_PROCESSOR_DATA *) ((UINT8*) ConfigData + sizeof (PROC_TRACE_DATA));\r
83\r
84 ConfigData->NumberOfProcessors = (UINT32) NumberOfProcessors;\r
85 ConfigData->ProcTraceMemSize = PcdGet32 (PcdCpuProcTraceMemSize);\r
86 ConfigData->ProcTraceOutputScheme = PcdGet8 (PcdCpuProcTraceOutputScheme);\r
87\r
88 return ConfigData;\r
89}\r
90\r
91/**\r
92 Detects if Intel Processor Trace feature supported on current \r
93 processor.\r
94\r
95 @param[in] ProcessorNumber The index of the CPU executing this function.\r
96 @param[in] CpuInfo A pointer to the REGISTER_CPU_FEATURE_INFORMATION\r
97 structure for the CPU executing this function.\r
98 @param[in] ConfigData A pointer to the configuration buffer returned\r
99 by CPU_FEATURE_GET_CONFIG_DATA. NULL if\r
100 CPU_FEATURE_GET_CONFIG_DATA was not provided in\r
101 RegisterCpuFeature().\r
102\r
103 @retval TRUE Processor Trace feature is supported.\r
104 @retval FALSE Processor Trace feature is not supported.\r
105\r
106 @note This service could be called by BSP/APs.\r
107**/\r
108BOOLEAN\r
109EFIAPI\r
110ProcTraceSupport (\r
111 IN UINTN ProcessorNumber,\r
112 IN REGISTER_CPU_FEATURE_INFORMATION *CpuInfo,\r
113 IN VOID *ConfigData OPTIONAL\r
114 )\r
115{\r
116 PROC_TRACE_DATA *ProcTraceData;\r
117 CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS_EBX Ebx;\r
118 CPUID_INTEL_PROCESSOR_TRACE_MAIN_LEAF_ECX Ecx;\r
119\r
120 //\r
121 // Check if ProcTraceMemorySize option is enabled (0xFF means disable by user)\r
122 //\r
123 ProcTraceData = (PROC_TRACE_DATA *) ConfigData;\r
b2b0ffc9
ED
124 if ((ProcTraceData->ProcTraceMemSize > RtitTopaMemorySize128M) ||\r
125 (ProcTraceData->ProcTraceOutputScheme > ProcTraceOutputSchemeToPA)) {\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
141 if (ProcTraceData->ProcessorData[ProcessorNumber].TopaSupported || \r
142 ProcTraceData->ProcessorData[ProcessorNumber].SingleRangeSupported) {\r
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
195\r
196 MemRegionBaseAddr = 0;\r
197 FirstIn = FALSE;\r
198\r
199 if (ProcTraceData->ThreadMemRegionTable == NULL) {\r
200 FirstIn = TRUE;\r
201 DEBUG ((DEBUG_INFO, "Initialize Processor Trace\n"));\r
202 }\r
203\r
204 ///\r
205 /// Refer to PROC_TRACE_MEM_SIZE Table for Size Encoding\r
206 ///\r
207 MemRegionSize = (UINT32) (1 << (ProcTraceData->ProcTraceMemSize + 12));\r
208 if (FirstIn) {\r
209 DEBUG ((DEBUG_INFO, "ProcTrace: MemSize requested: 0x%X \n", MemRegionSize));\r
210 }\r
211\r
212 //\r
213 // Clear MSR_IA32_RTIT_CTL[0] and IA32_RTIT_STS only if MSR_IA32_RTIT_CTL[0]==1b\r
214 //\r
b2b0ffc9
ED
215 CtrlReg.Uint64 = AsmReadMsr64 (MSR_IA32_RTIT_CTL);\r
216 if (CtrlReg.Bits.TraceEn != 0) {\r
bc230057
ED
217 ///\r
218 /// Clear bit 0 in MSR IA32_RTIT_CTL (570)\r
219 ///\r
b2b0ffc9 220 CtrlReg.Bits.TraceEn = 0;\r
bc230057
ED
221 CPU_REGISTER_TABLE_WRITE64 (\r
222 ProcessorNumber,\r
223 Msr,\r
224 MSR_IA32_RTIT_CTL,\r
b2b0ffc9 225 CtrlReg.Uint64\r
bc230057
ED
226 );\r
227\r
228 ///\r
229 /// Clear MSR IA32_RTIT_STS (571h) to all zeros\r
230 ///\r
b2b0ffc9 231 StatusReg.Uint64 = 0x0;\r
bc230057
ED
232 CPU_REGISTER_TABLE_WRITE64 (\r
233 ProcessorNumber,\r
234 Msr,\r
235 MSR_IA32_RTIT_STATUS,\r
b2b0ffc9 236 StatusReg.Uint64\r
bc230057
ED
237 );\r
238 }\r
239\r
240 if (FirstIn) {\r
241 //\r
242 // Let BSP allocate and create the necessary memory region (Aligned to the size of\r
243 // the memory region from setup option(ProcTraceMemSize) which is an integral multiple of 4kB)\r
244 // for the all the enabled threads for storing Processor Trace debug data. Then Configure the trace\r
245 // address base in MSR, IA32_RTIT_OUTPUT_BASE (560h) bits 47:12. Note that all regions must be\r
246 // aligned based on their size, not just 4K. Thus a 2M region must have bits 20:12 clear.\r
247 //\r
248 ThreadMemRegionTable = (UINTN *) AllocatePool (ProcTraceData->NumberOfProcessors * sizeof (UINTN *));\r
249 if (ThreadMemRegionTable == NULL) {\r
250 DEBUG ((DEBUG_ERROR, "Allocate ProcTrace ThreadMemRegionTable Failed\n"));\r
251 return RETURN_OUT_OF_RESOURCES;\r
252 }\r
253 ProcTraceData->ThreadMemRegionTable = ThreadMemRegionTable;\r
254\r
255 for (Index = 0; Index < ProcTraceData->NumberOfProcessors; Index++, ProcTraceData->AllocatedThreads++) {\r
256 Pages = EFI_SIZE_TO_PAGES (MemRegionSize);\r
257 Alignment = MemRegionSize;\r
258 AlignedAddress = (UINTN) AllocateAlignedReservedPages (Pages, Alignment);\r
259 if (AlignedAddress == 0) {\r
260 DEBUG ((DEBUG_ERROR, "ProcTrace: Out of mem, allocated only for %d threads\n", ProcTraceData->AllocatedThreads));\r
261 if (Index == 0) {\r
262 //\r
263 // Could not allocate for BSP even\r
264 //\r
265 FreePool ((VOID *) ThreadMemRegionTable);\r
266 ThreadMemRegionTable = NULL;\r
267 return RETURN_OUT_OF_RESOURCES;\r
268 }\r
269 break;\r
270 }\r
271\r
272 ThreadMemRegionTable[Index] = AlignedAddress;\r
273 DEBUG ((DEBUG_INFO, "ProcTrace: PT MemRegionBaseAddr(aligned) for thread %d: 0x%llX \n", Index, (UINT64) ThreadMemRegionTable[Index]));\r
274 }\r
275\r
276 DEBUG ((DEBUG_INFO, "ProcTrace: Allocated PT mem for %d thread \n", ProcTraceData->AllocatedThreads));\r
277 MemRegionBaseAddr = ThreadMemRegionTable[0];\r
278 } else {\r
279 if (ProcessorNumber < ProcTraceData->AllocatedThreads) {\r
280 MemRegionBaseAddr = ProcTraceData->ThreadMemRegionTable[ProcessorNumber];\r
281 } else {\r
282 return RETURN_SUCCESS;\r
283 }\r
284 }\r
285\r
286 ///\r
287 /// Check Processor Trace output scheme: Single Range output or ToPA table\r
288 ///\r
289\r
290 //\r
291 // Single Range output scheme\r
292 //\r
293 if (ProcTraceData->ProcessorData[ProcessorNumber].SingleRangeSupported && \r
294 (ProcTraceData->ProcTraceOutputScheme == OutputSchemeSingleRange)) {\r
295 if (FirstIn) {\r
296 DEBUG ((DEBUG_INFO, "ProcTrace: Enabling Single Range Output scheme \n"));\r
297 }\r
298\r
299 //\r
300 // Clear MSR IA32_RTIT_CTL (0x570) ToPA (Bit 8)\r
301 //\r
b2b0ffc9
ED
302 CtrlReg.Uint64 = AsmReadMsr64 (MSR_IA32_RTIT_CTL);\r
303 CtrlReg.Bits.ToPA = 0;\r
bc230057
ED
304 CPU_REGISTER_TABLE_WRITE64 (\r
305 ProcessorNumber,\r
306 Msr,\r
307 MSR_IA32_RTIT_CTL,\r
b2b0ffc9 308 CtrlReg.Uint64\r
bc230057
ED
309 );\r
310\r
311 //\r
b2b0ffc9 312 // Program MSR IA32_RTIT_OUTPUT_BASE (0x560) bits[63:7] with the allocated Memory Region\r
bc230057 313 //\r
b2b0ffc9
ED
314 OutputBaseReg.Bits.Base = (MemRegionBaseAddr >> 7) & 0x01FFFFFF;\r
315 OutputBaseReg.Bits.BaseHi = RShiftU64 ((UINT64) MemRegionBaseAddr, 32) & 0xFFFFFFFF;\r
bc230057
ED
316 CPU_REGISTER_TABLE_WRITE64 (\r
317 ProcessorNumber,\r
318 Msr,\r
319 MSR_IA32_RTIT_OUTPUT_BASE,\r
b2b0ffc9 320 OutputBaseReg.Uint64\r
bc230057
ED
321 );\r
322\r
323 //\r
324 // Program the Mask bits for the Memory Region to MSR IA32_RTIT_OUTPUT_MASK_PTRS (561h)\r
325 //\r
b2b0ffc9
ED
326 OutputMaskPtrsReg.Bits.MaskOrTableOffset = ((MemRegionSize - 1) >> 7) & 0x01FFFFFF;\r
327 OutputMaskPtrsReg.Bits.OutputOffset = RShiftU64 ((UINT64) (MemRegionSize - 1), 32) & 0xFFFFFFFF;\r
bc230057
ED
328 CPU_REGISTER_TABLE_WRITE64 (\r
329 ProcessorNumber,\r
330 Msr,\r
331 MSR_IA32_RTIT_OUTPUT_MASK_PTRS,\r
b2b0ffc9 332 OutputMaskPtrsReg.Uint64\r
bc230057 333 );\r
bc230057
ED
334 }\r
335\r
336 //\r
337 // ToPA(Table of physical address) scheme\r
338 //\r
339 if (ProcTraceData->ProcessorData[ProcessorNumber].TopaSupported && \r
340 (ProcTraceData->ProcTraceOutputScheme == OutputSchemeToPA)) {\r
341 //\r
342 // Create ToPA structure aligned at 4KB for each logical thread\r
343 // with at least 2 entries by 8 bytes size each. The first entry\r
344 // should have the trace output base address in bits 47:12, 6:9\r
345 // for Size, bits 4,2 and 0 must be cleared. The second entry\r
346 // should have the base address of the table location in bits\r
347 // 47:12, bits 4 and 2 must be cleared and bit 0 must be set.\r
348 //\r
349 if (FirstIn) {\r
350 DEBUG ((DEBUG_INFO, "ProcTrace: Enabling ToPA scheme \n"));\r
351 //\r
352 // Let BSP allocate ToPA table mem for all threads\r
353 //\r
354 TopaMemArray = (UINTN *) AllocatePool (ProcTraceData->AllocatedThreads * sizeof (UINTN *));\r
355 if (TopaMemArray == NULL) {\r
356 DEBUG ((DEBUG_ERROR, "ProcTrace: Allocate mem for ToPA Failed\n"));\r
357 return RETURN_OUT_OF_RESOURCES;\r
358 }\r
359 ProcTraceData->TopaMemArray = TopaMemArray;\r
360\r
361 for (Index = 0; Index < ProcTraceData->AllocatedThreads; Index++) {\r
362 Pages = EFI_SIZE_TO_PAGES (sizeof (PROC_TRACE_TOPA_TABLE));\r
363 Alignment = 0x1000;\r
364 AlignedAddress = (UINTN) AllocateAlignedReservedPages (Pages, Alignment);\r
365 if (AlignedAddress == 0) {\r
366 if (Index < ProcTraceData->AllocatedThreads) {\r
367 ProcTraceData->AllocatedThreads = Index;\r
368 }\r
369 DEBUG ((DEBUG_ERROR, "ProcTrace: Out of mem, allocating ToPA mem only for %d threads\n", ProcTraceData->AllocatedThreads));\r
370 if (Index == 0) {\r
371 //\r
372 // Could not allocate for BSP\r
373 //\r
374 FreePool ((VOID *) TopaMemArray);\r
375 TopaMemArray = NULL;\r
376 return RETURN_OUT_OF_RESOURCES;\r
377 }\r
378 break;\r
379 }\r
380\r
381 TopaMemArray[Index] = AlignedAddress;\r
382 DEBUG ((DEBUG_INFO, "ProcTrace: Topa table address(aligned) for thread %d is 0x%llX \n", Index, (UINT64) TopaMemArray[Index]));\r
383 }\r
384\r
385 DEBUG ((DEBUG_INFO, "ProcTrace: Allocated ToPA mem for %d thread \n", ProcTraceData->AllocatedThreads));\r
386 //\r
387 // BSP gets the first block\r
388 //\r
389 TopaTableBaseAddr = TopaMemArray[0];\r
390 } else {\r
391 //\r
392 // Count for currently executing AP.\r
393 //\r
394 if (ProcessorNumber < ProcTraceData->AllocatedThreads) {\r
395 TopaTableBaseAddr = ProcTraceData->TopaMemArray[ProcessorNumber];\r
396 } else {\r
397 return RETURN_SUCCESS;\r
398 }\r
399 }\r
400\r
401 TopaTable = (PROC_TRACE_TOPA_TABLE *) TopaTableBaseAddr;\r
b2b0ffc9
ED
402 TopaEntryPtr = &TopaTable->TopaEntry[0];\r
403 TopaEntryPtr->Bits.Base = (MemRegionBaseAddr >> 12) & 0x000FFFFF;\r
404 TopaEntryPtr->Bits.BaseHi = RShiftU64 ((UINT64) MemRegionBaseAddr, 32) & 0xFFFFFFFF;\r
405 TopaEntryPtr->Bits.Size = ProcTraceData->ProcTraceMemSize;\r
406 TopaEntryPtr->Bits.END = 0;\r
407\r
408 TopaEntryPtr = &TopaTable->TopaEntry[1];\r
409 TopaEntryPtr->Bits.Base = (TopaTableBaseAddr >> 12) & 0x000FFFFF;\r
410 TopaEntryPtr->Bits.BaseHi = RShiftU64 ((UINT64) TopaTableBaseAddr, 32) & 0xFFFFFFFF;\r
411 TopaEntryPtr->Bits.END = 1;\r
bc230057
ED
412\r
413 //\r
b2b0ffc9 414 // Program the MSR IA32_RTIT_OUTPUT_BASE (0x560) bits[63:7] with ToPA base\r
bc230057 415 //\r
b2b0ffc9
ED
416 OutputBaseReg.Bits.Base = (TopaTableBaseAddr >> 7) & 0x01FFFFFF;\r
417 OutputBaseReg.Bits.BaseHi = RShiftU64 ((UINT64) TopaTableBaseAddr, 32) & 0xFFFFFFFF;\r
bc230057
ED
418 CPU_REGISTER_TABLE_WRITE64 (\r
419 ProcessorNumber,\r
420 Msr,\r
421 MSR_IA32_RTIT_OUTPUT_BASE,\r
b2b0ffc9 422 OutputBaseReg.Uint64\r
bc230057
ED
423 );\r
424\r
425 //\r
426 // Set the MSR IA32_RTIT_OUTPUT_MASK (0x561) bits[63:7] to 0\r
427 //\r
b2b0ffc9
ED
428 OutputMaskPtrsReg.Bits.MaskOrTableOffset = 0;\r
429 OutputMaskPtrsReg.Bits.OutputOffset = 0;\r
bc230057
ED
430 CPU_REGISTER_TABLE_WRITE64 (\r
431 ProcessorNumber,\r
432 Msr,\r
433 MSR_IA32_RTIT_OUTPUT_MASK_PTRS,\r
b2b0ffc9 434 OutputMaskPtrsReg.Uint64\r
bc230057
ED
435 );\r
436 //\r
437 // Enable ToPA output scheme by enabling MSR IA32_RTIT_CTL (0x570) ToPA (Bit 8)\r
438 //\r
b2b0ffc9
ED
439 CtrlReg.Uint64 = AsmReadMsr64 (MSR_IA32_RTIT_CTL);\r
440 CtrlReg.Bits.ToPA = 1;\r
bc230057
ED
441 CPU_REGISTER_TABLE_WRITE64 (\r
442 ProcessorNumber,\r
443 Msr,\r
444 MSR_IA32_RTIT_CTL,\r
b2b0ffc9 445 CtrlReg.Uint64\r
bc230057
ED
446 );\r
447 }\r
448\r
449 ///\r
450 /// Enable the Processor Trace feature from MSR IA32_RTIT_CTL (570h)\r
451 ///\r
b2b0ffc9
ED
452 CtrlReg.Uint64 = AsmReadMsr64 (MSR_IA32_RTIT_CTL);\r
453 CtrlReg.Bits.OS = 1;\r
454 CtrlReg.Bits.User = 1;\r
455 CtrlReg.Bits.BranchEn = 1;\r
bc230057 456 if (!State) {\r
b2b0ffc9
ED
457 CtrlReg.Bits.TraceEn = 0;\r
458 } else {\r
459 CtrlReg.Bits.TraceEn = 1;\r
bc230057
ED
460 }\r
461 CPU_REGISTER_TABLE_WRITE64 (\r
462 ProcessorNumber,\r
463 Msr,\r
464 MSR_IA32_RTIT_CTL,\r
b2b0ffc9 465 CtrlReg.Uint64\r
bc230057
ED
466 );\r
467\r
468 return RETURN_SUCCESS;\r
469}\r