REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3737 Apply uncrustify changes to .c/.h files in the SourceLevelDebugPkg package Cc: Andrew Fish <afish@apple.com> Cc: Leif Lindholm <leif@nuviainc.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com> Reviewed-by: Hao A Wu <hao.a.wu@intel.com> Reviewed-by: Ray Ni <ray.ni@intel.com>
		
			
				
	
	
		
			383 lines
		
	
	
		
			8.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			383 lines
		
	
	
		
			8.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @file
 | 
						|
  Multi-Processor support functions implementation.
 | 
						|
 | 
						|
  Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.<BR>
 | 
						|
  SPDX-License-Identifier: BSD-2-Clause-Patent
 | 
						|
 | 
						|
**/
 | 
						|
 | 
						|
#include "DebugAgent.h"
 | 
						|
 | 
						|
GLOBAL_REMOVE_IF_UNREFERENCED DEBUG_MP_CONTEXT volatile  mDebugMpContext = { 0, 0, 0, { 0 }, { 0 }, 0, 0, 0, 0, FALSE, FALSE };
 | 
						|
 | 
						|
GLOBAL_REMOVE_IF_UNREFERENCED DEBUG_CPU_DATA volatile  mDebugCpuData = { 0 };
 | 
						|
 | 
						|
/**
 | 
						|
  Acquire a spin lock when Multi-processor supported.
 | 
						|
 | 
						|
  It will block in the function if cannot get the access control.
 | 
						|
  If Multi-processor is not supported, return directly.
 | 
						|
 | 
						|
  @param[in, out] MpSpinLock      A pointer to the spin lock.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
AcquireMpSpinLock (
 | 
						|
  IN OUT SPIN_LOCK  *MpSpinLock
 | 
						|
  )
 | 
						|
{
 | 
						|
  if (!MultiProcessorDebugSupport ()) {
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  while (TRUE) {
 | 
						|
    if (AcquireSpinLockOrFail (MpSpinLock)) {
 | 
						|
      break;
 | 
						|
    }
 | 
						|
 | 
						|
    CpuPause ();
 | 
						|
    continue;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Release a spin lock when Multi-processor supported.
 | 
						|
 | 
						|
  @param[in, out] MpSpinLock      A pointer to the spin lock.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
ReleaseMpSpinLock (
 | 
						|
  IN OUT SPIN_LOCK  *MpSpinLock
 | 
						|
  )
 | 
						|
{
 | 
						|
  if (!MultiProcessorDebugSupport ()) {
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  ReleaseSpinLock (MpSpinLock);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Break the other processor by send IPI.
 | 
						|
 | 
						|
  @param[in] CurrentProcessorIndex  Current processor index value.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
HaltOtherProcessors (
 | 
						|
  IN UINT32  CurrentProcessorIndex
 | 
						|
  )
 | 
						|
{
 | 
						|
  DebugAgentMsgPrint (DEBUG_AGENT_INFO, "processor[%x]:Try to halt other processors.\n", CurrentProcessorIndex);
 | 
						|
  if (!DebugAgentIsBsp (CurrentProcessorIndex)) {
 | 
						|
    SetIpiSentByApFlag (TRUE);
 | 
						|
  }
 | 
						|
 | 
						|
  mDebugMpContext.BreakAtCpuIndex = CurrentProcessorIndex;
 | 
						|
 | 
						|
  //
 | 
						|
  // Set the debug viewpoint to the current breaking CPU.
 | 
						|
  //
 | 
						|
  SetDebugViewPoint (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 ();
 | 
						|
 | 
						|
  AcquireMpSpinLock (&mDebugMpContext.MpContextSpinLock);
 | 
						|
 | 
						|
  for (Index = 0; Index < mDebugCpuData.CpuCount; Index++) {
 | 
						|
    if (mDebugCpuData.ApicID[Index] == LocalApicID) {
 | 
						|
      break;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  if (Index == mDebugCpuData.CpuCount) {
 | 
						|
    mDebugCpuData.ApicID[Index] = LocalApicID;
 | 
						|
    mDebugCpuData.CpuCount++;
 | 
						|
  }
 | 
						|
 | 
						|
  ReleaseMpSpinLock (&mDebugMpContext.MpContextSpinLock);
 | 
						|
 | 
						|
  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
 | 
						|
DebugAgentIsBsp (
 | 
						|
  IN UINT32  ProcessorIndex
 | 
						|
  )
 | 
						|
{
 | 
						|
  MSR_IA32_APIC_BASE_REGISTER  MsrApicBase;
 | 
						|
 | 
						|
  //
 | 
						|
  // If there are less than 2 CPUs detected, then the currently executing CPU
 | 
						|
  // must be the BSP.  This avoids an access to an MSR that may not be supported
 | 
						|
  // on single core CPUs.
 | 
						|
  //
 | 
						|
  if (mDebugCpuData.CpuCount < 2) {
 | 
						|
    return TRUE;
 | 
						|
  }
 | 
						|
 | 
						|
  MsrApicBase.Uint64 = AsmReadMsr64 (MSR_IA32_APIC_BASE);
 | 
						|
  if (MsrApicBase.Bits.BSP == 1) {
 | 
						|
    if (mDebugMpContext.BspIndex != ProcessorIndex) {
 | 
						|
      AcquireMpSpinLock (&mDebugMpContext.MpContextSpinLock);
 | 
						|
      mDebugMpContext.BspIndex = ProcessorIndex;
 | 
						|
      ReleaseMpSpinLock (&mDebugMpContext.MpContextSpinLock);
 | 
						|
    }
 | 
						|
 | 
						|
    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;
 | 
						|
 | 
						|
  AcquireMpSpinLock (&mDebugMpContext.MpContextSpinLock);
 | 
						|
 | 
						|
  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;
 | 
						|
 | 
						|
  ReleaseMpSpinLock (&mDebugMpContext.MpContextSpinLock);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  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;
 | 
						|
 | 
						|
  AcquireMpSpinLock (&mDebugMpContext.MpContextSpinLock);
 | 
						|
 | 
						|
  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;
 | 
						|
 | 
						|
  ReleaseMpSpinLock (&mDebugMpContext.MpContextSpinLock);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  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
 | 
						|
  )
 | 
						|
{
 | 
						|
  AcquireMpSpinLock (&mDebugMpContext.MpContextSpinLock);
 | 
						|
  mDebugMpContext.RunCommandSet = RunningFlag;
 | 
						|
  ReleaseMpSpinLock (&mDebugMpContext.MpContextSpinLock);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Set the current view point to be debugged.
 | 
						|
 | 
						|
  @param[in] ProcessorIndex   Processor index value.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
SetDebugViewPoint (
 | 
						|
  IN UINT32  ProcessorIndex
 | 
						|
  )
 | 
						|
{
 | 
						|
  AcquireMpSpinLock (&mDebugMpContext.MpContextSpinLock);
 | 
						|
  mDebugMpContext.ViewPointIndex = ProcessorIndex;
 | 
						|
  ReleaseMpSpinLock (&mDebugMpContext.MpContextSpinLock);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Set the IPI send by BPS/AP flag.
 | 
						|
 | 
						|
  @param[in] IpiSentByApFlag   TRUE means this IPI is sent by AP.
 | 
						|
                               FALSE means this IPI is sent by BSP.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
SetIpiSentByApFlag (
 | 
						|
  IN BOOLEAN  IpiSentByApFlag
 | 
						|
  )
 | 
						|
{
 | 
						|
  AcquireMpSpinLock (&mDebugMpContext.MpContextSpinLock);
 | 
						|
  mDebugMpContext.IpiSentByAp = IpiSentByApFlag;
 | 
						|
  ReleaseMpSpinLock (&mDebugMpContext.MpContextSpinLock);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Check the next pending breaking CPU.
 | 
						|
 | 
						|
  @retval others      There is at least one processor broken, the minimum
 | 
						|
                      index number of Processor returned.
 | 
						|
  @retval -1          No any processor broken.
 | 
						|
 | 
						|
**/
 | 
						|
UINT32
 | 
						|
FindNextPendingBreakCpu (
 | 
						|
  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;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Check if the current processor is the first breaking processor.
 | 
						|
 | 
						|
  If yes, halt other processors.
 | 
						|
 | 
						|
  @param[in] ProcessorIndex   Processor index value.
 | 
						|
 | 
						|
  @return TRUE       This processor is the first breaking processor.
 | 
						|
  @return FALSE      This processor is not the first breaking processor.
 | 
						|
 | 
						|
**/
 | 
						|
BOOLEAN
 | 
						|
IsFirstBreakProcessor (
 | 
						|
  IN UINT32  ProcessorIndex
 | 
						|
  )
 | 
						|
{
 | 
						|
  if (MultiProcessorDebugSupport ()) {
 | 
						|
    if (mDebugMpContext.BreakAtCpuIndex != (UINT32)-1) {
 | 
						|
      //
 | 
						|
      // The current processor is not the first breaking one.
 | 
						|
      //
 | 
						|
      SetCpuBreakFlagByIndex (ProcessorIndex, TRUE);
 | 
						|
      return FALSE;
 | 
						|
    } else {
 | 
						|
      //
 | 
						|
      // If no any processor breaks, try to halt other processors
 | 
						|
      //
 | 
						|
      HaltOtherProcessors (ProcessorIndex);
 | 
						|
      return TRUE;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return TRUE;
 | 
						|
}
 |