diff options
author | Jan Kiszka <jan.kiszka@siemens.com> | 2012-08-14 10:24:03 +0200 |
---|---|---|
committer | Marcelo Tosatti <mtosatti@redhat.com> | 2012-08-14 19:23:16 -0300 |
commit | 205df4d1a87cbb14a50655fb2c0a987467fb29d6 (patch) | |
tree | 83d118f404509796a2c18189cb152e46bca8d454 /hw/kvm | |
parent | 873359d411eeb380906761e46839a2b705dbcf75 (diff) | |
download | qemu-205df4d1a87cbb14a50655fb2c0a987467fb29d6.tar.gz qemu-205df4d1a87cbb14a50655fb2c0a987467fb29d6.tar.bz2 qemu-205df4d1a87cbb14a50655fb2c0a987467fb29d6.zip |
kvm: i8254: Cache kernel clock offset in KVMPITState
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>
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Diffstat (limited to 'hw/kvm')
-rw-r--r-- | 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 c5d3711a04..c235d80a5a 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; } } |