
On systems using the generic timer routines defined in lib/time.c we use timebase_l and timebase_h fields from the gd to detect wraparounds in our tick counter. The tick calculcation algorithm silently assumes that a long is only 32 bits, which leads to wrong results when timebase_h is not 0 on 64-bit systems. As one possible fix lets initialize timebase_h (and timebase_l) to 0, so on 64-bit systems timebase_h will never(TM) be bigger than 0 and thus cannot spoil timebase_l by being ORed into it.
This fixes occasional timeout issues on the Pine64 (and possibly other ARM64 systems).
Signed-off-by: Andre Przywara andre.przywara@arm.com --- Hi,
I am bit puzzled what the proper fix is, this one is the easiest I could come up with. Not sure if the gd should be zeroed normally (and it's just broken on sunxi/arm64 because of some linker issues) or whether we really forgot to initialize those fields and just got away with it. Other fixes I tried are implementing get_ticks() in armv8/generic_timer.c or fixing the generic get_ticks() implementation by using "#if BITS_PER_LONG < 64" in the function to shortcut the code on 64-bit systems. Please have your say on what's best.
Cheers, Andre.
P.S. "Never" above seems to be 195 years assuming a worst-case 3GHz arch timer.
lib/time.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/lib/time.c b/lib/time.c index f37150f..b77d134 100644 --- a/lib/time.c +++ b/lib/time.c @@ -109,6 +109,8 @@ static uint64_t notrace tick_to_time(uint64_t tick)
int __weak timer_init(void) { + gd->timebase_l = 0; + gd->timebase_h = 0; return 0; }