2 Multi-Processor support functions implementation.
4 Copyright (c) 2010 - 2016, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php.
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15 #include "DebugAgent.h"
17 GLOBAL_REMOVE_IF_UNREFERENCED DEBUG_MP_CONTEXT
volatile mDebugMpContext
= {0,0,0,{0},{0},0,0,0,0,FALSE
,FALSE
};
19 GLOBAL_REMOVE_IF_UNREFERENCED DEBUG_CPU_DATA
volatile mDebugCpuData
= {0};
22 Acquire a spin lock when Multi-processor supported.
24 It will block in the function if cannot get the access control.
25 If Multi-processor is not supported, return directly.
27 @param[in, out] MpSpinLock A pointer to the spin lock.
32 IN OUT SPIN_LOCK
*MpSpinLock
35 if (!MultiProcessorDebugSupport()) {
40 if (AcquireSpinLockOrFail (MpSpinLock
)) {
49 Release a spin lock when Multi-processor supported.
51 @param[in, out] MpSpinLock A pointer to the spin lock.
56 IN OUT SPIN_LOCK
*MpSpinLock
59 if (!MultiProcessorDebugSupport()) {
63 ReleaseSpinLock (MpSpinLock
);
67 Break the other processor by send IPI.
69 @param[in] CurrentProcessorIndex Current processor index value.
74 IN UINT32 CurrentProcessorIndex
77 DebugAgentMsgPrint (DEBUG_AGENT_INFO
, "processor[%x]:Try to halt other processors.\n", CurrentProcessorIndex
);
78 if (!IsBsp (CurrentProcessorIndex
)) {
79 SetIpiSentByApFlag (TRUE
);;
82 mDebugMpContext
.BreakAtCpuIndex
= CurrentProcessorIndex
;
85 // Set the debug viewpoint to the current breaking CPU.
87 SetDebugViewPoint (CurrentProcessorIndex
);
90 // Send fixed IPI to other processors.
92 SendFixedIpiAllExcludingSelf (DEBUG_TIMER_VECTOR
);
97 Get the current processor's index.
99 @return Processor index value.
110 LocalApicID
= (UINT16
) GetApicId ();
112 AcquireMpSpinLock (&mDebugMpContext
.MpContextSpinLock
);
114 for (Index
= 0; Index
< mDebugCpuData
.CpuCount
; Index
++) {
115 if (mDebugCpuData
.ApicID
[Index
] == LocalApicID
) {
120 if (Index
== mDebugCpuData
.CpuCount
) {
121 mDebugCpuData
.ApicID
[Index
] = LocalApicID
;
122 mDebugCpuData
.CpuCount
++ ;
125 ReleaseMpSpinLock (&mDebugMpContext
.MpContextSpinLock
);
131 Check if the specified processor is BSP or not.
133 @param[in] ProcessorIndex Processor index value.
135 @retval TRUE It is BSP.
136 @retval FALSE It isn't BSP.
141 IN UINT32 ProcessorIndex
144 MSR_IA32_APIC_BASE_REGISTER MsrApicBase
;
147 // If there are less than 2 CPUs detected, then the currently executing CPU
148 // must be the BSP. This avoids an access to an MSR that may not be supported
149 // on single core CPUs.
151 if (mDebugCpuData
.CpuCount
< 2) {
155 MsrApicBase
.Uint64
= AsmReadMsr64 (MSR_IA32_APIC_BASE
);
156 if (MsrApicBase
.Bits
.BSP
== 1) {
157 if (mDebugMpContext
.BspIndex
!= ProcessorIndex
) {
158 AcquireMpSpinLock (&mDebugMpContext
.MpContextSpinLock
);
159 mDebugMpContext
.BspIndex
= ProcessorIndex
;
160 ReleaseMpSpinLock (&mDebugMpContext
.MpContextSpinLock
);
169 Set processor stop flag bitmask in MP context.
171 @param[in] ProcessorIndex Processor index value.
172 @param[in] StopFlag TRUE means set stop flag.
173 FALSE means clean break flag.
177 SetCpuStopFlagByIndex (
178 IN UINT32 ProcessorIndex
,
185 AcquireMpSpinLock (&mDebugMpContext
.MpContextSpinLock
);
187 Value
= mDebugMpContext
.CpuStopStatusMask
[ProcessorIndex
/ 8];
188 Index
= ProcessorIndex
% 8;
190 Value
= BitFieldWrite8 (Value
, Index
, Index
, 1);
192 Value
= BitFieldWrite8 (Value
, Index
, Index
, 0);
194 mDebugMpContext
.CpuStopStatusMask
[ProcessorIndex
/ 8] = Value
;
196 ReleaseMpSpinLock (&mDebugMpContext
.MpContextSpinLock
);
200 Set processor break flag bitmask in MP context.
202 @param[in] ProcessorIndex Processor index value.
203 @param[in] BreakFlag TRUE means set break flag.
204 FALSE means clean break flag.
208 SetCpuBreakFlagByIndex (
209 IN UINT32 ProcessorIndex
,
216 AcquireMpSpinLock (&mDebugMpContext
.MpContextSpinLock
);
218 Value
= mDebugMpContext
.CpuBreakMask
[ProcessorIndex
/ 8];
219 Index
= ProcessorIndex
% 8;
221 Value
= BitFieldWrite8 (Value
, Index
, Index
, 1);
223 Value
= BitFieldWrite8 (Value
, Index
, Index
, 0);
225 mDebugMpContext
.CpuBreakMask
[ProcessorIndex
/ 8] = Value
;
227 ReleaseMpSpinLock (&mDebugMpContext
.MpContextSpinLock
);
231 Check if processor is stopped already.
233 @param[in] ProcessorIndex Processor index value.
235 @retval TRUE Processor is stopped already.
236 @retval TRUE Processor isn't stopped.
241 IN UINT32 ProcessorIndex
246 CpuMask
= (UINT8
) (1 << (ProcessorIndex
% 8));
248 if ((mDebugMpContext
.CpuStopStatusMask
[ProcessorIndex
/ 8] & CpuMask
) != 0) {
256 Set the run command flag.
258 @param[in] RunningFlag TRUE means run command flag is set.
259 FALSE means run command flag is cleared.
264 IN BOOLEAN RunningFlag
267 AcquireMpSpinLock (&mDebugMpContext
.MpContextSpinLock
);
268 mDebugMpContext
.RunCommandSet
= RunningFlag
;
269 ReleaseMpSpinLock (&mDebugMpContext
.MpContextSpinLock
);
273 Set the current view point to be debugged.
275 @param[in] ProcessorIndex Processor index value.
280 IN UINT32 ProcessorIndex
283 AcquireMpSpinLock (&mDebugMpContext
.MpContextSpinLock
);
284 mDebugMpContext
.ViewPointIndex
= ProcessorIndex
;
285 ReleaseMpSpinLock (&mDebugMpContext
.MpContextSpinLock
);
289 Set the IPI send by BPS/AP flag.
291 @param[in] IpiSentByApFlag TRUE means this IPI is sent by AP.
292 FALSE means this IPI is sent by BSP.
297 IN BOOLEAN IpiSentByApFlag
300 AcquireMpSpinLock (&mDebugMpContext
.MpContextSpinLock
);
301 mDebugMpContext
.IpiSentByAp
= IpiSentByApFlag
;
302 ReleaseMpSpinLock (&mDebugMpContext
.MpContextSpinLock
);
306 Check the next pending breaking CPU.
308 @retval others There is at least one processor broken, the minimum
309 index number of Processor returned.
310 @retval -1 No any processor broken.
314 FindNextPendingBreakCpu (
320 for (Index
= 0; Index
< DEBUG_CPU_MAX_COUNT
/ 8; Index
++) {
321 if (mDebugMpContext
.CpuBreakMask
[Index
] != 0) {
322 return (UINT32
) LowBitSet32 (mDebugMpContext
.CpuBreakMask
[Index
]) + Index
* 8;
329 Check if all processors are in running status.
331 @retval TRUE All processors run.
332 @retval FALSE At least one processor does not run.
342 for (Index
= 0; Index
< DEBUG_CPU_MAX_COUNT
/ 8; Index
++) {
343 if (mDebugMpContext
.CpuStopStatusMask
[Index
] != 0) {
351 Check if the current processor is the first breaking processor.
353 If yes, halt other processors.
355 @param[in] ProcessorIndex Processor index value.
357 @return TRUE This processor is the first breaking processor.
358 @return FALSE This processor is not the first breaking processor.
362 IsFirstBreakProcessor (
363 IN UINT32 ProcessorIndex
366 if (MultiProcessorDebugSupport()) {
367 if (mDebugMpContext
.BreakAtCpuIndex
!= (UINT32
) -1) {
369 // The current processor is not the first breaking one.
371 SetCpuBreakFlagByIndex (ProcessorIndex
, TRUE
);
375 // If no any processor breaks, try to halt other processors
377 HaltOtherProcessors (ProcessorIndex
);