WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] Fix both Xen and XenLinux to correctly handle 64-bit

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] Fix both Xen and XenLinux to correctly handle 64-bit
From: Xen patchbot -unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Mon, 08 Aug 2005 07:06:10 -0400
Delivery-date: Mon, 08 Aug 2005 11:06:38 +0000
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# HG changeset patch
# User kaf24@xxxxxxxxxxxxxxxxxxxx
# Node ID 6fc0b68b0a9ca2ab6164ee02db7fcf70905665f0
# Parent  a9ee400a5da98acc8da566a24ecae05902b2bed2
Fix both Xen and XenLinux to correctly handle 64-bit
time deltas. Good for robustness and future-proofing.
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>

diff -r a9ee400a5da9 -r 6fc0b68b0a9c 
linux-2.6-xen-sparse/arch/xen/i386/kernel/time.c
--- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/time.c  Mon Aug  8 09:13:19 2005
+++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/time.c  Mon Aug  8 10:59:22 2005
@@ -166,25 +166,34 @@
        .delay = delay_tsc,
 };
 
-static inline u32 down_shift(u64 time, int shift)
-{
+/*
+ * 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;
+       u32 tmp;
+
        if ( shift < 0 )
-               return (u32)(time >> -shift);
-       return (u32)((u32)time << shift);
-}
-
-/*
- * 32-bit multiplication of integer multiplicand and fractional multiplier
- * yielding 32-bit integer product.
- */
-static inline u32 mul_frac(u32 multiplicand, u32 multiplier)
-{
-       u32 product_int, product_frac;
+               delta >>= -shift;
+       else
+               delta <<= shift;
+
        __asm__ (
-               "mul %3"
-               : "=a" (product_frac), "=d" (product_int)
-               : "0" (multiplicand), "r" (multiplier) );
-       return product_int;
+               "pushl %%edx    ; "
+               "mull  %3       ; "
+               "popl  %%eax    ; "
+               "pushl %%edx    ; "
+               "mull  %3       ; "
+               "popl  %3       ; "
+               "addl  %3,%%eax ; "
+               "xorl  %3,%3    ; "
+               "adcl  %3,%%edx ; "
+               : "=A" (product), "=r" (tmp)
+               : "A" (delta), "1" (mul_frac) );
+
+       return product;
 }
 
 void init_cpu_khz(void)
@@ -192,27 +201,28 @@
        u64 __cpu_khz = 1000000ULL << 32;
        struct vcpu_time_info *info = &HYPERVISOR_shared_info->vcpu_time[0];
        do_div(__cpu_khz, info->tsc_to_system_mul);
-       cpu_khz = down_shift(__cpu_khz, -info->tsc_shift);
+       if ( info->tsc_shift < 0 )
+               cpu_khz = __cpu_khz >> -info->tsc_shift;
+       else
+               cpu_khz = __cpu_khz << info->tsc_shift;
        printk(KERN_INFO "Xen reported: %lu.%03lu MHz processor.\n",
               cpu_khz / 1000, cpu_khz % 1000);
 }
 
 static u64 get_nsec_offset(struct shadow_time_info *shadow)
 {
-       u64 now;
-       u32 delta;
+       u64 now, delta;
        rdtscll(now);
-       delta = down_shift(now - shadow->tsc_timestamp, shadow->tsc_shift);
-       return mul_frac(delta, shadow->tsc_to_nsec_mul);
+       delta = now - shadow->tsc_timestamp;
+       return scale_delta(delta, shadow->tsc_to_nsec_mul, shadow->tsc_shift);
 }
 
 static unsigned long get_usec_offset(struct shadow_time_info *shadow)
 {
-       u64 now;
-       u32 delta;
+       u64 now, delta;
        rdtscll(now);
-       delta = down_shift(now - shadow->tsc_timestamp, shadow->tsc_shift);
-       return mul_frac(delta, shadow->tsc_to_usec_mul);
+       delta = now - shadow->tsc_timestamp;
+       return scale_delta(delta, shadow->tsc_to_usec_mul, shadow->tsc_shift);
 }
 
 static void update_wallclock(void)
diff -r a9ee400a5da9 -r 6fc0b68b0a9c xen/arch/x86/time.c
--- a/xen/arch/x86/time.c       Mon Aug  8 09:13:19 2005
+++ b/xen/arch/x86/time.c       Mon Aug  8 10:59:22 2005
@@ -67,13 +67,6 @@
 static spinlock_t platform_timer_lock = SPIN_LOCK_UNLOCKED;
 static u64 (*read_platform_count)(void);
 
-static inline u32 down_shift(u64 time, int shift)
-{
-    if ( shift < 0 )
-        return (u32)(time >> -shift);
-    return (u32)((u32)time << shift);
-}
-
 /*
  * 32-bit division of integer dividend and integer divisor yielding
  * 32-bit fractional quotient.
@@ -83,7 +76,7 @@
     u32 quotient, remainder;
     ASSERT(dividend < divisor);
     __asm__ ( 
-        "div %4"
+        "divl %4"
         : "=a" (quotient), "=d" (remainder)
         : "0" (0), "1" (dividend), "r" (divisor) );
     return quotient;
@@ -101,6 +94,36 @@
         : "=a" (product_frac), "=d" (product_int)
         : "0" (multiplicand), "r" (multiplier) );
     return product_int;
+}
+
+/*
+ * 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, struct time_scale *scale)
+{
+    u64 product;
+    u32 tmp;
+
+    if ( scale->shift < 0 )
+        delta >>= -scale->shift;
+    else
+        delta <<= scale->shift;
+
+    __asm__ (
+        "pushl %%edx    ; "
+        "mull  %3       ; "
+        "popl  %%eax    ; "
+        "pushl %%edx    ; "
+        "mull  %3       ; "
+        "popl  %3       ; "
+        "addl  %3,%%eax ; "
+        "xorl  %3,%3    ; "
+        "adcl  %3,%%edx ; "
+        : "=A" (product), "=r" (tmp)
+        : "A" (delta), "1" (scale->mul_frac) );
+
+    return product;
 }
 
 void timer_interrupt(int irq, void *dev_id, struct cpu_user_regs *regs)
@@ -486,11 +509,9 @@
 
 static s_time_t __read_platform_stime(u64 platform_time)
 {
-    u64 diff64 = platform_time - platform_timer_stamp;
-    u32 diff   = down_shift(diff64, platform_timer_scale.shift);
+    u64 diff = platform_time - platform_timer_stamp;
     ASSERT(spin_is_locked(&platform_timer_lock));
-    return (stime_platform_stamp + 
-            (u64)mul_frac(diff, platform_timer_scale.mul_frac));
+    return (stime_platform_stamp + scale_delta(diff, &platform_timer_scale));
 }
 
 static s_time_t read_platform_stime(void)
@@ -619,13 +640,12 @@
 s_time_t get_s_time(void)
 {
     struct cpu_time *t = &cpu_time[smp_processor_id()];
-    u64 tsc;
-    u32 delta;
+    u64 tsc, delta;
     s_time_t now;
 
     rdtscll(tsc);
-    delta = down_shift(tsc - t->local_tsc_stamp, t->tsc_scale.shift);
-    now = t->stime_local_stamp + (u64)mul_frac(delta, t->tsc_scale.mul_frac);
+    delta = tsc - t->local_tsc_stamp;
+    now = t->stime_local_stamp + scale_delta(delta, &t->tsc_scale);
 
     return now;
 }

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

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] Fix both Xen and XenLinux to correctly handle 64-bit, Xen patchbot -unstable <=