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