From: Sami Mujawar <sami.muja...@arm.com> FirmwarePerformanceDxe.c utilizes the Timer Library function GetTimeInNanoSecond() which was not implemented by the ArmArchTimerLib.
This patch adds this missing functionality. In the process some common preprocessor code was moved out of MicroSecondDelay(). Code at: https://github.com/EvanLloyd/tianocore/commit/cfa119bc7343d5410a173dc8202de629db15a5f0 Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Evan Lloyd <evan.ll...@arm.com> --- ArmPkg/Library/ArmArchTimerLib/ArmArchTimerLib.c | 100 ++++++++++++++++---- 1 file changed, 81 insertions(+), 19 deletions(-) diff --git a/ArmPkg/Library/ArmArchTimerLib/ArmArchTimerLib.c b/ArmPkg/Library/ArmArchTimerLib/ArmArchTimerLib.c index a0e4f58..1be90c5 100644 --- a/ArmPkg/Library/ArmArchTimerLib/ArmArchTimerLib.c +++ b/ArmPkg/Library/ArmArchTimerLib/ArmArchTimerLib.c @@ -1,7 +1,7 @@ /** @file Generic ARM implementation of TimerLib.h - Copyright (c) 2011-2014, ARM Limited. All rights reserved. + Copyright (c) 2011-2016, ARM Limited. All rights reserved. This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License @@ -24,6 +24,14 @@ #define TICKS_PER_MICRO_SEC (PcdGet32 (PcdArmArchTimerFreqInHz)/1000000U) +// Select appropriate multiply function for platform architecture. +#ifdef MDE_CPU_ARM +#define MultU64xN MultU64x32 +#else +#define MultU64xN MultU64x64 +#endif + + RETURN_STATUS EFIAPI TimerConstructor ( @@ -76,6 +84,28 @@ TimerConstructor ( return RETURN_SUCCESS; } +/** + A local utility function that returns the PCD value, if specified. + Otherwise it defaults to ArmGenericTimerGetTimerFreq. + + @return The timer frequency. + +**/ +STATIC +UINTN +EFIAPI +GetPlatformTimerFreq ( + ) +{ + UINTN TimerFreq; + + TimerFreq = PcdGet32 (PcdArmArchTimerFreqInHz); + if (TimerFreq == 0) { + TimerFreq = ArmGenericTimerGetTimerFreq (); + } + return TimerFreq; +} + /** Stalls the CPU for the number of microseconds specified by MicroSeconds. @@ -93,23 +123,6 @@ MicroSecondDelay ( { UINT64 TimerTicks64; UINT64 SystemCounterVal; - UINT64 (EFIAPI - *MultU64xN) ( - IN UINT64 Multiplicand, - IN UINTN Multiplier - ); - UINTN TimerFreq; - -#ifdef MDE_CPU_ARM - MultU64xN = MultU64x32; -#else - MultU64xN = MultU64x64; -#endif - - TimerFreq = PcdGet32 (PcdArmArchTimerFreqInHz); - if (TimerFreq == 0) { - TimerFreq = ArmGenericTimerGetTimerFreq (); - } // Calculate counter ticks that can represent requested delay: // = MicroSeconds x TICKS_PER_MICRO_SEC @@ -117,7 +130,7 @@ MicroSecondDelay ( TimerTicks64 = DivU64x32 ( MultU64xN ( MicroSeconds, - TimerFreq + GetPlatformTimerFreq () ), 1000000U ); @@ -229,3 +242,52 @@ GetPerformanceCounterProperties ( return (UINT64)ArmGenericTimerGetTimerFreq (); } + +/** + Converts elapsed ticks of performance counter to time in nanoseconds. + + This function converts the elapsed ticks of running performance counter to + time value in unit of nanoseconds. + + @param Ticks The number of elapsed ticks of running performance counter. + + @return The elapsed time in nanoseconds. + +**/ +UINT64 +EFIAPI +GetTimeInNanoSecond ( + IN UINT64 Ticks + ) +{ + UINT64 NanoSeconds; + UINT32 Remainder; + UINT32 TimerFreq; + + TimerFreq = GetPlatformTimerFreq (); + // + // Ticks + // Time = --------- x 1,000,000,000 + // Frequency + // + NanoSeconds = MultU64xN ( + DivU64x32Remainder ( + Ticks, + TimerFreq, + &Remainder), + 1000000000U + ); + + // + // Frequency < 0x100000000, so Remainder < 0x100000000, then (Remainder * 1,000,000,000) + // will not overflow 64-bit. + // + NanoSeconds += DivU64x32 ( + MultU64xN ( + (UINT64) Remainder, + 1000000000U), + TimerFreq + ); + + return NanoSeconds; +} -- 2.7.0 _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel