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