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