2 Multi-Processor support functions implementation.
4 Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
9 #include "DebugAgent.h"
11 GLOBAL_REMOVE_IF_UNREFERENCED DEBUG_MP_CONTEXT
volatile mDebugMpContext
= { 0, 0, 0, { 0 }, { 0 }, 0, 0, 0, 0, FALSE
, FALSE
};
13 GLOBAL_REMOVE_IF_UNREFERENCED DEBUG_CPU_DATA
volatile mDebugCpuData
= { 0 };
16 Acquire a spin lock when Multi-processor supported.
18 It will block in the function if cannot get the access control.
19 If Multi-processor is not supported, return directly.
21 @param[in, out] MpSpinLock A pointer to the spin lock.
26 IN OUT SPIN_LOCK
*MpSpinLock
29 if (!MultiProcessorDebugSupport ()) {
34 if (AcquireSpinLockOrFail (MpSpinLock
)) {
44 Release a spin lock when Multi-processor supported.
46 @param[in, out] MpSpinLock A pointer to the spin lock.
51 IN OUT SPIN_LOCK
*MpSpinLock
54 if (!MultiProcessorDebugSupport ()) {
58 ReleaseSpinLock (MpSpinLock
);
62 Break the other processor by send IPI.
64 @param[in] CurrentProcessorIndex Current processor index value.
69 IN UINT32 CurrentProcessorIndex
72 DebugAgentMsgPrint (DEBUG_AGENT_INFO
, "processor[%x]:Try to halt other processors.\n", CurrentProcessorIndex
);
73 if (!DebugAgentIsBsp (CurrentProcessorIndex
)) {
74 SetIpiSentByApFlag (TRUE
);
77 mDebugMpContext
.BreakAtCpuIndex
= CurrentProcessorIndex
;
80 // Set the debug viewpoint to the current breaking CPU.
82 SetDebugViewPoint (CurrentProcessorIndex
);
85 // Send fixed IPI to other processors.
87 SendFixedIpiAllExcludingSelf (DEBUG_TIMER_VECTOR
);
91 Get the current processor's index.
93 @return Processor index value.
104 LocalApicID
= (UINT16
)GetApicId ();
106 AcquireMpSpinLock (&mDebugMpContext
.MpContextSpinLock
);
108 for (Index
= 0; Index
< mDebugCpuData
.CpuCount
; Index
++) {
109 if (mDebugCpuData
.ApicID
[Index
] == LocalApicID
) {
114 if (Index
== mDebugCpuData
.CpuCount
) {
115 mDebugCpuData
.ApicID
[Index
] = LocalApicID
;
116 mDebugCpuData
.CpuCount
++;
119 ReleaseMpSpinLock (&mDebugMpContext
.MpContextSpinLock
);
125 Check if the specified processor is BSP or not.
127 @param[in] ProcessorIndex Processor index value.
129 @retval TRUE It is BSP.
130 @retval FALSE It isn't BSP.
135 IN UINT32 ProcessorIndex
138 MSR_IA32_APIC_BASE_REGISTER MsrApicBase
;
141 // If there are less than 2 CPUs detected, then the currently executing CPU
142 // must be the BSP. This avoids an access to an MSR that may not be supported
143 // on single core CPUs.
145 if (mDebugCpuData
.CpuCount
< 2) {
149 MsrApicBase
.Uint64
= AsmReadMsr64 (MSR_IA32_APIC_BASE
);
150 if (MsrApicBase
.Bits
.BSP
== 1) {
151 if (mDebugMpContext
.BspIndex
!= ProcessorIndex
) {
152 AcquireMpSpinLock (&mDebugMpContext
.MpContextSpinLock
);
153 mDebugMpContext
.BspIndex
= ProcessorIndex
;
154 ReleaseMpSpinLock (&mDebugMpContext
.MpContextSpinLock
);
164 Set processor stop flag bitmask in MP context.
166 @param[in] ProcessorIndex Processor index value.
167 @param[in] StopFlag TRUE means set stop flag.
168 FALSE means clean break flag.
172 SetCpuStopFlagByIndex (
173 IN UINT32 ProcessorIndex
,
180 AcquireMpSpinLock (&mDebugMpContext
.MpContextSpinLock
);
182 Value
= mDebugMpContext
.CpuStopStatusMask
[ProcessorIndex
/ 8];
183 Index
= ProcessorIndex
% 8;
185 Value
= BitFieldWrite8 (Value
, Index
, Index
, 1);
187 Value
= BitFieldWrite8 (Value
, Index
, Index
, 0);
190 mDebugMpContext
.CpuStopStatusMask
[ProcessorIndex
/ 8] = Value
;
192 ReleaseMpSpinLock (&mDebugMpContext
.MpContextSpinLock
);
196 Set processor break flag bitmask in MP context.
198 @param[in] ProcessorIndex Processor index value.
199 @param[in] BreakFlag TRUE means set break flag.
200 FALSE means clean break flag.
204 SetCpuBreakFlagByIndex (
205 IN UINT32 ProcessorIndex
,
212 AcquireMpSpinLock (&mDebugMpContext
.MpContextSpinLock
);
214 Value
= mDebugMpContext
.CpuBreakMask
[ProcessorIndex
/ 8];
215 Index
= ProcessorIndex
% 8;
217 Value
= BitFieldWrite8 (Value
, Index
, Index
, 1);
219 Value
= BitFieldWrite8 (Value
, Index
, Index
, 0);
222 mDebugMpContext
.CpuBreakMask
[ProcessorIndex
/ 8] = Value
;
224 ReleaseMpSpinLock (&mDebugMpContext
.MpContextSpinLock
);
228 Check if processor is stopped already.
230 @param[in] ProcessorIndex Processor index value.
232 @retval TRUE Processor is stopped already.
233 @retval TRUE Processor isn't stopped.
238 IN UINT32 ProcessorIndex
243 CpuMask
= (UINT8
)(1 << (ProcessorIndex
% 8));
245 if ((mDebugMpContext
.CpuStopStatusMask
[ProcessorIndex
/ 8] & CpuMask
) != 0) {
253 Set the run command flag.
255 @param[in] RunningFlag TRUE means run command flag is set.
256 FALSE means run command flag is cleared.
261 IN BOOLEAN RunningFlag
264 AcquireMpSpinLock (&mDebugMpContext
.MpContextSpinLock
);
265 mDebugMpContext
.RunCommandSet
= RunningFlag
;
266 ReleaseMpSpinLock (&mDebugMpContext
.MpContextSpinLock
);
270 Set the current view point to be debugged.
272 @param[in] ProcessorIndex Processor index value.
277 IN UINT32 ProcessorIndex
280 AcquireMpSpinLock (&mDebugMpContext
.MpContextSpinLock
);
281 mDebugMpContext
.ViewPointIndex
= ProcessorIndex
;
282 ReleaseMpSpinLock (&mDebugMpContext
.MpContextSpinLock
);
286 Set the IPI send by BPS/AP flag.
288 @param[in] IpiSentByApFlag TRUE means this IPI is sent by AP.
289 FALSE means this IPI is sent by BSP.
294 IN BOOLEAN IpiSentByApFlag
297 AcquireMpSpinLock (&mDebugMpContext
.MpContextSpinLock
);
298 mDebugMpContext
.IpiSentByAp
= IpiSentByApFlag
;
299 ReleaseMpSpinLock (&mDebugMpContext
.MpContextSpinLock
);
303 Check the next pending breaking CPU.
305 @retval others There is at least one processor broken, the minimum
306 index number of Processor returned.
307 @retval -1 No any processor broken.
311 FindNextPendingBreakCpu (
317 for (Index
= 0; Index
< DEBUG_CPU_MAX_COUNT
/ 8; Index
++) {
318 if (mDebugMpContext
.CpuBreakMask
[Index
] != 0) {
319 return (UINT32
)LowBitSet32 (mDebugMpContext
.CpuBreakMask
[Index
]) + Index
* 8;
327 Check if all processors are in running status.
329 @retval TRUE All processors run.
330 @retval FALSE At least one processor does not run.
340 for (Index
= 0; Index
< DEBUG_CPU_MAX_COUNT
/ 8; Index
++) {
341 if (mDebugMpContext
.CpuStopStatusMask
[Index
] != 0) {
350 Check if the current processor is the first breaking processor.
352 If yes, halt other processors.
354 @param[in] ProcessorIndex Processor index value.
356 @return TRUE This processor is the first breaking processor.
357 @return FALSE This processor is not the first breaking processor.
361 IsFirstBreakProcessor (
362 IN UINT32 ProcessorIndex
365 if (MultiProcessorDebugSupport ()) {
366 if (mDebugMpContext
.BreakAtCpuIndex
!= (UINT32
)-1) {
368 // The current processor is not the first breaking one.
370 SetCpuBreakFlagByIndex (ProcessorIndex
, TRUE
);
374 // If no any processor breaks, try to halt other processors
376 HaltOtherProcessors (ProcessorIndex
);