]> git.proxmox.com Git - mirror_edk2.git/blame - SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/DebugMp.c
SourceLevelDebugPkg DebugAgentLib: Rename IsBsp to DebugAgentIsBsp
[mirror_edk2.git] / SourceLevelDebugPkg / Library / DebugAgent / DebugAgentCommon / DebugMp.c
CommitLineData
18b144ea 1/** @file\r
2 Multi-Processor support functions implementation.\r
3\r
a2acb04c 4 Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.<BR>\r
18b144ea 5 This program and the accompanying materials\r
6 are licensed and made available under the terms and conditions of the BSD License\r
7 which accompanies this distribution. The full text of the license may be found at\r
8 http://opensource.org/licenses/bsd-license.php.\r
9\r
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
13**/\r
14\r
15#include "DebugAgent.h"\r
16\r
4fe43eb3 17GLOBAL_REMOVE_IF_UNREFERENCED DEBUG_MP_CONTEXT volatile mDebugMpContext = {0,0,0,{0},{0},0,0,0,0,FALSE,FALSE};\r
18b144ea 18\r
4fe43eb3 19GLOBAL_REMOVE_IF_UNREFERENCED DEBUG_CPU_DATA volatile mDebugCpuData = {0};\r
18b144ea 20\r
21/**\r
b422b62c 22 Acquire a spin lock when Multi-processor supported.\r
18b144ea 23\r
24 It will block in the function if cannot get the access control.\r
b422b62c 25 If Multi-processor is not supported, return directly.\r
26\r
27 @param[in, out] MpSpinLock A pointer to the spin lock.\r
18b144ea 28\r
29**/\r
30VOID\r
b422b62c 31AcquireMpSpinLock (\r
32 IN OUT SPIN_LOCK *MpSpinLock\r
18b144ea 33 )\r
34{\r
b422b62c 35 if (!MultiProcessorDebugSupport()) {\r
18b144ea 36 return;\r
37 }\r
38\r
39 while (TRUE) {\r
b422b62c 40 if (AcquireSpinLockOrFail (MpSpinLock)) {\r
18b144ea 41 break;\r
42 }\r
43 CpuPause ();\r
44 continue;\r
45 }\r
46}\r
47\r
48/**\r
b422b62c 49 Release a spin lock when Multi-processor supported.\r
18b144ea 50\r
b422b62c 51 @param[in, out] MpSpinLock A pointer to the spin lock.\r
18b144ea 52\r
53**/\r
54VOID\r
b422b62c 55ReleaseMpSpinLock (\r
56 IN OUT SPIN_LOCK *MpSpinLock\r
18b144ea 57 )\r
58{\r
b422b62c 59 if (!MultiProcessorDebugSupport()) {\r
60 return;\r
18b144ea 61 }\r
18b144ea 62\r
b422b62c 63 ReleaseSpinLock (MpSpinLock);\r
18b144ea 64}\r
65\r
66/**\r
67 Break the other processor by send IPI.\r
68\r
69 @param[in] CurrentProcessorIndex Current processor index value.\r
70\r
71**/\r
72VOID\r
73HaltOtherProcessors (\r
74 IN UINT32 CurrentProcessorIndex\r
75 )\r
76{\r
93c0bdec 77 DebugAgentMsgPrint (DEBUG_AGENT_INFO, "processor[%x]:Try to halt other processors.\n", CurrentProcessorIndex);\r
a2acb04c 78 if (!DebugAgentIsBsp (CurrentProcessorIndex)) {\r
18b144ea 79 SetIpiSentByApFlag (TRUE);;\r
80 }\r
81\r
82 mDebugMpContext.BreakAtCpuIndex = CurrentProcessorIndex;\r
83\r
28c6c878 84 //\r
85 // Set the debug viewpoint to the current breaking CPU.\r
86 //\r
87 SetDebugViewPoint (CurrentProcessorIndex);\r
88\r
18b144ea 89 //\r
90 // Send fixed IPI to other processors.\r
91 //\r
92 SendFixedIpiAllExcludingSelf (DEBUG_TIMER_VECTOR);\r
4fe43eb3 93\r
18b144ea 94}\r
95\r
96/**\r
97 Get the current processor's index.\r
98\r
99 @return Processor index value.\r
100\r
101**/\r
102UINT32\r
103GetProcessorIndex (\r
104 VOID\r
105 )\r
106{\r
107 UINT32 Index;\r
108 UINT16 LocalApicID;\r
109\r
110 LocalApicID = (UINT16) GetApicId ();\r
111\r
b422b62c 112 AcquireMpSpinLock (&mDebugMpContext.MpContextSpinLock);\r
18b144ea 113\r
114 for (Index = 0; Index < mDebugCpuData.CpuCount; Index ++) {\r
115 if (mDebugCpuData.ApicID[Index] == LocalApicID) {\r
116 break;\r
117 }\r
118 }\r
119\r
120 if (Index == mDebugCpuData.CpuCount) {\r
121 mDebugCpuData.ApicID[Index] = LocalApicID;\r
122 mDebugCpuData.CpuCount ++ ;\r
123 }\r
124\r
b422b62c 125 ReleaseMpSpinLock (&mDebugMpContext.MpContextSpinLock);\r
18b144ea 126\r
127 return Index;\r
128}\r
129\r
130/**\r
131 Check if the specified processor is BSP or not.\r
132\r
133 @param[in] ProcessorIndex Processor index value.\r
134\r
135 @retval TRUE It is BSP.\r
136 @retval FALSE It isn't BSP.\r
137\r
138**/\r
139BOOLEAN\r
a2acb04c 140DebugAgentIsBsp (\r
d5203c10 141 IN UINT32 ProcessorIndex\r
18b144ea 142 )\r
143{\r
a742e186
JF
144 MSR_IA32_APIC_BASE_REGISTER MsrApicBase;\r
145 \r
d5203c10
MK
146 //\r
147 // If there are less than 2 CPUs detected, then the currently executing CPU\r
148 // must be the BSP. This avoids an access to an MSR that may not be supported \r
149 // on single core CPUs.\r
150 //\r
151 if (mDebugCpuData.CpuCount < 2) {\r
152 return TRUE;\r
153 }\r
154\r
a742e186
JF
155 MsrApicBase.Uint64 = AsmReadMsr64 (MSR_IA32_APIC_BASE);\r
156 if (MsrApicBase.Bits.BSP == 1) {\r
18b144ea 157 if (mDebugMpContext.BspIndex != ProcessorIndex) {\r
b422b62c 158 AcquireMpSpinLock (&mDebugMpContext.MpContextSpinLock);\r
18b144ea 159 mDebugMpContext.BspIndex = ProcessorIndex;\r
b422b62c 160 ReleaseMpSpinLock (&mDebugMpContext.MpContextSpinLock);\r
18b144ea 161 }\r
162 return TRUE;\r
163 } else {\r
164 return FALSE;\r
165 }\r
166}\r
167\r
168/**\r
169 Set processor stop flag bitmask in MP context.\r
170\r
171 @param[in] ProcessorIndex Processor index value.\r
172 @param[in] StopFlag TRUE means set stop flag.\r
173 FALSE means clean break flag.\r
174\r
175**/\r
176VOID\r
177SetCpuStopFlagByIndex (\r
178 IN UINT32 ProcessorIndex,\r
179 IN BOOLEAN StopFlag\r
180 )\r
181{\r
182 UINT8 Value;\r
183 UINTN Index;\r
184\r
b422b62c 185 AcquireMpSpinLock (&mDebugMpContext.MpContextSpinLock);\r
18b144ea 186\r
187 Value = mDebugMpContext.CpuStopStatusMask[ProcessorIndex / 8];\r
188 Index = ProcessorIndex % 8;\r
189 if (StopFlag) {\r
190 Value = BitFieldWrite8 (Value, Index, Index, 1);\r
191 } else {\r
192 Value = BitFieldWrite8 (Value, Index, Index, 0);\r
193 }\r
194 mDebugMpContext.CpuStopStatusMask[ProcessorIndex / 8] = Value;\r
195\r
b422b62c 196 ReleaseMpSpinLock (&mDebugMpContext.MpContextSpinLock);\r
18b144ea 197}\r
198\r
199/**\r
200 Set processor break flag bitmask in MP context.\r
201\r
202 @param[in] ProcessorIndex Processor index value.\r
203 @param[in] BreakFlag TRUE means set break flag.\r
204 FALSE means clean break flag.\r
205\r
206**/\r
207VOID\r
208SetCpuBreakFlagByIndex (\r
209 IN UINT32 ProcessorIndex,\r
210 IN BOOLEAN BreakFlag\r
211 )\r
212{\r
213 UINT8 Value;\r
214 UINTN Index;\r
215\r
b422b62c 216 AcquireMpSpinLock (&mDebugMpContext.MpContextSpinLock);\r
18b144ea 217\r
218 Value = mDebugMpContext.CpuBreakMask[ProcessorIndex / 8];\r
219 Index = ProcessorIndex % 8;\r
220 if (BreakFlag) {\r
221 Value = BitFieldWrite8 (Value, Index, Index, 1);\r
222 } else {\r
223 Value = BitFieldWrite8 (Value, Index, Index, 0);\r
224 }\r
225 mDebugMpContext.CpuBreakMask[ProcessorIndex / 8] = Value;\r
226\r
b422b62c 227 ReleaseMpSpinLock (&mDebugMpContext.MpContextSpinLock);\r
18b144ea 228}\r
229\r
230/**\r
231 Check if processor is stopped already.\r
232\r
233 @param[in] ProcessorIndex Processor index value.\r
234\r
235 @retval TRUE Processor is stopped already.\r
236 @retval TRUE Processor isn't stopped.\r
237\r
238**/\r
239BOOLEAN\r
240IsCpuStopped (\r
241 IN UINT32 ProcessorIndex\r
242 )\r
243{\r
244 UINT8 CpuMask;\r
245\r
246 CpuMask = (UINT8) (1 << (ProcessorIndex % 8));\r
247\r
248 if ((mDebugMpContext.CpuStopStatusMask[ProcessorIndex / 8] & CpuMask) != 0) {\r
249 return TRUE;\r
250 } else {\r
251 return FALSE;\r
252 }\r
253}\r
254\r
255/**\r
256 Set the run command flag.\r
257\r
258 @param[in] RunningFlag TRUE means run command flag is set.\r
259 FALSE means run command flag is cleared.\r
260\r
261**/\r
262VOID\r
263SetCpuRunningFlag (\r
264 IN BOOLEAN RunningFlag\r
265 )\r
266{\r
b422b62c 267 AcquireMpSpinLock (&mDebugMpContext.MpContextSpinLock);\r
18b144ea 268 mDebugMpContext.RunCommandSet = RunningFlag;\r
b422b62c 269 ReleaseMpSpinLock (&mDebugMpContext.MpContextSpinLock);\r
18b144ea 270}\r
271\r
272/**\r
273 Set the current view point to be debugged.\r
274\r
275 @param[in] ProcessorIndex Processor index value.\r
276\r
277**/\r
278VOID\r
279SetDebugViewPoint (\r
280 IN UINT32 ProcessorIndex\r
281 )\r
282{\r
b422b62c 283 AcquireMpSpinLock (&mDebugMpContext.MpContextSpinLock);\r
18b144ea 284 mDebugMpContext.ViewPointIndex = ProcessorIndex;\r
b422b62c 285 ReleaseMpSpinLock (&mDebugMpContext.MpContextSpinLock);\r
18b144ea 286}\r
287\r
288/**\r
93c0bdec 289 Set the IPI send by BPS/AP flag.\r
18b144ea 290\r
291 @param[in] IpiSentByApFlag TRUE means this IPI is sent by AP.\r
292 FALSE means this IPI is sent by BSP.\r
293\r
294**/\r
295VOID\r
296SetIpiSentByApFlag (\r
297 IN BOOLEAN IpiSentByApFlag\r
298 )\r
299{\r
b422b62c 300 AcquireMpSpinLock (&mDebugMpContext.MpContextSpinLock);\r
18b144ea 301 mDebugMpContext.IpiSentByAp = IpiSentByApFlag;\r
b422b62c 302 ReleaseMpSpinLock (&mDebugMpContext.MpContextSpinLock);\r
18b144ea 303}\r
304\r
305/**\r
93c0bdec 306 Check the next pending breaking CPU.\r
18b144ea 307\r
308 @retval others There is at least one processor broken, the minimum\r
309 index number of Processor returned.\r
310 @retval -1 No any processor broken.\r
311\r
312**/\r
313UINT32\r
93c0bdec 314FindNextPendingBreakCpu (\r
18b144ea 315 VOID\r
316 )\r
317{\r
318 UINT32 Index;\r
4fe43eb3 319\r
18b144ea 320 for (Index = 0; Index < DEBUG_CPU_MAX_COUNT / 8; Index ++) {\r
321 if (mDebugMpContext.CpuBreakMask[Index] != 0) {\r
322 return (UINT32) LowBitSet32 (mDebugMpContext.CpuBreakMask[Index]) + Index * 8;\r
323 }\r
324 }\r
325 return (UINT32)-1;\r
326}\r
4fe43eb3 327\r
18b144ea 328/**\r
329 Check if all processors are in running status.\r
330\r
331 @retval TRUE All processors run.\r
332 @retval FALSE At least one processor does not run.\r
333\r
334**/\r
335BOOLEAN\r
336IsAllCpuRunning (\r
337 VOID\r
338 )\r
339{\r
340 UINTN Index;\r
4fe43eb3 341\r
18b144ea 342 for (Index = 0; Index < DEBUG_CPU_MAX_COUNT / 8; Index ++) {\r
343 if (mDebugMpContext.CpuStopStatusMask[Index] != 0) {\r
344 return FALSE;\r
345 }\r
346 }\r
347 return TRUE;\r
348}\r
349\r
93c0bdec 350/**\r
351 Check if the current processor is the first breaking processor.\r
352\r
4fe43eb3
JF
353 If yes, halt other processors.\r
354\r
93c0bdec 355 @param[in] ProcessorIndex Processor index value.\r
4fe43eb3 356\r
93c0bdec 357 @return TRUE This processor is the first breaking processor.\r
358 @return FALSE This processor is not the first breaking processor.\r
4fe43eb3 359\r
93c0bdec 360**/\r
361BOOLEAN\r
362IsFirstBreakProcessor (\r
363 IN UINT32 ProcessorIndex\r
364 )\r
365{\r
b422b62c 366 if (MultiProcessorDebugSupport()) {\r
93c0bdec 367 if (mDebugMpContext.BreakAtCpuIndex != (UINT32) -1) {\r
368 //\r
369 // The current processor is not the first breaking one.\r
370 //\r
371 SetCpuBreakFlagByIndex (ProcessorIndex, TRUE);\r
372 return FALSE;\r
373 } else {\r
374 //\r
375 // If no any processor breaks, try to halt other processors\r
376 //\r
377 HaltOtherProcessors (ProcessorIndex);\r
378 return TRUE;\r
379 }\r
380 }\r
381 return TRUE;\r
4fe43eb3 382}\r
93c0bdec 383\r