This patch hardens the implementation of hpet clock with 64-bit counter by enforcing that every read of the main counter is NOT less than the previous value.
Fixes #382 Signed-off-by: Waldemar Kozaczuk <jwkozac...@gmail.com> --- drivers/hpet.cc | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/drivers/hpet.cc b/drivers/hpet.cc index 22afae7d..ba9ed3bc 100644 --- a/drivers/hpet.cc +++ b/drivers/hpet.cc @@ -29,6 +29,7 @@ protected: mmioaddr_t _addr; uint64_t _wall; uint64_t _period; + std::atomic<s64> _last_read_counter; }; #define HPET_COUNTER 0x0f0 @@ -55,11 +56,23 @@ public: hpet_64bit_clock(mmioaddr_t hpet_mmio_address) : hpetclock(hpet_mmio_address) {} protected: virtual s64 time() override __attribute__((no_instrument_function)) { - return _wall + mmio_getq(_addr + HPET_COUNTER) * _period;; + return _wall + fetch_counter() * _period; } virtual s64 uptime() override __attribute__((no_instrument_function)) { - return mmio_getq(_addr + HPET_COUNTER) * _period;; + return fetch_counter() * _period; + } +private: + s64 fetch_counter() { + auto last_valid_counter = _last_read_counter.load(); + + s64 counter; + do { + counter = mmio_getq(_addr + HPET_COUNTER); + } while (counter < last_valid_counter); + + _last_read_counter.store(counter); + return counter; } }; @@ -99,6 +112,7 @@ hpetclock::hpetclock(mmioaddr_t hpet_mmio_address) mmio_setl(_addr + HPET_COUNTER, 0); mmio_setl(_addr + HPET_COUNTER + 4, 0); + _last_read_counter.store(0); _wall = r->wallclock_ns(); // We got them all, now we restart the HPET. -- 2.20.1 -- You received this message because you are subscribed to the Google Groups "OSv Development" group. To unsubscribe from this group and stop receiving emails from it, send an email to osv-dev+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/osv-dev/20190628040415.7411-1-jwkozaczuk%40gmail.com. For more options, visit https://groups.google.com/d/optout.