--- /dev/null
+/** @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