Introduce a way to enable and disable the availability of
HTM (Hardware Transactional Memory) for pSeries guests.
Signed-off-by: Andrea Bolognani <abologna(a)redhat.com>
---
The availability of the corresponding QEMU toggle is currently
crudely inferred from the version number, but there's ongoing
discussion on how to introspect it properly through QMP, hence
the RFC status of this patch.
docs/formatdomain.html.in | 7 ++++
docs/schemas/domaincommon.rng | 5 +++
src/conf/domain_conf.c | 44 +++++++++++++++++++++++
src/conf/domain_conf.h | 1 +
src/qemu/qemu_capabilities.c | 9 +++++
src/qemu/qemu_capabilities.h | 1 +
src/qemu/qemu_command.c | 13 +++++++
tests/qemuxml2argvdata/pseries-features-htm.args | 19 ++++++++++
tests/qemuxml2argvdata/pseries-features-htm.xml | 30 ++++++++++++++++
tests/qemuxml2argvtest.c | 3 ++
tests/qemuxml2xmloutdata/pseries-features-htm.xml | 1 +
tests/qemuxml2xmltest.c | 3 ++
12 files changed, 136 insertions(+)
create mode 100644 tests/qemuxml2argvdata/pseries-features-htm.args
create mode 100644 tests/qemuxml2argvdata/pseries-features-htm.xml
create mode 120000 tests/qemuxml2xmloutdata/pseries-features-htm.xml
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index 1e2fccaeb..22b0739ac 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -1770,6 +1770,7 @@
</kvm>
<pseries>
<hpt resizing='required'/>
+ <htm state='off'/>
</pseries>
<pvspinlock state='on'/>
<gic version='2'/>
@@ -1921,6 +1922,12 @@
<td>resizing: enabled, disabled, required</td>
<td><span class="since">4.1.0 (QEMU
2.10)</span></td>
</tr>
+ <tr>
+ <td>htm</td>
+ <td>Configure HTM (Hardware Transactional Memory)</td>
+ <td>state: on, off</td>
+ <td><span class="since">4.1.0 (QEMU
2.12)</span></td>
+ </tr>
</table>
</dd>
<dt><code>pmu</code></dt>
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index fead6e7cc..b49318aa3 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -5538,6 +5538,11 @@
<ref name="resizing"/>
</element>
</optional>
+ <optional>
+ <element name="htm">
+ <ref name="featurestate"/>
+ </element>
+ </optional>
</interleave>
</element>
</define>
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 763228ca7..34ef08e21 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -176,6 +176,7 @@ VIR_ENUM_IMPL(virDomainKVM, VIR_DOMAIN_KVM_LAST,
VIR_ENUM_IMPL(virDomainPSeries,
VIR_DOMAIN_PSERIES_LAST,
"hpt",
+ "htm",
);
VIR_ENUM_IMPL(virDomainCapsFeature, VIR_DOMAIN_CAPS_FEATURE_LAST,
@@ -19175,6 +19176,28 @@ virDomainDefParseXML(xmlDocPtr xml,
VIR_FREE(tmp);
break;
+ case VIR_DOMAIN_PSERIES_HTM:
+ if (!(tmp = virXMLPropString(nodes[i], "state"))) {
+ virReportError(VIR_ERR_XML_ERROR,
+ _("Missing 'state' attribute for "
+ "'%s' pSeries feature"),
+ nodes[i]->name);
+ goto error;
+ }
+
+ if ((value = virTristateSwitchTypeFromString(tmp)) < 0) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("Invalid value '%s' for 'state'
"
+ "attribute of '%s' pSeries
feature"),
+ nodes[i]->name, tmp);
+ goto error;
+ }
+
+ def->pseries_features[feature] = value;
+
+ VIR_FREE(tmp);
+ break;
+
case VIR_DOMAIN_PSERIES_LAST:
break;
}
@@ -21225,6 +21248,18 @@ virDomainDefFeaturesCheckABIStability(virDomainDefPtr src,
}
break;
+ case VIR_DOMAIN_PSERIES_HTM:
+ if (src->pseries_features[i] != dst->pseries_features[i]) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("State of '%s' pSeries feature differs:
"
+ "source: '%s', destination:
'%s'"),
+ virDomainPSeriesTypeToString(i),
+
virTristateSwitchTypeToString(src->pseries_features[i]),
+
virTristateSwitchTypeToString(dst->pseries_features[i]));
+ return false;
+ }
+ break;
+
case VIR_DOMAIN_PSERIES_LAST:
break;
}
@@ -26618,6 +26653,15 @@ virDomainDefFormatInternal(virDomainDefPtr def,
virDomainHPTResizingTypeToString(def->pseries_hpt_resizing));
break;
+ case VIR_DOMAIN_PSERIES_HTM:
+ if (def->pseries_features[j] == VIR_TRISTATE_SWITCH_ABSENT)
+ break;
+
+ virBufferAsprintf(buf, "<%s
state='%s'/>\n",
+ virDomainPSeriesTypeToString(j),
+
virTristateSwitchTypeToString(def->pseries_features[j]));
+ break;
+
case VIR_DOMAIN_PSERIES_LAST:
break;
}
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 91db2220a..3c1a61c8e 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -1768,6 +1768,7 @@ typedef enum {
typedef enum {
VIR_DOMAIN_PSERIES_HPT = 0,
+ VIR_DOMAIN_PSERIES_HTM,
VIR_DOMAIN_PSERIES_LAST
} virDomainPSeries;
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index 5e03447ba..5897b6c66 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -458,6 +458,7 @@ VIR_ENUM_IMPL(virQEMUCaps, QEMU_CAPS_LAST,
/* 280 */
"pl011",
"machine.pseries.max-cpu-compat",
+ "machine.pseries.cap-htm",
);
@@ -4894,6 +4895,14 @@ virQEMUCapsInitQMPMonitor(virQEMUCapsPtr qemuCaps,
virQEMUCapsSet(qemuCaps, QEMU_CAPS_MACHINE_PSERIES_MAX_CPU_COMPAT);
}
+ /* No way to query cap-htm availability... Yet. See
+ *
http://lists.nongnu.org/archive/html/qemu-devel/2018-01/msg04674.html
+ * for an attempt at making this introspectable through QMP */
+ if (qemuCaps->version >= 2012000 &&
+ ARCH_IS_PPC64(qemuCaps->arch)) {
+ virQEMUCapsSet(qemuCaps, QEMU_CAPS_MACHINE_PSERIES_CAP_HTM);
+ }
+
if (virQEMUCapsProbeQMPCommands(qemuCaps, mon) < 0)
goto cleanup;
diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h
index 3dfc77f87..5401a3118 100644
--- a/src/qemu/qemu_capabilities.h
+++ b/src/qemu/qemu_capabilities.h
@@ -443,6 +443,7 @@ typedef enum {
/* 280 */
QEMU_CAPS_DEVICE_PL011, /* -device pl011 (not user-instantiable) */
QEMU_CAPS_MACHINE_PSERIES_MAX_CPU_COMPAT, /* -machine pseries,max-cpu-compat= */
+ QEMU_CAPS_MACHINE_PSERIES_CAP_HTM, /* -machine pseries,cap-htm= */
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 26122b048..bb8567629 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -7366,6 +7366,8 @@ virDomainPSeriesToQEMUCaps(int feature)
switch ((virDomainPSeries) feature) {
case VIR_DOMAIN_PSERIES_HPT:
return QEMU_CAPS_MACHINE_PSERIES_RESIZE_HPT;
+ case VIR_DOMAIN_PSERIES_HTM:
+ return QEMU_CAPS_MACHINE_PSERIES_CAP_HTM;
case VIR_DOMAIN_PSERIES_LAST:
break;
}
@@ -7379,6 +7381,8 @@ virDomainPSeriesToMachineOption(int feature)
switch ((virDomainPSeries) feature) {
case VIR_DOMAIN_PSERIES_HPT:
return "resize-hpt";
+ case VIR_DOMAIN_PSERIES_HTM:
+ return "cap-htm";
case VIR_DOMAIN_PSERIES_LAST:
break;
}
@@ -7659,6 +7663,15 @@ qemuBuildMachineCommandLine(virCommandPtr cmd,
goto cleanup;
break;
+ case VIR_DOMAIN_PSERIES_HTM:
+ if (def->pseries_features[i] == VIR_TRISTATE_SWITCH_ABSENT)
+ break;
+
+ value = virTristateSwitchTypeToString(def->pseries_features[i]);
+ if (qemuBuildMachineCommandLinePSeriesFeature(&buf, i, value,
qemuCaps) < 0)
+ goto cleanup;
+ break;
+
case VIR_DOMAIN_PSERIES_LAST:
goto cleanup;
}
diff --git a/tests/qemuxml2argvdata/pseries-features-htm.args
b/tests/qemuxml2argvdata/pseries-features-htm.args
new file mode 100644
index 000000000..64fd28ed2
--- /dev/null
+++ b/tests/qemuxml2argvdata/pseries-features-htm.args
@@ -0,0 +1,19 @@
+LC_ALL=C \
+PATH=/bin \
+HOME=/home/test \
+USER=test \
+LOGNAME=test \
+QEMU_AUDIO_DRV=none \
+/usr/bin/qemu-system-ppc64 \
+-name guest \
+-S \
+-machine pseries,accel=tcg,cap-htm=on \
+-m 512 \
+-smp 1,sockets=1,cores=1,threads=1 \
+-uuid 1ccfd97d-5eb4-478a-bbe6-88d254c16db7 \
+-nographic \
+-nodefaults \
+-chardev socket,id=charmonitor,path=/tmp/lib/domain--1-guest/monitor.sock,\
+server,nowait \
+-mon chardev=charmonitor,id=monitor,mode=readline \
+-boot c
diff --git a/tests/qemuxml2argvdata/pseries-features-htm.xml
b/tests/qemuxml2argvdata/pseries-features-htm.xml
new file mode 100644
index 000000000..9e92aa91e
--- /dev/null
+++ b/tests/qemuxml2argvdata/pseries-features-htm.xml
@@ -0,0 +1,30 @@
+<domain type='qemu'>
+ <name>guest</name>
+ <uuid>1ccfd97d-5eb4-478a-bbe6-88d254c16db7</uuid>
+ <memory unit='KiB'>524288</memory>
+ <currentMemory unit='KiB'>524288</currentMemory>
+ <vcpu placement='static'>1</vcpu>
+ <os>
+ <type arch='ppc64' machine='pseries'>hvm</type>
+ <boot dev='hd'/>
+ </os>
+ <features>
+ <pseries>
+ <htm state='on'/>
+ </pseries>
+ </features>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>destroy</on_crash>
+ <devices>
+ <emulator>/usr/bin/qemu-system-ppc64</emulator>
+ <controller type='usb' index='0' model='none'/>
+ <controller type='pci' index='0' model='pci-root'>
+ <model name='spapr-pci-host-bridge'/>
+ <target index='0'/>
+ </controller>
+ <memballoon model='none'/>
+ <panic model='pseries'/>
+ </devices>
+</domain>
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
index cc9280db0..03d159e69 100644
--- a/tests/qemuxml2argvtest.c
+++ b/tests/qemuxml2argvtest.c
@@ -1899,6 +1899,9 @@ mymain(void)
DO_TEST_PARSE_ERROR("pseries-features-invalid-machine",
QEMU_CAPS_MACHINE_OPT,
QEMU_CAPS_MACHINE_PSERIES_RESIZE_HPT);
+ DO_TEST("pseries-features-htm",
+ QEMU_CAPS_MACHINE_OPT,
+ QEMU_CAPS_MACHINE_PSERIES_CAP_HTM);
DO_TEST("pseries-serial-native",
QEMU_CAPS_NODEFCONFIG,
diff --git a/tests/qemuxml2xmloutdata/pseries-features-htm.xml
b/tests/qemuxml2xmloutdata/pseries-features-htm.xml
new file mode 120000
index 000000000..42cf0f7d7
--- /dev/null
+++ b/tests/qemuxml2xmloutdata/pseries-features-htm.xml
@@ -0,0 +1 @@
+../qemuxml2argvdata/pseries-features-htm.xml
\ No newline at end of file
diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c
index ba4e853f9..e97f17740 100644
--- a/tests/qemuxml2xmltest.c
+++ b/tests/qemuxml2xmltest.c
@@ -766,6 +766,9 @@ mymain(void)
DO_TEST("pseries-features-hpt",
QEMU_CAPS_MACHINE_OPT,
QEMU_CAPS_MACHINE_PSERIES_RESIZE_HPT);
+ DO_TEST("pseries-features-htm",
+ QEMU_CAPS_MACHINE_OPT,
+ QEMU_CAPS_MACHINE_PSERIES_CAP_HTM);
DO_TEST("pseries-serial-native",
QEMU_CAPS_NODEFCONFIG,
--
2.14.3