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) |