Blob Blame History Raw
From d1026b0bd63883eb1d992963559ef645f634c8fa Mon Sep 17 00:00:00 2001
Message-Id: <d1026b0bd63883eb1d992963559ef645f634c8fa.1383922567.git.jdenemar@redhat.com>
From: Peter Krempa <pkrempa@redhat.com>
Date: Fri, 8 Nov 2013 12:33:34 +0100
Subject: [PATCH] qemu: Add support for paravirtual spinlocks in the guest

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
(cherry picked from commit e0dc851164d57f26ec10ceed022fe913f76ba24c)

    Conflicts:
    tests/qemuxml2argvdata/qemuxml2argv-pv-spinlock-enabled.args:
    tests/qemuxml2argvdata/qemuxml2argv-pv-spinlock-disabled.args:
           commit a216e6487255d not backported

Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
---
 docs/formatdomain.html.in                          |  8 +++++
 docs/schemas/domaincommon.rng                      | 10 +++++-
 src/conf/domain_conf.c                             | 36 +++++++++++++++++++++-
 src/conf/domain_conf.h                             |  1 +
 src/qemu/qemu_command.c                            | 13 ++++++++
 .../qemuxml2argv-pv-spinlock-disabled.args         |  5 +++
 .../qemuxml2argv-pv-spinlock-disabled.xml          | 26 ++++++++++++++++
 .../qemuxml2argv-pv-spinlock-enabled.args          |  5 +++
 .../qemuxml2argv-pv-spinlock-enabled.xml           | 26 ++++++++++++++++
 tests/qemuxml2argvtest.c                           |  2 ++
 tests/qemuxml2xmltest.c                            |  2 ++
 11 files changed, 132 insertions(+), 2 deletions(-)
 create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pv-spinlock-disabled.args
 create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pv-spinlock-disabled.xml
 create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pv-spinlock-enabled.args
 create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pv-spinlock-enabled.xml

diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index 132c16c..913c011 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -1191,6 +1191,7 @@
       &lt;vapic state='on'/&gt;
       &lt;spinlocks state='on' retries='4096'&lt;/spinlocks&gt;
     &lt;/hyperv&gt;
+    &lt;pvspinlock/&gt;
 
   &lt;/features&gt;
   ...</pre>
@@ -1262,6 +1263,13 @@
         </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>
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index 9563893..4e61d7c 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -3510,7 +3510,7 @@
   </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>
@@ -3556,6 +3556,14 @@
               <empty/>
             </element>
           </optional>
+          <optional>
+            <element name="pvspinlock">
+              <optional>
+                <ref name="featurestate"/>
+              </optional>
+              <empty/>
+            </element>
+          </optional>
         </interleave>
       </element>
     </optional>
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 6664c2a..57a82b6 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -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",
@@ -11343,6 +11344,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;
         }
@@ -16706,6 +16723,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");
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 3d2b3a4..1d27ccd 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -1603,6 +1603,7 @@ enum virDomainFeature {
     VIR_DOMAIN_FEATURE_VIRIDIAN,
     VIR_DOMAIN_FEATURE_PRIVNET,
     VIR_DOMAIN_FEATURE_HYPERV,
+    VIR_DOMAIN_FEATURE_PVSPINLOCK,
 
     VIR_DOMAIN_FEATURE_LAST
 };
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index f14b0f2..0d08852 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -6574,6 +6574,19 @@ qemuBuildCpuArgStr(const 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
index 0000000..65c66ec
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-pv-spinlock-disabled.args
@@ -0,0 +1,5 @@
+LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test \
+/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
index 0000000..4820476
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-pv-spinlock-disabled.xml
@@ -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
index 0000000..dc4cbe1
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-pv-spinlock-enabled.args
@@ -0,0 +1,5 @@
+LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test \
+/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
index 0000000..ac8781b
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-pv-spinlock-enabled.xml
@@ -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>
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
index 1d964ce..2f05727 100644
--- a/tests/qemuxml2argvtest.c
+++ b/tests/qemuxml2argvtest.c
@@ -446,6 +446,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);
diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c
index 6eebc68..5a47ef8 100644
--- a/tests/qemuxml2xmltest.c
+++ b/tests/qemuxml2xmltest.c
@@ -156,6 +156,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");
-- 
1.8.4.2