[libvirt] [PATCH v2 7/7] qemu: parse and create -cpu ..., -kvmclock

Paolo Bonzini pbonzini at redhat.com
Fri Jan 27 13:49:52 UTC 2012


Creating part of the -cpu command-line from something other than the
<cpu> XML element introduces some ugliness.

Reviewed-by: Jiri Denemark <jdenemar at redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
---
 src/qemu/qemu_command.c                            |   77 ++++++++++++++++++--
 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, 160 insertions(+), 7 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 d01696e..a39622c 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
@@ -6829,14 +6859,47 @@ qemuParseCommandLineCPU(virDomainDefPtr dom,
             if (!feature)
                 goto no_memory;
 
-            if (!cpu) {
-                if (!(cpu = qemuInitGuestCPU(dom)))
+            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,
+                                    _("conflicting occurrences of kvmclock feature"));
                     goto error;
+                }
+                dom->clock.timers[i]->present = present;
+                ret = 0;
+            } else {
+                if (!cpu) {
+                    if (!(cpu = qemuInitGuestCPU(dom)))
+                        goto error;
 
-                cpu->model = model;
-                model = NULL;
+                    cpu->model = model;
+                    model = NULL;
+                }
+
+                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..8472b8a
--- /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 -enable-kvm -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..6816c00
--- /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 -enable-kvm -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..bae4c47
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-cpu-kvmclock.xml
@@ -0,0 +1,24 @@
+<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>
+  <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..6fe9ff6
--- /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/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..6ff3b35
--- /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/kvm</emulator>
+    <memballoon model='virtio'/>
+  </devices>
+</domain>
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
index d40b37e..63221ab 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, QEMU_CAPS_ENABLE_KVM);
+    DO_TEST("cpu-host-kvmclock", false, QEMU_CAPS_ENABLE_KVM, QEMU_CAPS_CPU_HOST);
+    DO_TEST("kvmclock", false, QEMU_CAPS_KVM);
 
     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 df317fd..09628d8 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.6




More information about the libvir-list mailing list