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.

Reply via email to