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