Andi,
Here is the monotonic_clock() interface for AMD64. This implements the
function for both TSC and HPET time sources.
thanks
-john
diff -Nru a/arch/x86_64/kernel/time.c b/arch/x86_64/kernel/time.c
--- a/arch/x86_64/kernel/time.c Mon Jun 23 19:27:28 2003
+++ b/arch/x86_64/kernel/time.c Mon Jun 23 19:27:29 2003
@@ -47,6 +47,7 @@
unsigned long hpet_tick; /* HPET clocks / interrupt */
unsigned long vxtime_hz = 1193182;
int report_lost_ticks; /* command line option */
+unsigned long long monotonic_base;
struct vxtime_data __vxtime __section_vxtime; /* for vsyscalls */
@@ -219,6 +220,47 @@
spin_unlock(&rtc_lock);
}
+
+/* monotonic_clock(): returns # of nanoseconds passed since time_init()
+ * Note: This function is required to return accurate
+ * time even in the absence of multiple timer ticks.
+ */
+unsigned long long monotonic_clock(void)
+{
+ unsigned long seq;
+ u32 last_offset, this_offset, offset;
+ unsigned long long base;
+
+ if (vxtime.mode == VXTIME_HPET) {
+ do {
+ seq = read_seqbegin(&xtime_lock);
+
+ last_offset = vxtime.last;
+ base = monotonic_base;
+ this_offset = hpet_readl(HPET_T0_CMP) - hpet_tick;
+
+ } while (read_seqretry(&xtime_lock, seq));
+ offset = (this_offset - last_offset);
+ offset *=(NSEC_PER_SEC/HZ)/hpet_tick;
+ return base + offset;
+ }else{
+ do {
+ seq = read_seqbegin(&xtime_lock);
+
+ last_offset = vxtime.last_tsc;
+ base = monotonic_base;
+ } while (read_seqretry(&xtime_lock, seq));
+ sync_core();
+ rdtscll(this_offset);
+ offset = (this_offset - last_offset)*1000/cpu_khz;
+ return base + offset;
+ }
+
+
+}
+EXPORT_SYMBOL(monotonic_clock);
+
+
static irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
static unsigned long rtc_update = 0;
@@ -252,6 +294,9 @@
if (offset - vxtime.last > hpet_tick) {
lost = (offset - vxtime.last) / hpet_tick - 1;
}
+
+ monotonic_base +=
+ (offset - vxtime.last)*(NSEC_PER_SEC/HZ) / hpet_tick;
vxtime.last = offset;
} else {
@@ -265,6 +310,8 @@
lost = offset / (USEC_PER_SEC / HZ);
offset %= (USEC_PER_SEC / HZ);
}
+
+ monotonic_base += (tsc - vxtime.last_tsc)*1000000/cpu_khz ;
vxtime.last_tsc = tsc - vxtime.quot * delay / vxtime.tsc_quot;