]> git.proxmox.com Git - mirror_edk2.git/blobdiff - SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/DebugMp.c
Import SourceLevelDebugPkg.
[mirror_edk2.git] / SourceLevelDebugPkg / Library / DebugAgent / DebugAgentCommon / DebugMp.c
diff --git a/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/DebugMp.c b/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/DebugMp.c
new file mode 100644 (file)
index 0000000..7d053fa
--- /dev/null
@@ -0,0 +1,365 @@
+/** @file\r
+  Multi-Processor support functions implementation.\r
+\r
+  Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>\r
+  This program and the accompanying materials\r
+  are licensed and made available under the terms and conditions of the BSD License\r
+  which accompanies this distribution.  The full text of the license may be found at\r
+  http://opensource.org/licenses/bsd-license.php.\r
+\r
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "DebugAgent.h"\r
+\r
+DEBUG_MP_CONTEXT volatile  mDebugMpContext = {0,0,0,0,0,0,0,0,FALSE,FALSE};\r
+\r
+DEBUG_CPU_DATA volatile  mDebugCpuData = {0};\r
+\r
+/**\r
+  Acquire access control on debug port.\r
+\r
+  It will block in the function if cannot get the access control.\r
+\r
+**/\r
+VOID\r
+AcquireDebugPortControl (\r
+  VOID\r
+  )\r
+{\r
+  if (!MultiProcessorDebugSupport) {\r
+    return;\r
+  }\r
+\r
+  while (TRUE) {\r
+    if (AcquireSpinLockOrFail (&mDebugMpContext.DebugPortSpinLock)) {\r
+      break;\r
+    }\r
+    CpuPause ();\r
+    continue;\r
+  }\r
+}\r
+\r
+/**\r
+  Release access control on debug port.\r
+\r
+**/\r
+VOID\r
+ReleaseDebugPortControl (\r
+  VOID\r
+  )\r
+{\r
+  if (!MultiProcessorDebugSupport) {\r
+    return;\r
+  }\r
+\r
+  ReleaseSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
+}\r
+\r
+/**\r
+  Acquire access control on MP context.\r
+\r
+  It will block in the function if cannot get the access control.\r
+\r
+**/\r
+VOID\r
+AcquireMpContextControl (\r
+  VOID\r
+  )\r
+{\r
+  while (TRUE) {\r
+    if (AcquireSpinLockOrFail (&mDebugMpContext.MpContextSpinLock)) {\r
+      break;\r
+    }\r
+    CpuPause ();\r
+    continue;\r
+  }\r
+}\r
+\r
+/**\r
+  Release access control on MP context.\r
+\r
+**/\r
+VOID\r
+ReleaseMpContextControl (\r
+  VOID\r
+  )\r
+{\r
+  ReleaseSpinLock (&mDebugMpContext.MpContextSpinLock);\r
+}\r
+\r
+/**\r
+  Break the other processor by send IPI.\r
+\r
+  @param[in] CurrentProcessorIndex  Current processor index value.\r
+\r
+**/\r
+VOID\r
+HaltOtherProcessors (\r
+  IN UINT32             CurrentProcessorIndex\r
+  )\r
+{\r
+\r
+  if (!IsBsp (CurrentProcessorIndex)) {\r
+    SetIpiSentByApFlag (TRUE);;\r
+  }\r
+\r
+  mDebugMpContext.BreakAtCpuIndex = CurrentProcessorIndex;\r
+\r
+  //\r
+  // Send fixed IPI to other processors.\r
+  //\r
+  SendFixedIpiAllExcludingSelf (DEBUG_TIMER_VECTOR);\r
+  \r
+}\r
+\r
+/**\r
+  Get the current processor's index.\r
+\r
+  @return Processor index value.\r
+\r
+**/\r
+UINT32\r
+GetProcessorIndex (\r
+  VOID\r
+  )\r
+{\r
+  UINT32                Index;\r
+  UINT16                LocalApicID;\r
+\r
+  LocalApicID = (UINT16) GetApicId ();\r
+\r
+  AcquireMpContextControl ();\r
+\r
+  for (Index = 0; Index < mDebugCpuData.CpuCount; Index ++) {\r
+    if (mDebugCpuData.ApicID[Index] == LocalApicID) {\r
+      break;\r
+    }\r
+  }\r
+\r
+  if (Index == mDebugCpuData.CpuCount) {\r
+    mDebugCpuData.ApicID[Index] = LocalApicID;\r
+    mDebugCpuData.CpuCount ++ ;\r
+  }\r
+\r
+  ReleaseMpContextControl ();\r
+\r
+  return Index;\r
+}\r
+\r
+/**\r
+  Check if the specified processor is BSP or not.\r
+\r
+  @param[in] ProcessorIndex Processor index value.\r
+\r
+  @retval TRUE    It is BSP.\r
+  @retval FALSE   It isn't BSP.\r
+\r
+**/\r
+BOOLEAN\r
+IsBsp (\r
+  IN UINT32             ProcessorIndex\r
+  )\r
+{\r
+  if (AsmMsrBitFieldRead64 (MSR_IA32_APIC_BASE_ADDRESS, 8, 8) == 1) {\r
+    if (mDebugMpContext.BspIndex != ProcessorIndex) {\r
+      AcquireMpContextControl ();\r
+      mDebugMpContext.BspIndex = ProcessorIndex;\r
+      ReleaseMpContextControl ();\r
+    }\r
+    return TRUE;\r
+  } else {\r
+    return FALSE;\r
+  }\r
+}\r
+\r
+/**\r
+  Set processor stop flag bitmask in MP context.\r
+\r
+  @param[in] ProcessorIndex Processor index value.\r
+  @param[in] StopFlag       TRUE means set stop flag.\r
+                            FALSE means clean break flag.\r
+\r
+**/\r
+VOID\r
+SetCpuStopFlagByIndex (\r
+  IN UINT32             ProcessorIndex,\r
+  IN BOOLEAN            StopFlag\r
+  )\r
+{\r
+  UINT8                 Value;\r
+  UINTN                 Index;\r
+\r
+  AcquireMpContextControl ();\r
+\r
+  Value = mDebugMpContext.CpuStopStatusMask[ProcessorIndex / 8];\r
+  Index = ProcessorIndex % 8;\r
+  if (StopFlag) {\r
+    Value = BitFieldWrite8 (Value, Index, Index, 1);\r
+  } else {\r
+    Value = BitFieldWrite8 (Value, Index, Index, 0);\r
+  }\r
+  mDebugMpContext.CpuStopStatusMask[ProcessorIndex / 8] = Value;\r
+\r
+  ReleaseMpContextControl ();\r
+}\r
+\r
+/**\r
+  Set processor break flag bitmask in MP context.\r
+\r
+  @param[in] ProcessorIndex Processor index value.\r
+  @param[in] BreakFlag      TRUE means set break flag.\r
+                            FALSE means clean break flag.\r
+\r
+**/\r
+VOID\r
+SetCpuBreakFlagByIndex (\r
+  IN UINT32             ProcessorIndex,\r
+  IN BOOLEAN            BreakFlag\r
+  )\r
+{\r
+  UINT8                 Value;\r
+  UINTN                 Index;\r
+\r
+  AcquireMpContextControl ();\r
+\r
+  Value = mDebugMpContext.CpuBreakMask[ProcessorIndex / 8];\r
+  Index = ProcessorIndex % 8;\r
+  if (BreakFlag) {\r
+    Value = BitFieldWrite8 (Value, Index, Index, 1);\r
+  } else {\r
+    Value = BitFieldWrite8 (Value, Index, Index, 0);\r
+  }\r
+  mDebugMpContext.CpuBreakMask[ProcessorIndex / 8] = Value;\r
+\r
+  ReleaseMpContextControl ();\r
+}\r
+\r
+/**\r
+  Check if processor is stopped already.\r
+\r
+  @param[in] ProcessorIndex   Processor index value.\r
+\r
+  @retval TRUE        Processor is stopped already.\r
+  @retval TRUE        Processor isn't stopped.\r
+\r
+**/\r
+BOOLEAN\r
+IsCpuStopped (\r
+  IN UINT32              ProcessorIndex\r
+  )\r
+{\r
+  UINT8                 CpuMask;\r
+\r
+  CpuMask = (UINT8) (1 << (ProcessorIndex % 8));\r
+\r
+  if ((mDebugMpContext.CpuStopStatusMask[ProcessorIndex / 8] & CpuMask) != 0) {\r
+    return TRUE;\r
+  } else {\r
+    return FALSE;\r
+  }\r
+}\r
+\r
+/**\r
+  Set the run command flag.\r
+\r
+  @param[in] RunningFlag   TRUE means run command flag is set.\r
+                           FALSE means run command flag is cleared.\r
+\r
+**/\r
+VOID\r
+SetCpuRunningFlag (\r
+  IN BOOLEAN            RunningFlag\r
+  )\r
+{\r
+  AcquireMpContextControl ();\r
+\r
+  mDebugMpContext.RunCommandSet = RunningFlag;\r
+\r
+  ReleaseMpContextControl ();\r
+}\r
+\r
+/**\r
+  Set the current view point to be debugged.\r
+\r
+  @param[in] ProcessorIndex   Processor index value.\r
+\r
+**/\r
+VOID\r
+SetDebugViewPoint (\r
+  IN UINT32             ProcessorIndex\r
+  )\r
+{\r
+  AcquireMpContextControl ();\r
+\r
+  mDebugMpContext.ViewPointIndex = ProcessorIndex;\r
+\r
+  ReleaseMpContextControl ();\r
+}\r
+\r
+/**\r
+  Initialize debug timer.\r
+\r
+  @param[in] IpiSentByApFlag   TRUE means this IPI is sent by AP.\r
+                               FALSE means this IPI is sent by BSP.\r
+\r
+**/\r
+VOID\r
+SetIpiSentByApFlag (\r
+  IN BOOLEAN            IpiSentByApFlag\r
+  )\r
+{\r
+  AcquireMpContextControl ();\r
+\r
+  mDebugMpContext.IpiSentByAp = IpiSentByApFlag;\r
+\r
+  ReleaseMpContextControl ();\r
+}\r
+\r
+/**\r
+  Check if any processor breaks.\r
+\r
+  @retval others      There is at least one processor broken, the minimum\r
+                      index number of Processor returned.\r
+  @retval -1          No any processor broken.\r
+\r
+**/\r
+UINT32\r
+FindCpuNotRunning (\r
+  VOID\r
+  )\r
+{\r
+  UINT32               Index;\r
+  \r
+  for (Index = 0; Index < DEBUG_CPU_MAX_COUNT / 8; Index ++) {\r
+    if (mDebugMpContext.CpuBreakMask[Index] != 0) {\r
+      return  (UINT32) LowBitSet32 (mDebugMpContext.CpuBreakMask[Index]) + Index * 8;\r
+    }\r
+  }\r
+  return (UINT32)-1;\r
+}\r
+  \r
+/**\r
+  Check if all processors are in running status.\r
+\r
+  @retval TRUE        All processors run.\r
+  @retval FALSE       At least one processor does not run.\r
+\r
+**/\r
+BOOLEAN\r
+IsAllCpuRunning (\r
+  VOID\r
+  )\r
+{\r
+  UINTN              Index;\r
+  \r
+  for (Index = 0; Index < DEBUG_CPU_MAX_COUNT / 8; Index ++) {\r
+    if (mDebugMpContext.CpuStopStatusMask[Index] != 0) {\r
+      return FALSE;\r
+    }\r
+  }\r
+  return TRUE;\r
+}\r
+\r