]> git.proxmox.com Git - mirror_edk2.git/blame - SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/DebugMp.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[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
85f7e110 5 SPDX-License-Identifier: BSD-2-Clause-Patent\r
18b144ea 6\r
7**/\r
8\r
9#include "DebugAgent.h"\r
10\r
c1e126b1 11GLOBAL_REMOVE_IF_UNREFERENCED DEBUG_MP_CONTEXT volatile mDebugMpContext = { 0, 0, 0, { 0 }, { 0 }, 0, 0, 0, 0, FALSE, FALSE };\r
18b144ea 12\r
c1e126b1 13GLOBAL_REMOVE_IF_UNREFERENCED DEBUG_CPU_DATA volatile mDebugCpuData = { 0 };\r
18b144ea 14\r
15/**\r
b422b62c 16 Acquire a spin lock when Multi-processor supported.\r
18b144ea 17\r
18 It will block in the function if cannot get the access control.\r
b422b62c 19 If Multi-processor is not supported, return directly.\r
20\r
21 @param[in, out] MpSpinLock A pointer to the spin lock.\r
18b144ea 22\r
23**/\r
24VOID\r
b422b62c 25AcquireMpSpinLock (\r
c1e126b1 26 IN OUT SPIN_LOCK *MpSpinLock\r
18b144ea 27 )\r
28{\r
c1e126b1 29 if (!MultiProcessorDebugSupport ()) {\r
18b144ea 30 return;\r
31 }\r
32\r
33 while (TRUE) {\r
b422b62c 34 if (AcquireSpinLockOrFail (MpSpinLock)) {\r
18b144ea 35 break;\r
36 }\r
c1e126b1 37\r
18b144ea 38 CpuPause ();\r
39 continue;\r
40 }\r
41}\r
42\r
43/**\r
b422b62c 44 Release a spin lock when Multi-processor supported.\r
18b144ea 45\r
b422b62c 46 @param[in, out] MpSpinLock A pointer to the spin lock.\r
18b144ea 47\r
48**/\r
49VOID\r
b422b62c 50ReleaseMpSpinLock (\r
c1e126b1 51 IN OUT SPIN_LOCK *MpSpinLock\r
18b144ea 52 )\r
53{\r
c1e126b1 54 if (!MultiProcessorDebugSupport ()) {\r
b422b62c 55 return;\r
18b144ea 56 }\r
18b144ea 57\r
b422b62c 58 ReleaseSpinLock (MpSpinLock);\r
18b144ea 59}\r
60\r
61/**\r
62 Break the other processor by send IPI.\r
63\r
64 @param[in] CurrentProcessorIndex Current processor index value.\r
65\r
66**/\r
67VOID\r
68HaltOtherProcessors (\r
c1e126b1 69 IN UINT32 CurrentProcessorIndex\r
18b144ea 70 )\r
71{\r
93c0bdec 72 DebugAgentMsgPrint (DEBUG_AGENT_INFO, "processor[%x]:Try to halt other processors.\n", CurrentProcessorIndex);\r
a2acb04c 73 if (!DebugAgentIsBsp (CurrentProcessorIndex)) {\r
c1e126b1 74 SetIpiSentByApFlag (TRUE);\r
18b144ea 75 }\r
76\r
77 mDebugMpContext.BreakAtCpuIndex = CurrentProcessorIndex;\r
78\r
28c6c878 79 //\r
80 // Set the debug viewpoint to the current breaking CPU.\r
81 //\r
82 SetDebugViewPoint (CurrentProcessorIndex);\r
83\r
18b144ea 84 //\r
85 // Send fixed IPI to other processors.\r
86 //\r
87 SendFixedIpiAllExcludingSelf (DEBUG_TIMER_VECTOR);\r
18b144ea 88}\r
89\r
90/**\r
91 Get the current processor's index.\r
92\r
93 @return Processor index value.\r
94\r
95**/\r
96UINT32\r
97GetProcessorIndex (\r
98 VOID\r
99 )\r
100{\r
c1e126b1
MK
101 UINT32 Index;\r
102 UINT16 LocalApicID;\r
18b144ea 103\r
c1e126b1 104 LocalApicID = (UINT16)GetApicId ();\r
18b144ea 105\r
b422b62c 106 AcquireMpSpinLock (&mDebugMpContext.MpContextSpinLock);\r
18b144ea 107\r
c1e126b1 108 for (Index = 0; Index < mDebugCpuData.CpuCount; Index++) {\r
18b144ea 109 if (mDebugCpuData.ApicID[Index] == LocalApicID) {\r
110 break;\r
111 }\r
112 }\r
113\r
114 if (Index == mDebugCpuData.CpuCount) {\r
115 mDebugCpuData.ApicID[Index] = LocalApicID;\r
c1e126b1 116 mDebugCpuData.CpuCount++;\r
18b144ea 117 }\r
118\r
b422b62c 119 ReleaseMpSpinLock (&mDebugMpContext.MpContextSpinLock);\r
18b144ea 120\r
121 return Index;\r
122}\r
123\r
124/**\r
125 Check if the specified processor is BSP or not.\r
126\r
127 @param[in] ProcessorIndex Processor index value.\r
128\r
129 @retval TRUE It is BSP.\r
130 @retval FALSE It isn't BSP.\r
131\r
132**/\r
133BOOLEAN\r
a2acb04c 134DebugAgentIsBsp (\r
d5203c10 135 IN UINT32 ProcessorIndex\r
18b144ea 136 )\r
137{\r
a742e186 138 MSR_IA32_APIC_BASE_REGISTER MsrApicBase;\r
77695f4d 139\r
d5203c10
MK
140 //\r
141 // If there are less than 2 CPUs detected, then the currently executing CPU\r
77695f4d 142 // must be the BSP. This avoids an access to an MSR that may not be supported\r
d5203c10
MK
143 // on single core CPUs.\r
144 //\r
145 if (mDebugCpuData.CpuCount < 2) {\r
146 return TRUE;\r
147 }\r
148\r
a742e186
JF
149 MsrApicBase.Uint64 = AsmReadMsr64 (MSR_IA32_APIC_BASE);\r
150 if (MsrApicBase.Bits.BSP == 1) {\r
18b144ea 151 if (mDebugMpContext.BspIndex != ProcessorIndex) {\r
b422b62c 152 AcquireMpSpinLock (&mDebugMpContext.MpContextSpinLock);\r
18b144ea 153 mDebugMpContext.BspIndex = ProcessorIndex;\r
b422b62c 154 ReleaseMpSpinLock (&mDebugMpContext.MpContextSpinLock);\r
18b144ea 155 }\r
c1e126b1 156\r
18b144ea 157 return TRUE;\r
158 } else {\r
159 return FALSE;\r
160 }\r
161}\r
162\r
163/**\r
164 Set processor stop flag bitmask in MP context.\r
165\r
166 @param[in] ProcessorIndex Processor index value.\r
167 @param[in] StopFlag TRUE means set stop flag.\r
168 FALSE means clean break flag.\r
169\r
170**/\r
171VOID\r
172SetCpuStopFlagByIndex (\r
c1e126b1
MK
173 IN UINT32 ProcessorIndex,\r
174 IN BOOLEAN StopFlag\r
18b144ea 175 )\r
176{\r
c1e126b1
MK
177 UINT8 Value;\r
178 UINTN Index;\r
18b144ea 179\r
b422b62c 180 AcquireMpSpinLock (&mDebugMpContext.MpContextSpinLock);\r
18b144ea 181\r
182 Value = mDebugMpContext.CpuStopStatusMask[ProcessorIndex / 8];\r
183 Index = ProcessorIndex % 8;\r
184 if (StopFlag) {\r
185 Value = BitFieldWrite8 (Value, Index, Index, 1);\r
186 } else {\r
187 Value = BitFieldWrite8 (Value, Index, Index, 0);\r
188 }\r
c1e126b1 189\r
18b144ea 190 mDebugMpContext.CpuStopStatusMask[ProcessorIndex / 8] = Value;\r
191\r
b422b62c 192 ReleaseMpSpinLock (&mDebugMpContext.MpContextSpinLock);\r
18b144ea 193}\r
194\r
195/**\r
196 Set processor break flag bitmask in MP context.\r
197\r
198 @param[in] ProcessorIndex Processor index value.\r
199 @param[in] BreakFlag TRUE means set break flag.\r
200 FALSE means clean break flag.\r
201\r
202**/\r
203VOID\r
204SetCpuBreakFlagByIndex (\r
c1e126b1
MK
205 IN UINT32 ProcessorIndex,\r
206 IN BOOLEAN BreakFlag\r
18b144ea 207 )\r
208{\r
c1e126b1
MK
209 UINT8 Value;\r
210 UINTN Index;\r
18b144ea 211\r
b422b62c 212 AcquireMpSpinLock (&mDebugMpContext.MpContextSpinLock);\r
18b144ea 213\r
214 Value = mDebugMpContext.CpuBreakMask[ProcessorIndex / 8];\r
215 Index = ProcessorIndex % 8;\r
216 if (BreakFlag) {\r
217 Value = BitFieldWrite8 (Value, Index, Index, 1);\r
218 } else {\r
219 Value = BitFieldWrite8 (Value, Index, Index, 0);\r
220 }\r
c1e126b1 221\r
18b144ea 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
c1e126b1 238 IN UINT32 ProcessorIndex\r
18b144ea 239 )\r
240{\r
c1e126b1 241 UINT8 CpuMask;\r
18b144ea 242\r
c1e126b1 243 CpuMask = (UINT8)(1 << (ProcessorIndex % 8));\r
18b144ea 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
c1e126b1 261 IN BOOLEAN RunningFlag\r
18b144ea 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
c1e126b1 277 IN UINT32 ProcessorIndex\r
18b144ea 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
c1e126b1 294 IN BOOLEAN IpiSentByApFlag\r
18b144ea 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
c1e126b1 315 UINT32 Index;\r
4fe43eb3 316\r
c1e126b1 317 for (Index = 0; Index < DEBUG_CPU_MAX_COUNT / 8; Index++) {\r
18b144ea 318 if (mDebugMpContext.CpuBreakMask[Index] != 0) {\r
c1e126b1 319 return (UINT32)LowBitSet32 (mDebugMpContext.CpuBreakMask[Index]) + Index * 8;\r
18b144ea 320 }\r
321 }\r
c1e126b1 322\r
18b144ea 323 return (UINT32)-1;\r
324}\r
4fe43eb3 325\r
18b144ea 326/**\r
327 Check if all processors are in running status.\r
328\r
329 @retval TRUE All processors run.\r
330 @retval FALSE At least one processor does not run.\r
331\r
332**/\r
333BOOLEAN\r
334IsAllCpuRunning (\r
335 VOID\r
336 )\r
337{\r
c1e126b1 338 UINTN Index;\r
4fe43eb3 339\r
c1e126b1 340 for (Index = 0; Index < DEBUG_CPU_MAX_COUNT / 8; Index++) {\r
18b144ea 341 if (mDebugMpContext.CpuStopStatusMask[Index] != 0) {\r
342 return FALSE;\r
343 }\r
344 }\r
c1e126b1 345\r
18b144ea 346 return TRUE;\r
347}\r
348\r
93c0bdec 349/**\r
350 Check if the current processor is the first breaking processor.\r
351\r
4fe43eb3
JF
352 If yes, halt other processors.\r
353\r
93c0bdec 354 @param[in] ProcessorIndex Processor index value.\r
4fe43eb3 355\r
93c0bdec 356 @return TRUE This processor is the first breaking processor.\r
357 @return FALSE This processor is not the first breaking processor.\r
4fe43eb3 358\r
93c0bdec 359**/\r
360BOOLEAN\r
361IsFirstBreakProcessor (\r
c1e126b1 362 IN UINT32 ProcessorIndex\r
93c0bdec 363 )\r
364{\r
c1e126b1
MK
365 if (MultiProcessorDebugSupport ()) {\r
366 if (mDebugMpContext.BreakAtCpuIndex != (UINT32)-1) {\r
93c0bdec 367 //\r
368 // The current processor is not the first breaking one.\r
369 //\r
370 SetCpuBreakFlagByIndex (ProcessorIndex, TRUE);\r
371 return FALSE;\r
372 } else {\r
373 //\r
374 // If no any processor breaks, try to halt other processors\r
375 //\r
376 HaltOtherProcessors (ProcessorIndex);\r
377 return TRUE;\r
378 }\r
379 }\r
c1e126b1 380\r
93c0bdec 381 return TRUE;\r
4fe43eb3 382}\r