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