From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail03.groups.io (mail03.groups.io [45.79.227.220]) by spool.mail.gandi.net (Postfix) with ESMTPS id 843FFD8120F for ; Fri, 12 Apr 2024 07:34:22 +0000 (UTC) DKIM-Signature: a=rsa-sha256; bh=DOX9HhZIj3THE89IVVMMRsCN59HsJuZgl6lLVubpfKI=; c=relaxed/simple; d=groups.io; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References:MIME-Version:Precedence:List-Subscribe:List-Help:Sender:List-Id:Mailing-List:Delivered-To:Resent-Date:Resent-From:Reply-To:List-Unsubscribe-Post:List-Unsubscribe:Content-Transfer-Encoding; s=20240206; t=1712907261; v=1; b=Ev2uNUdd1yYmqB+0cCcZqO5tXf9UNLrVxuJgDg1fJKiLMMRu01Q+VWQaLMn1NRjJDCslU5bp 3EWWNGtQ8Ybvt8D6UbzbDg+TtYslUl4MgeCjvC4gbZdo0PMYwzKafuIdbD+V+mF4101rAUMnEOA A7RSBe/FUDXSfXxp1yUqLlb8V76m4YBCLgn4yh7mRQDQDvk15Aj91ft1tSnxwJJ4Zx+HeLYBvkm 9zgakCYIcUDJp2TgaE2L/MeCwFpyy8mzWI5psRn77w6xveNsqyBGA8HtbuPgYI7CIkpDTn8+oum YcZezzQikFAyUSuO1HY8S4p5OpzUWmSy4GYgSmTnT/iTA== X-Received: by 127.0.0.2 with SMTP id SUtyYY7687511xhDXBN6qJAs; Fri, 12 Apr 2024 00:34:21 -0700 X-Received: from mail.loongson.cn (mail.loongson.cn [114.242.206.163]) by mx.groups.io with SMTP id smtpd.web10.41422.1712907259845111129 for ; Fri, 12 Apr 2024 00:34:20 -0700 X-Received: from loongson.cn (unknown [10.2.9.245]) by gateway (Coremail) with SMTP id _____8CxWOj14xhmEkcmAA--.2429S3; Fri, 12 Apr 2024 15:34:13 +0800 (CST) X-Received: from code-server.gen (unknown [10.2.9.245]) by localhost.localdomain (Coremail) with SMTP id AQAAf8CxqhL04xhmcZB4AA--.24401S2; Fri, 12 Apr 2024 15:34:12 +0800 (CST) From: "Chao Li" To: devel@edk2.groups.io Cc: Ray Ni , Rahul Kumar , Gerd Hoffmann Subject: [edk2-devel] [PATCH v3 05/13] UefiCpuPkg: Add LoongArch64 CPU Timer instance Date: Fri, 12 Apr 2024 15:34:11 +0800 Message-Id: <20240412073411.3487047-1-lichao@loongson.cn> In-Reply-To: <20240412073254.3486364-1-lichao@loongson.cn> References: <20240412073254.3486364-1-lichao@loongson.cn> MIME-Version: 1.0 X-CM-TRANSID: AQAAf8CxqhL04xhmcZB4AA--.24401S2 X-CM-SenderInfo: xolfxt3r6o00pqjv00gofq/1tbiAQAFCGYXn2oMjAAIsA X-Coremail-Antispam: 1Uk129KBjDUn29KB7ZKAUJUUUUU529EdanIXcx71UUUUU7KY7 ZEXasCq-sGcSsGvfJ3UbIjqfuFe4nvWSU5nxnvy29KBjDU0xBIdaVrnUUvcSsGvfC2Kfnx nUUI43ZEXa7xR_UUUUUUUUU== Precedence: Bulk List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Resent-Date: Fri, 12 Apr 2024 00:34:20 -0700 Resent-From: lichao@loongson.cn Reply-To: devel@edk2.groups.io,lichao@loongson.cn List-Unsubscribe-Post: List-Unsubscribe=One-Click List-Unsubscribe: X-Gm-Message-State: 4kicELexllHRADBzNpdbKURlx7686176AA= Content-Transfer-Encoding: 8bit X-GND-Status: LEGIT Authentication-Results: spool.mail.gandi.net; dkim=pass header.d=groups.io header.s=20240206 header.b=Ev2uNUdd; spf=pass (spool.mail.gandi.net: domain of bounce@groups.io designates 45.79.227.220 as permitted sender) smtp.mailfrom=bounce@groups.io; dmarc=none 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=4734 Cc: Ray Ni Cc: Rahul Kumar Cc: Gerd Hoffmann Signed-off-by: Chao Li Acked-by: Gerd Hoffmann Reviewed-by: Ray Ni --- .../Library/CpuTimerLib/BaseCpuTimerLib.inf | 15 +- .../CpuTimerLib/LoongArch64/CpuTimerLib.c | 250 ++++++++++++++++++ UefiCpuPkg/UefiCpuPkg.dsc | 3 + 3 files changed, 266 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 f0f4ae902a..4a1c7c0510 100644 --- a/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.inf +++ b/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.inf @@ -1,10 +1,15 @@ ## @file # Base CPU Timer Library # -# Provides basic timer support using CPUID Leaf 0x15 XTAL frequency. The performance +# Provides basic timer support. +# +# In x86, using CPUID Leaf 0x15 XTAL frequency. The performance # counter features are provided by the processors time stamp counter. # +# In LoongArch64, using CPUCFG 0x4 and 0x5 for Stable Counter frequency. +# # 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,10 +23,13 @@ [Defines] 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 @@ -31,5 +39,8 @@ [LibraryClasses] DebugLib PcdLib +[LibraryClasses.LoongArch64] + 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..7ba7408498 --- /dev/null +++ b/UefiCpuPkg/Library/CpuTimerLib/LoongArch64/CpuTimerLib.c @@ -0,0 +1,250 @@ +/** @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); + + ASSERT (StableTimerFreq != 0); + + 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 + ); + ASSERT_RETURN_ERROR (Status); + + // + // 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 10b33594e5..2eebd45125 100644 --- a/UefiCpuPkg/UefiCpuPkg.dsc +++ b/UefiCpuPkg/UefiCpuPkg.dsc @@ -110,6 +110,9 @@ [LibraryClasses.common.UEFI_APPLICATION] UefiApplicationEntryPoint|MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf +[LibraryClasses.LoongArch64] + SafeIntLib|MdePkg/Library/BaseSafeIntLib/BaseSafeIntLib.inf + # # Drivers/Libraries within this package # -- 2.27.0 -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#117652): https://edk2.groups.io/g/devel/message/117652 Mute This Topic: https://groups.io/mt/105478494/7686176 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io] -=-=-=-=-=-=-=-=-=-=-=-