Revision 0ec329da
b/Makefile.target | ||
---|---|---|
37 | 37 |
LIBS+=-lm |
38 | 38 |
endif |
39 | 39 |
|
40 |
kvm.o kvm-all.o vhost.o vhost_net.o: QEMU_CFLAGS+=$(KVM_CFLAGS) |
|
40 |
kvm.o kvm-all.o vhost.o vhost_net.o kvmclock.o: QEMU_CFLAGS+=$(KVM_CFLAGS)
|
|
41 | 41 |
|
42 | 42 |
config-target.h: config-target.h-timestamp |
43 | 43 |
config-target.h-timestamp: config-target.mak |
... | ... | |
218 | 218 |
obj-i386-y += vmport.o applesmc.o |
219 | 219 |
obj-i386-y += device-hotplug.o pci-hotplug.o smbios.o wdt_ib700.o |
220 | 220 |
obj-i386-y += debugcon.o multiboot.o |
221 |
obj-i386-y += pc_piix.o |
|
221 |
obj-i386-y += pc_piix.o kvmclock.o
|
|
222 | 222 |
obj-i386-$(CONFIG_SPICE) += qxl.o qxl-logger.o qxl-render.o |
223 | 223 |
|
224 | 224 |
# shared objects |
b/hw/kvmclock.c | ||
---|---|---|
1 |
/* |
|
2 |
* QEMU KVM support, paravirtual clock device |
|
3 |
* |
|
4 |
* Copyright (C) 2011 Siemens AG |
|
5 |
* |
|
6 |
* Authors: |
|
7 |
* Jan Kiszka <jan.kiszka@siemens.com> |
|
8 |
* |
|
9 |
* This work is licensed under the terms of the GNU GPL version 2. |
|
10 |
* See the COPYING file in the top-level directory. |
|
11 |
* |
|
12 |
*/ |
|
13 |
|
|
14 |
#include "qemu-common.h" |
|
15 |
#include "sysemu.h" |
|
16 |
#include "sysbus.h" |
|
17 |
#include "kvm.h" |
|
18 |
#include "kvmclock.h" |
|
19 |
|
|
20 |
#if defined(CONFIG_KVM_PARA) && defined(KVM_CAP_ADJUST_CLOCK) |
|
21 |
|
|
22 |
#include <linux/kvm.h> |
|
23 |
#include <linux/kvm_para.h> |
|
24 |
|
|
25 |
typedef struct KVMClockState { |
|
26 |
SysBusDevice busdev; |
|
27 |
uint64_t clock; |
|
28 |
bool clock_valid; |
|
29 |
} KVMClockState; |
|
30 |
|
|
31 |
static void kvmclock_pre_save(void *opaque) |
|
32 |
{ |
|
33 |
KVMClockState *s = opaque; |
|
34 |
struct kvm_clock_data data; |
|
35 |
int ret; |
|
36 |
|
|
37 |
if (s->clock_valid) { |
|
38 |
return; |
|
39 |
} |
|
40 |
ret = kvm_vm_ioctl(kvm_state, KVM_GET_CLOCK, &data); |
|
41 |
if (ret < 0) { |
|
42 |
fprintf(stderr, "KVM_GET_CLOCK failed: %s\n", strerror(ret)); |
|
43 |
data.clock = 0; |
|
44 |
} |
|
45 |
s->clock = data.clock; |
|
46 |
/* |
|
47 |
* If the VM is stopped, declare the clock state valid to avoid re-reading |
|
48 |
* it on next vmsave (which would return a different value). Will be reset |
|
49 |
* when the VM is continued. |
|
50 |
*/ |
|
51 |
s->clock_valid = !vm_running; |
|
52 |
} |
|
53 |
|
|
54 |
static int kvmclock_post_load(void *opaque, int version_id) |
|
55 |
{ |
|
56 |
KVMClockState *s = opaque; |
|
57 |
struct kvm_clock_data data; |
|
58 |
|
|
59 |
data.clock = s->clock; |
|
60 |
data.flags = 0; |
|
61 |
return kvm_vm_ioctl(kvm_state, KVM_SET_CLOCK, &data); |
|
62 |
} |
|
63 |
|
|
64 |
static void kvmclock_vm_state_change(void *opaque, int running, int reason) |
|
65 |
{ |
|
66 |
KVMClockState *s = opaque; |
|
67 |
|
|
68 |
if (running) { |
|
69 |
s->clock_valid = false; |
|
70 |
} |
|
71 |
} |
|
72 |
|
|
73 |
static int kvmclock_init(SysBusDevice *dev) |
|
74 |
{ |
|
75 |
KVMClockState *s = FROM_SYSBUS(KVMClockState, dev); |
|
76 |
|
|
77 |
qemu_add_vm_change_state_handler(kvmclock_vm_state_change, s); |
|
78 |
return 0; |
|
79 |
} |
|
80 |
|
|
81 |
static const VMStateDescription kvmclock_vmsd = { |
|
82 |
.name = "kvmclock", |
|
83 |
.version_id = 1, |
|
84 |
.minimum_version_id = 1, |
|
85 |
.minimum_version_id_old = 1, |
|
86 |
.pre_save = kvmclock_pre_save, |
|
87 |
.post_load = kvmclock_post_load, |
|
88 |
.fields = (VMStateField[]) { |
|
89 |
VMSTATE_UINT64(clock, KVMClockState), |
|
90 |
VMSTATE_END_OF_LIST() |
|
91 |
} |
|
92 |
}; |
|
93 |
|
|
94 |
static SysBusDeviceInfo kvmclock_info = { |
|
95 |
.qdev.name = "kvmclock", |
|
96 |
.qdev.size = sizeof(KVMClockState), |
|
97 |
.qdev.vmsd = &kvmclock_vmsd, |
|
98 |
.qdev.no_user = 1, |
|
99 |
.init = kvmclock_init, |
|
100 |
}; |
|
101 |
|
|
102 |
/* Note: Must be called after VCPU initialization. */ |
|
103 |
void kvmclock_create(void) |
|
104 |
{ |
|
105 |
if (kvm_enabled() && |
|
106 |
first_cpu->cpuid_kvm_features & (1ULL << KVM_FEATURE_CLOCKSOURCE)) { |
|
107 |
sysbus_create_simple("kvmclock", -1, NULL); |
|
108 |
} |
|
109 |
} |
|
110 |
|
|
111 |
static void kvmclock_register_device(void) |
|
112 |
{ |
|
113 |
if (kvm_enabled()) { |
|
114 |
sysbus_register_withprop(&kvmclock_info); |
|
115 |
} |
|
116 |
} |
|
117 |
|
|
118 |
device_init(kvmclock_register_device); |
|
119 |
|
|
120 |
#else /* !(CONFIG_KVM_PARA && KVM_CAP_ADJUST_CLOCK) */ |
|
121 |
|
|
122 |
void kvmclock_create(void) |
|
123 |
{ |
|
124 |
} |
|
125 |
#endif /* !(CONFIG_KVM_PARA && KVM_CAP_ADJUST_CLOCK) */ |
b/hw/kvmclock.h | ||
---|---|---|
1 |
/* |
|
2 |
* QEMU KVM support, paravirtual clock device |
|
3 |
* |
|
4 |
* Copyright (C) 2011 Siemens AG |
|
5 |
* |
|
6 |
* Authors: |
|
7 |
* Jan Kiszka <jan.kiszka@siemens.com> |
|
8 |
* |
|
9 |
* This work is licensed under the terms of the GNU GPL version 2. |
|
10 |
* See the COPYING file in the top-level directory. |
|
11 |
* |
|
12 |
*/ |
|
13 |
|
|
14 |
void kvmclock_create(void); |
b/hw/pc_piix.c | ||
---|---|---|
32 | 32 |
#include "boards.h" |
33 | 33 |
#include "ide.h" |
34 | 34 |
#include "kvm.h" |
35 |
#include "kvmclock.h" |
|
35 | 36 |
#include "sysemu.h" |
36 | 37 |
#include "sysbus.h" |
37 | 38 |
#include "arch_init.h" |
... | ... | |
66 | 67 |
const char *kernel_cmdline, |
67 | 68 |
const char *initrd_filename, |
68 | 69 |
const char *cpu_model, |
69 |
int pci_enabled) |
|
70 |
int pci_enabled, |
|
71 |
int kvmclock_enabled) |
|
70 | 72 |
{ |
71 | 73 |
int i; |
72 | 74 |
ram_addr_t below_4g_mem_size, above_4g_mem_size; |
... | ... | |
86 | 88 |
|
87 | 89 |
pc_cpus_init(cpu_model); |
88 | 90 |
|
91 |
if (kvmclock_enabled) { |
|
92 |
kvmclock_create(); |
|
93 |
} |
|
94 |
|
|
89 | 95 |
/* allocate ram and load rom/bios */ |
90 | 96 |
pc_memory_init(ram_size, kernel_filename, kernel_cmdline, initrd_filename, |
91 | 97 |
&below_4g_mem_size, &above_4g_mem_size); |
... | ... | |
193 | 199 |
{ |
194 | 200 |
pc_init1(ram_size, boot_device, |
195 | 201 |
kernel_filename, kernel_cmdline, |
196 |
initrd_filename, cpu_model, 1); |
|
202 |
initrd_filename, cpu_model, 1, 1); |
|
203 |
} |
|
204 |
|
|
205 |
static void pc_init_pci_no_kvmclock(ram_addr_t ram_size, |
|
206 |
const char *boot_device, |
|
207 |
const char *kernel_filename, |
|
208 |
const char *kernel_cmdline, |
|
209 |
const char *initrd_filename, |
|
210 |
const char *cpu_model) |
|
211 |
{ |
|
212 |
pc_init1(ram_size, boot_device, |
|
213 |
kernel_filename, kernel_cmdline, |
|
214 |
initrd_filename, cpu_model, 1, 0); |
|
197 | 215 |
} |
198 | 216 |
|
199 | 217 |
static void pc_init_isa(ram_addr_t ram_size, |
... | ... | |
207 | 225 |
cpu_model = "486"; |
208 | 226 |
pc_init1(ram_size, boot_device, |
209 | 227 |
kernel_filename, kernel_cmdline, |
210 |
initrd_filename, cpu_model, 0); |
|
228 |
initrd_filename, cpu_model, 0, 1);
|
|
211 | 229 |
} |
212 | 230 |
|
213 | 231 |
static QEMUMachine pc_machine = { |
... | ... | |
222 | 240 |
static QEMUMachine pc_machine_v0_13 = { |
223 | 241 |
.name = "pc-0.13", |
224 | 242 |
.desc = "Standard PC", |
225 |
.init = pc_init_pci, |
|
243 |
.init = pc_init_pci_no_kvmclock,
|
|
226 | 244 |
.max_cpus = 255, |
227 | 245 |
.compat_props = (GlobalProperty[]) { |
228 | 246 |
{ |
... | ... | |
249 | 267 |
static QEMUMachine pc_machine_v0_12 = { |
250 | 268 |
.name = "pc-0.12", |
251 | 269 |
.desc = "Standard PC", |
252 |
.init = pc_init_pci, |
|
270 |
.init = pc_init_pci_no_kvmclock,
|
|
253 | 271 |
.max_cpus = 255, |
254 | 272 |
.compat_props = (GlobalProperty[]) { |
255 | 273 |
{ |
... | ... | |
280 | 298 |
static QEMUMachine pc_machine_v0_11 = { |
281 | 299 |
.name = "pc-0.11", |
282 | 300 |
.desc = "Standard PC, qemu 0.11", |
283 |
.init = pc_init_pci, |
|
301 |
.init = pc_init_pci_no_kvmclock,
|
|
284 | 302 |
.max_cpus = 255, |
285 | 303 |
.compat_props = (GlobalProperty[]) { |
286 | 304 |
{ |
... | ... | |
319 | 337 |
static QEMUMachine pc_machine_v0_10 = { |
320 | 338 |
.name = "pc-0.10", |
321 | 339 |
.desc = "Standard PC, qemu 0.10", |
322 |
.init = pc_init_pci, |
|
340 |
.init = pc_init_pci_no_kvmclock,
|
|
323 | 341 |
.max_cpus = 255, |
324 | 342 |
.compat_props = (GlobalProperty[]) { |
325 | 343 |
{ |
Also available in: Unified diff