]> xenbits.xensource.com Git - libvirt.git/commitdiff
qemu: Add support for paravirtual spinlocks in the guest
authorPeter Krempa <pkrempa@redhat.com>
Mon, 23 Sep 2013 16:32:11 +0000 (18:32 +0200)
committerPeter Krempa <pkrempa@redhat.com>
Fri, 8 Nov 2013 08:44:42 +0000 (09:44 +0100)
The linux kernel recently added support for paravirtual spinlock
handling to avoid performance regressions on overcomitted hosts. This
feature needs to be turned in the hypervisor so that the guest OS is
notified about the possible support.

This patch adds a new feature "paravirt-spinlock" to the XML and
supporting code to enable the "kvm_pv_unhalt" pseudo CPU feature in
qemu.

https://bugzilla.redhat.com/show_bug.cgi?id=1008989

docs/formatdomain.html.in
docs/schemas/domaincommon.rng
src/conf/domain_conf.c
src/conf/domain_conf.h
src/qemu/qemu_command.c
tests/qemuxml2argvdata/qemuxml2argv-pv-spinlock-disabled.args [new file with mode: 0644]
tests/qemuxml2argvdata/qemuxml2argv-pv-spinlock-disabled.xml [new file with mode: 0644]
tests/qemuxml2argvdata/qemuxml2argv-pv-spinlock-enabled.args [new file with mode: 0644]
tests/qemuxml2argvdata/qemuxml2argv-pv-spinlock-enabled.xml [new file with mode: 0644]
tests/qemuxml2argvtest.c
tests/qemuxml2xmltest.c

index aa9070107b0ebb8995138da942979734f0aba21d..096e2a3f339daed911ae108e887f4ba4b7b7e0e5 100644 (file)
       &lt;vapic state='on'/&gt;
       &lt;spinlocks state='on' retries='4096'/&gt;
     &lt;/hyperv&gt;
+    &lt;pvspinlock/&gt;
 
   &lt;/features&gt;
   ...</pre>
         </tr>
       </table>
       </dd>
+      <dt><code>pvspinlock</code></dt>
+      <dd>Notify the guest that the host supports paravirtual spinlocks
+          for example by exposing the pvticketlocks mechanism. This feature
+          can be explicitly disabled by using <code>state='off'</code>
+          attribute.
+      </dd>
+
     </dl>
 
     <h3><a name="elementsTime">Time keeping</a></h3>
index 1f301618379ebc56ef942a69ddf89c865b1307e6..80848d2054a11fb245951844cebc09d0fa87ec66 100644 (file)
   </define>
   <!--
       A set of optional features: PAE, APIC, ACPI,
-      HyperV Enlightenment and HAP support
+      HyperV Enlightenment, paravirtual spinlocks  and HAP support
     -->
   <define name="features">
     <optional>
               <empty/>
             </element>
           </optional>
+          <optional>
+            <element name="pvspinlock">
+              <optional>
+                <ref name="featurestate"/>
+              </optional>
+              <empty/>
+            </element>
+          </optional>
         </interleave>
       </element>
     </optional>
index d23e72410bc7b0d8b5677c223a1d5f5b56eeb22e..c1e0ea736a0056d3c7f69d4b5f6bdfd4224ca535 100644 (file)
@@ -142,7 +142,8 @@ VIR_ENUM_IMPL(virDomainFeature, VIR_DOMAIN_FEATURE_LAST,
               "hap",
               "viridian",
               "privnet",
-              "hyperv")
+              "hyperv",
+              "pvspinlock")
 
 VIR_ENUM_IMPL(virDomainFeatureState, VIR_DOMAIN_FEATURE_STATE_LAST,
               "default",
@@ -11440,6 +11441,22 @@ virDomainDefParseXML(xmlDocPtr xml,
             def->features[val] = VIR_DOMAIN_FEATURE_STATE_ON;
             break;
 
+        case VIR_DOMAIN_FEATURE_PVSPINLOCK:
+            node = ctxt->node;
+            ctxt->node = nodes[i];
+            if ((tmp = virXPathString("string(./@state)", ctxt))) {
+                if ((def->features[val] = virDomainFeatureStateTypeFromString(tmp)) == -1) {
+                    virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                                   _("unknown state atribute '%s' of feature '%s'"),
+                                   tmp, virDomainFeatureTypeToString(val));
+                    goto error;
+                }
+            } else {
+                def->features[val] = VIR_DOMAIN_FEATURE_STATE_ON;
+            }
+            ctxt->node = node;
+            break;
+
         case VIR_DOMAIN_FEATURE_LAST:
             break;
         }
@@ -16807,6 +16824,23 @@ virDomainDefFormatInternal(virDomainDefPtr def,
 
                 break;
 
+            case VIR_DOMAIN_FEATURE_PVSPINLOCK:
+                switch ((enum virDomainFeatureState) def->features[i]) {
+                case VIR_DOMAIN_FEATURE_STATE_LAST:
+                case VIR_DOMAIN_FEATURE_STATE_DEFAULT:
+                    break;
+
+                case VIR_DOMAIN_FEATURE_STATE_ON:
+                   virBufferAsprintf(buf, "    <%s state='on'/>\n", name);
+                   break;
+
+                case VIR_DOMAIN_FEATURE_STATE_OFF:
+                   virBufferAsprintf(buf, "    <%s state='off'/>\n", name);
+                   break;
+                }
+
+                break;
+
             case VIR_DOMAIN_FEATURE_APIC:
                 if (def->features[i] == VIR_DOMAIN_FEATURE_STATE_ON) {
                     virBufferAddLit(buf, "    <apic");
index ffd7e9d97f2513727cf5f904ca4699a70fb0e38a..05c2a84d306ac44f2b64423c0dfe7fbb0e1071c9 100644 (file)
@@ -1619,6 +1619,7 @@ enum virDomainFeature {
     VIR_DOMAIN_FEATURE_VIRIDIAN,
     VIR_DOMAIN_FEATURE_PRIVNET,
     VIR_DOMAIN_FEATURE_HYPERV,
+    VIR_DOMAIN_FEATURE_PVSPINLOCK,
 
     VIR_DOMAIN_FEATURE_LAST
 };
index f34f716cc240e45b4da06fbde59ef16c82c2354f..e8742f5c88a4ce40d409da3cbbbf06855ce8f1b4 100644 (file)
@@ -6718,6 +6718,19 @@ qemuBuildCpuArgStr(virQEMUDriverPtr driver,
         have_cpu = true;
     }
 
+    if (def->features[VIR_DOMAIN_FEATURE_PVSPINLOCK]) {
+        char sign;
+        if (def->features[VIR_DOMAIN_FEATURE_PVSPINLOCK] == VIR_DOMAIN_FEATURE_STATE_ON)
+            sign = '+';
+        else
+            sign = '-';
+
+        virBufferAsprintf(&buf, "%s,%ckvm_pv_unhalt",
+                          have_cpu ? "" : default_model,
+                          sign);
+        have_cpu = true;
+    }
+
     if (def->features[VIR_DOMAIN_FEATURE_HYPERV] == VIR_DOMAIN_FEATURE_STATE_ON) {
         if (!have_cpu) {
             virBufferAdd(&buf, default_model, -1);
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-pv-spinlock-disabled.args b/tests/qemuxml2argvdata/qemuxml2argv-pv-spinlock-disabled.args
new file mode 100644 (file)
index 0000000..80047f9
--- /dev/null
@@ -0,0 +1,5 @@
+LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test QEMU_AUDIO_DRV=none \
+/usr/bin/qemu -S -M pc \
+-cpu qemu32,-kvm_pv_unhalt -m 214 -smp 6 -nographic -monitor \
+unix:/tmp/test-monitor,server,nowait -boot n -usb -net none -serial \
+none -parallel none
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-pv-spinlock-disabled.xml b/tests/qemuxml2argvdata/qemuxml2argv-pv-spinlock-disabled.xml
new file mode 100644 (file)
index 0000000..4820476
--- /dev/null
@@ -0,0 +1,26 @@
+<domain type='qemu'>
+  <name>QEMUGuest1</name>
+  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+  <memory unit='KiB'>219100</memory>
+  <currentMemory unit='KiB'>219100</currentMemory>
+  <vcpu placement='static'>6</vcpu>
+  <os>
+    <type arch='i686' machine='pc'>hvm</type>
+    <boot dev='network'/>
+  </os>
+  <features>
+    <acpi/>
+    <pae/>
+    <pvspinlock state='off'/>
+  </features>
+  <clock offset='utc'/>
+  <on_poweroff>destroy</on_poweroff>
+  <on_reboot>restart</on_reboot>
+  <on_crash>destroy</on_crash>
+  <devices>
+    <emulator>/usr/bin/qemu</emulator>
+    <controller type='usb' index='0'/>
+    <controller type='pci' index='0' model='pci-root'/>
+    <memballoon model='virtio'/>
+  </devices>
+</domain>
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-pv-spinlock-enabled.args b/tests/qemuxml2argvdata/qemuxml2argv-pv-spinlock-enabled.args
new file mode 100644 (file)
index 0000000..70db173
--- /dev/null
@@ -0,0 +1,5 @@
+LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test QEMU_AUDIO_DRV=none \
+/usr/bin/qemu -S -M pc \
+-cpu qemu32,+kvm_pv_unhalt -m 214 -smp 6 -nographic -monitor \
+unix:/tmp/test-monitor,server,nowait -boot n -usb -net none -serial \
+none -parallel none
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-pv-spinlock-enabled.xml b/tests/qemuxml2argvdata/qemuxml2argv-pv-spinlock-enabled.xml
new file mode 100644 (file)
index 0000000..ac8781b
--- /dev/null
@@ -0,0 +1,26 @@
+<domain type='qemu'>
+  <name>QEMUGuest1</name>
+  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+  <memory unit='KiB'>219100</memory>
+  <currentMemory unit='KiB'>219100</currentMemory>
+  <vcpu placement='static'>6</vcpu>
+  <os>
+    <type arch='i686' machine='pc'>hvm</type>
+    <boot dev='network'/>
+  </os>
+  <features>
+    <acpi/>
+    <pae/>
+    <pvspinlock state='on'/>
+  </features>
+  <clock offset='utc'/>
+  <on_poweroff>destroy</on_poweroff>
+  <on_reboot>restart</on_reboot>
+  <on_crash>destroy</on_crash>
+  <devices>
+    <emulator>/usr/bin/qemu</emulator>
+    <controller type='usb' index='0'/>
+    <controller type='pci' index='0' model='pci-root'/>
+    <memballoon model='virtio'/>
+  </devices>
+</domain>
index a74ac2a597e47c4294bfc28d9d1f96246a800884..0629e310efc9124926886b52ce51957f620ae2a0 100644 (file)
@@ -448,6 +448,8 @@ mymain(void)
             QEMU_CAPS_CHARDEV_SPICEVMC, QEMU_CAPS_SPICE, QEMU_CAPS_HDA_DUPLEX);
     DO_TEST("eoi-disabled", NONE);
     DO_TEST("eoi-enabled", NONE);
+    DO_TEST("pv-spinlock-disabled", NONE);
+    DO_TEST("pv-spinlock-enabled", NONE);
     DO_TEST("kvmclock+eoi-disabled", QEMU_CAPS_ENABLE_KVM);
 
     DO_TEST("hyperv", NONE);
index 4e308b406b2572219ff6db22175293312080050e..ffff3b556903d8f9dbf9fda26e084e45aec9d14f 100644 (file)
@@ -159,6 +159,8 @@ mymain(void)
     DO_TEST("cpu-eoi-enabled");
     DO_TEST("eoi-disabled");
     DO_TEST("eoi-enabled");
+    DO_TEST("pv-spinlock-disabled");
+    DO_TEST("pv-spinlock-enabled");
 
     DO_TEST("hyperv");
     DO_TEST("hyperv-off");