1 /** @file
2 SMM Timer feature support
3 
4 Copyright (c) 2009 - 2015, 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 
13 **/
14 
15 #include "PiSmmCpuDxeSmm.h"
16 
17 UINT64   mTimeoutTicker = 0;
18 //
19 //  Number of counts in a roll-over cycle of the performance counter.
20 //
21 UINT64   mCycle = 0;
22 //
23 // Flag to indicate the performance counter is count-up or count-down.
24 //
25 BOOLEAN  mCountDown;
26 
27 /**
28   Initialize Timer for SMM AP Sync.
29 
30 **/
31 VOID
InitializeSmmTimer(VOID)32 InitializeSmmTimer (
33   VOID
34   )
35 {
36   UINT64  TimerFrequency;
37   UINT64  Start;
38   UINT64  End;
39 
40   TimerFrequency = GetPerformanceCounterProperties (&Start, &End);
41   mTimeoutTicker = DivU64x32 (
42                      MultU64x64(TimerFrequency, PcdGet64 (PcdCpuSmmApSyncTimeout)),
43                      1000 * 1000
44                      );
45   if (End < Start) {
46     mCountDown = TRUE;
47     mCycle = Start - End;
48   } else {
49     mCountDown = FALSE;
50     mCycle = End - Start;
51   }
52 }
53 
54 /**
55   Start Timer for SMM AP Sync.
56 
57 **/
58 UINT64
59 EFIAPI
StartSyncTimer(VOID)60 StartSyncTimer (
61   VOID
62   )
63 {
64   return GetPerformanceCounter ();
65 }
66 
67 
68 /**
69   Check if the SMM AP Sync timer is timeout.
70 
71   @param Timer  The start timer from the begin.
72 
73 **/
74 BOOLEAN
75 EFIAPI
IsSyncTimerTimeout(IN UINT64 Timer)76 IsSyncTimerTimeout (
77   IN      UINT64                    Timer
78   )
79 {
80   UINT64  CurrentTimer;
81   UINT64  Delta;
82 
83   CurrentTimer = GetPerformanceCounter ();
84   //
85   // We need to consider the case that CurrentTimer is equal to Timer
86   // when some timer runs too slow and CPU runs fast. We think roll over
87   // condition does not happen on this case.
88   //
89   if (mCountDown) {
90     //
91     // The performance counter counts down.  Check for roll over condition.
92     //
93     if (CurrentTimer <= Timer) {
94       Delta = Timer - CurrentTimer;
95     } else {
96       //
97       // Handle one roll-over.
98       //
99       Delta = mCycle - (CurrentTimer - Timer) + 1;
100     }
101   } else {
102     //
103     // The performance counter counts up.  Check for roll over condition.
104     //
105     if (CurrentTimer >= Timer) {
106       Delta = CurrentTimer - Timer;
107     } else {
108       //
109       // Handle one roll-over.
110       //
111       Delta = mCycle - (Timer - CurrentTimer) + 1;
112     }
113   }
114 
115   return (BOOLEAN) (Delta >= mTimeoutTicker);
116 }
117