Creating part of the -cpu command-line from something other than the
<cpu> XML element introduces some ugliness.
---
src/qemu/qemu_command.c | 72 ++++++++++++++++++--
tests/qemuargv2xmltest.c | 4 +
.../qemuxml2argv-cpu-host-kvmclock.args | 4 +
.../qemuxml2argv-cpu-host-kvmclock.xml | 23 ++++++
.../qemuxml2argv-cpu-kvmclock.args | 4 +
.../qemuxml2argvdata/qemuxml2argv-cpu-kvmclock.xml | 24 +++++++
tests/qemuxml2argvdata/qemuxml2argv-kvmclock.args | 4 +
tests/qemuxml2argvdata/qemuxml2argv-kvmclock.xml | 21 ++++++
tests/qemuxml2argvtest.c | 3 +
tests/qemuxml2xmltest.c | 3 +
10 files changed, 157 insertions(+), 5 deletions(-)
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-cpu-host-kvmclock.args
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-cpu-host-kvmclock.xml
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-cpu-kvmclock.args
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-cpu-kvmclock.xml
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-kvmclock.args
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-kvmclock.xml
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 7c4460e..24e3adf 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -3500,7 +3500,9 @@ qemuBuildCpuArgStr(const struct qemud_driver *driver,
virCPUDefPtr cpu = NULL;
unsigned int ncpus = 0;
const char **cpus = NULL;
+ const char *default_model;
union cpuData *data = NULL;
+ bool have_cpu = false;
int ret = -1;
virBuffer buf = VIR_BUFFER_INITIALIZER;
int i;
@@ -3517,6 +3519,11 @@ qemuBuildCpuArgStr(const struct qemud_driver *driver,
goto cleanup;
}
+ if (STREQ(def->os.arch, "i686"))
+ default_model = "qemu32";
+ else
+ default_model = "qemu64";
+
if (cpu) {
virCPUCompareResult cmp;
const char *preferred;
@@ -3594,6 +3601,7 @@ qemuBuildCpuArgStr(const struct qemud_driver *driver,
virBufferAsprintf(&buf, ",%c%s", sign,
guest->features[i].name);
}
}
+ have_cpu = true;
} else {
/*
* Need to force a 32-bit guest CPU type if
@@ -3610,8 +3618,26 @@ qemuBuildCpuArgStr(const struct qemud_driver *driver,
if (STREQ(def->os.arch, "i686") &&
((STREQ(ut->machine, "x86_64") &&
strstr(emulator, "kvm")) ||
- strstr(emulator, "x86_64")))
- virBufferAddLit(&buf, "qemu32");
+ strstr(emulator, "x86_64"))) {
+ virBufferAdd(&buf, default_model, -1);
+ have_cpu = true;
+ }
+ }
+
+ /* Now force kvmclock on/off based on the corresponding <timer> element. */
+ for (i = 0; i < def->clock.ntimers; i++) {
+ if (def->clock.timers[i]->name == VIR_DOMAIN_TIMER_NAME_KVMCLOCK
&&
+ def->clock.timers[i]->present != -1) {
+ char sign;
+ if (def->clock.timers[i]->present)
+ sign = '+';
+ else
+ sign = '-';
+ virBufferAsprintf(&buf, "%s,%ckvmclock",
+ have_cpu ? "" : default_model,
+ sign);
+ break;
+ }
}
if (virBufferError(&buf))
@@ -4091,6 +4117,10 @@ qemuBuildCommandLine(virConnectPtr conn,
virDomainTimerNameTypeToString(def->clock.timers[i]->name));
goto error;
+ case VIR_DOMAIN_TIMER_NAME_KVMCLOCK:
+ /* This is handled when building -cpu. */
+ break;
+
case VIR_DOMAIN_TIMER_NAME_RTC:
/* This has already been taken care of (in qemuBuildClockArgStr)
if QEMU_CAPS_RTC is set (mutually exclusive with
@@ -6822,10 +6852,42 @@ qemuParseCommandLineCPU(virDomainDefPtr dom,
if (!feature)
goto no_memory;
- if (!cpu && !(cpu = qemuInitGuestCPU(dom)))
- goto error;
+ if (STREQ(feature, "kvmclock")) {
+ bool present = (policy == VIR_CPU_FEATURE_REQUIRE);
+ int i;
+
+ for (i = 0; i < dom->clock.ntimers; i++) {
+ if (dom->clock.timers[i]->name ==
VIR_DOMAIN_TIMER_NAME_KVMCLOCK) {
+ break;
+ }
+ }
+
+ if (i == dom->clock.ntimers) {
+ if (VIR_REALLOC_N(dom->clock.timers, i+1) < 0 ||
+ VIR_ALLOC(dom->clock.timers[i]) < 0)
+ goto no_memory;
+ dom->clock.timers[i]->name = VIR_DOMAIN_TIMER_NAME_KVMCLOCK;
+ dom->clock.timers[i]->present = -1;
+ dom->clock.timers[i]->tickpolicy = -1;
+ dom->clock.timers[i]->track = -1;
+ dom->clock.ntimers++;
+ }
+
+ if (dom->clock.timers[i]->present != -1 &&
+ dom->clock.timers[i]->present != present) {
+ qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("multiple occurrences of kvmclock
feature"));
+ goto error;
+ }
+ dom->clock.timers[i]->present = present;
+ ret = 0;
+ } else {
+ if (!cpu && !(cpu = qemuInitGuestCPU(dom)))
+ goto error;
+
+ ret = virCPUDefAddFeature(cpu, feature, policy);
+ }
- ret = virCPUDefAddFeature(cpu, feature, policy);
VIR_FREE(feature);
if (ret < 0)
goto error;
diff --git a/tests/qemuargv2xmltest.c b/tests/qemuargv2xmltest.c
index cb3cafd..28434ff 100644
--- a/tests/qemuargv2xmltest.c
+++ b/tests/qemuargv2xmltest.c
@@ -144,6 +144,10 @@ mymain(void)
DO_TEST("boot-cdrom");
DO_TEST("boot-network");
DO_TEST("boot-floppy");
+ DO_TEST("kvmclock");
+ /* This needs <emulator>./qemu.sh</emulator> which doesn't work here.
*/
+ /*DO_TEST("cpu-kvmclock");*/
+
/* Can't roundtrip xenner arch */
/*DO_TEST("bootloader");*/
DO_TEST("clock-utc");
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-cpu-host-kvmclock.args
b/tests/qemuxml2argvdata/qemuxml2argv-cpu-host-kvmclock.args
new file mode 100644
index 0000000..6a5df28
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-cpu-host-kvmclock.args
@@ -0,0 +1,4 @@
+LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test ./qemu.sh -S -M pc \
+-cpu host,-kvmclock -m 214 -smp 6 \
+-nographic -monitor unix:/tmp/test-monitor,server,nowait -no-acpi -boot n -net \
+none -serial none -parallel none -usb
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-cpu-host-kvmclock.xml
b/tests/qemuxml2argvdata/qemuxml2argv-cpu-host-kvmclock.xml
new file mode 100644
index 0000000..15a9e44
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-cpu-host-kvmclock.xml
@@ -0,0 +1,23 @@
+<domain type='kvm'>
+ <name>QEMUGuest1</name>
+ <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+ <memory>219100</memory>
+ <currentMemory>219100</currentMemory>
+ <vcpu>6</vcpu>
+ <os>
+ <type arch='x86_64' machine='pc'>hvm</type>
+ <boot dev='network'/>
+ </os>
+ <cpu mode='host-passthrough'>
+ </cpu>
+ <clock offset='utc'>
+ <timer name='kvmclock' present='no'/>
+ </clock>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>destroy</on_crash>
+ <devices>
+ <emulator>/./qemu.sh</emulator>
+ <memballoon model='virtio'/>
+ </devices>
+</domain>
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-cpu-kvmclock.args
b/tests/qemuxml2argvdata/qemuxml2argv-cpu-kvmclock.args
new file mode 100644
index 0000000..f7c33fb
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-cpu-kvmclock.args
@@ -0,0 +1,4 @@
+LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test ./qemu.sh -S -M pc \
+-cpu core2duo,-kvmclock -m 214 -smp 6 \
+-nographic -monitor unix:/tmp/test-monitor,server,nowait -no-acpi -boot n -net \
+none -serial none -parallel none -usb
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-cpu-kvmclock.xml
b/tests/qemuxml2argvdata/qemuxml2argv-cpu-kvmclock.xml
new file mode 100644
index 0000000..e8b0bb1
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-cpu-kvmclock.xml
@@ -0,0 +1,24 @@
+<domain type='qemu'>
+ <name>QEMUGuest1</name>
+ <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+ <memory>219100</memory>
+ <currentMemory>219100</currentMemory>
+ <vcpu>6</vcpu>
+ <os>
+ <type arch='i686' machine='pc'>hvm</type>
+ <boot dev='network'/>
+ </os>
+ <cpu mode='custom' match='exact'>
+ <model fallback='allow'>core2duo</model>
+ </cpu>
+ <clock offset='utc'>
+ <timer name='kvmclock' present='no'/>
+ </clock>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>destroy</on_crash>
+ <devices>
+ <emulator>/./qemu.sh</emulator>
+ <memballoon model='virtio'/>
+ </devices>
+</domain>
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-kvmclock.args
b/tests/qemuxml2argvdata/qemuxml2argv-kvmclock.args
new file mode 100644
index 0000000..4c7aa3b
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-kvmclock.args
@@ -0,0 +1,4 @@
+LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu-kvm -S -M pc \
+-cpu qemu32,-kvmclock -m 214 -smp 6 \
+-nographic -monitor unix:/tmp/test-monitor,server,nowait -no-acpi -boot n -net \
+none -serial none -parallel none -usb
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-kvmclock.xml
b/tests/qemuxml2argvdata/qemuxml2argv-kvmclock.xml
new file mode 100644
index 0000000..2e090ae
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-kvmclock.xml
@@ -0,0 +1,21 @@
+<domain type='kvm'>
+ <name>QEMUGuest1</name>
+ <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+ <memory>219100</memory>
+ <currentMemory>219100</currentMemory>
+ <vcpu>6</vcpu>
+ <os>
+ <type arch='i686' machine='pc'>hvm</type>
+ <boot dev='network'/>
+ </os>
+ <clock offset='utc'>
+ <timer name='kvmclock' present='no'/>
+ </clock>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>destroy</on_crash>
+ <devices>
+ <emulator>/usr/bin/qemu-kvm</emulator>
+ <memballoon model='virtio'/>
+ </devices>
+</domain>
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
index d40b37e..ddb4369 100644
--- a/tests/qemuxml2argvtest.c
+++ b/tests/qemuxml2argvtest.c
@@ -385,6 +385,9 @@ mymain(void)
DO_TEST("clock-variable", false, QEMU_CAPS_RTC);
*/
DO_TEST("clock-france", false, QEMU_CAPS_RTC);
+ DO_TEST("cpu-kvmclock", false, NONE);
+ DO_TEST("cpu-host-kvmclock", false, QEMU_CAPS_KVM, QEMU_CAPS_CPU_HOST);
+ DO_TEST("kvmclock", false, NONE);
DO_TEST("hugepages", false, QEMU_CAPS_MEM_PATH);
DO_TEST("disk-cdrom", false, NONE);
diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c
index 293c2a7..caff5c6 100644
--- a/tests/qemuxml2xmltest.c
+++ b/tests/qemuxml2xmltest.c
@@ -124,6 +124,9 @@ mymain(void)
DO_TEST("bootloader");
DO_TEST("clock-utc");
DO_TEST("clock-localtime");
+ DO_TEST("cpu-kvmclock");
+ DO_TEST("cpu-host-kvmclock");
+ DO_TEST("kvmclock");
DO_TEST("hugepages");
DO_TEST("disk-aio");
DO_TEST("disk-cdrom");
--
1.7.7.1