Skip to content

Commit

Permalink
ArmPkg: Fix timer wrap-around
Browse files Browse the repository at this point in the history
The timer counter register can wrap around and when this happens,
we'll get misbehavior for any MicroSecondDelay() calls. This adds
handling for that.

Signed-off-by: Carsten Haitzler <[email protected]>
  • Loading branch information
Carsten Haitzler authored and mergify[bot] committed Sep 1, 2024
1 parent 4ef87f4 commit af15e45
Showing 1 changed file with 10 additions and 4 deletions.
14 changes: 10 additions & 4 deletions ArmPkg/Library/ArmArchTimerLib/ArmArchTimerLib.c
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ MicroSecondDelay (
{
UINT64 TimerTicks64;
UINT64 SystemCounterVal;
UINT64 PreviousSystemCounterVal;
UINT64 DeltaCounterVal;

// Calculate counter ticks that represent requested delay:
// = MicroSeconds x TICKS_PER_MICRO_SEC
Expand All @@ -75,13 +77,17 @@ MicroSecondDelay (
);

// Read System Counter value
SystemCounterVal = ArmGenericTimerGetSystemCount ();

TimerTicks64 += SystemCounterVal;
PreviousSystemCounterVal = ArmGenericTimerGetSystemCount ();

// Wait until delay count expires.
while (SystemCounterVal < TimerTicks64) {
while (TimerTicks64 > 0) {
SystemCounterVal = ArmGenericTimerGetSystemCount ();
// Get how much we advanced this tick. Wrap around still has delta correct
DeltaCounterVal = (SystemCounterVal - PreviousSystemCounterVal)
& (MAX_UINT64 >> 8); // Account for a lesser (minimum) size
// Never wrap back around below zero by choosing the min and thus stop at 0
TimerTicks64 -= MIN (TimerTicks64, DeltaCounterVal);
PreviousSystemCounterVal = SystemCounterVal;
}

return MicroSeconds;
Expand Down

0 comments on commit af15e45

Please sign in to comment.