qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH uq/master 1/2] kvm: i8254: Cache kernel clock offset in KVMPITState
@ 2012-08-14  8:24 Jan Kiszka
  2012-08-14  8:24 ` [Qemu-devel] [PATCH uq/master 2/2] kvm: i8254: Finish time conversion fix Jan Kiszka
  2012-08-14 19:00 ` [Qemu-devel] [PATCH uq/master 1/2] kvm: i8254: Cache kernel clock offset in KVMPITState Marcelo Tosatti
  0 siblings, 2 replies; 3+ messages in thread
From: Jan Kiszka @ 2012-08-14  8:24 UTC (permalink / raw)
  To: Avi Kivity, Marcelo Tosatti
  Cc: kvm, Gleb Natapov, Michael Tokarev, qemu-devel, qemu-stable,
	Gerd Hoffmann

To prepare the final fix for clock calibration issues with the in-kernel
PIT, we want to cache the offset between vmclock and the clock used by
the in-kernel PIT. So far, we only need to update it when the VM state
changes between running and stopped because we only read the in-kernel
PIT state while the VM is running.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
 hw/kvm/i8254.c |   38 ++++++++++++++++++++++++--------------
 1 files changed, 24 insertions(+), 14 deletions(-)

diff --git a/hw/kvm/i8254.c b/hw/kvm/i8254.c
index c5d3711..c235d80 100644
--- a/hw/kvm/i8254.c
+++ b/hw/kvm/i8254.c
@@ -35,7 +35,8 @@
 typedef struct KVMPITState {
     PITCommonState pit;
     LostTickPolicy lost_tick_policy;
-    bool state_valid;
+    bool vm_stopped;
+    int64_t kernel_clock_offset;
 } KVMPITState;
 
 static int64_t abs64(int64_t v)
@@ -43,19 +44,11 @@ static int64_t abs64(int64_t v)
     return v < 0 ? -v : v;
 }
 
-static void kvm_pit_get(PITCommonState *pit)
+static void kvm_pit_update_clock_offset(KVMPITState *s)
 {
-    KVMPITState *s = DO_UPCAST(KVMPITState, pit, pit);
-    struct kvm_pit_state2 kpit;
-    struct kvm_pit_channel_state *kchan;
-    struct PITChannelState *sc;
     int64_t offset, clock_offset;
     struct timespec ts;
-    int i, ret;
-
-    if (s->state_valid) {
-        return;
-    }
+    int i;
 
     /*
      * Measure the delta between CLOCK_MONOTONIC, the base used for
@@ -72,6 +65,21 @@ static void kvm_pit_get(PITCommonState *pit)
             clock_offset = offset;
         }
     }
+    s->kernel_clock_offset = clock_offset;
+}
+
+static void kvm_pit_get(PITCommonState *pit)
+{
+    KVMPITState *s = DO_UPCAST(KVMPITState, pit, pit);
+    struct kvm_pit_state2 kpit;
+    struct kvm_pit_channel_state *kchan;
+    struct PITChannelState *sc;
+    int i, ret;
+
+    /* No need to re-read the state if VM is stopped. */
+    if (s->vm_stopped) {
+        return;
+    }
 
     if (kvm_has_pit_state2()) {
         ret = kvm_vm_ioctl(kvm_state, KVM_GET_PIT2, &kpit);
@@ -106,7 +114,7 @@ static void kvm_pit_get(PITCommonState *pit)
         sc->mode = kchan->mode;
         sc->bcd = kchan->bcd;
         sc->gate = kchan->gate;
-        sc->count_load_time = kchan->count_load_time + clock_offset;
+        sc->count_load_time = kchan->count_load_time + s->kernel_clock_offset;
     }
 
     sc = &pit->channels[0];
@@ -211,10 +219,12 @@ static void kvm_pit_vm_state_change(void *opaque, int running,
     KVMPITState *s = opaque;
 
     if (running) {
-        s->state_valid = false;
+        kvm_pit_update_clock_offset(s);
+        s->vm_stopped = false;
     } else {
+        kvm_pit_update_clock_offset(s);
         kvm_pit_get(&s->pit);
-        s->state_valid = true;
+        s->vm_stopped = true;
     }
 }
 
-- 
1.7.3.4

^ permalink raw reply related	[flat|nested] 3+ messages in thread

* [Qemu-devel] [PATCH uq/master 2/2] kvm: i8254: Finish time conversion fix
  2012-08-14  8:24 [Qemu-devel] [PATCH uq/master 1/2] kvm: i8254: Cache kernel clock offset in KVMPITState Jan Kiszka
@ 2012-08-14  8:24 ` Jan Kiszka
  2012-08-14 19:00 ` [Qemu-devel] [PATCH uq/master 1/2] kvm: i8254: Cache kernel clock offset in KVMPITState Marcelo Tosatti
  1 sibling, 0 replies; 3+ messages in thread
From: Jan Kiszka @ 2012-08-14  8:24 UTC (permalink / raw)
  To: Avi Kivity, Marcelo Tosatti
  Cc: kvm, Gleb Natapov, Michael Tokarev, qemu-devel, qemu-stable,
	Gerd Hoffmann

0cdd3d1444 fixed reading back the counter load time from the kernel
while assuming the kernel would always update its load time on writing
the state. That is only true for channel 1, and so pit_get_channel_info
returned wrong output pin states for high counter values.

Fix this by applying the offset also on kvm_pit_put. Now we also need to
update the offset when we write the state while the VM is stopped as it
keeps on changing in that state.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
 hw/kvm/i8254.c |   14 ++++++++++----
 1 files changed, 10 insertions(+), 4 deletions(-)

diff --git a/hw/kvm/i8254.c b/hw/kvm/i8254.c
index c235d80..53d13e3 100644
--- a/hw/kvm/i8254.c
+++ b/hw/kvm/i8254.c
@@ -122,17 +122,23 @@ static void kvm_pit_get(PITCommonState *pit)
         pit_get_next_transition_time(sc, sc->count_load_time);
 }
 
-static void kvm_pit_put(PITCommonState *s)
+static void kvm_pit_put(PITCommonState *pit)
 {
+    KVMPITState *s = DO_UPCAST(KVMPITState, pit, pit);
     struct kvm_pit_state2 kpit;
     struct kvm_pit_channel_state *kchan;
     struct PITChannelState *sc;
     int i, ret;
 
-    kpit.flags = s->channels[0].irq_disabled ? KVM_PIT_FLAGS_HPET_LEGACY : 0;
+    /* The offset keeps changing as long as the VM is stopped. */
+    if (s->vm_stopped) {
+        kvm_pit_update_clock_offset(s);
+    }
+
+    kpit.flags = pit->channels[0].irq_disabled ? KVM_PIT_FLAGS_HPET_LEGACY : 0;
     for (i = 0; i < 3; i++) {
         kchan = &kpit.channels[i];
-        sc = &s->channels[i];
+        sc = &pit->channels[i];
         kchan->count = sc->count;
         kchan->latched_count = sc->latched_count;
         kchan->count_latched = sc->count_latched;
@@ -145,7 +151,7 @@ static void kvm_pit_put(PITCommonState *s)
         kchan->mode = sc->mode;
         kchan->bcd = sc->bcd;
         kchan->gate = sc->gate;
-        kchan->count_load_time = sc->count_load_time;
+        kchan->count_load_time = sc->count_load_time - s->kernel_clock_offset;
     }
 
     ret = kvm_vm_ioctl(kvm_state,
-- 
1.7.3.4

^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [Qemu-devel] [PATCH uq/master 1/2] kvm: i8254: Cache kernel clock offset in KVMPITState
  2012-08-14  8:24 [Qemu-devel] [PATCH uq/master 1/2] kvm: i8254: Cache kernel clock offset in KVMPITState Jan Kiszka
  2012-08-14  8:24 ` [Qemu-devel] [PATCH uq/master 2/2] kvm: i8254: Finish time conversion fix Jan Kiszka
@ 2012-08-14 19:00 ` Marcelo Tosatti
  1 sibling, 0 replies; 3+ messages in thread
From: Marcelo Tosatti @ 2012-08-14 19:00 UTC (permalink / raw)
  To: Jan Kiszka
  Cc: Gleb Natapov, kvm, Michael Tokarev, qemu-stable, qemu-devel,
	Gerd Hoffmann, Avi Kivity

On Tue, Aug 14, 2012 at 10:24:03AM +0200, Jan Kiszka wrote:
> To prepare the final fix for clock calibration issues with the in-kernel
> PIT, we want to cache the offset between vmclock and the clock used by
> the in-kernel PIT. So far, we only need to update it when the VM state
> changes between running and stopped because we only read the in-kernel
> PIT state while the VM is running.
> 
> Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>

Applied, thanks.

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2012-08-14 19:01 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-08-14  8:24 [Qemu-devel] [PATCH uq/master 1/2] kvm: i8254: Cache kernel clock offset in KVMPITState Jan Kiszka
2012-08-14  8:24 ` [Qemu-devel] [PATCH uq/master 2/2] kvm: i8254: Finish time conversion fix Jan Kiszka
2012-08-14 19:00 ` [Qemu-devel] [PATCH uq/master 1/2] kvm: i8254: Cache kernel clock offset in KVMPITState Marcelo Tosatti

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).