]> git.proxmox.com Git - mirror_edk2.git/blame - SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/DebugMp.c
EDK II Contributions.txt: Update patch format information
[mirror_edk2.git] / SourceLevelDebugPkg / Library / DebugAgent / DebugAgentCommon / DebugMp.c
CommitLineData
18b144ea 1/** @file\r
2 Multi-Processor support functions implementation.\r
3\r
b422b62c 4 Copyright (c) 2010 - 2013, 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
b422b62c 17DEBUG_MP_CONTEXT volatile mDebugMpContext = {0,0,0,{0},{0},0,0,0,0,FALSE,FALSE};\r
18b144ea 18\r
19DEBUG_CPU_DATA volatile mDebugCpuData = {0};\r
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
18b144ea 78 if (!IsBsp (CurrentProcessorIndex)) {\r
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
93 \r
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
140IsBsp (\r
141 IN UINT32 ProcessorIndex\r
142 )\r
143{\r
144 if (AsmMsrBitFieldRead64 (MSR_IA32_APIC_BASE_ADDRESS, 8, 8) == 1) {\r
145 if (mDebugMpContext.BspIndex != ProcessorIndex) {\r
b422b62c 146 AcquireMpSpinLock (&mDebugMpContext.MpContextSpinLock);\r
18b144ea 147 mDebugMpContext.BspIndex = ProcessorIndex;\r
b422b62c 148 ReleaseMpSpinLock (&mDebugMpContext.MpContextSpinLock);\r
18b144ea 149 }\r
150 return TRUE;\r
151 } else {\r
152 return FALSE;\r
153 }\r
154}\r
155\r
156/**\r
157 Set processor stop flag bitmask in MP context.\r
158\r
159 @param[in] ProcessorIndex Processor index value.\r
160 @param[in] StopFlag TRUE means set stop flag.\r
161 FALSE means clean break flag.\r
162\r
163**/\r
164VOID\r
165SetCpuStopFlagByIndex (\r
166 IN UINT32 ProcessorIndex,\r
167 IN BOOLEAN StopFlag\r
168 )\r
169{\r
170 UINT8 Value;\r
171 UINTN Index;\r
172\r
b422b62c 173 AcquireMpSpinLock (&mDebugMpContext.MpContextSpinLock);\r
18b144ea 174\r
175 Value = mDebugMpContext.CpuStopStatusMask[ProcessorIndex / 8];\r
176 Index = ProcessorIndex % 8;\r
177 if (StopFlag) {\r
178 Value = BitFieldWrite8 (Value, Index, Index, 1);\r
179 } else {\r
180 Value = BitFieldWrite8 (Value, Index, Index, 0);\r
181 }\r
182 mDebugMpContext.CpuStopStatusMask[ProcessorIndex / 8] = Value;\r
183\r
b422b62c 184 ReleaseMpSpinLock (&mDebugMpContext.MpContextSpinLock);\r
18b144ea 185}\r
186\r
187/**\r
188 Set processor break flag bitmask in MP context.\r
189\r
190 @param[in] ProcessorIndex Processor index value.\r
191 @param[in] BreakFlag TRUE means set break flag.\r
192 FALSE means clean break flag.\r
193\r
194**/\r
195VOID\r
196SetCpuBreakFlagByIndex (\r
197 IN UINT32 ProcessorIndex,\r
198 IN BOOLEAN BreakFlag\r
199 )\r
200{\r
201 UINT8 Value;\r
202 UINTN Index;\r
203\r
b422b62c 204 AcquireMpSpinLock (&mDebugMpContext.MpContextSpinLock);\r
18b144ea 205\r
206 Value = mDebugMpContext.CpuBreakMask[ProcessorIndex / 8];\r
207 Index = ProcessorIndex % 8;\r
208 if (BreakFlag) {\r
209 Value = BitFieldWrite8 (Value, Index, Index, 1);\r
210 } else {\r
211 Value = BitFieldWrite8 (Value, Index, Index, 0);\r
212 }\r
213 mDebugMpContext.CpuBreakMask[ProcessorIndex / 8] = Value;\r
214\r
b422b62c 215 ReleaseMpSpinLock (&mDebugMpContext.MpContextSpinLock);\r
18b144ea 216}\r
217\r
218/**\r
219 Check if processor is stopped already.\r
220\r
221 @param[in] ProcessorIndex Processor index value.\r
222\r
223 @retval TRUE Processor is stopped already.\r
224 @retval TRUE Processor isn't stopped.\r
225\r
226**/\r
227BOOLEAN\r
228IsCpuStopped (\r
229 IN UINT32 ProcessorIndex\r
230 )\r
231{\r
232 UINT8 CpuMask;\r
233\r
234 CpuMask = (UINT8) (1 << (ProcessorIndex % 8));\r
235\r
236 if ((mDebugMpContext.CpuStopStatusMask[ProcessorIndex / 8] & CpuMask) != 0) {\r
237 return TRUE;\r
238 } else {\r
239 return FALSE;\r
240 }\r
241}\r
242\r
243/**\r
244 Set the run command flag.\r
245\r
246 @param[in] RunningFlag TRUE means run command flag is set.\r
247 FALSE means run command flag is cleared.\r
248\r
249**/\r
250VOID\r
251SetCpuRunningFlag (\r
252 IN BOOLEAN RunningFlag\r
253 )\r
254{\r
b422b62c 255 AcquireMpSpinLock (&mDebugMpContext.MpContextSpinLock);\r
18b144ea 256 mDebugMpContext.RunCommandSet = RunningFlag;\r
b422b62c 257 ReleaseMpSpinLock (&mDebugMpContext.MpContextSpinLock);\r
18b144ea 258}\r
259\r
260/**\r
261 Set the current view point to be debugged.\r
262\r
263 @param[in] ProcessorIndex Processor index value.\r
264\r
265**/\r
266VOID\r
267SetDebugViewPoint (\r
268 IN UINT32 ProcessorIndex\r
269 )\r
270{\r
b422b62c 271 AcquireMpSpinLock (&mDebugMpContext.MpContextSpinLock);\r
18b144ea 272 mDebugMpContext.ViewPointIndex = ProcessorIndex;\r
b422b62c 273 ReleaseMpSpinLock (&mDebugMpContext.MpContextSpinLock);\r
18b144ea 274}\r
275\r
276/**\r
93c0bdec 277 Set the IPI send by BPS/AP flag.\r
18b144ea 278\r
279 @param[in] IpiSentByApFlag TRUE means this IPI is sent by AP.\r
280 FALSE means this IPI is sent by BSP.\r
281\r
282**/\r
283VOID\r
284SetIpiSentByApFlag (\r
285 IN BOOLEAN IpiSentByApFlag\r
286 )\r
287{\r
b422b62c 288 AcquireMpSpinLock (&mDebugMpContext.MpContextSpinLock);\r
18b144ea 289 mDebugMpContext.IpiSentByAp = IpiSentByApFlag;\r
b422b62c 290 ReleaseMpSpinLock (&mDebugMpContext.MpContextSpinLock);\r
18b144ea 291}\r
292\r
293/**\r
93c0bdec 294 Check the next pending breaking CPU.\r
18b144ea 295\r
296 @retval others There is at least one processor broken, the minimum\r
297 index number of Processor returned.\r
298 @retval -1 No any processor broken.\r
299\r
300**/\r
301UINT32\r
93c0bdec 302FindNextPendingBreakCpu (\r
18b144ea 303 VOID\r
304 )\r
305{\r
306 UINT32 Index;\r
307 \r
308 for (Index = 0; Index < DEBUG_CPU_MAX_COUNT / 8; Index ++) {\r
309 if (mDebugMpContext.CpuBreakMask[Index] != 0) {\r
310 return (UINT32) LowBitSet32 (mDebugMpContext.CpuBreakMask[Index]) + Index * 8;\r
311 }\r
312 }\r
313 return (UINT32)-1;\r
314}\r
315 \r
316/**\r
317 Check if all processors are in running status.\r
318\r
319 @retval TRUE All processors run.\r
320 @retval FALSE At least one processor does not run.\r
321\r
322**/\r
323BOOLEAN\r
324IsAllCpuRunning (\r
325 VOID\r
326 )\r
327{\r
328 UINTN Index;\r
329 \r
330 for (Index = 0; Index < DEBUG_CPU_MAX_COUNT / 8; Index ++) {\r
331 if (mDebugMpContext.CpuStopStatusMask[Index] != 0) {\r
332 return FALSE;\r
333 }\r
334 }\r
335 return TRUE;\r
336}\r
337\r
93c0bdec 338/**\r
339 Check if the current processor is the first breaking processor.\r
340\r
341 If yes, halt other processors. \r
342 \r
343 @param[in] ProcessorIndex Processor index value.\r
344 \r
345 @return TRUE This processor is the first breaking processor.\r
346 @return FALSE This processor is not the first breaking processor.\r
347 \r
348**/\r
349BOOLEAN\r
350IsFirstBreakProcessor (\r
351 IN UINT32 ProcessorIndex\r
352 )\r
353{\r
b422b62c 354 if (MultiProcessorDebugSupport()) {\r
93c0bdec 355 if (mDebugMpContext.BreakAtCpuIndex != (UINT32) -1) {\r
356 //\r
357 // The current processor is not the first breaking one.\r
358 //\r
359 SetCpuBreakFlagByIndex (ProcessorIndex, TRUE);\r
360 return FALSE;\r
361 } else {\r
362 //\r
363 // If no any processor breaks, try to halt other processors\r
364 //\r
365 HaltOtherProcessors (ProcessorIndex);\r
366 return TRUE;\r
367 }\r
368 }\r
369 return TRUE;\r
370} \r
371\r