c1c534
From 6d24efd64d6de00d29f8bf2329940c427f5cc6f9 Mon Sep 17 00:00:00 2001
c1c534
Message-Id: <6d24efd64d6de00d29f8bf2329940c427f5cc6f9@dist-git>
c1c534
From: Andrea Bolognani <abologna@redhat.com>
c1c534
Date: Wed, 15 Nov 2017 10:28:54 +0100
c1c534
Subject: [PATCH] qemu: Enable configuration of HPT resizing for pSeries guests
c1c534
c1c534
Most of the time it's okay to leave this up to negotiation between
c1c534
the guest and the host, but in some situations it can be useful to
c1c534
manually decide the behavior, especially to enforce its availability.
c1c534
c1c534
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1308743
c1c534
c1c534
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
c1c534
Reviewed-by: John Ferlan <jferlan@redhat.com>
c1c534
(cherry picked from commit 85b2ae96dfcf7dc324d6782f64c848fa412443e4)
c1c534
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
c1c534
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
c1c534
---
c1c534
 docs/schemas/domaincommon.rng                    | 15 ++++++++
c1c534
 src/conf/domain_conf.c                           | 46 +++++++++++++++++++++++-
c1c534
 src/conf/domain_conf.h                           | 12 +++++++
c1c534
 src/libvirt_private.syms                         |  1 +
c1c534
 src/qemu/qemu_capabilities.c                     |  8 +++++
c1c534
 src/qemu/qemu_capabilities.h                     |  1 +
c1c534
 src/qemu/qemu_command.c                          | 20 +++++++++++
c1c534
 src/qemu/qemu_domain.c                           |  8 +++++
c1c534
 tests/qemucapabilitiesdata/caps_2.10.0.ppc64.xml |  1 +
c1c534
 9 files changed, 111 insertions(+), 1 deletion(-)
c1c534
c1c534
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
c1c534
index 710b3af7f7..367861c1ea 100644
c1c534
--- a/docs/schemas/domaincommon.rng
c1c534
+++ b/docs/schemas/domaincommon.rng
c1c534
@@ -4722,6 +4722,9 @@
c1c534
           <optional>
c1c534
             <ref name="ioapic"/>
c1c534
           </optional>
c1c534
+          <optional>
c1c534
+            <ref name="hpt"/>
c1c534
+          </optional>
c1c534
         </interleave>
c1c534
       </element>
c1c534
     </optional>
c1c534
@@ -4910,6 +4913,18 @@
c1c534
     </element>
c1c534
   </define>
c1c534
 
c1c534
+  <define name="hpt">
c1c534
+    <element name="hpt">
c1c534
+      <attribute name="resizing">
c1c534
+        <choice>
c1c534
+          <value>enabled</value>
c1c534
+          <value>disabled</value>
c1c534
+          <value>required</value>
c1c534
+        </choice>
c1c534
+      </attribute>
c1c534
+    </element>
c1c534
+  </define>
c1c534
+
c1c534
   <define name="address">
c1c534
     <element name="address">
c1c534
       <choice>
c1c534
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
c1c534
index ca5d0bcc54..641a978f07 100644
c1c534
--- a/src/conf/domain_conf.c
c1c534
+++ b/src/conf/domain_conf.c
c1c534
@@ -148,7 +148,9 @@ VIR_ENUM_IMPL(virDomainFeature, VIR_DOMAIN_FEATURE_LAST,
c1c534
               "vmport",
c1c534
               "gic",
c1c534
               "smm",
c1c534
-              "ioapic")
c1c534
+              "ioapic",
c1c534
+              "hpt",
c1c534
+);
c1c534
 
c1c534
 VIR_ENUM_IMPL(virDomainCapabilitiesPolicy, VIR_DOMAIN_CAPABILITIES_POLICY_LAST,
c1c534
               "default",
c1c534
@@ -877,6 +879,13 @@ VIR_ENUM_IMPL(virDomainIOAPIC,
c1c534
               "qemu",
c1c534
               "kvm")
c1c534
 
c1c534
+VIR_ENUM_IMPL(virDomainHPTResizing,
c1c534
+              VIR_DOMAIN_HPT_RESIZING_LAST,
c1c534
+              "enabled",
c1c534
+              "disabled",
c1c534
+              "required",
c1c534
+);
c1c534
+
c1c534
 /* Internal mapping: subset of block job types that can be present in
c1c534
  * <mirror> XML (remaining types are not two-phase). */
c1c534
 VIR_ENUM_DECL(virDomainBlockJob)
c1c534
@@ -18765,6 +18774,22 @@ virDomainDefParseXML(xmlDocPtr xml,
c1c534
             }
c1c534
             break;
c1c534
 
c1c534
+        case VIR_DOMAIN_FEATURE_HPT:
c1c534
+            tmp = virXMLPropString(nodes[i], "resizing");
c1c534
+            if (tmp) {
c1c534
+                int value = virDomainHPTResizingTypeFromString(tmp);
c1c534
+                if (value < 0) {
c1c534
+                    virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
c1c534
+                                   _("Unknown HPT resizing setting: %s"),
c1c534
+                                   tmp);
c1c534
+                    goto error;
c1c534
+                }
c1c534
+                def->hpt_resizing = value;
c1c534
+                def->features[val] = VIR_TRISTATE_SWITCH_ON;
c1c534
+                VIR_FREE(tmp);
c1c534
+            }
c1c534
+            break;
c1c534
+
c1c534
         /* coverity[dead_error_begin] */
c1c534
         case VIR_DOMAIN_FEATURE_LAST:
c1c534
             break;
c1c534
@@ -20955,6 +20980,18 @@ virDomainDefFeaturesCheckABIStability(virDomainDefPtr src,
c1c534
         return false;
c1c534
     }
c1c534
 
c1c534
+    /* HPT resizing */
c1c534
+    if (src->features[VIR_DOMAIN_FEATURE_HPT] == VIR_TRISTATE_SWITCH_ON) {
c1c534
+        if (src->hpt_resizing != dst->hpt_resizing) {
c1c534
+            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
c1c534
+                           _("HPT resizing configuration differs: "
c1c534
+                             "source: '%s', destination: '%s'"),
c1c534
+                           virDomainHPTResizingTypeToString(src->hpt_resizing),
c1c534
+                           virDomainHPTResizingTypeToString(dst->hpt_resizing));
c1c534
+            return false;
c1c534
+        }
c1c534
+    }
c1c534
+
c1c534
     return true;
c1c534
 }
c1c534
 
c1c534
@@ -26204,6 +26241,13 @@ virDomainDefFormatInternal(virDomainDefPtr def,
c1c534
                 }
c1c534
                 break;
c1c534
 
c1c534
+            case VIR_DOMAIN_FEATURE_HPT:
c1c534
+                if (def->features[i] == VIR_TRISTATE_SWITCH_ON) {
c1c534
+                    virBufferAsprintf(buf, "<hpt resizing='%s'/>\n",
c1c534
+                                      virDomainHPTResizingTypeToString(def->hpt_resizing));
c1c534
+                }
c1c534
+                break;
c1c534
+
c1c534
             /* coverity[dead_error_begin] */
c1c534
             case VIR_DOMAIN_FEATURE_LAST:
c1c534
                 break;
c1c534
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
c1c534
index 388fa92dda..f967e603d1 100644
c1c534
--- a/src/conf/domain_conf.h
c1c534
+++ b/src/conf/domain_conf.h
c1c534
@@ -1715,6 +1715,7 @@ typedef enum {
c1c534
     VIR_DOMAIN_FEATURE_GIC,
c1c534
     VIR_DOMAIN_FEATURE_SMM,
c1c534
     VIR_DOMAIN_FEATURE_IOAPIC,
c1c534
+    VIR_DOMAIN_FEATURE_HPT,
c1c534
 
c1c534
     VIR_DOMAIN_FEATURE_LAST
c1c534
 } virDomainFeature;
c1c534
@@ -1843,6 +1844,16 @@ typedef enum {
c1c534
 
c1c534
 VIR_ENUM_DECL(virDomainIOAPIC);
c1c534
 
c1c534
+typedef enum {
c1c534
+    VIR_DOMAIN_HPT_RESIZING_ENABLED = 0,
c1c534
+    VIR_DOMAIN_HPT_RESIZING_DISABLED,
c1c534
+    VIR_DOMAIN_HPT_RESIZING_REQUIRED,
c1c534
+
c1c534
+    VIR_DOMAIN_HPT_RESIZING_LAST
c1c534
+} virDomainHPTResizing;
c1c534
+
c1c534
+VIR_ENUM_DECL(virDomainHPTResizing);
c1c534
+
c1c534
 /* Operating system configuration data & machine / arch */
c1c534
 typedef struct _virDomainOSEnv virDomainOSEnv;
c1c534
 typedef virDomainOSEnv *virDomainOSEnvPtr;
c1c534
@@ -2315,6 +2326,7 @@ struct _virDomainDef {
c1c534
     virGICVersion gic_version;
c1c534
     char *hyperv_vendor_id;
c1c534
     virDomainIOAPIC ioapic;
c1c534
+    virDomainHPTResizing hpt_resizing;
c1c534
 
c1c534
     /* These options are of type virTristateSwitch: ON = keep, OFF = drop */
c1c534
     int caps_features[VIR_DOMAIN_CAPS_FEATURE_LAST];
c1c534
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
c1c534
index 6653f95722..8d1d4a896b 100644
c1c534
--- a/src/libvirt_private.syms
c1c534
+++ b/src/libvirt_private.syms
c1c534
@@ -385,6 +385,7 @@ virDomainHostdevModeTypeToString;
c1c534
 virDomainHostdevRemove;
c1c534
 virDomainHostdevSubsysPCIBackendTypeToString;
c1c534
 virDomainHostdevSubsysTypeToString;
c1c534
+virDomainHPTResizingTypeToString;
c1c534
 virDomainHubTypeFromString;
c1c534
 virDomainHubTypeToString;
c1c534
 virDomainHypervTypeFromString;
c1c534
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
c1c534
index 37a58b3640..3793f16590 100644
c1c534
--- a/src/qemu/qemu_capabilities.c
c1c534
+++ b/src/qemu/qemu_capabilities.c
c1c534
@@ -443,6 +443,7 @@ VIR_ENUM_IMPL(virQEMUCaps, QEMU_CAPS_LAST,
c1c534
               /* 270 */
c1c534
               "vxhs",
c1c534
               "virtio-blk.num-queues",
c1c534
+              "machine.pseries.resize-hpt",
c1c534
     );
c1c534
 
c1c534
 
c1c534
@@ -4780,6 +4781,13 @@ virQEMUCapsInitQMPMonitor(virQEMUCapsPtr qemuCaps,
c1c534
     if (qemuCaps->version >= 2006000)
c1c534
         virQEMUCapsSet(qemuCaps, QEMU_CAPS_MACHINE_KERNEL_IRQCHIP_SPLIT);
c1c534
 
c1c534
+    /* HPT resizing is supported since QEMU 2.10 on ppc64; unfortunately
c1c534
+     * there's no sane way to probe for it */
c1c534
+    if (qemuCaps->version >= 2010000 &&
c1c534
+        ARCH_IS_PPC64(qemuCaps->arch)) {
c1c534
+        virQEMUCapsSet(qemuCaps, QEMU_CAPS_MACHINE_PSERIES_RESIZE_HPT);
c1c534
+    }
c1c534
+
c1c534
     if (virQEMUCapsProbeQMPCommands(qemuCaps, mon) < 0)
c1c534
         goto cleanup;
c1c534
 
c1c534
diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h
c1c534
index cacc2b77ed..f0e2e9016f 100644
c1c534
--- a/src/qemu/qemu_capabilities.h
c1c534
+++ b/src/qemu/qemu_capabilities.h
c1c534
@@ -429,6 +429,7 @@ typedef enum {
c1c534
     /* 270 */
c1c534
     QEMU_CAPS_VXHS, /* -drive file.driver=vxhs via query-qmp-schema */
c1c534
     QEMU_CAPS_VIRTIO_BLK_NUM_QUEUES, /* virtio-blk-*.num-queues */
c1c534
+    QEMU_CAPS_MACHINE_PSERIES_RESIZE_HPT, /* -machine pseries,resize-hpt */
c1c534
 
c1c534
     QEMU_CAPS_LAST /* this must always be the last item */
c1c534
 } virQEMUCapsFlags;
c1c534
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
c1c534
index e60f93083f..aa7079229f 100644
c1c534
--- a/src/qemu/qemu_command.c
c1c534
+++ b/src/qemu/qemu_command.c
c1c534
@@ -7566,6 +7566,26 @@ qemuBuildMachineCommandLine(virCommandPtr cmd,
c1c534
             }
c1c534
         }
c1c534
 
c1c534
+        if (def->features[VIR_DOMAIN_FEATURE_HPT] == VIR_TRISTATE_SWITCH_ON) {
c1c534
+            const char *str;
c1c534
+
c1c534
+            if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_MACHINE_PSERIES_RESIZE_HPT)) {
c1c534
+                virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
c1c534
+                               _("HTP resizing is not supported by this "
c1c534
+                                 "QEMU binary"));
c1c534
+                goto cleanup;
c1c534
+            }
c1c534
+
c1c534
+            str = virDomainHPTResizingTypeToString(def->hpt_resizing);
c1c534
+            if (!str) {
c1c534
+                virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
c1c534
+                               _("Invalid setting for HPT resizing"));
c1c534
+                goto cleanup;
c1c534
+            }
c1c534
+
c1c534
+            virBufferAsprintf(&buf, ",resize-hpt=%s", str);
c1c534
+        }
c1c534
+
c1c534
         if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_BOOTINDEX) &&
c1c534
             virQEMUCapsGet(qemuCaps, QEMU_CAPS_LOADPARM))
c1c534
             qemuAppendLoadparmMachineParm(&buf, def);
c1c534
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
c1c534
index 81f45516af..485e085cea 100644
c1c534
--- a/src/qemu/qemu_domain.c
c1c534
+++ b/src/qemu/qemu_domain.c
c1c534
@@ -3109,6 +3109,14 @@ qemuDomainDefVerifyFeatures(const virDomainDef *def)
c1c534
         return -1;
c1c534
     }
c1c534
 
c1c534
+    if (def->features[VIR_DOMAIN_FEATURE_HPT] == VIR_TRISTATE_SWITCH_ON &&
c1c534
+        !qemuDomainIsPSeries(def)) {
c1c534
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
c1c534
+                       "%s",
c1c534
+                       _("HPT tuning is only supported for pSeries guests"));
c1c534
+        return -1;
c1c534
+    }
c1c534
+
c1c534
     return 0;
c1c534
 }
c1c534
 
c1c534
diff --git a/tests/qemucapabilitiesdata/caps_2.10.0.ppc64.xml b/tests/qemucapabilitiesdata/caps_2.10.0.ppc64.xml
c1c534
index 0dfa20726c..b0ee3f1523 100644
c1c534
--- a/tests/qemucapabilitiesdata/caps_2.10.0.ppc64.xml
c1c534
+++ b/tests/qemucapabilitiesdata/caps_2.10.0.ppc64.xml
c1c534
@@ -177,6 +177,7 @@
c1c534
   <flag name='virtio-gpu.max_outputs'/>
c1c534
   <flag name='vxhs'/>
c1c534
   <flag name='virtio-blk.num-queues'/>
c1c534
+  <flag name='machine.pseries.resize-hpt'/>
c1c534
   <version>2010000</version>
c1c534
   <kvmVersion>0</kvmVersion>
c1c534
   <package> (v2.10.0)</package>
c1c534
-- 
c1c534
2.15.0
c1c534