TianoCore EDK2 master
Loading...
Searching...
No Matches
SmmPeriodicSmiLib.c
Go to the documentation of this file.
1
9#include <PiSmm.h>
10
12
13#include <Library/BaseLib.h>
16#include <Library/DebugLib.h>
17#include <Library/TimerLib.h>
20
22
27#define PERIODIC_SMI_LIBRARY_ALLOCATE_SIZE 0x08
28
32#define PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT_SIGNATURE SIGNATURE_32 ('P', 'S', 'M', 'I')
33
37typedef struct {
41 UINT32 Signature;
53 VOID *Context;
57 UINT64 TickPeriod;
73 VOID *Stack;
120 BASE_LIBRARY_JUMP_BUFFER DispatchJumpBuffer;
126 BOOLEAN YieldFlag;
133 BASE_LIBRARY_JUMP_BUFFER YieldJumpBuffer;
140
146#define PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT_FROM_LINK(a) \
147 CR ( \
148 a, \
149 PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT, \
150 Link, \
151 PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT_SIGNATURE \
152 )
153
158
167
173
179
185
199 VOID
200 )
201{
203}
204
229 IN EFI_HANDLE DispatchHandle OPTIONAL
230 )
231{
232 LIST_ENTRY *Link;
233 PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT *PeriodicSmiLibraryHandler;
234
235 //
236 // If DispatchHandle is NULL, then return the active periodic SMI handler
237 //
238 if (DispatchHandle == NULL) {
240 }
241
242 //
243 // Search the periodic SMI handler entries for a a matching DispatchHandle
244 //
248 )
249 {
250 PeriodicSmiLibraryHandler = PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT_FROM_LINK (Link);
251
252 if (PeriodicSmiLibraryHandler->DispatchHandle == DispatchHandle) {
253 return PeriodicSmiLibraryHandler;
254 }
255 }
256
257 //
258 // No entries match DispatchHandle, so return NULL
259 //
260 return NULL;
261}
262
283 IN EFI_HANDLE DispatchHandle OPTIONAL
284 )
285{
286 if (DispatchHandle == NULL) {
288 } else {
290 }
291
293}
294
301VOID
303 PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT *PeriodicSmiLibraryHandler
304 )
305{
306 ASSERT (PeriodicSmiLibraryHandler->DispatchHandle == NULL);
307 if (PeriodicSmiLibraryHandler->Stack != NULL) {
308 FreePages (
309 PeriodicSmiLibraryHandler->Stack,
310 EFI_SIZE_TO_PAGES (PeriodicSmiLibraryHandler->StackSize)
311 );
312 PeriodicSmiLibraryHandler->Stack = NULL;
313 }
314
315 RemoveEntryList (&PeriodicSmiLibraryHandler->Link);
316 InsertHeadList (&gFreePeriodicSmiLibraryHandlers, &PeriodicSmiLibraryHandler->Link);
317}
318
327BOOLEAN
329 VOID
330 )
331{
332 UINTN Index;
333 PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT *PeriodicSmiLibraryHandler;
334
335 //
336 // Add the entries to the list
337 //
338 for (Index = 0; Index < PERIODIC_SMI_LIBRARY_ALLOCATE_SIZE; Index++) {
339 PeriodicSmiLibraryHandler = AllocatePool (sizeof (PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT));
340 if (PeriodicSmiLibraryHandler == NULL) {
341 break;
342 }
343
345 InsertHeadList (&gFreePeriodicSmiLibraryHandlers, &PeriodicSmiLibraryHandler->Link);
346 }
347
348 return (BOOLEAN)(Index > 0);
349}
350
362 VOID
363 )
364{
365 PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT *PeriodicSmiLibraryHandler;
366
369 return NULL;
370 }
371 }
372
373 //
374 // Get one from the list of free periodic SMI handlers.
375 //
376 PeriodicSmiLibraryHandler = PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT_FROM_LINK (
378 );
379 RemoveEntryList (&PeriodicSmiLibraryHandler->Link);
380 InsertTailList (&gPeriodicSmiLibraryHandlers, &PeriodicSmiLibraryHandler->Link);
381
382 return PeriodicSmiLibraryHandler;
383}
384
397UINT64 *
398EFIAPI
400 VOID
401 )
402{
403 //
404 // Return the table allocated and populated by SmmPeriodicSmiLibConstructor()
405 //
406 return gSmiTickPeriodTable;
407}
408
420UINT64
421EFIAPI
423 VOID
424 )
425{
426 PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT *PeriodicSmiLibraryHandler;
427 UINT64 Current;
428 UINT64 Count;
429
430 //
431 // If there is no active periodic SMI handler, then return 0
432 //
433 PeriodicSmiLibraryHandler = GetActivePeriodicSmiLibraryHandler ();
434 if (PeriodicSmiLibraryHandler == NULL) {
435 return 0;
436 }
437
438 //
439 // Get the current performance counter value
440 //
441 Current = GetPerformanceCounter ();
442
443 //
444 // Count the number of performance counter ticks since the periodic SMI handler
445 // was dispatched or the last time this function was called.
446 //
447 if (PeriodicSmiLibraryHandler->PerfomanceCounterEndValue > PeriodicSmiLibraryHandler->PerfomanceCounterStartValue) {
448 //
449 // The performance counter counts up. Check for roll over condition.
450 //
451 if (Current > PeriodicSmiLibraryHandler->DispatchCheckPointTime) {
452 Count = Current - PeriodicSmiLibraryHandler->DispatchCheckPointTime;
453 } else {
454 Count = (Current - PeriodicSmiLibraryHandler->PerfomanceCounterStartValue) + (PeriodicSmiLibraryHandler->PerfomanceCounterEndValue - PeriodicSmiLibraryHandler->DispatchCheckPointTime);
455 }
456 } else {
457 //
458 // The performance counter counts down. Check for roll over condition.
459 //
460 if (PeriodicSmiLibraryHandler->DispatchCheckPointTime > Current) {
461 Count = PeriodicSmiLibraryHandler->DispatchCheckPointTime - Current;
462 } else {
463 Count = (PeriodicSmiLibraryHandler->DispatchCheckPointTime - PeriodicSmiLibraryHandler->PerfomanceCounterEndValue) + (PeriodicSmiLibraryHandler->PerfomanceCounterStartValue - Current);
464 }
465 }
466
467 //
468 // Accumulate the total number of performance counter ticks since the periodic
469 // SMI handler was dispatched or resumed.
470 //
471 PeriodicSmiLibraryHandler->DispatchTotalTime += Count;
472
473 //
474 // Update the checkpoint value to the current performance counter value
475 //
476 PeriodicSmiLibraryHandler->DispatchCheckPointTime = Current;
477
478 //
479 // Convert the total number of performance counter ticks to 100 ns units
480 //
481 return DivU64x64Remainder (
482 MultU64x32 (PeriodicSmiLibraryHandler->DispatchTotalTime, 10000000),
483 PeriodicSmiLibraryHandler->PerfomanceCounterRate,
484 NULL
485 );
486}
487
496VOID
497EFIAPI
499 VOID
500 )
501{
502 PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT *PeriodicSmiLibraryHandler;
503
504 //
505 // If there is no active periodic SMI handler, then return
506 //
507 PeriodicSmiLibraryHandler = GetActivePeriodicSmiLibraryHandler ();
508 if (PeriodicSmiLibraryHandler == NULL) {
509 return;
510 }
511
512 //
513 // Perform a long jump back to the point when the currently executing dispatch
514 // function was dispatched.
515 //
516 LongJump (&PeriodicSmiLibraryHandler->DispatchJumpBuffer, 1);
517
518 //
519 // Must never return
520 //
521 ASSERT (FALSE);
522 CpuDeadLoop ();
523}
524
542UINT64
543EFIAPI
545 VOID
546 )
547{
548 PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT *PeriodicSmiLibraryHandler;
549 UINTN SetJumpFlag;
550
551 //
552 // If there is no active periodic SMI handler, then return
553 //
554 PeriodicSmiLibraryHandler = GetActivePeriodicSmiLibraryHandler ();
555 if (PeriodicSmiLibraryHandler == NULL) {
556 return 0;
557 }
558
559 //
560 // If PeriodicSmiYield() is called without an allocated stack, then just return
561 // immediately with an elapsed time of 0.
562 //
563 if (PeriodicSmiLibraryHandler->Stack == NULL) {
564 return 0;
565 }
566
567 //
568 // Set a flag so the next periodic SMI event will resume at where SetJump()
569 // is called below.
570 //
571 PeriodicSmiLibraryHandler->YieldFlag = TRUE;
572
573 //
574 // Save context in YieldJumpBuffer
575 //
576 SetJumpFlag = SetJump (&PeriodicSmiLibraryHandler->YieldJumpBuffer);
577 if (SetJumpFlag == 0) {
578 //
579 // The initial call to SetJump() always returns 0.
580 // If this is the initial call, then exit the current periodic SMI handler
581 //
583 }
584
585 //
586 // We get here when a LongJump is performed from PeriodicSmiDispatchFunctionOnCpu()
587 // to resume a periodic SMI handler that called PeriodicSmiYield() on the
588 // previous time this periodic SMI handler was dispatched.
589 //
590 // Clear the flag so the next periodic SMI dispatch will not resume.
591 //
592 PeriodicSmiLibraryHandler->YieldFlag = FALSE;
593
594 //
595 // Return the amount elapsed time that occurred while yielded
596 //
597 return PeriodicSmiLibraryHandler->ElapsedTime;
598}
599
610VOID
611EFIAPI
613 IN VOID *Context1 OPTIONAL,
614 IN VOID *Context2 OPTIONAL
615 )
616{
617 PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT *PeriodicSmiLibraryHandler;
618
619 //
620 // Convert Context1 to PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT *
621 //
622 PeriodicSmiLibraryHandler = (PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT *)Context1;
623
624 //
625 // Dispatch the registered handler passing in the context that was registered
626 // and the amount of time that has elapsed since the previous time this
627 // periodic SMI handler was dispatched.
628 //
629 PeriodicSmiLibraryHandler->DispatchFunction (
630 PeriodicSmiLibraryHandler->Context,
631 PeriodicSmiLibraryHandler->ElapsedTime
632 );
633
634 //
635 // If this DispatchFunction() returns, then unconditionally call PeriodicSmiExit()
636 // to perform a LongJump() back to PeriodicSmiDispatchFunctionOnCpu(). The
637 // LongJump() will resume execution on the original stack.
638 //
640}
641
652VOID
653EFIAPI
655 PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT *PeriodicSmiLibraryHandler
656 )
657{
658 //
659 // Save context in DispatchJumpBuffer. The initial call to SetJump() always
660 // returns 0. If this is the initial call, then either resume from a prior
661 // call to PeriodicSmiYield() or call the DispatchFunction registered in
662 // PeriodicSmiEnable() using an allocated stack if one was specified.
663 //
664 if (SetJump (&PeriodicSmiLibraryHandler->DispatchJumpBuffer) != 0) {
665 return;
666 }
667
668 //
669 // Capture the performance counter value just before the periodic SMI handler
670 // is resumed so the amount of time the periodic SMI handler executes can be
671 // calculated.
672 //
673 PeriodicSmiLibraryHandler->DispatchTotalTime = 0;
674 PeriodicSmiLibraryHandler->DispatchCheckPointTime = GetPerformanceCounter ();
675
676 if (PeriodicSmiLibraryHandler->YieldFlag) {
677 //
678 // Perform a long jump back to the point where the previously dispatched
679 // function called PeriodicSmiYield().
680 //
681 LongJump (&PeriodicSmiLibraryHandler->YieldJumpBuffer, 1);
682 } else if (PeriodicSmiLibraryHandler->Stack == NULL) {
683 //
684 // If Stack is NULL then call DispatchFunction using current stack passing
685 // in the context that was registered and the amount of time that has
686 // elapsed since the previous time this periodic SMI handler was dispatched.
687 //
688 PeriodicSmiLibraryHandler->DispatchFunction (
689 PeriodicSmiLibraryHandler->Context,
690 PeriodicSmiLibraryHandler->ElapsedTime
691 );
692
693 //
694 // If this DispatchFunction() returns, then unconditionally call PeriodicSmiExit()
695 // to perform a LongJump() back to this function.
696 //
698 } else {
699 //
700 // If Stack is not NULL then call DispatchFunction switching to the allocated stack
701 //
704 PeriodicSmiLibraryHandler,
705 NULL,
706 (UINT8 *)PeriodicSmiLibraryHandler->Stack + PeriodicSmiLibraryHandler->StackSize
707 );
708 }
709
710 //
711 // Must never return
712 //
713 ASSERT (FALSE);
714 CpuDeadLoop ();
715}
716
729VOID
730EFIAPI
732 IN OUT VOID *Buffer
733 )
734{
735 PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT *PeriodicSmiLibraryHandler;
736
737 //
738 // Get context
739 //
740 PeriodicSmiLibraryHandler = (PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT *)Buffer;
741
742 //
743 // Execute dispatch function on the currently executing logical CPU
744 //
745 PeriodicSmiDispatchFunctionOnCpu (PeriodicSmiLibraryHandler);
746
747 //
748 // Release the dispatch spin lock
749 //
750 ReleaseSpinLock (&PeriodicSmiLibraryHandler->DispatchLock);
751}
752
776EFIAPI
778 IN EFI_HANDLE DispatchHandle,
779 IN CONST VOID *Context OPTIONAL,
780 IN OUT VOID *CommBuffer OPTIONAL,
781 IN OUT UINTN *CommBufferSize OPTIONAL
782 )
783{
784 PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT *PeriodicSmiLibraryHandler;
785 EFI_SMM_PERIODIC_TIMER_CONTEXT *TimerContext;
786 EFI_STATUS Status;
787
788 //
789 // Set the active periodic SMI handler
790 //
791 PeriodicSmiLibraryHandler = SetActivePeriodicSmiLibraryHandler (DispatchHandle);
792 if (PeriodicSmiLibraryHandler == NULL) {
793 return EFI_NOT_FOUND;
794 }
795
796 //
797 // Retrieve the elapsed time since the last time this periodic SMI handler was called
798 //
799 PeriodicSmiLibraryHandler->ElapsedTime = 0;
800 if (CommBuffer != NULL) {
801 TimerContext = (EFI_SMM_PERIODIC_TIMER_CONTEXT *)CommBuffer;
802 PeriodicSmiLibraryHandler->ElapsedTime = TimerContext->ElapsedTime;
803 }
804
805 //
806 // Dispatch the periodic SMI handler
807 //
808 if ((PeriodicSmiLibraryHandler->Cpu == PERIODIC_SMI_LIBRARY_ANY_CPU) ||
809 (PeriodicSmiLibraryHandler->Cpu == gSmst->CurrentlyExecutingCpu))
810 {
811 //
812 // Dispatch on the currently execution CPU if the CPU specified in PeriodicSmiEnable()
813 // was PERIODIC_SMI_LIBRARY_ANY_CPU or the currently executing CPU matches the CPU
814 // that was specified in PeriodicSmiEnable().
815 //
816 PeriodicSmiDispatchFunctionOnCpu (PeriodicSmiLibraryHandler);
817 } else {
818 //
819 // Acquire spin lock for ths periodic SMI handler. The AP will release the
820 // spin lock when it is done executing the periodic SMI handler.
821 //
822 AcquireSpinLock (&PeriodicSmiLibraryHandler->DispatchLock);
823
824 //
825 // Execute the periodic SMI handler on the CPU that was specified in
826 // PeriodicSmiEnable().
827 //
828 Status = gSmst->SmmStartupThisAp (
830 PeriodicSmiLibraryHandler->Cpu,
831 PeriodicSmiLibraryHandler
832 );
833 if (!EFI_ERROR (Status)) {
834 //
835 // Wait for the AP to release the spin lock.
836 //
837 while (!AcquireSpinLockOrFail (&PeriodicSmiLibraryHandler->DispatchLock)) {
838 CpuPause ();
839 }
840 }
841
842 //
843 // Release the spin lock for the periodic SMI handler.
844 //
845 ReleaseSpinLock (&PeriodicSmiLibraryHandler->DispatchLock);
846 }
847
848 //
849 // Reclaim the active periodic SMI handler if it was disabled during the current dispatch.
850 //
851 if (PeriodicSmiLibraryHandler->DispatchHandle == NULL) {
852 ReclaimPeriodicSmiLibraryHandler (PeriodicSmiLibraryHandler);
853 }
854
855 //
856 // Update state to show that there is no active periodic SMI handler
857 //
859
860 return EFI_SUCCESS;
861}
862
904EFIAPI
906 IN OUT EFI_HANDLE *DispatchHandle OPTIONAL,
907 IN PERIODIC_SMI_LIBRARY_HANDLER DispatchFunction,
908 IN CONST VOID *Context OPTIONAL,
909 IN UINT64 TickPeriod,
910 IN UINTN Cpu,
911 IN UINTN StackSize
912 )
913{
914 EFI_STATUS Status;
915 UINTN Index;
916 PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT *PeriodicSmiLibraryHandler;
917
918 //
919 // Make sure all the input parameters are valid
920 //
921 if (DispatchFunction == NULL) {
922 return EFI_INVALID_PARAMETER;
923 }
924
925 for (Index = 0; gSmiTickPeriodTable[Index] != 0; Index++) {
926 if (gSmiTickPeriodTable[Index] == TickPeriod) {
927 break;
928 }
929 }
930
931 if (gSmiTickPeriodTable[Index] == 0) {
932 return EFI_UNSUPPORTED;
933 }
934
935 if ((Cpu != PERIODIC_SMI_LIBRARY_ANY_CPU) && (Cpu >= gSmst->NumberOfCpus)) {
936 return EFI_INVALID_PARAMETER;
937 }
938
939 //
940 // Find a free periodic SMI handler entry
941 //
942 PeriodicSmiLibraryHandler = FindFreePeriodicSmiLibraryHandler ();
943 if (PeriodicSmiLibraryHandler == NULL) {
944 return EFI_OUT_OF_RESOURCES;
945 }
946
947 //
948 // Initialize a new periodic SMI handler entry
949 //
950 PeriodicSmiLibraryHandler->YieldFlag = FALSE;
951 PeriodicSmiLibraryHandler->DispatchHandle = NULL;
952 PeriodicSmiLibraryHandler->DispatchFunction = DispatchFunction;
953 PeriodicSmiLibraryHandler->Context = (VOID *)Context;
954 PeriodicSmiLibraryHandler->Cpu = Cpu;
955 PeriodicSmiLibraryHandler->StackSize = ALIGN_VALUE (StackSize, EFI_PAGE_SIZE);
956 if (PeriodicSmiLibraryHandler->StackSize > 0) {
957 PeriodicSmiLibraryHandler->Stack = AllocatePages (EFI_SIZE_TO_PAGES (PeriodicSmiLibraryHandler->StackSize));
958 if (PeriodicSmiLibraryHandler->Stack == NULL) {
959 return EFI_OUT_OF_RESOURCES;
960 }
961
962 ZeroMem (PeriodicSmiLibraryHandler->Stack, PeriodicSmiLibraryHandler->StackSize);
963 } else {
964 PeriodicSmiLibraryHandler->Stack = NULL;
965 }
966
967 InitializeSpinLock (&PeriodicSmiLibraryHandler->DispatchLock);
968 PeriodicSmiLibraryHandler->PerfomanceCounterRate = GetPerformanceCounterProperties (
969 &PeriodicSmiLibraryHandler->PerfomanceCounterStartValue,
970 &PeriodicSmiLibraryHandler->PerfomanceCounterEndValue
971 );
972 PeriodicSmiLibraryHandler->RegisterContext.Period = TickPeriod;
973 PeriodicSmiLibraryHandler->RegisterContext.SmiTickInterval = TickPeriod;
974 Status = gSmmPeriodicTimerDispatch2->Register (
977 &PeriodicSmiLibraryHandler->RegisterContext,
978 &PeriodicSmiLibraryHandler->DispatchHandle
979 );
980 if (EFI_ERROR (Status)) {
981 PeriodicSmiLibraryHandler->DispatchHandle = NULL;
982 ReclaimPeriodicSmiLibraryHandler (PeriodicSmiLibraryHandler);
983 return EFI_OUT_OF_RESOURCES;
984 }
985
986 //
987 // Return the registered handle if the optional DispatchHandle parameter is not NULL
988 //
989 if (DispatchHandle != NULL) {
990 *DispatchHandle = PeriodicSmiLibraryHandler->DispatchHandle;
991 }
992
993 return EFI_SUCCESS;
994}
995
1013BOOLEAN
1014EFIAPI
1016 IN EFI_HANDLE DispatchHandle OPTIONAL
1017 )
1018{
1019 PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT *PeriodicSmiLibraryHandler;
1020 EFI_STATUS Status;
1021
1022 //
1023 // Lookup the periodic SMI handler specified by DispatchHandle
1024 //
1025 PeriodicSmiLibraryHandler = LookupPeriodicSmiLibraryHandler (DispatchHandle);
1026 if (PeriodicSmiLibraryHandler == NULL) {
1027 return FALSE;
1028 }
1029
1030 //
1031 // Unregister the periodic SMI handler from the SMM Periodic Timer Dispatch 2 Protocol
1032 //
1033 Status = gSmmPeriodicTimerDispatch2->UnRegister (
1035 PeriodicSmiLibraryHandler->DispatchHandle
1036 );
1037 if (EFI_ERROR (Status)) {
1038 return FALSE;
1039 }
1040
1041 //
1042 // Mark the entry for the disabled periodic SMI handler as free, and
1043 // call ReclaimPeriodicSmiLibraryHandler to move it to the list of free
1044 // periodic SMI handlers.
1045 //
1046 PeriodicSmiLibraryHandler->DispatchHandle = NULL;
1047 if (PeriodicSmiLibraryHandler != GetActivePeriodicSmiLibraryHandler ()) {
1048 ReclaimPeriodicSmiLibraryHandler (PeriodicSmiLibraryHandler);
1049 }
1050
1051 return TRUE;
1052}
1053
1066EFIAPI
1068 IN EFI_HANDLE ImageHandle,
1069 IN EFI_SYSTEM_TABLE *SystemTable
1070 )
1071{
1072 EFI_STATUS Status;
1073 UINT64 *SmiTickInterval;
1074 UINTN Count;
1075
1076 //
1077 // Locate the SMM Periodic Timer Dispatch 2 Protocol
1078 //
1079 Status = gSmst->SmmLocateProtocol (
1080 &gEfiSmmPeriodicTimerDispatch2ProtocolGuid,
1081 NULL,
1083 );
1084 ASSERT_EFI_ERROR (Status);
1085 ASSERT (gSmmPeriodicTimerDispatch2 != NULL);
1086
1087 //
1088 // Count the number of periodic SMI tick intervals that the SMM Periodic Timer
1089 // Dispatch 2 Protocol supports.
1090 //
1091 SmiTickInterval = NULL;
1092 Count = 0;
1093 do {
1094 Status = gSmmPeriodicTimerDispatch2->GetNextShorterInterval (
1096 &SmiTickInterval
1097 );
1098 Count++;
1099 } while (SmiTickInterval != NULL);
1100
1101 //
1102 // Allocate a buffer for the table of supported periodic SMI tick periods.
1103 //
1104 gSmiTickPeriodTable = AllocateZeroPool (Count * sizeof (UINT64));
1105 ASSERT (gSmiTickPeriodTable != NULL);
1106
1107 //
1108 // Fill in the table of supported periodic SMI tick periods.
1109 //
1110 SmiTickInterval = NULL;
1111 Count = 0;
1112 do {
1113 gSmiTickPeriodTable[Count] = 0;
1114 Status = gSmmPeriodicTimerDispatch2->GetNextShorterInterval (
1116 &SmiTickInterval
1117 );
1118 if (SmiTickInterval != NULL) {
1119 gSmiTickPeriodTable[Count] = *SmiTickInterval;
1120 }
1121
1122 Count++;
1123 } while (SmiTickInterval != NULL);
1124
1125 //
1126 // Allocate buffer for initial set of periodic SMI handlers
1127 //
1129
1130 return EFI_SUCCESS;
1131}
1132
1144EFIAPI
1146 IN EFI_HANDLE ImageHandle,
1147 IN EFI_SYSTEM_TABLE *SystemTable
1148 )
1149{
1150 LIST_ENTRY *Link;
1151 PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT *PeriodicSmiLibraryHandler;
1152
1153 //
1154 // Free the table of supported periodic SMI tick rates
1155 //
1156 if (gSmiTickPeriodTable != NULL) {
1158 }
1159
1160 //
1161 // Disable all periodic SMI handlers
1162 //
1164 PeriodicSmiLibraryHandler = PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT_FROM_LINK (Link);
1166 PeriodicSmiDisable (PeriodicSmiLibraryHandler->DispatchHandle);
1167 }
1168
1169 //
1170 // Free all the periodic SMI handler entries
1171 //
1173 PeriodicSmiLibraryHandler = PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT_FROM_LINK (Link);
1174 Link = RemoveEntryList (Link);
1175 FreePool (PeriodicSmiLibraryHandler);
1176 }
1177
1178 return EFI_SUCCESS;
1179}
UINT64 UINTN
UINT64 EFIAPI GetPerformanceCounterProperties(OUT UINT64 *StartValue OPTIONAL, OUT UINT64 *EndValue OPTIONAL)
UINT64 EFIAPI GetPerformanceCounter(VOID)
BOOLEAN EFIAPI IsNull(IN CONST LIST_ENTRY *List, IN CONST LIST_ENTRY *Node)
Definition: LinkedList.c:443
BOOLEAN EFIAPI IsListEmpty(IN CONST LIST_ENTRY *ListHead)
Definition: LinkedList.c:403
LIST_ENTRY *EFIAPI GetNextNode(IN CONST LIST_ENTRY *List, IN CONST LIST_ENTRY *Node)
Definition: LinkedList.c:333
RETURNS_TWICE UINTN EFIAPI SetJump(OUT BASE_LIBRARY_JUMP_BUFFER *JumpBuffer)
VOID EFIAPI SwitchStack(IN SWITCH_STACK_ENTRY_POINT EntryPoint, IN VOID *Context1 OPTIONAL, IN VOID *Context2 OPTIONAL, IN VOID *NewStack,...)
Definition: SwitchStack.c:42
LIST_ENTRY *EFIAPI InsertHeadList(IN OUT LIST_ENTRY *ListHead, IN OUT LIST_ENTRY *Entry)
Definition: LinkedList.c:218
LIST_ENTRY *EFIAPI GetFirstNode(IN CONST LIST_ENTRY *List)
Definition: LinkedList.c:298
VOID EFIAPI CpuDeadLoop(VOID)
Definition: CpuDeadLoop.c:25
VOID EFIAPI CpuPause(VOID)
LIST_ENTRY *EFIAPI RemoveEntryList(IN CONST LIST_ENTRY *Entry)
Definition: LinkedList.c:590
UINT64 EFIAPI MultU64x32(IN UINT64 Multiplicand, IN UINT32 Multiplier)
Definition: MultU64x32.c:27
UINT64 EFIAPI DivU64x64Remainder(IN UINT64 Dividend, IN UINT64 Divisor, OUT UINT64 *Remainder OPTIONAL)
#define INITIALIZE_LIST_HEAD_VARIABLE(ListHead)
Definition: BaseLib.h:2904
VOID EFIAPI LongJump(IN BASE_LIBRARY_JUMP_BUFFER *JumpBuffer, IN UINTN Value)
Definition: LongJump.c:29
LIST_ENTRY *EFIAPI InsertTailList(IN OUT LIST_ENTRY *ListHead, IN OUT LIST_ENTRY *Entry)
Definition: LinkedList.c:259
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
VOID EFIAPI FreePages(IN VOID *Buffer, IN UINTN Pages)
VOID *EFIAPI AllocateZeroPool(IN UINTN AllocationSize)
VOID EFIAPI FreePool(IN VOID *Buffer)
#define NULL
Definition: Base.h:319
#define CONST
Definition: Base.h:259
#define ALIGN_VALUE(Value, Alignment)
Definition: Base.h:948
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define ASSERT_EFI_ERROR(StatusParameter)
Definition: DebugLib.h:462
EFI_SMM_SYSTEM_TABLE2 * gSmst
VOID *EFIAPI AllocatePool(IN UINTN AllocationSize)
VOID *EFIAPI AllocatePages(IN UINTN Pages)
LIST_ENTRY gFreePeriodicSmiLibraryHandlers
VOID EFIAPI PeriodicSmiExit(VOID)
PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT * GetActivePeriodicSmiLibraryHandler(VOID)
PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT * FindFreePeriodicSmiLibraryHandler(VOID)
UINT64 *EFIAPI PeriodicSmiSupportedTickPeriod(VOID)
EFI_STATUS EFIAPI PeriodicSmiEnable(IN OUT EFI_HANDLE *DispatchHandle OPTIONAL, IN PERIODIC_SMI_LIBRARY_HANDLER DispatchFunction, IN CONST VOID *Context OPTIONAL, IN UINT64 TickPeriod, IN UINTN Cpu, IN UINTN StackSize)
#define PERIODIC_SMI_LIBRARY_ALLOCATE_SIZE
EFI_STATUS EFIAPI SmmPeriodicSmiLibConstructor(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable)
#define PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT_FROM_LINK(a)
UINT64 * gSmiTickPeriodTable
UINT64 EFIAPI PeriodicSmiExecutionTime(VOID)
VOID EFIAPI PeriodicSmiDispatchFunctionSwitchStack(IN VOID *Context1 OPTIONAL, IN VOID *Context2 OPTIONAL)
PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT * LookupPeriodicSmiLibraryHandler(IN EFI_HANDLE DispatchHandle OPTIONAL)
LIST_ENTRY gPeriodicSmiLibraryHandlers
BOOLEAN EFIAPI PeriodicSmiDisable(IN EFI_HANDLE DispatchHandle OPTIONAL)
#define PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT_SIGNATURE
PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT * SetActivePeriodicSmiLibraryHandler(IN EFI_HANDLE DispatchHandle OPTIONAL)
EFI_STATUS EFIAPI PeriodicSmiDispatchFunction(IN EFI_HANDLE DispatchHandle, IN CONST VOID *Context OPTIONAL, IN OUT VOID *CommBuffer OPTIONAL, IN OUT UINTN *CommBufferSize OPTIONAL)
EFI_SMM_PERIODIC_TIMER_DISPATCH2_PROTOCOL * gSmmPeriodicTimerDispatch2
EFI_STATUS EFIAPI SmmPeriodicSmiLibDestructor(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable)
VOID ReclaimPeriodicSmiLibraryHandler(PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT *PeriodicSmiLibraryHandler)
VOID EFIAPI PeriodicSmiDispatchFunctionWithLock(IN OUT VOID *Buffer)
BOOLEAN EnlargeFreePeriodicSmiLibraryHandlerList(VOID)
VOID EFIAPI PeriodicSmiDispatchFunctionOnCpu(PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT *PeriodicSmiLibraryHandler)
PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT * gActivePeriodicSmiLibraryHandler
UINT64 EFIAPI PeriodicSmiYield(VOID)
VOID(EFIAPI * PERIODIC_SMI_LIBRARY_HANDLER)(IN CONST VOID *Context OPTIONAL, IN UINT64 ElapsedTime)
SPIN_LOCK *EFIAPI AcquireSpinLock(IN OUT SPIN_LOCK *SpinLock)
SPIN_LOCK *EFIAPI InitializeSpinLock(OUT SPIN_LOCK *SpinLock)
volatile UINTN SPIN_LOCK
SPIN_LOCK *EFIAPI ReleaseSpinLock(IN OUT SPIN_LOCK *SpinLock)
BOOLEAN EFIAPI AcquireSpinLockOrFail(IN OUT SPIN_LOCK *SpinLock)
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
#define EFI_SIZE_TO_PAGES(Size)
Definition: UefiBaseType.h:200
VOID * EFI_HANDLE
Definition: UefiBaseType.h:33
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
EFI_SMM_STARTUP_THIS_AP SmmStartupThisAp
Definition: PiSmmCis.h:140
EFI_SMM_PERIODIC_TIMER_REGISTER_CONTEXT RegisterContext
BASE_LIBRARY_JUMP_BUFFER YieldJumpBuffer
PERIODIC_SMI_LIBRARY_HANDLER DispatchFunction
BASE_LIBRARY_JUMP_BUFFER DispatchJumpBuffer