diff options
author | Carsten Haitzler <carsten.haitzler@foss.arm.com> | 2024-05-17 11:49:22 +0100 |
---|---|---|
committer | mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> | 2024-09-01 09:55:01 +0000 |
commit | af15e4535dcd4b2bfd0799ab36f0a3622687bdd3 (patch) | |
tree | 6fab804408aad3cc28fb31e36b0b5d91ecc36003 /ArmPkg | |
parent | 4ef87f455b57e4529db1420fbfba22c9c16f1444 (diff) | |
download | edk2-af15e4535dcd4b2bfd0799ab36f0a3622687bdd3.zip edk2-af15e4535dcd4b2bfd0799ab36f0a3622687bdd3.tar.gz edk2-af15e4535dcd4b2bfd0799ab36f0a3622687bdd3.tar.bz2 |
ArmPkg: Fix timer wrap-around
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 <carsten.haitzler@foss.arm.com>
Diffstat (limited to 'ArmPkg')
-rw-r--r-- | ArmPkg/Library/ArmArchTimerLib/ArmArchTimerLib.c | 14 |
1 files changed, 10 insertions, 4 deletions
diff --git a/ArmPkg/Library/ArmArchTimerLib/ArmArchTimerLib.c b/ArmPkg/Library/ArmArchTimerLib/ArmArchTimerLib.c index 76f94c9..cc1be01 100644 --- a/ArmPkg/Library/ArmArchTimerLib/ArmArchTimerLib.c +++ b/ArmPkg/Library/ArmArchTimerLib/ArmArchTimerLib.c @@ -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
@@ -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;
|