From: john stultz <johnstul@us.ibm.com>

Here is the monotonic_clock() interface for AMD64.  This implements the
function for both TSC and HPET time sources.  



 arch/x86_64/kernel/time.c |   47 ++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 47 insertions(+)

diff -puN arch/x86_64/kernel/time.c~amd64-monotonic-clock arch/x86_64/kernel/time.c
--- 25/arch/x86_64/kernel/time.c~amd64-monotonic-clock	2003-06-23 22:53:55.000000000 -0700
+++ 25-akpm/arch/x86_64/kernel/time.c	2003-06-23 22:53:55.000000000 -0700
@@ -47,6 +47,7 @@ unsigned long hpet_period;				/* fsecs /
 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 @@ static void set_rtc_mmss(unsigned long n
 	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 @@ static irqreturn_t timer_interrupt(int i
 		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 {
@@ -266,6 +311,8 @@ static irqreturn_t timer_interrupt(int i
 			offset %= (USEC_PER_SEC / HZ);
 		}
 
+		monotonic_base += (tsc - vxtime.last_tsc)*1000000/cpu_khz ;
+
 		vxtime.last_tsc = tsc - vxtime.quot * delay / vxtime.tsc_quot;
 
 		if ((((tsc - vxtime.last_tsc) *

_