public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: "Laszlo Ersek" <lersek@redhat.com>
To: devel@edk2.groups.io, lichao@loongson.cn
Cc: Eric Dong <eric.dong@intel.com>, Ray Ni <ray.ni@intel.com>,
	Rahul Kumar <rahul1.kumar@intel.com>,
	Gerd Hoffmann <kraxel@redhat.com>
Subject: Re: [edk2-devel] [PATCH v3 11/39] UefiCpuPkg: Add LoongArch64 CPU Timer library
Date: Wed, 22 Nov 2023 17:12:25 +0100	[thread overview]
Message-ID: <2e42db7c-a927-f47b-7d80-632895b11e1b@redhat.com> (raw)
In-Reply-To: <20231117100007.3609080-1-lichao@loongson.cn>

On 11/17/23 11:00, Chao Li wrote:
> 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.dong@intel.com>
> Cc: Ray Ni <ray.ni@intel.com>
> Cc: Rahul Kumar <rahul1.kumar@intel.com>
> Cc: Gerd Hoffmann <kraxel@redhat.com>
> Signed-off-by: Chao Li <lichao@loongson.cn>
> ---
>  .../BaseLoongArch64CpuTimerLib.inf            |  30 +++
>  .../BaseLoongArch64CpuTimerLib.uni            |  15 ++
>  .../BaseLoongArch64CpuTimerLib/CpuTimerLib.c  | 226 ++++++++++++++++++
>  UefiCpuPkg/UefiCpuPkg.dsc                     |   3 +
>  4 files changed, 274 insertions(+)
>  create mode 100644 UefiCpuPkg/Library/BaseLoongArch64CpuTimerLib/BaseLoongArch64CpuTimerLib.inf
>  create mode 100644 UefiCpuPkg/Library/BaseLoongArch64CpuTimerLib/BaseLoongArch64CpuTimerLib.uni
>  create mode 100644 UefiCpuPkg/Library/BaseLoongArch64CpuTimerLib/CpuTimerLib.c

(1) sorry about the annoying comment, but the library should be called
(preferably) BaseTimerLibLoongArch64Cpu.

We're frequently not consistent with the following library instance
naming scheme, but in theory anyway, library instances should be named
as follows:

  <firmware module type><lib class name><library instance identifier>

Thus, in this case, Base + TimerLib + LoongArch64Cpu.

update UNI file name, INF file name, directory name, BASE_NAME and
MODULE_UNI_FILE accordingly (if you agree)

> 
> diff --git a/UefiCpuPkg/Library/BaseLoongArch64CpuTimerLib/BaseLoongArch64CpuTimerLib.inf b/UefiCpuPkg/Library/BaseLoongArch64CpuTimerLib/BaseLoongArch64CpuTimerLib.inf
> new file mode 100644
> index 0000000000..c00c215aec
> --- /dev/null
> +++ b/UefiCpuPkg/Library/BaseLoongArch64CpuTimerLib/BaseLoongArch64CpuTimerLib.inf
> @@ -0,0 +1,30 @@
> +## @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                       = 0x00010005

(2) Can you use the most recent INF file version? (Generally applies to
all new INF files in the series.)

The latest version is 1.29
<https://tianocore-docs.github.io/edk2-InfSpecification/draft/>, and you
can just write "1.29" here.

> +  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.common]
> +  CpuTimerLib.c

(3) ".common" is not an error, but superfluous here.

> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  UefiCpuPkg/UefiCpuPkg.dec

(4) Do you actually consume any artifact from "UefiCpuPkg.dec"?

Unless you do, there's no need to depend on "UefiCpuPkg.dec" here.

(5) Relatedly: the TimerLib class is declared in "MdePkg.dec". Thus, if
you indeed don't need anything from "UefiCpuPkg.dec", I'd suggest moving
this library instance under MdePkg.

> +
> +[LibraryClasses]
> +  BaseLib
> +  PcdLib
> +  DebugLib

(6) If it's not too much of a burden, it's best to keep library classes
alphabetically sorted.

> diff --git a/UefiCpuPkg/Library/BaseLoongArch64CpuTimerLib/BaseLoongArch64CpuTimerLib.uni b/UefiCpuPkg/Library/BaseLoongArch64CpuTimerLib/BaseLoongArch64CpuTimerLib.uni
> new file mode 100644
> index 0000000000..72d38ec679
> --- /dev/null
> +++ b/UefiCpuPkg/Library/BaseLoongArch64CpuTimerLib/BaseLoongArch64CpuTimerLib.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..349b881cbc
> --- /dev/null
> +++ b/UefiCpuPkg/Library/BaseLoongArch64CpuTimerLib/CpuTimerLib.c
> @@ -0,0 +1,226 @@
> +/** @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/TimerLib.h>
> +#include <Library/BaseLib.h>
> +#include <Library/DebugLib.h>
> +#include <Register/LoongArch64/Cpucfg.h>

(7) It's best to keep the Library includes in sync with the
[LibraryClasses] section from the INF file.

(And to keep the #include directives alphabetically sorted as well.)

You are including <Library/TimerLib.h> here because the file is going to
define those functions. OK. This is the sole justified difference
between the Library #includes here and the [LibraryClasses] section in
the INF file.

Regarding dependencies, you are including <Library/BaseLib.h> and
<Library/DebugLib.h>, but [LibraryClasses] in addition lists PcdLib.
Thus, <Library/PcdLib.h> is missing here. (You are likely getting it
included recursively, but that's not clean enough.)

> +
> +/**
> +  Calculate clock frequency using CPUCFG 0x4 and 0x5 registers.
> +
> +  @param  VOID.

(8) This @param is useless and should be avoided, AFAICT. I think the
EccCheck plugin will not complain.

> +
> +  @return The frequency in Hz.
> +
> +**/
> +UINT32
> +EFIAPI
> +CalcConstFreq (

(9) Should be STATIC, and should *not* be EFIAPI. It is not a public
library or protocol interface.

> +  VOID
> +  )
> +{
> +  UINT32                 BaseFreq;
> +  UINT32                 ClockMultiplier;
> +  UINT32                 ClockDivide;
> +  CPUCFG_REG4_INFO_DATA  CCFreq;

(10) Per edk2 coding style, when acronyms and abbreviations are grouped
together, each individual acronym itself is supposed to be CamelCase.
For example, when we use "PCI" in identifiers, it becomes "Pci". So I
think this variable should be called "CcFreq", where "CC" stands for
"CPU Config". If I'm wrong about "CC", then please ignore this point.

> +  CPUCFG_REG5_INFO_DATA  CpucfgReg5Data;
> +  UINT32                 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;

(11) My comment here probably affects the header file where you
introduced the CC_FREQ field name. It should be CcFreq.

Same for MUL and DIV below.

> +  ClockMultiplier = CpucfgReg5Data.Bits.CC_MUL & 0xFFFFULL;
> +  ClockDivide     = CpucfgReg5Data.Bits.CC_DIV & 0xFFFFULL;

(12) Seeing how the Uint32 members of the unions (?) are used for
populating the bitfields, the ULL suffix on the masks seems superfluous.
The results are stored to UINT32 local variables, too. 0xFFFF should
suffice.

> +
> +  if (!BaseFreq || !ClockMultiplier || !ClockDivide) {

(13) The edk2 coding style does not like scalar types *other* than
BOOLEAN to be used in logical context. Please rewrite as:

  (BaseFreq == 0) || (ClockMultiplier == 0) || (ClockDivide == 0)

> +    DEBUG ((DEBUG_ERROR, "LoongArch Stable Timer is not available in the CPU, hence this library cannot be used.\n"));

(13) I think this line is a bit too long (117 chars). I think the
currently accepted limit (?) is 100 characters (but I'm unsure).

Recommend to break this up to multiple lines.

> +    StableTimerFreq = 0;

(14) Needless assignment AFAICT.

> +    ASSERT (0);

(15) Should be ASSERT (FALSE).

(16) I recommend that a CpuDeadLoop() call be added here too, because
ASSERT()s are compiled out of RELEASE builds.

> +  } else {

(17) an "else" branch seems awkward here; code after ASSERT (FALSE) /
CpuDeadLoop() is supposed to be unreachable, so whatever you do here can
just be unnested.

> +    StableTimerFreq = (BaseFreq * ClockMultiplier / ClockDivide);

(18) Unsafe multiplication.

ClockMultiplier is at most 0xFFFF, but BaseFreq (from CC_FREQ) may
theoretically be as high as MAX_UINT32.

- If there is a LoongArch64 specification that places a 0xFFFF limit on
CC_FREQ, then please add such an ASSERT() here.

- If there is no such specification, then cast either BaseFreq or
ClockMultiplier to UINT64. A UINT64 multiplication will not overflow
here (because MAX_UINT32 * 0xFFFF fits in 32+16=48 bits).


(19) In turn, the result of the division needs to be checked against two
boundaries:

- it must not be zero (could occur if the divisor is too large, relative
to the product). Returning zero from this function would case problems
elsewhere.

- it must fit in a UINT32. Better yet, change the return type of the
function to UINT64.


> +  }
> +
> +  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
> +  )
> +{
> +  UINTN  Count, Ticks, Start, End;
> +
> +  Count = (CalcConstFreq () * MicroSeconds) / 1000000;

(20) Unchecked multiplication. CalcConstFreq() may be as large as

  (MAX_UINT32 * 0xFFFF / 1)

and then dependent on MicroSeconds we could overflow even a UINT64 here.

This function does not permit returning errors, so I'm not fully sure
what to do. Normally I'd recommend a safe UINT64 multiplication from
SafeIntLib (and then storing the quotient, from the division, in a UINT64).

> +  Start = AsmReadStableCounter ();
> +  End   = Start + Count;
> +
> +  do {
> +    Ticks = AsmReadStableCounter ();
> +  } while (Ticks < End);

The rest of this patch indicates that

(a) the performance counter is just the stable counter
(GetPerformanceCounter() simply calls AsmReadStableCounter()), and that

(b) the range is [BIT2, BIT48-1] (both sides inclusive).

(21) The problem is that this simple loop does not consider wrap-around.

We should do something like this:

  RETURN_STATUS  Status;
  UINT64         Remaining;
  UINT64         Start;

  Status = SafeUint64Mult (CalcConstFreq (), MicroSeconds, &Remaining);
  ASSERT_RETURN_ERROR (Status);
  if (RETURN_ERROR (Status)) {
    CpuDeadLoop ();
  }

  //
  // for the given number of microseconds, the needed tick count should
  // be rounded upwards
  //
  Status = SafeUint64Add (Remaining, 1000000 - 1, &Remaining);
  ASSERT_RETURN_ERROR (Status);
  if (RETURN_ERROR (Status)) {
    CpuDeadLoop ();
  }

  Remaining = DivU64x32 (Remaining, 1000000);
  Start = AsmReadStableCounter ();

  while (Remaining > 0) {
    UINT64  Stop;
    UINT64  Diff;

    Stop = AsmReadStableCounter ();

    if (Start <= Stop) {
      //
      // no wrap-around
      //
      Diff = Stop - Start;
    } else {
      //
      // wrap-around
      //
      Diff = (BIT48 - Start) + (Stop - BIT2);
    }

    Start = Stop;

    Remaining -= MIN (Remaining, Diff);
  }

> +
> +  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
> +  )
> +{
> +  UINT32  MicroSeconds;
> +
> +  if (NanoSeconds % 1000 == 0) {
> +    MicroSeconds = NanoSeconds/1000;
> +  } else {
> +    MicroSeconds = NanoSeconds/1000 + 1;
> +  }

(22) MicroSeconds should have type UINTN.

(23) Using DivU64x32Remainder() would be more idiomatic.

(

I agree that, if we find that the remainder is nonzero, adding 1 to the
quotient is safe, for the original UINTN range too.

Initial condition:

  ns <= MAX_UINTN

Divide by 1000 (mathematically):

  ns/1000 <= MAX_UINTN/1000

Because floor(x) <= x, we can expand the left hand side:

  floor(ns/1000) <= ns/1000 <= MAX_UINTN/1000

Drop the middle:

  floor(ns/1000) <= MAX_UINTN/1000

Add 1:

  floor(ns/1000) + 1 <= MAX_UINTN/1000 + 1

At the left hand side, we now have the C language result (the truncated,
then incremented, quotinent).

Now, a small detour:

  1/1000 < 1

Multiply by x (assuming x>0):

  x / 1000 < x

Substitute MAX_UINTN for x (MAX_UINTN is positive):

  MAX_UINTN/1000 < MAX_UINTN

Then use this to expand the right hand side:

  floor(ns/1000) + 1 <= MAX_UINTN/1000 + 1 < MAX_UINTN + 1

Drop the middle:

  floor(ns/1000) + 1 < MAX_UINTN + 1

Given that both sides are integers, we get

  floor(ns/1000) + 1 <= MAX_UINTN

which is what we needed.

)

> +
> +  MicroSecondDelay (MicroSeconds);
> +
> +  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 AsmReadStableCounter ();
> +}
> +
> +/**
> +  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 = BIT2;
> +  }
> +
> +  if (EndValue != NULL) {
> +    *EndValue = BIT48 - 1;
> +  }
> +
> +  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;
> +
> +  Frequency = GetPerformanceCounterProperties (NULL, NULL);
> +
> +  //
> +  //          Ticks
> +  // Time = --------- x 1,000,000,000
> +  //        Frequency
> +  //
> +  NanoSeconds = MultU64x32 (DivU64x64Remainder (Ticks, Frequency, &Remainder), 1000000000u);

(24) I understand this is being copied from elsewhere, but the
multiplication by 10^9 should be checked against overflow, using
SafeIntLib. If we have e.g. a 100 MHz clock, then passing in
Ticks=MAX_UINT64 will lead to an overflow. :(

> +
> +  //
> +  // 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.
> +  //

What we want here is (Remainder * 10^9 / Frequency), and in that we want
the product not to overflow 2^64 - 1. Thus, we need

  Remainder * 10^9 <= 2^64 - 1

  Remainder <= (2^64 - 1) / 10^9

The floor -- i.e., integral part -- of the RHS is 18,446,744,073
decimal, or 100_01001011_10000010_11111010_00001001 binary. The most
significant bit that is set is bit 34. But that's not a sufficient
condition, if we only consider the MSB in Remainder, because other bits
that should be clear (such as bit 33) could still be set. The sufficient
condition is thus that the MSB be <= 33. Therefore the comment is OK.

> +  Shift        = MAX (0, HighBitSet64 (Remainder) - 33);

Quirky, but correct.

If Remainder is 0, then HighBitSet64 returns -1, and we compare -34 vs.
0 -- we get zero. OK, no shift needed.

Otherwise, if HighBitSet64 returns a value in the range [0..33], then we
compare [-33..0] vs 0 -- we get zero from MAX. OK, no shift needed.

Otherwise, HighBitSet64 returns a value from the range [34..63], then we
compare [1..30] against zero, and the former prevails (gets stored to
Shift). OK.

> +  Remainder    = RShiftU64 (Remainder, (UINTN)Shift);
> +  Frequency    = RShiftU64 (Frequency, (UINTN)Shift);

I *think* this approach will ensure that Frequency is not zero.
Remainder is strictly smaller than Frequency, and we shift out only so
many LSBs from Remainder (and Frequency) that (Remainder * 10^9) below
*just* not overflow. That means Remainder should not end up being zeroed
out, and so Frequency shouldn't either (the MSB of the original
Frequency is larger than or equal to the MSB of the original Remainder). OK.

> +  NanoSeconds += DivU64x64Remainder (MultU64x32 (Remainder, 1000000000u), Frequency, NULL);

So the RHS here may give us a proper NanoSeconds increment, but how do
we know that the addition will not overflow NanoSeconds?

Here's an example:

  Ticks = 18,446,744,055,553,255,925 (0xFFFF_FFFB_C5CC_E9F5)
  Frequency = 999,999,999 (0x3B9A_C9FF)

(

The idea with this example is that dividing Ticks by Frequency and then
multiplying the result with 1,000,000,000 causes a *very slight* blow-up:

  Ticks / 999,999,999 * 1,000,000,000 =
  Ticks * (1,000,000,000 / 999,999,999)

in such a tricky way that this blow-up:

(a) *just* doesn't overflow the first part of the function (where we use
the integral multiples of Frequency), but

(b) does overflow the last part (where we use the remaining, fractional,
multiple of Frequency).

The way to achieve that, after setting Frequency to just below 1GHz for
the above blow-up, is to start with Ticks = MAX_UINT64, perform the
division, then maximize Remainder in comprison to the divisor (i.e.,
Frequency) -- increase Remainder to (Frequency-1) --, then recalculate
Ticks from that *backwards* (increase Ticks the same as we increased
Remainder).

)

And then this happens:

- the initial DivU64x64Remainder (Ticks, Frequency, &Remainder) call
returns 18,446,744,073 (0x4_4B82_FA09) as quotient, and sets Remainder
to 999,999,998 (0x3B9A_C9FE, binary 111011_10011010_11001001_11111110).

- the first MultU64x32() call produces 18,446,744,073,000,000,000 in
NanoSeconds (0xFFFF_FFFF_D5B5_1A00).

- Remainder's MSB is bit 29, thus Shift gets assigned 0.

- Multiplying Remainder by 1,000,000,000 produces
999,999,998,000,000,000 (0xDE0_B6B3_302E_6C00). No overflow, as intended.

- Dividing that product by Frequency produces 999,999,998 (0x3B9A_C9FE)
as the *increment* for NanoSeconds.

- Adding this increment (0x3B9A_C9FE) to NanoSeconds from earlier
(0xFFFF_FFFF_D5B5_1A00) *does* overflow: the result would be
0x1_0000_0000_114F_E3FE!

(25) This proves that, generally speaking, the final "+=" operation
(increment) is unsafe -- in every TimerLib instance in edk2 that uses
this calculation --, and should be replaced with an addition from
SafeIntLib.

I'm not asking for a tree-wide fix, but using SafeIntLib here would be nice.


> +
> +  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/BaseLoongArch64CpuTimerLib.inf
> +
>  [BuildOptions]
>    *_*_*_CC_FLAGS = -D DISABLE_NEW_DEPRECATED_INTERFACES

(26) And then this should go into MdePkg.dec, according to points (4)
and (5) above.

Thanks
Laszlo



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#111613): https://edk2.groups.io/g/devel/message/111613
Mute This Topic: https://groups.io/mt/102644766/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/leave/12367111/7686176/1913456212/xyzzy [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



  reply	other threads:[~2023-11-22 16:12 UTC|newest]

Thread overview: 71+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <20231117095742.3605778-1-lichao@loongs>
2023-11-17  9:58 ` [edk2-devel] [PATCH v3 01/39] MdePkg: Add the header file named Csr.h for LoongArch64 Chao Li
2023-11-17  9:58 ` [edk2-devel] [PATCH v3 02/39] MdePkg: Add LoongArch64 FPU function set into BaseCpuLib Chao Li
2023-11-17  9:59 ` [edk2-devel] [PATCH v3 03/39] MdePkg: Add LoongArch64 exception function set into BaseLib Chao Li
2023-11-17  9:59 ` [edk2-devel] [PATCH v3 04/39] MdePkg: Add LoongArch64 local interrupt " Chao Li
2023-11-17  9:59 ` [edk2-devel] [PATCH v3 05/39] MdePkg: Add LoongArch Cpucfg function Chao Li
2023-11-17  9:59 ` [edk2-devel] [PATCH v3 06/39] MdePkg: Add read stable counter operation for LoongArch Chao Li
2023-11-17  9:59 ` [edk2-devel] [PATCH v3 07/39] MdePkg: Add CSR " Chao Li
2023-11-17  9:59 ` [edk2-devel] [PATCH v3 08/39] MdePkg: Add IOCSR " Chao Li
2023-11-17  9:59 ` [edk2-devel] [PATCH v3 09/39] MdePkg: Add a new library named PeiServicesTablePointerLibReg Chao Li
2023-11-17 11:35   ` Leif Lindholm
2023-11-20  3:07     ` Chao Li
2023-11-21 14:37   ` Laszlo Ersek
2023-11-22  1:47     ` Chao Li
2023-11-24 11:35       ` Laszlo Ersek
2023-11-27  3:27         ` Chao Li
2023-12-01  0:32           ` 回复: " gaoliming via groups.io
2023-12-01  8:20             ` Chao Li
     [not found]         ` <179B5D231F190982.32091@groups.io>
2023-11-29  1:35           ` Chao Li
2023-11-17  9:59 ` [edk2-devel] [PATCH v3 10/39] MdePkg: Add method of LoongArch64 to PeiServicesTablePointerLibReg Chao Li
2023-11-17 10:00 ` [edk2-devel] [PATCH v3 11/39] UefiCpuPkg: Add LoongArch64 CPU Timer library Chao Li
2023-11-22 16:12   ` Laszlo Ersek [this message]
2023-11-22 16:13     ` Laszlo Ersek
2023-11-23 11:43     ` Chao Li
2023-12-11 17:16       ` Laszlo Ersek
2023-12-12  3:45         ` Chao Li
2023-11-17 10:00 ` [edk2-devel] [PATCH v3 12/39] UefiCpuPkg: Add CPU exception library for LoongArch Chao Li
2023-11-17 10:00 ` [edk2-devel] [PATCH v3 13/39] UefiCpuPkg: Add CpuMmuLib.h to UefiCpuPkg Chao Li
2023-11-17 20:18   ` Andrei Warkentin
2023-11-20  3:26     ` Chao Li
2023-11-30  0:59   ` Ni, Ray
2023-11-30  2:25     ` Chao Li
     [not found]     ` <179C457B5B852375.31732@groups.io>
2023-12-04  7:31       ` Chao Li
2023-12-05  8:27         ` Ni, Ray
2023-12-05 12:27           ` Chao Li
     [not found]           ` <179DEF40376B662A.18076@groups.io>
2023-12-08  2:10             ` Chao Li
2023-12-11  8:13               ` Ni, Ray
2023-12-11  8:19                 ` Chao Li
2023-11-17 10:00 ` [edk2-devel] [PATCH v3 14/39] UefiCpuPkg: Add LoongArch64CpuMmuLib " Chao Li
2023-11-17 10:00 ` [edk2-devel] [PATCH v3 15/39] UefiCpuPkg: Add multiprocessor library for LoongArch64 Chao Li
2023-11-17 10:00 ` [edk2-devel] [PATCH v3 16/39] UefiCpuPkg: Add CpuDxe driver " Chao Li
2023-11-17 10:00 ` [edk2-devel] [PATCH v3 17/39] EmbeddedPkg: Add PcdPrePiCpuIoSize width for LOONGARCH64 Chao Li
2023-11-17 10:01 ` [edk2-devel] [PATCH v3 18/39] ArmVirtPkg: Move PCD of FDT base address and FDT padding to OvmfPkg Chao Li
2023-11-17 10:01 ` [edk2-devel] [PATCH v3 19/39] MdePkg: Add a PCD feature flag named PcdPciIoTranslationIsEnabled Chao Li
2023-11-17 10:01 ` [edk2-devel] [PATCH v3 20/39] UefiCpuPkg: Add MMIO method in CpuIo2Dxe Chao Li
2023-11-17 10:01 ` [edk2-devel] [PATCH v3 21/39] ArmVirtPkg: Enable UefiCpuPkg version CpuIo2Dxe Chao Li
2023-11-17 10:01 ` [edk2-devel] [PATCH v3 22/39] ArmPkg: Remove ArmPciCpuIo2Dxe from ArmPkg Chao Li
2023-11-17 13:13   ` Leif Lindholm
2023-11-20  3:24     ` Chao Li
2023-11-20 18:47       ` Leif Lindholm
2023-11-21  1:10         ` Chao Li
2023-11-17 10:01 ` [edk2-devel] [PATCH v3 23/39] OvmfPkg/RiscVVirt: Enable UefiCpuPkg version CpuIo2Dxe Chao Li
2023-11-17 20:15   ` Andrei Warkentin
2023-11-20  3:04     ` Chao Li
2023-11-17 10:01 ` [edk2-devel] [PATCH v3 24/39] OvmfPkg/RiscVVirt: Remove PciCpuIo2Dxe from RiscVVirt Chao Li
2023-11-17 10:02 ` [edk2-devel] [PATCH v3 25/39] ArmVirtPkg: Move the FdtSerialPortAddressLib to OvmfPkg Chao Li
2023-11-17 10:02 ` [edk2-devel] [PATCH v3 26/39] ArmVirtPkg: Move the PcdTerminalTypeGuidBuffer into OvmfPkg Chao Li
2023-11-17 10:02 ` [edk2-devel] [PATCH v3 27/39] ArmVirtPkg: Move PlatformBootManagerLib to OvmfPkg Chao Li
2023-11-17 10:02 ` [edk2-devel] [PATCH v3 28/39] OvmfPkg/LoongArchVirt: Add stable timer driver Chao Li
2023-11-17 10:02 ` [edk2-devel] [PATCH v3 29/39] OvmfPkg/LoongArchVirt: Add a NULL library named CollectApResouceLibNull Chao Li
2023-11-17 10:02 ` [edk2-devel] [PATCH v3 30/39] OvmfPkg/LoongArchVirt: Add serial port hook library Chao Li
2023-11-17 10:03 ` [edk2-devel] [PATCH v3 31/39] OvmfPkg/LoongArchVirt: Add the early serial port output library Chao Li
2023-11-17 10:03 ` [edk2-devel] [PATCH v3 32/39] OvmfPkg/LoongArchVirt: Add real time clock library Chao Li
2023-11-17 10:03 ` [edk2-devel] [PATCH v3 33/39] OvmfPkg/LoongArchVirt: Add NorFlashQemuLib Chao Li
2023-11-17 10:03 ` [edk2-devel] [PATCH v3 34/39] OvmfPkg/LoongArchVirt: Add FdtQemuFwCfgLib Chao Li
2023-11-17 10:03 ` [edk2-devel] [PATCH v3 35/39] OvmfPkg/LoongArchVirt: Add reset system library Chao Li
2023-11-17 10:03 ` [edk2-devel] [PATCH v3 36/39] OvmfPkg/LoongArchVirt: Support SEC phase Chao Li
2023-11-17 10:03 ` [edk2-devel] [PATCH v3 37/39] OvmfPkg/LoongArchVirt: Support PEI phase Chao Li
2023-11-17 10:04 ` [edk2-devel] [PATCH v3 38/39] OvmfPkg/LoongArchVirt: Add build file Chao Li
2023-11-17 10:04 ` [edk2-devel] [PATCH v3 39/39] OvmfPkg/LoongArchVirt: Add self introduction file Chao Li
     [not found] ` <179860C0A131BC70.3002@groups.io>
2023-11-20  9:55   ` [edk2-devel] [PATCH v3 14/39] UefiCpuPkg: Add LoongArch64CpuMmuLib to UefiCpuPkg Chao Li
     [not found] ` <179860DB0A3E8D83.6542@groups.io>
2023-11-21  6:39   ` [edk2-devel] [PATCH v3 27/39] ArmVirtPkg: Move PlatformBootManagerLib to OvmfPkg Chao Li

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=2e42db7c-a927-f47b-7d80-632895b11e1b@redhat.com \
    --to=devel@edk2.groups.io \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox