Home | History | Annotate | Download | only in SecPeiDxeTimerLibUefiCpu
      1 /** @file
      2   Timer Library functions built upon ITC on IPF.
      3 
      4   Copyright (c) 2006 - 2011, 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 <Base.h>
     16 #include <Library/TimerLib.h>
     17 #include <Library/BaseLib.h>
     18 #include <Library/PalLib.h>
     19 
     20 
     21 /**
     22   Performs a delay measured as number of ticks.
     23 
     24   An internal function to perform a delay measured as number of ticks. It's
     25   invoked by MicroSecondDelay() and NanoSecondDelay().
     26 
     27   @param  Delay The number of ticks to delay.
     28 
     29 **/
     30 VOID
     31 EFIAPI
     32 InternalIpfDelay (
     33   IN      INT64                     Delay
     34   )
     35 {
     36   INT64                             Ticks;
     37 
     38   //
     39   // The target timer count is calculated here
     40   //
     41   Ticks = (INT64)AsmReadItc () + Delay;
     42 
     43   //
     44   // Wait until time out
     45   // Delay > 2^63 could not be handled by this function
     46   // Timer wrap-arounds are handled correctly by this function
     47   //
     48   while (Ticks - (INT64)AsmReadItc() >= 0);
     49 }
     50 
     51 /**
     52   Stalls the CPU for at least the given number of microseconds.
     53 
     54   Stalls the CPU for the number of microseconds specified by MicroSeconds.
     55 
     56   @param  MicroSeconds  The minimum number of microseconds to delay.
     57 
     58   @return The value of MicroSeconds inputted.
     59 
     60 **/
     61 UINTN
     62 EFIAPI
     63 MicroSecondDelay (
     64   IN      UINTN                     MicroSeconds
     65   )
     66 {
     67   InternalIpfDelay (
     68     GetPerformanceCounterProperties (NULL, NULL) *
     69     MicroSeconds /
     70     1000000
     71     );
     72   return MicroSeconds;
     73 }
     74 
     75 /**
     76   Stalls the CPU for at least the given number of nanoseconds.
     77 
     78   Stalls the CPU for the number of nanoseconds specified by NanoSeconds.
     79 
     80   @param  NanoSeconds The minimum number of nanoseconds to delay.
     81 
     82   @return The value of NanoSeconds inputted.
     83 
     84 **/
     85 UINTN
     86 EFIAPI
     87 NanoSecondDelay (
     88   IN      UINTN                     NanoSeconds
     89   )
     90 {
     91   InternalIpfDelay (
     92     GetPerformanceCounterProperties (NULL, NULL) *
     93     NanoSeconds /
     94     1000000000
     95     );
     96   return NanoSeconds;
     97 }
     98 
     99 /**
    100   Retrieves the current value of a 64-bit free running performance counter.
    101 
    102   The counter can either count up by 1 or count down by 1. If the physical
    103   performance counter counts by a larger increment, then the counter values
    104   must be translated. The properties of the counter can be retrieved from
    105   GetPerformanceCounterProperties().
    106 
    107   @return The current value of the free running performance counter.
    108 
    109 **/
    110 UINT64
    111 EFIAPI
    112 GetPerformanceCounter (
    113   VOID
    114   )
    115 {
    116   return AsmReadItc ();
    117 }
    118 
    119 /**
    120   Retrieves the 64-bit frequency in Hz and the range of performance counter
    121   values.
    122 
    123   If StartValue is not NULL, then the value that the performance counter starts
    124   with immediately after is it rolls over is returned in StartValue. If
    125   EndValue is not NULL, then the value that the performance counter end with
    126   immediately before it rolls over is returned in EndValue. The 64-bit
    127   frequency of the performance counter in Hz is always returned. If StartValue
    128   is less than EndValue, then the performance counter counts up. If StartValue
    129   is greater than EndValue, then the performance counter counts down. For
    130   example, a 64-bit free running counter that counts up would have a StartValue
    131   of 0 and an EndValue of 0xFFFFFFFFFFFFFFFF. A 24-bit free running counter
    132   that counts down would have a StartValue of 0xFFFFFF and an EndValue of 0.
    133 
    134   @param  StartValue  The value the performance counter starts with when it
    135                       rolls over.
    136   @param  EndValue    The value that the performance counter ends with before
    137                       it rolls over.
    138 
    139   @return The frequency in Hz.
    140 
    141 **/
    142 UINT64
    143 EFIAPI
    144 GetPerformanceCounterProperties (
    145   OUT      UINT64                    *StartValue,  OPTIONAL
    146   OUT      UINT64                    *EndValue     OPTIONAL
    147   )
    148 {
    149   PAL_CALL_RETURN                   PalRet;
    150   UINT64                            BaseFrequence;
    151 
    152   if (StartValue != NULL) {
    153     *StartValue = 0;
    154   }
    155 
    156   if (EndValue != NULL) {
    157     *EndValue = (UINT64)(-1);
    158   }
    159 
    160   PalRet = PalCall (PAL_FREQ_BASE, 0, 0, 0);
    161   if (PalRet.Status != 0) {
    162     return 1000000;
    163   }
    164   BaseFrequence = PalRet.r9;
    165 
    166   PalRet = PalCall (PAL_FREQ_RATIOS, 0, 0, 0);
    167   if (PalRet.Status != 0) {
    168     return 1000000;
    169   }
    170 
    171   return BaseFrequence * (PalRet.r11 >> 32) / (UINT32)PalRet.r11;
    172 }
    173 
    174 /**
    175   Converts elapsed ticks of performance counter to time in nanoseconds.
    176 
    177   This function converts the elapsed ticks of running performance counter to
    178   time value in unit of nanoseconds.
    179 
    180   @param  Ticks     The number of elapsed ticks of running performance counter.
    181 
    182   @return The elapsed time in nanoseconds.
    183 
    184 **/
    185 UINT64
    186 EFIAPI
    187 GetTimeInNanoSecond (
    188   IN      UINT64                     Ticks
    189   )
    190 {
    191   UINT64  Frequency;
    192   UINT64  NanoSeconds;
    193   UINT64  Remainder;
    194   INTN    Shift;
    195 
    196   Frequency = GetPerformanceCounterProperties (NULL, NULL);
    197 
    198   //
    199   //          Ticks
    200   // Time = --------- x 1,000,000,000
    201   //        Frequency
    202   //
    203   NanoSeconds = MultU64x32 (DivU64x64Remainder (Ticks, Frequency, &Remainder), 1000000000u);
    204 
    205   //
    206   // Ensure (Remainder * 1,000,000,000) will not overflow 64-bit.
    207   // Since 2^29 < 1,000,000,000 = 0x3B9ACA00 < 2^30, Remainder should < 2^(64-30) = 2^34,
    208   // i.e. highest bit set in Remainder should <= 33.
    209   //
    210   Shift = MAX (0, HighBitSet64 (Remainder) - 33);
    211   Remainder = RShiftU64 (Remainder, (UINTN) Shift);
    212   Frequency = RShiftU64 (Frequency, (UINTN) Shift);
    213   NanoSeconds += DivU64x64Remainder (MultU64x32 (Remainder, 1000000000u), Frequency, NULL);
    214 
    215   return NanoSeconds;
    216 }
    217