UefiCpuPkg CpuCommFeaturesLib: Fix GP fault issue about ProcTrace
authorStar Zeng <star.zeng@intel.com>
Sat, 25 May 2019 07:39:23 +0000 (15:39 +0800)
committerStar Zeng <star.zeng@intel.com>
Thu, 6 Jun 2019 10:51:45 +0000 (18:51 +0800)
BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=1808

In current code, the values of TopaEntryPtr->Uint64 for TopaTable
and the values of OutputBaseReg.Uint64 and OutputMaskPtrsReg.Uint64
to register table write for RTIT_OUTPUT_BASE and RTIT_OUTPUT_MASK_PTRS
are not been initialized in whole. For example, the reserved bits in
OutputBaseReg.Uint64 are random that will cause GP fault like below
when SetProcessorRegister (in CpuFeaturesInitialize.c) sets register
based on register table.

!!!! X64 Exception Type - 0D(#GP - General Protection)
  CPU Apic ID - 00000000 !!!!
ExceptionData - 0000000000000000
RIP  -0000000064D69576, CS  -0000000000000038, RFLAGS -0000000000010246
RAX  -000000006B9F1001, RCX -0000000000000560, RDX -0000000000000000
RBX  -0000000064EECA18, RSP -000000006CB82BA0, RBP -0000000000000008
RSI  -0000000080000000, RDI -0000000000000011
R8   -000000006B9493D0, R9  -0000000000000010, R10 -00000000000000FF
R11  -000000006CB82A50, R12 -0000000064D70F50, R13 -0000000066547050
R14  -0000000064E3E198, R15 -0000000000000000
DS   -0000000000000030, ES  -0000000000000030, FS  -0000000000000030
GS   -0000000000000030, SS  -0000000000000030
CR0  -0000000080010013, CR2 -0000000000000000, CR3 -000000006C601000
CR4  -0000000000000628, CR8 -0000000000000000
DR0  -0000000000000000, DR1 -0000000000000000, DR2 -0000000000000000
DR3  -0000000000000000, DR6 -00000000FFFF0FF0, DR7 -0000000000000400
GDTR -000000006B8CCF18 0000000000000047, LDTR -0000000000000000
IDTR -000000006687E018 0000000000000FFF,   TR -0000000000000000
FXSAVE_STATE -000000006CB82800

And current code gets MSR_IA32_RTIT_CTL, MSR_IA32_RTIT_OUTPUT_BASE and
MSR_IA32_RTIT_OUTPUT_MASK_PTRS in ProcTraceInitialize() and uses their
values for all processors. But ProcTraceInitialize() is only executed
by BSP, that means the values just for BSP. For good practice, the code
should get MSR_IA32_RTIT_CTL, MSR_IA32_RTIT_OUTPUT_BASE and
MSR_IA32_RTIT_OUTPUT_MASK_PTRS in ProcTraceSupport (executed by all
processors), and then use them in ProcTraceInitialize() for all
processors. This can also resolve the issue that the values of
OutputBaseReg.Uint64 and OutputMaskPtrsReg.Uint64 are not been
initialized in whole.

For TopaEntryPtr->Uint64, this patch updates code to initialize it
in whole explicitly by TopaEntryPtr->Uint64 = 0 before updating its
fields.

At the same time, this patch also eliminates the ProcTraceSupported
field in PROC_TRACE_PROCESSOR_DATA and the TopaMemArrayCount field in
PROC_TRACE_DATA.

Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Eric Dong <eric.dong@intel.com>
Cc: Ruiyu Ni <ruiyu.ni@intel.com>
Cc: Chandana Kumar <chandana.c.kumar@intel.com>
Cc: Kevin Li <kevin.y.li@intel.com>
Signed-off-by: Star Zeng <star.zeng@intel.com>
Reviewed-by: Eric Dong <eric.dong@intel.com>
UefiCpuPkg/Library/CpuCommonFeaturesLib/ProcTrace.c

index b98eb11..6114591 100644 (file)
@@ -29,9 +29,11 @@ typedef enum {
 } RTIT_OUTPUT_SCHEME;\r
 \r
 typedef struct  {\r
-  BOOLEAN  ProcTraceSupported;\r
-  BOOLEAN  TopaSupported;\r
-  BOOLEAN  SingleRangeSupported;\r
+  BOOLEAN                                   TopaSupported;\r
+  BOOLEAN                                   SingleRangeSupported;\r
+  MSR_IA32_RTIT_CTL_REGISTER                RtitCtrl;\r
+  MSR_IA32_RTIT_OUTPUT_BASE_REGISTER        RtitOutputBase;\r
+  MSR_IA32_RTIT_OUTPUT_MASK_PTRS_REGISTER   RtitOutputMaskPtrs;\r
 } PROC_TRACE_PROCESSOR_DATA;\r
 \r
 typedef struct  {\r
@@ -44,7 +46,6 @@ typedef struct  {
   UINTN                       AllocatedThreads;\r
 \r
   UINTN                       *TopaMemArray;\r
-  UINTN                       TopaMemArrayCount;\r
 \r
   PROC_TRACE_PROCESSOR_DATA   *ProcessorData;\r
 } PROC_TRACE_DATA;\r
@@ -124,8 +125,7 @@ ProcTraceSupport (
   // Check if Processor Trace is supported\r
   //\r
   AsmCpuidEx (CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS, 0, NULL, &Ebx.Uint32, NULL, NULL);\r
-  ProcTraceData->ProcessorData[ProcessorNumber].ProcTraceSupported = (BOOLEAN) (Ebx.Bits.IntelProcessorTrace == 1);\r
-  if (!ProcTraceData->ProcessorData[ProcessorNumber].ProcTraceSupported) {\r
+  if (Ebx.Bits.IntelProcessorTrace == 0) {\r
     return FALSE;\r
   }\r
 \r
@@ -134,6 +134,9 @@ ProcTraceSupport (
   ProcTraceData->ProcessorData[ProcessorNumber].SingleRangeSupported = (BOOLEAN) (Ecx.Bits.SingleRangeOutput == 1);\r
   if ((ProcTraceData->ProcessorData[ProcessorNumber].TopaSupported && (ProcTraceData->ProcTraceOutputScheme == RtitOutputSchemeToPA)) ||\r
       (ProcTraceData->ProcessorData[ProcessorNumber].SingleRangeSupported && (ProcTraceData->ProcTraceOutputScheme == RtitOutputSchemeSingleRange))) {\r
+    ProcTraceData->ProcessorData[ProcessorNumber].RtitCtrl.Uint64 = AsmReadMsr64 (MSR_IA32_RTIT_CTL);\r
+    ProcTraceData->ProcessorData[ProcessorNumber].RtitOutputBase.Uint64 = AsmReadMsr64 (MSR_IA32_RTIT_OUTPUT_BASE);\r
+    ProcTraceData->ProcessorData[ProcessorNumber].RtitOutputMaskPtrs.Uint64 = AsmReadMsr64 (MSR_IA32_RTIT_OUTPUT_MASK_PTRS);\r
     return TRUE;\r
   }\r
 \r
@@ -202,7 +205,7 @@ ProcTraceInitialize (
   //\r
   // Clear MSR_IA32_RTIT_CTL[0] and IA32_RTIT_STS only if MSR_IA32_RTIT_CTL[0]==1b\r
   //\r
-  CtrlReg.Uint64 = AsmReadMsr64 (MSR_IA32_RTIT_CTL);\r
+  CtrlReg.Uint64 = ProcTraceData->ProcessorData[ProcessorNumber].RtitCtrl.Uint64;\r
   if (CtrlReg.Bits.TraceEn != 0) {\r
     ///\r
     /// Clear bit 0 in MSR IA32_RTIT_CTL (570)\r
@@ -251,9 +254,9 @@ ProcTraceInitialize (
     //\r
     //   Let BSP allocate and create the necessary memory region (Aligned to the size of\r
     //   the memory region from setup option(ProcTraceMemSize) which is an integral multiple of 4kB)\r
-    //   for the all the enabled threads for storing Processor Trace debug data. Then Configure the trace\r
+    //   for all the enabled threads to store Processor Trace debug data. Then Configure the trace\r
     //   address base in MSR, IA32_RTIT_OUTPUT_BASE (560h) bits 47:12. Note that all regions must be\r
-    //   aligned based on their size, not just 4K. Thus a 2M region must have bits 20:12 clear.\r
+    //   aligned based on their size, not just 4K. Thus a 2M region must have bits 20:12 cleared.\r
     //\r
     ThreadMemRegionTable = (UINTN *) AllocatePool (ProcTraceData->NumberOfProcessors * sizeof (UINTN *));\r
     if (ThreadMemRegionTable == NULL) {\r
@@ -284,13 +287,12 @@ ProcTraceInitialize (
     }\r
 \r
     DEBUG ((DEBUG_INFO, "ProcTrace: Allocated PT mem for %d thread \n", ProcTraceData->AllocatedThreads));\r
-    MemRegionBaseAddr = ThreadMemRegionTable[0];\r
+  }\r
+\r
+  if (ProcessorNumber < ProcTraceData->AllocatedThreads) {\r
+    MemRegionBaseAddr = ProcTraceData->ThreadMemRegionTable[ProcessorNumber];\r
   } else {\r
-    if (ProcessorNumber < ProcTraceData->AllocatedThreads) {\r
-      MemRegionBaseAddr = ProcTraceData->ThreadMemRegionTable[ProcessorNumber];\r
-    } else {\r
-      return RETURN_SUCCESS;\r
-    }\r
+    return RETURN_SUCCESS;\r
   }\r
 \r
   ///\r
@@ -309,7 +311,6 @@ ProcTraceInitialize (
     //\r
     // Clear MSR IA32_RTIT_CTL (0x570) ToPA (Bit 8)\r
     //\r
-    CtrlReg.Uint64 = AsmReadMsr64 (MSR_IA32_RTIT_CTL);\r
     CtrlReg.Bits.ToPA = 0;\r
     CPU_REGISTER_TABLE_WRITE64 (\r
       ProcessorNumber,\r
@@ -321,6 +322,7 @@ ProcTraceInitialize (
     //\r
     // Program MSR IA32_RTIT_OUTPUT_BASE (0x560) bits[63:7] with the allocated Memory Region\r
     //\r
+    OutputBaseReg.Uint64 = ProcTraceData->ProcessorData[ProcessorNumber].RtitOutputBase.Uint64;\r
     OutputBaseReg.Bits.Base = (MemRegionBaseAddr >> 7) & 0x01FFFFFF;\r
     OutputBaseReg.Bits.BaseHi = RShiftU64 ((UINT64) MemRegionBaseAddr, 32) & 0xFFFFFFFF;\r
     CPU_REGISTER_TABLE_WRITE64 (\r
@@ -333,6 +335,7 @@ ProcTraceInitialize (
     //\r
     // Program the Mask bits for the Memory Region to MSR IA32_RTIT_OUTPUT_MASK_PTRS (561h)\r
     //\r
+    OutputMaskPtrsReg.Uint64 = ProcTraceData->ProcessorData[ProcessorNumber].RtitOutputMaskPtrs.Uint64;\r
     OutputMaskPtrsReg.Bits.MaskOrTableOffset = ((MemRegionSize - 1) >> 7) & 0x01FFFFFF;\r
     OutputMaskPtrsReg.Bits.OutputOffset = RShiftU64 (MemRegionSize - 1, 32) & 0xFFFFFFFF;\r
     CPU_REGISTER_TABLE_WRITE64 (\r
@@ -376,10 +379,10 @@ ProcTraceInitialize (
           if (Index < ProcTraceData->AllocatedThreads) {\r
             ProcTraceData->AllocatedThreads = Index;\r
           }\r
-          DEBUG ((DEBUG_ERROR, "ProcTrace:  Out of mem, allocating ToPA mem only for %d threads\n", ProcTraceData->AllocatedThreads));\r
+          DEBUG ((DEBUG_ERROR, "ProcTrace:  Out of mem, allocated ToPA mem only for %d threads\n", ProcTraceData->AllocatedThreads));\r
           if (Index == 0) {\r
             //\r
-            // Could not allocate for BSP\r
+            // Could not allocate for BSP even\r
             //\r
             FreePool ((VOID *) TopaMemArray);\r
             TopaMemArray = NULL;\r
@@ -393,29 +396,24 @@ ProcTraceInitialize (
       }\r
 \r
       DEBUG ((DEBUG_INFO, "ProcTrace: Allocated ToPA mem for %d thread \n", ProcTraceData->AllocatedThreads));\r
-      //\r
-      // BSP gets the first block\r
-      //\r
-      TopaTableBaseAddr = TopaMemArray[0];\r
+    }\r
+\r
+    if (ProcessorNumber < ProcTraceData->AllocatedThreads) {\r
+      TopaTableBaseAddr = ProcTraceData->TopaMemArray[ProcessorNumber];\r
     } else {\r
-      //\r
-      // Count for currently executing AP.\r
-      //\r
-      if (ProcessorNumber < ProcTraceData->AllocatedThreads) {\r
-        TopaTableBaseAddr = ProcTraceData->TopaMemArray[ProcessorNumber];\r
-      } else {\r
-        return RETURN_SUCCESS;\r
-      }\r
+      return RETURN_SUCCESS;\r
     }\r
 \r
     TopaTable = (PROC_TRACE_TOPA_TABLE *) TopaTableBaseAddr;\r
     TopaEntryPtr = &TopaTable->TopaEntry[0];\r
+    TopaEntryPtr->Uint64 = 0;\r
     TopaEntryPtr->Bits.Base = (MemRegionBaseAddr >> 12) & 0x000FFFFF;\r
     TopaEntryPtr->Bits.BaseHi = RShiftU64 ((UINT64) MemRegionBaseAddr, 32) & 0xFFFFFFFF;\r
     TopaEntryPtr->Bits.Size = ProcTraceData->ProcTraceMemSize;\r
     TopaEntryPtr->Bits.END = 0;\r
 \r
     TopaEntryPtr = &TopaTable->TopaEntry[1];\r
+    TopaEntryPtr->Uint64 = 0;\r
     TopaEntryPtr->Bits.Base = (TopaTableBaseAddr >> 12) & 0x000FFFFF;\r
     TopaEntryPtr->Bits.BaseHi = RShiftU64 ((UINT64) TopaTableBaseAddr, 32) & 0xFFFFFFFF;\r
     TopaEntryPtr->Bits.END = 1;\r
@@ -423,6 +421,7 @@ ProcTraceInitialize (
     //\r
     // Program the MSR IA32_RTIT_OUTPUT_BASE (0x560) bits[63:7] with ToPA base\r
     //\r
+    OutputBaseReg.Uint64 = ProcTraceData->ProcessorData[ProcessorNumber].RtitOutputBase.Uint64;\r
     OutputBaseReg.Bits.Base = (TopaTableBaseAddr >> 7) & 0x01FFFFFF;\r
     OutputBaseReg.Bits.BaseHi = RShiftU64 ((UINT64) TopaTableBaseAddr, 32) & 0xFFFFFFFF;\r
     CPU_REGISTER_TABLE_WRITE64 (\r
@@ -435,6 +434,7 @@ ProcTraceInitialize (
     //\r
     // Set the MSR IA32_RTIT_OUTPUT_MASK (0x561) bits[63:7] to 0\r
     //\r
+    OutputMaskPtrsReg.Uint64 = ProcTraceData->ProcessorData[ProcessorNumber].RtitOutputMaskPtrs.Uint64;\r
     OutputMaskPtrsReg.Bits.MaskOrTableOffset = 0;\r
     OutputMaskPtrsReg.Bits.OutputOffset = 0;\r
     CPU_REGISTER_TABLE_WRITE64 (\r
@@ -446,7 +446,6 @@ ProcTraceInitialize (
     //\r
     // Enable ToPA output scheme by enabling MSR IA32_RTIT_CTL (0x570) ToPA (Bit 8)\r
     //\r
-    CtrlReg.Uint64 = AsmReadMsr64 (MSR_IA32_RTIT_CTL);\r
     CtrlReg.Bits.ToPA = 1;\r
     CPU_REGISTER_TABLE_WRITE64 (\r
       ProcessorNumber,\r
@@ -459,7 +458,6 @@ ProcTraceInitialize (
   ///\r
   /// Enable the Processor Trace feature from MSR IA32_RTIT_CTL (570h)\r
   ///\r
-  CtrlReg.Uint64 = AsmReadMsr64 (MSR_IA32_RTIT_CTL);\r
   CtrlReg.Bits.OS = 1;\r
   CtrlReg.Bits.User = 1;\r
   CtrlReg.Bits.BranchEn = 1;\r