mirror of
				https://github.com/acidanthera/audk.git
				synced 2025-10-31 19:23:54 +01:00 
			
		
		
		
	https://bugzilla.tianocore.org/show_bug.cgi?id=1373 Replace BSD 2-Clause License with BSD+Patent License. This change is based on the following emails: https://lists.01.org/pipermail/edk2-devel/2019-February/036260.html https://lists.01.org/pipermail/edk2-devel/2018-October/030385.html RFCs with detailed process for the license change: V3: https://lists.01.org/pipermail/edk2-devel/2019-March/038116.html V2: https://lists.01.org/pipermail/edk2-devel/2019-March/037669.html V1: https://lists.01.org/pipermail/edk2-devel/2019-March/037500.html Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Michael D Kinney <michael.d.kinney@intel.com> Reviewed-by: Hao Wu <hao.a.wu@intel.com>
		
			
				
	
	
		
			378 lines
		
	
	
		
			8.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			378 lines
		
	
	
		
			8.6 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;
 | |
| }
 | |
| 
 |