Statistics
| Branch: | Revision:

root / hw / i386 / kvm / clock.c @ 58cd9864

History | View | Annotate | Download (3.7 kB)

1 0ec329da Jan Kiszka
/*
2 0ec329da Jan Kiszka
 * QEMU KVM support, paravirtual clock device
3 0ec329da Jan Kiszka
 *
4 0ec329da Jan Kiszka
 * Copyright (C) 2011 Siemens AG
5 0ec329da Jan Kiszka
 *
6 0ec329da Jan Kiszka
 * Authors:
7 0ec329da Jan Kiszka
 *  Jan Kiszka        <jan.kiszka@siemens.com>
8 0ec329da Jan Kiszka
 *
9 0ec329da Jan Kiszka
 * This work is licensed under the terms of the GNU GPL version 2.
10 0ec329da Jan Kiszka
 * See the COPYING file in the top-level directory.
11 0ec329da Jan Kiszka
 *
12 6b620ca3 Paolo Bonzini
 * Contributions after 2012-01-13 are licensed under the terms of the
13 6b620ca3 Paolo Bonzini
 * GNU GPL, version 2 or (at your option) any later version.
14 0ec329da Jan Kiszka
 */
15 0ec329da Jan Kiszka
16 0ec329da Jan Kiszka
#include "qemu-common.h"
17 9c17d615 Paolo Bonzini
#include "sysemu/sysemu.h"
18 9c17d615 Paolo Bonzini
#include "sysemu/kvm.h"
19 3b9a6ee5 Jan Kiszka
#include "hw/sysbus.h"
20 3b9a6ee5 Jan Kiszka
#include "hw/kvm/clock.h"
21 0ec329da Jan Kiszka
22 0ec329da Jan Kiszka
#include <linux/kvm.h>
23 0ec329da Jan Kiszka
#include <linux/kvm_para.h>
24 0ec329da Jan Kiszka
25 0ec329da Jan Kiszka
typedef struct KVMClockState {
26 0ec329da Jan Kiszka
    SysBusDevice busdev;
27 0ec329da Jan Kiszka
    uint64_t clock;
28 0ec329da Jan Kiszka
    bool clock_valid;
29 0ec329da Jan Kiszka
} KVMClockState;
30 0ec329da Jan Kiszka
31 0ec329da Jan Kiszka
static void kvmclock_pre_save(void *opaque)
32 0ec329da Jan Kiszka
{
33 0ec329da Jan Kiszka
    KVMClockState *s = opaque;
34 0ec329da Jan Kiszka
    struct kvm_clock_data data;
35 0ec329da Jan Kiszka
    int ret;
36 0ec329da Jan Kiszka
37 0ec329da Jan Kiszka
    if (s->clock_valid) {
38 0ec329da Jan Kiszka
        return;
39 0ec329da Jan Kiszka
    }
40 0ec329da Jan Kiszka
    ret = kvm_vm_ioctl(kvm_state, KVM_GET_CLOCK, &data);
41 0ec329da Jan Kiszka
    if (ret < 0) {
42 0ec329da Jan Kiszka
        fprintf(stderr, "KVM_GET_CLOCK failed: %s\n", strerror(ret));
43 0ec329da Jan Kiszka
        data.clock = 0;
44 0ec329da Jan Kiszka
    }
45 0ec329da Jan Kiszka
    s->clock = data.clock;
46 0ec329da Jan Kiszka
    /*
47 0ec329da Jan Kiszka
     * If the VM is stopped, declare the clock state valid to avoid re-reading
48 0ec329da Jan Kiszka
     * it on next vmsave (which would return a different value). Will be reset
49 0ec329da Jan Kiszka
     * when the VM is continued.
50 0ec329da Jan Kiszka
     */
51 1354869c Luiz Capitulino
    s->clock_valid = !runstate_is_running();
52 0ec329da Jan Kiszka
}
53 0ec329da Jan Kiszka
54 0ec329da Jan Kiszka
static int kvmclock_post_load(void *opaque, int version_id)
55 0ec329da Jan Kiszka
{
56 0ec329da Jan Kiszka
    KVMClockState *s = opaque;
57 0ec329da Jan Kiszka
    struct kvm_clock_data data;
58 0ec329da Jan Kiszka
59 0ec329da Jan Kiszka
    data.clock = s->clock;
60 0ec329da Jan Kiszka
    data.flags = 0;
61 0ec329da Jan Kiszka
    return kvm_vm_ioctl(kvm_state, KVM_SET_CLOCK, &data);
62 0ec329da Jan Kiszka
}
63 0ec329da Jan Kiszka
64 1dfb4dd9 Luiz Capitulino
static void kvmclock_vm_state_change(void *opaque, int running,
65 1dfb4dd9 Luiz Capitulino
                                     RunState state)
66 0ec329da Jan Kiszka
{
67 0ec329da Jan Kiszka
    KVMClockState *s = opaque;
68 f349c12c Eric B Munson
    CPUArchState *penv = first_cpu;
69 f349c12c Eric B Munson
    int cap_clock_ctrl = kvm_check_extension(kvm_state, KVM_CAP_KVMCLOCK_CTRL);
70 f349c12c Eric B Munson
    int ret;
71 0ec329da Jan Kiszka
72 0ec329da Jan Kiszka
    if (running) {
73 0ec329da Jan Kiszka
        s->clock_valid = false;
74 f349c12c Eric B Munson
75 f349c12c Eric B Munson
        if (!cap_clock_ctrl) {
76 f349c12c Eric B Munson
            return;
77 f349c12c Eric B Munson
        }
78 f349c12c Eric B Munson
        for (penv = first_cpu; penv != NULL; penv = penv->next_cpu) {
79 1bc22652 Andreas Färber
            ret = kvm_vcpu_ioctl(ENV_GET_CPU(penv), KVM_KVMCLOCK_CTRL, 0);
80 f349c12c Eric B Munson
            if (ret) {
81 f349c12c Eric B Munson
                if (ret != -EINVAL) {
82 f349c12c Eric B Munson
                    fprintf(stderr, "%s: %s\n", __func__, strerror(-ret));
83 f349c12c Eric B Munson
                }
84 f349c12c Eric B Munson
                return;
85 f349c12c Eric B Munson
            }
86 f349c12c Eric B Munson
        }
87 0ec329da Jan Kiszka
    }
88 0ec329da Jan Kiszka
}
89 0ec329da Jan Kiszka
90 0ec329da Jan Kiszka
static int kvmclock_init(SysBusDevice *dev)
91 0ec329da Jan Kiszka
{
92 0ec329da Jan Kiszka
    KVMClockState *s = FROM_SYSBUS(KVMClockState, dev);
93 0ec329da Jan Kiszka
94 0ec329da Jan Kiszka
    qemu_add_vm_change_state_handler(kvmclock_vm_state_change, s);
95 0ec329da Jan Kiszka
    return 0;
96 0ec329da Jan Kiszka
}
97 0ec329da Jan Kiszka
98 0ec329da Jan Kiszka
static const VMStateDescription kvmclock_vmsd = {
99 0ec329da Jan Kiszka
    .name = "kvmclock",
100 0ec329da Jan Kiszka
    .version_id = 1,
101 0ec329da Jan Kiszka
    .minimum_version_id = 1,
102 0ec329da Jan Kiszka
    .minimum_version_id_old = 1,
103 0ec329da Jan Kiszka
    .pre_save = kvmclock_pre_save,
104 0ec329da Jan Kiszka
    .post_load = kvmclock_post_load,
105 0ec329da Jan Kiszka
    .fields = (VMStateField[]) {
106 0ec329da Jan Kiszka
        VMSTATE_UINT64(clock, KVMClockState),
107 0ec329da Jan Kiszka
        VMSTATE_END_OF_LIST()
108 0ec329da Jan Kiszka
    }
109 0ec329da Jan Kiszka
};
110 0ec329da Jan Kiszka
111 999e12bb Anthony Liguori
static void kvmclock_class_init(ObjectClass *klass, void *data)
112 999e12bb Anthony Liguori
{
113 39bffca2 Anthony Liguori
    DeviceClass *dc = DEVICE_CLASS(klass);
114 999e12bb Anthony Liguori
    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
115 999e12bb Anthony Liguori
116 999e12bb Anthony Liguori
    k->init = kvmclock_init;
117 39bffca2 Anthony Liguori
    dc->no_user = 1;
118 39bffca2 Anthony Liguori
    dc->vmsd = &kvmclock_vmsd;
119 999e12bb Anthony Liguori
}
120 999e12bb Anthony Liguori
121 8c43a6f0 Andreas Färber
static const TypeInfo kvmclock_info = {
122 39bffca2 Anthony Liguori
    .name          = "kvmclock",
123 39bffca2 Anthony Liguori
    .parent        = TYPE_SYS_BUS_DEVICE,
124 39bffca2 Anthony Liguori
    .instance_size = sizeof(KVMClockState),
125 39bffca2 Anthony Liguori
    .class_init    = kvmclock_class_init,
126 0ec329da Jan Kiszka
};
127 0ec329da Jan Kiszka
128 0ec329da Jan Kiszka
/* Note: Must be called after VCPU initialization. */
129 0ec329da Jan Kiszka
void kvmclock_create(void)
130 0ec329da Jan Kiszka
{
131 0ec329da Jan Kiszka
    if (kvm_enabled() &&
132 0514ef2f Eduardo Habkost
        first_cpu->features[FEAT_KVM] & ((1ULL << KVM_FEATURE_CLOCKSOURCE) |
133 cf7d3e64 Jan Kiszka
                                         (1ULL << KVM_FEATURE_CLOCKSOURCE2))) {
134 0ec329da Jan Kiszka
        sysbus_create_simple("kvmclock", -1, NULL);
135 0ec329da Jan Kiszka
    }
136 0ec329da Jan Kiszka
}
137 0ec329da Jan Kiszka
138 83f7d43a Andreas Färber
static void kvmclock_register_types(void)
139 0ec329da Jan Kiszka
{
140 39bffca2 Anthony Liguori
    type_register_static(&kvmclock_info);
141 0ec329da Jan Kiszka
}
142 0ec329da Jan Kiszka
143 83f7d43a Andreas Färber
type_init(kvmclock_register_types)