root / hw / kvmclock.c @ ba7cb5a8
History | View | Annotate | Download (2.9 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 | 0ec329da | Jan Kiszka | */
|
13 | 0ec329da | Jan Kiszka | |
14 | 0ec329da | Jan Kiszka | #include "qemu-common.h" |
15 | 0ec329da | Jan Kiszka | #include "sysemu.h" |
16 | 0ec329da | Jan Kiszka | #include "sysbus.h" |
17 | 0ec329da | Jan Kiszka | #include "kvm.h" |
18 | 0ec329da | Jan Kiszka | #include "kvmclock.h" |
19 | 0ec329da | Jan Kiszka | |
20 | 0ec329da | Jan Kiszka | #if defined(CONFIG_KVM_PARA) && defined(KVM_CAP_ADJUST_CLOCK)
|
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 | 0ec329da | Jan Kiszka | s->clock_valid = !vm_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 | 0ec329da | Jan Kiszka | static void kvmclock_vm_state_change(void *opaque, int running, int reason) |
65 | 0ec329da | Jan Kiszka | { |
66 | 0ec329da | Jan Kiszka | KVMClockState *s = opaque; |
67 | 0ec329da | Jan Kiszka | |
68 | 0ec329da | Jan Kiszka | if (running) {
|
69 | 0ec329da | Jan Kiszka | s->clock_valid = false;
|
70 | 0ec329da | Jan Kiszka | } |
71 | 0ec329da | Jan Kiszka | } |
72 | 0ec329da | Jan Kiszka | |
73 | 0ec329da | Jan Kiszka | static int kvmclock_init(SysBusDevice *dev) |
74 | 0ec329da | Jan Kiszka | { |
75 | 0ec329da | Jan Kiszka | KVMClockState *s = FROM_SYSBUS(KVMClockState, dev); |
76 | 0ec329da | Jan Kiszka | |
77 | 0ec329da | Jan Kiszka | qemu_add_vm_change_state_handler(kvmclock_vm_state_change, s); |
78 | 0ec329da | Jan Kiszka | return 0; |
79 | 0ec329da | Jan Kiszka | } |
80 | 0ec329da | Jan Kiszka | |
81 | 0ec329da | Jan Kiszka | static const VMStateDescription kvmclock_vmsd = { |
82 | 0ec329da | Jan Kiszka | .name = "kvmclock",
|
83 | 0ec329da | Jan Kiszka | .version_id = 1,
|
84 | 0ec329da | Jan Kiszka | .minimum_version_id = 1,
|
85 | 0ec329da | Jan Kiszka | .minimum_version_id_old = 1,
|
86 | 0ec329da | Jan Kiszka | .pre_save = kvmclock_pre_save, |
87 | 0ec329da | Jan Kiszka | .post_load = kvmclock_post_load, |
88 | 0ec329da | Jan Kiszka | .fields = (VMStateField[]) { |
89 | 0ec329da | Jan Kiszka | VMSTATE_UINT64(clock, KVMClockState), |
90 | 0ec329da | Jan Kiszka | VMSTATE_END_OF_LIST() |
91 | 0ec329da | Jan Kiszka | } |
92 | 0ec329da | Jan Kiszka | }; |
93 | 0ec329da | Jan Kiszka | |
94 | 0ec329da | Jan Kiszka | static SysBusDeviceInfo kvmclock_info = {
|
95 | 0ec329da | Jan Kiszka | .qdev.name = "kvmclock",
|
96 | 0ec329da | Jan Kiszka | .qdev.size = sizeof(KVMClockState),
|
97 | 0ec329da | Jan Kiszka | .qdev.vmsd = &kvmclock_vmsd, |
98 | 0ec329da | Jan Kiszka | .qdev.no_user = 1,
|
99 | 0ec329da | Jan Kiszka | .init = kvmclock_init, |
100 | 0ec329da | Jan Kiszka | }; |
101 | 0ec329da | Jan Kiszka | |
102 | 0ec329da | Jan Kiszka | /* Note: Must be called after VCPU initialization. */
|
103 | 0ec329da | Jan Kiszka | void kvmclock_create(void) |
104 | 0ec329da | Jan Kiszka | { |
105 | 0ec329da | Jan Kiszka | if (kvm_enabled() &&
|
106 | 450fb75c | Glauber Costa | first_cpu->cpuid_kvm_features & ((1ULL << KVM_FEATURE_CLOCKSOURCE)
|
107 | 450fb75c | Glauber Costa | #ifdef KVM_FEATURE_CLOCKSOURCE2
|
108 | 450fb75c | Glauber Costa | || (1ULL << KVM_FEATURE_CLOCKSOURCE2)
|
109 | 450fb75c | Glauber Costa | #endif
|
110 | 450fb75c | Glauber Costa | )) { |
111 | 0ec329da | Jan Kiszka | sysbus_create_simple("kvmclock", -1, NULL); |
112 | 0ec329da | Jan Kiszka | } |
113 | 0ec329da | Jan Kiszka | } |
114 | 0ec329da | Jan Kiszka | |
115 | 0ec329da | Jan Kiszka | static void kvmclock_register_device(void) |
116 | 0ec329da | Jan Kiszka | { |
117 | 0ec329da | Jan Kiszka | if (kvm_enabled()) {
|
118 | 0ec329da | Jan Kiszka | sysbus_register_withprop(&kvmclock_info); |
119 | 0ec329da | Jan Kiszka | } |
120 | 0ec329da | Jan Kiszka | } |
121 | 0ec329da | Jan Kiszka | |
122 | 0ec329da | Jan Kiszka | device_init(kvmclock_register_device); |
123 | 0ec329da | Jan Kiszka | |
124 | 0ec329da | Jan Kiszka | #else /* !(CONFIG_KVM_PARA && KVM_CAP_ADJUST_CLOCK) */ |
125 | 0ec329da | Jan Kiszka | |
126 | 0ec329da | Jan Kiszka | void kvmclock_create(void) |
127 | 0ec329da | Jan Kiszka | { |
128 | 0ec329da | Jan Kiszka | } |
129 | 0ec329da | Jan Kiszka | #endif /* !(CONFIG_KVM_PARA && KVM_CAP_ADJUST_CLOCK) */ |