From mboxrd@z Thu Jan 1 00:00:00 1970 From: Gerd Hoffmann Subject: Re: pv clock: kvm is incompatible with xen :-( Date: Fri, 11 Apr 2008 17:01:14 +0200 Message-ID: <47FF7D3A.5000602@redhat.com> References: <47FF1441.6010801@redhat.com> <47FF545C.3010107@qumranet.com> <47FF6B43.1070305@redhat.com> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="------------010406090904060804040305" Cc: kvm-devel , Jeremy Fitzhardinge , Glauber de Oliveira Costa To: Avi Kivity Return-path: In-Reply-To: <47FF6B43.1070305@redhat.com> List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: kvm-devel-bounces@lists.sourceforge.net Errors-To: kvm-devel-bounces@lists.sourceforge.net List-Id: kvm.vger.kernel.org This is a multi-part message in MIME format. --------------010406090904060804040305 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit Gerd Hoffmann wrote: > Wall clock is off a few hours though. Oops. > > I think the way wall clock and system clock work together in xen (Jeremy > correct me if I'm wrong) is that the wall clock specifies the point in > time where the system clock started going. As kvm fills in host system > time into the guest system time fields the guest wall clock fields > should be filled with the host boot time timestamp I'd say. Following up myself with a quick&dirty patch to tackle this issue too. This one calculates the boot time. That should be solveable better, include/linux/time.h lists two functions which sound promising: extern void getboottime(struct timespec *ts); extern void monotonic_to_bootbased(struct timespec *ts); Neither of them is available to modules though, so I can't test without rebooting my laptop ... monotonic_to_bootbased() sounds like we would get hosts ntp adjustments in the guests for free. cheers, Gerd -- http://kraxel.fedorapeople.org/xenner/ --------------010406090904060804040305 Content-Type: text/x-patch; name="kvmclock-2.diff" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="kvmclock-2.diff" diff -up kvm-65/kernel/x86.c.fix kvm-65/kernel/x86.c --- kvm-65/kernel/x86.c.fix 2008-04-06 21:23:07.000000000 +0200 +++ kvm-65/kernel/x86.c 2008-04-11 16:17:23.000000000 +0200 @@ -490,7 +490,7 @@ static void kvm_write_wall_clock(struct { static int version; struct kvm_wall_clock wc; - struct timespec wc_ts; + struct timespec now,sys,boot; if (!wall_clock) return; @@ -499,9 +499,11 @@ static void kvm_write_wall_clock(struct kvm_write_guest(kvm, wall_clock, &version, sizeof(version)); - wc_ts = current_kernel_time(); - wc.wc_sec = wc_ts.tv_sec; - wc.wc_nsec = wc_ts.tv_nsec; + now = current_kernel_time(); + ktime_get_ts(&sys); + boot = ns_to_timespec(timespec_to_ns(&now) - timespec_to_ns(&sys)); + wc.wc_sec = boot.tv_sec; + wc.wc_nsec = boot.tv_nsec; wc.wc_version = version; kvm_write_guest(kvm, wall_clock, &wc, sizeof(wc)); @@ -548,6 +550,44 @@ static void kvm_write_guest_time(struct mark_page_dirty(v->kvm, vcpu->time >> PAGE_SHIFT); } +static uint32_t div_frac(uint32_t dividend, uint32_t divisor) +{ + uint32_t quotient, remainder; + + __asm__ ( "divl %4" + : "=a" (quotient), "=d" (remainder) + : "0" (0), "1" (dividend), "r" (divisor) ); + return quotient; +} + +static void kvm_set_time_scale(uint32_t tsc_khz, struct kvm_vcpu_time_info *hv_clock) +{ + uint64_t nsecs = 1000000000LL; + int32_t shift = 0; + uint64_t tps64; + uint32_t tps32; + + tps64 = tsc_khz * 1000LL; + while (tps64 > nsecs*2) { + tps64 >>= 1; + shift--; + } + + tps32 = (uint32_t)tps64; + while (tps32 <= (uint32_t)nsecs) { + tps32 <<= 1; + shift++; + } + + hv_clock->tsc_shift = shift; + hv_clock->tsc_to_system_mul = div_frac(nsecs, tps32); + +#if 0 + printk(KERN_DEBUG "%s: tsc_khz %u, tsc_shift %d, tsc_mul %u\n", + __FUNCTION__, tsc_khz, hv_clock->tsc_shift, + hv_clock->tsc_to_system_mul); +#endif +} int kvm_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data) { @@ -596,9 +636,7 @@ int kvm_set_msr_common(struct kvm_vcpu * /* ...but clean it before doing the actual write */ vcpu->arch.time_offset = data & ~(PAGE_MASK | 1); - vcpu->arch.hv_clock.tsc_to_system_mul = - clocksource_khz2mult(kvm_tsc_khz, 22); - vcpu->arch.hv_clock.tsc_shift = 22; + kvm_set_time_scale(kvm_tsc_khz, &vcpu->arch.hv_clock); down_read(¤t->mm->mmap_sem); vcpu->arch.time_page = --------------010406090904060804040305 Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline ------------------------------------------------------------------------- This SF.net email is sponsored by the 2008 JavaOne(SM) Conference Don't miss this year's exciting event. There's still time to save $100. Use priority code J8TL2D2. http://ad.doubleclick.net/clk;198757673;13503038;p?http://java.sun.com/javaone --------------010406090904060804040305 Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline _______________________________________________ kvm-devel mailing list kvm-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/kvm-devel --------------010406090904060804040305--