From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp-relay-internal-0.canonical.com (smtp-relay-internal-0.canonical.com [185.125.188.122]) by mx.groups.io with SMTP id smtpd.web10.5294.1670472434531866657 for ; Wed, 07 Dec 2022 20:07:15 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@canonical.com header.s=20210705 header.b=n2wXFkKG; spf=pass (domain: canonical.com, ip: 185.125.188.122, mailfrom: heinrich.schuchardt@canonical.com) Received: from mail-wm1-f69.google.com (mail-wm1-f69.google.com [209.85.128.69]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by smtp-relay-internal-0.canonical.com (Postfix) with ESMTPS id CCF7744341 for ; Thu, 8 Dec 2022 04:07:12 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=canonical.com; s=20210705; t=1670472432; bh=bfUEvAcKpjYDei8yC7dj7InkOQ37yu7FkaY0jqddDFo=; h=Message-ID:Date:MIME-Version:Subject:To:Cc:References:From: In-Reply-To:Content-Type; b=n2wXFkKGo9x7dH8yFg+sWWdXDp4Yq0KIfocvuXzp+nbyvQnQ917gDnDR1QgZa/wxW ljAqLoE4MEBIAmPdUzrMTQGGFL30pZtI6NDRD8rvnk0sbfrzLqxSQXq3hXEmdF0TZp p71KTjSrd4P/ss2oit6ru0AcSkESO7igIR9HhCdudvL2LxlCIlTInVpI4mVz/IIrQn fhSIerd3Fe5ShjoZIimlwg08Egy6aOOHzRupjU9ldFZS3wfkpO7fK9wytHsQHtIN/o 6OydRshWwo+OIDXC9LqbHgcuDUQu5yV6iuOl2tcNnsHUTZzFM0WO4gFYRt2pfp5yAg DHGQj7ZlC+NKA== Received: by mail-wm1-f69.google.com with SMTP id c1-20020a7bc001000000b003cfe40fca79so89711wmb.6 for ; Wed, 07 Dec 2022 20:07:12 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:in-reply-to:from:references:cc:to :content-language:subject:user-agent:mime-version:date:message-id :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=bfUEvAcKpjYDei8yC7dj7InkOQ37yu7FkaY0jqddDFo=; b=WESRaSzoiGfTjsmpA8b6hA+bWM4Z+cX/479yFw8Y1ALor00iK42hRpA0IfSEH48Ud0 eBkWEe0OgbVTlIDVhs5EXoHF+MRBnCrKaCopMhpQBwZ2ZWUeU9fMnAiCbBRZh3WN/RqP FqgBeCCQZgPxmjWHal+XVEBYMQ+PPgef/KqX9fAU0AV2rDWpl1zXkrTTkyGt/Zwz3Mg1 66Nq05qxTWruMndz+WVr2tj2RqFHY1wPL30pQ0+vjRUfA+pUFpbsi0u/pX5t4WSPuiBh JnW/zrxqruHaXQeV1Vshr/QSSUHpqA6LwaoKDretOlHsyCMDHVxa5xkLy+CUbE0Rtz+h fEKw== X-Gm-Message-State: ANoB5pl0i6f+Zfjk7s1ajVl+xNWOUMQIAuSSdI8MvWlBIug/B1Wv8mi8 hPRu12vpbJRnf0MwBp5IHd3Vare5wHGJJD/ppaJBwh+UDhApRJzR9RrgRd4dqRlqEBuGKZuvF/v c+HgoaGVylyu4jKyrMu1RZBkP8uROq8Q= X-Received: by 2002:a5d:5305:0:b0:242:25e:e731 with SMTP id e5-20020a5d5305000000b00242025ee731mr36604084wrv.48.1670464797976; Wed, 07 Dec 2022 17:59:57 -0800 (PST) X-Google-Smtp-Source: AA0mqf7ytTgnbH0TmpLUtOgKDr+PMbfo3jxl2Le/e/jqLRVrCVZPb5dv0YtsCB1tOy2c4TdOyCsz+w== X-Received: by 2002:a5d:5305:0:b0:242:25e:e731 with SMTP id e5-20020a5d5305000000b00242025ee731mr36604063wrv.48.1670464797546; Wed, 07 Dec 2022 17:59:57 -0800 (PST) Received: from [192.168.123.94] (ip-088-152-145-137.um26.pools.vodafone-ip.de. [88.152.145.137]) by smtp.gmail.com with ESMTPSA id i10-20020a1c540a000000b003d1f2c3e571sm3165639wmb.33.2022.12.07.17.59.56 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Wed, 07 Dec 2022 17:59:56 -0800 (PST) Message-ID: <18a8f742-4f5a-e267-94b5-72d4f4836e1c@canonical.com> Date: Thu, 8 Dec 2022 02:59:55 +0100 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Thunderbird/102.5.1 Subject: Re: [RFC PATCH V2 07/19] MdePkg: Add ArchTimerLib library To: Sunil V L Cc: Jian J Wang , Liming Gao , Eric Dong , Ray Ni , Rahul Kumar , Debkumar De , Catharine West , Daniel Schaefer , Abner Chang , Leif Lindholm , Andrew Fish , Ard Biesheuvel , Anup Patel , devel@edk2.groups.io References: <20220907113626.540065-1-sunilvl@ventanamicro.com> <20220907113626.540065-8-sunilvl@ventanamicro.com> From: Heinrich Schuchardt In-Reply-To: <20220907113626.540065-8-sunilvl@ventanamicro.com> Content-Language: en-US Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit On 9/7/22 13:36, Sunil V L wrote: > This library implements the TimerLib.h functionality. This library > is similar to CpuTimerLib but needs the library constructor. > > Signed-off-by: Sunil V L > --- > MdePkg/Library/ArchTimerLib/ArchTimerLib.inf | 40 +++ > MdePkg/Library/ArchTimerLib/RiscV64/CpuTimerLib.c | 299 ++++++++++++++++++++ > MdePkg/Library/ArchTimerLib/ArchTimerLib.uni | 14 + > 3 files changed, 353 insertions(+) > > diff --git a/MdePkg/Library/ArchTimerLib/ArchTimerLib.inf b/MdePkg/Library/ArchTimerLib/ArchTimerLib.inf > new file mode 100644 > index 000000000000..b61ae58d0142 > --- /dev/null > +++ b/MdePkg/Library/ArchTimerLib/ArchTimerLib.inf > @@ -0,0 +1,40 @@ > +## @file > +# Timer Library Instance which needs a constructor for the architecture. > +# > +# Copyright (c) 2016 - 2019, Hewlett Packard Enterprise Development LP. All rights reserved.
> +# Copyright (c) 2022, Ventana Micro System Inc. All rights reserved.
> +# > +# SPDX-License-Identifier: BSD-2-Clause-Patent > +# > +## > + > +[Defines] > + INF_VERSION = 0x0001001b > + BASE_NAME = ArchTimerLib > + FILE_GUID = D3CF51A9-1CEA-4776-A8AB-CCFD14D7DAAF > + MODULE_TYPE = BASE > + VERSION_STRING = 1.0 > + LIBRARY_CLASS = TimerLib > + MODULE_UNI_FILE = ArchTimerLib.uni > + CONSTRUCTOR = ArchTimerLibConstructor > + > +[Sources.RISCV64] > + RiscV64/CpuTimerLib.c > + > +[Packages] > + MdePkg/MdePkg.dec > + MdeModulePkg/MdeModulePkg.dec > + UefiCpuPkg/UefiCpuPkg.dec > + EmbeddedPkg/EmbeddedPkg.dec > + > +[LibraryClasses] > + BaseLib > + DebugLib > + FdtLib > + HobLib > + > +[Pcd] > + gUefiCpuPkgTokenSpaceGuid.PcdRiscVTimerFrequencyInHz ## CONSUMES > + > +[Guids] > + gFdtHobGuid > diff --git a/MdePkg/Library/ArchTimerLib/RiscV64/CpuTimerLib.c b/MdePkg/Library/ArchTimerLib/RiscV64/CpuTimerLib.c > new file mode 100644 > index 000000000000..a81ac8c37cad > --- /dev/null > +++ b/MdePkg/Library/ArchTimerLib/RiscV64/CpuTimerLib.c > @@ -0,0 +1,299 @@ > +/** @file > + RISC-V instance of Timer Library. > + > + Copyright (c) 2016 - 2022, Hewlett Packard Enterprise Development LP. All rights reserved.
> + Copyright (c) 2022, Ventana Micro Systems Inc. All rights reserved.
> + > + SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > + > +STATIC UINT32 mTimeBaseFrequency; > +STATIC BOOLEAN mTimeBaseFreqInitialized; > + > +UINT32 > +InternalGetTimerFrequency( > + VOID > + ) > +{ > + return mTimeBaseFrequency; > +} > + > + > +/** > + Stalls the CPU for at least the given number of ticks. > + > + Stalls the CPU for at least the given number of ticks. It's invoked by > + MicroSecondDelay() and NanoSecondDelay(). > + > + @param Delay A period of time to delay in ticks. > + > +**/ > +VOID > +InternalRiscVTimerDelay ( > + IN UINT32 Delay > + ) > +{ > + UINT32 Ticks; > + UINT32 Times; > + > + Times = Delay >> (RISCV_TIMER_COMPARE_BITS - 2); > + Delay &= ((1 << (RISCV_TIMER_COMPARE_BITS - 2)) - 1); > + do { > + // > + // The target timer count is calculated here > + // > + Ticks = csr_read(CSR_TIME) + Delay; > + Delay = 1 << (RISCV_TIMER_COMPARE_BITS - 2); > + while (((Ticks - csr_read(CSR_TIME)) & (1 << (RISCV_TIMER_COMPARE_BITS - 1))) == 0) { > + CpuPause (); Is CpuPause() guaranteed to return before two ticks have elapsed? '== 0' might be too strict especially when considering that interrupts might have to be handled in future. You don't want this routine to hang for another 2^32 ticks. Best regards Heinrich > + } > + } while (Times-- > 0); > +} > + > +/** > + 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 > + ) > +{ > + InternalRiscVTimerDelay ( > + (UINT32)DivU64x32 ( > + MultU64x32 ( > + MicroSeconds, > + InternalGetTimerFrequency() > + ), > + 1000000u > + ) > + ); > + 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 > + ) > +{ > + InternalRiscVTimerDelay ( > + (UINT32)DivU64x32 ( > + MultU64x32 ( > + NanoSeconds, > + InternalGetTimerFrequency() > + ), > + 1000000000u > + ) > + ); > + return NanoSeconds; > +} > + > +/** > + Retrieves the current value of a 64-bit free running performance counter. > + > + Retrieves the current value of a 64-bit free running performance counter. The > + counter can either count up by 1 or count down by 1. If the physical > + performance counter counts by a larger increment, then the counter values > + must be translated. The properties of the counter can be retrieved from > + GetPerformanceCounterProperties(). > + > + @return The current value of the free running performance counter. > + > +**/ > +UINT64 > +EFIAPI > +GetPerformanceCounter ( > + VOID > + ) > +{ > + return (UINT64)csr_read (CSR_TIME); > +} > + > +/**return > + Retrieves the 64-bit frequency in Hz and the range of performance counter > + values. > + > + If StartValue is not NULL, then the value that the performance counter starts > + with immediately after is it rolls over is returned in StartValue. If > + EndValue is not NULL, then the value that the performance counter end with > + immediately before it rolls over is returned in EndValue. The 64-bit > + frequency of the performance counter in Hz is always returned. If StartValue > + is less than EndValue, then the performance counter counts up. If StartValue > + is greater than EndValue, then the performance counter counts down. For > + example, a 64-bit free running counter that counts up would have a StartValue > + of 0 and an EndValue of 0xFFFFFFFFFFFFFFFF. A 24-bit free running counter > + that counts down would have a StartValue of 0xFFFFFF and an EndValue of 0. > + > + @param StartValue The value the performance counter starts with when it > + rolls over. > + @param EndValue The value that the performance 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 = 32 - 1; > + } > + > + return InternalGetTimerFrequency(); > +} > + > +/** > + 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; > + > + // > + // Ticks > + // Time = --------- x 1,000,000,000 > + // Frequency > + // > + NanoSeconds = MultU64x32 (DivU64x32Remainder (Ticks, InternalGetTimerFrequency(), &Remainder), 1000000000u); > + > + // > + // Frequency < 0x100000000, so Remainder < 0x100000000, then (Remainder * 1,000,000,000) > + // will not overflow 64-bit. > + // > + NanoSeconds += DivU64x32 (MultU64x32 ((UINT64)Remainder, 1000000000u), InternalGetTimerFrequency()); > + > + return NanoSeconds; > +} > + > +STATIC > +RETURN_STATUS > +EFIAPI > +FdtInitializeTimerFrequency ( > + VOID > + ) > +{ > + VOID *Hob; > + VOID *Fdt; > + INT32 CpusNode, Len; > + const fdt32_t *Prop; > + > + Hob = GetFirstGuidHob (&gFdtHobGuid); > + if ((Hob == NULL) || (GET_GUID_HOB_DATA_SIZE (Hob) != sizeof (UINT64))) { > + DEBUG ((DEBUG_ERROR, "%a: No FDT Hob found\n", __FUNCTION__)); > + return EFI_NOT_FOUND; > + } > + > + Fdt = (VOID *)(UINTN)*(UINT64 *)GET_GUID_HOB_DATA (Hob); > + > + if (fdt_check_header (Fdt) != 0) { > + DEBUG (( > + DEBUG_ERROR, > + "%a: No DTB found @ 0x%p\n", > + __FUNCTION__, > + Fdt > + )); > + return EFI_NOT_FOUND; > + } > + > + // The "cpus" node resides at the the root of the DT. Fetch it. > + CpusNode = fdt_path_offset (Fdt, "/cpus"); > + if (CpusNode < 0) { > + DEBUG ((DEBUG_ERROR, "%a: Invalid /cpus node\n", __FUNCTION__)); > + return EFI_NOT_FOUND; > + } > + > + Prop = fdt_getprop((void *)Fdt, CpusNode, "timebase-frequency", &Len); > + if (!Prop) { > + DEBUG ((DEBUG_ERROR, "%a: timebase-frequency propertynot found\n", __FUNCTION__)); > + return EFI_NOT_FOUND; > + } > + > + mTimeBaseFrequency = fdt32_to_cpu(*Prop); > + DEBUG((DEBUG_INFO, "%a: Timer Frequency (DT) is set to 0x%x\n", __FUNCTION__, mTimeBaseFrequency)); > + > + return EFI_SUCCESS; > +} > +/** > + Initializes the Timer Frequency by reading it from the DTB > + > +**/ > +RETURN_STATUS > +EFIAPI > +ArchTimerLibConstructor ( > + VOID > + ) > +{ > + EFI_STATUS Status; > + > + /* > + * Initialize only once > + */ > + if (mTimeBaseFreqInitialized) { > + return EFI_SUCCESS; > + } > + > + mTimeBaseFreqInitialized = 1; > + > + Status = FdtInitializeTimerFrequency(); > + > + if (EFI_ERROR(Status)) { > + mTimeBaseFrequency = PcdGet32 (PcdRiscVTimerFrequencyInHz); > + DEBUG((DEBUG_INFO, "%a: Timer Frequency (PCD) is set to 0x%x\n", __FUNCTION__, mTimeBaseFrequency)); > + } > + > + return EFI_SUCCESS; > +} > diff --git a/MdePkg/Library/ArchTimerLib/ArchTimerLib.uni b/MdePkg/Library/ArchTimerLib/ArchTimerLib.uni > new file mode 100644 > index 000000000000..1c900bea42bf > --- /dev/null > +++ b/MdePkg/Library/ArchTimerLib/ArchTimerLib.uni > @@ -0,0 +1,14 @@ > +// /** @file > +// Base CPU Timer Library > +// > +// Provides basic timer support using architecture specific methods. > +// > +// Copyright (c) 2022, Ventana Micro Systems Inc. All rights reserved.
> +// > +// SPDX-License-Identifier: BSD-2-Clause-Patent > +// > +// **/ > + > +#string STR_MODULE_ABSTRACT #language en-US "CPU Timer Library" > + > +#string STR_MODULE_DESCRIPTION #language en-US "Provides basic timer support using architecture specific methods"