2 Multi-Processor support functions implementation.
4 Copyright (c) 2010 - 2014, 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 if (AsmMsrBitFieldRead64 (MSR_IA32_APIC_BASE_ADDRESS
, 8, 8) == 1) {
145 if (mDebugMpContext
.BspIndex
!= ProcessorIndex
) {
146 AcquireMpSpinLock (&mDebugMpContext
.MpContextSpinLock
);
147 mDebugMpContext
.BspIndex
= ProcessorIndex
;
148 ReleaseMpSpinLock (&mDebugMpContext
.MpContextSpinLock
);
157 Set processor stop flag bitmask in MP context.
159 @param[in] ProcessorIndex Processor index value.
160 @param[in] StopFlag TRUE means set stop flag.
161 FALSE means clean break flag.
165 SetCpuStopFlagByIndex (
166 IN UINT32 ProcessorIndex
,
173 AcquireMpSpinLock (&mDebugMpContext
.MpContextSpinLock
);
175 Value
= mDebugMpContext
.CpuStopStatusMask
[ProcessorIndex
/ 8];
176 Index
= ProcessorIndex
% 8;
178 Value
= BitFieldWrite8 (Value
, Index
, Index
, 1);
180 Value
= BitFieldWrite8 (Value
, Index
, Index
, 0);
182 mDebugMpContext
.CpuStopStatusMask
[ProcessorIndex
/ 8] = Value
;
184 ReleaseMpSpinLock (&mDebugMpContext
.MpContextSpinLock
);
188 Set processor break flag bitmask in MP context.
190 @param[in] ProcessorIndex Processor index value.
191 @param[in] BreakFlag TRUE means set break flag.
192 FALSE means clean break flag.
196 SetCpuBreakFlagByIndex (
197 IN UINT32 ProcessorIndex
,
204 AcquireMpSpinLock (&mDebugMpContext
.MpContextSpinLock
);
206 Value
= mDebugMpContext
.CpuBreakMask
[ProcessorIndex
/ 8];
207 Index
= ProcessorIndex
% 8;
209 Value
= BitFieldWrite8 (Value
, Index
, Index
, 1);
211 Value
= BitFieldWrite8 (Value
, Index
, Index
, 0);
213 mDebugMpContext
.CpuBreakMask
[ProcessorIndex
/ 8] = Value
;
215 ReleaseMpSpinLock (&mDebugMpContext
.MpContextSpinLock
);
219 Check if processor is stopped already.
221 @param[in] ProcessorIndex Processor index value.
223 @retval TRUE Processor is stopped already.
224 @retval TRUE Processor isn't stopped.
229 IN UINT32 ProcessorIndex
234 CpuMask
= (UINT8
) (1 << (ProcessorIndex
% 8));
236 if ((mDebugMpContext
.CpuStopStatusMask
[ProcessorIndex
/ 8] & CpuMask
) != 0) {
244 Set the run command flag.
246 @param[in] RunningFlag TRUE means run command flag is set.
247 FALSE means run command flag is cleared.
252 IN BOOLEAN RunningFlag
255 AcquireMpSpinLock (&mDebugMpContext
.MpContextSpinLock
);
256 mDebugMpContext
.RunCommandSet
= RunningFlag
;
257 ReleaseMpSpinLock (&mDebugMpContext
.MpContextSpinLock
);
261 Set the current view point to be debugged.
263 @param[in] ProcessorIndex Processor index value.
268 IN UINT32 ProcessorIndex
271 AcquireMpSpinLock (&mDebugMpContext
.MpContextSpinLock
);
272 mDebugMpContext
.ViewPointIndex
= ProcessorIndex
;
273 ReleaseMpSpinLock (&mDebugMpContext
.MpContextSpinLock
);
277 Set the IPI send by BPS/AP flag.
279 @param[in] IpiSentByApFlag TRUE means this IPI is sent by AP.
280 FALSE means this IPI is sent by BSP.
285 IN BOOLEAN IpiSentByApFlag
288 AcquireMpSpinLock (&mDebugMpContext
.MpContextSpinLock
);
289 mDebugMpContext
.IpiSentByAp
= IpiSentByApFlag
;
290 ReleaseMpSpinLock (&mDebugMpContext
.MpContextSpinLock
);
294 Check the next pending breaking CPU.
296 @retval others There is at least one processor broken, the minimum
297 index number of Processor returned.
298 @retval -1 No any processor broken.
302 FindNextPendingBreakCpu (
308 for (Index
= 0; Index
< DEBUG_CPU_MAX_COUNT
/ 8; Index
++) {
309 if (mDebugMpContext
.CpuBreakMask
[Index
] != 0) {
310 return (UINT32
) LowBitSet32 (mDebugMpContext
.CpuBreakMask
[Index
]) + Index
* 8;
317 Check if all processors are in running status.
319 @retval TRUE All processors run.
320 @retval FALSE At least one processor does not run.
330 for (Index
= 0; Index
< DEBUG_CPU_MAX_COUNT
/ 8; Index
++) {
331 if (mDebugMpContext
.CpuStopStatusMask
[Index
] != 0) {
339 Check if the current processor is the first breaking processor.
341 If yes, halt other processors.
343 @param[in] ProcessorIndex Processor index value.
345 @return TRUE This processor is the first breaking processor.
346 @return FALSE This processor is not the first breaking processor.
350 IsFirstBreakProcessor (
351 IN UINT32 ProcessorIndex
354 if (MultiProcessorDebugSupport()) {
355 if (mDebugMpContext
.BreakAtCpuIndex
!= (UINT32
) -1) {
357 // The current processor is not the first breaking one.
359 SetCpuBreakFlagByIndex (ProcessorIndex
, TRUE
);
363 // If no any processor breaks, try to halt other processors
365 HaltOtherProcessors (ProcessorIndex
);