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