direct-io.hg
changeset 6044:6fc0b68b0a9c
Fix both Xen and XenLinux to correctly handle 64-bit
time deltas. Good for robustness and future-proofing.
Signed-off-by: Keir Fraser <keir@xensource.com>
time deltas. Good for robustness and future-proofing.
Signed-off-by: Keir Fraser <keir@xensource.com>
author | kaf24@firebug.cl.cam.ac.uk |
---|---|
date | Mon Aug 08 10:59:22 2005 +0000 (2005-08-08) |
parents | a9ee400a5da9 |
children | 704e6cc4a684 |
files | linux-2.6-xen-sparse/arch/xen/i386/kernel/time.c xen/arch/x86/time.c |
line diff
1.1 --- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/time.c Mon Aug 08 09:13:19 2005 +0000 1.2 +++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/time.c Mon Aug 08 10:59:22 2005 +0000 1.3 @@ -166,25 +166,34 @@ struct timer_opts timer_tsc = { 1.4 .delay = delay_tsc, 1.5 }; 1.6 1.7 -static inline u32 down_shift(u64 time, int shift) 1.8 +/* 1.9 + * Scale a 64-bit delta by scaling and multiplying by a 32-bit fraction, 1.10 + * yielding a 64-bit result. 1.11 + */ 1.12 +static inline u64 scale_delta(u64 delta, u32 mul_frac, int shift) 1.13 { 1.14 + u64 product; 1.15 + u32 tmp; 1.16 + 1.17 if ( shift < 0 ) 1.18 - return (u32)(time >> -shift); 1.19 - return (u32)((u32)time << shift); 1.20 -} 1.21 + delta >>= -shift; 1.22 + else 1.23 + delta <<= shift; 1.24 1.25 -/* 1.26 - * 32-bit multiplication of integer multiplicand and fractional multiplier 1.27 - * yielding 32-bit integer product. 1.28 - */ 1.29 -static inline u32 mul_frac(u32 multiplicand, u32 multiplier) 1.30 -{ 1.31 - u32 product_int, product_frac; 1.32 __asm__ ( 1.33 - "mul %3" 1.34 - : "=a" (product_frac), "=d" (product_int) 1.35 - : "0" (multiplicand), "r" (multiplier) ); 1.36 - return product_int; 1.37 + "pushl %%edx ; " 1.38 + "mull %3 ; " 1.39 + "popl %%eax ; " 1.40 + "pushl %%edx ; " 1.41 + "mull %3 ; " 1.42 + "popl %3 ; " 1.43 + "addl %3,%%eax ; " 1.44 + "xorl %3,%3 ; " 1.45 + "adcl %3,%%edx ; " 1.46 + : "=A" (product), "=r" (tmp) 1.47 + : "A" (delta), "1" (mul_frac) ); 1.48 + 1.49 + return product; 1.50 } 1.51 1.52 void init_cpu_khz(void) 1.53 @@ -192,27 +201,28 @@ void init_cpu_khz(void) 1.54 u64 __cpu_khz = 1000000ULL << 32; 1.55 struct vcpu_time_info *info = &HYPERVISOR_shared_info->vcpu_time[0]; 1.56 do_div(__cpu_khz, info->tsc_to_system_mul); 1.57 - cpu_khz = down_shift(__cpu_khz, -info->tsc_shift); 1.58 + if ( info->tsc_shift < 0 ) 1.59 + cpu_khz = __cpu_khz >> -info->tsc_shift; 1.60 + else 1.61 + cpu_khz = __cpu_khz << info->tsc_shift; 1.62 printk(KERN_INFO "Xen reported: %lu.%03lu MHz processor.\n", 1.63 cpu_khz / 1000, cpu_khz % 1000); 1.64 } 1.65 1.66 static u64 get_nsec_offset(struct shadow_time_info *shadow) 1.67 { 1.68 - u64 now; 1.69 - u32 delta; 1.70 + u64 now, delta; 1.71 rdtscll(now); 1.72 - delta = down_shift(now - shadow->tsc_timestamp, shadow->tsc_shift); 1.73 - return mul_frac(delta, shadow->tsc_to_nsec_mul); 1.74 + delta = now - shadow->tsc_timestamp; 1.75 + return scale_delta(delta, shadow->tsc_to_nsec_mul, shadow->tsc_shift); 1.76 } 1.77 1.78 static unsigned long get_usec_offset(struct shadow_time_info *shadow) 1.79 { 1.80 - u64 now; 1.81 - u32 delta; 1.82 + u64 now, delta; 1.83 rdtscll(now); 1.84 - delta = down_shift(now - shadow->tsc_timestamp, shadow->tsc_shift); 1.85 - return mul_frac(delta, shadow->tsc_to_usec_mul); 1.86 + delta = now - shadow->tsc_timestamp; 1.87 + return scale_delta(delta, shadow->tsc_to_usec_mul, shadow->tsc_shift); 1.88 } 1.89 1.90 static void update_wallclock(void)
2.1 --- a/xen/arch/x86/time.c Mon Aug 08 09:13:19 2005 +0000 2.2 +++ b/xen/arch/x86/time.c Mon Aug 08 10:59:22 2005 +0000 2.3 @@ -67,13 +67,6 @@ static struct time_scale platform_timer_ 2.4 static spinlock_t platform_timer_lock = SPIN_LOCK_UNLOCKED; 2.5 static u64 (*read_platform_count)(void); 2.6 2.7 -static inline u32 down_shift(u64 time, int shift) 2.8 -{ 2.9 - if ( shift < 0 ) 2.10 - return (u32)(time >> -shift); 2.11 - return (u32)((u32)time << shift); 2.12 -} 2.13 - 2.14 /* 2.15 * 32-bit division of integer dividend and integer divisor yielding 2.16 * 32-bit fractional quotient. 2.17 @@ -83,7 +76,7 @@ static inline u32 div_frac(u32 dividend, 2.18 u32 quotient, remainder; 2.19 ASSERT(dividend < divisor); 2.20 __asm__ ( 2.21 - "div %4" 2.22 + "divl %4" 2.23 : "=a" (quotient), "=d" (remainder) 2.24 : "0" (0), "1" (dividend), "r" (divisor) ); 2.25 return quotient; 2.26 @@ -103,6 +96,36 @@ static inline u32 mul_frac(u32 multiplic 2.27 return product_int; 2.28 } 2.29 2.30 +/* 2.31 + * Scale a 64-bit delta by scaling and multiplying by a 32-bit fraction, 2.32 + * yielding a 64-bit result. 2.33 + */ 2.34 +static inline u64 scale_delta(u64 delta, struct time_scale *scale) 2.35 +{ 2.36 + u64 product; 2.37 + u32 tmp; 2.38 + 2.39 + if ( scale->shift < 0 ) 2.40 + delta >>= -scale->shift; 2.41 + else 2.42 + delta <<= scale->shift; 2.43 + 2.44 + __asm__ ( 2.45 + "pushl %%edx ; " 2.46 + "mull %3 ; " 2.47 + "popl %%eax ; " 2.48 + "pushl %%edx ; " 2.49 + "mull %3 ; " 2.50 + "popl %3 ; " 2.51 + "addl %3,%%eax ; " 2.52 + "xorl %3,%3 ; " 2.53 + "adcl %3,%%edx ; " 2.54 + : "=A" (product), "=r" (tmp) 2.55 + : "A" (delta), "1" (scale->mul_frac) ); 2.56 + 2.57 + return product; 2.58 +} 2.59 + 2.60 void timer_interrupt(int irq, void *dev_id, struct cpu_user_regs *regs) 2.61 { 2.62 if ( timer_ack ) 2.63 @@ -486,11 +509,9 @@ static int init_cyclone(void) 2.64 2.65 static s_time_t __read_platform_stime(u64 platform_time) 2.66 { 2.67 - u64 diff64 = platform_time - platform_timer_stamp; 2.68 - u32 diff = down_shift(diff64, platform_timer_scale.shift); 2.69 + u64 diff = platform_time - platform_timer_stamp; 2.70 ASSERT(spin_is_locked(&platform_timer_lock)); 2.71 - return (stime_platform_stamp + 2.72 - (u64)mul_frac(diff, platform_timer_scale.mul_frac)); 2.73 + return (stime_platform_stamp + scale_delta(diff, &platform_timer_scale)); 2.74 } 2.75 2.76 static s_time_t read_platform_stime(void) 2.77 @@ -619,13 +640,12 @@ static unsigned long get_cmos_time(void) 2.78 s_time_t get_s_time(void) 2.79 { 2.80 struct cpu_time *t = &cpu_time[smp_processor_id()]; 2.81 - u64 tsc; 2.82 - u32 delta; 2.83 + u64 tsc, delta; 2.84 s_time_t now; 2.85 2.86 rdtscll(tsc); 2.87 - delta = down_shift(tsc - t->local_tsc_stamp, t->tsc_scale.shift); 2.88 - now = t->stime_local_stamp + (u64)mul_frac(delta, t->tsc_scale.mul_frac); 2.89 + delta = tsc - t->local_tsc_stamp; 2.90 + now = t->stime_local_stamp + scale_delta(delta, &t->tsc_scale); 2.91 2.92 return now; 2.93 }