]> git.proxmox.com Git - mirror_edk2.git/blob - SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/DebugMp.c
Add missing braces around initializer.
[mirror_edk2.git] / SourceLevelDebugPkg / Library / DebugAgent / DebugAgentCommon / DebugMp.c
1 /** @file
2 Multi-Processor support functions implementation.
3
4 Copyright (c) 2010 - 2012, 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.
9
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.
12
13 **/
14
15 #include "DebugAgent.h"
16
17 DEBUG_MP_CONTEXT volatile mDebugMpContext = {0,0,{0},{0},0,0,0,0,FALSE,FALSE};
18
19 DEBUG_CPU_DATA volatile mDebugCpuData = {0};
20
21 /**
22 Acquire access control on debug port.
23
24 It will block in the function if cannot get the access control.
25
26 **/
27 VOID
28 AcquireDebugPortControl (
29 VOID
30 )
31 {
32 if (!MultiProcessorDebugSupport) {
33 return;
34 }
35
36 while (TRUE) {
37 if (AcquireSpinLockOrFail (&mDebugMpContext.DebugPortSpinLock)) {
38 break;
39 }
40 CpuPause ();
41 continue;
42 }
43 }
44
45 /**
46 Release access control on debug port.
47
48 **/
49 VOID
50 ReleaseDebugPortControl (
51 VOID
52 )
53 {
54 if (!MultiProcessorDebugSupport) {
55 return;
56 }
57
58 ReleaseSpinLock (&mDebugMpContext.DebugPortSpinLock);
59 }
60
61 /**
62 Acquire access control on MP context.
63
64 It will block in the function if cannot get the access control.
65
66 **/
67 VOID
68 AcquireMpContextControl (
69 VOID
70 )
71 {
72 while (TRUE) {
73 if (AcquireSpinLockOrFail (&mDebugMpContext.MpContextSpinLock)) {
74 break;
75 }
76 CpuPause ();
77 continue;
78 }
79 }
80
81 /**
82 Release access control on MP context.
83
84 **/
85 VOID
86 ReleaseMpContextControl (
87 VOID
88 )
89 {
90 ReleaseSpinLock (&mDebugMpContext.MpContextSpinLock);
91 }
92
93 /**
94 Break the other processor by send IPI.
95
96 @param[in] CurrentProcessorIndex Current processor index value.
97
98 **/
99 VOID
100 HaltOtherProcessors (
101 IN UINT32 CurrentProcessorIndex
102 )
103 {
104 DebugAgentMsgPrint (DEBUG_AGENT_INFO, "processor[%x]:Try to halt other processors.\n", CurrentProcessorIndex);
105 if (!IsBsp (CurrentProcessorIndex)) {
106 SetIpiSentByApFlag (TRUE);;
107 }
108
109 mDebugMpContext.BreakAtCpuIndex = CurrentProcessorIndex;
110
111 //
112 // Set the debug viewpoint to the current breaking CPU.
113 //
114 SetDebugViewPoint (CurrentProcessorIndex);
115
116 //
117 // Send fixed IPI to other processors.
118 //
119 SendFixedIpiAllExcludingSelf (DEBUG_TIMER_VECTOR);
120
121 }
122
123 /**
124 Get the current processor's index.
125
126 @return Processor index value.
127
128 **/
129 UINT32
130 GetProcessorIndex (
131 VOID
132 )
133 {
134 UINT32 Index;
135 UINT16 LocalApicID;
136
137 LocalApicID = (UINT16) GetApicId ();
138
139 AcquireMpContextControl ();
140
141 for (Index = 0; Index < mDebugCpuData.CpuCount; Index ++) {
142 if (mDebugCpuData.ApicID[Index] == LocalApicID) {
143 break;
144 }
145 }
146
147 if (Index == mDebugCpuData.CpuCount) {
148 mDebugCpuData.ApicID[Index] = LocalApicID;
149 mDebugCpuData.CpuCount ++ ;
150 }
151
152 ReleaseMpContextControl ();
153
154 return Index;
155 }
156
157 /**
158 Check if the specified processor is BSP or not.
159
160 @param[in] ProcessorIndex Processor index value.
161
162 @retval TRUE It is BSP.
163 @retval FALSE It isn't BSP.
164
165 **/
166 BOOLEAN
167 IsBsp (
168 IN UINT32 ProcessorIndex
169 )
170 {
171 if (AsmMsrBitFieldRead64 (MSR_IA32_APIC_BASE_ADDRESS, 8, 8) == 1) {
172 if (mDebugMpContext.BspIndex != ProcessorIndex) {
173 AcquireMpContextControl ();
174 mDebugMpContext.BspIndex = ProcessorIndex;
175 ReleaseMpContextControl ();
176 }
177 return TRUE;
178 } else {
179 return FALSE;
180 }
181 }
182
183 /**
184 Set processor stop flag bitmask in MP context.
185
186 @param[in] ProcessorIndex Processor index value.
187 @param[in] StopFlag TRUE means set stop flag.
188 FALSE means clean break flag.
189
190 **/
191 VOID
192 SetCpuStopFlagByIndex (
193 IN UINT32 ProcessorIndex,
194 IN BOOLEAN StopFlag
195 )
196 {
197 UINT8 Value;
198 UINTN Index;
199
200 AcquireMpContextControl ();
201
202 Value = mDebugMpContext.CpuStopStatusMask[ProcessorIndex / 8];
203 Index = ProcessorIndex % 8;
204 if (StopFlag) {
205 Value = BitFieldWrite8 (Value, Index, Index, 1);
206 } else {
207 Value = BitFieldWrite8 (Value, Index, Index, 0);
208 }
209 mDebugMpContext.CpuStopStatusMask[ProcessorIndex / 8] = Value;
210
211 ReleaseMpContextControl ();
212 }
213
214 /**
215 Set processor break flag bitmask in MP context.
216
217 @param[in] ProcessorIndex Processor index value.
218 @param[in] BreakFlag TRUE means set break flag.
219 FALSE means clean break flag.
220
221 **/
222 VOID
223 SetCpuBreakFlagByIndex (
224 IN UINT32 ProcessorIndex,
225 IN BOOLEAN BreakFlag
226 )
227 {
228 UINT8 Value;
229 UINTN Index;
230
231 AcquireMpContextControl ();
232
233 Value = mDebugMpContext.CpuBreakMask[ProcessorIndex / 8];
234 Index = ProcessorIndex % 8;
235 if (BreakFlag) {
236 Value = BitFieldWrite8 (Value, Index, Index, 1);
237 } else {
238 Value = BitFieldWrite8 (Value, Index, Index, 0);
239 }
240 mDebugMpContext.CpuBreakMask[ProcessorIndex / 8] = Value;
241
242 ReleaseMpContextControl ();
243 }
244
245 /**
246 Check if processor is stopped already.
247
248 @param[in] ProcessorIndex Processor index value.
249
250 @retval TRUE Processor is stopped already.
251 @retval TRUE Processor isn't stopped.
252
253 **/
254 BOOLEAN
255 IsCpuStopped (
256 IN UINT32 ProcessorIndex
257 )
258 {
259 UINT8 CpuMask;
260
261 CpuMask = (UINT8) (1 << (ProcessorIndex % 8));
262
263 if ((mDebugMpContext.CpuStopStatusMask[ProcessorIndex / 8] & CpuMask) != 0) {
264 return TRUE;
265 } else {
266 return FALSE;
267 }
268 }
269
270 /**
271 Set the run command flag.
272
273 @param[in] RunningFlag TRUE means run command flag is set.
274 FALSE means run command flag is cleared.
275
276 **/
277 VOID
278 SetCpuRunningFlag (
279 IN BOOLEAN RunningFlag
280 )
281 {
282 AcquireMpContextControl ();
283
284 mDebugMpContext.RunCommandSet = RunningFlag;
285
286 ReleaseMpContextControl ();
287 }
288
289 /**
290 Set the current view point to be debugged.
291
292 @param[in] ProcessorIndex Processor index value.
293
294 **/
295 VOID
296 SetDebugViewPoint (
297 IN UINT32 ProcessorIndex
298 )
299 {
300 AcquireMpContextControl ();
301
302 mDebugMpContext.ViewPointIndex = ProcessorIndex;
303
304 ReleaseMpContextControl ();
305 }
306
307 /**
308 Set the IPI send by BPS/AP flag.
309
310 @param[in] IpiSentByApFlag TRUE means this IPI is sent by AP.
311 FALSE means this IPI is sent by BSP.
312
313 **/
314 VOID
315 SetIpiSentByApFlag (
316 IN BOOLEAN IpiSentByApFlag
317 )
318 {
319 AcquireMpContextControl ();
320
321 mDebugMpContext.IpiSentByAp = IpiSentByApFlag;
322
323 ReleaseMpContextControl ();
324 }
325
326 /**
327 Check the next pending breaking CPU.
328
329 @retval others There is at least one processor broken, the minimum
330 index number of Processor returned.
331 @retval -1 No any processor broken.
332
333 **/
334 UINT32
335 FindNextPendingBreakCpu (
336 VOID
337 )
338 {
339 UINT32 Index;
340
341 for (Index = 0; Index < DEBUG_CPU_MAX_COUNT / 8; Index ++) {
342 if (mDebugMpContext.CpuBreakMask[Index] != 0) {
343 return (UINT32) LowBitSet32 (mDebugMpContext.CpuBreakMask[Index]) + Index * 8;
344 }
345 }
346 return (UINT32)-1;
347 }
348
349 /**
350 Check if all processors are in running status.
351
352 @retval TRUE All processors run.
353 @retval FALSE At least one processor does not run.
354
355 **/
356 BOOLEAN
357 IsAllCpuRunning (
358 VOID
359 )
360 {
361 UINTN Index;
362
363 for (Index = 0; Index < DEBUG_CPU_MAX_COUNT / 8; Index ++) {
364 if (mDebugMpContext.CpuStopStatusMask[Index] != 0) {
365 return FALSE;
366 }
367 }
368 return TRUE;
369 }
370
371 /**
372 Check if the current processor is the first breaking processor.
373
374 If yes, halt other processors.
375
376 @param[in] ProcessorIndex Processor index value.
377
378 @return TRUE This processor is the first breaking processor.
379 @return FALSE This processor is not the first breaking processor.
380
381 **/
382 BOOLEAN
383 IsFirstBreakProcessor (
384 IN UINT32 ProcessorIndex
385 )
386 {
387 if (MultiProcessorDebugSupport) {
388 if (mDebugMpContext.BreakAtCpuIndex != (UINT32) -1) {
389 //
390 // The current processor is not the first breaking one.
391 //
392 SetCpuBreakFlagByIndex (ProcessorIndex, TRUE);
393 return FALSE;
394 } else {
395 //
396 // If no any processor breaks, try to halt other processors
397 //
398 HaltOtherProcessors (ProcessorIndex);
399 return TRUE;
400 }
401 }
402 return TRUE;
403 }
404