diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index 9cec1a0637..82fdfd5f73 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -4736,6 +4736,9 @@
+
+
+
@@ -4924,6 +4927,18 @@
+
+
+
+
+ enabled
+ disabled
+ required
+
+
+
+
+
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index fffcc8e9da..62d0a1683a 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -148,7 +148,9 @@ VIR_ENUM_IMPL(virDomainFeature, VIR_DOMAIN_FEATURE_LAST,
"vmport",
"gic",
"smm",
- "ioapic")
+ "ioapic",
+ "hpt",
+);
VIR_ENUM_IMPL(virDomainCapabilitiesPolicy, VIR_DOMAIN_CAPABILITIES_POLICY_LAST,
"default",
@@ -882,6 +884,13 @@ VIR_ENUM_IMPL(virDomainIOAPIC,
"qemu",
"kvm")
+VIR_ENUM_IMPL(virDomainHPTResizing,
+ VIR_DOMAIN_HPT_RESIZING_LAST,
+ "enabled",
+ "disabled",
+ "required",
+);
+
/* Internal mapping: subset of block job types that can be present in
* XML (remaining types are not two-phase). */
VIR_ENUM_DECL(virDomainBlockJob)
@@ -18775,6 +18784,22 @@ virDomainDefParseXML(xmlDocPtr xml,
}
break;
+ case VIR_DOMAIN_FEATURE_HPT:
+ tmp = virXMLPropString(nodes[i], "resizing");
+ if (tmp) {
+ int value = virDomainHPTResizingTypeFromString(tmp);
+ if (value < 0) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("Unknown HPT resizing setting: %s"),
+ tmp);
+ goto error;
+ }
+ def->hpt_resizing = value;
+ def->features[val] = VIR_TRISTATE_SWITCH_ON;
+ VIR_FREE(tmp);
+ }
+ break;
+
/* coverity[dead_error_begin] */
case VIR_DOMAIN_FEATURE_LAST:
break;
@@ -20965,6 +20990,18 @@ virDomainDefFeaturesCheckABIStability(virDomainDefPtr src,
return false;
}
+ /* HPT resizing */
+ if (src->features[VIR_DOMAIN_FEATURE_HPT] == VIR_TRISTATE_SWITCH_ON) {
+ if (src->hpt_resizing != dst->hpt_resizing) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("HPT resizing configuration differs: "
+ "source: '%s', destination: '%s'"),
+ virDomainHPTResizingTypeToString(src->hpt_resizing),
+ virDomainHPTResizingTypeToString(dst->hpt_resizing));
+ return false;
+ }
+ }
+
return true;
}
@@ -26214,6 +26251,13 @@ virDomainDefFormatInternal(virDomainDefPtr def,
}
break;
+ case VIR_DOMAIN_FEATURE_HPT:
+ if (def->features[i] == VIR_TRISTATE_SWITCH_ON) {
+ virBufferAsprintf(buf, "\n",
+ virDomainHPTResizingTypeToString(def->hpt_resizing));
+ }
+ break;
+
/* coverity[dead_error_begin] */
case VIR_DOMAIN_FEATURE_LAST:
break;
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index e3f060b122..41443a02c9 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -1723,6 +1723,7 @@ typedef enum {
VIR_DOMAIN_FEATURE_GIC,
VIR_DOMAIN_FEATURE_SMM,
VIR_DOMAIN_FEATURE_IOAPIC,
+ VIR_DOMAIN_FEATURE_HPT,
VIR_DOMAIN_FEATURE_LAST
} virDomainFeature;
@@ -1851,6 +1852,16 @@ typedef enum {
VIR_ENUM_DECL(virDomainIOAPIC);
+typedef enum {
+ VIR_DOMAIN_HPT_RESIZING_ENABLED = 0,
+ VIR_DOMAIN_HPT_RESIZING_DISABLED,
+ VIR_DOMAIN_HPT_RESIZING_REQUIRED,
+
+ VIR_DOMAIN_HPT_RESIZING_LAST
+} virDomainHPTResizing;
+
+VIR_ENUM_DECL(virDomainHPTResizing);
+
/* Operating system configuration data & machine / arch */
typedef struct _virDomainOSEnv virDomainOSEnv;
typedef virDomainOSEnv *virDomainOSEnvPtr;
@@ -2323,6 +2334,7 @@ struct _virDomainDef {
virGICVersion gic_version;
char *hyperv_vendor_id;
virDomainIOAPIC ioapic;
+ virDomainHPTResizing hpt_resizing;
/* These options are of type virTristateSwitch: ON = keep, OFF = drop */
int caps_features[VIR_DOMAIN_CAPS_FEATURE_LAST];
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 5a4d50471d..a91b87d09a 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -387,6 +387,7 @@ virDomainHostdevModeTypeToString;
virDomainHostdevRemove;
virDomainHostdevSubsysPCIBackendTypeToString;
virDomainHostdevSubsysTypeToString;
+virDomainHPTResizingTypeToString;
virDomainHubTypeFromString;
virDomainHubTypeToString;
virDomainHypervTypeFromString;
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index 7cb091056b..1badadbc2e 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -443,6 +443,7 @@ VIR_ENUM_IMPL(virQEMUCaps, QEMU_CAPS_LAST,
/* 270 */
"vxhs",
"virtio-blk.num-queues",
+ "machine.pseries.resize-hpt",
);
@@ -4776,6 +4777,13 @@ virQEMUCapsInitQMPMonitor(virQEMUCapsPtr qemuCaps,
if (qemuCaps->version >= 2006000)
virQEMUCapsSet(qemuCaps, QEMU_CAPS_MACHINE_KERNEL_IRQCHIP_SPLIT);
+ /* HPT resizing is supported since QEMU 2.10 on ppc64; unfortunately
+ * there's no sane way to probe for it */
+ if (qemuCaps->version >= 2010000 &&
+ ARCH_IS_PPC64(qemuCaps->arch)) {
+ virQEMUCapsSet(qemuCaps, QEMU_CAPS_MACHINE_PSERIES_RESIZE_HPT);
+ }
+
if (virQEMUCapsProbeQMPCommands(qemuCaps, mon) < 0)
goto cleanup;
diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h
index cacc2b77ed..f0e2e9016f 100644
--- a/src/qemu/qemu_capabilities.h
+++ b/src/qemu/qemu_capabilities.h
@@ -429,6 +429,7 @@ typedef enum {
/* 270 */
QEMU_CAPS_VXHS, /* -drive file.driver=vxhs via query-qmp-schema */
QEMU_CAPS_VIRTIO_BLK_NUM_QUEUES, /* virtio-blk-*.num-queues */
+ QEMU_CAPS_MACHINE_PSERIES_RESIZE_HPT, /* -machine pseries,resize-hpt */
QEMU_CAPS_LAST /* this must always be the last item */
} virQEMUCapsFlags;
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index eb72db33ba..56729e4981 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -7489,6 +7489,26 @@ qemuBuildMachineCommandLine(virCommandPtr cmd,
}
}
+ if (def->features[VIR_DOMAIN_FEATURE_HPT] == VIR_TRISTATE_SWITCH_ON) {
+ const char *str;
+
+ if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_MACHINE_PSERIES_RESIZE_HPT)) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("HTP resizing is not supported by this "
+ "QEMU binary"));
+ goto cleanup;
+ }
+
+ str = virDomainHPTResizingTypeToString(def->hpt_resizing);
+ if (!str) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("Invalid setting for HPT resizing"));
+ goto cleanup;
+ }
+
+ virBufferAsprintf(&buf, ",resize-hpt=%s", str);
+ }
+
if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_BOOTINDEX) &&
virQEMUCapsGet(qemuCaps, QEMU_CAPS_LOADPARM))
qemuAppendLoadparmMachineParm(&buf, def);
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index a36e157529..cc7596bad1 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -3144,6 +3144,14 @@ qemuDomainDefVerifyFeatures(const virDomainDef *def)
return -1;
}
+ if (def->features[VIR_DOMAIN_FEATURE_HPT] == VIR_TRISTATE_SWITCH_ON &&
+ !qemuDomainIsPSeries(def)) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ "%s",
+ _("HPT tuning is only supported for pSeries guests"));
+ return -1;
+ }
+
return 0;
}
diff --git a/tests/qemucapabilitiesdata/caps_2.10.0.ppc64.xml b/tests/qemucapabilitiesdata/caps_2.10.0.ppc64.xml
index 0dfa20726c..b0ee3f1523 100644
--- a/tests/qemucapabilitiesdata/caps_2.10.0.ppc64.xml
+++ b/tests/qemucapabilitiesdata/caps_2.10.0.ppc64.xml
@@ -177,6 +177,7 @@
+
2010000
0
(v2.10.0)