Acked-by: Ray Ni <ray...@intel.com> Thanks, Ray > -----Original Message----- > From: Chao Li <lic...@loongson.cn> > Sent: Tuesday, December 12, 2023 9:12 PM > To: devel@edk2.groups.io > Cc: Dong, Eric <eric.d...@intel.com>; Ni, Ray <ray...@intel.com>; Kumar, > Rahul R <rahul.r.ku...@intel.com>; Gerd Hoffmann <kra...@redhat.com> > Subject: [PATCH v4 10/37] UefiCpuPkg: Add LoongArch64 CPU Timer library > > Add the LoongArch64 CPU Timer library, using CPUCFG 0x4 and 0x5 for > Stable Counter frequency. > > BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=4584 > > Cc: Eric Dong <eric.d...@intel.com> > Cc: Ray Ni <ray...@intel.com> > Cc: Rahul Kumar <rahul1.ku...@intel.com> > Cc: Gerd Hoffmann <kra...@redhat.com> > Signed-off-by: Chao Li <lic...@loongson.cn> > --- > .../BaseLoongArch64CpuTimerLib.inf | 29 ++ > .../BaseLoongArch64CpuTimerLib.uni | 15 ++ > .../BaseLoongArch64CpuTimerLib/CpuTimerLib.c | 251 > ++++++++++++++++++ > UefiCpuPkg/UefiCpuPkg.dsc | 3 + > 4 files changed, 298 insertions(+) > create mode 100644 > UefiCpuPkg/Library/BaseLoongArch64CpuTimerLib/BaseLoongArch64CpuTim > erLib.inf > create mode 100644 > UefiCpuPkg/Library/BaseLoongArch64CpuTimerLib/BaseLoongArch64CpuTim > erLib.uni > create mode 100644 > UefiCpuPkg/Library/BaseLoongArch64CpuTimerLib/CpuTimerLib.c > > diff --git > a/UefiCpuPkg/Library/BaseLoongArch64CpuTimerLib/BaseLoongArch64CpuT > imerLib.inf > b/UefiCpuPkg/Library/BaseLoongArch64CpuTimerLib/BaseLoongArch64CpuT > imerLib.inf > new file mode 100644 > index 0000000000..ab94d91858 > --- /dev/null > +++ > b/UefiCpuPkg/Library/BaseLoongArch64CpuTimerLib/BaseLoongArch64CpuT > imerLib.inf > @@ -0,0 +1,29 @@ > +## @file > +# Base CPU Timer Library > +# > +# Provides base timer support using CPUCFG 0x4 and 0x5 stable counter > frequency. > +# > +# Copyright (c) 2023, Loongson Technology Corporation Limited. All rights > reserved.<BR> > +# SPDX-License-Identifier: BSD-2-Clause-Patent > +# > +## > + > +[Defines] > + INF_VERSION = 0x00010029 > + BASE_NAME = > BaseLoongArch64CpuTimerLib > + FILE_GUID = > 740389C7-CC44-4A2F-88DC-89D97D312E7C > + MODULE_TYPE = BASE > + VERSION_STRING = 1.0 > + LIBRARY_CLASS = TimerLib > + MODULE_UNI_FILE = > BaseLoongArch64CpuTimerLib.uni > + > +[Sources] > + CpuTimerLib.c > + > +[Packages] > + MdePkg/MdePkg.dec > + > +[LibraryClasses] > + BaseLib > + DebugLib > + SafeIntLib > diff --git > a/UefiCpuPkg/Library/BaseLoongArch64CpuTimerLib/BaseLoongArch64CpuT > imerLib.uni > b/UefiCpuPkg/Library/BaseLoongArch64CpuTimerLib/BaseLoongArch64CpuT > imerLib.uni > new file mode 100644 > index 0000000000..72d38ec679 > --- /dev/null > +++ > b/UefiCpuPkg/Library/BaseLoongArch64CpuTimerLib/BaseLoongArch64CpuT > imerLib.uni > @@ -0,0 +1,15 @@ > +// /** @file > +// Base CPU Timer Library > +// > +// Provides base timer support using CPUCFG 0x4 and 0x5 stable counter > frequency. > +// > +// Copyright (c) 2023, Loongson Technology Corporation Limited. All rights > reserved.<BR> > +// > +// SPDX-License-Identifier: BSD-2-Clause-Patent > +// > +// **/ > + > + > +#string STR_MODULE_ABSTRACT #language en-US > "LOONGARCH CPU Timer Library" > + > +#string STR_MODULE_DESCRIPTION #language en-US "Provides > basic timer support using CPUCFG 0x4 and 0x5 stable counter frequency." > diff --git a/UefiCpuPkg/Library/BaseLoongArch64CpuTimerLib/CpuTimerLib.c > b/UefiCpuPkg/Library/BaseLoongArch64CpuTimerLib/CpuTimerLib.c > new file mode 100644 > index 0000000000..828ca4a51a > --- /dev/null > +++ b/UefiCpuPkg/Library/BaseLoongArch64CpuTimerLib/CpuTimerLib.c > @@ -0,0 +1,251 @@ > +/** @file > + CPUCFG 0x4 and 0x5 for Stable Counter frequency instance of Timer > Library. > + > + Copyright (c) 2023, Loongson Technology Corporation Limited. All rights > reserved.<BR> > + > + SPDX-License-Identifier: BSD-2-Clause-Patent > +**/ > + > +#include <Base.h> > +#include <Library/BaseLib.h> > +#include <Library/DebugLib.h> > +#include <Library/SafeIntLib.h> > +#include <Library/TimerLib.h> > +#include <Register/LoongArch64/Cpucfg.h> > + > +/** > + 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; > +} > diff --git a/UefiCpuPkg/UefiCpuPkg.dsc b/UefiCpuPkg/UefiCpuPkg.dsc > index 074fd77461..8e34a9cd6b 100644 > --- a/UefiCpuPkg/UefiCpuPkg.dsc > +++ b/UefiCpuPkg/UefiCpuPkg.dsc > @@ -205,5 +205,8 @@ > UefiCpuPkg/CpuTimerDxeRiscV64/CpuTimerDxeRiscV64.inf > UefiCpuPkg/CpuDxeRiscV64/CpuDxeRiscV64.inf > > +[Components.LOONGARCH64] > + > UefiCpuPkg/Library/BaseLoongArch64CpuTimerLib/BaseLoongArch64CpuTim > erLib.inf > + > [BuildOptions] > *_*_*_CC_FLAGS = -D DISABLE_NEW_DEPRECATED_INTERFACES > -- > 2.27.0
-=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#112695): https://edk2.groups.io/g/devel/message/112695 Mute This Topic: https://groups.io/mt/103129089/21656 Group Owner: devel+ow...@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/leave/9847357/21656/1706620634/xyzzy [arch...@mail-archive.com] -=-=-=-=-=-=-=-=-=-=-=-