All of lore.kernel.org
 help / color / mirror / Atom feed
From: Grzegorz Milos <gm281@cam.ac.uk>
To: xen-devel <xen-devel@lists.xensource.com>,
	Keir Fraser <Keir.Fraser@cl.cam.ac.uk>
Subject: [PATCH] mini-os updated
Date: Fri, 19 Aug 2005 17:46:56 +0100	[thread overview]
Message-ID: <43060D00.3090301@cam.ac.uk> (raw)
In-Reply-To: <42F13672.20204@us.ibm.com>

[-- Attachment #1: Type: text/plain, Size: 63 bytes --]

Mini-os updated to use the new timer interface.

Cheers
Gregor

[-- Attachment #2: patch --]
[-- Type: text/plain, Size: 10063 bytes --]

# HG changeset patch
# User gmilos@localhost.localdomain
# Node ID 3068565f6a32fde5fe1c11d44fd08d876d2b633f
# Parent  082a537ff4dec66574788126b3b047ef76e59803
Mini-os updated to use the new time interface.
Signed-off-by: Grzegorz Milos <gm281@cam.ac.uk>

diff -r 082a537ff4de -r 3068565f6a32 extras/mini-os/include/time.h
--- a/extras/mini-os/include/time.h	Thu Aug 18 17:04:48 2005
+++ b/extras/mini-os/include/time.h	Fri Aug 19 16:42:51 2005
@@ -28,7 +28,7 @@
  * of real time into system time 
  */
 typedef s64 s_time_t;
-#define NOW()                   ((s_time_t)get_s_time())
+#define NOW()                   ((s_time_t)monotonic_clock())
 #define SECONDS(_s)             (((s_time_t)(_s))  * 1000000000UL )
 #define TENTHS(_ts)             (((s_time_t)(_ts)) * 100000000UL )
 #define HUNDREDTHS(_hs)         (((s_time_t)(_hs)) * 10000000UL )
@@ -36,7 +36,8 @@
 #define MICROSECS(_us)          (((s_time_t)(_us)) * 1000UL )
 #define Time_Max                ((s_time_t) 0x7fffffffffffffffLL)
 #define FOREVER                 Time_Max
-
+#define NSEC_TO_USEC(_nsec)     (_nsec / 1000UL)
+#define NSEC_TO_SEC(_nsec)      (_nsec / 1000000000ULL)
 
 /* wall clock time  */
 typedef long time_t;
@@ -44,6 +45,11 @@
 struct timeval {
 	time_t		tv_sec;		/* seconds */
 	suseconds_t	tv_usec;	/* microseconds */
+};
+
+struct timespec {
+    time_t      ts_sec;
+    long        ts_nsec;
 };
 
 
diff -r 082a537ff4de -r 3068565f6a32 extras/mini-os/kernel.c
--- a/extras/mini-os/kernel.c	Thu Aug 18 17:04:48 2005
+++ b/extras/mini-os/kernel.c	Fri Aug 19 16:42:51 2005
@@ -132,20 +132,6 @@
     i = 0;
     for ( ; ; ) 
     {      
-        if(i >= 1000)         
-        {
-            {
-                unsigned long saved;
-                __asm__ ("movl %%esp, %0"
-                         :"=r"(saved)  /* y is output operand */
-                            /* x is input operand */);
-//                        :"a"); /* %eax is clobbered register */
-                printk("ESP=0x%lx\n", saved);
-            }
-            
-            printk("1000 bloks\n");
-            i=0;            
-        }
 //        HYPERVISOR_yield();
         block(1);
         i++;
diff -r 082a537ff4de -r 3068565f6a32 extras/mini-os/time.c
--- a/extras/mini-os/time.c	Thu Aug 18 17:04:48 2005
+++ b/extras/mini-os/time.c	Fri Aug 19 16:42:51 2005
@@ -43,19 +43,20 @@
  * Time functions
  *************************************************************************/
 
-/* Cached *multiplier* to convert TSC counts to microseconds.
- * (see the equation below).
- * Equal to 2^32 * (1 / (clocks per usec) ).
- * Initialized in time_init.
- */
-static unsigned long fast_gettimeoffset_quotient;
-
-
 /* These are peridically updated in shared_info, and then copied here. */
-static u32 shadow_tsc_stamp;
-static s64 shadow_system_time;
-static u32 shadow_time_version;
-static struct timeval shadow_tv;
+struct shadow_time_info {
+	u64 tsc_timestamp;     /* TSC at last update of time vals.  */
+	u64 system_timestamp;  /* Time, in nanosecs, since boot.    */
+	u32 tsc_to_nsec_mul;
+	u32 tsc_to_usec_mul;
+	int tsc_shift;
+	u32 version;
+};
+static struct timespec shadow_ts;
+static u32 shadow_ts_version;
+
+static struct shadow_time_info shadow;
+
 
 #ifndef rmb
 #define rmb()  __asm__ __volatile__ ("lock; addl $0,0(%%esp)": : :"memory")
@@ -63,116 +64,150 @@
 
 #define HANDLE_USEC_OVERFLOW(_tv)          \
     do {                                   \
-        while ( (_tv).tv_usec >= 1000000 ) \
+        while ( (_tv)->tv_usec >= 1000000 ) \
         {                                  \
-            (_tv).tv_usec -= 1000000;      \
-            (_tv).tv_sec++;                \
+            (_tv)->tv_usec -= 1000000;      \
+            (_tv)->tv_sec++;                \
         }                                  \
     } while ( 0 )
 
+static inline int time_values_up_to_date(void)
+{
+	struct vcpu_time_info *src = &HYPERVISOR_shared_info->vcpu_time[0]; 
+
+	return (shadow.version == src->version);
+}
+
+
+/*
+ * Scale a 64-bit delta by scaling and multiplying by a 32-bit fraction,
+ * yielding a 64-bit result.
+ */
+static inline u64 scale_delta(u64 delta, u32 mul_frac, int shift)
+{
+	u64 product;
+#ifdef __i386__
+	u32 tmp1, tmp2;
+#endif
+
+	if ( shift < 0 )
+		delta >>= -shift;
+	else
+		delta <<= shift;
+
+#ifdef __i386__
+	__asm__ (
+		"mul  %5       ; "
+		"mov  %4,%%eax ; "
+		"mov  %%edx,%4 ; "
+		"mul  %5       ; "
+		"add  %4,%%eax ; "
+		"xor  %5,%5    ; "
+		"adc  %5,%%edx ; "
+		: "=A" (product), "=r" (tmp1), "=r" (tmp2)
+		: "a" ((u32)delta), "1" ((u32)(delta >> 32)), "2" (mul_frac) );
+#else
+	__asm__ (
+		"mul %%rdx ; shrd $32,%%rdx,%%rax"
+		: "=a" (product) : "0" (delta), "d" ((u64)mul_frac) );
+#endif
+
+	return product;
+}
+
+
+static unsigned long get_nsec_offset(void)
+{
+	u64 now, delta;
+	rdtscll(now);
+	delta = now - shadow.tsc_timestamp;
+	return scale_delta(delta, shadow.tsc_to_nsec_mul, shadow.tsc_shift);
+}
+
+
 static void get_time_values_from_xen(void)
 {
-    do {
-        shadow_time_version = HYPERVISOR_shared_info->time_version2;
-        rmb();
-        shadow_tv.tv_sec    = HYPERVISOR_shared_info->wc_sec;
-        shadow_tv.tv_usec   = HYPERVISOR_shared_info->wc_usec;
-        shadow_tsc_stamp    = (u32)HYPERVISOR_shared_info->tsc_timestamp;
-        shadow_system_time  = HYPERVISOR_shared_info->system_time;
-        rmb();
-    }
-    while ( shadow_time_version != HYPERVISOR_shared_info->time_version1 );
-}
-
-
-#define TIME_VALUES_UP_TO_DATE \
-    (shadow_time_version == HYPERVISOR_shared_info->time_version2)
-
-static u32  get_time_delta_usecs(void)
-{
-	register unsigned long eax, edx;
-
-	/* Read the Time Stamp Counter */
-
-	rdtsc(eax,edx);
-
-	/* .. relative to previous jiffy (32 bits is enough) */
-	eax -= shadow_tsc_stamp;
-
-	/*
-	 * Time offset = (tsc_low delta) * fast_gettimeoffset_quotient
-	 *             = (tsc_low delta) * (usecs_per_clock)
-	 *             = (tsc_low delta) * (usecs_per_jiffy / clocks_per_jiffy)
-	 *
-	 * Using a mull instead of a divl saves up to 31 clock cycles
-	 * in the critical path.
-	 */
-
-	__asm__("mull %2"
-		:"=a" (eax), "=d" (edx)
-		:"rm" (fast_gettimeoffset_quotient),
-		 "0" (eax));
-
-	/* our adjusted time offset in microseconds */
-	return edx;
-}
-
-s64 get_s_time (void)
-{
-    u64 u_delta;
-    s64 ret;
-
- again:
-
-    u_delta = get_time_delta_usecs();
-    ret = shadow_system_time + (1000 * u_delta);
-
-    if ( unlikely(!TIME_VALUES_UP_TO_DATE) )
-    {
-        /*
-         * We may have blocked for a long time, rendering our calculations
-         * invalid (e.g. the time delta may have overflowed). Detect that
-         * and recalculate with fresh values.
-         */
-        get_time_values_from_xen();
-        goto again;
-    }
-
-    return ret;
-}
+	struct vcpu_time_info    *src = &HYPERVISOR_shared_info->vcpu_time[0];
+
+ 	do {
+		shadow.version = src->version;
+		rmb();
+		shadow.tsc_timestamp     = src->tsc_timestamp;
+		shadow.system_timestamp  = src->system_time;
+		shadow.tsc_to_nsec_mul   = src->tsc_to_system_mul;
+		shadow.tsc_shift         = src->tsc_shift;
+		rmb();
+	}
+	while ((src->version & 1) | (shadow.version ^ src->version));
+
+	shadow.tsc_to_usec_mul = shadow.tsc_to_nsec_mul / 1000;
+}
+
+
+
+
+/* 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.
+ */
+u64 monotonic_clock(void)
+{
+	u64 time;
+	u32 local_time_version;
+
+	do {
+		local_time_version = shadow.version;
+		rmb();
+		time = shadow.system_timestamp + get_nsec_offset();
+        if (!time_values_up_to_date())
+			get_time_values_from_xen();
+		rmb();
+	} while (local_time_version != shadow.version);
+
+	return time;
+}
+
+static void update_wallclock(void)
+{
+	shared_info_t *s = HYPERVISOR_shared_info;
+
+	do {
+		shadow_ts_version = s->wc_version;
+		rmb();
+		shadow_ts.ts_sec  = s->wc_sec;
+		shadow_ts.ts_nsec = s->wc_nsec;
+		rmb();
+	}
+	while ((s->wc_version & 1) | (shadow_ts_version ^ s->wc_version));
+}
+
 
 void gettimeofday(struct timeval *tv)
 {
-    struct timeval _tv;
-
-    do {
-        get_time_values_from_xen();
-        _tv.tv_usec = get_time_delta_usecs();
-        _tv.tv_sec   = shadow_tv.tv_sec;
-        _tv.tv_usec += shadow_tv.tv_usec;
-    }
-    while ( unlikely(!TIME_VALUES_UP_TO_DATE) );
-
-    HANDLE_USEC_OVERFLOW(_tv);
-    *tv = _tv;
-}
+    u64 nsec = monotonic_clock();
+    nsec += shadow_ts.ts_nsec;
+    
+    
+    tv->tv_sec = shadow_ts.ts_sec;
+    tv->tv_sec += NSEC_TO_SEC(nsec);
+    tv->tv_usec = NSEC_TO_USEC(nsec % 1000000000UL);
+}
+
 
 static void print_current_time(void)
 {
-    struct timeval tv;
-
-    get_time_values_from_xen();
+    struct timeval tv;    
 
     gettimeofday(&tv);
     printk("T(s=%ld us=%ld)\n", tv.tv_sec, tv.tv_usec);
 }
 
+
 void block(u32 millisecs)
 {
     struct timeval tv;
     gettimeofday(&tv);
-    //printk("tv.tv_sec=%ld, tv.tv_usec=%ld, shadow_system_time=%lld\n", tv.tv_sec, tv.tv_usec, shadow_system_time );
-    HYPERVISOR_set_timer_op(get_s_time() + 1000000LL * (s64) millisecs);
+    HYPERVISOR_set_timer_op(monotonic_clock() + 1000000LL * (s64) millisecs);
     HYPERVISOR_block();
 }
 
@@ -185,7 +220,7 @@
     static int i;
 
     get_time_values_from_xen();
-
+    update_wallclock();
     i++;
     if (i >= 1000) {
         print_current_time();
@@ -197,24 +232,5 @@
 
 void init_time(void)
 {
-    u64         __cpu_khz;
-    unsigned long cpu_khz;
-
-    __cpu_khz = HYPERVISOR_shared_info->cpu_freq;
-
-    cpu_khz = (u32) (__cpu_khz/1000);
-
-    printk("Xen reported: %lu.%03lu MHz processor.\n", 
-           cpu_khz / 1000, cpu_khz % 1000);
-	/* (10^6 * 2^32) / cpu_hz = (10^3 * 2^32) / cpu_khz =
-	   (2^32 * 1 / (clocks/us)) */
-	{	
-		unsigned long eax=0, edx=1000;
-		__asm__("divl %2"
-		    :"=a" (fast_gettimeoffset_quotient), "=d" (edx)
-		    :"r" (cpu_khz),
-		    "0" (eax), "1" (edx));
-	}
-
     bind_virq(VIRQ_TIMER, &timer_handler);
 }

[-- Attachment #3: Type: text/plain, Size: 138 bytes --]

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel

      parent reply	other threads:[~2005-08-19 16:46 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2005-08-03 21:26 [PATCH] Make Xend use consoled and xc_console Anthony Liguori
2005-08-03 21:30 ` Anthony Liguori
2005-08-19 16:46 ` Grzegorz Milos [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=43060D00.3090301@cam.ac.uk \
    --to=gm281@cam.ac.uk \
    --cc=Keir.Fraser@cl.cam.ac.uk \
    --cc=xen-devel@lists.xensource.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.