]> git.proxmox.com Git - mirror_edk2.git/blob - SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/DebugMp.c
Import SourceLevelDebugPkg.
[mirror_edk2.git] / SourceLevelDebugPkg / Library / DebugAgent / DebugAgentCommon / DebugMp.c
1 /** @file
2 Multi-Processor support functions implementation.
3
4 Copyright (c) 2010, 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
105 if (!IsBsp (CurrentProcessorIndex)) {
106 SetIpiSentByApFlag (TRUE);;
107 }
108
109 mDebugMpContext.BreakAtCpuIndex = CurrentProcessorIndex;
110
111 //
112 // Send fixed IPI to other processors.
113 //
114 SendFixedIpiAllExcludingSelf (DEBUG_TIMER_VECTOR);
115
116 }
117
118 /**
119 Get the current processor's index.
120
121 @return Processor index value.
122
123 **/
124 UINT32
125 GetProcessorIndex (
126 VOID
127 )
128 {
129 UINT32 Index;
130 UINT16 LocalApicID;
131
132 LocalApicID = (UINT16) GetApicId ();
133
134 AcquireMpContextControl ();
135
136 for (Index = 0; Index < mDebugCpuData.CpuCount; Index ++) {
137 if (mDebugCpuData.ApicID[Index] == LocalApicID) {
138 break;
139 }
140 }
141
142 if (Index == mDebugCpuData.CpuCount) {
143 mDebugCpuData.ApicID[Index] = LocalApicID;
144 mDebugCpuData.CpuCount ++ ;
145 }
146
147 ReleaseMpContextControl ();
148
149 return Index;
150 }
151
152 /**
153 Check if the specified processor is BSP or not.
154
155 @param[in] ProcessorIndex Processor index value.
156
157 @retval TRUE It is BSP.
158 @retval FALSE It isn't BSP.
159
160 **/
161 BOOLEAN
162 IsBsp (
163 IN UINT32 ProcessorIndex
164 )
165 {
166 if (AsmMsrBitFieldRead64 (MSR_IA32_APIC_BASE_ADDRESS, 8, 8) == 1) {
167 if (mDebugMpContext.BspIndex != ProcessorIndex) {
168 AcquireMpContextControl ();
169 mDebugMpContext.BspIndex = ProcessorIndex;
170 ReleaseMpContextControl ();
171 }
172 return TRUE;
173 } else {
174 return FALSE;
175 }
176 }
177
178 /**
179 Set processor stop flag bitmask in MP context.
180
181 @param[in] ProcessorIndex Processor index value.
182 @param[in] StopFlag TRUE means set stop flag.
183 FALSE means clean break flag.
184
185 **/
186 VOID
187 SetCpuStopFlagByIndex (
188 IN UINT32 ProcessorIndex,
189 IN BOOLEAN StopFlag
190 )
191 {
192 UINT8 Value;
193 UINTN Index;
194
195 AcquireMpContextControl ();
196
197 Value = mDebugMpContext.CpuStopStatusMask[ProcessorIndex / 8];
198 Index = ProcessorIndex % 8;
199 if (StopFlag) {
200 Value = BitFieldWrite8 (Value, Index, Index, 1);
201 } else {
202 Value = BitFieldWrite8 (Value, Index, Index, 0);
203 }
204 mDebugMpContext.CpuStopStatusMask[ProcessorIndex / 8] = Value;
205
206 ReleaseMpContextControl ();
207 }
208
209 /**
210 Set processor break flag bitmask in MP context.
211
212 @param[in] ProcessorIndex Processor index value.
213 @param[in] BreakFlag TRUE means set break flag.
214 FALSE means clean break flag.
215
216 **/
217 VOID
218 SetCpuBreakFlagByIndex (
219 IN UINT32 ProcessorIndex,
220 IN BOOLEAN BreakFlag
221 )
222 {
223 UINT8 Value;
224 UINTN Index;
225
226 AcquireMpContextControl ();
227
228 Value = mDebugMpContext.CpuBreakMask[ProcessorIndex / 8];
229 Index = ProcessorIndex % 8;
230 if (BreakFlag) {
231 Value = BitFieldWrite8 (Value, Index, Index, 1);
232 } else {
233 Value = BitFieldWrite8 (Value, Index, Index, 0);
234 }
235 mDebugMpContext.CpuBreakMask[ProcessorIndex / 8] = Value;
236
237 ReleaseMpContextControl ();
238 }
239
240 /**
241 Check if processor is stopped already.
242
243 @param[in] ProcessorIndex Processor index value.
244
245 @retval TRUE Processor is stopped already.
246 @retval TRUE Processor isn't stopped.
247
248 **/
249 BOOLEAN
250 IsCpuStopped (
251 IN UINT32 ProcessorIndex
252 )
253 {
254 UINT8 CpuMask;
255
256 CpuMask = (UINT8) (1 << (ProcessorIndex % 8));
257
258 if ((mDebugMpContext.CpuStopStatusMask[ProcessorIndex / 8] & CpuMask) != 0) {
259 return TRUE;
260 } else {
261 return FALSE;
262 }
263 }
264
265 /**
266 Set the run command flag.
267
268 @param[in] RunningFlag TRUE means run command flag is set.
269 FALSE means run command flag is cleared.
270
271 **/
272 VOID
273 SetCpuRunningFlag (
274 IN BOOLEAN RunningFlag
275 )
276 {
277 AcquireMpContextControl ();
278
279 mDebugMpContext.RunCommandSet = RunningFlag;
280
281 ReleaseMpContextControl ();
282 }
283
284 /**
285 Set the current view point to be debugged.
286
287 @param[in] ProcessorIndex Processor index value.
288
289 **/
290 VOID
291 SetDebugViewPoint (
292 IN UINT32 ProcessorIndex
293 )
294 {
295 AcquireMpContextControl ();
296
297 mDebugMpContext.ViewPointIndex = ProcessorIndex;
298
299 ReleaseMpContextControl ();
300 }
301
302 /**
303 Initialize debug timer.
304
305 @param[in] IpiSentByApFlag TRUE means this IPI is sent by AP.
306 FALSE means this IPI is sent by BSP.
307
308 **/
309 VOID
310 SetIpiSentByApFlag (
311 IN BOOLEAN IpiSentByApFlag
312 )
313 {
314 AcquireMpContextControl ();
315
316 mDebugMpContext.IpiSentByAp = IpiSentByApFlag;
317
318 ReleaseMpContextControl ();
319 }
320
321 /**
322 Check if any processor breaks.
323
324 @retval others There is at least one processor broken, the minimum
325 index number of Processor returned.
326 @retval -1 No any processor broken.
327
328 **/
329 UINT32
330 FindCpuNotRunning (
331 VOID
332 )
333 {
334 UINT32 Index;
335
336 for (Index = 0; Index < DEBUG_CPU_MAX_COUNT / 8; Index ++) {
337 if (mDebugMpContext.CpuBreakMask[Index] != 0) {
338 return (UINT32) LowBitSet32 (mDebugMpContext.CpuBreakMask[Index]) + Index * 8;
339 }
340 }
341 return (UINT32)-1;
342 }
343
344 /**
345 Check if all processors are in running status.
346
347 @retval TRUE All processors run.
348 @retval FALSE At least one processor does not run.
349
350 **/
351 BOOLEAN
352 IsAllCpuRunning (
353 VOID
354 )
355 {
356 UINTN Index;
357
358 for (Index = 0; Index < DEBUG_CPU_MAX_COUNT / 8; Index ++) {
359 if (mDebugMpContext.CpuStopStatusMask[Index] != 0) {
360 return FALSE;
361 }
362 }
363 return TRUE;
364 }
365