Hi Ray and Laszlo, I would very much like to be merged into stable202302, the soft feature deadline is 2024-02-05, so could you please hlep to review this patch as soon as passable? Please... Thanks, Chao On 2024/1/31 11:30, Chao Li wrote: > > Hi Ray, > > Can you please help to review this patch again? > > On 2024/1/26 14:29, Chao Li wrote: >> Add the LoongArch64 CPU Timer instance to CpuTimerLib, using CPUCFG 0x4 >> and 0x5 for Stable Counter frequency. >> >> BZ:https://bugzilla.tianocore.org/show_bug.cgi?id=4584 >> >> Cc: Eric Dong >> Cc: Ray Ni >> Cc: Rahul Kumar >> Cc: Gerd Hoffmann >> Signed-off-by: Chao Li >> --- >> .../Library/CpuTimerLib/BaseCpuTimerLib.inf | 9 +- >> .../CpuTimerLib/LoongArch64/CpuTimerLib.c | 251 ++++++++++++++++++ >> 2 files changed, 258 insertions(+), 2 deletions(-) >> create mode 100644 UefiCpuPkg/Library/CpuTimerLib/LoongArch64/CpuTimerLib.c >> >> diff --git a/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.inf b/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.inf >> index de0648de91..7e6152ef7e 100644 >> --- a/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.inf >> +++ b/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.inf >> @@ -5,6 +5,7 @@ >> # counter features are provided by the processors time stamp counter. >> # >> # Copyright (c) 2021, Intel Corporation. All rights reserved.
>> +# Copyright (c) 2024, Loongson Technology Corporation Limited. All rights reserved.
>> # SPDX-License-Identifier: BSD-2-Clause-Patent >> # >> ## >> @@ -18,18 +19,22 @@ >> LIBRARY_CLASS = TimerLib >> MODULE_UNI_FILE = BaseCpuTimerLib.uni >> >> -[Sources] >> +[Sources.IA32, Sources.X64] >> CpuTimerLib.c >> BaseCpuTimerLib.c >> >> +[Sources.LOONGARCH64] >> + LoongArch64/CpuTimerLib.c >> + >> [Packages] >> MdePkg/MdePkg.dec >> UefiCpuPkg/UefiCpuPkg.dec >> >> [LibraryClasses] >> BaseLib >> - PcdLib >> DebugLib >> + PcdLib >> + SafeIntLib >> >> [Pcd] >> gUefiCpuPkgTokenSpaceGuid.PcdCpuCoreCrystalClockFrequency ## CONSUMES >> diff --git a/UefiCpuPkg/Library/CpuTimerLib/LoongArch64/CpuTimerLib.c b/UefiCpuPkg/Library/CpuTimerLib/LoongArch64/CpuTimerLib.c >> new file mode 100644 >> index 0000000000..a5ae8d0185 >> --- /dev/null >> +++ b/UefiCpuPkg/Library/CpuTimerLib/LoongArch64/CpuTimerLib.c >> @@ -0,0 +1,251 @@ >> +/** @file >> + CPUCFG 0x4 and 0x5 for Stable Counter frequency instance of Timer Library. >> + >> + Copyright (c) 2024, Loongson Technology Corporation Limited. All rights reserved.
>> + >> + SPDX-License-Identifier: BSD-2-Clause-Patent >> +**/ >> + >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> + >> +/** >> + Calculate clock frequency using CPUCFG 0x4 and 0x5 registers. >> + >> + @param VOID. >> + >> + @return The frequency in Hz. >> + >> +**/ >> +STATIC >> +UINT64 >> +CalcConstFreq ( >> + VOID >> + ) >> +{ >> + UINT32 BaseFreq; >> + UINT64 ClockMultiplier; >> + UINT32 ClockDivide; >> + CPUCFG_REG4_INFO_DATA CcFreq; >> + CPUCFG_REG5_INFO_DATA CpucfgReg5Data; >> + UINT64 StableTimerFreq; >> + >> + // >> + // Get the the crystal frequency corresponding to the constant >> + // frequency timer and the clock used by the timer. >> + // >> + AsmCpucfg (CPUCFG_REG4_INFO, &CcFreq.Uint32); >> + >> + // >> + // Get the multiplication factor and frequency division factor >> + // corresponding to the constant frequency timer and the clock >> + // used by the timer. >> + // >> + AsmCpucfg (CPUCFG_REG5_INFO, &CpucfgReg5Data.Uint32); >> + >> + BaseFreq = CcFreq.Bits.CC_FREQ; >> + ClockMultiplier = CpucfgReg5Data.Bits.CC_MUL & 0xFFFF; >> + ClockDivide = CpucfgReg5Data.Bits.CC_DIV & 0xFFFF; >> + >> + if ((BaseFreq == 0x0) || (ClockMultiplier == 0x0) || (ClockDivide == 0x0)) { >> + DEBUG (( >> + DEBUG_ERROR, >> + "LoongArch Stable Timer is not available in the CPU, hence this library cannot be used.\n" >> + )); >> + ASSERT (FALSE); >> + CpuDeadLoop (); >> + } >> + >> + StableTimerFreq = ((ClockMultiplier * BaseFreq) / ClockDivide); >> + >> + if (StableTimerFreq == 0x0) { >> + ASSERT (FALSE); >> + } >> + >> + return StableTimerFreq; >> +} >> + >> +/** >> + Stalls the CPU for at least the given number of microseconds. >> + >> + Stalls the CPU for the number of microseconds specified by MicroSeconds. >> + >> + @param MicroSeconds The minimum number of microseconds to delay. >> + >> + @return MicroSeconds >> + >> +**/ >> +UINTN >> +EFIAPI >> +MicroSecondDelay ( >> + IN UINTN MicroSeconds >> + ) >> +{ >> + UINT64 CurrentTicks, ExceptedTicks, Remaining; >> + RETURN_STATUS Status; >> + >> + Status = SafeUint64Mult (MicroSeconds, CalcConstFreq (), &Remaining); >> + ASSERT_RETURN_ERROR (Status); >> + >> + ExceptedTicks = DivU64x32 (Remaining, 1000000U); >> + CurrentTicks = AsmReadStableCounter (); >> + ExceptedTicks += CurrentTicks; >> + >> + do { >> + CurrentTicks = AsmReadStableCounter (); >> + } while (CurrentTicks < ExceptedTicks); >> + >> + return MicroSeconds; >> +} >> + >> +/** >> + Stalls the CPU for at least the given number of nanoseconds. >> + >> + Stalls the CPU for the number of nanoseconds specified by NanoSeconds. >> + >> + @param NanoSeconds The minimum number of nanoseconds to delay. >> + >> + @return NanoSeconds >> + >> +**/ >> +UINTN >> +EFIAPI >> +NanoSecondDelay ( >> + IN UINTN NanoSeconds >> + ) >> +{ >> + UINTN MicroSeconds; >> + >> + // Round up to 1us Tick Number >> + MicroSeconds = NanoSeconds / 1000; >> + MicroSeconds += ((NanoSeconds % 1000) == 0) ? 0 : 1; >> + >> + MicroSecondDelay (MicroSeconds); >> + >> + return NanoSeconds; >> +} >> + >> +/** >> + Retrieves the current value of a 64-bit free running Stable Counter. >> + >> + The LoongArch defines a constant frequency timer, whose main body is a >> + 64-bit counter called StableCounter. StableCounter is set to 0 after >> + reset, and then increments by 1 every counting clock cycle. When the >> + count reaches all 1s, it automatically wraps around to 0 and continues >> + to increment. >> + The properties of the Stable Counter can be retrieved from >> + GetPerformanceCounterProperties(). >> + >> + @return The current value of the Stable Counter. >> + >> +**/ >> +UINT64 >> +EFIAPI >> +GetPerformanceCounter ( >> + VOID >> + ) >> +{ >> + // >> + // Just return the value of Stable Counter. >> + // >> + return AsmReadStableCounter (); >> +} >> + >> +/** >> + Retrieves the 64-bit frequency in Hz and the range of Stable Counter >> + values. >> + >> + If StartValue is not NULL, then the value that the stbale counter starts >> + with immediately after is it rolls over is returned in StartValue. If >> + EndValue is not NULL, then the value that the stable counter end with >> + immediately before it rolls over is returned in EndValue. The 64-bit >> + frequency of the system frequency in Hz is always returned. >> + >> + @param StartValue The value the stable counter starts with when it >> + rolls over. >> + @param EndValue The value that the stable counter ends with before >> + it rolls over. >> + >> + @return The frequency in Hz. >> + >> +**/ >> +UINT64 >> +EFIAPI >> +GetPerformanceCounterProperties ( >> + OUT UINT64 *StartValue OPTIONAL, >> + OUT UINT64 *EndValue OPTIONAL >> + ) >> +{ >> + if (StartValue != NULL) { >> + *StartValue = 0; >> + } >> + >> + if (EndValue != NULL) { >> + *EndValue = 0xFFFFFFFFFFFFFFFFULL; >> + } >> + >> + return CalcConstFreq (); >> +} >> + >> +/** >> + 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 Frequency; >> + UINT64 NanoSeconds; >> + UINT64 Remainder; >> + INTN Shift; >> + RETURN_STATUS Status; >> + >> + Frequency = GetPerformanceCounterProperties (NULL, NULL); >> + >> + // >> + // Ticks >> + // Time = --------- x 1,000,000,000 >> + // Frequency >> + // >> + Status = SafeUint64Mult ( >> + DivU64x64Remainder (Ticks, Frequency, &Remainder), >> + 1000000000u, >> + &NanoSeconds >> + ); >> + >> + // >> + // Ensure (Remainder * 1,000,000,000) will not overflow 64-bit. >> + // Since 2^29 < 1,000,000,000 = 0x3B9ACA00 < 2^30, Remainder should < 2^(64-30) = 2^34, >> + // i.e. highest bit set in Remainder should <= 33. >> + // >> + Shift = MAX (0, HighBitSet64 (Remainder) - 33); >> + Remainder = RShiftU64 (Remainder, (UINTN)Shift); >> + Frequency = RShiftU64 (Frequency, (UINTN)Shift); >> + >> + Status = SafeUint64Add ( >> + NanoSeconds, >> + DivU64x64Remainder ( >> + MultU64x32 (Remainder, 1000000000u), >> + Frequency, >> + NULL >> + ), >> + &NanoSeconds >> + ); >> + ASSERT_RETURN_ERROR (Status); >> + >> + return NanoSeconds; >> +} > -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#114860): https://edk2.groups.io/g/devel/message/114860 Mute This Topic: https://groups.io/mt/104070166/7686176 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io] -=-=-=-=-=-=-=-=-=-=-=-