Commit 205df4d1 authored by Jan Kiszka's avatar Jan Kiszka Committed by Marcelo Tosatti
Browse files

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: default avatarJan Kiszka <jan.kiszka@siemens.com>
Signed-off-by: default avatarMarcelo Tosatti <mtosatti@redhat.com>
parent 873359d4
Loading
Loading
Loading
Loading
+24 −14
Original line number Diff line number Diff line
@@ -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;
    }
}