]> git.proxmox.com Git - mirror_edk2.git/blame - UefiCpuPkg/Library/CpuCommonFeaturesLib/ProcTrace.c
UefiCpuPkg/CpuCommonFeaturesLib: Register MSR base on scope Info.
[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
bc230057
ED
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 18/// This macro define the max entries in the Topa table.\r
7367cc6c
LG
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
b2b0ffc9 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
7367cc6c 46 UINT8 ProcTraceOutputScheme;\r
bc230057
ED
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
7367cc6c 91 Detects if Intel Processor Trace feature supported on current\r
bc230057
ED
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 193\r
d28daadd
ED
194 //\r
195 // The scope of the MSR_IA32_RTIT_* is core for below processor type, only program\r
196 // MSR_IA32_RTIT_* for thread 0 in each core.\r
197 //\r
198 if (IS_GOLDMONT_PROCESSOR (CpuInfo->DisplayFamily, CpuInfo->DisplayModel) ||\r
199 IS_GOLDMONT_PLUS_PROCESSOR (CpuInfo->DisplayFamily, CpuInfo->DisplayModel)) {\r
200 if (CpuInfo->ProcessorInfo.Location.Thread != 0) {\r
201 return RETURN_SUCCESS;\r
202 }\r
203 }\r
204\r
bc230057 205 ProcTraceData = (PROC_TRACE_DATA *) ConfigData;\r
3dcb5325 206 ASSERT (ProcTraceData != NULL);\r
bc230057
ED
207\r
208 MemRegionBaseAddr = 0;\r
209 FirstIn = FALSE;\r
210\r
211 if (ProcTraceData->ThreadMemRegionTable == NULL) {\r
212 FirstIn = TRUE;\r
213 DEBUG ((DEBUG_INFO, "Initialize Processor Trace\n"));\r
214 }\r
215\r
216 ///\r
217 /// Refer to PROC_TRACE_MEM_SIZE Table for Size Encoding\r
218 ///\r
219 MemRegionSize = (UINT32) (1 << (ProcTraceData->ProcTraceMemSize + 12));\r
220 if (FirstIn) {\r
221 DEBUG ((DEBUG_INFO, "ProcTrace: MemSize requested: 0x%X \n", MemRegionSize));\r
222 }\r
223\r
224 //\r
225 // Clear MSR_IA32_RTIT_CTL[0] and IA32_RTIT_STS only if MSR_IA32_RTIT_CTL[0]==1b\r
226 //\r
b2b0ffc9
ED
227 CtrlReg.Uint64 = AsmReadMsr64 (MSR_IA32_RTIT_CTL);\r
228 if (CtrlReg.Bits.TraceEn != 0) {\r
bc230057
ED
229 ///\r
230 /// Clear bit 0 in MSR IA32_RTIT_CTL (570)\r
231 ///\r
b2b0ffc9 232 CtrlReg.Bits.TraceEn = 0;\r
bc230057
ED
233 CPU_REGISTER_TABLE_WRITE64 (\r
234 ProcessorNumber,\r
235 Msr,\r
236 MSR_IA32_RTIT_CTL,\r
b2b0ffc9 237 CtrlReg.Uint64\r
bc230057
ED
238 );\r
239\r
240 ///\r
241 /// Clear MSR IA32_RTIT_STS (571h) to all zeros\r
242 ///\r
b2b0ffc9 243 StatusReg.Uint64 = 0x0;\r
bc230057
ED
244 CPU_REGISTER_TABLE_WRITE64 (\r
245 ProcessorNumber,\r
246 Msr,\r
247 MSR_IA32_RTIT_STATUS,\r
b2b0ffc9 248 StatusReg.Uint64\r
bc230057
ED
249 );\r
250 }\r
251\r
252 if (FirstIn) {\r
253 //\r
254 // Let BSP allocate and create the necessary memory region (Aligned to the size of\r
255 // the memory region from setup option(ProcTraceMemSize) which is an integral multiple of 4kB)\r
256 // for the all the enabled threads for storing Processor Trace debug data. Then Configure the trace\r
257 // address base in MSR, IA32_RTIT_OUTPUT_BASE (560h) bits 47:12. Note that all regions must be\r
258 // aligned based on their size, not just 4K. Thus a 2M region must have bits 20:12 clear.\r
259 //\r
260 ThreadMemRegionTable = (UINTN *) AllocatePool (ProcTraceData->NumberOfProcessors * sizeof (UINTN *));\r
261 if (ThreadMemRegionTable == NULL) {\r
262 DEBUG ((DEBUG_ERROR, "Allocate ProcTrace ThreadMemRegionTable Failed\n"));\r
263 return RETURN_OUT_OF_RESOURCES;\r
264 }\r
265 ProcTraceData->ThreadMemRegionTable = ThreadMemRegionTable;\r
266\r
267 for (Index = 0; Index < ProcTraceData->NumberOfProcessors; Index++, ProcTraceData->AllocatedThreads++) {\r
268 Pages = EFI_SIZE_TO_PAGES (MemRegionSize);\r
269 Alignment = MemRegionSize;\r
270 AlignedAddress = (UINTN) AllocateAlignedReservedPages (Pages, Alignment);\r
271 if (AlignedAddress == 0) {\r
272 DEBUG ((DEBUG_ERROR, "ProcTrace: Out of mem, allocated only for %d threads\n", ProcTraceData->AllocatedThreads));\r
273 if (Index == 0) {\r
274 //\r
275 // Could not allocate for BSP even\r
276 //\r
277 FreePool ((VOID *) ThreadMemRegionTable);\r
278 ThreadMemRegionTable = NULL;\r
279 return RETURN_OUT_OF_RESOURCES;\r
280 }\r
281 break;\r
282 }\r
283\r
284 ThreadMemRegionTable[Index] = AlignedAddress;\r
285 DEBUG ((DEBUG_INFO, "ProcTrace: PT MemRegionBaseAddr(aligned) for thread %d: 0x%llX \n", Index, (UINT64) ThreadMemRegionTable[Index]));\r
286 }\r
287\r
288 DEBUG ((DEBUG_INFO, "ProcTrace: Allocated PT mem for %d thread \n", ProcTraceData->AllocatedThreads));\r
289 MemRegionBaseAddr = ThreadMemRegionTable[0];\r
290 } else {\r
291 if (ProcessorNumber < ProcTraceData->AllocatedThreads) {\r
292 MemRegionBaseAddr = ProcTraceData->ThreadMemRegionTable[ProcessorNumber];\r
293 } else {\r
294 return RETURN_SUCCESS;\r
295 }\r
296 }\r
297\r
298 ///\r
299 /// Check Processor Trace output scheme: Single Range output or ToPA table\r
300 ///\r
301\r
302 //\r
303 // Single Range output scheme\r
304 //\r
7367cc6c 305 if (ProcTraceData->ProcessorData[ProcessorNumber].SingleRangeSupported &&\r
330021fa 306 (ProcTraceData->ProcTraceOutputScheme == RtitOutputSchemeSingleRange)) {\r
bc230057
ED
307 if (FirstIn) {\r
308 DEBUG ((DEBUG_INFO, "ProcTrace: Enabling Single Range Output scheme \n"));\r
309 }\r
310\r
311 //\r
312 // Clear MSR IA32_RTIT_CTL (0x570) ToPA (Bit 8)\r
313 //\r
b2b0ffc9
ED
314 CtrlReg.Uint64 = AsmReadMsr64 (MSR_IA32_RTIT_CTL);\r
315 CtrlReg.Bits.ToPA = 0;\r
bc230057
ED
316 CPU_REGISTER_TABLE_WRITE64 (\r
317 ProcessorNumber,\r
318 Msr,\r
319 MSR_IA32_RTIT_CTL,\r
b2b0ffc9 320 CtrlReg.Uint64\r
bc230057
ED
321 );\r
322\r
323 //\r
b2b0ffc9 324 // Program MSR IA32_RTIT_OUTPUT_BASE (0x560) bits[63:7] with the allocated Memory Region\r
bc230057 325 //\r
b2b0ffc9
ED
326 OutputBaseReg.Bits.Base = (MemRegionBaseAddr >> 7) & 0x01FFFFFF;\r
327 OutputBaseReg.Bits.BaseHi = RShiftU64 ((UINT64) MemRegionBaseAddr, 32) & 0xFFFFFFFF;\r
bc230057
ED
328 CPU_REGISTER_TABLE_WRITE64 (\r
329 ProcessorNumber,\r
330 Msr,\r
331 MSR_IA32_RTIT_OUTPUT_BASE,\r
b2b0ffc9 332 OutputBaseReg.Uint64\r
bc230057
ED
333 );\r
334\r
335 //\r
336 // Program the Mask bits for the Memory Region to MSR IA32_RTIT_OUTPUT_MASK_PTRS (561h)\r
337 //\r
b2b0ffc9 338 OutputMaskPtrsReg.Bits.MaskOrTableOffset = ((MemRegionSize - 1) >> 7) & 0x01FFFFFF;\r
821f24b1 339 OutputMaskPtrsReg.Bits.OutputOffset = RShiftU64 (MemRegionSize - 1, 32) & 0xFFFFFFFF;\r
bc230057
ED
340 CPU_REGISTER_TABLE_WRITE64 (\r
341 ProcessorNumber,\r
342 Msr,\r
343 MSR_IA32_RTIT_OUTPUT_MASK_PTRS,\r
b2b0ffc9 344 OutputMaskPtrsReg.Uint64\r
bc230057 345 );\r
bc230057
ED
346 }\r
347\r
348 //\r
349 // ToPA(Table of physical address) scheme\r
350 //\r
7367cc6c 351 if (ProcTraceData->ProcessorData[ProcessorNumber].TopaSupported &&\r
330021fa 352 (ProcTraceData->ProcTraceOutputScheme == RtitOutputSchemeToPA)) {\r
bc230057
ED
353 //\r
354 // Create ToPA structure aligned at 4KB for each logical thread\r
355 // with at least 2 entries by 8 bytes size each. The first entry\r
356 // should have the trace output base address in bits 47:12, 6:9\r
357 // for Size, bits 4,2 and 0 must be cleared. The second entry\r
358 // should have the base address of the table location in bits\r
359 // 47:12, bits 4 and 2 must be cleared and bit 0 must be set.\r
360 //\r
361 if (FirstIn) {\r
362 DEBUG ((DEBUG_INFO, "ProcTrace: Enabling ToPA scheme \n"));\r
363 //\r
364 // Let BSP allocate ToPA table mem for all threads\r
365 //\r
366 TopaMemArray = (UINTN *) AllocatePool (ProcTraceData->AllocatedThreads * sizeof (UINTN *));\r
367 if (TopaMemArray == NULL) {\r
368 DEBUG ((DEBUG_ERROR, "ProcTrace: Allocate mem for ToPA Failed\n"));\r
369 return RETURN_OUT_OF_RESOURCES;\r
370 }\r
371 ProcTraceData->TopaMemArray = TopaMemArray;\r
372\r
373 for (Index = 0; Index < ProcTraceData->AllocatedThreads; Index++) {\r
374 Pages = EFI_SIZE_TO_PAGES (sizeof (PROC_TRACE_TOPA_TABLE));\r
375 Alignment = 0x1000;\r
376 AlignedAddress = (UINTN) AllocateAlignedReservedPages (Pages, Alignment);\r
377 if (AlignedAddress == 0) {\r
378 if (Index < ProcTraceData->AllocatedThreads) {\r
379 ProcTraceData->AllocatedThreads = Index;\r
380 }\r
381 DEBUG ((DEBUG_ERROR, "ProcTrace: Out of mem, allocating ToPA mem only for %d threads\n", ProcTraceData->AllocatedThreads));\r
382 if (Index == 0) {\r
383 //\r
384 // Could not allocate for BSP\r
385 //\r
386 FreePool ((VOID *) TopaMemArray);\r
387 TopaMemArray = NULL;\r
388 return RETURN_OUT_OF_RESOURCES;\r
389 }\r
390 break;\r
391 }\r
392\r
393 TopaMemArray[Index] = AlignedAddress;\r
394 DEBUG ((DEBUG_INFO, "ProcTrace: Topa table address(aligned) for thread %d is 0x%llX \n", Index, (UINT64) TopaMemArray[Index]));\r
395 }\r
396\r
397 DEBUG ((DEBUG_INFO, "ProcTrace: Allocated ToPA mem for %d thread \n", ProcTraceData->AllocatedThreads));\r
398 //\r
399 // BSP gets the first block\r
400 //\r
401 TopaTableBaseAddr = TopaMemArray[0];\r
402 } else {\r
403 //\r
404 // Count for currently executing AP.\r
405 //\r
406 if (ProcessorNumber < ProcTraceData->AllocatedThreads) {\r
407 TopaTableBaseAddr = ProcTraceData->TopaMemArray[ProcessorNumber];\r
408 } else {\r
409 return RETURN_SUCCESS;\r
410 }\r
411 }\r
412\r
413 TopaTable = (PROC_TRACE_TOPA_TABLE *) TopaTableBaseAddr;\r
b2b0ffc9
ED
414 TopaEntryPtr = &TopaTable->TopaEntry[0];\r
415 TopaEntryPtr->Bits.Base = (MemRegionBaseAddr >> 12) & 0x000FFFFF;\r
416 TopaEntryPtr->Bits.BaseHi = RShiftU64 ((UINT64) MemRegionBaseAddr, 32) & 0xFFFFFFFF;\r
417 TopaEntryPtr->Bits.Size = ProcTraceData->ProcTraceMemSize;\r
418 TopaEntryPtr->Bits.END = 0;\r
419\r
420 TopaEntryPtr = &TopaTable->TopaEntry[1];\r
421 TopaEntryPtr->Bits.Base = (TopaTableBaseAddr >> 12) & 0x000FFFFF;\r
422 TopaEntryPtr->Bits.BaseHi = RShiftU64 ((UINT64) TopaTableBaseAddr, 32) & 0xFFFFFFFF;\r
423 TopaEntryPtr->Bits.END = 1;\r
bc230057
ED
424\r
425 //\r
b2b0ffc9 426 // Program the MSR IA32_RTIT_OUTPUT_BASE (0x560) bits[63:7] with ToPA base\r
bc230057 427 //\r
b2b0ffc9
ED
428 OutputBaseReg.Bits.Base = (TopaTableBaseAddr >> 7) & 0x01FFFFFF;\r
429 OutputBaseReg.Bits.BaseHi = RShiftU64 ((UINT64) TopaTableBaseAddr, 32) & 0xFFFFFFFF;\r
bc230057
ED
430 CPU_REGISTER_TABLE_WRITE64 (\r
431 ProcessorNumber,\r
432 Msr,\r
433 MSR_IA32_RTIT_OUTPUT_BASE,\r
b2b0ffc9 434 OutputBaseReg.Uint64\r
bc230057
ED
435 );\r
436\r
437 //\r
438 // Set the MSR IA32_RTIT_OUTPUT_MASK (0x561) bits[63:7] to 0\r
439 //\r
b2b0ffc9
ED
440 OutputMaskPtrsReg.Bits.MaskOrTableOffset = 0;\r
441 OutputMaskPtrsReg.Bits.OutputOffset = 0;\r
bc230057
ED
442 CPU_REGISTER_TABLE_WRITE64 (\r
443 ProcessorNumber,\r
444 Msr,\r
445 MSR_IA32_RTIT_OUTPUT_MASK_PTRS,\r
b2b0ffc9 446 OutputMaskPtrsReg.Uint64\r
bc230057
ED
447 );\r
448 //\r
449 // Enable ToPA output scheme by enabling MSR IA32_RTIT_CTL (0x570) ToPA (Bit 8)\r
450 //\r
b2b0ffc9
ED
451 CtrlReg.Uint64 = AsmReadMsr64 (MSR_IA32_RTIT_CTL);\r
452 CtrlReg.Bits.ToPA = 1;\r
bc230057
ED
453 CPU_REGISTER_TABLE_WRITE64 (\r
454 ProcessorNumber,\r
455 Msr,\r
456 MSR_IA32_RTIT_CTL,\r
b2b0ffc9 457 CtrlReg.Uint64\r
bc230057
ED
458 );\r
459 }\r
460\r
461 ///\r
462 /// Enable the Processor Trace feature from MSR IA32_RTIT_CTL (570h)\r
463 ///\r
b2b0ffc9
ED
464 CtrlReg.Uint64 = AsmReadMsr64 (MSR_IA32_RTIT_CTL);\r
465 CtrlReg.Bits.OS = 1;\r
466 CtrlReg.Bits.User = 1;\r
467 CtrlReg.Bits.BranchEn = 1;\r
bc230057 468 if (!State) {\r
b2b0ffc9
ED
469 CtrlReg.Bits.TraceEn = 0;\r
470 } else {\r
471 CtrlReg.Bits.TraceEn = 1;\r
bc230057
ED
472 }\r
473 CPU_REGISTER_TABLE_WRITE64 (\r
474 ProcessorNumber,\r
475 Msr,\r
476 MSR_IA32_RTIT_CTL,\r
b2b0ffc9 477 CtrlReg.Uint64\r
bc230057
ED
478 );\r
479\r
480 return RETURN_SUCCESS;\r
481}\r