]> git.proxmox.com Git - mirror_qemu.git/blame - hw/i386/kvm/i8254.c
Use DECLARE_*CHECKER* macros
[mirror_qemu.git] / hw / i386 / kvm / i8254.c
CommitLineData
5d17c0d2
JK
1/*
2 * KVM in-kernel PIT (i8254) support
3 *
4 * Copyright (c) 2003-2004 Fabrice Bellard
5 * Copyright (c) 2012 Jan Kiszka, Siemens AG
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 */
a9c94277 25
b6a0aa05 26#include "qemu/osdep.h"
a9c94277 27#include <linux/kvm.h>
2ae16a6a 28#include "qapi/qapi-types-misc.h"
da34e65c 29#include "qapi/error.h"
0b8fa32f 30#include "qemu/module.h"
1de7afc9 31#include "qemu/timer.h"
54d31236 32#include "sysemu/runstate.h"
0d09e41a
PB
33#include "hw/timer/i8254.h"
34#include "hw/timer/i8254_internal.h"
9c17d615 35#include "sysemu/kvm.h"
db1015e9 36#include "qom/object.h"
5d17c0d2
JK
37
38#define KVM_PIT_REINJECT_BIT 0
39
0cdd3d14
JK
40#define CALIBRATION_ROUNDS 3
41
db1015e9
EH
42typedef struct KVMPITClass KVMPITClass;
43typedef struct KVMPITState KVMPITState;
8110fa1d
EH
44DECLARE_OBJ_CHECKERS(KVMPITState, KVMPITClass,
45 KVM_PIT, TYPE_KVM_I8254)
58cd9864 46
db1015e9 47struct KVMPITState {
58cd9864
AF
48 PITCommonState parent_obj;
49
5d17c0d2 50 LostTickPolicy lost_tick_policy;
205df4d1
JK
51 bool vm_stopped;
52 int64_t kernel_clock_offset;
db1015e9 53};
5d17c0d2 54
db1015e9 55struct KVMPITClass {
a15d0912
AF
56 PITCommonClass parent_class;
57
58 DeviceRealize parent_realize;
db1015e9 59};
a15d0912 60
0cdd3d14 61static int64_t abs64(int64_t v)
5d17c0d2 62{
0cdd3d14
JK
63 return v < 0 ? -v : v;
64}
65
205df4d1 66static void kvm_pit_update_clock_offset(KVMPITState *s)
0cdd3d14 67{
0cdd3d14
JK
68 int64_t offset, clock_offset;
69 struct timespec ts;
205df4d1 70 int i;
0cdd3d14
JK
71
72 /*
73 * Measure the delta between CLOCK_MONOTONIC, the base used for
bc72ad67 74 * kvm_pit_channel_state::count_load_time, and QEMU_CLOCK_VIRTUAL. Take the
0cdd3d14
JK
75 * minimum of several samples to filter out scheduling noise.
76 */
77 clock_offset = INT64_MAX;
78 for (i = 0; i < CALIBRATION_ROUNDS; i++) {
bc72ad67 79 offset = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
0cdd3d14
JK
80 clock_gettime(CLOCK_MONOTONIC, &ts);
81 offset -= ts.tv_nsec;
82 offset -= (int64_t)ts.tv_sec * 1000000000;
83 if (abs64(offset) < abs64(clock_offset)) {
84 clock_offset = offset;
85 }
86 }
205df4d1
JK
87 s->kernel_clock_offset = clock_offset;
88}
89
90static void kvm_pit_get(PITCommonState *pit)
91{
58cd9864 92 KVMPITState *s = KVM_PIT(pit);
205df4d1
JK
93 struct kvm_pit_state2 kpit;
94 struct kvm_pit_channel_state *kchan;
95 struct PITChannelState *sc;
96 int i, ret;
97
98 /* No need to re-read the state if VM is stopped. */
99 if (s->vm_stopped) {
100 return;
101 }
0cdd3d14 102
5d17c0d2
JK
103 if (kvm_has_pit_state2()) {
104 ret = kvm_vm_ioctl(kvm_state, KVM_GET_PIT2, &kpit);
105 if (ret < 0) {
106 fprintf(stderr, "KVM_GET_PIT2 failed: %s\n", strerror(ret));
107 abort();
108 }
0cdd3d14 109 pit->channels[0].irq_disabled = kpit.flags & KVM_PIT_FLAGS_HPET_LEGACY;
5d17c0d2
JK
110 } else {
111 /*
112 * kvm_pit_state2 is superset of kvm_pit_state struct,
113 * so we can use it for KVM_GET_PIT as well.
114 */
115 ret = kvm_vm_ioctl(kvm_state, KVM_GET_PIT, &kpit);
116 if (ret < 0) {
117 fprintf(stderr, "KVM_GET_PIT failed: %s\n", strerror(ret));
118 abort();
119 }
120 }
121 for (i = 0; i < 3; i++) {
122 kchan = &kpit.channels[i];
0cdd3d14 123 sc = &pit->channels[i];
5d17c0d2
JK
124 sc->count = kchan->count;
125 sc->latched_count = kchan->latched_count;
126 sc->count_latched = kchan->count_latched;
127 sc->status_latched = kchan->status_latched;
128 sc->status = kchan->status;
129 sc->read_state = kchan->read_state;
130 sc->write_state = kchan->write_state;
131 sc->write_latch = kchan->write_latch;
132 sc->rw_mode = kchan->rw_mode;
133 sc->mode = kchan->mode;
134 sc->bcd = kchan->bcd;
135 sc->gate = kchan->gate;
205df4d1 136 sc->count_load_time = kchan->count_load_time + s->kernel_clock_offset;
5d17c0d2
JK
137 }
138
0cdd3d14 139 sc = &pit->channels[0];
5d17c0d2
JK
140 sc->next_transition_time =
141 pit_get_next_transition_time(sc, sc->count_load_time);
142}
143
050a4606 144static void kvm_pit_put(PITCommonState *pit)
5d17c0d2 145{
58cd9864 146 KVMPITState *s = KVM_PIT(pit);
b0a05512 147 struct kvm_pit_state2 kpit = {};
5d17c0d2
JK
148 struct kvm_pit_channel_state *kchan;
149 struct PITChannelState *sc;
150 int i, ret;
151
050a4606
JK
152 /* The offset keeps changing as long as the VM is stopped. */
153 if (s->vm_stopped) {
154 kvm_pit_update_clock_offset(s);
155 }
156
157 kpit.flags = pit->channels[0].irq_disabled ? KVM_PIT_FLAGS_HPET_LEGACY : 0;
5d17c0d2
JK
158 for (i = 0; i < 3; i++) {
159 kchan = &kpit.channels[i];
050a4606 160 sc = &pit->channels[i];
5d17c0d2
JK
161 kchan->count = sc->count;
162 kchan->latched_count = sc->latched_count;
163 kchan->count_latched = sc->count_latched;
164 kchan->status_latched = sc->status_latched;
165 kchan->status = sc->status;
166 kchan->read_state = sc->read_state;
167 kchan->write_state = sc->write_state;
168 kchan->write_latch = sc->write_latch;
169 kchan->rw_mode = sc->rw_mode;
170 kchan->mode = sc->mode;
171 kchan->bcd = sc->bcd;
172 kchan->gate = sc->gate;
050a4606 173 kchan->count_load_time = sc->count_load_time - s->kernel_clock_offset;
5d17c0d2
JK
174 }
175
176 ret = kvm_vm_ioctl(kvm_state,
177 kvm_has_pit_state2() ? KVM_SET_PIT2 : KVM_SET_PIT,
178 &kpit);
179 if (ret < 0) {
180 fprintf(stderr, "%s failed: %s\n",
181 kvm_has_pit_state2() ? "KVM_SET_PIT2" : "KVM_SET_PIT",
182 strerror(ret));
183 abort();
184 }
185}
186
187static void kvm_pit_set_gate(PITCommonState *s, PITChannelState *sc, int val)
188{
189 kvm_pit_get(s);
190
191 switch (sc->mode) {
192 default:
193 case 0:
194 case 4:
195 /* XXX: just disable/enable counting */
196 break;
197 case 1:
198 case 2:
199 case 3:
200 case 5:
201 if (sc->gate < val) {
202 /* restart counting on rising edge */
bc72ad67 203 sc->count_load_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
5d17c0d2
JK
204 }
205 break;
206 }
207 sc->gate = val;
208
209 kvm_pit_put(s);
210}
211
212static void kvm_pit_get_channel_info(PITCommonState *s, PITChannelState *sc,
213 PITChannelInfo *info)
214{
215 kvm_pit_get(s);
216
217 pit_get_channel_info_common(s, sc, info);
218}
219
220static void kvm_pit_reset(DeviceState *dev)
221{
58cd9864 222 PITCommonState *s = PIT_COMMON(dev);
5d17c0d2
JK
223
224 pit_reset_common(s);
225
226 kvm_pit_put(s);
227}
228
229static void kvm_pit_irq_control(void *opaque, int n, int enable)
230{
231 PITCommonState *pit = opaque;
232 PITChannelState *s = &pit->channels[0];
233
234 kvm_pit_get(pit);
235
236 s->irq_disabled = !enable;
237
238 kvm_pit_put(pit);
239}
240
0cdd3d14
JK
241static void kvm_pit_vm_state_change(void *opaque, int running,
242 RunState state)
243{
244 KVMPITState *s = opaque;
245
246 if (running) {
205df4d1 247 kvm_pit_update_clock_offset(s);
be894f51 248 kvm_pit_put(PIT_COMMON(s));
205df4d1 249 s->vm_stopped = false;
0cdd3d14 250 } else {
205df4d1 251 kvm_pit_update_clock_offset(s);
58cd9864 252 kvm_pit_get(PIT_COMMON(s));
205df4d1 253 s->vm_stopped = true;
0cdd3d14
JK
254 }
255}
256
a15d0912 257static void kvm_pit_realizefn(DeviceState *dev, Error **errp)
5d17c0d2 258{
a15d0912
AF
259 PITCommonState *pit = PIT_COMMON(dev);
260 KVMPITClass *kpc = KVM_PIT_GET_CLASS(dev);
58cd9864 261 KVMPITState *s = KVM_PIT(pit);
5d17c0d2
JK
262 struct kvm_pit_config config = {
263 .flags = 0,
264 };
265 int ret;
266
267 if (kvm_check_extension(kvm_state, KVM_CAP_PIT2)) {
268 ret = kvm_vm_ioctl(kvm_state, KVM_CREATE_PIT2, &config);
269 } else {
270 ret = kvm_vm_ioctl(kvm_state, KVM_CREATE_PIT);
271 }
272 if (ret < 0) {
a15d0912
AF
273 error_setg(errp, "Create kernel PIC irqchip failed: %s",
274 strerror(ret));
275 return;
5d17c0d2
JK
276 }
277 switch (s->lost_tick_policy) {
104059da 278 case LOST_TICK_POLICY_DELAY:
5d17c0d2 279 break; /* enabled by default */
104059da 280 case LOST_TICK_POLICY_DISCARD:
5d17c0d2
JK
281 if (kvm_check_extension(kvm_state, KVM_CAP_REINJECT_CONTROL)) {
282 struct kvm_reinject_control control = { .pit_reinject = 0 };
283
284 ret = kvm_vm_ioctl(kvm_state, KVM_REINJECT_CONTROL, &control);
285 if (ret < 0) {
a15d0912
AF
286 error_setg(errp,
287 "Can't disable in-kernel PIT reinjection: %s",
288 strerror(ret));
289 return;
5d17c0d2
JK
290 }
291 }
292 break;
293 default:
a15d0912
AF
294 error_setg(errp, "Lost tick policy not supported.");
295 return;
5d17c0d2
JK
296 }
297
257a7430 298 memory_region_init_io(&pit->ioports, OBJECT(dev), NULL, NULL, "kvm-pit", 4);
5d17c0d2 299
a15d0912 300 qdev_init_gpio_in(dev, kvm_pit_irq_control, 1);
5d17c0d2 301
0cdd3d14
JK
302 qemu_add_vm_change_state_handler(kvm_pit_vm_state_change, s);
303
a15d0912 304 kpc->parent_realize(dev, errp);
5d17c0d2
JK
305}
306
307static Property kvm_pit_properties[] = {
c7bcc85d 308 DEFINE_PROP_UINT32("iobase", PITCommonState, iobase, -1),
5d17c0d2 309 DEFINE_PROP_LOSTTICKPOLICY("lost_tick_policy", KVMPITState,
104059da 310 lost_tick_policy, LOST_TICK_POLICY_DELAY),
5d17c0d2
JK
311 DEFINE_PROP_END_OF_LIST(),
312};
313
314static void kvm_pit_class_init(ObjectClass *klass, void *data)
315{
a15d0912 316 KVMPITClass *kpc = KVM_PIT_CLASS(klass);
5d17c0d2
JK
317 PITCommonClass *k = PIT_COMMON_CLASS(klass);
318 DeviceClass *dc = DEVICE_CLASS(klass);
319
bf853881
PMD
320 device_class_set_parent_realize(dc, kvm_pit_realizefn,
321 &kpc->parent_realize);
5d17c0d2
JK
322 k->set_channel_gate = kvm_pit_set_gate;
323 k->get_channel_info = kvm_pit_get_channel_info;
5d17c0d2 324 dc->reset = kvm_pit_reset;
4f67d30b 325 device_class_set_props(dc, kvm_pit_properties);
5d17c0d2
JK
326}
327
8c43a6f0 328static const TypeInfo kvm_pit_info = {
58cd9864 329 .name = TYPE_KVM_I8254,
5d17c0d2
JK
330 .parent = TYPE_PIT_COMMON,
331 .instance_size = sizeof(KVMPITState),
332 .class_init = kvm_pit_class_init,
a15d0912 333 .class_size = sizeof(KVMPITClass),
5d17c0d2
JK
334};
335
336static void kvm_pit_register(void)
337{
338 type_register_static(&kvm_pit_info);
339}
340
341type_init(kvm_pit_register)