1 /** @file
2 Include file for PI MP Services Protocol Thunk.
3 
4 Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution.  The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9 
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12 Module Name:
13 
14 **/
15 
16 #ifndef _MP_SERVICES_ON_FRAMEWORK_MP_SERVICES_THUNK_
17 #define _MP_SERVICES_ON_FRAMEWORK_MP_SERVICES_THUNK_
18 
19 #include <Protocol/MpService.h>
20 #include <Protocol/FrameworkMpService.h>
21 #include <Protocol/GenericMemoryTest.h>
22 
23 #include <Library/BaseLib.h>
24 #include <Library/SynchronizationLib.h>
25 #include <Library/DebugLib.h>
26 #include <Library/UefiLib.h>
27 #include <Library/BaseMemoryLib.h>
28 #include <Library/UefiDriverEntryPoint.h>
29 #include <Library/MemoryAllocationLib.h>
30 #include <Library/UefiBootServicesTableLib.h>
31 #include <Library/DxeServicesTableLib.h>
32 #include <Library/IoLib.h>
33 #include <Library/TimerLib.h>
34 #include <Library/DebugAgentLib.h>
35 #include <Library/LocalApicLib.h>
36 
37 #define AP_STACK_SIZE                         0x8000
38 #define MAX_CPU_NUMBER                        256
39 
40 //
41 // Bit definition for IPI
42 //
43 #define BROADCAST_MODE_ALL_EXCLUDING_SELF_BIT  0xC0000
44 #define SPECIFY_CPU_MODE_BIT                   0x00000
45 #define TRIGGER_MODE_LEVEL_BIT                 0x08000
46 #define ASSERT_BIT                             0x04000
47 
48 //
49 // Local APIC register definition for IPI.
50 //
51 #define APIC_REGISTER_SPURIOUS_VECTOR_OFFSET  0xF0
52 #define APIC_REGISTER_ICR_LOW_OFFSET          0x300
53 #define APIC_REGISTER_ICR_HIGH_OFFSET         0x310
54 #define APIC_REGISTER_LVT_TIMER               0x320
55 #define APIC_REGISTER_TIMER_INIT_COUNT        0x380
56 #define APIC_REGISTER_LINT0_VECTOR_OFFSET     0x350
57 #define APIC_REGISTER_LINT1_VECTOR_OFFSET     0x360
58 #define APIC_REGISTER_TIMER_COUNT             0x390
59 #define APIC_REGISTER_TIMER_DIVIDE            0x3E0
60 
61 //
62 // Definition for MSR address
63 //
64 #define MSR_IA32_TIME_STAMP_COUNTER           0x10
65 #define MSR_IA32_APIC_BASE                    0x1B
66 
67 typedef struct {
68   UINTN             Lock;
69   VOID              *StackStart;
70   UINTN             StackSize;
71   VOID              *ApFunction;
72   IA32_DESCRIPTOR   GdtrProfile;
73   IA32_DESCRIPTOR   IdtrProfile;
74   UINT32            BufferStart;
75   UINT32            Cr3;
76   UINT32            ProcessorNumber[MAX_CPU_NUMBER];
77 } MP_CPU_EXCHANGE_INFO;
78 
79 typedef struct {
80   UINT8 *RendezvousFunnelAddress;
81   UINTN PModeEntryOffset;
82   UINTN FlatJumpOffset;
83   UINTN LModeEntryOffset;
84   UINTN LongJumpOffset;
85   UINTN Size;
86 } MP_ASSEMBLY_ADDRESS_MAP;
87 
88 typedef enum {
89   CpuStateIdle,
90   CpuStateReady,
91   CpuStateBusy,
92   CpuStateFinished,
93   CpuStateDisabled
94 } CPU_STATE;
95 
96 //
97 // Define Individual Processor Data block.
98 //
99 typedef struct {
100   EFI_AP_PROCEDURE volatile      Procedure;
101   VOID* volatile                 Parameter;
102 
103   EFI_EVENT                      WaitEvent;
104   BOOLEAN                        *Finished;
105   UINT64                         ExpectedTime;
106   UINT64                         CurrentTime;
107   UINT64                         TotalTime;
108 
109   SPIN_LOCK                      CpuDataLock;
110   CPU_STATE volatile             State;
111 
112 } CPU_DATA_BLOCK;
113 
114 //
115 // Define MP data block which consumes individual processor block.
116 //
117 typedef struct {
118   SPIN_LOCK                   APSerializeLock;
119 
120   EFI_EVENT                   CheckAPsEvent;
121 
122   UINTN                       FinishCount;
123   UINTN                       StartCount;
124 
125   BOOLEAN                     CpuList[MAX_CPU_NUMBER];
126 
127   EFI_AP_PROCEDURE            Procedure;
128   VOID                        *ProcArguments;
129   BOOLEAN                     SingleThread;
130   EFI_EVENT                   WaitEvent;
131   UINTN                       **FailedCpuList;
132   UINT64                      ExpectedTime;
133   UINT64                      CurrentTime;
134   UINT64                      TotalTime;
135 
136   CPU_DATA_BLOCK              CpuData[MAX_CPU_NUMBER];
137 } MP_SYSTEM_DATA;
138 
139 /**
140   Implementation of GetNumberOfProcessors() service of MP Services Protocol.
141 
142   This service retrieves the number of logical processor in the platform
143   and the number of those logical processors that are enabled on this boot.
144   This service may only be called from the BSP.
145 
146   @param  This                       A pointer to the EFI_MP_SERVICES_PROTOCOL instance.
147   @param  NumberOfProcessors         Pointer to the total number of logical processors in the system,
148                                      including the BSP and disabled APs.
149   @param  NumberOfEnabledProcessors  Pointer to the number of enabled logical processors that exist
150                                      in system, including the BSP.
151 
152   @retval EFI_SUCCESS	             Number of logical processors and enabled logical processors retrieved..
153   @retval EFI_DEVICE_ERROR           Caller processor is AP.
154   @retval EFI_INVALID_PARAMETER      NumberOfProcessors is NULL
155   @retval EFI_INVALID_PARAMETER      NumberOfEnabledProcessors is NULL
156 
157 **/
158 EFI_STATUS
159 EFIAPI
160 GetNumberOfProcessors (
161   IN  EFI_MP_SERVICES_PROTOCOL     *This,
162   OUT UINTN                        *NumberOfProcessors,
163   OUT UINTN                        *NumberOfEnabledProcessors
164   );
165 
166 /**
167   Implementation of GetNumberOfProcessors() service of MP Services Protocol.
168 
169   Gets detailed MP-related information on the requested processor at the
170   instant this call is made. This service may only be called from the BSP.
171 
172   @param  This                  A pointer to the EFI_MP_SERVICES_PROTOCOL instance.
173   @param  ProcessorNumber       The handle number of processor.
174   @param  ProcessorInfoBuffer   A pointer to the buffer where information for the requested processor is deposited.
175 
176   @retval EFI_SUCCESS           Processor information successfully returned.
177   @retval EFI_DEVICE_ERROR      Caller processor is AP.
178   @retval EFI_INVALID_PARAMETER ProcessorInfoBuffer is NULL
179   @retval EFI_NOT_FOUND         Processor with the handle specified by ProcessorNumber does not exist.
180 
181 **/
182 EFI_STATUS
183 EFIAPI
184 GetProcessorInfo (
185   IN       EFI_MP_SERVICES_PROTOCOL     *This,
186   IN       UINTN                        ProcessorNumber,
187   OUT      EFI_PROCESSOR_INFORMATION    *ProcessorInfoBuffer
188   );
189 
190 /**
191   Implementation of StartupAllAPs() service of MP Services Protocol.
192 
193   This service lets the caller get all enabled APs to execute a caller-provided function.
194   This service may only be called from the BSP.
195 
196   @param  This                  A pointer to the EFI_MP_SERVICES_PROTOCOL instance.
197   @param  Procedure             A pointer to the function to be run on enabled APs of the system.
198   @param  SingleThread          Indicates whether to execute the function simultaneously or one by one..
199   @param  WaitEvent             The event created by the caller.
200                                 If it is NULL, then execute in blocking mode.
201                                 If it is not NULL, then execute in non-blocking mode.
202   @param  TimeoutInMicroSeconds The time limit in microseconds for this AP to finish the function.
203                                 Zero means infinity.
204   @param  ProcedureArgument     Pointer to the optional parameter of the assigned function.
205   @param  FailedCpuList         The list of processor numbers that fail to finish the function before
206                                 TimeoutInMicrosecsond expires.
207 
208   @retval EFI_SUCCESS           In blocking mode, all APs have finished before the timeout expired.
209   @retval EFI_SUCCESS           In non-blocking mode, function has been dispatched to all enabled APs.
210   @retval EFI_DEVICE_ERROR      Caller processor is AP.
211   @retval EFI_NOT_STARTED       No enabled AP exists in the system.
212   @retval EFI_NOT_READY         Any enabled AP is busy.
213   @retval EFI_TIMEOUT           In blocking mode, The timeout expired before all enabled APs have finished.
214   @retval EFI_INVALID_PARAMETER Procedure is NULL.
215 
216 **/
217 EFI_STATUS
218 EFIAPI
219 StartupAllAPs (
220   IN  EFI_MP_SERVICES_PROTOCOL   *This,
221   IN  EFI_AP_PROCEDURE           Procedure,
222   IN  BOOLEAN                    SingleThread,
223   IN  EFI_EVENT                  WaitEvent             OPTIONAL,
224   IN  UINTN                      TimeoutInMicroSeconds,
225   IN  VOID                       *ProcedureArgument    OPTIONAL,
226   OUT UINTN                      **FailedCpuList       OPTIONAL
227   );
228 
229 /**
230   Implementation of StartupThisAP() service of MP Services Protocol.
231 
232   This service lets the caller get one enabled AP to execute a caller-provided function.
233   This service may only be called from the BSP.
234 
235   @param  This                  A pointer to the EFI_MP_SERVICES_PROTOCOL instance.
236   @param  Procedure             A pointer to the function to be run on the designated AP.
237   @param  ProcessorNumber       The handle number of AP..
238   @param  WaitEvent             The event created by the caller.
239                                 If it is NULL, then execute in blocking mode.
240                                 If it is not NULL, then execute in non-blocking mode.
241   @param  TimeoutInMicroseconds The time limit in microseconds for this AP to finish the function.
242                                 Zero means infinity.
243   @param  ProcedureArgument     Pointer to the optional parameter of the assigned function.
244   @param  Finished              Indicates whether AP has finished assigned function.
245                                 In blocking mode, it is ignored.
246 
247   @retval EFI_SUCCESS           In blocking mode, specified AP has finished before the timeout expires.
248   @retval EFI_SUCCESS           In non-blocking mode, function has been dispatched to specified AP.
249   @retval EFI_DEVICE_ERROR      Caller processor is AP.
250   @retval EFI_TIMEOUT           In blocking mode, the timeout expires before specified AP has finished.
251   @retval EFI_NOT_READY         Specified AP is busy.
252   @retval EFI_NOT_FOUND         Processor with the handle specified by ProcessorNumber does not exist.
253   @retval EFI_INVALID_PARAMETER ProcessorNumber specifies the BSP or disabled AP.
254   @retval EFI_INVALID_PARAMETER Procedure is NULL.
255 
256 **/
257 EFI_STATUS
258 EFIAPI
259 StartupThisAP (
260   IN  EFI_MP_SERVICES_PROTOCOL   *This,
261   IN  EFI_AP_PROCEDURE           Procedure,
262   IN  UINTN                      ProcessorNumber,
263   IN  EFI_EVENT                  WaitEvent OPTIONAL,
264   IN  UINTN                      TimeoutInMicroseconds,
265   IN  VOID                       *ProcedureArgument OPTIONAL,
266   OUT BOOLEAN                    *Finished OPTIONAL
267   );
268 
269 /**
270   Implementation of SwitchBSP() service of MP Services Protocol.
271 
272   This service switches the requested AP to be the BSP from that point onward.
273   This service may only be called from the current BSP.
274 
275   @param  This                  A pointer to the EFI_MP_SERVICES_PROTOCOL instance.
276   @param  ProcessorNumber       The handle number of processor.
277   @param  EnableOldBSP          Whether to enable or disable the original BSP.
278 
279   @retval EFI_SUCCESS           BSP successfully switched.
280   @retval EFI_DEVICE_ERROR      Caller processor is AP.
281   @retval EFI_NOT_FOUND         Processor with the handle specified by ProcessorNumber does not exist.
282   @retval EFI_INVALID_PARAMETER ProcessorNumber specifies the BSP or disabled AP.
283   @retval EFI_NOT_READY         Specified AP is busy.
284 
285 **/
286 EFI_STATUS
287 EFIAPI
288 SwitchBSP (
289   IN  EFI_MP_SERVICES_PROTOCOL            *This,
290   IN  UINTN                               ProcessorNumber,
291   IN  BOOLEAN                             EnableOldBSP
292   );
293 
294 /**
295   Implementation of EnableDisableAP() service of MP Services Protocol.
296 
297   This service lets the caller enable or disable an AP.
298   This service may only be called from the BSP.
299 
300   @param  This                   A pointer to the EFI_MP_SERVICES_PROTOCOL instance.
301   @param  ProcessorNumber        The handle number of processor.
302   @param  EnableAP               Indicates whether the newstate of the AP is enabled or disabled.
303   @param  HealthFlag             Indicates new health state of the AP..
304 
305   @retval EFI_SUCCESS            AP successfully enabled or disabled.
306   @retval EFI_DEVICE_ERROR       Caller processor is AP.
307   @retval EFI_NOT_FOUND          Processor with the handle specified by ProcessorNumber does not exist.
308   @retval EFI_INVALID_PARAMETERS ProcessorNumber specifies the BSP.
309 
310 **/
311 EFI_STATUS
312 EFIAPI
313 EnableDisableAP (
314   IN  EFI_MP_SERVICES_PROTOCOL            *This,
315   IN  UINTN                               ProcessorNumber,
316   IN  BOOLEAN                             EnableAP,
317   IN  UINT32                              *HealthFlag OPTIONAL
318   );
319 
320 /**
321   Implementation of WhoAmI() service of MP Services Protocol.
322 
323   This service lets the caller processor get its handle number.
324   This service may be called from the BSP and APs.
325 
326   @param  This                  A pointer to the EFI_MP_SERVICES_PROTOCOL instance.
327   @param  ProcessorNumber       Pointer to the handle number of AP.
328 
329   @retval EFI_SUCCESS           Processor number successfully returned.
330   @retval EFI_INVALID_PARAMETER ProcessorNumber is NULL
331 
332 **/
333 EFI_STATUS
334 EFIAPI
335 WhoAmI (
336   IN  EFI_MP_SERVICES_PROTOCOL            *This,
337   OUT UINTN                               *ProcessorNumber
338   );
339 
340 /**
341   Checks APs' status periodically.
342 
343   This function is triggerred by timer perodically to check the
344   state of APs for StartupAllAPs() and StartupThisAP() executed
345   in non-blocking mode.
346 
347   @param  Event    Event triggered.
348   @param  Context  Parameter passed with the event.
349 
350 **/
351 VOID
352 EFIAPI
353 CheckAPsStatus (
354   IN  EFI_EVENT                           Event,
355   IN  VOID                                *Context
356   );
357 
358 /**
359   Checks status of all APs.
360 
361   This function checks whether all APs have finished task assigned by StartupAllAPs(),
362   and whether timeout expires.
363 
364   @retval EFI_SUCCESS           All APs have finished task assigned by StartupAllAPs().
365   @retval EFI_TIMEOUT           The timeout expires.
366   @retval EFI_NOT_READY         APs have not finished task and timeout has not expired.
367 
368 **/
369 EFI_STATUS
370 CheckAllAPs (
371   VOID
372   );
373 
374 /**
375   Checks status of specified AP.
376 
377   This function checks whether specified AP has finished task assigned by StartupThisAP(),
378   and whether timeout expires.
379 
380   @param  ProcessorNumber       The handle number of processor.
381 
382   @retval EFI_SUCCESS           Specified AP has finished task assigned by StartupThisAPs().
383   @retval EFI_TIMEOUT           The timeout expires.
384   @retval EFI_NOT_READY         Specified AP has not finished task and timeout has not expired.
385 
386 **/
387 EFI_STATUS
388 CheckThisAP (
389   UINTN  ProcessorNumber
390   );
391 
392 /**
393   Calculate timeout value and return the current performance counter value.
394 
395   Calculate the number of performance counter ticks required for a timeout.
396   If TimeoutInMicroseconds is 0, return value is also 0, which is recognized
397   as infinity.
398 
399   @param  TimeoutInMicroseconds   Timeout value in microseconds.
400   @param  CurrentTime             Returns the current value of the performance counter.
401 
402   @return Expected timestamp counter for timeout.
403           If TimeoutInMicroseconds is 0, return value is also 0, which is recognized
404           as infinity.
405 
406 **/
407 UINT64
408 CalculateTimeout (
409   IN  UINTN   TimeoutInMicroseconds,
410   OUT UINT64  *CurrentTime
411   );
412 
413 /**
414   Checks whether timeout expires.
415 
416   Check whether the number of ellapsed performance counter ticks required for a timeout condition
417   has been reached.  If Timeout is zero, which means infinity, return value is always FALSE.
418 
419   @param  PreviousTime         On input, the value of the performance counter when it was last read.
420                                On output, the current value of the performance counter
421   @param  TotalTime            The total amount of ellapsed time in performance counter ticks.
422   @param  Timeout              The number of performance counter ticks required to reach a timeout condition.
423 
424   @retval TRUE                 A timeout condition has been reached.
425   @retval FALSE                A timeout condition has not been reached.
426 
427 **/
428 BOOLEAN
429 CheckTimeout (
430   IN OUT UINT64  *PreviousTime,
431   IN     UINT64  *TotalTime,
432   IN     UINT64  Timeout
433   );
434 
435 /**
436   Searches for the next waiting AP.
437 
438   Search for the next AP that is put in waiting state by single-threaded StartupAllAPs().
439 
440   @param  NextProcessorNumber  Pointer to the processor number of the next waiting AP.
441 
442   @retval EFI_SUCCESS          The next waiting AP has been found.
443   @retval EFI_NOT_FOUND        No waiting AP exists.
444 
445 **/
446 EFI_STATUS
447 GetNextWaitingProcessorNumber (
448   OUT UINTN                               *NextProcessorNumber
449   );
450 
451 /**
452   Wrapper function for all procedures assigned to AP.
453 
454   Wrapper function for all procedures assigned to AP via MP service protocol.
455   It controls states of AP and invokes assigned precedure.
456 
457 **/
458 VOID
459 ApProcWrapper (
460   VOID
461   );
462 
463 /**
464   Function to wake up a specified AP and assign procedure to it.
465 
466   @param  ProcessorNumber  Handle number of the specified processor.
467   @param  Procedure        Procedure to assign.
468   @param  ProcArguments    Argument for Procedure.
469 
470 **/
471 VOID
472 WakeUpAp (
473   IN   UINTN                 ProcessorNumber,
474   IN   EFI_AP_PROCEDURE      Procedure,
475   IN   VOID                  *ProcArguments
476   );
477 
478 /**
479   Terminate AP's task and set it to idle state.
480 
481   This function terminates AP's task due to timeout by sending INIT-SIPI,
482   and sends it to idle state.
483 
484   @param  ProcessorNumber  Handle number of the specified processor.
485 
486 **/
487 VOID
488 ResetProcessorToIdleState (
489   UINTN      ProcessorNumber
490   );
491 
492 /**
493   Worker function of EnableDisableAP ()
494 
495   Worker function of EnableDisableAP (). Changes state of specified processor.
496 
497   @param  ProcessorNumber Processor number of specified AP.
498   @param  NewState        Desired state of the specified AP.
499 
500   @retval EFI_SUCCESS     AP's state successfully changed.
501 
502 **/
503 EFI_STATUS
504 ChangeCpuState (
505   IN     UINTN                      ProcessorNumber,
506   IN     BOOLEAN                    NewState
507   );
508 
509 /**
510   Gets the processor number of BSP.
511 
512   @return  The processor number of BSP.
513 
514 **/
515 UINTN
516 GetBspNumber (
517   VOID
518   );
519 
520 /**
521   Get address map of RendezvousFunnelProc.
522 
523   This function gets address map of RendezvousFunnelProc.
524 
525   @param  AddressMap   Output buffer for address map information
526 
527 **/
528 VOID
529 AsmGetAddressMap (
530   OUT MP_ASSEMBLY_ADDRESS_MAP    *AddressMap
531   );
532 
533 #endif
534